SlideShare a Scribd company logo
ドメイン駆動設計入門
2013年9月26日
有限会社システム設計 増田
BPStudy #73
1.ソフトウェアの核心ドメインモデル
2.ドメインモデルとオブジェクト指向
3.ドメイン駆動設計のインプット
4.ドメインモデルの実装パターン
アジェンダ
1
ソフトウェアの核心
ドメインモデル
業務システムの基本構成
画面
アプリケーション
連携
アプリケーション
帳票
アプリケーション
データベース
ドメインモデルパターン
画面
アプリケーション
連携
アプリケーション
帳票
アプリケーション
データベース
ドメイン
モデル
(ビジネス層)
業務の
データとロジック
ドメインモデル
• 業務のデータと業務の機能をコードで表現
– ビジネス層に集約する
– 関係するデータと機能をクラスにまとめる
• ハイブリットなアプローチ
– データの視点と機能の視点
• 両方からアプローチする
• 二つの視点をいったりきたりする
– データと機能の結びつき強める
• クラスにカプセル化
• データ保持クラスと機能クラス(データ操作クラス)
に分けるのはアンチパターン
関連するデータと機能は
クラスにまとめる
氏名
nameKana()
originalFamilyName()
住所
line()
city()
連絡
手段
firstChoice()
change()
changePriority()
連絡
履歴
unprocessed()
lastThreeContacts()
withinTwoMonths()
ドメインモデルをみんなで使う
画面
アプリケーション
連携/バッチ
アプリケーション
帳票
アプリケーション
データベース
氏名
住所 連絡
履歴
連絡
手段 業務で使う
データ+ロジックを
ここに集約
作る順番
データベース
OR
マッピング
2
5
アプリケーション
サービス
(API宣言)
3
ドメイン
モデル
1
機能テスト
4
なぜ
ドメインモデル
パターン
で作るのか?
コード量が減る
• テストが減る
• ドキュメントが減る
• バグ調査が楽になる
• 変更の影響が見通しやすい
コード量が減れば
ドメインモデルは
コードの重複を減らす
• あちこちに分散しがちな業務ロジックを
データ中心に整理し、集約する
• いやな臭い
– データを要求する getter メソッド
• そのデータを使うロジックが、別のクラスに分散
• あちこちのクラスに重複して書かれている危険な
兆候
コードが膨張するアンチパターン
• トランザクションスクリプト
– 機能単位/画面イベント単位に業務ロジックを記述
– あちこちの画面/帳票/外部連携に、似たロジック
が繰り返し登場
– 使われない「共通業務ロジック」(共通部品構想の
残骸)
• どこでも業務ロジック
– ビュー記述に業務ロジックをべた書き
– 画面コントローラに業務ロジックをべた書き
– Data Access Object に業務ロジックをべた書き
– SQL に業務ロジックをべた書き
ドメインモデルに
業務ロジックを集めて
重複したコードを
減らしましょう
アプリケーションの中核部品
画面
アプリケーション
連携
アプリケーション
帳票
アプリケーション
データベース
ドメイン
モデル
ここに
業務ロジックを
集める
ドメインモデル
表面に見えるメリット
• コード量が減る
• 業務のロジックが書いてある場所が見つ
けやすい
• 業務のロジックを変更した時の影響範囲
が局所化される
ドメインモデル
ほんとうの価値
• 業務の知識の浸透
– ビジネス目標/システムの価値の理解
– 業務の全体像/基本の仕組みの理解
– 業務の現場にある肌感覚、現場の知恵
• 言語表現を超えた暗黙知が育つ
– 業務アプリケーションの設計のコツ、かんどころ、
おとしどころ、…
– 個人に内面化された価値観、方向感
– チームで共有化された価値観、方向感
• 「あたり」がつくようになる
– 的外れの作業/とんでもない勘違い/手戻りが減る
– 進むべき方向がわかりやすくなる
2
ドメインモデルと
オブジェクト指向設計
個人的な話
• ドメイン駆動設計に出会って、オブジェ
クト指向も便利と思うようになった
• それまでは
– C言語で構造化プログラミング
– Oracle データベース中心アプローチ + PL/SQL
で手続き型プログラミング
• 私にとってオブジェクト指向設計は、
ドメイン駆動設計の実践手段の一つ
ドメイン駆動設計のための
オブジェクト指向設計
• 部品化
• 条件分岐と多態
• 制御構造の再利用
• 全体の建てつけ
部品化アプローチ
• 集める
– 関係するデータとロジックを一つのクラスに
– 関連するクラス群をパッケージに
• 目的に特化する
– 特化:PersonName,Money, ScheduledDate, …
– 汎用:String, BigDecimal, Date, …
• 業務用語の粒度にあわせた部品
– 「予定日」とか「合計金額」がクラス候補
– クラス=データとロジックの置き場所
区分と分岐
• 区分、種別
– 夏季料金/冬季料金
– 特別会員/一般会員
– 申請中/承認済/実行済
…
• 条件分岐で記述?
– if/else
– switch case
多態
インタフェース宣言と実装クラス
• interface 季節料金
– price ()
• 実装クラス
– class 夏価格 implements 季節料金
– class 冬価格 implements 季節料金
• データとロジックの置き場所
– 夏の期間、夏の料金計算式 → 夏価格クラス
– 冬の期間、冬の料金計算式 → 冬価格クラス
• 使う側
– どの季節でも、季節料金#price() を呼ぶだけ
多態
オブジェクトの生成と選択
Map<季節名,季節料金> 料金=
[ “夏” : new 夏価格(),
“冬” : new 冬価格() ];
price( “夏” )
{
料金.get(“夏”).price();
}
enum 季節
{
夏( new 夏価格()) , 冬( new 冬価格() ) ;
private 季節料金 料金;
季節( 季節料金 料金)
{
this.料金 = 料金
}
}
// 画面アプリケーション
// select ボックスを “夏” を選択
季節.valueOf( “夏” ).price()
// OR マッピング
enum 季節.夏 -> データベースに季節名を保存
データベースの季節名 -> enum.valuleOf(“夏” )
if 夏
return new 夏価格()
else
return new 冬価格()
※一か所だけ条件分岐が残る
制御構造の再利用
• フレームワーク
– IoC : Inversion of Control (制御の反転)
• Control = if/else, switch, for, try-catch-throw, goto …
• Inversion:反転の意味
– アプリケーションプログラミング
» 制御構造を書く → 制御構造を書かない
• たとえば
– コレクションフレームワーク と for 文
– バリデーションフレームワーク と if 文
– ORマッピングフレームワーク と for 文/if 文
– MVC フレームワークと switch 文
全体の建てつけ
アプリケーションサーバー
• アプリケーション起動イベントのリスニング
– HTTP リクエスト、非同期メッセージ、メール受信
– データベース変更、File 追加
• 文脈(Context ) に沿ったアプリケーションの実行
– ターゲットのオブジェクト#メソッドを判定・起動
– 環境依存性の分離(リソースの間接参照 JNDI etc.)
– 横断的関心事の実行 ロギング、セキュリティ、…
• たとえば
– Tomcat ( HTTP リクエストハンドラ)
– Active MQ + Mule ESB ( 非同期メッセージハンドラ)
– Jame ( メール受信ハンドラ)
補足:パターンについて
• パターン
– アーキテクチャパターン : PoEAA, EIP, …
– GoF デザインパターン
• 確立したパターンは、自分で書く必要はなくなりつつある
– GoF のオブジェクト生成パターン
• Spring : Bean コンテナ の Bean 生成機能
• Java : enum (singleton)
– GoF の Strategy/State パターン
• Java : enum
– PoEAA のドメインモデルパターンとデータマッパ
• OR Mapping ツール
– PoEAA のフロントコントローラパターン
• Spring MVC Dispatcher Servlet
– EIP
• Mule ESB
3
ドメイン駆動設計の
インプット
主要なインプット
ドメイン
モデル
最初に手に入れるべき情報
いつも気にすべき情報
機能モデリングの元ネタ
データモデリングの元ネタ
アーキテクチャ
スタイル
プロセス
スタイル
オブジェクト指向
設計スタイル
最初に手に入れるべき情報
全体イメージと方向感
• ビジネス企画書
– トップ向けのプレゼン資料
– 予算申請時の説明資料
• ドメインのガイドブック
いつも気にすべき情報
フィードバック/実験結果
• 同僚の言葉
– ビジネス企画書の言葉を使っている?
– ドメインガイドブックの言葉を使っている?
– それは画面イベント(ボタン)駆動では?
– それはデータ操作命令では?
• 利用者の反応/利害関係者の言葉
– モデルに登場しているか?
– モデルで説明できるか?
データモデリングの元ネタ
• 画面
– ワイヤーフレーム
– 項目定義書
• 帳票
– サンプル
– レイアウト、項目定義書
• 既存データベース
– DDL
– ER 図
• 外部インタフェース
– ファイル仕様書
– サンプルファイル
機能モデリングの元ネタ
• 機能要求
– 機能要求一覧
– ユースケース一覧/ユースケース記述
– バックログアイテム、ユーザーストーリー、…
– 画面遷移図、画面イベント一覧
• ユーザマニュアル、オンラインヘルプ
– 既存システム
– 類似システム
• 業務体系
– 業務マニュアル
– 組織表、職務分掌規程
データと機能
ハイブリッドなアプローチ
• データの視点
– 業務で使うデータを洗い出して構造化(データクラス)
– データの識別キーとデータ整合性
– 「一覧」や「合計」など導出データもクラスとして明示
• ロジックの置き場所の有力な「候補」
• 機能の視点
– 利用者のやりたいこと(機能要求)
– 業務の手順、判断ロジック、計算式
– ユースケース、ユーザストーリー、バックログ
– 画面遷移、画面イベント
• 二つの視点をいったりきたりしながら
– データに機能を寄せる
– 機能にデータを寄せる
ドメイン駆動設計の基本スタイル
• アーキテクチャ
– ドメインモデル中心
• フレームワークの設計思想、利用例
– 非同期メッセージング
• ビジネスがそう動いている
• プロセス
– フィードバックサイクル
– 繰り返しのリズム
– 身軽、機敏
• オブジェクト指向設計
– データ+ロジック
– 目的特化
– 継続的な設計改善(リファクタリング)
ケーススタディ
プロジェクト初日のインプット
• Aプロジェクト
– ビジネス企画書の読み合わせ
– ドメインガイドブックの持ち寄り、ななめ読み
• Bプロジェクト
– 言語、ミドルウェア、フレームワーク、…
– ツール、サーバー環境、コミットルール、…
• Cプロジェクト
– マスタースケジュール、組織体制図、会議体、…
– WBS、マイルストーン、成果物、規約、…
• Dプロジェクト
– スプリント、バックログ、スタンダップミーティング、…
– テスト駆動、ペアプログラミング、継続的デリバリ、…
4
ドメインモデルの
実装パターン
実装パターン
• 目的特化
• かたまり
• 永続化
• アプリケーションインタフェース
目的特化
ドメインモデルの基礎部品
• 日付、期間、数量、金額、単位、名称、備考、…
– String, BigDecimal, Date など汎用部品をラッピングし
た目的特化部品
– フィールド変数は、ひとつか二つ
– 長さ、文字種、形式など目的特化で限定
– ロジックの置き場所 ( getter で値を返さない )
• Value Object パターン
– 完全コンストラクタ
• すべてのフィールド値を、生成時に決定
– 不変
• setter を書かない
• 値の変更は、別のオブジェクトを生成して返す
目的特化
ファーストクラスコレクション
• コレクションだけを保持する特別クラス
class ItemList { private List<Item> }
• 汎用インタフェースを必要なものだけに限定
する
– add() , size(), …
• コレクションの操作ロジックを集約
– for 文
– 集合操作
– コレクションを他クラスに渡さない
• どうしても必要なら 不変にして渡す
目的特化
区分、種別、イベント/状態の宣言
• 静的に列挙できる場合
– enum 宣言
• インタフェース宣言+実装クラス群+Singleton
Java コンパイラがやってくれる
• 外部のマスター定義を読み込む場合
– Map + singleton
• Spring の bean 生成 + autowired
• イベント/状態
– クラスを分ける
• イベント種類ごと
• 状態種類ごと
– 遷移ロジックをステートパターンで記述
かたまりのパターン
• Bounded Context
– チームの関心スコープを明確にする
– ユビキタス言語
– 組織パターン
• モジュール
– 関心事の範囲を明確にするパッケージを宣言
– public スコープは最小限。基本はパッケージスコープ。
– モジュール間の依存関係を最少にする(方向、依存線の数)
• Aggregate
– 基礎部品 ( Value Oject ) の集合体
– 集合体の識別
• Aggregate の root オブジェクトとしての Entity パターン
– 必要なら用途別に Aggregate を用意する
• 顧客サマリー(一覧用),
• 顧客連絡先
• 顧客履歴
かたまりのパターン
Aggregateの利用
• Repository
– 業務の関心事「記録」を表現
– Aggregate 単位の保存/取り出し
– インタフェース宣言して実装と分離
• データアクセスへの依存性を逆転させる
• Transfer
– 業務の関心事「通知」を表現
– 必要なら通知専用の Aggregateを追加
• Factory
– 業務の関心事としての Builder パターン
• 「準備」や「用意」が複雑な場合
Aggregateと永続化
• データモデルとオブジェクトモデル
– データモデル ( データのみ )
• 正規化が原則
• 導出可能データは保存しない
• すべての関係は、キーを元に 1 対多として構造化
• 参照方向は「多→1」に固定
• 構造的にデータ整合性を維持する
– オブジェクトモデル(データ+ロジック)
• 導出データもオブジェクトで表現する
– ロジックの置き場所として重要
• 関連の表現の自由度が高い
– ネットワーク構造、参照方向、多重度の制約
– データ整合性はロジックで維持する必要がある
永続化
• SQL マッピングのすすめ
– 正規化したデータモデルを、SELECT 文でオブ
ジェクト用に冗長化してマッピングする
• 危険な臭い
– OR マッピングの隠ぺいや SQL自動生成
• オブジェクトが、データの入れ物の設計だけにな
りがち
• ドメインモデル(オブジェクトモデル)の設計改
善の制約になりがち
サービス層
データベース
OR
マッピング
2
5
アプリケーション
サービス
(API宣言)
3
ドメイン
モデル
1
機能テスト
4
サービス層
アプリケーションインタフェース
• アプリケーションインタフェース
– アプリケーションとドメインモデルの接点
• 業務機能の宣言(ユースケースの実現)
– 登録()、記録()、作成()、…
– 参照()、検索()、絞り込み()、…
– キャンセル()、取り消し()、訂正()、…
• 業務手順の記述
– 検証() , 記録(), 通知() 3行程度の手続きを記述
– 判断、計算、加工はドメインモデルに委譲する
おわりに
アプリケーションの中核部品
ドメインモデル
画面
アプリケーション
連携
アプリケーション
帳票
アプリケーション
データベース
ドメイン
モデル
ここに
業務ロジックを
集める
なぜドメイン駆動設計か?
• コード量が減る
– 重複しがちなコードを、データ構造を軸に整
理・統合する
– 業務ロジックが、プレゼンテーション層、
データアクセス層から消えていく
• 手戻りが減る
– 業務の仕組み/こだわりポイント/やるべき
こと
• メンバー個人に内面化
• チーム共有の暗黙知の発達
お誘い
オブジェクト設計エクササイズ
チームモデリングで学ぶドメイン駆動設計
2013/10/05 (土) 13:30 - 16:30
開催場所 : mixi 渋谷区東1-2-20 住友不動産渋谷ファーストタワー7F
参加費:五千円
内容:
チームにわかれて、ドメインモデリングを実際にやってみる
• イテレーション 3回を予定
• 業務知識が豊富なドメインモデルに育てる
• モデルとコードを結びつける
• モデルの洗練
• モデルの検証
ありがとうございました

More Related Content

ドメイン駆動設計入門