エリック・エヴァンスのドメイン駆動設計を読んでいる ( 8 )
サービスと隔離されたドメイン層
銀行サービスの例
モジュール
これまた「モジュールとは」の定義がなかったが、(この本こんなのばっかり)きっと名前空間やパッケージ的な意味なのだろう。
モジュールにもユビキタス言語で用いる名前をつけること。
インフラストラクチャ 駆動 パッケージングの落とし穴
技術的なフレームワークが一番パッケージング(モジュール化)しやすいが、
落とし穴もある。
良いフレームワークは、
- レイヤ化アーキテクチャを強制
- インフラストラクチャとユーザーインターフェースコードを別のグループのパッケージに入れる
- ドメイン層も物理的に分離
ドメイン層をとにかく分離するため、パッケージングで隔離してしまおう。
さもなくば、ドメイン層をパッケージングできる余地を残すこと。
エリック・エヴァンスのドメイン駆動設計を読んでいる ( 7 )
値オブジェクトを設計する
- あるモデル属性がその属性しか対象にしないなら、それは値オブジェクトとするべき
- 一過性ものは確実に値オブジェクト
- 人は同一性があるが、その人の名前は無い。
なので、人はエンティティ。名前は値オブジェクト。
サービス
エンティティにも値オブジェクトにもあてはまらないもの。
アクション(ふるまい、手続き)など。
優れたサービスとは
DDDにおいて、重要なプロセスや変換処理がエンティティや値オブジェクトの自然な責務じゃない時、それはサービスとして独立される事。
サービスには状態を持たせないこと
エリック・エヴァンスのドメイン駆動設計を読んでいる ( 6 )
第4章 ドメインを隔離する
- ソフトウエアの中で、ドメインに関係した実装部分は一部
- その一部が、技術的な解決部分に埋もれてはいけない
- それを埋もれないように分離するアーキテクチャが「レイヤ化アーキテクチャ」
レイヤ化アーキテクチャ
情報の表示、入力の受付/解釈
MVCでいうV。
・アプリケーション
ビジネスルールなどを含まず、ほかのレイヤ(ユーザーインターフェースとドメインなど)の仲介をする。
MVCでいうC。
・ドメイン
言わずもがな、ドメイン層。
MVCでいうM(だが、MVCはドメインとインフラストラクチャが分離されてないので、厳格ではない)
・インフラストラクチャ
例えば、DB/S3/メールなど。技術的な解決部分。
MVCでいうM(だが、MVCはドメインとインフラストラクチャが分離されてないので、厳格ではない)
レイヤは下位層にのみ依存するようにすること。
レイヤを関連づける
とはいえ、実際には下のレイヤー(例:インフラストラクチャからドメイン)につなげたいという要求は普通にある。
- 疎結合であるべきだが、やるならコールバックやオブザーバーパターンが使われる
- また、ドメイン層だけ隔離できれば、アプローチは他のものでも良い
- ただ、他のレイヤの機能を直接的に支援する仕組みのあるフレームワークもある。全てのドメインオブジェクトに抽象基底クラスを用意するなど。
ActiveRecordの事だね…
→これらは、ドメインモデルの設計に大きく影響する
アーキテクチャフレームワーク
実装に使うフレームワーク選択は重要
- 良いフレームワークは、技術的問題をこっそり解決してくれてモデリングに専念できる
- フレームワークのせいでドメインの分離やモデリングにつらい所があれば、フレームワークの全機能をあえて使わないという選択しもある
ドメイン層はモデルが息づく場所
ドメイン層は、モデルとそれに関わる設計の全てが現れる場所。
ソフトウエアで表現されたモデル
値オブジェクト、エンティティ、サービスのどこに寄せるかは極めて難しい。
そもそも値オブジェクト、エンティティの詳しい用語説明この本のここまでに無かったよね…。
突然説明も無しに登場してきた感があるが、ググった結果こちらに説明があった。
- エンティティ
一意なものを表す。一意な識別子を持っている。
長期にわたって変更(ライフサイクル)を管理する必要があるもの。
別々の実装をまたいで追跡されるようなもの。
社員。識別子は社員番号
記事。識別子は年度と記事連番
商品。識別子はJANコード - 値オブジェクト
変更(ライフサイクル)を管理する必要がないもの。
色、誕生日、電話番号、指名など。
対象の存在そのものでなく、対象のパラメータ的なものという事かな?
また、これらに含めずに「アクション」 「操作」として持つ方が良いものもある。
なんかふんわりした話ばっかりでわかりづらい…。後の章で細かい説明あるっぽいしここまで。
関連
関連もちゃんと管理しようねという話。
- 関連を精査して、本質的じゃないものを減らす
- 関連の方向を強制する
関連の方向性を強制する事が重要。
両方の関連があると、その2つが存在していないと意味がないものを感じてしまう。
エリック・エヴァンスのドメイン駆動設計を読んでいる ( 5 )
モデルと実装を紐づける
設計と実装でモデルをわけない事
- 分析だけの「分析モデル」であってはいけない
- フィードバックを受け、実装も分析も更新されること
- 設計 or 設計の中心となる部分がドメインモデルに紐づいてないならそのモデルに価値はほとんどない。ソフトウエアが正確かどうかも疑わしい
- モデルと設計された機能の紐付けが複雑だと、設計の変更がすぐにフィードバックされなくなる
モデルと設計(つまりコード)、現実的に同期できるものなのか?
「実装を一部の狂いもなくモデルに紐づけるには、通常、オブジェクト志向プログラミングのようなモデリングパラダイムをサポートする、ソフトウエア開発のためのツールと言語が必要」
モデリングと相性の良いプログラミング言語、ツールを選ぶべき。
- Cなどの手続き型はやはり相性よくない
- オブジェクト指向言語は相性良い
Golangは…?
- モデルと実装での食い違いを、内部にも外部(ユーザー)にも見せないこと。作らないこと。破綻する
かの高尚なInternetExplolerがURLのお気に入りをブクマシステムと混ぜてしまっているため、文字によって切り取られたり微妙
- モデルを作る技術的な人は、一定時間コードにも費やさないといけない(つまり、設計者と実装者は同じ)
エリック・エヴァンスのドメイン駆動設計を読んでいる ( 4 )
ドキュメントはコードや会話での表現を補わなければならない
プログラムは信じられるが、ドキュメントなんて限りなく信用ならんという話。
- ドキュメントどころか、プログラム内のコメントさえも同期されなくなることはよくある
- プログラムならあいまいな所は無いし
- 逆に、口頭でのやりとりやホワイトボードでのやりとりのほうが後に残らなくて無害
- コミュニケーションの媒体としてコードに頼ろうとすれば、クリーンで透過的にしようという気になれるし
ただし、プログラムだけで仕様を伝えるのは限界がある
- その場合のドキュメントは、「コードを補足するもの」にする
- 実際の仕様をもろもろ書き出すわけじゃない
どんなドキュメントが良いか
- チームの活動に同期してないなら有害
- コードや会話と用語が一致していること
- 最小限で、コードと会話の補足に止めること
実行可能な基盤
正しいことをするだけでなく、正しいことを言うコードを書くこと
説明のためのモデル
- チーム内のモデルは1つであるべき
次は「モデルと実装を紐づける」
エリック・エヴァンスのドメイン駆動設計を読んでいる ( 3 )
コミュニケーションと言語の使い方
ユビキタス言語、声に出してモデリングする、1つのチームに1つの言語
ユビキタス言語、モデルの作成/更新はとにかく開発者とドメインエキスパートでずれないようにという話。
- モデルにもとづいた会話のためのツールは、特になんでも良い
会話でも。ただ、コミュニケーションのあらゆる媒体に仕込む - ドメインエキスパート、開発者の間がそれぞれ「あいつら業務/技術の事よくわかってないだろう」という感じで細かいことを言わないと、亀裂が入りモデルが出来上がらない
- 最悪なのは、同じ言葉でドメインエキスパートと開発者の間で意味が違うのを認識しつつ許しちゃう事
> アプリケーションの限られたスコープや開発者の理解をはるかに超えた専門用語は、ほぼ間違いなくユーザにもあるだろう。しかし、そうした専門用語は言語が拡張されたものでしかない。こうした方言は、同じドメインに関して、異なるモデルを反映した別の語彙を含んでいてはならないのだ
この文の意味がわからなかった。つまり、技術的な用語は含んではならないって事か?開発者とドメインエキスパートの間で分かり合える用語に落とし込む?のか - モデルとコードは共同体。モデルが変わったらコードも変わらないとおかしい
- ドメインエキスパートがモデルを意識できないなら、モデルがおかしいと考える
- ドキュメントは最小限に。実体と離れがち
ドキュメントと図
UML図に頼りすぎないこと。情報が多すぎ/少なすぎて、議論の場で一時的に使うことは良いにしてもモデリングをこれだけで進めるべきてはない。
- 設計 = 結局はコード
- 適切に書かれたJavaは(Java推しか)、豊かな表現力がある
- 一度永続化したドキュメントは、進捗との繋がりを失ってしまう
わかる…。つまり、可能な限りはドキュメント化すべきものをコードに落とし込むべきだと思う。
これに対するアプローチは次の章で・・・
エリック・エヴァンスのドメイン駆動設計を読んでいる ( 2 )
ドメインモデルを機能させる
前置き
業務知識をそのまま落とし込むことでなく、アプリケーションを育てていく上での良い形に落とし込んでいく事が重要そう
- ドメインエキスパート(対象業務の有識者)の頭の中にある知識でなくて、
厳密に構成されて抽象化されたもの - 現実をそのまま写すことではない
- ドメインエキスパートと、会話ができて開発者と同じモデルを見て話せる状態
- 選択したモデルが、言語の基盤(開発する上でコミュニケーションがとれる形に)
- モデルを通じて、どう業務を理解したか、どう選択/分解したかが分かること
ソフトウエアの核心
ドメインに関係した問題をユーザーのために解決する事。
- たいていの開発者は、ドメインに関係した問題を最重要視しない
- 技術的な解決を、専門分野、スキルを重視してしまう(わかる…)
- ドメインに関係した知識は、自分の能力を伸ばすものに見えない
- しかし、それを技術で解決しようとして的外れな解決をしてしまう
- でも実際には「複雑性」を解決するスキル価値のあるもの
知識を噛み砕く
ドメインエキスパート共同作業でモデルを作り上げる
- モデルは実装と紐づくこと(紐づかないならどちらかを直す)
- ドメインエキスパートは、開発者と(スケッチなどツールを使ったりも含める)
- 無駄なものは削ぎ落とす
無駄なものってなんだろう?現状のアプリケーションには必要ないってこと? - ウオーターフォールではうまく行かない
開発者からのフィードバックによるリファクタがなく、一方通行 - 目指せ好循環
継続的学習
知識はメンバーの中に育つ。意識的に育てる必要がある。
知識豊富な設計
モデルとなるものは、「名詞」そのものに止まらない
- ルールも活動もモデル
- エンティディや値を超えてその先にいこうとする事が大事
これ、クラス設計においても例えば「Post(投稿)」ってモデルがあって、その投稿ルールをモデルにそのまま実装するのでなく「PostPolicy」クラスに分けるとべき - これにより、開発者とさらにそれ以外の人にもコードを見せることで理解が得られやすい