little hands' lab

ドメイン駆動設計を布教したい

ドメイン駆動設計で実装を始めるのに一番とっつきやすいアーキテクチャは何か[DDD]

DDD連載記事

背景・前提

なぜDDD初心者はググリ出してすぐに心がくじけてしまうのかの記事で、

ネット上の文献で紹介されるアーキテクチャが様々なものとなっているのです。IDDDではヘキサゴナルアーキテクチャというものが掲げられていましたが、それを進化させたオニオンアーキテクチャ、クリーンアーキテクチャなどの有名な亜種が存在します。 これが実装に着手する際に非常に大きな混乱を呼ぶのです。文脈の理解、採用するアーキテクチャの選定に時間を取られることでしょう。

と書きました。こちらに対して、私が「一番とっつきやすい」と考えるアーキテクチャを紹介します。

前提としてですが、完全に個人的な経験に基づく私見になります。

DDDの理論の中で、アーキテクチャに関しては「エリック・エヴァンスのドメイン駆動開発」(以下原典)と実践ドメイン駆動開発(以下IDDD)とでも異なったものが紹介されており、唯一の正解というものは提示されていません。アーキテクチャは各プロジェクトの判断に委ねられているものであり、合う合わないはプロジェクトの要件やメンバーによって異なります。

ただ、それだけではまず始める時にどう着手すればよいか迷ってしまうと思うので、「初学者が手をつけるならこれが良いのでは」というものを私が提案する形になります。ご了承ください。

候補となるアーキテクチャと、その関係性

ネットでDDDの記事を漁るとだいたい以下のものがでてくると思います。

  1. レイヤードアーキテクチャ
  2. ヘキサゴナルアーキテクチャ
  3. オニオンアーキテクチャ
  4. クリーンアーキテクチャ

これらの概略を簡単にお話しします。

レイヤードアーキテクチャ

Layered.png

原典で紹介されているアーキテクチャ。 従来の3層アーキテクチャに比べて、Domain層を確立させ、そこにドメインロジックを凝集させよう、という発想のものです。

ヘキサゴナルアーキテクチャ

Hexagonal.png

IDDDで紹介されているアーキテクチャ。別名「ポートアンドアダプターアーキテクチャ」。 元はこちらのブログで2005年に提唱されたものです。

実は「ヘキサゴナル、オニオン、クリーン」の3つは、本質的には全く同じです。

思想としてはこのヘキサゴナルで完成されているんですよ。責務の区切り方と名称が少しずつ違うだけなんです。じゃあ、ヘキサゴナルでいいじゃないかって?

そうです、本質的には基本的にヘキサゴナルでよいし、結果的に同じ設計をしていることになるんです。

ただし・・・・

この図を見ても、実装イメージが湧かなくないですか?

私はこれがポイントだと思っていて、このわかりづらさがIDDDを読んだ人が手をすぐ動かせない理由ではないかと考えているのです。

結論を変な位置でいうと、私のオススメはオニオンアーキテクチャです。これは本質的には同じでも、責務の区切りと名称を変えた結果 直感的にわかりやすくなっているので、最初の導入はこの図を見ながらやるのが良いと思っています。

では、次にそちらを紹介します。

オニオンアーキテクチャ

ヘキサゴナルアーキテクチャを受けて、2008年にこちらのブログで提唱されたのがオニオンアーキテクチャです。

Onion.png 同じ構造を、平らに表現したのが以下の図です。 Onion(Flattened).png

少〜し、どういう構造にするのかイメージが湧いてきませんか? 詳細はこの後説明するのですが、ポイントは依存関係逆転の原則によってDomain層がInfrastructure層に依存しなくなっていることです。これによりDomain層のモデルが特定のライブラリなどに依存しない形の実装になるのです。

これはヘキサゴナルアーキテクチャでも全く同じ思想なのですが、概念図からはそのことが読み取りづらいのです。そのため、図を見たときの直感的なわかりやすさから、私は最初に着手するにあたってはオニオンアーキテクチャを推しています。

変な順番になってしまいましたが、比較のためにクリーンアーキテクチャも紹介します。

クリーンアーキテクチャ

ヘキサゴナル、オニオンやその他のアーキテクチャを受けて、2013年に概念を統合しようとしたのがクリーンアーキテクチャです。こちらのブログで提唱されました。

image.png 画像は同ブログから引用

同じく同心円が重なっている構造からわかるように、基本的に言っていることは同じです。違いとしては単語だけだと思っています。

クリーンアーキテクチャは、Androidアプリケーションのアーキテクチャとして、DDDとは関係なく使われている記事がちらほら見受けられました。

これは全くもって好みになるのですが、「UseCase層」というレイヤに何を書くのかわかりにくい点、「Domain層」ではなく「Entity層」というネーミング(DDD的にはEntityはDomain層の一部なので、収まりが悪い)から、私はオニオンアーキテクチャの方がよいと思っています。

これがしっくり来る方はクリーンアーキテクチャのネーミングを採用すれば良いかと思います。

アーキテクチャを使ってどう実装するのか

ドメイン層にどのようにふるまいを詰め込むのか、について、 【DDD】モデルでドメイン知識を表現するとは何か こちらの記事でサンプルコード付きで紹介しています。

Onion(Flattened).png

記事内のTaskエンティティがDomainModel、TaskRepositoryがDomainService、TaskApplicationがApplicationに該当します。 こうして見てみると、結構シンプルですし、レイヤーの名前と内容がイメージしやすいのではないでしょうか。

そういったわけで、私はDDDを最初に説明するときは、オニオンアーキテクチャと先ほどのようなサンプルコードの説明をするところから始めるようにしています。

オニオンアーキテクチャ、依存性の逆転については、また別の記事でもう少し深堀りしてみたいと思います。

(10/11追加)
ドメイン駆動 + オニオンアーキテクチャ概略書きました。