わかりやすくて最高だった「ドメイン駆動設計入門 ボトムアップでわかる!ドメイン駆動設計の基本」レビュー

2022.07.19

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

「ドメイン駆動設計入門 ボトムアップでわかる!ドメイン駆動設計の基本」を読んだところ、とても良かったのでレビューしたいと思います。

私の状況

まずこの本を読む前の私がどの程度ドメイン駆動設計について理解していたかご紹介します。

  • 以前同僚が書いてくれたサンプルコードを手本にレイヤードアーキテクチャみたいなTypeScriptのLambda関数を書いている
    • 「Service」とか「Repository」とかの単語を命名に使っているが、使い方あってるのか自信ない、というか意味をよくわかっていない
    • 実装中「この構成でええんか?」と何度も思い悩む
    • 時間かかるくらいなら雑にさっさと書いてしまったほうが良いのでは、と思うこともある。けどちゃんとしたコードを書きたいんや。
  • こういうのを読んで、テストしやすいコードの書き方を試行錯誤している
  • エリック・エヴァンスのドメイン駆動設計は未読。積読してる。(積読してるの忘れて2冊目を買いかけた?)

うーん、あらためてまとめるとドメイン駆動設計を学びたいというより、世間で良いと言われているコーディングパターンを知って自信を持ってコードが書きたいだけな気もしますね。

本の概要

タイトルどおりドメイン駆動設計の入門書です。ですがドメイン駆動設計全般について述べられた本ではないことにご注意ください。

ドメイン駆動設計は大分して2分野、ドメインのモデリングとドメインモデルの実装に分かれます。このうち前者、ドメインのモデリングについてはほとんど扱わず、後者つまり出来上がったドメインモデルを実装に落とし込んでいく際に有用な各種パターンについて解説している、いわゆる軽量DDDといわれる部分を扱っている本です。(とはいえ著者としては読者を軽量DDDに導きたいわけではありません。ドメイン駆動設計を学ぶにあたって、まずは学びやすいパターンの部分を先に、その後モデリング部分を学ぶのが良いとお考えとのことです。)

感想

とにかく具体的でわかりやすいです。この本はずっと以下の流れで話が進んでいきます。

  1. ベースとなるサンプルコードがあります
  2. このコードにはこういうイケてない点がありますね
  3. ドメイン駆動設計にはこういうパターン(概念)があります
  4. 導入してみましょう。より良いコードになりましたね?

すべて具体的なサンプルコードが載っています。サンプルコードはC#で書かれていますが、何かしらのオブジェクト指向プログラミングの経験があれば問題なく読めると思います。C#特有の構文についても冒頭に解説があります。

「なぜ現状のコードがイケてない(問題がある)のか」「DDDのパターン導入後のコードがどう良くなったのか」の説明が手厚い&わかりやすいので「なるほど確かにこれは良いな」と納得感があります。そのため読んでいて楽しかったです。

とはいえ一度読み切っただけの現状では、当たり前ですが「完全理解した」までとはなっておらず、頭の中にインデックスができた位の感覚です。読了後実際にコードを書いてみましたが、やはりこの本の色んなチャプターを見返しながら進めることになりました。それでも読了前の漠然とモヤモヤしながらのコーディングよりかは大分快適になり満足しています。

積読しているエリック・エヴァンスのドメイン駆動設計にも挑戦したいなと思いました。

各チャプターごとの概要と感想

Chapter 1 ドメイン駆動設計とは

「ドメイン」「ドメインモデル」「ドメインオブジェクト」「ドメイン駆動設計」などの用語の意味が説明されます。 一番最後のコラム「なぜいま、ドメイン駆動設計か」が納得感が高くてよかったです。

Chapter 2 システム固有の値を表現する「値オブジェクト」

値オブジェクトについての解説のチャプターです。まずは値オブジェクトを使わず代わりにプログラミング言語に用意されてあるプリミティブな値を使ってコードを書いた際の問題点が説明され、それから値オブジェクトとは何か、その性質などが説明されます。

「私達は値を変更しているのではない、代入しているのである…」あたりの解説は最初「???」だったのですが、後のチャプターも読むとどういうことなのか理解できました。また、ある値を値オブジェクトとして扱うべきか?それともプリミティブな値で済ますか?の判断基準がわかりやすかったです。

Chapter 3 ライフサイクルのあるオブジェクト「エンティティ」

エンティティについて、値オブジェクトと対比させる形で解説されます。この対比させる流れが明瞭で良かったです。

Chapter 4 不自然さを解決する「ドメインサービス」

値オブジェクトやエンティティに書くと不自然になる処理を書く場所としてドメインサービスが必要だという解説がされます。ドメインサービスを使いすぎることの弊害「ドメインモデル貧血症」も紹介されます。これまでの私はまさにドメインモデル貧血症だったなと勉強になりました。

このチャプターはこれまでのチャプターと同様、ユーザーのドメインモデルを使っての一通りの解説が終わった後、題材を物流システムに変えて再度解説が始まるのがよいです。ユーザーと物流システム、2つの例で学ぶことにより理解が深まります。

