Tsubatoの発信記録

主に機械学習やデータサイエンス関連で学んだことを書いています。

読書記録 ドメイン駆動設計入門

0. この投稿の概要

  • ドメイン駆動設計入門を読んで学んだことをまとめます。ドメイン駆動設計とはプログラムの適用対象の領域の知識に焦点をあてた設計手法です。

  • ドメインの知識はドメインオブジェクトとしてコードで表現され、それらを組み立てることでアプリケーションが実現されます。本書ではドメインオブジェクトとアプリケーションの実装パターンが主に紹介されています。

1. 知識を表現するパターン

値オブジェクト
  • システム固有の値を表したオブジェクトであり「値」がもつ3つの性質を持つ。その性質は不変である、交換が可能である、等価性によって比較されること。
    • ここでいう値は1や"hello"のようなリテラルのようなものか。これらは当然変更できないし、あくまでこれらの値をもつ変数の中身を交換することができる。また、==のような演算子で比較ができる。
  • どの値を値オブジェクトとして実装するかの判断基準は「ルールが存在しているか」(ルールをオブジェクトが担保するため)と「それ単体で取り扱いたいか」。
  • 値オブジェクトのメリットはその値に関するルールの実装を集約できること。プリミティブ型を使う場合、その値を利用する場所全てでルールチェックをする必要がある。
エンティティ
  • 値オブジェクトとは異なり、属性ではなく同一性によって識別されるオブジェクト。値は可変で、識別のためにIDを持ち、等価性の比較はIDだけを比べる。例: ユーザ情報
  • エンティティを採用する判断基準は「ライフサイクルが存在し、そこに連続性が存在するかどうか」。同じものでもシステムの関心によって値オブジェクトとエンティティどちらが適切か変わる。
  • エンティティ、値オブジェクトのようなドメインオブジェクトを使うメリットは、ドメインの変化に対応するために変更する場所が明確になること。
ドメインサービス
  • ドメインオブジェクトに実装すると不自然になるようなふるまいを提供する。例: ユーザ名の重複確認
  • 手続き型の実装を助長してしまいので、可能な限り使わない。

2. アプリケーションを表現するためのパターン

リポジトリ
  • オブジェクトのインスタンスをデータストアに保存するときは、直接的にデータストアに書き込みを実行せずに、リポジトリに依頼をする。逆にインスタンスを再構築するときもリポジトリに依頼をする。
  • リポジトリはインターフェースとして抽象化して、具体的なデータストアの操作はその具象クラスとして実装する。
アプリケーションサービス
  • ドメインオブジェクトを組み合わせてユースケースを実現するオブジェクト。例: ユーザ情報のCRUD処理
  • ユーザ情報取得処理ではドメインオブジェクトをそのまま返すとアプリケーションサービス以外のオブジェクトがドメインオブジェクトのふるまいを呼び出してしまう可能性がある。それを防ぐためにはデータ転送用のオブジェクトを代わりに返す。
  • ドメインのルールはアプリケーションサービスに記述しないで、ドメインオブジェクトやドメインサービスに記述する。
ファクトリ
  • 複雑なオブジェクトの生成を処理するオブジェクト。「コンストラクタ内で他のオブジェクトを生成するかどうか」はファクトリを作る際の動機づけになる。

3. 知識を表現する、より発展的なパターン

集約
  • 集約は複数のオブジェクトをまとめてひとつの意味を持ったオブジェクト。集約の外部から内部のオブジェクトを操作してはいけない。必ず集約オブジェクト自身が内部のオブジェクトを操作する。
  • そもそもインスタンスを持たせなければ、内部のオブジェクトを外部から呼び出しようがなくなる。インスタンスの代わりにそのIDを保持すればメモリの節約にもなる。
仕様
  • 仕様はあるオブジェクトが評価基準に達しているか判定するオブジェクト。
  • 複雑な評価はドメインオブジェクトの一つなのでアプリケーションに記述すべきではないが、エンティティに置くと煩雑になる。その場合は仕様として独立しドメインオブジェクトとして切り出す。

4. その他

依存関係逆転の原則
  • データストアの操作などハードに近い処理を行うオブジェクトは下位レベルで、クライアントに近い処理は上位レベル。上位が下位に依存してはならず、抽象オブジェクトを作成し、どちらのオブジェクトも抽象に依存するようにする。
ユビキタス言語
  • プロジェクトにおける共通言語(語彙)、最終成果物であるコードでもこの表現が現れるべき。

5. 感想

  • ドメイン駆動設計というと謎の用語が大量にあってハードルが高く感じるが、本書を読むとそこまで身構える必要がないような気分になる。ちゃんと理解するには原典を読むべきなんだろうが、その下準備として読んで損はない一冊だと思う。

  • 私はボトムアップな設計*1とはどのようなものか知りたくて本書に手を出したが、本書で取り上げるアプリケーションが小さかったので、ドメインからどのようなドメインオブジェクトを取り出せばよいかという設計の話がほとんど無く少し残念だった。
  • ドメイン駆動設計」を採用せずとも、知識やルールを部品として独立したオブジェクトにして、それらを組み合わせてアプリケーションを作るというのはオブジェクト指向の基本だと思うので、拝借できるテクニックや考え方は使わせてもらいたいと思う。

*1:副題にボトムアップという言葉が入っているが、あくまでドメイン駆動設計をボトムアップ的に説明するという意味。著者もドメイン駆動設計はボトムアップなアプローチだと書いているが、その詳しい説明はなかったと思う。