IThaiのブログ

IT関連の話題やタイに関する様々なことを書いていきます。

【前半】ドメイン駆動設計を読んで

ドメイン駆動設計書のデファクトスタンダードになっている「エリック・エバンスのドメイン駆動設計」を読みました。

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

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

とても分厚い本で途中息切れしましたので、

とりあえず、インプットのために、今のところ印象に残った言葉を記述しておきます。

概念が実装から切り離せない理由の一端には、実装上の問題を考慮せずには役に立つ概念モデルを構築することができない、ということである。

例えばユーザと要件定義者と設計者と実装者が違う人である場合など。特に設計と実装は同じでなければいけないということですかね。

ドメインモデルというものが、最初にモデル化され、その後で実装されるようなものではない、ということだ。真に強力なドメインモデルは時間と共に進化するということであり、偉大なベテランモデラであっても、最高のアイデアを得られるのはシステムが初期リリースされた後のことだ、ということである。

アジャイルな開発スタイルに通じるものがあると思います。

単語やフレーズを使っていろいろ試しながら、モデリング作業に言語能力を活用することがきわめて重要だ。これは、図を描くことによって視覚的、空間的な思考を駆使することがきわめて重要なのと変わらない。我々が自分たちの分析能力を用いる際に、方法論的な分析や設計と合わせて、コードの持つあの不思議な「感じ」を使うのと全く同じなのだ。このような思考方法は互いに補完し合うものなので、役に立つモデルと設計を見つけるにはそれらすべてが必要になる。

会議などで各人が同じ内容を自分の言葉で話すことやホワイトボードで図を書いて説明することが有効だと感じました。

本書の要点は、実装、設計、そしてチーム内のコミュニケーションの根底にあるモデルは1 つだけであるべきだ、ということである。

モデルは開発関連のすべてに共通するものだということらしい。

モデル駆動設計は、分析モデルと設計という二分法を捨て去り、両方の目的に使える単一のモデルを探し出す

コードの変更に対して責任を負う人はだれでも、コードを通してモデルを表現することを習得しなければならない。すべての開発者は、モデルに関する議論にいずれかの段階で参加して、ドメインエキスパートと話をしなければならない。その他の方法で寄与する人々は、ユビキタス言語を通じてモデルに対する考え方をダイナミックに交換する際に、コードに触れる人々を意識して巻き込まなければならない。

これはなかなか難しいけど、コードレビューを行うなどして、コードの変更はチーム内で認識しておくべき。

本質的な原則は、レイヤ内のどの要素も、同じレイヤの他の要素か、その「下にある」レイヤの要素にしか依存しない、ということである。

今となっては当たり前だけど、MVCフレームワークは自然とそうなるように出来ている。

ドメイン層をインフラストラクチャ層とユーザインタフェース層から分離することにより、各レイヤをはるかに明確に設計できるようになる。レイヤを隔離すると、保守にかかるコストが格段に低くなるが、それは、各レイヤが別々の速度で進化して、別々の要求に対応する傾向があるからである。このように分離することで、分散システムにも配置しやすくなる。別々のレイヤを、それぞれ別々のサーバやクライアントに柔軟に配置できるようにすることで、通信のオーバーヘッドを最小化して、性能を向上させることができる。

ただ、こうした分離が重要なのは、プロジェクトで頻繁にユーザインタフェースを出金依頼に置き換える必要があるからではなく、関心事を明確に分離することで、各レイヤの設計を理解し維持管理するのが容易になるからである。

UIは変わりやすい。またオブジェクト志向でよく言われる、関心の分離の考え方はとても重要だと思います。

モデルと実装は詳細のレベルで結びつけなければならない。この議論は、関連を設計して無駄をなくすという問題から始める。オブジェクト間の関連は、想像するのも描くのも簡単だが、実装するとなると泥沼になるかもしれない。オブジェクト自体に目を向けつつも、詳細なモデル上の選択と実装上の関心事との間にある関係性を絶えず精査することで、モデルを表現する3 パターンの要素の区別に専念することにしよう。その要素とは、エンティティ、値オブジェクト、サービスである。

例えば、一対多の関連は、インスタンス変数のコレクションとして実装されるかもしれない。しかし、そこまで直接的に設計する必要は、必ずしもない。コレクションは存在せず、アクセッサメソッドがデータベースに問い合わせて適切なレコードを見つけ、それに基づいてオブジェクトをインスタンス化するかもしれない。これらの設計はどちらも同じモデルを反映しているだろう。関連を辿る特定の仕組みを設計で定義し、モデル内にある関連とふるまいを一致させなければならない。

オブジェクト関連の実装についての具体的で分かりやすい説明。

オブジェクトの中には、主要な定義が属性によってなされないものもある。そういうオブジェクトは同一性のつながりを表現するのであり、その同一性は、時間が経っても、異なるかたちで表現されても変わらない。そういうオブジェクトは属性が異なっていても、他のオブジェクトと一致しなければならないことがある。また、あるオブジェクトは、同じ属性を持っていたとしても、他のオブジェクトと区別しなければならない。

ソフトウェアのエンティティで使われるIDで同一性を確保している。

モデルで最も目立つオブジェクトが、通常はエンティティであり、また、各エンティティの同一性を追跡することが非常に重要であることから、あらゆるドメインオブジェクトに同一性を割り当てようと考えるのは自然なことである。実際、フレームワークの中には、あらゆるオブジェクトに一意のID を割り当てるものもある。システムはそうした追跡すべてに対処しなければならず、行えたかもしれない性能の最適化の多くは不可能になる。

エンティティのすべてにIDを付ける設計は考え直すべきかもしれない。

あるオブジェクトが他の多くのオブジェクトから参照されている場合、参照している側のオブジェクトの中には、参照されているオブジェクトの近く(同一ページ上)になくて、データを得るのに追加の物理操作が必要となるものもある。同一インスタンスへの参照を共有するのではなく、コピーを生成することによって、多くのエンティティの一属性として機能する値オブジェクトを、それを使用する各エンティティと同じページに格納することができる

関係データベースでは、特定の値を独立したテーブルに入れて関連を生成するよりも、その値オブジェクトを所有するエンティティのテーブルに入れたいことがあるかもしれない。分散システムでは、値オブジェクトへの参照を別サーバに持つと、メッセージに対する応答が遅くなる

非正規化の説明です。ストーレージの容量や保守しやすさよりパフォーマンスを重要視した設計になります。

後半に続きます。