2010/03/0324(DomainDrivenDesign勉強会資料)
id:masakanou

「ドメイン駆動」でDOMAINDRIVENDESIGN
をさらに深く
                                        1
アジェンダ

・書籍「ドメイン駆動」の紹介
 -どんな内容?
 -だれが読むべき?
・各章の紹介




                 2
本のテーマ

・「ドメインをクリーンに作りつつ、永続記
 憶とも仲良くする方法」

・ドメインモデルと
 データベースの間に
 橋をかける



                       3
ERIC EVANS SAYS:

・DDDの進め方を学ぶ最良の方法は、フレンド
 リーで忍耐強く経験を積んだ実践者の隣に座
 り、ステップバイステップで一緒に問題を解
 いていくことである




                     4
現実

・忍耐強く経験を積んだ実践者がいない
・忍耐強く経験を積んだ実践者はいるが、フ
 レンドリーじゃない
・忍耐強く経験を積んだ実践者とステップバ
 イステップで取り組む機会がない
・解くべき問題がわからない



                       5
DOMAINDRIVENDESIGNって無理かも…




                            6
ERIC EVANS SAYS:

・「ドメイン駆動」を読むということは、
最良の方法を実践することである。




                      7
つまり

・「ドメイン駆動」を読むということは、
 フレンドリーで忍耐強く経験を積んだ実践者
 の隣に座り、ステップバイステップで一緒に
 問題を解いていくことである
・これは、ドメイン駆動設計を学ぶ最良の方
 法である




                    8
さらに

・おれらはDomainDrivenDesign勉強会をやっ
 てる!
・わかんないことは聞ける絶好のチャンス!




                                9
ちょっと読みたくなってきませんか?




                    10
11
前提知識

・オブジェクト指向
 ソフトウェアアーキテクチャの原則




                    12
前提知識

・デザインパターン
 -リファレンスとして使います




                  13
前提知識

・リファクタリング
 -これもリファレンス




              14
今読んでる

・デザインパターンの
 適用法




             15
あとで読む

・オブジェクトの責務・ロールとか




                   16
ERIC EVANS SAYS:

・効果的な設計は、機械的な機械的に学んだ
 テクニックの束ではない
・思考方法だ




                       17
DOMAINDRIVENDESIGNを勉強会をやって

・DomainDrivenDesignでドメインをクリーン
 につくるための思考方法は理解できたかも
・だけど、実際のコードのイメージが
 湧かない
・理論はわかってきた。応用する具体的な方
 法が知りたい
 →そんなあなたに
 本「ドメイン駆動」が使えるかも

                                18
本の目次
   序章 橋渡し
   第一部 背景

    第1章 尊重すべき価値
   第2章 パターン入門              DDDの前提となる思考方法と道具
   第3章 TDDとリファクタリング

    第二部   DDDの応用
    第4章   新しいデフォルトアーキテクチャ
   第5章   DDDの手法で前進する          サンプルアプリケーションを
   第6章   インフラのための準備           テスト駆動で深堀り
   第7章   ルールを機能させる

    第三部 PoEAAの応用
   第8章 永続記憶のためのインフラ
                              POEAAとの連携
   第9章 NHibernateを導入する

    第四部 次は何か
   第10章 これからの設計テクニック
   第11章 UIにフォーカス             おまけ(筆者の友人が書いたもの)
   第五部 付録
   付録A 他のドメインモデルスタイル
   付録B 論じたパターンのカタログ                           19
第1章 尊重すべき価値
・モデル重視の設計
・ドメインモデルパターン(POEAA)
・開発プロセス
 -初日から本当に優れた詳細仕様を書ける
 知識など得られるはずがない
・ドメイン知識は
 プロジェクトとともに発展する
・システムを作ることは、効率よくアイデア
 を得るための方法
                       20
第1章 尊重すべき価値

・テスト駆動設計(TDD)
 -設計のためにテストを書く
・リファクタリング
 -モデルの「不吉なにおい」を改良する




                      21
第2章 パターン入門

・パターンを使うのは、最初の設計時にでは
 なくて、リファクタリングの目標や方向と
 して




                       22
第2章 パターン入門

・「エンタープライズアプリケーションアー
 キテクチャパターン」は、ドメインモデル自
 体をどのように組み立てるかということより
 も、
 ドメインモデルをサポート
 する
 インフラに関係している



                    23
第2章 パターン入門

・ドメインパターンで重視されるのは
 -ドメインモデル自体の構成方法
 -ドメイン知識をモデル内にカプセル化する
 方法
 -ユビキタス言語を適用する方法
 -インフラによって重要な部分が影響を受け
 ないようにする方法



                    24
