wiki@y-kurose

日々是好日。

ユーザ用ツール

サイト用ツール


本:読書会:エリック・エヴァンスのドメイン駆動設計

エリック・エヴァンスのドメイン駆動設計

目次

第0回

スケジュールと進行方法の設定

  • 1回/週、1.5~2h/回
  • 交代で音読:約50分
  • なにかあれば付箋にメモ:音読と並行
  • 説明しながら付箋を貼る:約10分
  • 注目度が高い点について自由に話す:約15分
  • 何かまとめる:約5分

第1章

第1章

  • 【ドメイン】と言うのはよく分からないが、この本の内容はどうも既になんとなく知っていることのよう
  • ただし、正しくと分かっているかも怪しく、知っているとできているかは違うのでこれからしっかり勉強する

ふりかえり

第1章

  • 次回は音読する人は立って情熱的に読む
  • 問題点:人が少ない
    • 楽しく何か得るものがある会にしたい
    • きちんと終わらせて、打ち上げ飲み会ができたら最高
  • ここまででちょうど1.5時間
    • 第一章は短いのでこの程度だが、ボリュームがある章では少々厳しいかもしれない
    • 適宜、進行方法をアップデートする

第1回

第1回

  • 前回のTryであがったお菓子をメンバーが持参

第2章

第2章 以下抜粋

  • 【モデル】≠図である(図はあくまでモデルを説明する手段の一つ、完全な図を目指すのはお門違い)
  • DSL(ドメイン固有言語)や暗黙知の共有に通じる話
  • 各々の頭の中にあるイメージをどのように共有して統一(整合)していくかという話?
  • やはり今まで暗黙のうちにやられていたことのようだ(ただし、理解してやるのは大事だと思う)
  • 共通見解として、この章の言いたいことは【同じ言葉で語ろう!!】という事
    • 同じ言葉を使うのは、ドメインエキスパートと開発者の間でもあるし、会話・設計書・図・コードの間でも

ふりかえり

第2章

  • 立っての輪読は継続
  • お菓子も好評
  • ペンが薄いので新しいものが欲しい
  • 誰の意見かわかるように付箋の色を変えたい
  • まとめが弱い
  • 一旦立ち止まる
    • 1章を4人で読むと量が多い
    • 途中キリの良いところで立ち止まって、理解度や疑問点について問題ないかを確認するタイミンが欲しい

第2回

第3章【モデルと実装を結びつける】

第3章

  • 【モデル】は分析の手段にも設計の手段にもなる
  • ただし、以下の場合うまく効果を発揮できない
    • それぞれで別のモデルを使ってる
    • 分析に偏りすぎて(実装がJavaの場合はオブジェクト指向に則るなどの)設計側の原則を無視している
    • 逆に実装に偏りすぎていていてドメインの必要な概念が欠落したモデル
  • 優れた【モデル】は一度では作成できない
    • 知識を噛み砕き、何度も洗煉させていく必要がある
    • そのためにもモデラとプログラマを分けるは得策ではない

ふりかえり

第3章

  • 自分が読んでる部分が頭に入らない
  • 1章を4人程度の人数一周で読みきってしまうのは、担当分が長く感じる
  • 次回はキリのいいところではなく、単純にページで区切ってやってみる

第3回

第2部【モデル駆動設計の構成要素】〜 第4章【ドメインを隔離する】のドメイン層はモデルが息づく場所(P73)

第3回

  • 第2部からは少し具体的な話
    • 「ドメインに関する部分を、他の関心ごとと分ける」
    • 具体的な手法として【レイヤー化アーキテクチャ】や【MVC】がある
  • レイヤー化アーキテクチャやMVC自体は既にに知っているので目新しさはない
    • ただし、それを綺麗に実践できてるプロジェクトにはなかなか会えない
  • レイヤー化アーキテクチャ・MVCも考え方はシンプル
    • モデル駆動設計を実施するためにはとりあえず【ドメイン層】が分離されていれば良い
    • そうすることで、表示や永続化やその他もろもろのことを気にすることなく、【モデルと実装との整合性を保つ】ことができる
    • 逆にそうでない場合は、コードを読んでもよくわからないし、テストは煩雑となかなかに辛いことになる

