レイヤアーキテクチャとは
レイヤアーキテクチャは、その名の通り、幾つかの層に分割してシステムを構築するパターンです。昔ながらのN層システムと呼ばれる、2層(クライアントアプリ→DB)や3層(ブラウザ→Webサーバー→DB)もレイヤアーキテクチャの一種です。
このアーキテクチャのポイントは、ライブラリや名前空間を分割することに加え、各レイヤの依存関係を明確にして、適切な責務に沿って実装することが重要となります。
レイヤアーキテクチャでのDDD
DDDとレイヤアーキテクチャを組み合わせた場合の各レイヤの特徴について見ていきましょう。
UI層
ドメイン層のモデルを使うことも可能ですが、描画での使用のみにしておくことが推奨されています。可能であれば、ドメインがビューの影響を受けることを防ぐために「プレゼンテーションモデル」を作ります。
アプリケーション層
UI層から使用されます。ここには「アプリケーションサービス」が存在します。アプリケーションサービスは「ドメインサービス」と異なり、ドメインロジックを持たず軽量なコーディネーターのような役割を果たします。
ドメイン層
ユースケースやユーザーストーリーを実装します。ドメインモデルが提供され、「ファクトリ」か「集約」のコンストラクタにてインスタンスを生成します。ドメイン層には「ドメインサービス」が含まれ、ステートレスな操作として、ドメインの操作を行います。また、イベント駆動の場合「ドメインイベント」を発行します。
インフラストラクチャ層
「リポジトリ」を使用して永続化を行います。
DDDの各要素については今後の章で紹介しますので、ここでは構成イメージだけご理解いただければ結構です。
依存性逆転の原則(DIP)を用いたレイヤアーキテクチャ
続けてDIPについて紹介します。SaaSOvationチームは、複雑化するソフトウェアにユニットテストツールを用いて品質改善対応をする際にDIPを導入しました。Robert C. Martin氏が提唱したDIP(依存性逆転の原則:Dependency Inversion Principle)とは「上位が下位に依存する従来の形をやめ、抽象が詳細に依存するのではなく、実装が抽象に依存するべき」という指針です。プログラムの実装としては、依存性の注入(DIコンテナ)、サービスファクトリ、プラグインなどの方式が使用されます。
例えば、インフラストラクチャの実装にドメインが依存するのではなく、ドメインの抽象(インターフェイス)に対してインフラストラクチャの実装が依存する形になります。これは前述のレイヤアーキテクチャと逆の依存関係が成り立つため、依存性逆転と呼ばれます。このアーキテクチャでは、ドメインが他のレイヤに依存しなくなるため、ドメイン層を独立させ、シンプルに管理しやすくなります。
ヘキサゴナルアーキテクチャー
DIPの採用でドメインの独立性は高まりますが、インフラストラクチャ層の実装は複雑になりがちです。そこでSaaSOvationチームでは、NoSQL/メッセージングといった新しい永続化技術の導入時に「ヘキサゴナルアーキテクチャ」を導入しました。これは、Alistair Cockburn氏が提唱したパターンで、要約すると「アプリケーション(ドメイン)層を中心に捉え、ユーザー操作/自動テストといった入力側もデータベース/モックといった出力側も、全てまとめて差し替え可能な外部インターフェイスとして扱う」という考え方です。
レイヤアーキテクチャでは、上位(もしくはフロントエンド)と下位(もしくはバックエンド)という「非対称性」な構成でしたが、ヘキサゴナルアーキテクチャでは、ドメインを中心において「処理を駆動するプライマリ」側と「処理が駆動されるセカンダリ」側と連携します。例えば、何かの処理がある場合、プライマリ側(左上部分)のアクションによってドメインが呼び出されます。そして、セカンダリ側(右下部分)によって保存したりイベントを生成したりします。この「対称性」なイメージを想起させるためヘキサゴンなアーキテクチャ(六角形なアーキテクチャ)と命名されました。
ヘキサゴナルを構成する「ポート&アダプタ」
ヘキサゴナルアーキテクチャは、構成上の仕組みから「ポート&アダプタ」とも呼ばれます。システムの目的に応じて「ポート」が設計され、技術的に差しかえが可能な部分が「アダプタ」として用意されます。「ドメイン」部分は機能やユースケースを基に設計し、「ポート&アダプタ」部分は技術的なインターフェース別で設計するイメージとなります。
例としては、永続化機能のポートにおいて、実データベースを使うアダプタと自動テスト用モックを使うアダプタを用意します。将来的にはNoSQLやクラウドストレージ用のアダプタが追加されるかもしれません。
ヘキサゴナルアーキテクチャのメリット
ヘキサゴナルアーキテクチャのメリットは、柔軟なアーキテクチャのため、他のアーキテクチャもうまく取り込むことができることです。また、周辺の技術が決まっていなくても、暫定的にアダプタを作成し、ドメインの開発を進められます。さらに上手に設計すると、ドメイン層のロジックが外部に漏れなくなり、ユースケースを適切に実装できます。
DIPのレイヤアーキテクチャを用いている場合は、ヘキサゴナルな要素が少なからず含まれていますので、ヘキサゴナルアーキテクチャに変更することを検討してみると良いでしょう。