第3章 TDDとリファクタリング

・TDDによってドメインモデルをつくっていく
 -最初から大きなクラス設計をしない
 -いちどにひとつづつ
・リファクタリングの結果としてパターンが
 出てくる




                     25
第4章 新しいデフォルトアーキテクチャ

・新しいデフォルトアーキテクチャ
 …DomainModelを基礎としたもの

・データベース中心の設計から
 ドメインモデル中心の設計に変わったのは、
 (効率性より)メンテナンスを重視する
 ようになったから
・長期的にみてメンテナンス性に優れている
 -テストのしやすさも増す

                        26
第4章 新しいデフォルトアーキテクチャ

・「最初のスケッチ」で9個の問題
 /機能リストが提示される。
・この問題/機能リストを最終章まで
 TDD/DomainDrivenDesignで解決していくのが
 この本の目的




                               27
第4章 新しいデフォルトアーキテクチャ
・複雑で柔軟性に富むフィルタ…QueryObjectが一つの解決策
 -QueryObjectを使っていることはカプセル化しておくとよい

・Repositoryを使ってカプセル化。クライアントはAPIを使いやす
 くなる
・双方向性はコストがかかる
 -Repository経由でたどり着くことにより、片方向の関連になる
・並行処理単位をつくるにはAggregateを使う。
 -パフォーマンス問題は、例えばLazyLoadを使って解決する
・最初からSPECIFICATIONに飛びつかなくてもよいのでは




                                     28
第4章 新しいデフォルトアーキテクチャ

・ドメインモデルにUIを結びつける最初の試み
・目標:
 -UIプログラマのために単純なAPIが提供でき
 ているか
 -UIプログラマはモデルを簡単に理解できてUI
 に集中できるか
 -ドメインモデルとの間に複雑なプロトコルが
 あって気になるようなことはないか
 -UIプログラマが楽になるための工夫
  -NULLオブジェクトとか


                       29
第5章 DDDの手法で前進する

・テスト駆動でドメインモデルができていき
 ます。
・ここはぜひ実際にみなさんで体験してみて
 ほしいところ
・なので詳細は割愛します。
 (口頭で説明するより、実際に体験するのが
 早道)


                    30
第5章 DDDの手法で前進する

・いきなりインタフェースを切る必要がある
 か?その実装の交換を望んでいるのか?
・永続記憶とビジネスルールの密結合には
 強い警戒感を持つべし
・ドメインモデルが実装すべき動作や仕様を
 発見し、明確にする手段としてのテスト
・Repositoryを使うことにより、データベー
 ス操作の検討をあとまわしにできる

                            31
第6章 インフラのための準備

・目指すところ

-実際のデータベースを操作せずに、セーブ
 シナリオのためのテストを書けるようにする

-目指すところは、インフラに左右されない
 コードを書くこと


                       32
第6章 インフラのための準備
・ライフスタイルとしてのPOCO
・POCO…Plain Old CLR Object (POJOの.NET版)
・FowlerはPI(Persistence Ignorance)という
 表現を使用
・PIかどうかを見分けるには、
 「ドメインモデルにインフラ関連の外部DLLに関する参照が含ま
 れているかどうか」を確認するのがはやい
     (例)O/RマッパーとしてNHibernateを使用している場合、
      nhibernate.dllに対する参照がドメインモデルのコードに含まれて
      いたら、不吉なにおい

参考: Visual Studio 2010 EF4 POCO Part1
http://blogs.msdn.com/daisukei/archive/2009/06/02/visual-studio-2010-ef4-poco-part1.aspx
Entity Framework POCO Template for .NET 3.5 : Don't Be Iffy
http://thedatafarm.com/blog/data-access/entity-framework-poco-template-for-net-3-5/




                                                                                           33
第6章 インフラのための準備
・PIのメリット…TDDにとって好都合である。Entityや
 ValueObjectが明確でクリーンになる
・RepositoryにとってのPI…Repositoryはインフラを
 動かさなければならない。
・永続記憶抽象化レイア(NWorkspace)の導入
    ドメインモデルにRepositoryを置いて、インフラを参照
     する
    参照するのは、永続化フレームワークではなく
     NWorkspace DLL
    同じRepositoryがO/Rマッパーとフェイクの両方を対象
     に動作する
    フェイクはインスタンスを永続化せず、メモリ内ハッ
     シュテーブルにインスタンスを格納。初期のリファクタ
     リングに便利
                                   34
第6章 インフラのための準備
・以下のようなものは不吉なにおい

