僕とDDDとClean ArchitectureとやっぱりDDD

2022/04/21更新 ふりかえってみて、この記事は手段と目的をごっちゃにしちゃった自分がよくわかる記事です。 DDDは「どうやってコードを書くか」が問題ではありません。その点を勘違いしちゃってるエンジニアの話として、続きを読みたい人は読んでください🙏

DDD(Domain Driven Design)って難しいですよね。難しい難しいとばかり考えていた僕もようやく最近になって少しずつわかってきた気がします。そのきっかけとなった書籍と僕のストーリーを本記事で紹介できたらと思います。

TL;DR

  • Clean Architectureはなんとなくわかる
  • DDDは難しい

と感じている人は「Domain-Driven Design in PHP」を読むと道が拓けるかもしれない。

leanpub.com

僕とDDD

DDDといえばEvansのドメイン駆動設計:

そしてVernonの実践ドメイン駆動設計:

が有名です。「ドメイン駆動設計」の内容をより実際の設計に当てはめている「実践ドメイン駆動設計」の方がわかりやすいという意見を聞いたりしますが、僕にとっては両方ともなかなかに難易度の高い書籍です。少しずつ読んでは「なんとなく言ってることはわかる」と思いながらも今ひとつ身についた気がしない類のものでした。このように感じている人はそれなりにいるんじゃないかなと思ってます。

僕とClean Architecture

DDD難しいし、実際のプロジェクトに適用しようと思っても手が止まる。。。

ということでしばらく本棚に戻していたのですが、次に見つけたのがClean Architectureなるものでした。Qiitaの記事で見つけたのがきっかけだったのですが、実際に自分の馴染みのあるコード(Rest APIだったりAndroidのアプリだったり)で書かれていたこともあって「これは実際のプロジェクトでも書けそう」と思えたのが「僕とDDD」の出会いとの大きな違いかなと思います。

実際にはQiitaの記事だけでは心もとないので、以下のような記事や講演で学びながら実案件でも適用していきました。

Uncle BobのClean Architectureの記事

blog.cleancoder.com

Uncle BobによるClean Architectureの講演

www.youtube.com

(いくつかありますが、最初にみて面白かったのがこれです)

Uncle Bobと息子のMicah MartinがペアプロしながらWebシステムを作る講義

learning.oreilly.com

GitHub上のソースコード

github.com

Clean Architecture(書籍)

僕がClean Architecture学び始めたころはまだ無かったのですが、正式に書籍も発売されています。

Clean Architectureでモヤッとしたこと

Clean Architectureを採用したプロジェクトでは、オレオレClean Architectureでありながらもそれなりにルールを守った自信はあります(特に依存関係やScreaming Architecture部分)。が、いざ実装するとなったときに「ロジックをどこに置くのか」というところで結構悩むことがありました。

  • ○○ロジックはUseCase(Interactor)に入れる?
  • △△ロジックはEntityに入れる?
  • 同じようなロジック(例えばValidation)が複数箇所にあるけどこれは誰の役割?
  • などなど

Clean Architectureの書籍に「第20章 ビジネスルール」という章があるのですが、

  • エンティティは最重要ビジネスルールを含む
  • ユースケースアプリケーション固有のビジネスルールを含む

と言われてもなかなかエモくて直感的にわかりにくいと感じました。そして結構こういうところがコードレビューでチーム内で意見が分かれたりして変に時間がかかっちゃったりしたのを覚えています。「Clean Architecture良い!」という思いとともに「まだすっきりしない点が残る」という状態が続きました。「やっぱりDDDなマインドが足りていないからなのか?」ということでDDD学習に戻ることにしたのがここ1年くらいの話です。

DDDとClean Architecture

「実践ドメイン駆動設計」を再び読み直してみたのですが、不思議なことにClean Architectureを経てから読み直してみると見えてくるものが変わりました。たぶんですけど、

馴染みのあるコードからClean Architectureを学んだ
↓ 
Clean Architecture(書籍)を読んだら答え合わせのように腑に落ちる点が多かった
↓
この書籍内にドメイン駆動的な話も入っていた(んじゃないかと思う)
↓
無意識のうちにDDDの概念が少し増えた状態で改めて「実践ドメイン駆動設計」を読み始めた
↓
書籍内に出てくる単語や概念に馴染みが増していたので以前より想像しやすくなった

ということだと思います。

ただ、以前より理解がしやすくなったとは言え、モヤッとは残ったままで、以下のトピックを理解したいと思いつつもいまいちピンとこない感じでした。

  • Application Service
  • Domain Service
  • Aggregate
  • Entity
  • Value Object
  • Domain Event

結局繰り返しになるんですけど、「なんとなく言ってることはわかる」で止まってしまって、いざ自分のコードに入れようとすると「どうしたら良いんだろ?」になっちゃうんですね。(つまりわかっていない)

今にして思うと「わかろうとするモチベーションが足りなかった」だけな気もします。

そんな中最近「Domain-Driven-Design in PHP」という本に出会いました。

Domain-Driven-Design in PHP

leanpub.com

O'Reillyのサブスクリプションがある方はこちらのリンクからも読むことができます!

この書籍は結構前から知っていたんですけど、PHPというだけで避けてました。(ごめんなさい。でもそう思った人は僕だけじゃないはず!)

最近は毎日のようにPHP触ってますし、PHPへの抵抗も昔よりだいぶ無くなったので読んで見ることにしました。

