Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
ドメイン駆動設計読書メモ
  • 価値ある知識と無価値な知識を慎重に選り分けてコードに落とし込む
  • 現実の事象あるいは概念を抽象化した概念がモデル
    • 現実をすべて忠実に再現するわけではない
  • 💭 現実の世界をコードにするのがモデリングじゃない。開発者による取捨選択がある
  • ドメインオブジェクトはドメインモデルの実装表現
  • 値オブジェクト
    • 性質
      • 不変
      • 交換可能
        • 値を更新するのではなく、新しい値を代入する
      • 等価性によって比較される
        • インスタンスが異なっても、値が同一なら等価
    • ドメインオブジェクトにする基準
      • ルールが存在するか
      • 単体で取り扱いたいか
  • エンティティ
    • 可変である
    • 同じ属性であっても区別される
      • 同姓同名であっても同一人物ではない
    • 同一性により区別される
      • 識別子(Identity)が利用される
  • ドメインサービス
    • ドメインのためのサービス
    • 物流システムの輸送
      • ある拠点から別の拠点に荷物を輸送する
        • TransportService#transport(from, to, baggage)
      • 特定のオブジェクトの定義に当てはまらないものを抽出する
    • ユーザーの存在確認
      • UserService#exists(user)
    • 可能な限りドメインサービスを避ける
      • まずはエンティティや値オブジェクトに定義する
    • 入出力を伴う処理を取り扱わないようにする
      • ドメインモデルのコード上の表現である
      • エンティティや値オブジェクトと同一
    • 命名
      • ドメインの概念
      • or ドメインの概念 + Service
      • or ドメインの概念 + DomainService
  • リポジトリ
    • データの永続化や再構築を抽象的に扱う
    • find, get, save...
  • アプリケーションサービス
    • アプリケーションのためのサービス
    • ユースケースを実現する
      • ユーザー機能
        • 登録、確認、更新、退会、etc
    • ドメインオブジェクトを公開して扱うか
      • 公開する選択肢は処理自体を単純にするが危険性をはらむ
      • 非公開にした場合、公開オブジェクトに移し替えて返却する
    • パラメータにコマンドオブジェクトを用いる戦術
      • 更新可能なフィールドが増えるたびにメソッドシグニチャの変更が発生するのを防ぐ
    • まとまりを表現するのにパッケージを使う
  • LCOM (Lack of Cohesion in Methods)
    • 凝集度を計る
    • すべてのインスタンス変数はすべてのメソッドで使われるべき
  • 依存関係のコントロール
    • 依存関係逆転の原則 (Dependency Inversion Principle)
      • 上位レベルのモジュールは下位レベルのモジュールに依存してはならない
        • どちらのモジュールも抽象に依存すべき
      • 抽象は、実装の詳細に依存してはならない
        • 実装の詳細が抽象に依存すべきである
    • Service Locator パターン
      • 依存解決先となるオブジェクトを事前に登録しておき、ServiceLocator を経由してインスタンスを取得する
      • 導入しやすいが、アンチパターンと言われている
        • 依存関係が外部から見えづらくなる
        • テストの維持が難しくなる
    • IoC Container (DI Container) パターン
      • IoC (Inversion of Control) は「制御の反転」を意味する
      • Dependency Injection パターンは依存関係の変更に強制力をもたせられる
      • IoC Container は設定に従って依存の解決を行い、インスタンスを生成する
  • シングルトンを static の代わりとして扱うのは誤り
  • 複雑な生成処理
    • コンストラクタが単純でなくなるときはファクトリを定義する
      • コンストラクタ内で他のオブジェクトを生成するか
    • User#createCircle()
  • ユニットオブワーク
    • トランザクション制御のパターン
  • 集約
    • オブジェクト操作の原則
      • メソッドを呼び出すオブジェクト
        • オブジェクト自身
        • 引数として渡されたオブジェクト
        • インスタンス変数
        • 直接インスタンス化したオブジェクト
    • フィールがゲッターを通じて公開されていると、ルールが漏れ出すことを防げない
      • 内部データの隠蔽
        • 通知オブジェクトを使う
          • コードの記述量は大量に増える
    • 集約の区切り方
      • 変更の単位
      • リポジトリは変更の単位である集約ごとに用意する
    • IDによるコンポジション
      • 識別子をインスタンスの代わりとして保持する
    • 識別子の公開
      • 識別子に対してビジネスルールが記述されることは多くない
      • 公開するメリットのほうが大きいこともある
    • 集約の大きさはなるべく小さく保つべき
    • コードは可能な限り言葉との齟齬がないようにする
  • 仕様
    • あるオブジェクトが評価基準に達しているかを判定するオブジェクト
      • おすすめかどうか判定するオブジェクト
        • CircleRepsitory#find(Specification recommendSpecification)
      • 仕様をリポジトリのフィルターとして扱うときは、パフォーマンスへの考慮が必要
    • 複雑なクエリは仕様やリポジトリを使わず分離する
      • CQS や CQRS
      • コマンドとクエリの分離
  • 短絡的な解決を図ったコードは複雑怪奇な進化を遂げて、いつの日かあなたの前に立ちはだかる
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.