ふりかえり

第3回

  • 進め方については概ね好評
  • 前回までよりペースが落ちた
  • 早く進めることより、理解しながらやりたい
  • 今回の方式を継続する

第4回

第4章【ドメインを隔離する】「利口なUI アンチパターン」(P.74)〜 第5章【ソフトウェアで表現されたモデル】「エンティティ」(P.91)

第4回

利口なUI

  • 前回【ドメインを他のことと分ける】ということを学んだ
    • その例としてきたのが【レイヤー化アーキテクチャ】
    • 今回はその逆のパターンとして【利口なUI】とう選択肢について
  • 【利口なUI】とは次のような実装
    • ビジネスロジックをUIに入れる
    • アプリケーションは機能毎に独立したIFとして実装し、ビジネスルールもそこに入れる
    • 関係DBをデータ共有のリポジトリとして使う
  • 利点(言い訳)
    • 単純なアプリケーションの場合は簡単ですぐ作れる
    • 機能単位で分割しているのでリリースタイミングを調整しやすい
  • 問題点
    • 再利用も抽象化もされず、コピペのオンパレード
    • リファクタリングしづらい
    • 複雑になってくるとお手上げ
      • 一度「利口なUI」を選択すると、それをやめてモデル駆動設計を行うにはすべて作り直し
  • モデル駆動設計に取り組むには、最初からふさわしい やり方で設計をする必要がある
    • つまり残念なことに、実際の仕事では既に手遅れのプロジェクトも多数ある

エンティティ

  • モデル間の関係を減らすこと(疎結合にする)ことが大切
  • 【エンティティ】とは定義が属性によってではなく【同一性】によって行われるオブジェクト
    • 「ある人」は属性として「名前」、「年齢」、「身長」、「体重」 などを持っている
    • もし、これらが変わったとしても、別の人にはならない
    • この場合、何をもって「ある人」が同一か判断するかは少し難しいですが、ソフトウェアシステムでは一意の識別子を割り当てるなどして対応する
  • すべてのオブジェクトがエンティティになるわけではない
    • たとえ現実世界では同一のものでも、アプリケーションが対象としている問題によってエンティティになったりならなかったりする

ふりかえり

第4回

  • いったん付箋に書いて、それを貼りながら話をしていたが、(人数も少ないので)直接ホワイトボードに書き込みながらの方がいい
  • 付箋だと小さくて見づらい
  • 次は随時直接書き込みながら進めてみる

第5回

「エンティティをモデル化する」(P.91)〜「値オブジェクト」(P.102)

第5回

  • 前回の続き
    • 【エンティティ】の説明と、モデルの別の構成要素である【値オブジェクト】の説明
  • エンティティと値オブジェクトと比べることで違いはよく分かった
    • ただし、依然としてそれでどうなるのかというのはやや曖昧

エンティティと値オブジェクトの違い

  • 【エンティティ】が同一性(どれであるか?/誰であるか?)を重要視する
  • 【値オブジェクト】は何であるか?のみを重視する
    • 「何色のペンかは大事だが、どのペン(代えのものかどうか)は重要じゃない」など

値オブジェクトの不変という性質

  • 何であるかが重要な【値オブジェクト】にとっては、値が違うという事は別のものという事になる
  • つまり、値を変えるには、別のオブジェクトで置き換えるしかない
  • これ(値が変わらないことが保証されていること)によって、DBスキーマの非正規化を使った高速化をしてもデータの整合性を保証したり、デザインパターンのFlyweightパターンを安心して使えたりする

ふりかえり

第5回

