実践ドメイン駆動設計を読んだ
動機
Evans本だけだと抽象的な話が多く、またIDDDもよく読まれている本だったので。
特に集約、サブドメイン、境界付けられたコンテキストのあたりについて知りたかった。
感想
前半の問題空間、解決空間についての話や、サブドメインなどについての具体的な話が掘り下げられていて良かった。
一方で普段RailsでtoCのWebプラットフォームを作っている、という立場からすると、掲載されている実装自体がそのまま役に立つというわけではなく、またイベントソーシングに対してもちょっと懐疑的な部分があったので、後半はさほどだった。
章立てられてはいるが、別の章の中でも有用そうなことが書いてあるなと思ったので、概念ごとにメモをとることにした。
軽量DDDとは?
DDDを技術的なツールセットとして、エンティティやリポジトリなどの実装パターンを導入してみること
ユビキタス言語や境界づけられたコンテキスト: 戦略的設計
エンティティ, リポジトリなどの話: 戦術的設計
ドメイン、コアドメイン、汎用サブドメイン、支援サブドメイン
ドメインとは広い意味で言うと、組織が行う事業やそれを取り巻く世界のことだ(p.41)
ほとんどのソフトウェアのドメインは複数のサブドメインを持つ
ドメインは事業全体、その一部を指すのがコアドメイン・サブドメイン
エンタープライズモデル: ドメイン全体をカバーする単一のモデル
DDDはむしろ複数のサブドメインを組みああせて、組織の全てのドメインを組み上げることになる
ありがちな状況として、サブシステムの数が本来あるべき姿より少なすぎて、ひとつのサブシステムで多くの業務を掛け持ちしすぎている可能性がある(p.43)
本来サブドメインに分割すべきドメインモデルを分割できていないせいで、今後の変更もずっと困難になる
これは確かにそう、というかよく聞く話。ヤフーのクーポンとカートの話とか、ミノなんとかの動画の話とか
これはRailsだと厳しいかもなぁ。ありうる方法としてPostとUserがあったとして、authorsを用意するとか?それもあんまりかな?でもPostから参照しているUserの振る舞いを管理できるという点ではいい案かもしれない
=> 書籍の後ろの方で認証コンテキストから値オブジェクトとしてauthorsとかを作ってた
需要予測の導入はコアドメインになるだろう
事業の優位性を確立している領域がコアドメインになるっぽい。
これなら確かにサブドメイン関連の話もわかりやすくなった(凝集されたメカニズム然り)
業務に不可欠な内容を表しているがコアドメインとはいえないようなモデルのことを支援サブドメインと呼ぶ
業務上何か特別なことをしていなくても、ソリューション全体として必要なドメインもある。それが汎用サブドメインだ。(p.48)
ちょっとこのへん曖昧かも。てか支援サブドメインってDDD本に出てきた?
主要サブドメイン?
ドメインは問題空間と解決空間を持っている(p.54)
問題空間を評価する際には、既存のサブドメインや、今後必要となるサブドメインについても見ることになる
解決空間は境界づけられたコンテキストのことで、特定のソフトウェアモデルの集合となる
各サブドメインを、境界づけられたコンテキストと一対一で対応させるのが、望ましいゴールだ(p.54)
マッピングサービスは在庫コンテキストの中にはなく、在庫サブドメインの中にはある(p.57)
問題空間と解決空間の区別。解決空間においては別の境界づけられたコンテキストに属しているが、問題空間においては在庫サブドメインの中にある。
境界づけられたコンテキストの中にファイルが入るかどうかはチームがそれを管理しているかどうかによる(p.63)
単一の境界づけられたコンテキストは単一のチームが受け持つ(p.68)
認証・アクセスコンテキストを分離する
これはRailsだとPunditっていうgemがあって、主にActionで使ってたからレイヤによる分割なのかと思ってたけど
認証・アクセスのコンテキストが汎用的だからドメインを管理するためのライブラリになっていると思えば使い方が見えてくるかも
仕様パターン(Policy)が使われていて、検証以外に選択ができるのも納得
汎用サブドメインもしくは顧客にとっての支援サブドメインになるであろうドメインは、実際のところはその事業のコアドメインである(p.33)
ある境界づけられたコンテキストの開発を主作業としているのなら、外部の顧客からの視点がどうであれ、それは事業のコアドメインだ
意味がわからない
境界付けられたコンテキスト
境界づけられたコンテキストは当初の想定よりも比較的小さくなる
境界づけられたコンテキストはひとつの業務ドメインのユビキタス言語全体を捉えることができる程度の大きさにとどまるものであり、それよりは大きくならない(p.23)
コンテキストマップの描き方
DDD本だと境界づけられたコンテキストの切り方って大体チームとかの物理要因なのかなと思ってたけど
IDDDではチームが境界を発見した、みたいなことも書いてある
コンテキストのラベルをIssueやPRに貼るっていうのも良さそう
それを実装しようと思った人がどういう開発の流れになってるんだろう?っていうのが探せるので
企画側もプログラムのことはわかっていない
Aのことについて話すとあぁBのことですね、って言われるのは確かに不快かも
フィードバックループが成立していないのが問題な気がする
企画側はやりたいことを説明して、開発が細かいところを質問して実装するだと最終的なアウトプットは良さそうだけど
仕組みは知らないし、今後何ができるようになるのかもわからない、みたいな状態があってそれが嫌なのかも
きちんと仕組みを理解することで、管理画面での配送設定ミス、みたいなのを防げるといい
ドメインエキスパートが、ソフトウェアの設計に貢献できる(p.25)
ユビキタス言語
ユビキタス言語はドメインエキスパートの話す言語をただ使うだけではない、チーム全体で作り上げるもの
ナースが患者にインフルエンザワクチンを投与する、というのがあったら
Vaccine vaccine = vaccines.standardAdultFluDose()
nurse.adminsterFluVaccine(patient, vaccine)
みたいに書けるようにしないといけない
ということはUserNotifcation.send_pushみたいなやつって変なのかな
単にコードを読める状態にしておく、とも違う気がするし…
DDDを使うときには、アプリケーションサービスを適宜見直していくのが私達の役割になる
って書いてあるので多分そうなんだけど、じゃあユーザーがゲームのレビューを投稿する、っていうときにcurrent_user.create_posts!
ってするかって言われると多分違う
テストが両方ともユビキタス言語に従っている、っていうのも書いてあるけど、どういうレベルのテストなんだろう?アプリケーション層?
その「振る舞い」は今回のソフトウェアでモデリングしようとしているシナリオの意図を明示していない(p.31)
表現力を上げるために、テストデータも現実的なものにしなければいけないということだ(p.36)
テストデータを用意するときに必要最低限の属性だけセットするのか、実際に使われるメソッドを使って用意するのか、の答えになっている
図や用語集をメンテし続けるのは非現実的なので、いつでも捨てられるようにしておく
スナップショット的に使えるようにする、みたいな話だと理解
そうすると、ちゃんとタイムスタンプが欲しくなるよなぁ
- 新しいドメインオブジェクトが、ドメインモデルのクライアントからどのように使われるべきなのかを示すテストを書く(p.35)
その後、新しいドメインオブジェクトの正しさを検証するテストも追加する
インフラ
コアドメインモデルのオブジェクトとインフラストラクチャを結合させたりはしないこと(p.117)
通知とかをドメインからだすなってことやね。で、そのための仕組みにドメインイベントがいるってことなんだと思われる
=> 普通にアプリケーション層から出すこともある
リポジトリインターフェースの実装をインフラに置いてしまうと、インフラからドメインへの参照が起こることになる(?)ので良くない
=> これ
実装モジュール(?)
インフラストラクチャレイヤを再下層に置くと、いくつか不都合が起きることに気づいた(p.118)
ドメインレイヤが必要とする技術的なところ(?)
DIPを使ってインフラ > UI > アプリケーション > ドメインの順になるようにしている(p.119)
これどういうことなんだろう。ドメイン層がインフラ必要になったらドメイン層にインターフェース作ってインフラに実装させる、みたいなことなんだろうけど
インフラを最上段に持ってくるっていうのがピンとこないな。ドメインを最下段に持ってくるとどこにも依存していなくていい、っていうのは分かるんだけど
ヘキサゴナルにつながる、というのもちょっとまだ想像できないところかな
イベント駆動
ヘキサゴナル
このヘキサゴナルってやつ今流行ってる、IOだけ状態持たせてビジネスロジックは関数型でやろうみたいなやつと相性良さそう
アプリケーションの内部は、機能要件単位で設計する(p.123)
ヘキサゴナルの場合はユースケースを基準にして作り、何種類出力があるかとかクライアントがどうだとかは基準にしない(?)
イベント駆動がメッセージング、ヘキサゴナルと相性がいい p.124
集約の外部へ変更を伝播させるときにイベントを発行して、システムでそれを再度受け取る、みたいな形にしておけば疎結合になっていいよね、みたいな話だという理解。
わかるけどトランザクション管理大変そうと思っていたら、そもそもトランザクションの1単位が集約であるべきで、それ以外の変更は結果整合性で保証する、ということが書いてあって、確かに複数のシステムが関わるのであれば最初からその仕組みにしとくのはありなのかなと思った。
境界づけられたコンテキストにまたがった処理もイベント駆動で行うので、同じように切り離しておけると良いということかな
一方でイベント駆動はメッセージの再送や順番の問題など色々考えることが多くてしんどそうだなというのが正直なところ。サブシステムの何かが失敗したときに、失敗したというメッセージを発行してロールバックしたりするんだろうか。それも大変そう…
ドメインイベント
もしこれらの振る舞いがBacklogItemになければ、イベントの通知をクライアント側で作らなければならなくなる。ドメインのロジックがモデルから外に流出してしまうというわけだ(p.32)
アプリケーションレイヤがイベントのサブスクライバを登録することになるかもしれない(p.117)
サブスクライバが、イベントの発行元の集約に追加の問い合わせをすることは避ける(p.282)
イベントを捕捉するには、別の集約の状態に依存している集約を見つけるのが最も簡単だろう
イベントのペイロードに、そのイベントに対する処理を実行するための情報を詰める
イベント配信にWebを使うことで既存のキャッシュの仕組みを利用することができ、パフォーマンスやスケーラビリティの面で恩恵を受けることができる(p.303)
ドメインオブジェクトを冪等にすることが難しい場合は、サブスクライバ/レシーバ自体が冪等になるように設計することもできる(p.317)
サブスクライバの永続化メカニズムの中に記録用の場所を確保して、処理済みのメッセージのトピック名とそのメッセージIDを保存しておくことだ
イベントソーシング
イベントソーシング、集約に対するイベントを保存しておくのは大変じゃないかっていうのと、イベントの適用結果が後から変わらないことをどうやって保証するのか気になる (p.157)
たぶんイミュータブルデータモデルに近いと思うんだけどコマンドの記録だからもっと手前で保存してる?
A+ESを実装しようとすると、ほぼ間違いなく、何らかの形でのコマンドクエリ責務分離が必要になる(p.522)
イベントストリームへのクエリは難しいからだ
リードモデルプロジェクション(p.551)
シンプルなドメインイベントのサブスクライバ群を使って、永続リードモデルの生成と更新を行う。
イベントの写像を作り、読み込み専用モデルとして永続化する
ドキュメントベースのDBと相性がよい
ビューテーブルのようなものなので、プロジェクションの実装を変更したあとはリードモデルの再構築をすると書いてある。
それってどうなんだろう…デプロイにダウンタイムが必要になるってことだよね?イベント駆動だからメッセージはキューにためておいて、再構築したあとに処理すればいいという発想なんだろうか
この本自体がエンタープライズシステムを想定していて、本番運用後の頻繁なデプロイを想定していないとか、利用者の制限がやりやすいとかなのかも?
システム全体をイベント駆動にする、というよりは特定の領域に関してのみそうする、というのはありかなと思った。
例えばECサイトで、注文に関わるものをOrderEventとして管理するとか。
コンテキストでシステムが分かれている想定だから、スコープは自分の想定よりも狭いのかもしれない
イベントソーシングは本来、本質的に関数型であるものだ(p.562)
集約のメソッドは、ステートレスな関数群にも変換できる。
この関数はドメインサービスそして状態をパラメータとして受け取る。そしてゼロ個以上のイベントを返す。
これは確かにと思った。変更の伝播をイベントで表現して、ポートとアダプターで抽象化すればIO <-> ドメインみたいな構造に収めることができるというか…
リポジトリ、とかもIOを返すものとして考えるとクラスの切り分けもしやすそうかなと。だから関数型ドメイン駆動の本が出たりするんだろうか
集約
集約ルートによる識別子の生成の場合には、リポジトリを使うことが多い(p.170)
ドメインの識別子とデータベースの主キーを分けてもいい(p.179)
SecurityPrincipal型を検討したが採用しない(p.187)
ユースケースや隠れたシナリオに注意してモデリングする必要がある
集約の内部からリポジトリを使うことは、できる限り避けるべきだ(p.254)
集約のルールのひとつは、単一のトランザクション内では単一のインスタンスだけを変更しなければならないというものだ。(p.254)
集約の切り方の重要な指針だと思う
境界づけられたコンテキスト内で集約を見つけ出そうとするときには、そのモデルの真の不変条件を理解しなければいけない(p.340)
整合性の境界の論理的な意味は「その内部にあるあらゆるものは、どんな操作をするに関わらず、特定の不変条件のルールに従う」ということだ
ユーザーインターフェースからのリクエストは、ひとつの集約のインスタンスに対する単一のコマンドにして実行するよう注意しなければいけない。(p.341)
スペルミスの修正や、descriptionがnameをより適切に表すように変更するといった場合だろう
そういったことをドメインエキスパートが明示することはおそらくないだろうが、これは暗黙のルールといえる
複数の集約のインスタンスを更新しなければいけないようなユースケース
そのユースケースのゴールが、複数の永続トランザクションにまたがるものなのか、それともひとつのトランザクションで完結するものなのか。もし後者なら、そのユースケースは疑ってかかるに値する。
依存するオブジェクトは事前に探しておいて、集約のコマンドメソッドにそれを渡すほうが好ましい(p.373)
集約内で別の集約を探して処理に利用するのはやめておいたほうがいいということか
リポジトリやドメインサービスを集約のインスタンスに注入しない
アプリケーションサービスに注入するのは有用なやり方
永続指向のデータストアを使うと、集約に対する基本的な読み書きは、かなりシンプルになる。
そのため、この手のデータストアのことを、集約ストアあるいは集約指向のデーターベースなどと呼ぶこともある
キーを指定してデータを一気に読み書きできるので集約と相性いいのはわかる
本当にパフォーマンス上の問題がない限り、集約のルート以外から中身を取れないようにする(p.416)
単一のトランザクション内で、すべての型の集約のデータを読み出してから、プログラム内でそれを組み合わせたコンテナを組み立てて、
それをクライアントに戻すといった処理は行いたくない。ユースケースに最適化したクエリを使う。
永続化メカニズムに対して複雑なクエリを指定して、その結果をユースケース専用に作った値オブジェクトに動的に格納する(p.416)
ただし、このようなクエリが多くなってきたときは、集約の設計ミスを覆い隠すリポジトリ
の臭いがしている
それでも集約の境界に設計ミスがないときはCQRSを検討する
NoSQLは集約志向データベースと言える、というのは腑に落ちる表現だった
ユースケースに最適化したリポジトリのクエリはあくまでドメインに特化したものなので、作られるのはDTOではなく値オブジェクトで(p.499)
整合性
ユースケースについて考えるときはデータの整合性を保つのが誰の役割なのかに注目
それがユースケースを実行するユーザー自身の役割ならば、トランザクション整合性を保つようにしよう
もしデータの整合性の維持が、別のユーザー(あるいはシステム)の役割ならば、結果整合性を受け入れよう(p.352)
楽観的並行性制御のためだけに双方向の関連を維持するのは避けたほうがいい
インフラ(ORマッパーやフレームワーク)の問題をドメインに持ち込むなという話
ドメインサービス
ドメインサービスが使えるのはこれらのような場合だ(p.256)
重要なビジネスロジックを実行する
ドメインオブジェクトを、ひとつの構成から別の構成に変換する
複数のドメインオブジェクトからの入力に基づいて、値を算出する
なにかのメソッドをエンティティや値に持たせるのが単に不格好だという場合にも、サービスを定義すればうまく落ち着くだろう
アプリケーションサービス内でドメインサービス呼び出すとき、Serviceが入れ子になってるように見えるのがちょっと嫌だなと思った(p.445)
アプリケーションサービス内での他アプリケーションサービスの呼び出しは想定されてないみたいだけど、
ドメインサービスの方はエンティティと並列の関係っぽいから、その辺りの理解の統一が難しそう。
あと、命名もApplicationServiceの方はGroupMemberServiceみたいなちょっと抽象的な名前なのに、ドメインサービスの方は具体的な操作の名前になってないといけないっていうのもちょっと気持ち悪い。
RESTとRESTful
毎回忘れる
REST?RESTful? 今理解していることをアウトプットしてみる https://zenn.dev/keyproducts/articles/28f061ff450a25
統一インターフェース、アドレス可能性(一意リソース)、ステートレス、接続性
接続性: クライアントがサーバーへの経路を発見できるようにする。そしてHypermediaを使ってアプリケーションの状態を切り替える。リソースはリンクによってつながっている
HATEOAS: レスポンスにそのリソースでできることのリンクが載ってる
GET PUT DELETEは冪等
CQRS
伝統的なモデルの中にある問い合わせの責務と、同じモデルの中にある純粋なコマンド実行の責務とを、切り分けてみよう(p.134)
ゲッターだけをもつオブジェクトとオブジェクトの状態を変化させるメソッド(コマンド)だけをもつオブジェクトに分ける
確かに良さそうではあるけど、コマンド内での参照はどうするんだろう
どっちかというと複雑なビューにどう対応するか、パフォーマンスチューニングするか、への回答っぽい
CQRSでコマンドの最後にはクエリモデルを更新するためのイベントを発行しなければならない(p.140)
CQRSだとクエリとコマンドが分かれているので、コマンドの結果をクエリに反映させる仕組みが必要。それもイベントで行う。
長期プロセスは分散環境での並列処理が絡むことが多いが、分散トランザクションについては何も打つ手がない(p.153)
長期プロセスは結果整合性で良しとする。どこの時点でコケるか、を考えないといけないし、コケたとしてどこまでコミット、ロールバックするかも考えないといけなくて大変。
エンティティ
エンティティを値オブジェクトのコンテナにする(p.209)
エンティティは属性によって定義づけられるものではないのだから、エンティティに備わる属性は値オブジェクトとして切り出すことができる、という理解
public class Role extends Entity
(p.454)
ScrumProductOwner、ScrumTeamMemberをRoleとして管理するときに、Entityにするのがちょっとどうなのかなと思った
1:1のテーブルをORマッパーで扱いやすくするためにEntityにしてるのか、Roleは役割そのものではなく、Tenantに対するユーザーの役割で、
Userに対するRoleは必ず1つあって、tenantごとにどちらかを選択する。そのRoleは属性が変わったとしても同一性を保つからEntityなのか…
roleRepositoryからtenantIdとRoleNameで探してるから、テナントごとに違ったりする想定なのかも。
ロールインターフェース(p.196)
エンティティすべてをクライアントに公開するのではなく、使わせたいものだけインターフェースとして公開することで、フレームワークに必要なpublicメソッドを隠したりできる
標準型
モノ(Entity)あるいは説明(ValueObject)があった上でさらに標準型を利用してそれを他と区別する(p.223)
集約を標準型として用い、型ごとに集約のインスタンスを用意する(?)(p.227)
使うその標準型のオブジェクトを取ってくるときに、集約を分けておく?
GroupにUserあるいはGroupを割り当てるとき、それぞれの集約を作っておいてそれを使う
わかったようなわからないような…標準型は利用する側の境界づけられたコンテキスト内で管理するものではないので気をつける(p.227)、っていうのはなんとなくわかる。
渡された標準型を使って分岐するのではなく、使用側で取ってくる標準型を指定するとコンテキストが曖昧になって良くない、みたいな話という理解
値オブジェクト
値はモノではなく、概念である(p.210)
それはあくまで概念であり、ドメイン内にあるモノを計測したり定量化したり、あるいは何らかの形式で説明したりした結果にすぎない
エンティティがモノで、値オブジェクトがそれを説明する概念っていうことなのかな?だからエンティティが値オブジェクトのコンテナになる
値オブジェクトはエンティティへの参照を保持してよいが、エンティティの状態が変わるなら値の不変性に違反するのであくまで全体としての不変性や表現力、利便性のためだけにする
値オブジェクトを作るときは、オブジェクトではなく値を引数に取ったほうがいい(p.220)
値オブジェクトがオブジェクトを引数に取ると、オブジェクトの内部構造に対して依存が発生してしまう
パラメータ内でエンティティを変更しないという保証ができない
ORMで複数の値をDBのEntityに格納する場合の扱い(p.243)
複数の値オブジェクトをORマッパー経由でDBに格納するとき、一旦エンティティとして保存して代理主キーを隠す
これは交差テーブルをアプリケーション側から隠すときに使えそう
ファクトリ
Tenant#registerUserの中でnew Userしてる(p.199)
説明のためなんだろうけど、ちょっと違和感があった。
Userがどう作られるか、っていうのはライフサイクルで大事なところだと思うので、Userクラスに名前付きコンストラクタとかで置いておいたほうがいい気がするけど
集約のコンストラクタをクライアントから隠蔽するために、コンストラクタをprotectedとして宣言する
CalendarEntryを作るときにCalendarから作らせたいが、CalendarEntry自体のコンストラクタはクライアントに見せない。
リポジトリ
コレクション指向のリポジトリではSetをまねる (p.389)
addやremoveのみを使い、saveのような書き戻すメソッドを使わない
Setのように、同じインスタンスは何度addしても実際には1つ
一対一のマッピングを使った集約の削除の際には、注意すべき点がある
関連するオブジェクトに変更を連鎖させることはできないので、関連の両側にあるオブジェクトを、明示的に削除しなければいけない。(p.398)
一対一の関連の削除はDBの制約もあり、順番を考慮しなければならず、避けるべき理由の一つとなっている
アプリケーションサービスはドメインモデルのRepositoryインターフェースに依存する。しかし、インフラストラクチャから実際に利用するのはその実装クラスである。(p.514)
リポジトリの実装はインフラストラクチャに置く
バリデーション
ユーザーインターフェースにおけるバリデーションはドメインモデルにおけるバリデーションとは別
ユーザーインターフェスではあくまでも粗いレベルのバリデーションにとどめ、業務に関する深い知識はモデルの中だけで表現するようにしたい
エンティティ単体で完全に妥当な状態だったとしても、エンティティ全体として妥当であるとは限らない(p.207)
バリデーションに段階があることを意識できたほうがいい。
オブジェクト全体のバリデーションには遅延バリデーションが有効
バリデーションはドメインオブジェクト自身よりも変更頻度が高いので分離しておいたほうがいい。
(振る舞いを扱うという責務に、状態を維持するという責務も加わってしまうため)
DBのユニーク制約はどこに置くんだろう?ユニークであること自体はリポジトリに問い合わせてチェックして、実際のエラーが起きたときの処理もリポジトリかな?
ValidatorがValidationNotificationHandlerを受け取ってエラーを通知して返す(p.205)
これはValidatorから実際の通知のメッセージをどうするか、みたいなところを切り離せるので良さそう
モジュール
顧客向けのプロダクト名をモジュール名に使うことはなかった。
ブランド名は変わることがあるものだし、プロダクト名とその背後の境界づけられたコンテキストには直接の関係がないこともあるからだ(p.323)
当初のサービス名は変わったけどディレクトリとかに名前が使われていて混乱を生むケースたまに見かける
ドメインサービスを中粒度のサービスレイヤとみなし、それがモデルの上にかぶさっていると考えるならモジュールを分けるのもいいが、ドメインモデル貧血症を起こしがちになることに気をつける
私達が設計・実装するのは、ドメインではなく、ドメインのモデルである。
つまり結論としては、モデルを取りまとめるモジュール名としてはdomain.modelのほうが適している。(p.325)
境界づけられたコンテキストの前にモジュールを検討する(p.330)
境界づけられたコンテキストはモジュールの代わりに使うべきものではない。
モジュールは、凝集したドメインオブジェクトをモジュール化したり、凝集していないドメインオブジェクトを切り分けたりするときに使うものだ(p.330)
腐敗防止層
腐敗防止層での値オブジェクトの組み立てにはTranslatorを使うが、集約を組み立てるならリポジトリを使うほうが自然(p.452)
アプリケーション
モデルとクライアントが密結合してしまう問題の回避策として、メディエイターインターフェースを用意するという考え方もある(p.496)
集約にメディエイターを渡して、集約の内部でメディエイターに値をセットする
メディエイターのインターフェースをビューの使用と結び付けず、集約の状態をレンダリングすることだけに注力すること
ビューのレンダリングに必要な複数の集約のインスタンス全体を、単一のドメインペイロードオブジェクトにまとめる(p.497)
DPOは個別の属性ではなく、集約のインスタンスそのものへの参照を保持するようになっている
バラバラに渡すと大変だからコンテナにいれて渡すと楽だよね、ぐらいの意味か?
遅延読み込みの解決ができない(取ってきたときに読み込みを完了させて一貫性を担保できない)ので、早期読み込み方式に切り替えるか、ドメイン依存リゾルバを使う
ドメイン依存リゾルバは、ユースケースごとに必要なプロパティに対して直接指定してアクセスさせるもの
ユーザーが行った編集操作も、プレゼンテーションモデルで追跡する
プレゼンテーションモデルはアプリケーションサービスに対する最小限のファサードとして振る舞うことになる(p.502)
プレゼンテーションモデルはもともとモデルからビューへ、そしてビューからモデルへの両方向に対応するために作られたものだからである
多分デスクトップアプリケーションみたいなのを想定してて、Webアプリ的なものの話ではない