先日、上記の本を読んだので読書メモを残します。 (知識のまとめに若干AIの力を借りています)
書籍の感想
「ドメイン駆動設計」というものについて言葉だけ知っているが意味はよく知らない、という状態だったので読んでみました。
「ボドムアップでわかる!」あるように具体例から解説をされていて、なぜこれが必要なのか、という点が理解しやすく感じました。
普段Railsでアプケーション開発をしていると、Railsの「レール」で開発をしていると遭遇しない層の話などもあり、Railsの「設定より規約」の思想をより感じることになった一冊だったような気がします。
ドメイン駆動設計とは
ビジネスの問題を解決するためにビジネスの理解を進め、ビジネスの表現をする。ビジネスとコードを結びつけて継続的かつ反復的な改良を施せるように枠組みを作ることにより、ソフトウェアをより役立つものにしようというものです。
成瀬 允宣. ドメイン駆動設計入門 ボトムアップでわかる!ドメイン駆動設計の基本 (p. 4). (Function). Kindle Edition.
先日読んだ『ソフトウェアアーキテクチャの基礎』でもそうだったが、「継続的に反復する」というのは現代で良い設計とされるための重要な要素なんだろうという感想です。
Chapter1 ドメイン駆動設計とは
- ドメインは「プログラムを適用する対象となる領域」
- ドメインの概念をモデリングして得られたモデルをドメインモデルと呼ぶ
- モデリング: ドメインの概念を、ソフトウェアで必要な情報に限定して抽象化する作業
- ドメインモデルをソフトウェアで動作するモジュールとして表現したものがドメインオブジェクト
- したがって、ドメインの変化があれば、ドメインモデルを通じてドメインオブジェクトに伝達される
Chapter2 値オブジェクト
- 値オブジェクトとは、「氏名」などのようにシステム固有の値を表したオブジェクトのこと
- 値オブジェクトの値は不変
- 値オブジェクトにすべきかどうかの判断基準は、「そこにルールがあるか」「それ単体で扱いたいか」
- 振る舞いをまとめてルールを語らせる(自己文書化)
- 「表現力を増す」「不正な値を存在させない」「誤った代入を防ぐ」「ロジックの散在を防ぐ」を実現するための手段となる
Chapter3 エンティティ
- 値オブジェクトとの主な違いは「同一性によって区別される」「可変」「同じ属性でも区別される」「ライフサイクルがある」
-「ユーザー」のイメージ
- idが同じであれば同じ、同じ生年月日でも別々のユーザーと認識される、退会でユーザーが削除される、など
| 値オブジェクト | エンティティ | |
|---|---|---|
| 同一性の基準値 | (中身) が同じなら同じもの | ID が同じなら同じもの |
| 不変性 | 不変 | 変化してよい |
| 例 | 金額、住所、色、座標 | ユーザー、注文、商品 |
Chapter4 ドメインサービス
- ドメインオブジェクト(値オブジェクトやエンティティ)に記述すると不自然になる振る舞いを記述する場所
- 例えばユーザーの重複チェックをユーザーオブジェクトにさせると、ユーザーオブジェクト自身に問い合わせることになり不自然
- ただし、ドメインオブジェクトに記載できることまでドメインサービスに書くと、ドメイン貧血症(ドメインが何も語らなくなる)になるので注意
Chapter5 リポジトリ
- データの永続化にまつわる処理を抽象化するための層(DB操作など)
- ドメインオブジェクトがDBの変更等の影響を受けない
感想
RailsだとActiveRecordでいわゆる「ドメインオブジェクト」と「リポジトリ」の役割が両方入っており明確に違うなーと勉強になった。
Chapter6 アプリケーションサービス
- アプリケーション向けのユースケースを実現するオブジェクト
- ユーザー登録など
感想
RailsのServiceクラスの役割に一番近いのはこれかなーと思ったりした。
Chapter7 柔軟性をもたらす依存関係のコントロール
- 依存関係逆転の法則
- 上位レベルのモジュールは下位レベルのモジュールに依存してはならない、どちらのモジュールも抽象に依存すべきである。
- 抽象は、実装の詳細に依存してはならない。実装の詳細が抽象に依存すべきである。
- とあるアプリケーションサービスがリポジトリクラスに依存してしまっている場合(上位が下位に依存し、抽象が詳細に依存してしまっている状態)、抽象層を作成することでアプリケーションサービスとリポジトリクラスが共に抽象に依存できるようになり、リポジトリの変更がアプリケーションサービスに影響しないようにできる
- データベースの操作のコードを変えたらより高レベルなアプリケーションサービスのコードを変えないといけない、というのは避けたい
Chapter9 複雑な生成処理を行う「ファクトリ」
- 複雑なオブジェクトの生成処理をオブジェクトとして定義すること
- 「コンストラクタ内で他のオブジェクトを生成するかどうか」はファクトリを作る際の動機づけに良い指標
Chapter10 データの整合性を保つ
- ユニーク制約やトランザクションを使って整合性を保つ
- ただ、整合性は高次元な概念
- ビジネスロジックには整合性を保つための詳細ではなく、整合性が必要な処理であることの明確な主張が書かれるべき
Chapter12 ドメインのルールを守る「集約」
- 集約ルートを通ってのみオブジェクトを操作させるようにする
- 関連するものとして、オブジェクト指向では「デルメルの法則」がある
- userクラスの中で、address.location.cityとせず、userがcityメソッドを呼べるようにして、内部構造(addressやlocation)を知る必要をなくすようなこと
Chapter13 複雑な条件を表現する「仕様」
- あるオブジェクトがある評価基準に達しているかを判定するオブジェクト
- ドメインオブジェクトが必要以上に他のオブジェクトの情報を知らないといけなかったりする際に導入し、複雑な評価処理をカプセル化する