「ドメイン駆動設計 モデリング実践ガイド」を読んだ

February 05, 2023

ドメイン駆動設計 モデリング実践ガイド

https://booth.pm/ja/items/1835632

DDD周りを改めておさらいするために読んだ。 ネットで一通りDDDの記事とかを流し見した後に読むとよさそう。 コンパクトだが、体系的にまとまっている。

memo・感想

第1章 DDD 概要

DDD とは?

  • Domain : ソフトウェアで問題を解決しようとする対象領域
  • DDD とは、モデリングによってソフトウェアの価値を高めることを目指す開発手法
    • モデルとは?
      • ドメインモデル:ドメインの問題を解決するためのモデル
      • データモデル:データの永続化(永続化方法の効率化という問題を解決するための)モデル
    • 基本的にはモデル = ドメインモデルを指す

綺麗なコードを書くことはもちろんだけど、ちゃんと価値を生み出せるような・生み出し続けやすいコードを目指す(その結果綺麗なコードになる)。 手段と目的を履き違えないようにしないとね。

よくないモデルとは??

  • 問題を解決できないモデル
    • ドメインの問題を解決する目の必要な要件を満たすことができないもの
      • XXXの機能がない
      • YYYができない

結局ソフトウェアを使って、課題解決・価値創出ができないと意味ないもんね。

良いモデルを作るには???

  • ドメインエキスパートと会話をする
    • 業務に詳しい人
  • 運用して得られた発見をモデルに還元する

下請け的に仕事をするのではなく、一緒に課題解決をする意識。 相手の言っているドメインの課題の本質を理解する。よく言われることだが「言われた機能をただ作る」だけではダメ。 また、運用してみないと見えてこない課題ももちろんある。 普段から密にコミュニケーションを取り、開発後の課題も認識し、改善を続ける。

取り組む上での大事な考え方

  • 課題ドリブン
  • 小さく初めて小さく失敗
    • アジャイル的に

何をやるにしても大事な考え方

DDDの向き不向き

  • 向いている
    • 解決しようとしているドメインが複雑な場合
  • 向いていない
    • シンプルなアプリケーション
    • 技術的な関心ごとの方が高い
      • いかに高速に動かすかなど

なんでもDDD病に陥らないようにしないと

第2章 モデリングから実装まで

ドメインモデル貧血症とは??

  • ドメインそうのオブジェクトが、十分なドメイン知識(ルール・制約)を持っていないこと
  • UseCase層にドメイン知識が染み出したりしている
    • 結果、そのドメインの整合性がどこで担保されているのかが追いづらい
    • 整合性が保てなくなったりする。

なんで貧血に喩えられているんだろ

ユースケースそうの考え方

  • 「何をしたいか?」(What)だけを示す
  • 「どう実現するか?」(How)はドメイン・リポジトリに隠蔽する

非常にわかりやすい説明。

ドメイン層オブジェクト設計の基本方針

  • ドメインモデルの知識を対応するオブジェクトに書く
    • レイヤー分けを機械的に行うことで見通しが良くなる
  • 常に正しいインスタンスしか存在させない
    • 生成条件の強制
      • 正しい条件で作られることを保証
    • ミューテーション条件の矯正
      • 正しい状態であり続けることを保証
      • 変更は、正しい変更を保証するメソッドのみを通して行われる

ミューテーション条件の矯正、ユースケースでやっちゃう時があるから気をつけないと。

第3章 DDD固有のモデリング手法

集約とは?

  • 「 必ず守りたい強い整合性を持ったオブジェクトのまとまり」のこと
    • 片方の状態がもう片方に影響するもの
  • 強い整合性確保が必要なものを一つの集約に
  • トランザクションを必ず一つに

まだ理解が浅い。

境界づけられたコンテキストとは?

  • 特定のモデルを適用する境界
    • 「商品」と言っても、関係者の中で示すこと・関心ごとが違う。商品を買って郵送する時、同じ商品だが。
      • 販売部:売値・在庫
      • 配送部:配送先・配送状況

コンテキスト(ドメインを扱う人の立場)によって、対象への関心ごとが変わるよねって話

第4章 設計の基本原則

凝縮度・結合度

  • 機能・クラス単位で考える
  • 高凝縮・低結合にすればするほど以下の項目が改善する
    • 理解容易性
    • 拡張性
    • 信頼性
    • 再利用性
    • テスト容易性
  • 凝縮度
    • 「このクラスは何をするものか?」が明確になっていれば高い凝縮度
  • 低結合
    • 他の変更の影響を受けない。影響が小さい。

