超約『エリック・エヴァンスのドメイン駆動設計』(前編)
『エリック・エヴァンスのドメイン駆動設計』を読んだのでまとめてみます。
第1部 ドメインモデルを機能させる
第1章 知識を噛み砕く
我々プログラマはシステム開発のプロだが、顧客自身の業務領域(ドメイン)に関しては何も知らない。
一方、顧客は自身の業務領域については熟知しているが、それを上手くシステム化する方法を知らない。
したがって、顧客が持つ「何をするのか、なぜするのか」とプログラマが持つ「どうやってやるのか」をすり合わせる作業が必要。
方法を知る者が職を得て、彼の働く理由を知るものが雇い主になる。
――クラフト・ロレンス(行商人)
昔の人はよく言ったものです。
第2章 コミュニケーションと言語の使い方
一言で言うと、「名前重要」。*3
本書の中ではどこでも使える言語ということで「ユビキタス言語」と言っている。
プログラマが使う言葉と顧客が使う言葉に乖離があってはならない。
技術的に詳細な部分まで顧客に理解してもらう必要はないが、クラス名やインスタンスが持つ属性名は顧客と共有できるものでなければならない。
実装上、クラス名などは英語でつけると思うので、このあたり英語圏の人間は得だなと思う。
第3章 モデルと実装を結びつける
プロジェクト参加者の共通語彙(ユビキタス言語)を設定し、ドメインを表せるモデルを考えたら、それを実装に生かす。
ただし、困難なことは常に実装をする際に現れる。
実装上の困難が生じた場合、モデルを考えなおす。
このとき、実装上の困難を解決するために、ドメインモデルと実装が乖離してはならない。
また、ドメインモデルと実装を解離させないがために、貧弱な機能になってはならない。
ドメインモデルと実装を一致させるためには、モデリングと実装の間でコミュニケートし、フィードバックを伴ったイテレーションによってすり合わせを行う必要がある。
そのためには、モデルに携わる人がコードに触れ、コードを書く人がモデルを理解・表現しなければならない。
第2部 モデル駆動設計の構成要素
第4章 ドメインを隔離する
他の一般的な設計のように、ドメイン駆動設計においてもレイヤ化アーキテクチャを用いて複雑な処理をシンプルな要素に分解する。
本書では、
の4層に分けられている。
このうち、アプリケーション層は「何をするべきか」のみ知っているべきであり、「どうやるか」はドメイン層がその責任を負う。
ドメイン駆動設計では、ドメインモデルを表したドメイン層によってソフトウェアが構成される。
ドメイン層の要素を他の無関係な要素から分離し、設計と実装を一致させることがドメイン駆動設計の必須条件となる。
第5章 ソフトウェアで表現されたモデル
ドメイン駆動設計では、モデルを表現する要素を3パターンに分ける。
エンティティ
仮に「人オブジェクト」なるものがあったとして、ある2つのインスタンスの氏名が一致したとしても、それは同姓同名の人というだけであって、同一人物ではない。
こういった、同一性によって定義されるオブジェクトをエンティティと呼び、エンティティは連続性を維持しなければならない。
値オブジェクト
あるモデル要素が物事の特徴を記述するものであり、その属性しか関心の対象にならないのであれば、それを値オブジェクトという。
値オブジェクトにおいては同一性は重視されない。
値オブジェクトはその性質上、複数のインスタンスから参照されるので、不変(immutable)でなければならない。
また、住所と郵便番号など、類似の概念バラバラに定義するのではなく、統一体を形成すべきである。*7
サービス
設計を進めていくと、概念的にどのオブジェクトにも属さないような操作が含まれることがある。
この操作をどこかのオブジェクトに無理やり押し付けるのではなく、独立したサービスとして設計する。
エンティティや値オブジェクトが本質的に名詞になるのに対し、サービスは「何かをする」ものであるため、動詞にちなんで命名される傾向がある。また、この操作名はユビキタス言語と共通の語彙でなければならない。
さらに、サービスは何かを受け取って何かを返すためだけに使用し、サービスに状態を持たせてはならない。
第6章 ドメインオブジェクトのライフサイクル
オブジェクトは生まれてから破棄されるまでの間に様々な状態を経る。
このオブジェクトの生涯にわたって整合性を維持し、かつ、ライフサイクル管理によってモデルが複雑になることを防ぐ必要がある。
そのために3つのパターンを用いる。