第6回

「サービス」(P.103)〜「モジュール」

第6回

  • 【エンティティ】と【値オブジェクト】のどちらに属するのも不自然な処理がある場合は【サービス】として定義する
  • サービスは状態を持たず、それ以前の操作に影響されない
    • 状態を持つならその状態とともにエンティティか値オブジェクトになる
  • サービスにもレイヤーがある(インフラストラクチャ層や、アプリケーション層など)
  • 複数のエンティティや値オブジェクトの協調動作をまとめてサービスとすれば、適切なインターフェースになる
  • 高凝集・疎結合
  • 作っている途中で初期の分類が良くなかった事が分かることはよくある
    • リファクタリングするには影響範囲が大きく、初期の分類のまま放置されることが多い
    • モデル駆動設計では、モジュールをうまく使い全体の俯瞰や関係ある部分の詳細のみへの注目などをやりやすくする
    • モデルがあれば、会話時にもどの部分についての話かもわかりやすく便利
  • 理想はそうだが、どうしても要素を足していく際にぎこちなくなってしまうという
    • 特に既存部分に一切手を入れれない事情がある場合はそうならざるを得ない

ふりかえり

第6回

  • 内容ではなく進行方法について
  • 今の方法だとおおよそ10P/回程度のペース
    • 約500Pあるこの本だと1年かかってしまう
    • 計算し直すと、20回ほどで終わりを目指すには約30P/回のペースですすめる必要がありそう
  • まずは試しに1回の読書会を時間ではなくページで区切ることに
    • 2時間あればよめそう
    • 無理ならまた考え直し

第7回

「モデリングパラダイム」の続き(P.117)〜「リポジトリ」

第7回

  • オブジェクト世界における【オブジェクトでないもの】とはなにか?
  • 代表は関係データベース
  • ドメインモデルは(オブジェクトモデルでなくても良いため)【オブジェクトでないもの】を加えることができる
  • ただし、うまくやらないとすぐにモデル駆動設計が失われてしまう
  • うまく混ぜるには次のことを気をつける
    • ユビキタス言語に頼る(一貫する)
    • UMLにこだわらず、合ったものを使う
    • 懐疑的であること ※難しかった
  • 技術的な側面にとらわれると、モデルがダメになるので気をつける

第7回

  • オブジェクトには単にコンストラクタでメモリ上に生成されてからGC等で抹殺されるまでの期間を超えて(ライスサイクルが)存在する
  • そのライフサイクルを【集約】と【ファクトリ】と【リポジトリ】にて実現する
  • 大事なことは、オブジェクトに対する変更の一貫性を保つこと
  • 【集約】は文字通り、複数のオブジェクトをまとめている
    • 1つの【ルートエンティティ】が存在するとすると集約の定義は、その内外の境界線の定義と等しく、外からは【ルートエンティティ】経由でしか内部への操作ができない
  • 重要そうな特徴
    • 【ルートエンティティ】は普遍性をチェックする
    • 集約外のオブジェクトは(一時的な使用を除き)集約内のオブジェクトへの参照を保持することはできない
    • 集約内への変更は集約全体の不変条件すべてが満たされなければならない
  • 【ファクトリ】は以下のような理由でオブジェクトの生成を隠蔽する
    • 複雑な生成操作はオブジェクト本来の責務と無関係
    • 上記理由で利用側が組立を行うとカプセル化に違反している
    • 利用側に対して実装を隠蔽したい
  • ファクトリは隠蔽しているだけなので、ドメインモデル上で何の責務も負っていないがドメイン設計の一部
  • 定義する場所は以下(いずれの場合も不変条件を満たしたオブジェクトを生成するのが大切)
    • 集約のルートエンティティ(既存の集約に要素を追加する場合など)
    • オブジェクトの生成に関わるオブジェクト(生成に必要な情報を取得する)
    • 専用のオブジェクト(自然な置き場所がない場合)

