53
ドメイン駆動設計の 捉え方 2015/07/18版

ドメイン駆動設計の捉え方 20150718

Embed Size (px)

Citation preview

ドメイン駆動設計の 捉え方

2015/07/18版

アジェンダ• 言葉の定義

• ドメイン駆動設計の原則

• 効果的なモデリングの要素

• 戦略的設計

• より深いドメインモデルへ向かうリファクタリング

• しなやかな設計

• ドメインの隔離方法

• まとめ

言葉の定義

ドメインとは?• ドメインとは、ソフトウェアを利用する人達の活動と関心ごと。

• ソフトウェアの利用は利用者の活動の一部なので、利用しないシーンも含めて活動の目的・背景を理解することがドメインを理解するということ。

モデルとは?• モデルとは、膨大な知識を整理したシンプルでわかりやすい図。

• 大量のinput情報に対して、本当に重要な情報だけを選別して、シンプルな表現でoutputすること。

ドメインモデルとは?• 対象領域において、プロジェクトメンバの頭の中で構築された概念の集まり。

• 用語と概念の関係性を表現。

ドメイン駆動設計の 原則

• ドメインに集中する。

• ドメインモデルを探求する。

• ユビキタス言語を語る。

ドメインに集中する• 一番複雑なのは、『ドメインそのもの(ユーザの活動やビジネス)』

• ドメインの複雑性を考慮して、設計すべき。

• 技術だけに注力して作られたソフトウェアはドメインエキスパートの考え方と結びつかない。

• 業務中心 > 技術中心

ドメインモデルを探求する• ドメインに対する深い理解と集中すべき主要な概念を反映したモデルを作成する。

• ドメインエキスパートと開発者の共同作業でドメインモデルを作り上げていく。

• ドメインモデルは時間と共に進化する。

ユビキタス言語を語る• ユビキタス言語により、ドメインエキスパートと開発者を結びつける。

• ドメインモデルを作成するための共同作業は、ドメインエキスパートと開発者で共通認識の言語を形成していくプロセス。

• ユビキタス言語はコードやタスク・機能の記述などでも利用

効果的な モデリングの要素

・実装を通して、モデルにフィードバックをかけることが重要

“ドメインモデルと実装を結びつける”

・モデリングとプログラミングでメンバを分離しない

・モデルの持つ意図を実装に引き継ぐ

・ドメインモデルがプロジェクトの中心で、 他のドキュメントなどはモデルから言葉を取り出す

“ドメインモデルに基づいて

言語を洗練させる”

・最終的には、プロジェクトで流れ続ける情報を 体系化するためのツールとしてモデルを位置付ける

・データモデルと違い、振る舞いと業務ルールも表現する

“知識豊富なドメインモデルを作成”

・ドメインエキスパートの頭にある膨大な情報から 役に立つ知識をモデル化する

・開発メンバーが全員参加で作成する

・分析と設計の両方で利用できるモデルを作成

・イテレーションごとに重要な概念を追加し、 不要な概念を削除する

“ドメインモデルを蒸留させる”

・表現すべきことをより簡単に言う方法を見つける

・会話の表現がわかりやすいか、ぎこちないかを検証する

“ドメインモデルの言葉をブレーンストーミングなどで実験する”

・メンバ全員で一緒にモデルをかみ砕くことにより、 メンバ間のやりとりを変化させていく

戦略的設計

• 境界づけられたコンテキスト

• 蒸留

• 大規模な構造

境界づけられたコンテキスト• 明示的に境界づけられたコンテキストを定義した上で、ドメインモデルを適用するのはコンテキスト内部に限定。

• コンテキスト同士の関係も定義することによって、モデルの質が低下するのを避ける。(コンテキストマップのこと)

蒸留• モデルで最も価値がある領域をコアドメインという。

• コアドメインを探す活動を蒸留という。

• コアドメインを見つけて、コアドメインをサポートする大量のモデルやコードから容易に区別する手段を提供すること

大規模な構造• システムをおおよその構造から議論/理解できるようにするための枠組み。

• 個別部分を最適に構造化するよりも、モデル全体としての扱いやすさを優先。

大規模な構造 ~責務のレイヤー~

• ドメインモデル内にある概念上の依存関係を調べて、自然な階層が認められたら、階層に抽象的な責務を割り当てを実施。

• 階層は、ドメインの基本的な現実や優先事項を伝える。

• 階層の責務を決める際は、技術的な意思決定というより、ビジネス上の意思決定で行う。

大規模な構造 ~責務のレイヤーの例~

依 存 関 係

DDD本より引用

蒸留×大規模な構造

依 存 関 係

DDD本より引用

戦略的設計のまとめ• 「大規模な構造」と「蒸留」によって、ドメイン内の複雑な関係を理解できるようになる一方で、全体像を見失わずにいられる。

• 「境界づけられたコンテキスト」によって、別々のシステムの作業を進めても、モデルを壊してしまったり、意図せず断片化してしまったりすることがなくなる。

より深いドメインモデルへ 向かうリファクタリング

リファクタリングのレベルマイクロリファクタリング

• コードを読みやすくするなど、技術視点で実施。

ドメインリファクタリング

• ドメインについての新たな洞察から実施。

リファクタリングのアプローチ• ドメインリファクタリングから開始。

• ドメインモデルのリファクタリングにおいて、ドメインモデルに対する不満の原因が何であれ、意図を明確かつ自然に伝達するようモデルを改良する方法を探し出す。

コミュニケーションのぎこちなさ• コミュニケーションのぎこちなさに敏感になることによって、リファクタリングの候補を探す。

