ドメイン駆動
とは
-
以下のアプローチをとる
-
ドメインを抽象化しモデルに落とし込む
-
モデルをソフトウェアとして実現する
-
ソフトウェアには以下の課題がある
-
実際の業務をきちんと理解しないで作ったら、リリースしてもあんまり使われなかったり不評なものができる
-
きちんと整理されてないプログラムを書いたら、あとから修正するのがどんどん大変になる
-
それを解決するためには
-
ドメインについて理解を深め、モデルを改善する
-
ドメインエキスパートからフィードバッグをもらう
-
認識齟齬やコミュニケーションコストを減らすため、ドメインエキスパート、開発者全体が同じ言語
ユビキタス言語
を使う
-
このモデルは、ここの問題の範囲、こっちはここ、のように
境界付けられたコンテキスト
を明示する
-
モデルを継続的にソフトウェアに反映する
-
モデルを改善したら、おのずとモデルをソフトウェアも反映する必要がある
-
通常、モデルはDBの構造に近いので、変更コストが高い
-
それを達成するために
-
モデルをできる限りソフトウェア上に表現する
-
モデルとコードに乖離があると、マッピングが大変になっていく
-
モデルをドキュメントに記述しようとしても齟齬が生まれると困る
-
実績のあるDDDのデザインパターンを使用する
-
ドメインって言葉自体が抽象的だけど
-
ビジネスルールや使い方をソフトウェアにきちんと反映させましょうねってこと
用語
ドメインオブジェクト
現実のドメインの振る舞いを表したオブジェクト
普通のオブジェクト指向でモデルを取り扱おうとしたらできるオブジェクトと考えて良い気がする
値オブジェクト
-
Identifyが出来ない
-
同じ値(属性)なら同じものとして扱われる(プリミティブな値と考えて良い)
-
不変:生成されたらあとは破棄されるだけ
エンティティ
-
Identifyができる
-
値が変更されても同一性を保ち、値が同一でも識別ができる
-
つまりシステム上(または全世界)でユニークな
id
属性に当たる属性を持つ
-
ライフサイクルが必要な場合、エンティティになる
サービス
オブジェクト間のタスクを実行する
ドメインサービス
-
ドメインのルールに起因する処理だが、各ドメインオブジェクトが実行するのは不自然な処理はドメインサービスが実行する
-
ユーザー自体に関する処理はドメインオブジェクトに持たせるが、ユーザーが存在するか否かはドメインサービスが確認する
アプリケーションサービス
-
アプリケーションのユースケースを実行する
-
ドメイン知識は持たず、ドメインオブジェクト間のタスク管理を行うようなイメージ
-
状態は持たない
-
一時的には持つが、永続的には持たない
-
各処理のときにドメインオブジェクトから取得する感じ
-
ドメインオブジェクトの振る舞いを呼び出すのはアプリケーションサービス(経由)で行う
リポジトリ
技術的なルールを抽象化し、オブジェクトの永続化を担う
NoSQLかRDBかインメモリか等はアプリケーションの関心事ではないため、そこを抽象化する
コントローラーはビューの実装をドメイン(モデル)に変換するだけの役割
ゲームのコントローラーは、人の入力をゲームの入力に変換する役割
集約
集約外から操作する際は、集約Root経由で操作を行う
Index.tsからreExportするようなイメージでいい気がする(ちょっと違うけど)
-
集約はできるだけ小さく保つ
-
集約単位 = リポジトリの単位 = Transactionの単位になるため
-
Transactionは可能な限り小さくしてロックを減らす
その他
-
依存関係逆転の法則
-
オブジェクト指向で処理やモデルを切り分けるのにわざわざクラスを実装するの大げさだなと思っていたけど、OOP言語は純粋(トップレベル)関数が実装出来ない。なのでTypeScriptでObjectを定義する=OOPでClassを定義するくらいの認識。
共通認識
上のレイヤーに行くときに、下のレイヤーの知識は抽象化する
参考