これは、ドメイン駆動設計(DDD) Advent Calendar 2022 9日目の記事です。
ドメイン駆動設計では、レイヤー化アーキテクチャ (Layered Architecture) でエンティティやバリューオブジェクト、ドメインイベント、ライフサイクルに関連する集約 (Aggregate)やリポジトリ (Repository)、ファクトリ (Factory) などが説明されています。
モダンな分散アーキテクチャが採用されるシステムでは、さまざまな種類のデータを処理することになります。流れるデータパケットには、単一の目的を持つものもあれば、複数の目的とライフサイクルの異なる要素を含むものもあります。
次のようなデータの例で考えてみましょう。
- 分散システムの一部のアプリケーションにトラフィックが集中しスケーリングをリクエストするデータ
- ユーザの操作に応じたデータに、ライフサイクルの異なる認証情報を同梱したデータ
- さまざまな分散システムからデータを集約して提供するデータ
最初に挙げたスケーリングをリクエストするデータについて考えてみます。
あるアプリケーションに流入するトラフィック量が増大したため、スケーリングを要求します。すると分散システムはそのアプリケーションをスケーリングするため、サーバー (やコンテナ) を起動して対処します。次に、起動したインスタンスにトラフィックが分配されるように、ロードバランサーやこのアプリケーションに依存する別のアプリケーションに増加したインスタンスのデータ (IP アドレスやポート番号等) を分散システムに流します。
ネットワークの世界では、特定の処理が行われる場所に関する抽象的な概念として「プレーン」という用語が「存在のプレーン」という意味で使用されます。
スケーリングによって、データパケットの転送を変更することになりますが、このようなプロセスは「コントロールプレーン」の一部とみなされることが一般的です。
よく知られているプレーンは、この「コントロールプレーン」と「データプレーン」の2種類あります。
例として挙げた 2 や 3 は「データプレーン」を流れるデータと言うことができます。
ドメイン駆動設計のモデリング対象に 1 のようなデータが現れることはほとんどないでしょう。おそらく意識的にか無意識のうちに、ドメインのデータではないとフィルターしていそうです。
ドメイン駆動設計は、ドメインに集中してモデリング、実装を進めることを目的としています。そのため、この「コントロールプレーン」を流れるデータを「アプリケーション」の設計と分離してモデリング、実装することへの異論はないことだろうと思います。
次に 2 のデータについて考えてみます。
現在アプリケーションの多くはブラウザやデスクトップアプリケーションの UI からインターネットを介してアクセスされます。そしてセキュリティを担保するため、ドメインに到達する前に、認証 (Authn)、認可 (Authz) の処理が実行され、条件を満たした場合にのみドメインの処理が実行されます。また、これらの処理の状況は監視、観察され「コントロールプレーン」を流れるデータを生成します。
さらに、アプリケーションが分散システム内の他のアプリケーションや外部システムと依存関係がある場合、それらのスケーリング等による変化を「コントロールプレーン」から受け取らなければならないかもしれません。具体的な例を挙げると、リレーショナルデータベースを読み書きができるプライマリと読み取り専用のレプリカで冗長化している場合に、プライマリが落ちて、レプリカがプライマリに昇格した場合など、アプリケーションはその変化を検知して、接続先をレプリカからプライマリに昇格した場所に切り替える必要があるかもしれません。
このような一般的に「横断的関心事」と呼ばれる、認証、認可や監視、観察のロギングや可観測性、ルーティング処理は、ドメインモデリングに組み込むべきでしょうか。
サービスメッシュパターンを使用すると、アプリケーションの「データプレーン」にプロキシなどのコンポーネントを配置して、このコンポーネントが「横断的関心事」を処理することで、アプリケーションはよりドメインの処理に集中できます。
最後に 3 のデータについて考えてみます。
さまざまな分散システムからデータを集めてレスポンスするだけでなく、UI から流れてきたデータを複数の分散システムに流す必要がある場合に「GraphQL」を使用することができます。これはどちらかというとフロントエンド寄りのものですが、この記事での議論は主にバックエンドを扱っているため GraphQL などをサポートするなんらかのコンポーネントからアクセスされる、ドメイン駆動設計に基づく各アプリケーションはそれぞれのドメインの処理に集中することができます。また、要件によってはデータメッシュパターンを使用することもできます。