DDD 20121106 SEA Forum November
-
Upload
- -
Category
Technology
-
view
3.340 -
download
3
description
Transcript of DDD 20121106 SEA Forum November
2012年11月6日(火) 有限会社 システム設計 代表取締役 増田 亨 Twitter @masuda220 ブログ システム設計日記
SEA Forum November
ドメイン駆動設計の めざすところ
実践の基本
より深く実践する
より大規模に実践する
利用者の関心事の理解 意思疎通 モデルと実装の一致
ドメイン層の分離・独立 ドメインオブジェクトの設計パターン
利用者の関心事を踏み込んで理解する 深い理解(=モデルの進化)の手がかり
大きなモデルを分割する 整合性維持の戦略
今日の話で触れる箇所 まえがき(xixページ)で著者が推奨している
▪ 第1部の導入文と第1章 ▪ 2章、3章、9章、14章
基本テクニック ▪ 4章、5章、6章
それ以外はほとんど触れません。あしからず。
自己流の経験談 ▪ 実装技術 :Java, Spring, MyBatis, Velocity … ▪ 開発プロセス:RDRA, ICONIX (もどき?)
DDDのちゃんとした(?)ガイドではありません。あしからず。
序文、まえがき 第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 Design 4章、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 Bind Bean Validation
Velocity テンプレート
Spring ORM
MyBatis SQLマップ
Apache James
ActiveMQ Mule ESB
Spring Web Flow
Spring フレームワークはドメイン駆動設計を意識している。
初日からドメインモデリング コンテキスト図(全体図)を描きながらドメイン層の
パッケージ図を描き始める
毎日なんらかのドメインモデリング (概要)業務フロー ▪ 業務のステップごとに要望事項など利用者の関心事を記述 ▪ でてくる言葉をドメインクラス図に反映
(詳細)ユースケース記述とロバストネス分析 ▪ ドメインクラス図を成長させる
(実装)そのままクラス名、メソッド名に ▪ ドメイン層以外のコードもドメイン層の名前を参照する(依存
関係)
システム外部環境
業務フロー図
概念モデル の洗練
関連クラス 依存クラス
画面・帳表 ユースケース
属性追加
システム境界
ドメインモデル
イベント 状態遷移
データモデル
システム価値
初期の 概念モデル
コンテキスト図
パッケージ構造 中核クラス
クラスの設計と実装
ロバストネス図
システム (ICONIX)
シーケンス図
操作追加
Java ソースコード
基盤クラス追加
ユースケースごとに開発
DDL/SQLソースコード
要件分析/要件定義
クライアント オブジェクト
依頼 協力する オブジェクト
サービス提供 能力
判断能力
情報の保持
他のオブジェクト と関連の保持
クライアントができるだけ楽をするように設計する
必読: ワーフスブラック 「オブジェクトデザイン」 1章 設計コンセプト
全体
部品A 部品N
部品群の構造化 <<structurer>>
情報保持 <<information holder>>
サービス(演算)提供 <<service provider>>
制御役 <<controller>>
調整役 <<coordinator>>
If/for を 持つ/持たない の違い
外部への見せ方 <<interface>>
Whole-Part に分解し、 それぞれのオブジェクトの役割を、単純に、明確にする
会員登録でメールアドレスが必要。
アドレス形式チェック。
存在しないアドレスを拒否。
フリーメールは不可。
拒否するフリーメールのドメイン名リスト。
Biglobe はサブドメイン方式。
携帯メールも不可。
個々の関心事を小さな部品で表現する やりたい事の追加や変更=部品の追加・入替え
日付 (時分秒を持たない) 時分(秒を持たない) 翌営業日, 休前日 月末,月初, 四半期, 半期, 年度 期間 有効期限 予定日 期限切れ一週間前のアラート 前日のリマインダ …
Date, String, BigDecimal, Long, …
プリミティブな型をラッピングした小さな部品に
業務に必要なデータとロジックをカプセル化
金額 単価 数量,数量単位,換算 消費税,税率,端数処理 合計,小計,総合計 数量割引 キャンペーン価格 季節料金 キャンセルポリシー …
管理番号,登録番号 取引先コード 取引区分 契約番号 商品番号 型式コード 製造番号 シリアルナンバー …
情報保持役
調整役
サービス提供役
構造保持役
情報保持役
制御役
サービス提供役 情報保持役
情報保持役
インタフェース役 インタフェース役
インタフェース役
サービス提供役 サービス提供役
小さく(50行以下) 役割が明確な オブジェクトが 小数の隣人と協力する
大きな部品 10以上のimport文 5以上のインスタンス変数 10行以上の長いメソッド 100行を超えるクラス
データ入れ物クラス getter/setter だけ
ひとつの部品(クラス)が
いろいろ知っていて、
なんでもやりたがる
get get get
set set set
業務の構造や業務ルールの理解が不十分。 よく分からないまま作った、とりあえずの置き場所(クラス、パッケージ)に、なんでも突っ込んでいく(偶発的凝集)
OOエクササイズ 9つの簡単なルール
メソッドの構成 オブジェクト間の特性の移動 データの再編成 条件記述の単純化 メソッド呼び出しの単純化
実装の哲学
ドメインの理解 言葉の力 モデル駆動
オブジェクト 設計スタイル 役割ステレオタイプ 小数の隣人と協力
For Thoughtful Developer Leading Designer 小さく作る練習
クラス 振る舞いとメソッド 状態とコレクション
テクニック
1.ひとつのメソッドのインデントは1段階まで 2.else 句 を使わない 3.すべてのプリミティブ、文字型をラッピング 4.ファーストクラスコレクションを使う 5.1行につき、ドットはひとつ 6.名前は省略しない 7.クラス50行、パッケージ10ファイルまで 8.インスタンス変数は2つまで 9.getter/setter を使わない
slideshare: オブジェクト指向できていますか? http://www.slideshare.net/MoriharuOhzu/ss-14083300 オブジェクト指向エクササイズのススメ http://www.slideshare.net/yojik/ss-1033616 オブジェクト指向の設計と実装 学び方のコツ http://www.slideshare.net/masuda220/ss-14263541
Associations 関連:できるだけ限定する
Entities (key) 利用者の関心事の識別と追跡
Value Objects (value) 関心事の内容や値の表現
Domain Events 業務イベント(記録・通知の単位)
Services 業務ルールや手順という関心事の表現
Modules 関心事のグルーピングと分割
※書籍の後で追加されたパターン
ドメインモデリングの基本ツール ▪ Whole-Part でクラスの役割を単純にすると、小さなクラスが増える
▪ それを「パッケージ」でカプセル化
▪ 全体をクラス間ではなくパッケージ間の関係で整理し把握する
募集 応募 選考
共通(日付・期間など)
関連は、ぎりぎりまで単純にする 双方向 → 単方向 多対多 → 1対多 → 1対1 (限定子) 参照 → 利用 ほんとうに必要か? アンチパターン ▪ モデル上の「関係」と、コードが一致していない ▪ 例:双方向・多対多を本当に実装するか?
関連を限定するほど、重要な関係・構造が明確になる
業務の基本語彙の実装パターン String, BigDecimal, Date(long) のラッパー 型宣言 → 表現力の向上 ▪ 連絡先、期間、金額、数量、登録日、締切日…
不変 → 振る舞いの安定
▪ コンストラクタで、すべて情報をセット ▪ set メソッドなし ▪ 演算結果は、新たにオブジェクトを生成して返す ▪ 参考:String の振舞
利用者が関心事をどう識別するか知っているクラス 受注番号、契約番号、…. 番号+名前が基本 ▪ 人間が理解・識別する情報 ▪ 内部的な シーケンス番号や、UUID ではない ▪ 一覧画面の表示項目やソート順とも関係する
その他の情報保持は他のクラスに委譲
契約 二者間の約束事 注文、申し込み、予約、…
トランザクション ( Domain Event ) 業務の処理単位
▪ 記録/通知 起票と記帳
▪ 「伝票」と「台帳」(残高更新) 人、組織 経済活動の主体(意思決定、責任)
モノ 売買の対象 金銭評価の対象
場所
部分 全体
場所 地域
条項 契約
予定作業 計画
メンバー グループ
ルール ポリシー
後続イベント イベント
物品 品種
個別取引 複合取引
コレクションは隠蔽する List<顧客> を顧客一覧クラスにラッピング 必要最小限のメソッド(業務の関心事)のみ提供 公開する場合も不変のコピーを渡す
顧客一覧
顧客数() 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
Aggregates 業務上、いっしょに扱うかたまり
Factories 情報生成時に固有の関心事/ルール
Repositories
「記録」という関心事
Transfers 「伝達」という関心事(追加)
利用者が、扱いたい情報の単位は? 変更のタイミングや頻度が同じ情報の「かたまり」は?
その「かたまり」を利用者は、どう呼んでいるか?
アンチパターン なんでも知っている巨大 Aggregate/巨大テーブル 利用者は、利用シーンに応じて、もっと小さ
い単位で情報を扱っている
アンチパターン Insert, update, delete
利用者の言葉で表現する/使い分ける 登録、追加、新規作成、… 改訂、訂正、更改、... キャンセル、取消、廃止、停止、…
ドメイン層を独立させる ドメイン層でインタフェース宣言 ▪ データアクセス層の存在・実装を知らない
データアクセス層で実装
▪ドメイン層(のインタフェース)に依存する
利用者の言葉で表現 通知、連絡、… 依頼、指示、… 送付、転送、回覧、…
ドメイン層を独立させる ドメイン層でインタフェース宣言 データアクセス層で実装
実装手段 電子メール RESTful スタイルの Web サービス メッセージングサービス ファイル転送 共有データベース
ごった煮コード ドメイン層と他の層のごった煮
トランザクション・スクリプト 手続き的な記述への執着
どこでも業務ロジック
UI、SQL、トリガーなどに業務ロジックを分散して記述
ドメインオブジェクト getter/setter 大忙し 役割分担の失敗、緊密すぎる協調
利用者のやりたいことに興味を持つこと ドメイン層の独立 ドメイン層に業務の知識、ルールを集約 ソフトウェアの設計原則を丁寧に実践する
関心の分離
カプセル化
小さなオブジェクトがごく少数の隣人と協力
抽象(ドメインモデル)に依存する
第3部 Refactoring Toward Deeper Insight 9章 隠れた概念を発掘し、明示する
最初は表面的なモデル とりあえず(表面的には)動くことは動く どこかぎこちない(利用者がしっくりきていない) 変更に弱い、副作用が多い
深いモデルを探究する動機 利用者の問題解決に、もっと役にたつソフトウェアにする 変更を、もっと簡単に、安全にする 業務都合による変更依頼が予測できる 利用者の期待以上の提案ができる
地道で継続的な努力 深いモデルにたどり着くには、モデリング・設計・実装の基本テクニックを、地道に繰り返すこと
短期決戦・作り逃げプロジェクトとは別の世界。
既存のモデルやコードの中から新しい切り口のクラス(パッケージ、メソッド、フィールド)候補が見つかる
モデルに新しい名前が登場 その言葉を使ってみると、会話がスムースになる いままでの疑問、違和感が一気に解消する
ごちゃごちゃしたコードがすっきりする クライアント側オブジェクト
▪ 面倒なことはすべて委譲 サービス提供側オブジェクト
▪ 前処理、後処理、条件分岐等が少ないシンプルなコード
職務経歴 ▪ 最低ひとつは記述が必要
最初の実装 ▪ 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>> 実行可能イベント
▪ あるいは State パターンで実装 課題 利用者は、そういう視点で業務をとらえているか?
▪ 意思疎通の手段として疑問。 通常の遷移/例外的な遷移/レアケースなどの業務感覚をモデルに盛り込んでいく努力。
状態マシンは無限ループ構造になりやすい ▪ 業務上はなんらかの許容範囲/限界があり、注意喚起などが必要
How より What ファウラー「リファクタリング」 ドメイン(業務、業種)のハンドブックや解説本
の利用
expireDate.add(-1);
expireDate.previousDay();
expireDate.dayOfFinalAlert ();
当初の要件:期限切れの前日にアラートメールを送る
アラートメールを送るタイミングの変更
宿泊予約
料金()
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 Design 14章 (大規模な)モデルの整合性を維持する
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 リスト 決め事は単純、明快に。文書化は必須。
利用者のやりたいことに興味を持つこと 現実の制約を正しく理解すること 本来の目的に、いつも立ち返ること
ハードルは高いが、 整合性維持、システム間連携のメリットは大きいことも事実。 技術論だけでなく、関係者を巻き込んだ、整合性維持戦略(投資判断)の策定と実施に、チャレンジする志は持ちたい
利用者の課題解決の役に立つソフトウェアを開発しましょう。
それが、私たちのミッションだから。
そのために
利用者のやりたいことに興味を持ちましょう。
モデリングと設計のスキルを磨き続けましょう。