B-Teck!

お仕事からゲームまで幅広く

【本】ドメイン駆動設計入門を読んだ

よんだ

読書メモ

  • chapter1
    • ドメインとは
      • プログラムを適用する対象となる領域
      • ドメインの概念を抽象化したものがドメインモデル
      • ドメインモデルをコードで表現したものがドメインオブジェクト
  • chapter2
    • 値とは?
      • 不変
      • 可換
      • 等価性
    • システム上必要な値はプリミティブなものではない可能性がある
      • 値をオブジェクトの形で表現したのが値オブジェクト
    • 値オブジェクトとして切り出す基準
      • 値としてのルールが存在するか
      • 単体で取り扱いたい概念か
        • 値として表現する価値のある概念か
    • バラバラの引数などではなく値オブジェクトとしてまとめるモチベーション
      • コード上での表現力を増す
      • 不正な値を存在させない
      • 誤った代入を防ぐ
      • ロジックの散逸を防ぐ
  • chapter3
    • エンティティとは?
      • 可変
      • 属性ではなく識別子などの同一性によって区別される
    • エンティティとして切り出す基準
      • システムの中にライフサイクルがある概念など(ユーザーとか)
  • chapter4
    • ドメインオブジェクトに振る舞いとして持たせると不自然なものを置くのがドメインサービス
    • ドメインサービスを使うのは最小限にするべき
      • オブジェクト自身の振る舞いがなくなってしまい、コード上の表現力が下がる
  • chapter5
    • リポジトリの責務
      • ドメインオブジェクトの永続化や再構築
    • リポジトリはinterfaceと実装で分ける
      • 利用側は具体の技術に依存せずに利用できる
      • ユニットテストしやすくなる
    • 重複確認などをリポジトリに持たせるのは注意
      • ドメインのルールの流出とも取れる
      • 識別子を渡して返却値をドメインサービスで検証するなど
  • chapter6
    • アプリケーションサービスとは
      • ユースケースを表現するためのオブジェクト
      • ドメインオブジェクトを組み合わせてユーザー機能を実現する
    • アプリケーションサービスにドメインオブジェクトを公開するか?
      • 公開する場合、ドメインの振る舞いを意図しないタイミングで利用される可能性がある
      • DTOなどに詰め替えるほうが唖然
    • 複雑な入力はCommandオブジェクトに切り出すなどする
      • 入力に変化があってもシグネチャが変わらないため、入力と操作のみの修正で良くなる
    • 凝集度を高めるためユースケース別にクラスを分ける場合もある
    • アプリケーションサービスは振る舞いを変えるような常態をもってはいけない
  • chapter7
    • 依存元・依存先が抽象を介して依存していることを依存性逆転の法則と呼ぶ
    • 抽象への依存を利用して実体を切り替える手法にService LocatorとDependency Injectionがある
  • chapter8
    • ドメインオブジェクトの生成はドメインの知識である
      • 複雑な生成はFactoryを作って切り出すとわかりやすくなる
  • chapter10
    • 連続する複数の処理はトランザクションで守られるべき
    • データベースの制約でも守れるが、基本はアプリケーションでも制約をかける
  • chapter12
    • 集約とは?
      • 不変条件を維持する単位
      • 境界とルートを持つ
        • 境界: 集約に含まれる範囲を定義する境界
        • ルート: 集約に含まれる特定のオブジェクト
    • 集約への操作はルートを経由し、内部のオブジェクトを直接操作しない
      • ルートが境界内のルールに責任を持つことをデメテルの法則っていうらしい
    • 集約の内部に実体を持たせず識別子のみをもたせる場合もある
      • ユーザー自体じゃなくてユーザーIDだけとか
  • chapter13
    • 仕様オブジェクトとは?
      • あるオブジェクトが仕様を満たしているかを判定するためのオブジェクト
      • 複数の集約をまたいだ制約などを判定させたいときに使う
      • アプリケーションサービスにドメインを流出させず、仕様としてまとめて管理できる
    • CQRS
      • コマンド: 書き込み
      • クエリ: 読み取り
      • 読み書きを分離することで複雑さを減らせる
    • QueryService
      • 集約をまたいだ複雑な検索や取得を、まとめる
  • chapter14
    • アーキテクチャは開発者に対するガードレールである
    • レイヤードアーキテクチャ
      • UI/アプリケーション/ドメイン/インフラで層を分ける
      • 各層の知識を他の層に持ち出さない
    • ヘキサゴナルアーキテクチャ
      • アプリケーションのコアに対してUIや保存媒体を差し替えられる
    • クリーンアーキテクチャ
      • 目的はヘキサゴナルアーキテクチャと同じ
      • Controllerからの呼び出し、処理、出力のそれぞれが抽象に依存している
        • 依存の方向が一方になるよう厳密に定義されている
  • chapter15
    • 実装パターンをなぞるだけでは軽量DDD
    • パターンが主眼ではなく、ドメインを表現するためのもの
    • ドメイン理解の手法
      • ドメインエキスパートとのモデリング
        • 開発者・ドメインエキスパート双方の理解を深めながらドメインモデリングを行う
      • ユビキタス言語
        • ドメインを表現するための言葉を定義する
        • コード上もユビキタス言語で表現されていると良い
      • 境界づけられたコンテキスト
        • 同じ言葉で表現されていても異なるコンテキストの場合がある
        • モデルに対する捉え方が変わる場所が境界
      • コンテキストマップ
        • 境界内のみに集中すると複数のコンテキストの関連を見失ってしまう
        • 各コンテキストのつながりを俯瞰できるようにしておく

感想

発売日に買ったものの複数回挫折していて、ようやく読み終われた。
いくつか気になる記述があったものの、DDDをコード上でどう表現するか概観するには良い本だった。

表紙に謳われているようにコードの表現からDDDの概念を説明する構成で、モデリングなどには踏み込んでいない。
これは良し悪しありそうで、設計パターンとして取り込む軽量DDDに流れてしまう危険性もあるかもしれない。できれば個別の概念を説明する軽めの本を別途読んでおくと良さそう。

ドメイン駆動設計入門というよりドメイン駆動設計実装入門みたいな雰囲気はある。

C#のサンプルコードをベースにScalaで写経しながら読み進めてたんたけど、Commandオブジェクトをどういう感じで表現するとしっくりくるのか全然わからない…
良いサンプルとかあれば教えて下さい