久しぶりにこんなにワクワクする技術書を読んだ。

というのが素直な感想です。僕がちょうどモヤッとしているところとジャストミートな内容だった、というのもあるんだと思いますが:

  • ちょうど良いボリューム感
  • ドメイン駆動設計」, 「実践ドメイン駆動設計」, そして「Clean Architecture」にも言及している
  • DDDの概念とリンクする豊富なサンプルコード
  • 書籍用に作ったシステムがGitHub上に公開してある

という4つのポイントが僕の中で高評価です。

ちょうど良いボリューム感

ページ数は394ページとそれなりにあるのですが、コードが占めている比率が高いので思ったよりすぐ読めます(僕は3,4日で読めました)。

目次は以下の通り。

* Getting Started with Domain-Driven Design
* Architectural Styles
* Value Objects
* Entities
* Services
* Domain Events
* Modules
* Aggregates
* Factories
* Repositories
* Application
* Integrating Bounded Contexts
* Appendix: Hexagonal Architecture with PHP

「実践ドメイン駆動設計」と比べてみても、概ねトピックはカバーできていると言えます。

* Getting Started with DDD
* Domains, Subdomains, and Bounded Contexts
* Context Maps
* Architecture
* Entities
* Value Objects
* Services
* Domain Events
* Modules
* Aggregates
* Factories
* Repositories
* Integrating Bounded Contexts
* Application
* Aggregates and Event Sourcing: A+ES

ドメイン駆動設計」, 「実践ドメイン駆動設計」, そして「Clean Architecture」にも言及している

要所要所でEvansの「ドメイン駆動設計」とVernonの「実践ドメイン駆動設計」の引用を使って説明をしてくれます。

例えばDomain Eventについて「実践ドメイン駆動設計」からは:

Vaughn Vernon defines a Domain Event as:

An occurrence of something that happened in the domain.

そして「ドメイン駆動設計」からは:

Eric Evans defines a Domain Event as:

A full-fledged part of the Domain Model, a representation of something that happened in the Domain. Ignore irrelevant Domain activity while making explicit the events that the Domain Experts want to track or be notified of, or which are associated with state change in the other Model objects.

というように両者を引用で出してくれます。書籍内でのわかりやすさも増すのですが、この引用をもとに「ドメイン駆動設計」と「実践ドメイン駆動設計」をリファランスとして要所要所で読み直していける点もすごく良いです。

また、さらにうれしいのはUncle BobのClean Architectureにも言及している点です。(この書籍が発売したときには「Clean Architecture」はまだ出版されていないので、あくまでUncle Bob(Robert C. Martin)について言及しています)

As Robert C. Martin says: The Web is a delivery mechanism [...] Your system architecture should be as ignorant as possible about how it is to be delivered. You should be able to deliver it as a console app, a web app, or even a web service app, without undue complication or any change to the fundamental architecture.

DDDの概念とリンクする豊富なサンプルコード

(ちょっと大げさですけど)文章よりコードが多いんじゃないかってくらいサンプルコードが都度紹介されています。そして、コードの要所要所に関して丁寧にわかりやすく説明がされているので、DDDの概念とコードがどう結びついていくのかが想像しやすいです。

書籍用に作ったシステムがGitHub上に公開してある

書籍用に作られた「Last Wishes」というシステムのコードがGitHub上に公開されています。

Last Wishesトップ画面

コンセプトは「ユーザーが亡くなった場合に、あらかじめ登録されていたお願い(Wish)を、指定したメールアドレス宛に送る」というものです。お願い(Wish)を登録した場合にはゲーム要素もあって、一定ポイントたまるとバッジが付与されるようになっています。

このシステムは大きく2つのアプリケーションに分かれています。

  • ユーザーのWishを管理し、メールを送信するコア部分のアプリ
  • ゲーム要素を提供する、Wishに応じたポイントを換算し、ユーザー毎に管理するアプリ

それが各々以下で公開されています。

github.com

github.com

システム構成は下の図のようになっていて、それなりにまともなメンツが揃ったシステムになっています。

Last Wishesの概要図

サンプルアプリではあまり見られない:

  • CQRSとEvent Sourcing
  • Bounded Context(Last WishesとLast Wishes Gamify)

というのも学ぶことができるのでかなり貴重な素材だと思います。このシステムと書籍を照らし合わせていくことで答え合わせもしていけるので、理解が進みやすいという印象もあります。

まとめ

  • 「Domain-Driven-Design in PHP」を読んだ
  • 馴染みやすいコードでDDDを体系的に学べる良書だった
  • ドメイン駆動設計」「実践ドメイン駆動設計」「Clean Architecture」をリンクさせてくれる1冊だと思った

と、思いをつらつらと書きましたが、同じように迷い、悩んでいる方がもしいるのであれば「Domain-Driven-Design in PHP」はかなりおすすめできる1冊なのでぜひ読んでみてください!ということを伝えたかったです。

この記事が何かしら一歩先に進めるきっかけになれば幸いです。

今後の予定

  • Vernonの「実践ドメイン駆動設計」を読み直す
  • Evansの「ドメイン駆動設計」を読み直す
  • Uncle Bobの「Clean Architecture」を読み直す
  • Last WishesをLumenに移行してみる
  • ↑ができたらgoにも移行してみる
  • 自分でScratchからアプリを作ってみる

という流れで精進していけたらいいなと思います!