ソフトウエアの核心にある
複雑さに立ち向かう
ギルドワークス 増田 亨
2019.5.11
レガシーをぶっつぶせ! 現場でDDD #genbadeDDD
2019/5/11 2
これから話すこと
2019/5/11 3
ドメイン駆動設計でなぜつくるのか?
「核心にある複雑さ」とは何か?
その複雑さに、どう立ち向かうか?
ドメイン駆動設計でなぜつくるのか?
42019/5/11
対照的な3つのプロジェクト
➢ 素早く最初の一歩を踏み出したソフトウエア
→ 成功! Ver.2 の開発に着手
→ 開発の泥沼化と挫折、 Ver.1 のレガシー化
➢ ドメインロジックの設計と改良を重視したプロジェクト
→ 成功! 開発を継続
→ 追加されるさまざまな要求に、柔軟性と拡張能力で応えることができた
➢ ドメインモデルに基づくエンタープライズシステムの開発
→ リッチなモデル、モデルから切り離された実装
→ 開発の泥沼化、数年かけて、なんとか動かすことはできた… レガシー化
2019/5/11 5
「まえがき」から
ドメイン駆動設計でつくる理由
2019/5/11 6
進化と成長を続けるソフトウェアを手に入れる
ソフトウェアの変更を楽で安全にする
No More Legacy !
レガシーはもうたくさんだ!
72019/5/11
ソフトウェアの変更容易性
82019/5/11
すべてにプラスに作用する
2019/5/11 9
変更が楽で安全
ビジネスの要求
開発スピード
開発コスト 運用コスト
性能改善
セキュリティ向上
使いやすさ
すべてにマイナスに作用する
2019/5/11 10
変更がやっかいで危険
ビジネスの要求
開発スピード
開発コスト 運用コスト
性能改善
セキュリティ向上
使いやすさ
ドメイン駆動設計
ソフトウェアの変更を楽で安全にする設計技法
112019/5/11
ソフトウェアの核心にある複雑さとは何か?
122019/5/11
いろいろな複雑さ
2019/5/11 13
ネットワーク
データベース
画面
レンダリング
クラウド/
コンテナ
フレームワーク 言語・
ライブラリ
ユーザの活動
ビジネス
ドメインロジック
ドメイン駆動設計のアプローチ
142019/5/11
ソフトウェアの核心にある複雑さ
ドメイン
ユーザの活動
ビジネスそのもの
ここが複雑さの源泉
ドメインロジック
ドメインの複雑さのソフトウェア表現
コード全体の一部
ここが核心
2019/5/11 15
複雑さ(ドメインロジック)をどこに書くか?
アプリケーション層
ビジネスルールを含まない
ドメイン層のオブジェクトを使って問題
を解決する
ドメイン層
ドメインロジックを記述する場所
ビジネスの概念を表現
ビジネスの状況を表す情報
ビジネスルールに基づく、計算や判
定のロジック
2019/5/11 16
ドメインロジックとは何か?
172019/5/11
ドメインロジック → ビジネスルール
182019/5/11
もっと限定的にとらえる
ドメインロジックを限定的にとらえる
ビジネスの概念 ビジネスルールを表現する語彙
ビジネスの状況
ビジネスルールの実行の元になる事実
(のデータ表現)
ビジネスルール 事実データを使った計算や判定のロジック
2019/5/11 19
ソフトウエアが複雑になる理由
ビジネスルール
金額、数量、期日、場所などの計算と判定
ビジネスルールを適用する条件による分岐
顧客区分、商品種別、有効期間、地域区分、金額区分、数量区分、
取引種類、取引状態、支払い方法、支払いタイミング、
割り増し条件、割引条件、キャンセル可能条件、…
2019/5/11 20
ソフトウェアの核心にある複雑さに立ち向かう
ビジネスルールの複雑さに立ち向かう
212019/5/11
ビジネスルールの複雑さに立ち向かう
2019/5/11 22
関心の分離の工夫
モジュール構造の工夫
ドメイン駆動設計のアプローチ
232019/5/11
2019/5/11 24
ドメインロジック 複雑さの根源
ドメインモデル 複雑さをモデルで整理
オブジェクト指向 モデルと実装の一致
ビジネスルールを中心に考える
252019/5/11
2019/5/11 26
ドメインロジック → ビジネスルール
ドメインモデル → 計算モデル
オブジェクト指向 → 型指向のプログラミング
2019/5/11 27
ユビキタス言語 →
ビジネスルールを
説明する語彙集
ドメインエキスパート →
ビジネスルールを
具体的に知っている人
複雑さと戦う準備
282019/5/11
ビジネスルールの記述を隔離する
2019/5/11 29
ビジネスルールの記述を隔離する
プレゼンテーション層の
モジュール群
アプリケーション層の
モジュール群
データソース層の
モジュール群
ビジネスルールを
記述したモジュール群
利用する
2019/5/11 30
ビジネスルールを記述するモジュール群に
複雑さが集中する
複雑なビジネスルールを整理し
わかりやすく記述するための考え方とやり方
2019/5/11 31
従来のモジュール構造とビジネスルール
トランザクションスクリプト
機能(データ処理手続き)に分割したモジュール群
ビジネスルールの記述、特に条件判定が、
あちこちのモジュールに断片化し、かつ重複する
変更がやっかいで危険
2019/5/11 32
ドメインモデル → 計算モデル
332019/5/11
ビジネスルールに基づく、計算や判定のモデル
もっと限定的にとらえる
入出力の関心と計算を分離する
2019/5/11 34
データの入力 結果の出力
データを使った
計算や判定
計算を入出力から隔離する
2019/5/11 35
データの入力 結果の出力
計算や判定の
ロジック
入力層から受け取ったデータから
オブジェクト/アグリゲートを生成する
(復元する)
結果を表現するオブジェクトを
出力層に渡す
ドメイン層のオブジェクト
計算に特化したアグリゲート
画面
JSON
データベース
画面
JSON
データベース
計算モデルと実装を一致させる
362019/5/11
オブジェクト指向 → 型指向のプログラミング
372019/5/11
もっと限定的にとらえる
「型」とは何か?
382019/5/11
型
ビジネスルール(計算/判定)を記述する部品(モジュール)
例:数値を扱う BigDecimal型, 日付を扱う LocalDate型
ただし、個々のビジネスルールを記述するには汎用的すぎる
2019/5/11 39
型指向のプログラミング
ビジネスルールに登場する値を分類する
値の種類(=型)ごとに、独自のクラスを定義する
値の種類ごとに有効な値の範囲を定義する
値の種類ごとに必要な計算・判定のロジックを記述する
2019/5/11 40
オブジェクト指向の基礎としての型
2019/5/11 41
型
値の種類
有効な値の範囲の定義
その値を使った操作の定義
カプセル化
ポリモーフィズム
継承
「型の定義」(値を表現するデータと操作)を、
一つの入れ物(ファイル)にまとめること
構成要素(変数、メソッド、オブジェクト)が
「複数の型」に所属すること
同じメソッド名で異なる型の引数 → オーバーロード
クラス定義に型をパラメータとして渡す → ジェネリクス
異なる型のグルーピング → サブタイピング
「型の親子関係」を定義して、
親の特性を、子の型が引き継いで利用できること
継承とサブタイピングは異なる概念
ビジネスルールを「型」を使って記述する
2019/5/11 42
ビジネスルールを構成する三つの要素
Fact 事実の表現
ビジネスの状況の記録や通知に使う型
・ 数値、日付、場所、識別番号、名称、…
Rule Factを使った
計算や判定のロジック
計算式
同一性の判定式
大小の比較式
Goal 知りたいこと
計算結果や判定結果を表現する型
・合計金額、予定日、残数、…
・出荷可否、受付可否、割引種類、…
2019/5/11 43
Fact-Rule-Goalを記述する
設計パターン
値オブジェクト
ロジックを持ったenum
コレクションのカプセル化
2019/5/11 44
詳細は17:20から
ソフトウェアの核心にある複雑さに
本格的に立ち向かう
2019/5/11 45
核心にある複雑さに本格的に立ち向かう
2019/5/11 46
深いモデルを探求する
ビジネスルールの中核を見定め、中核に集中する
ビジネスルール全体の関係を俯瞰的に整理する
本格的に立ち向かう
考え方とやり方
2019/5/11 47
エヴァンス本の構成
2019/5/11 48
第1部
ドメインモデルを
機能させる
第2部
モデル駆動設計の
構成要素
第3部
深い洞察に向かう
リファクタリング
第4部
戦略的設計
1章~3章 4章~7章 8章~13章 14章~17章
概論と基本事項
ここだけでは本格的に立ち向かえない
役に立つ「深いモデル」を
手に入れるための技法
「大規模」に適用する
「長期的」に取り組む
ための技法
深いモデルを探求する
492019/5/11
ドメイン駆動設計で大きな成果を得るのは
ドメインを深く理解したモデルを発見できた時
502019/5/11
役に立つ深いモデル
2019/5/11 51
最初からは見つからない
段階的に発見し、改善していく
暗黙的な概念 → なんとか言語化する
ぎこちない設計 → コードの表現力を改善
役に立つ深いモデルを発見する技法
2019/5/11 52
9章
暗黙的な概念を明示的にする
10章
しなやかな設計
ビジネスルールが
コードで明示できてないことの検知
「制約」や「ルール」を
クラスやメソッドで表現する実験
ぎこちなくても、とにかくコードにしてみる
明示的になったビジネスルールを
コードで分かりやすく表現する技法
意図の明白なインタフェース
副作用のない関数
表明
概念の輪郭
独立したクラス
閉じた操作
表現を
改善する
ビジネスを
理解する
ビジネスルールのコード表現の改善技法
意図の明白なインタフェース クラス名やメソッド名で、ビジネスルールの計算や判定の意図を表現する
副作用のない関数 同じ引数を与えれば、常に同じ結果を返すようにする
表明
メソッドの引数の「型」、メソッドの返す「型」で、
ビジネスルール実行の事前条件と事後条件を明確にする
概念の輪郭 ビジネスルールの関心の単位と、クラス/パッケージの単位を一致させる
独立したクラス ビジネスルールを独立して実行できる単位(クラス)に分解する
閉じた操作 引数の型、返す型が自分の型と同じになる演算セットを検討する
2019/5/11 53
ビジネスルールの中核を見定め
中核に集中する
542019/5/11
第4部:戦略的設計
2019/5/11 55
14章
モデルの整合性を維持する
15章
蒸留
16章
大規模な構造
ビジネスルールの複雑さに
大規模・長期的に
取り組むための準備
境界づけられたコンテキスト
コンテキスト内のモデルの一貫性
コンテキストマップ
ビジネスルールの複雑さの整理と
凝集度の改善
コアドメイン
汎用的なサブドメイン
凝集されたメカニズム
ドメインビジョン声明文
コアのハイライト
コアの隔離
コアの抽象化
ビジネスルールの全体像を共通理解に
関係の整理と凝集度・結合度の改善
責務のレイヤ
(能力・運用・約束・ポリシー)
知識レベルと運用レベル
中核を見定め、中核に集中する
ドメインビジョン声明文 中核となるビジネスルール、ビジネスポリシーを、自然言語で説明する
コアのハイライト 中核となるビジネスルールを記述した場所に目印をつける
コアの隔離 中核となるビジネスルールを特定のパッケージに集める
コアの抽象化 中核となるビジネスルールに他のパッケージを依存させる
2019/5/11 56
ビジネスルール全体の関係を
俯瞰的に整理する
572019/5/11
第4部:戦略的設計
2019/5/11 58
14章
モデルの整合性を維持する
15章
蒸留
16章
大規模な構造
ビジネスルールの複雑さに
大規模・長期的に
取り組むための準備
境界づけられたコンテキスト
コンテキスト内のモデルの一貫性
コンテキストマップ
ビジネスルールの複雑さの整理と
凝集度の改善
コアドメイン
汎用的なサブドメイン
凝集されたメカニズム
ドメインビジョン声明文
コアのハイライト
コアの隔離
コアの抽象化
ビジネスルールの全体像を共通理解に
関係の整理と凝集度・結合度の改善
責務のレイヤ
(能力・運用・約束・ポリシー)
知識レベルと運用レベル
ビジネスルール全体を俯瞰して整理する
ドメインオブジェクトのレイヤー化
ポリシー
事業運営の決め事
ビジネスルールの方針
価格、割引、優遇、拒絶
オーバーブッキング
キャンセル
約束
顧客との契約
取引先との契約
見積
予約
注文
運用
ビジネス活動の実態(イベント)
ビジネスルールの起動トリガー
出荷、売り上げ
請求、回収
能力 ビジネス運営上の制約条件
在庫
出荷能力
処理能力
2019/5/11 59
ビジネスルールの3つの源泉
価値提供の約束と支払いの約束
ビジネス活動の連鎖/約束の連鎖
競争優位の獲得策/競争劣位の防止策
契約
バリュー
チェーン
事業運営
ポリシー
2019/5/11 60
詳細は17:20から
まとめ
612019/5/11
ドメイン駆動設計でつくる理由
2019/5/11 62
進化と成長を続けるソフトウェアを手に入れる
ソフトウェアの変更を楽で安全にする
ビジネスルールを中心に考える
632019/5/11
2019/5/11 64
ドメインロジック → ビジネスルール
ドメインモデル → 計算モデル
オブジェクト指向 → 型指向のプログラミング
核心にある複雑さに本格的に立ち向かう
2019/5/11 65
深いモデルを探求する
ビジネスルールの中核を見定め、中核に集中する
ビジネスルール全体の関係を俯瞰的に整理する

ソフトウェアの核心にある複雑さに立ち向かう