ふりかえり

  • KPTではなく雑談ベースで実施
  • 今回から30P/回にしてみたが、図が多かったせいか、時間では1時間40分ほど
    • 無理の無さそうなペースではあるが、内容が難しくなると厳しいかも
  • 予習するべきか?
    • 手が回らないためしばらく今回の方法で続けてみる

第8回

「リポジトリ」(P.148)~「オブジェクトの生成」(P.176)

第8回

  • 集約について
    • 前回、集約の要素の生成時に不変条件を満たすために【ファクトリ】を学んだ
  • 【リポジトリ】は、ライフサイクル(newされてからGCで回収されるよりも長く、永続化などを通して、本当に不要なるまでは続く)に注目する
  • 一度DBに保存されたオブジェクトのは検索すればどこからでも取得可能
  • しかし、どこからでも取得してしまうとドメイン層が侵食されてしまいまう
  • それを回避するために、【リポジトリ】にDBアクセスなどをカプセル化してしまう
    • 利用側からは実態がメモリ上にあるのか、DB上にあるのか、もしかしたらファイルにあるか区別がつかないようになる
  • 【リポジトリ】は集約のルートエンティティに対してのみ提供する(境界線)
    • 追加、削除、取得のメソッドを提供し、その実装は隠蔽する(ドメインモデルに集中できるようにオブジェクト取得の技術要素は隠す)
    • 複雑なオブジェクトの生成を隠蔽するという意味ではファクトリと似ている
    • ただし、生成と再生成はやはり意味が違うので、リポジトリでDBから取り出し、オブジェクト構築はファクトリに移譲する事もできる
  • ドメイン層の隔離を考える
    • エンティティと値オブジェクトを区別する(区別必要なものか?交換可能か?などで判断)
    • 関連の設計する(不要な相互参照を消していき、必要なものを目立たせる)
    • 集約の境界を決める(誰から見ても一意なエンティティが集約のルートエンティティ候補)
    • リポジトリを選択する(各ルートエンティティに対して検索などが必要かで判断)
    • シナリオでチェック(違和感ないか)
    •  オブジェクトの生成について考える(モデルの不変条件を満たした状態でオブジェクトを生成できるように)

ふりかえり

  • スキップ

第9回

「リファクタリングのために立ち止まる」(P.177)〜「ブレイクスルー」(P.206)

第9回

  • ケーススタディの続き
  • 前回、循環参照によってオブジェクトの生成が大変だったが、今回はリポジトリを追加することで対応
  • リポジトリを介することで、生成が楽になる
  • 続いてモジュール分割について
    • 良くないのは各オブジェクトを【エンティティ】や【値オブジェクト】という種類で分類する
      • ドメイン(ここでは輸送)について無意味なため
    • 良いのは「顧客」や「輸送」、「請求」に分類
      • モジュール間の関係だけでもざっくりと意味がわかる
  • 最後に、これに対して機能を追加する
    • 「アナリシスパターン」と「エンタープライズセグメント」という知らない言葉が出てくる
    • 詳細は本書の後の方や「エンタープライズ アプリケーションアーキテクチャパターン」に説明がある

第9回

  • ローン管理アプリケーションを例にした設計のブレイクスルーの様子
  • ブレイクスルーはいきなり起こそうとしても無理で、ドメインへの理解を深める必要がある
  • ブレイクスルーが起こるとモデルがガラリと変わってしまうため、修正は大変になる
    • 実際の仕事では、影響範囲が大きくなかなかGOサインが出なさそう

ふりかえり

  • 今回は、技術的要素より読み物的な(ストーリ性のある)話で面白かった

第10回

