はじめに
この本はかなり長いので、じっくり更新続ける。
日本語版への序文
2003年の本らしい。
DDD の原則は3つだけ
- コアドメインに集中すること
- ドメインの実践者とソフトウェアの実践者による独創的な共同作業を通じて、モデルを探求すること
- 明示的な境界づけられたコンテキストの内部で、ユビキタス言語を語ること
日本語推薦文
この本で、オブジェクト指向設計の本は完結するといっても過言ではないとのこと
序文
ソフトウェア開発は複雑なので、ドメインモデルでコントロールすること
まえがき
- ほとんどのソフトウェアプロジェクトにおいて一番の焦点は、ドメインとドメインロジックに合わせる
- 複雑なドメインの設計は、モデルに紐づかならければならない
第1部 ドメインモデルを機能させる
ドメインモデルでは、次の基本的用法によって、どのモデルを選択するかが決定される
- モデルと設計の革新が相互に形成し合う
- モデルは、チームメンバ全員が使用する言語の基盤である
- モデルとは、蒸留された知識である
第1章 知識を噛み砕く
効果的なモデリング
- モデルと実装を紐づける
- モデルに基づいて、言語を洗練させる
全員が、ユビキタス言語で話せる状態 - 知識豊富なモデルを開発する
- モデルを蒸留する
不要なものは削ぎ落とす - ブレインストーミングと実験を行う
有能なドメインモデラー(開発者とドメインエキスパート)は、情報を引き出し、具現化する。
第2章 コミュニケーションと言語の使い方
ユビキタス言語を使おう
- モデルを言語の骨格として使用すること
- ユビキタス言語を統一させて、ドメインエキスパートと話すこと
声に出してモデリングするのがいい。
知識を持つドメインエキスパートが理解できないモデルなら、モデルに問題がある
- モデルは図ではない。
- すでにコードがやっていることを、ドキュメントでもやろうとするべきではない。
- UML図使おう
第3章 モデルと実装を結びつける
モデル駆動設計がとにかく大事
- ドメインモデルを一切持たず、次から次へと機能を満たすコードを作成するプロジェクトは、複雑なドメインになった瞬間に破綻する。
- 設計がドメインモデルに紐づいていないのであれば、ソフトウェアは正確であるかすら疑わしい
- チーム全体でドメインやモデルに責任を持つ意識が大事
第2部 モデル駆動設計の構成要素
第4章 ドメインを隔離する
-
レイヤ化アーキテクチャ → オブジェクト指向プログラムは、コードがビジネスオブジェクトに書かれることが多いが、関心事を分けることで複雑性を避け、凝集度を高く保てる
- ユーザーインターフェース層 → ユーザーに情報を開示して、コマンドを解釈する責務
- アプリケーション層 → レイヤは薄く保たれ、ビジネスルールや知識を持たずに、相互作用に必要な処理を行う層
- ドメイン層(またはモデル層) → ビジネスの状況を反映する層
- インフラストラクチャ層 → 上記層を支える技術層
- 参考: DDDの一般的なアーキテクチャをまとめてみた
-
- 要件が追加されて再利用されなくて詰む
第5章 ソフトウェアで表現されたモデル
モデルを表現する3パターンの要素 「エンティティ」「値オブジェクト」「サービス」
- 関連を扱いやすくする3つの方法
- 関連をたどる方向を強制 → 相互依存関係を減らす
- 限定子を付加して、多重度を効果的に減らす
- 本質的ではない関連を除去する
エンティティ(参照オブジェクト)
- アプリケーションのユーザにとって重要な区別が属性から独立してるものは、すべてエンティティである。
- 例: 人、都市、自動車
- エンティティをモデル化する時、モデルの定義を本質的なものまで削ぎ落とす
- エンティティは「誰であるか」や「何であるか」という概念によって同一性が定義される。
値オブジェクト
- あるオブジェクトが、ドメインにおける記述的な側面を表現し、概念的な同一性をもたないものを値オブジェクトという
- あるモデル要素において、その属性しか関心の対象にならないなら、その要素は値オブジェクトとして分類すること。
サービス
- モデルにおいて独立したインターフェイスとして提供される操作で、エンティティと値オブジェクトのように状態をカプセル化しない。
- 操作名はユビキタス言語にする必要がある。
- 引数と結果はドメインオブジェクトであるべき。
- 節度をもって利用するべき。
- サービスの3つの特徴
- 操作がドメインの概念に関係しているが、その概念がエンティティと値オブジェクトとしては自然ではない
- ドメインモデルの他の要素の観点から、インターフェイスが定義されている
- 操作に状態がない
- モジュールは低結合、高凝集で設計する
6章 オブジェクトのライフサイクル
集約を利用してモデルの境界線を引き締め、ファクトリを使用しオブジェクト集約を生成したり再構築、リポジトリがライフサイクルに対しアクセスとカプセル化を行う。
集約
- 集約とは、関連するオブジェクトの集まりであり、データを変更するための単位として扱われる
- エンティティと値オブジェクトを集約の中にまとめ、各集約の周囲に境界を定義すること
(WIP)ファクトリ
- 他のオブジェクトの生成を責務とするプログラム要素は、ファクトリと呼ばれる
- 複雑なオブジェクトや集約を生成するのに必要な知識をカプセル化する
- 優れたファクトリの共通要素
- 生成メソッドはそれぞれがアトミック。
- 生成される具象クラスではなく、要求される型に応じて抽象化しなければならない。
(WIP)リポジトリ
- 特定の型のオブジェクトを、すべて概念上の集合として表現する
- リポジトリは基底にあるデータストアをすべてカプセル化する
- トランザクション制御はクライアントに委ねること
7章 言語を使用する
モデルが改良されていくのを体感するために仮想の実例を示しながら学ぶ章
例として、販売管理システム
販売管理システムの内容の記載をすべて行うの甚大のためskip
第3部 よりよい洞察へ向かうリファクタリング
リファクタリングを行う際に、なぜそれを行うのか理解したうえで、ドメインエキスパートの目指す目的とコードの処理の動機を一致させることが重要
深いモデルは、ドメインエキスパートの重要な関心事と、それに最も深く関連した知識に関する明快な表現を提供するが、
一方で、ドメインの表面的な側面は捨て去る。
8章 ブレイクスルー
ユビキタス言語を育成、重要なドメインの概念を研究し、モデルで明示すること。
設計をよりしなやかに設計し、モデルを蒸留すること。
わずかな改良をためらわず日々行うこと。
9章 暗黙的な概念を明示的にする
実例を交えて、開発者とドメインエキスパートのやりとりからモデルをリファクタしている章
- ドメインエキスパートの使う言葉に耳を傾けること。複雑なことを簡素に述べていたら、モデルとして概念化できないか考える
10章 しなやかな設計
意図の明白なインターフェイス
- クラスと操作には、その効果と目的を記述する名前をつけ、約束したことを実行する手段には言及しないこと
- ユビキタス言語に従い、すぐ意味を推測できるようになるから。
- ふるまいを作成する前にテストを書いて、自分がクライアント開発者の視点で考えられるようにすること
副作用のない関数
- 操作は、コマンド(データに変更を加える)とクエリ(情報取得と演算)に分けられる
- 複数のリール間に存在する相互作用や、演算の合成は、予測するのが非常に困難
- 安全に予測できるように抽象化されていなければ、開発者は組み合わせの爆発を考慮して、生産性が落ちる
表明
- 操作の副作用が実装により暗黙的にしか定義されていない場合、移譲が行われている設計では、原因と結果がもつれる
- 表明がコーディングできない場合は、自動化されたユニットテストを書くこと。表明をReadMe等で書くことも良い
概念の輪郭
- モデル設計が一枚岩に埋め込まれていると、機能は重複する
- しかし、ただ分割するだけだと概念が確認できなくなる
- リファクタリングを行い続けると、凝集度が高くなり概念の輪郭が現れる
独立したクラス
- 依存関係が増える毎に、負荷が大きくなる。
- 低結合はオブジェクト設計の基本。できるときは徹底的にやること。オブジェクトのイメージから他の概念を取り除くこと。そういった自己完結クラスはどれもモジュールを理解する際の負担を軽減してくれる
11章 アナリシスパターンを適用する
WIP
12章 デザインパターンをモデルに関係づける
ストラテジーパターン
アルゴリズムのファミリーを定義し、それぞれをカプセル化して、相互に交換可能にする。
- プロセスの中で変化する部分を、モデルの中で独立したストラテジーオブジェクトとして括りに出すこと
コンポジットパターン
オブジェクトを組み立てて、部分と全体の階層を表すツリー構造を作ること。
ネストされたコンテナの関係性がモデルに反映されていないと、共通するふるまいを階層レベルで繰り返さなければならず、ネストに柔軟性がなくなる。
13章 より深い洞察に向かうリファクタリング
- ドメインに馴染む
- 常に、物事に対して違う見方をする
- ドメインエキスパートとの対話を途切れさせない
4部 戦略的設計
14章 モデルの整合性
継続的な統合
すべてのコードと外の実装成果物を頻繁にマージさせるプロセスを策定すること、その際、分裂に対して、素早く
警告する自動化されたテストを一緒に用いること。
コンテキストマップ
システムが大規模になると、関係者すべてで統一したモデルを作ることは難しくなる
コンテキストマップを構成する際のポイント
- 境界づけられたコンテキストには、それについて話ができるように名前がなければならない。それはユビキタス言語であるべき
- 全員がどこに境界があるかを知っていなければならず、コードのどの一部をとっても、そのコンテキストを認識しなければならない
腐敗防止層
他システムとの統合における変換層
外部システムは、自システムと同じ概念ドメインモデルを使用しているとは限らない。
詰め替えの層を挟むことで、外部システムの変更に対して自システムへの影響を防ぎやすくなる。