タイトルに書かれていることで全てなのですが、DDDとCQRSの併用について強調している日本語の情報が少ないので、軽くまとめておきます。
CQRS+DDD
CQRS(コマンドクエリ責務分離)とは、サーバの機能を「コマンド」(副作用あり)と「クエリ」(副作用なし)で完全に分けちゃおう、という考え方です。そもそも「コマンド」と「クエリ」ではあらゆる要件が異なります。
- 一貫性: 「コマンド」は整合性のある処理が必要、「クエリ」はあまり気にする必要なし
- ストレージ: 「コマンド」側は正規化してデータを保存したい、「クエリ」側は非正規な方が効率的
- スケーラビリティ: 「コマンド」は全体の負荷の中で占める割合が少ない、「クエリ」は負荷が大きい
なので分けちゃうわけですが、
- コマンド側
- 複雑なビジネスロジックが絡むので、ドメイン駆動が活躍
- クエリ側
- 複雑なビジネスロジックがないので、ドメイン層はスキップ
クエリ機能についてはDDDを省略することで、柔軟でスケーラビリティの高いクエリ機能を提供しつつ、Repositoryの肥大化を防いで、より重要なドメイン領域の設計に集中することが出来ます。
詳しくはGreg Youngによるオリジナルの文書を参照してください。Sipadan2003さんが日本語にも翻訳してくれています。また、Implementing Domain-Driven Designにも詳しいCQRSの説明があります。
なお、CQRS には必ず Event Sourcing の話がついて回りますが、Event Sourcing なしでもCQRSを利用することは出来ます。
DDD+CQRSのサンプル
- 関数型言語F#を使ったDDDとCQRS
- Domain-Driven Design with Python(ソースコード)
- Akkaを使ったリアクティブなDDDおよびCQRSベースのアプリケーション構築
最後に
ある程度大きなシステムでないと、DDDのオーバーヘッドはペイしないです。とはいえ、今後のサービスの成長を見越してDDDで設計したい場合が多々あると思うのですが、そのような場合の初期の仕掛けとしてCQRSを導入しておくのは、わりとありかなと思います。あと、DDDと言うと Layered Architecture が有名ですが、ドメイン層を依存関係の中心に置いた Hexagonal Architecture も使いやすいです。
なお、ここまで書いておきながら、CQRSの実践投入はまだやったことがないのであしからず。 少し実践しましたが、やはりクエリの実装が楽になりました。
ドメイン駆動開発シリーズ
- DDDで設計するならCQRSの利用を検討すべき
- ValueObject implementation in Python
- Hexagonal Architecture の実践には zope.interface が便利
追記
"Implementing Domain Driven Design" の日本語訳が出版されましたね。
ドメイン駆動設計を検討しているなら、必携の書です。