「暗黙的な概念を明示的にする」(P.207)〜「仕様」の途中(P.236)

  • 深いモデリングとは重要な概念を明示的に表現
  • 重要な概念に気付けるよう、知識の噛み砕きとリファクタリングの繰り返しが必要
  • ドメインエキスパート(その分野の人)が使う言葉に注意
    • より簡単な表現、用語は?
    • 用語の使い方を訂正されてないか?
    • 特定のフレーズを使った時にドメインエキスパートの困惑が消えることがないか?
  • ぎこちなさを精査する
    • 手続きによって説明しにくい複雑な処理があるか?
    • 新しい要求が出てくるたびに複雑さが増しているようなところは?
  • 自明のことを漏らさないように文献を読む
  • 「制約」はあちこちのメソッド内に散在し暗黙的な概念になりやすい
  • 明示的にするには分離して名前をつける
  • 【仕様】とは満たすべき基準を示すオブジェクト
    • ビジネスルールなど(エンディティ、値オブジェクトの責務に合わない)
    • ドメインから切り離すことはできないので区別してドメイン内で扱う
    • 判定とともにルールとしてくくりだすことができコードもスッキリする

ふりかえり

  • 会話パート面白かった

第11回

「仕様」(P.237)〜「概念の輪郭」(P.267)

第11回

  • 【仕様】を用いたサンプル
    • 化学製品が詰まったドラム缶を収容可能なコンテナの条件を「コンテナ仕様」としてくくりだす
    • これにより、うまくコンテナとドラム缶を対応付ける方法を考える
    • 具体的なコードとクラス図があるのでイメージがつかみやすい

第11回

  • 第10章のしなやかな設計について
  • 今回は関係するパターンのうち以下のものについて
    • 意図の明白なインスタンス
      • 名前が超重要!
      • 名前から機能が分からず実装の中身を確認されるなんてカプセル化の意味がない
    • 副作用のない関数(副作用の影響範囲を調べようとして中身を見ると(以下同様))
    • 表明(事前条件、不変条件、事後条件がはっきりしてれば気にすることが少なくて済む)
    • 概念の輪郭(適度な粒度で凝集したまとまりに分割)

ふりかえり

  • 前回とは別メンバーですが、2人だけだと寂しいですし、読むのが大変

第12回

「概念の輪郭」(P.268)〜「攻める角度」(P.297)

第12回

  • 前回に引き続き「しなやかな設計」のためのテクニック
  • 独立したクラス(そのクラス単体を調べれば理解できるように、不要な依存関係0を目指して可能な限り徹底的に低結合に保つ)
  • 閉じた操作(操作が閉じていると安心して組み合わせることができる)
  • 宣言的設計(言語として強要できないため、モラルが必要)
  • まずは「副作用のある関数」と「副作用のない関数」にわけるのがテストもしやすいですし、手始めとしていい

ふりかえり

  • 残念ながら今回も2人でした。2人だと白板を書いている余裕もなく大変

第13回

「アナリシスパターンを適用する」(P.299)〜「なぜ、フライウェイトではないのか?」(P.328)

  • 深いモデルとしなやかな設計について学んだが、実践には多くの話し合いと試行錯誤が必要になる
  • その過去の経験が「アナリシスパターン」にまとめられている
  • ゼロからモデルを考えるよりは、ベースがある分、モデルの形成が早くできそう
  • アナリシスパターンの他にもデザインパターンをモデルに関係づける方法もある
  • デザインパターンは具体的なクラス図にまで落とされていて、技術的側面のほうが強いように思われるが、中にはモデルを豊かにするものもある
    • ストラテジーパターンとコンポジットパターンがはうまく使えば効果ある
    • 逆にドメインモデルに合わないのはフライウェイトパターン
  • 本質は話し合いと試行錯誤なので、カタログ(パターン)だけでどうにかしようとしてもダメ

ふりかえり

  • 今回で集合での読書会は終了
  • 各自必要に応じて読み直しや、残りの部分を読む


本/読書会/エリック・エヴァンスのドメイン駆動設計.txt · 最終更新: 2019/10/22 14:34 by y-kurose