• ドメインエキスパートと開発者の両方ともドメインモデルにない語彙を使用したら警告サイン。

• 警告サインを好機と捉えて、その語彙を取り込むことでドメインモデルとコードを改善する。

設計のぎこちなさ• 以下のような複雑な箇所は、ドメイン側の活動における目的や背景を改めて理解して、改善につなげる。

• 新しい要求が来るたびに複雑になっていく箇所

• 説明しにくい複雑な業務ロジックが存在する箇所

リファクタリングの最終目標• コードが何をしているかを理解できるようになることに加えて、コードで表現された背景を理解できるようになること。

• これにより、ドメインエキスパートとのコミュニケーションとコードが関連づき、より深いドメインモデルを探求できる。

大切なこと• ドメインモデルと実装は、絶えず前進するだけのプロセスではない。

• 初期のドメインモデルと実装では重要と思えなかった問題が、困ったことになるのを防ぐために、頻繁にリファクタリングを行い、ドメインモデルと実装を改善するプロセスが大事。

しなやかな設計

概要• 初期リリース以降も、プロジェクトの進行を加速させるためには、変更に強い設計が必要不可欠。

• しなやかな設計とは『変更に強い設計』と定義。

テクニックの分類抽象化

理解を容易にして、 詳細を隠蔽する

分割

適切な粒度を保ち かつ依存関係を排除する

意図の明白な インターフェース

副作用のない関数

表明

概念の輪郭

独立したクラス

閉じた操作

意図の明白なインターフェース• クラス名/メソッド名は手段ではなく、目的が把握できるユビキタス言語の名前を付与。

• ユビキタス言語にすることによって、チームメンバーがすぐに意味を推測できる。

• 呼び出し側はインターフェースの内部処理を理解不要。

副作用のない関数• 複雑なロジックは、副作用のない関数によって、安全に実行。

• 副作用とは、システムの状態に対して行われる、あらゆる変更を意味。

• 呼び出し側で、副作用があるのか/ないのかを安全に予測できることが重要。

• コマンドクエリ分離の考え方。

表明• システムの状態を変更するメソッドは、表明によって特徴づける。

• 表明の具体的な表現方法としては、自動化されたユニットテストで表現。

条件名 説明

事後条件• 事後条件が操作の副作用なので、メソッドを呼び出すことで保証される結果を記述

事前条件 • 事前条件とは事後条件が成り立つことを保証するために満たすべき条件

クラスの不変条件• あらゆる操作が終わったときのオブジェクトの状態を宣言。集約全体の整合性に関するルールを厳密に定義

概念の輪郭• ドメインオブジェクトは、意味のある単位をより直感的に使用したり、組み合わせたりできるような単位で分割。

• 最初から理想となる分割はできず、リファクタリングした結果によるもの。

✦ リファクタリングは技術視点ではなく、ドメイン視点で実施。

独立したクラス• 関連が多ければ多いほど、モデルは複雑になるので、オブジェクト間の関連は低結合になるように徹底的にやる。

閉じた操作• 引数の型と戻り値の型が同じ場合は、閉じた操作と呼ぶ。

• 閉じた操作にすることによって、引数と戻り値が同じ型になるので、余計な概念を呼び込む必要がなくなる。

• 操作の引数や戻り値に新たなクラスが登場すると、新たな依存関係ができてしまう。

ドメインの隔離方法

何と隔離する?• ドメインをシステムの他の機能から切り離すことが重要。

• 他の機能とは、画面やデータの永続化の機能のこと。

隔離手段 ~レイヤ化アーキテクチャ~

• ドメイン駆動設計では以下4層に分離。

レイヤー名 説明ユーザインターフェース層 • ユーザに情報を表示して、ユーザからの何らかのリクエストを解釈

アプリケーション層• ビジネスルールや知識は含まない • やるべき作業を調整するだけで、実際の処理はドメイン層に委譲 • ビジネス状況を反映する状態は保持しない

ドメイン層• ビジネスの概念やビジネスルールを表現 • ビジネス状況を反映する状態はドメイン層で制御され、実際の格納処理はインフラストラクチャに委譲

インフラストラクチャ層• ドメインオブジェクトの永続化処理を行う • アプリケーションのためのメッセージ送信

各レイヤの依存関係• ドメイン層はどの層にも依存させない。

ドメイン層

ユーザインターフェース層

アプリケーション層

インフラストラクチャ層

隔離する目的• 本質的なビジネスの知識を捉えることが可能。

• プロジェクトが進むごとに蒸留しやすい設計。

• ソフトウェアの技術(htmlやsqlなど)に関係する概念と混同しなくなるので、ドメインを見失うことを避ける。

まとめ

ドメイン駆動設計の成功• 深いモデルによって、明確なビジョンがもたらされ、そのビジョンが新しい洞察を生み出す。

• しなやかな設計によって継続的な変更が容易になる。

ドメイン駆動設計の成功• 対象となるドメインを理解し、その理解をソフトウェアにおいて、具現化することを重視。

• ドメインモデルの品質に満足できないのは、ドメインについて学び続けている証拠。

ドメインが存在する限り、

変化し続け 成長し続け

価値を届け続ける ソフトウェアを作り続けることが重要

おまけ

DDDを理解するために• DDD本には、ドメインモデルとコードを行ったり来たりして、深いドメインモデルを築き上げていく。

• 哲学書のDDD本をちょっとでも理解するためには、本の内容と実践を行ったり来たりして、理解を深めていくことが重要。

同じような考えで