

翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。

# ベストプラクティス
<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>

製品が成功したら、ソフトウェアプロジェクトをマイクロサービスに分解して製品をスケールします。六角形アーキテクチャが提供する移植性を活用してパフォーマンスを向上させます。クエリサービスとコマンドハンドラーを別々の同期 API と非同期 APIs。コマンドクエリ責任分離 (CQRS) パターンとイベント駆動型アーキテクチャを採用することを検討してください。

多くの新機能リクエストが発生した場合は、DDD パターンに基づいて組織をスケーリングすることを検討してください。[組織のスケーリング](adapt-to-change.md#scaling) 「」セクションで前述したように、1 つ以上の機能を境界コンテキストとして所有するようにチームを構成します。これらのチームは、六角形アーキテクチャを使用してビジネスロジックを実装できます。

## 六角形アーキテクチャの概念にマッピングするプロジェクト構造を設計する
<a name="mapping"></a>

Infrastructure as Code (IaC) は、クラウド開発で広く採用されているプラクティスです。これにより、インフラストラクチャリソース (ネットワーク、ロードバランサー、仮想マシン、ゲートウェイなど) をソースコードとして定義して維持できます。これにより、バージョン管理システムを使用して、アーキテクチャに対するすべての変更を追跡できます。さらに、テスト目的でインフラストラクチャを簡単に作成して移動できます。クラウドアプリケーションを開発するときは、アプリケーションコードとインフラストラクチャコードを同じリポジトリに保持することをお勧めします。このアプローチにより、アプリケーションのインフラストラクチャを簡単に維持できます。

アプリケーションは、六角形アーキテクチャの概念 (プライマリアダプター）、 `entrypoints` (`domain`ドメインとインターフェイス）、 `adapters` (セカンダリアダプター) の 3 つのフォルダまたはプロジェクトに分割することをお勧めします。

次のプロジェクト構造は、 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`フォルダをプライマリアダプターとして使用します。このフォルダには`model`、プライマリアダプターがクライアントと通信するために必要なインターフェイスを定義する API が含まれています。`tests` フォルダには、 API end-to-endのテストが含まれています。これらは、アプリケーションのコンポーネントが統合され、連携して動作することを検証する浅いテストです。

セカンダリアダプターは、 `adapters`フォルダで表されるとおり、ドメインポートに必要な外部統合を実装します。データベースリポジトリは、セカンダリアダプターの優れた例です。データベースシステムが変更されたら、ドメインで定義された実装を使用して新しいアダプターを記述できます。ドメインやビジネスロジックを変更する必要はありません。`tests` サブフォルダには、各アダプターの外部統合テストが含まれています。