

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# 最佳實務
<a name="best-practices"></a>

## 建立商業網域的模型
<a name="model-domain"></a>

從商業網域回到軟體設計，以確保您撰寫的軟體符合業務需求。

使用網域驅動型設計 (DDD) 方法，例如[事件風暴](https://www.eventstorming.com/)，來建立商業網域的模型。事件風暴具有彈性的研討會格式。在研討會期間，網域和軟體專家會共同探索商業網域的複雜性。軟體專家使用研討會的交付項目來啟動軟體元件的設計和開發程序。

## 從頭開始撰寫和執行測試
<a name="testing"></a>

使用測試驅動開發 (TDD) 驗證您正在開發之軟體的正確性。TDD 最適合在單元測試層級運作。開發人員會先撰寫測試來設計軟體元件，該測試會叫用該元件。該元件一開始沒有實作，因此測試會失敗。下一個步驟是開發人員實作元件的功能，使用測試固定裝置搭配模擬物件來模擬外部相依性或連接埠的行為。當測試成功時，開發人員可以實作真正的轉接器以繼續。這種方法可改善軟體品質並產生更易讀的程式碼，因為開發人員了解使用者如何使用元件。六角架構透過分隔應用程式核心來支援 TDD 方法。開發人員撰寫著重於網域核心行為的單元測試。他們不需要撰寫複雜的轉接器來執行測試，而是可以使用簡單的模擬物件和固定裝置。

使用行為驅動型開發 (BDD)，以確保end-to-end。在 BDD 中，開發人員會定義功能的案例，並與業務利益相關者進行驗證。BDD 測試會盡可能使用自然語言來達成此目標。六角架構支援 BDD 方法及其主要和次要轉接器的概念。開發人員可以建立可在本機執行的主要和次要轉接器，而無需呼叫外部服務。他們會將 BDD 測試套件設定為使用本機主要轉接器來執行應用程式。

在持續整合管道中自動執行每個測試，以持續評估系統的品質。

## 定義網域的行為
<a name="behavior"></a>

將網域分解為實體、值物件和彙總 （閱讀有關[實作網域驅動的設計](https://www.oreilly.com/library/view/implementing-domain-driven-design/9780133039900/))，並定義其行為。實作網域的行為，讓在專案開始時寫入的測試成功。定義叫用網域物件行為的命令。定義網域物件在完成行為後發出的事件。

定義轉接器可用來與網域互動的界面。

## 自動化測試和部署
<a name="automate-testing"></a>

在初始概念驗證之後，我們建議您花時間實作 DevOps 實務。例如，持續整合和持續交付 (CI/CD) 管道和動態測試環境可協助您維持程式碼的品質，並避免在部署期間發生錯誤。
+ 在 CI 程序內執行您的單元測試，並在程式碼合併之前進行測試。
+ 建置 CD 程序，將您的應用程式部署到靜態開發/測試環境，或動態建立的環境，以支援自動整合和end-to-end測試。
+ 自動化專用環境的部署程序。



## 使用微服務和 CQRS 擴展您的產品
<a name="scale"></a>

如果您的產品成功，請將您的軟體專案分解為微服務，以擴展您的產品。利用六邊形架構提供的可攜性來改善效能。將查詢服務和命令處理常式分割為不同的同步和非同步 APIs。考慮採用命令查詢責任隔離 (CQRS) 模式和事件驅動型架構。

如果您收到許多新功能請求，請考慮根據 DDD 模式擴展您的組織。以團隊擁有一個或多個特徵作為邊界內容的方式組織您的團隊，如先前[組織擴展](adapt-to-change.md#scaling)章節中所述。這些團隊接著可以使用六邊形架構來實作商業邏輯。

## 設計對應至六邊形架構概念的專案結構
<a name="mapping"></a>

基礎設施即程式碼 (IaC) 是雲端開發中廣泛採用的實務。它可讓您將基礎設施資源 （例如網路、負載平衡器、虛擬機器和閘道） 定義為原始碼，並加以維護。如此一來，您可以使用版本控制系統來追蹤架構的所有變更。此外，您可以輕鬆建立和移動基礎設施，以供測試之用。我們建議您在開發雲端應用程式時，將應用程式程式碼和基礎設施程式碼保留在相同的儲存庫中。此方法可讓您輕鬆維護應用程式的基礎設施。

我們建議您將應用程式劃分為三個對應至六邊形架構概念的資料夾或專案： `entrypoints`（主要轉接器）、 `domain`（網域和介面） 和 `adapters`（次要轉接器）。

下列專案結構提供在設計 API 時此方法的範例 AWS。專案會如先前所建議，在相同的儲存庫中維護應用程式碼 (`app`) 和基礎設施碼 (`infra`)。

```
app/  # application code
|--- adapters/  # implementation of the ports defined in the domain
     |--- tests/  # adapter unit tests
|--- entrypoints/  # primary adapters, entry points
     |--- api/  # api entry point
          |--- model/  # api model
          |--- tests/  # end to end api tests
|--- domain/  # domain to implement business logic using hexagonal architecture
     |--- command_handlers/  # handlers used to run commands on the domain
     |--- commands/  # commands on the domain
     |--- events/  # events emitted by the domain
     |--- exceptions/  # exceptions defined on the domain
     |--- model/  # domain model
     |--- ports/  # abstractions used for external communication
     |--- tests/  # domain tests
infra/  # infrastructure code
```

如前所述，網域是應用程式的核心，不依賴任何其他模組。我們建議您建構 `domain` 資料夾，以包含下列子資料夾：
+ `command handlers` 包含在網域上執行命令的方法或類別。
+ `commands` 包含命令物件，定義在網域上執行 操作所需的資訊。
+ `events` 包含透過網域發出的事件，然後路由至其他微服務。
+ `exceptions` 包含網域中定義的已知錯誤。
+ `model` 包含網域實體、值物件和網域服務。
+ `ports` 包含網域透過其與資料庫、APIs 或其他外部元件通訊的抽象概念。
+ `tests` 包含在網域上執行的測試方法 （例如商業邏輯測試）。

主要轉接器是應用程式的進入點，由 `entrypoints` 資料夾表示。此範例使用 `api` 資料夾做為主要轉接器。此資料夾包含 API `model`，定義主要轉接器與用戶端通訊所需的界面。`tests` 資料夾包含 API end-to-end測試。這些是淺測試，可驗證應用程式的元件是否整合並協調運作。

次要轉接器，如 `adapters` 資料夾所示，實作網域連接埠所需的外部整合。資料庫儲存庫是次要轉接器的絕佳範例。當資料庫系統變更時，您可以使用網域定義的實作來撰寫新的轉接器。不需要變更網域或商業邏輯。`tests` 子資料夾包含每個轉接器的外部整合測試。