また、最後の方に次チャプターで扱うリポジトリへの導入があるのも流れがスムーズで良いですね。

Chapter 5 データにまつわる処理を分離する「リポジトリ」

前チャプターで軽く触れた問題点を解決するためにリポジトリがどう役立つか学べます。それに加えて、レポジトリを導入することでデータストアの差し替えも容易になる、という点もサンプルコードとともに解説されます。これはテストの書きやすさにもつながるので、非常に重要な概念だと感じました。各種AWSサービスをコードから呼び出す際にもリポジトリでうまく抽象化してテストを書くことができますよね。

Chapter 6 ユースケースを実現する「アプリケーションサービス」

  • チャプター4のドメインサービスとの違いが今ひとつ理解できず、ちょっと難しくなったなと感じました。何度か読むことでなんとなく掴めたかなという気はします(弱気)。
  • DTO(Data Transfer Object)も紹介されます。DTOの意義はなるほどと理解しましたが、ちょっと冗長すぎるのではとも感じました。
  • コマンドオブジェクトを使った、ドメインオブジェクトの変更に追従しやすくなる書き方についても教えてくれます。「シグネチャ」の意味が最初わからなくて混乱したのですが、「関数やメソッドの名前、引数の数やデータ型、返り値の型などの組み合わせのこと」だそうです。

Chapter 7 柔軟性をもたらす依存関係のコントロール

依存、依存関係逆転の原則などについて説明がなされた後、具体的な依存関係のコントロール方法として、Service LocatorパターンとIoC Container(DI Container)パターンが紹介されます。私はDIや依存関係の逆転についてはなんとなく知っていたのですが、「えーと、どっちがどっちに依存してるんだっけ」とよく混乱していたレベルで、それが本チャプターを読んで解消できました。

Chapter 8 ソフトウェアシステムを組み立てる

ここまで学んできたことにユーザーインターフェースを加えて、ソフトウェアとして成り立たせる方法を学びます。MVCフレームワーク(ASP.NET Core MVC)に組み込む方法やユニットテストについても扱っています。

Chapter 9 複雑な生成処理を行う「ファクトリ」

ドメインオブジェクトは生成過程が複雑になるときがあり、その生成処理を切り出してオブジェクトとしたものを「ファクトリ」と呼びます。このチャプターではファクトリの例、メリット、使い所について解説されています。使い所の説明の納得感が高かったです。

Chapter 10 データの整合性を保つ

データの整合性、トランザクションなどについて説明されています。

Chapter 11 アプリケーションを1から組み立てる

これまで登場した要素を使って、アプリケーションを1から組み立ててていきます。これだけ聴くと「Chapter 8 ソフトウェアシステムを組み立てる」と同じように聞こえますが、本チャプターでは実装に入る前の、求められている機能の確認から始まります。これまで学んだことがつながっていくのが面白かったです。

Chapter 12 ドメインのルールを守る「集約」

集約という概念を持ち込むことで、オブジェクトの操作にさらなる秩序がもたらされます。チャプター11で扱ったサークルのドメインを再び例にして、どのように集約を組み込んでいくのかを学びます。

ちょっと通知オブジェクトあたりは理解が追いつかずななめ読みになってしまったので、また読み直したいと思います。他の部分も難しめだなと感じました。

また、このチャプターで登場する「デメテルの法則」ですが、ウィキペディアに書かれている説明がわかりやすかったです。

  • 簡潔に言うと「直接の友達とだけ話すこと」と要約できる。

  • 具体的には、他のメソッドの戻り値として返されたオブジェクトのメソッドの呼び出しを避けるということになる。最近のオブジェクト指向言語の多くではフィールド識別子としてドット(.)が採用されているが、そのような言語においてはこの法則は単純に「使えるドットは一つだけ」と言い表すこともできる。つまり、"a.b.Method()"という呼び出しは法則に違反しているが"a.Method()"という呼び出しは問題ない。

  • 簡単な例として、犬を散歩に連れ出すことを考える。この際、犬の足に直接「歩け」と命じるのはおかしいだろう。この場合は、犬に対して命令し、自分の足の面倒は自分で見させるのが正しい方法だといえる。

Chapter 13 複雑な条件を表現する「仕様」

他のオブジェクトの評価をするためのオブジェクト「仕様」を導入するとどう良くなるのか知ることができます。

途中、パフォーマンスの観点からドメイン駆動設計を棚上げしたほうが良い場合についても述べられている点が良いなと思いました。

Chapter 14 アーキテクチャ

アーキテクチャとDDDの関係性の解説の後に、DDDと同時に語られることの多いアーキテクチャとして以下が紹介されます。

  • レイヤードアーキテクチャ
  • ヘキサゴナルアーキテクチャ
  • クリーンアーキテクチャ

Chapter 15 ドメイン駆動設計のとびらを開こう

このチャプターだけ唯一ドメインのモデリングについて扱っています。ただし概要だけにとどめて、より詳細な解説はエリック・エヴァンスのドメイン駆動設計を手にとって見てください、という構成になっています。

併せて読みたい