1.特定の基底クラス(object以外)の継承:
  ドメインモデル開発後、永続記憶に対応しようとしたときに、継承が要求されてドメイン
  モデルを変更しなければならないリスク
2.与えられたファクトリだけでインスタンス生成:
   ファクトリの強制は、ダーティーチェックで便宜を受けるためであることが多い
3.コレクションのために特別な(自由に選択できるなら使っていなかった)データ型を使用:
   レイジーロードをサポートするために使うことがある
4.特別なインターフェースを実装:
   永続可能とするためにインフラ提供のインターフェースを(ひとつまたは複数)実装す
  る
5.特別なコンストラクタを提供:
   データベースの値でインスタンスを再構成できるようにするために
6.特別な必須フィールドを提供:
      インフラがGuidベースのIdフィールドや、intのVersionを要求
7.特定の言語要素を避ける:
      readonlyフィールドを避ける


                                          35
第6章 インフラのための準備
・フェイクメカニズムの構築
・フェイクメカニズム…2つのレイヤを持つIDマップを使う。
 -第1レイヤ…現在のシナリオで読み出したすべての
 Entityを管理する
 -第2レイヤ…永続化エンジンをシミュレート
 -GetById()を呼び出したとき、要求された型のIDマップ
 にIDが見つかったらそのまま返す。みつからなければ第2
 レイヤにフェッチ。返ってきたオブジェクトを第1レイヤ
 にコピーして呼び出し元にオブジェクトを返す。
・すべてのテストがフェイクと本物のインフラの両方で実
 行できるのは、早い段階でテストが書けるのでよい目標
・フェイクでテストできることにより、リファクタリング
 に積極的になれる

                              36
第6章 インフラのための準備
・セーブのシナリオの処理
・論理的なUnitOfWorkを作って、その特徴を
 セーブに活かしたい
・RepositoryがUnitOfWorkとやり取りするの
 を筆者は好む
・集約(Aggregate)はPersistAll()呼び出し時
 に一貫性の取れた状態になるように設計する
 べき
・物理トランザクションとUnitOfWorkは同じ
 でありたい
                               37
第7章 ルールを機能させる
・大多数の要件はルールに関連する。ルールはドメインモ
 デルが本当に輝く領域。
・(今回のサンプルの前提)エラーがあってもすべての状態
 をセーブできるように
・ルールについては状態遷移を考慮に入れなければならな
 い
 →コンテキストが大切。注文業務なら「Ordered」に遷移
 する時にチェックすればよい
 (一時保存ならば、業務ルールに違反していても許容と
 いう判断もできる)
・コンシューマはAggregateRootに永続化できるかどうか尋
 ねる。子の状態はrootがチェックする
 →集約全体の違反ListはAggregeteRootに問い合わせれば
 良いようにする
                                  38
第7章 ルールを機能させる

・文字列の文字数が永続記憶の文字数に合わ
 ないかチェックするような場合
 →文字列用のオブジェクトが長さの上限を
 知っているというアプローチがある
 (Fowler:FixedLengthString)
                    VB6にもあるよ!


・仕様(Specification)にルールをカプセル
 化すると、単体テストをしやすい


                                39
第8章 永続記憶のためのインフラ
・DataMapperパターンを使用したO/Rマッピン
 グ
・UnitofWorkにより、仕事の論理的な単位の
 間にドメインモデルに加えられた変更につい
 ての情報をつかむ
・IdMapを使用してセッション内の個々の
 Entityのインスタンスが複数にならないよう
 にする
・LazyLoadにより必要になるまでサブクラス
 をロードしない
                          40
第8章 永続記憶のためのインフラ

・Metadata Mappingによるドメインモデルと
 データべーススキーマの関係の記述
・IDFieldによる主キーの保持
・ForeignKeyMappingでドメインモデル内の関
 係と外部キー参照を対応付ける
・継承の処理
 -SingleTableInheritance
 -ClassTableInheritance
 -ConcreteTableInheritance
                            41
第8章 永続記憶のためのインフラ




・詳細は、POEAAを合わせて読んでね…




                       42
最後に、メッセージ
・DomainDrivenDesignの副読本として有用
・実装イメージがわかない人は、特に
・さらに読まなきゃいけない本が広がる
 (後半はPOEAA参照しまくり)
・TDDでドメインを作り上げていくところ
 (5章)を写経するとよい
   (わたしも実施の予定…)
・C#かJavaかの違いは、たいしたことない。Java
 がいいならJavaで書けばいいのでは
 (どうせPOCOだし)
                           43

20100324 勉強会資料(ドメイン駆動)