低結合に意識が行きがちで、高凝縮になっていない時がある(自分の話)。一言で「何をするクラスか?モジュールか?」を答えられることを意識しないと。

第5章 アーキテクチャ

3層アーキテクチャ

  • プレゼンテーション層
    • クライアントとの入出力
  • ビジネスロジック層
    • ユースケースの実現
    • ドメイン知識の実現
  • データアクセス層
    • データベースとの入出力
    • ドメイン知識の表現

問題点

  • ビジネスロジック層が低凝縮になりがち
  • ドメイン知識が、ビジネスロジック層とデータアクセス層に分散しがち

実際三層アーキテクチャで作られて、数年運用されたサーバー触ってたけど、プレゼンテーション層もファットになりがち。要は三層とも全部肥大化しがち。

レイヤードアーキテクチャ

プレゼンテーション層 => アプリケーション層 => ドメイン層 => インフラ層 に依存。レイヤー毎の凝縮性が高まり、可読性が上がる。 が、ドメイン層(コア知識)が、インフラに依存してしまう。

オニオンアーキテクチャ

レイヤードアーキテクチャの進化系 依存関係逆転の原則を用いて、ドメイン層とインフラ層の依存関係を逆転。 図が丸型表記になっているので、オニオンと呼ばれているらしい。

ヘキサゴナルアーキテクチャ

基本的には、オニオンアーキテクチャと同じ。より詳細を定義したもの。 アプリケーションと外の世界がやり取りする際は、専用のポートとアダプターを作成するという思想に則っている。

クリーンアーキテクチャ

オニオン・ヘキサゴナルの進化系・概念の統合系らしい。

アーキテクチャを網羅して説明してくれている点が良い。個別での説明はよくあるが、網羅されているのは意外となかったりするので。

第6章 ドメイン層の実装

エンティティ

  • 同じ値でもそれぞれが違うもの
  • 識別子を持つ
  • 社員などはエンティティ。
    • 同じ名前でも違う社員
    • 社員番号という識別子を持つ

値オブジェクト

  • 同じ値であれば同じもの
  • 識別子を持たない
  • お金など
    • 違う10円玉でも同じ10円

ドメインサービス

  • オブジェクトとして表現すると無理があるもの
  • 集合に対する操作など
  • 重複チェック
    • 一つのオブジェクトで重複チェックはできない(他のオブジェクトも確認する必要がある)
    • こういった場合に用いる

ついついフワッとしたドメインサービスを作りがちなので気をつけねば。。

リポジトリ

  • 集約単位で永続化層へのアクセスを提供するもの
  • インターフェイスはドメイン層・実装はインフラ層に
  • リポジトリをListのように扱うと設計がうまくいく

List のように扱うという設計方針は初耳なので試してみたい。

ファクトリー

  • 生成の責務を持ったオブジェクト
    • ドメインサービスの一種とも言える
  • オブジェクトの生成ロジックが複雑な場合や、他の集約を参照する必要がある場合に使う。

第7章 ユースケース(アプリケーション)層の実装

  • ドメインが公開しているメソッドを使ってユースケースを実現する
  • 1ユースケースのクラス、1パブリックメソッドのイメージ

ユースケースが綺麗だと、大枠を記載した仕様書っぽくなるよね(細かい知識はドメイン)

第8章 CQRS

CQRS って何??

  • Command Query Responsibility Segregation(コマンドクエリ分離)
  • 参照に使用するモデルと、更新に使用するモデルを分けること
  • 参照系モデルは、特定のユースケースに特化した値の型を定義

メリット

  • 複数集約にまたがるでターを取得する際のコードがシンプルになり、保守性が高まる
  • クエリパフォーマンスが上がる、チューニングしやすくなる
  • 複数集約の条件で絞り込んでのページングができるようになる

デメリット

  • ドメインオブジェクトのデータが参照されている場所が追いにくくなる
  • アーキテクチャ自体が複雑になり、理解にコストがかかる

実際あんまり理解しきれていないかも。一回作って試してみよう。

第9章 プレゼンテーション層

  • クライアントとアプリケーションの入出力を実現
  • ユースケースからの返却値は、特定のクライアントに依存しない形式にする
  • クライアントに合わせたデータ形式への変換はプレゼンテーション層で行う

感想

コンパクトに要点が纏まっていて読みやすい本だった。アーキテクチャ周りも整理されており、わかりやすかった。DDD初心者や、知識を整理し直したい人にはおすすめ。


Profile picture

Written by kuropenguin Backend engineer who lives and works in Tokyo. About meTwitterGitHub