Upload
-
View
20.147
Download
1
Embed Size (px)
DESCRIPTION
第47回 SEA関西プロセス分科会 2012.6.23 ドメイン駆動設計 実践ガイド
Citation preview
第47回SEA関西プロセス分科会
2012年6月23日(土)有限会社 システム設計代表取締役 増田 亨Twitter @masuda220ブログシステム設計日記
ドメイン駆動設計のめざすところ
実践の基本
より深く実践する
より大規模に実践する
u利用者の関心事を理解するu関係者の間の意思疎通を楽にするuドメインモデルとドメイン層実装の一致
uドメイン層の分離・独立uドメインオブジェクトの設計パターン
u利用者の関心事を踏み込んで理解するu深い理解(=モデルの進化)の手がかり
u大きなモデルを分割するu整合性維持の戦略
¡ 今回とりあげる章は§ まえがき(xixページ)で推奨された章
▪ 第1部の導入と第1章
▪ 2章、3章、9章、14章
§ 基本テクニックとして、4章、5章、6章
§ それ以外は、ほとんど触れません。あしからず。¡ 内容は、私たち流のやり方の事例紹介§ 実装技術:Java, Spring, MyBatis, Velocity …§ 開発プロセス:RDRA, ICONIX§ 「ドメイン駆動設計」のちゃんとした(?)読み方ガイドではありません。
序文、まえがき第1部 1章、2章、3章
¡ 優れたドメインモデルは(ソフトウェア開発で)信じられないほどの価値をもたらす
▪ 序文 by マーチン・ファウラー
¡ 先進的なソフトウェア設計者は、ドメインモデリングと設計が重大なテーマであると(ずっと)認識してきた。
¡ 成功したプロジェクトに共通する特徴は、豊かなドメインモデルにある。
▪ まえがきエリックエバンス
利用者の関心事の模型
視覚化・構造化した用語集
ドメイン層の設計図(クラス図)
¡ クラス図が、モデルの主たる表現手段§ クラス図は、そのままコードに落とせる
§ その他の表現手段▪ 補足的に、説明文や図表も使う
▪ コードも表現手段の一つ(詳細すぎる)
¡ 振舞のモデリング§ クラス図は静的構造。振舞のモデリングも必要。
§ エバンス▪ 自然言語で、会話の中で、クラスの振舞を検証
§ ICONIX▪ ユースケース記述(自然言語)、ロバストネス図(振る舞い図)、ドメインクラス図(構造図)を突き合わせて、整合性をチェック
¡ 自然言語で実験してみる§ 利用者のやりたいことを、クラス図の語彙(パッケージ名、クラス名、メソッド名)で、話すことができるか?
§ クラス図に登場しない言葉が、会話に何度もでてこないか?
¡ コードで実験してみる§ ドメインモデルが、そのまま実装できるか?
§ コードとして、すっきりしているか?
§ 振舞のテストケースは、利用者のやりたいことを自然に表現しているか?
モデル =ドメイン層実装の羅針盤(利用者の関心事とコードの整合性維持)
チームメンバーの標準言語(効果的な意思疎通の基盤)
重要な関心事・業務知識・ルールの識別(時間配分・エネルギー配分の優先順位)
¡ -ing 現在進行形§ Never Ending Story
¡ Evolving ドメインモデルを育て続ける§ 小さく生む
§ フィードバック
§ 追加・変更
¡ Pervading ドメインモデルを行き渡らせ続ける§ 多くの関係者
§ いろいろな活動
§ さまざまなシステム構成要素
§ ライフサイクル全体
¡ Binding ドメインモデルと 前後を直接、結びつけ続ける§ 利用者の関心事とドメインモデル
§ ドメインモデルと実装コード
¡ 1章 知識をかみ砕く§ 利用者の関心事を知る
§ 継続的学習
§ 深いモデルの探求¡ 2章 コミュニケーションと言語の使い方§ 関係者の意思疎通
§ 会話(自然言語)によるモデリングと実験¡ 3章 モデルと実装を結びつける§ モデリングパラダイム(オブジェクト指向)
§ コードを書くモデラー
¡ 利用者のやりたいことに興味を持つ
¡ 表面的な理解で終わりにしない
¡ 深く突っ込んで理解する努力を続ける
¡ いちばんの武器は自然言語(国語力)
¡ 良いドメインモデルを手に入れて
§ Putting the Domain Model to Work
第2部The Building Blocks of a Model-Driven Design4章、5章、6章
¡ アーキテクチャ
§ ドメイン層は独立させる
§ 他の層がドメイン層に依存する
¡ プロセス
§ ドメインモデリング中心のプロセスの実践▪ RDRA + ICONIX▪ ドメインモデルの作成と改良を基本タスクに
¡ オブジェクト指向の設計スタイル
§ ワーフスブラック「オブジェクトデザイン」の第1章「設計コンセプト」
画面UI
コントローラ
メッセージング
メール送信
DBアクセス
利用者の関心事だけを記述する場所
ドメイン層の用意
画面 UIコントローラ
メッセージング
メール送信
DBアクセス
利用者の関心事を記述したクラス群
利用する 利用する
利用する
利用する
誰から使われているか知らない
利用する
顧客<< domain object >>
連絡方法
通知先() : メールアドレス
利用する
画面 UIコントローラDBアクセス
メール送信
メッセージング
顧客登録サービス<< application controller >>
呼び出す顧客リポジトリ
<< interface >>
登録する() : void存在を確認(顧客) : Boolean利用する
実装する
顧客トランスファー<< interface >>
Thank Youメール送る(顧客) : void関係部門に通知する(顧客) :void
利用する実装する
実装する
顧客<< domain object >>
連絡方法
通知先() : メールアドレス
画面 UIコントローラ
メッセージング
メール送信
DBアクセス
Spring MVC
Spring Mail
Spring JMS
Spring BindBean Validation
Velocityテンプレート
Spring ORM
MyBatis SQLマップ
Apache James
ActiveMQMule ESB
Spring Web Flow
Spring フレームワークは、ドメイン層とそれ以外の層、という考え方が明確。
ドメイン駆動設計の実践技術として良いと思う。
¡ RDRAとICONIXを参考にしている¡ 初日からドメインモデリング§ コンテキスト図を描きながら、ドメイン層のパッケージ図を描き始める
¡ 毎日ドメインモデリング§ 業務フローを書きながら、各業務ステップに要望事項や関心事を記述§ そこででてくる用語を、ドメインクラス図に反映
§ ユースケース記述、ロバストネス分析しながら、ドメインクラス図を発展させる§ そのままコードに落としていく
システム外部環境システム外部環境
利用シーン記述利用シーン記述
業務フロー図業務フロー図
概念モデルの洗練概念モデルの洗練
関連クラス依存クラス
画面・帳表画面・帳表ユースケースユースケース
属性追加属性追加
システム境界システム境界
ドメインモデルドメインモデル
イベントイベント 状態遷移状態遷移
データデータモデルモデル
システム価値システム価値
初期初期概念モデル概念モデル
要求図要求図コンテキスト図コンテキスト図
パッケージ構造中核クラス
クラスとテーブルの設計・実装
ロバストネス図ロバストネス図
システムシステム ((IICONIX)CONIX)
シーケンスシーケンス図図
操作操作追加追加コード
Javaソースコード
基盤クラス追加基盤クラス追加
予備設計
詳細設計
ユースケースごとに開発
コード
DDL/SQLソースコード
要件分析・要件定義
クライアントオブジェクト
依頼協力する
オブジェクト
サービス提供能力
判断能力
情報の保持
他のオブジェクトと関連の保持
クライアントができるだけ、楽をするように、設計する
必読:ワーフスブラック「オブジェクトデザイン」1章 設計コンセプト
全体
部品A 部品N
部品群の構造化<<structurer>>
情報保持<<information holder>>
サービス(演算)提供<<service provider>>
制御役<<controller>>
調整役<<coordinator>>
If/for を 持つ/持たない の違い
外部への見せ方<<interface>>
Whole-Part に分解し、それぞれのオブジェクトの役割を、単純に、明確にする
¡ Associations§ 関連:できるだけ限定する
¡ Entities (key)§ 利用者の関心事の識別と追跡
¡ Value Objects (value) § 関心事の内容や値の表現
¡ Services§ 業務ルールや手順という関心事の表現
¡ Modules§ 関心事のグルーピングと分割
¡ ドメインモデリングの基本ツール▪ Whole-Part でクラスの役割を単純にすると、小さなクラスが増える
▪ それを「パッケージ」でカプセル化
▪ 全体の構造を、クラスレベルの関係ではなく、パッケージ間の関係で整理・把握する
募集 応募 選考
共通(日付・期間など)
¡ 関連は、ぎりぎりまで単純にする
§ 双方向 → 単方向
§ 多対多 → 1対多 → 1対1 (限定子)§ 参照 → 利用
§ ほんとうに必要か?
§ アンチパターン
▪ モデル上の「関係」と、コードが一致していない
▪ 例:双方向・多対多の実装。とっても複雑。
関連を限定するほど、重要な関係・構造が明確になる
¡ 基本語彙の実装パターン
§ String, BigDecimal, Date(long) のラッパー
§ 型宣言 → 表現力の向上
▪ 連絡先、期間、金額、数量、登録日、締切日…
§ 不変 → 振る舞いの安定
▪ コンストラクタで、すべて情報をセット
▪ set メソッドなし
▪ 演算結果は、新たにオブジェクトを生成して返す
▪ 参考:String の振舞
¡ 利用者が関心事をどう識別するか知っているクラス
§ 受注番号、契約番号、….§ 番号+名前が基本
▪ 人間が理解・判断する情報
▪ 内部的なシーケンス番号や、UUID ではない
▪ 一覧画面に表示する項目、ソート順と関係
¡ その他の情報(属性)の保持は、他のクラスに委譲する
¡ 契約
§ 二者間の約束事
§ 注文、申し込み、予約、…¡ トランザクション ( domain event )§ 業務の処理単位
§ 伝票(起票)と記帳(残高<状態>更新)
¡ 人、組織¡ モノ¡ 場所
部分全体
場所地域
条項契約
予定作業計画
メンバーグループ
ルールポリシー
後続イベントイベント
物品品種
個別取引複合取引
¡ 顧客一覧クラスとかにカプセル化する¡ できるだけ、コレクションは隠ぺいする
§ そのまま公開しない
§ 公開する場合も、不変のコピーにして渡す
顧客一覧
顧客数()add(顧客)
顧客
class CustomerList{
private List<Customer> customers ;
int numberOfCustomers();void add( Customer customer );
}
¡ ビジネスパターンによるモデル駆動設計 by Hruby§ 2章構造パターン
§ 5章振舞パターン
¡ アナリシスパターン by Fowler§ 付録A.1.5 基本型
¡ ストリームラインオブジェクトモデリング by ニコラ
§ 3章協調パターン
¡ UML によるビジネスモデリング by エリクソン
§ 5章ビジネスルール
¡ The Data Model Resource Book 1,2,3¡ Data Model Patterns by Hay
¡ リファクタリング (ファウラー)§ 特に「変更の発散」「変更の分散」
§ その2つの臭いに有効なリファクタリング
▪ クラスの抽出
▪ メソッドの移動、フィールドの移動
§ その準備
▪ メソッドの抽出
▪ 説明用変数の導入
¡ 実装パターン(ケントベック)
§ 4章 動機
§ 5章 クラス、6章 状態
§ 7章 振る舞い、8章 メソッド
モデリングとコード設計のスタイルをオブジェクト指向で整合させる
クラス図とコードがセットになった例が豊富
¡ ドメインオブジェクトの扱い方
¡ 生成・保存・取り出しのライフサイクルの表現場所
§ Aggregates いつもいっしょに扱う単位
§ Factories 生成時に固有の関心事
§ Repositories 「記録」という関心事
§ Transfers 「伝達」という関心事(追加)
¡ 利用者が、扱いたい情報の単位は?¡ 変更のタイミングや頻度が同じ情報の「かたまり」は?¡ その「かたまり」を利用者は、どう呼んでいるか?¡ アンチパターン§ なんでも知っている巨大Aggregate/巨大テーブル
§ 利用者は、利用シーンに応じて、もっと小さい単位で、情報を扱っている
¡ アンチパターン§ Insert, update, delete
¡ 利用者の言葉で、表現する/使い分ける§ 登録、追加、新規作成、…§ 改訂、訂正、更改、...§ キャンセル、取消、廃止、停止、…
¡ ドメイン層を独立させる§ ドメイン層でインタフェース宣言
▪ データアクセス層の存在・実装を知らない
§ データアクセス層で実装▪ ドメイン層のインタフェースに「依存」する
¡ 利用者の言葉で表現§ 通知、連絡、…§ 依頼、指示、…§ 送付、転送、回覧、…
¡ ドメイン層を独立させる§ ドメイン層でインタフェース宣言§ データアクセス層で実装
¡ 実装手段§ 電子メール§ RESTful スタイルのWeb サービス§ メッセージングサービス§ ファイル転送§ 共有データベース
¡ ごった煮コード
§ ドメイン層と他の層のごった煮
¡ トランザクション・スクリプト
§ 手続きスタイルへの執着
¡ どこでも業務ロジック
§ UI、SQL、トリガーなどに業務ロジックを分散して記述
¡ ドメインオブジェクト getter/setter 大忙し
§ 役割分担の失敗、緊密すぎる協調
¡ 利用者のやりたいことに興味を持つこと¡ ドメイン層の独立¡ ドメイン層に業務の知識、ルールを集約
¡ ソフトウェアの設計原則を丁寧に実践すること
§ 関心の分離
§ カプセル化
§ 協調
第3部 Refactoring Toward Deeper Insight9章 隠れた概念を発掘し、明示する
¡ 最初は表面的なモデル§ とりあえず(表面的には)動くことは動く§ どこかぎこちない(利用者がしっくりきていない)§ 変更に弱い、副作用が怖い
¡ 深いモデルを探究する動機§ 利用者の問題解決に、もっと役にたつソフトウェアにする§ 変更を、もっと簡単に、安全にする§ 業務都合による変更依頼が予測できる§ 利用者の期待以上の提案ができる
¡ 地道で、継続的な努力§ 深いモデルにたどり着くには、モデリング・設計・実装の基本テクニックを、地道に繰り返すこと
§ 短期決戦・作り逃げプロジェクトとは別の世界。
¡ 既存のモデル、コードの中から、新しい切り口のクラス(パッケージ、メソッド、フィールド)候補が見つかる
¡ モデルに新しい名前が登場§ その言葉を使ってみると、会話がスムースになる§ いままでの疑問、違和感が一気に解消する
¡ ごちゃごちゃしたコードが、すっきりする§ クライアント側オブジェクト
▪ 面倒なことはすべて委譲
§ サービス提供側オブジェクト▪ 前処理、後処理、条件分岐等が少ないシンプルなコード
¡ 職務経歴▪ 最低ひとつは記述が必要
¡ 最初の実装▪ private List<仕事> 職務経歴;
▪ If 文で、最低一件を保障
¡ 「直近の仕事」+「その他職歴」の導入▪ private 仕事直近の仕事;▪ private List<仕事> その他職歴;
▪ 検証ロジック、永続化、画面記述、すべてに「直近の仕事」という必須項目が自然に実装された
¡ ある開発者との戦い?▪ 直近の仕事 = List<仕事>#get(0) で、実装したい。
¡ 違和感
§ 利用者との会話、意思疎通
§ 入り組んだ、ぎこちないコード
§ 変更の発散
▪ ひとつのクラスを異なる理由で何回も変更する
§ 変更の分散
▪ ひとつの変更を異なるクラスに分散して記述
違和感をそのまま放置しないことそこに宝の山があるかもしれない
¡ 隠れた概念(お宝)を発掘する§ 聞き耳を立てる
§ ぎこちなさを精査する
§ 矛盾を熟考する
§ 「その」本を読む
§ 挑戦を続ける¡ はっきりしない概念をモデル化する§ 制約
§ 手順
たいへんな作業ですが、発見できれば得るものは大きい
¡ 違和感、ぎこちない、釈然としない、怪しい、…¡ こういう感覚を持ったら
§ 聞き耳を立てる
§ 精査する
§ 熟考する
¡ アンテナで passive に受信するだけでなく、こちらから音波を発信して探索する active ソナーも必要
¡ そのドメインについて
§ 基本的な概念
§ 実践的な知見・知恵
§ 知識を凝集した
§ 深く考えられた
こういう情報が詰まった本を見つけて読む。深いモデルの探索に役立つ。
良い本を手に入れても、大切なことは、ドメインエキスパートとの会話。
¡ 制約
§ ルール、ポリシー、規約、料金表、…
¡ 手順
§ 手続き、ワークフロー、承認ルート、…
¡ 状態遷移
§ 承認待ち、申請中、差戻し、回答待ち、…
¡ まずは、言葉を書きとめる§ クラス図にノート(メモ)を追加§ クラスや関連に「制約」を記述
▪ [size < max]¡ モデリングパターンの利用を検討§ Policy クラス
▪ Rule の集約クラス▪ OverbookingPolicy, CancelPolicy, …
§ Criteria クラス▪ 検索条件、許容範囲など
§ Scheme クラス▪ Pricing Scheme, Identification Scheme , …
利用者、業務の専門家の言葉に登場する概念なら、そのままクラスにする
¡ 業務の手順や手続きは、重要な業務知識§ そこに関わる業務ルール(制約)も多い
§ しかし、直観的にはドメインオブジェクトとしてモデリングしにくい。
§ 「手順」「手続き」が業務の専門家の言葉としてでてきたら …§ Procedure クラスを仮に作って、実験してみる
¡ モデリングのヒント§ Fowler ”アナリシスパターン”
▪ 8章計画
§ Eriksson, Penker “UML によるビジネスモデリング”▪ 9章プロセスパターンのProcess-Process Instance パターン
¡ テクニカルには§ ステートマシンでモデリング§ EventType <<enum>>, StateType <<enum>> § Map<StateType, List<StateType> > 遷移先§ Map<StateType, List<EventType>> 実行可能イベント§ などで実装可能
¡ 課題§ 利用者は、そういう概念で業務をとらえているか?
▪ 意思疎通の手段として疑問。
▪ 大半のケース、例外ケース、レアケースなどの感覚を、なんとかして、構造に落とす。
§ ステートマシンは無限ループ構造になりやすい▪ 業務上は、なんらかの許容範囲があり、注意喚起も必要
¡ ファウラー「リファクタリング」
¡ ドメイン(業務、業種)のハンドブックや解説本の利用
宿泊予約
料金()
If ( date.before( SUMMER_START )|| date.after( SUMMER_END ) )
{charge = quantity * winterRate + winterFee ;
} else{
charge = quantity * summerRate ;}
宿泊予約
料金()is夏季()夏料金()冬料金()
クラス設計に業務の言葉を増やす
If ( isSummer( date ) ){
charge = summerCharge() ;} else{
charge = winterCharge()}
(124)説明用変数の導入(110)メソッドの抽出(149)クラスの抽出
¡ 和書
§ 基本用語のキャッチアップ
▪ まずは、用語になれる
▪ 漢字でどう書くか、わからない言葉はなくすこと
¡ 洋書
§ 和書よりも構造や用語定義にこだわった本が多い
▪ 目次や overview は、そのまま構造設計の雛形になる
▪ 索引は、クラス候補、メソッド候補の宝庫
§ (英語の)パッケージ名、クラス名、メソッド名のネタ本
¡ 利用者のやりたいことに興味を持つこと
¡ 会話/クラス図/コード上の違和感、ぎこちなさを気にすること
¡ 聞き耳・精査・熟考
¡ リファクタリング
¡ 「その」本を見つける
深いモデルにたどりついた時の、到達感の味を覚える
第4部 Strategic Design14章 (大規模な)モデルの整合性を維持する
¡ 14章 水平分割§ モデルをContext(文脈)単位に水平に分割§ Context 間の整合性維持の戦略
¡ 15章 蒸留 Distillation§ A4一枚に、要点を集約して表現する§ Core Domain, Domain Vision Statement, Highlighted
Core, …¡ 16章 レイヤ化§ ドメイン層の内部を、レイヤ構造にする
▪ リソース層/オペレーション層/ポリシー層▪ 先行ドメイン・後続ドメイン(時系列構造化)
¡ Bounded Context と Context Map§ 「文脈」単位に分割する§ 「文脈」間の関係を図示する§ As-Is のみ
¡ 文脈の境界はモデル外部の要因で決まる§ 利用部門§ 開発チーム、担当部門、担当会社§ プロジェクト単位、契約単位§ 技術方式
▪ レガシーシステム、外部システム、Java, .Net, PHP, …§ 運用責任部門と運用ポリシー
▪ SLA, セキュリティポリシー, …
¡ Shared Kernel¡ Customer/Supplier Development Team¡ Conformist¡ Anticorruption Layer¡ Separate Ways¡ Open Host Service¡ Published Language¡ Single Bounded Context
¡ Shared Kernel§ いままでシェアできていなかった
§ なぜ、今回はシェアできるのか?¡ Anticorruption Layer§ 必要悪? 技術負債の増加?
§ 両サイドからの変更のたびに、多大なコスト¡ Open Host Service¡ Published Language§ 汎用的=関心の分離の崩壊?
¡ Single Bounded Context§ 単一で扱えない規模・複雑さだから、困っている
¡ 大きくて複雑なシステムは、うまく扱えない、あつかった成功事例がない、という現実を素直に受け入れよう
¡ 技術の問題ではなく、人・組織・統治・慣習・文化の問題
¡ 現実にある制約
§ 時間・予算・成果責任
¡ やるべきこと=関係者の合意(共通意思)
§ 整合性維持に、今回は投資する
§ 整合性維持に、今回は投資しない
¡ チーム間の現実から判断する
§ 「意思疎通」の時間とエネルギーの見積もり
§ 達成のメリットの共有度合い
§ 未達時のリスクと対応策の共有度合い
¡ 志を持ってチャレンジは続ける▪ 身の回りで(責任のとれる範囲で)
▪ 小さく、短いサイクルで、継続的に
▪ 「連携」も利用者のやりたいこと。そのContext 内のモデルを洗練すれば、他のContext と連携しやすくなる。
本来の目的に、いつも立ち戻って、判断すること
¡ Separate Ways§ Bounded Context ごとに分離して開発する
§ おそらく、もっとも費用対効果が高い
§ 整合性維持、統合の見積もり
▪ コストは多めに見積もること
▪ 効果は少なめに見積もること
§ システムの整合性維持の前に、組織やビジネスの整合性維持・統合の取り組みを検証すること
¡ 可能な限り疎結合にする§ 引き渡すデータ項目を最少に§ マスタ等のコード体系に依存させない
▪ URI sheme:code 方式も一つの方法
§ 運用条件▪ どちらがいつ停止・再起動しても良いように
§ 非同期メッセージング▪ 応答待ちにしない
▪ Fire and Forget
¡ データ型、データ構造に依存させない§ 文字列表現§ (ゆるやかな)XML または Key-Value リスト§ 決め事は単純、明快に。文書化は必須。
¡ 利用者のやりたいことに興味を持つこと¡ 現実の制約を正しく理解すること
¡ 本来の目的に、いつも立ち返ること
ハードルは高いが、整合性維持、システム間連携の潜在メリットは大きいことも事実。
技術論だけでなく、関係者を巻き込んだ、整合性維持戦略の策定と実施に、チャレンジする志は持ちたい
¡ 利用者の課題解決の役に立つソフトウェアを開発しましょう。
¡ それが、私たちのミッションだから。
¡ そのために、
§ 利用者のやりたいことに興味を持ちましょう。
§ モデリングと設計のスキルを磨きましょう。