SlideShare a Scribd company logo
ドメイン駆動設計の実践


 リッチなドメインモデル
   名前探しの旅
         Java-ja DDD
       2013年3月22日
    有限会社 システム設計 増田
Domain-Driven Design (DDD)

 ドメイン駆動設計
ドメイン駆動設計への道
               設計の改善                         ドメインの理解
              ・メソッドの構成
オブジェクト指向      ・オブジェクト間の特性移動   設計のスタイル        言葉の力
基礎訓練          ・データの再編成                       モデル駆動
              ・条件記述の単純化          責任駆動設計
エクササイズ        ・メソッド呼び出しの単純化      役割ステレオタイプ
9つのルール
 小さく作る




                                  責任割当の原則
                                  GRASP




                                             For
  実装の原則                                      Thoughtful Developer
 ・クラス                                        Leading Designer
 ・振る舞いとメソッド
 ・状態とコレクション                     契約による設計
ドメイン駆動設計への道
                                シンプルな
                             トランザクションスクリプト
                リッチな
大きな           トランザクション
泥団子             スクリプト       リッチな
                シンプルな      ドメインモデル
               ドメインモデル

アーキテクチャなし
汎用データ型        テーブルと対応した
                           業務の言葉で組み立てる
汎用命名ルール       ドメインオブジェクト
                           小さなオブジェクト
(ドメインの言葉なし)   (データの入れ物)
                           役割を単純に
                           ばらばらに
ドメインモデルの開発
部品探しの旅   イテレーティブで発見的な活動
名前

     モデリング
             プログラミング

     リファクタリング
プログラミング
        は

    名前さがし
名前に手を抜けば、ひどい設計になる。

名前にこだわれば、良い設計になる。
クラス名      名前
 メソッド名      テーブル名    カラム名
                    スキーマ名
パッケージ名
 フィールド変数名          メッセージキュー名

 業務の言葉で
パラメータ名        ドメイン名

  埋め尽くす
 ローカル変数名
             パス名
                   サーバー名
                   ホスト名
   id属性   name属性    class 属性
業務の言葉をオブジェクトで
 日付 (時分秒を持たない)          金額               管理番号,登録番号
 時分(秒を持たない)             単価               取引先コード
 翌営業日, 休前日              数量,数量単位,換算       取引区分
 月末,月初, 四半期, 半期, 年度     消費税,税率,端数処理      契約番号
 期間                     合計,小計,総合計        商品番号
 有効期限                   数量割引             型式コード
 予定日                    キャンペーン価格         製造番号
 期限切れ一週間前のアラート          季節料金             シリアルナンバー
 前日のリマインダ               キャンセルポリシー        …
 …                      …

プログラミング言語の基本データ型 (Date,String, BigDecimal, Long, …)
    業務の基本用語ごとのオブジェクトに、
をラップした

その業務用語に関するデータとロジックをまとめる。

  超重要         ファンダメンタルなオブジェクト
ドメインオブジェクト

              設計パターン
ユースケースの実装
                     シンプルなトランザクションスクリプト


                                                                    Policy
基本の         Event   Repository        Transfer        Reference    (判断)
 部品        (出来事)      (記録)             (通知)            (参照)        (制約)



  日付       予定日      場所           商品種類                   単価
                                             部門
                      地域          形状                      数量      ここが
      期間                                         役割     税率
            翌月      拠点                                            育つほど
                                 型式        担当者                    楽になる
  有効期限                                                      端数
                 キャンペーン

 超重要           ファンダメンタルなオブジェクト
役に立つ
ドメインオブジェクト
 良い名前
 小さく作る
 ばらばらに
良い名前の見つけ方
語彙を増やす
              名前の宝庫(初日に見つける)
              ・その分野のガイドブック
              ・類似サービスのヘルプ画面
              ・類似パッケージソフトのカタログ
  読む/調べる      (英語版ならクラス名の宝庫)


  聴く/尋ねる      頻度、重要度、関心度、…



正しく使う(言葉を使って相手の反応をみる)
言葉を組み合わせてみて反応をみる
似た言葉を使い分けて反応をみる
小さく作る
クラス     50行以内
メソッド    3行以内
パッケージ   10ファイル以内

これを超えたら、
分割を考える習慣をつける。
3行メソッド
register( order )
{
    verify( order );
    record( order );
    notifyTo(shippingSection);
}
       こういうのが良い感じ
ドメインオブジェクト

実践の小技
How より What
汎用部品を専用部品に

  if を使わない
 for を使わない

setter を使わない
getter を使わない
How        より   What
expireDate.add(-1);

expireDate.previousDay();

expireDate.dayOfFinalAlert ();
                      業務の言葉の登場
汎用部品     を   専用部品に
String             AreaCode
Long               EntryNumber
BigDecimal ラッピング   Amount
Date               ExpireDate
List<Appoint>      Appointments

  なんでも屋             目的特化
 どこでも使える           業務固有の言葉
if を使わない
強力
     enum タイプごとに異なる振る舞いを、どこにも、If 文なしで記述
     strategy/state パターン
     Missing Object パターン
                    (null object)
     Map,Set
強力
                      If 文なしで必須/範囲/形式のチェック。
     Bean Validator   入力値だけでなくロジック内部でも使える。


              契約による設計 (防御的プログラミングと逆の発想)
     Assert   assert date != null : “有効な日付のみ” ;
              前提条件は表明するだけ。 if 文では書かない。
定石   for を使わない
 ファーストクラスコレクション
     コレクション操作ロジックの置き場所
     new Appoints( List<Appoint> )

 Collection フレームワーク API の復習
     TreeMap, LinkedHashSet, Deque,…

 ひと手間かければ、for/if いらず
     Comparable の実装
     Comparator の実装
     equals()/hashCode() の override
setter を使わない
定石

完全コンストラクタ
     Value Object パターン
     生成時に必要な値をすべてセット
     new Money( amount, currency );


setXXX() で状態を変えない
    ・新しいオブジェクトを作る
     ・ライフサイクルの短いオブジェクトの導入
      (状態を固定できるまで細分化)
getter を使わない
@Deprecated
   フレームワークは使っていいよ
   アプリケーションでは使っちゃだめよ

get したいときは、役割分担がおかしい。
    ロジックの移動  (データにロジックを寄せる)
    フィールドの移動 (ロジックにデータを寄せる)
ドメインオブジェクトは
ばらばらにしておく
 実践の小技
構造の変更に備える習慣
  構造は安易にコードに埋め込まない。
  初期の構造はまちがっていることが多い。
  構造の変更を簡単にする準備をしておく。


委譲メソッド
  面倒でも隣人とだけ話す
  × person.contactInfo().phones().mobile()
  ◎ person.primaryContact()

実装継承                   控え目に。もっと控えめに。
パッケージ階層               フラットに。もっとフラットに。
パッケージスコープを好む
public 宣言
   控え目に。もっと控えめに。
      パッケージスコープにできないか?
      パッケージの依存関係に改善の余地は?


import 文
   少なく。もっと少なく。
      クラスの分割が必要では?(責任の持ちすぎ)
      パッケージの依存関係の改善の余地は?
役に立つ
ドメインオブジェクト
ドメインオブジェクト

              設計パターン
ユースケースの実装
                     シンプルなトランザクションスクリプト


                                                                    Policy
基本の         Event   Repository        Transfer        Reference    (判断)
 部品        (出来事)      (記録)             (通知)            (参照)        (制約)



  日付       予定日      場所           商品種類                   単価
                                             部門
                      地域          形状                      数量      ここが
      期間                                         役割     税率
            翌月      拠点                                            育つほど
                                 型式        担当者                    楽になる
  有効期限                                                      端数
                 キャンペーン

 超重要           ファンダメンタルなオブジェクト
 良い名前
 小さく作る
 ばらばらに
Domain-Driven Design (DDD)

 ドメイン駆動設計

More Related Content

リッチなドメインモデル 名前探し

  • 1. ドメイン駆動設計の実践 リッチなドメインモデル 名前探しの旅 Java-ja DDD 2013年3月22日 有限会社 システム設計 増田
  • 2. Domain-Driven Design (DDD) ドメイン駆動設計
  • 3. ドメイン駆動設計への道 設計の改善 ドメインの理解 ・メソッドの構成 オブジェクト指向 ・オブジェクト間の特性移動 設計のスタイル 言葉の力 基礎訓練 ・データの再編成 モデル駆動 ・条件記述の単純化 責任駆動設計 エクササイズ ・メソッド呼び出しの単純化 役割ステレオタイプ 9つのルール 小さく作る 責任割当の原則 GRASP For 実装の原則 Thoughtful Developer ・クラス Leading Designer ・振る舞いとメソッド ・状態とコレクション 契約による設計
  • 4. ドメイン駆動設計への道 シンプルな トランザクションスクリプト リッチな 大きな トランザクション 泥団子 スクリプト リッチな シンプルな ドメインモデル ドメインモデル アーキテクチャなし 汎用データ型 テーブルと対応した 業務の言葉で組み立てる 汎用命名ルール ドメインオブジェクト 小さなオブジェクト (ドメインの言葉なし) (データの入れ物) 役割を単純に ばらばらに
  • 5. ドメインモデルの開発 部品探しの旅 イテレーティブで発見的な活動 名前 モデリング プログラミング リファクタリング
  • 6. プログラミング は 名前さがし 名前に手を抜けば、ひどい設計になる。 名前にこだわれば、良い設計になる。
  • 7. クラス名 名前 メソッド名 テーブル名 カラム名 スキーマ名 パッケージ名 フィールド変数名 メッセージキュー名 業務の言葉で パラメータ名 ドメイン名 埋め尽くす ローカル変数名 パス名 サーバー名 ホスト名 id属性 name属性 class 属性
  • 8. 業務の言葉をオブジェクトで 日付 (時分秒を持たない) 金額 管理番号,登録番号 時分(秒を持たない) 単価 取引先コード 翌営業日, 休前日 数量,数量単位,換算 取引区分 月末,月初, 四半期, 半期, 年度 消費税,税率,端数処理 契約番号 期間 合計,小計,総合計 商品番号 有効期限 数量割引 型式コード 予定日 キャンペーン価格 製造番号 期限切れ一週間前のアラート 季節料金 シリアルナンバー 前日のリマインダ キャンセルポリシー … … … プログラミング言語の基本データ型 (Date,String, BigDecimal, Long, …) 業務の基本用語ごとのオブジェクトに、 をラップした その業務用語に関するデータとロジックをまとめる。 超重要 ファンダメンタルなオブジェクト
  • 9. ドメインオブジェクト 設計パターン ユースケースの実装 シンプルなトランザクションスクリプト Policy 基本の Event Repository Transfer Reference (判断) 部品 (出来事) (記録) (通知) (参照) (制約) 日付 予定日 場所 商品種類 単価 部門 地域 形状 数量 ここが 期間 役割 税率 翌月 拠点 育つほど 型式 担当者 楽になる 有効期限 端数 キャンペーン 超重要 ファンダメンタルなオブジェクト
  • 12. 良い名前の見つけ方 語彙を増やす 名前の宝庫(初日に見つける) ・その分野のガイドブック ・類似サービスのヘルプ画面 ・類似パッケージソフトのカタログ 読む/調べる (英語版ならクラス名の宝庫) 聴く/尋ねる 頻度、重要度、関心度、… 正しく使う(言葉を使って相手の反応をみる) 言葉を組み合わせてみて反応をみる 似た言葉を使い分けて反応をみる
  • 13. 小さく作る クラス 50行以内 メソッド 3行以内 パッケージ 10ファイル以内 これを超えたら、 分割を考える習慣をつける。
  • 14. 3行メソッド register( order ) { verify( order ); record( order ); notifyTo(shippingSection); } こういうのが良い感じ
  • 16. How より What 汎用部品を専用部品に if を使わない for を使わない setter を使わない getter を使わない
  • 17. How より What expireDate.add(-1); expireDate.previousDay(); expireDate.dayOfFinalAlert (); 業務の言葉の登場
  • 18. 汎用部品 を 専用部品に String AreaCode Long EntryNumber BigDecimal ラッピング Amount Date ExpireDate List<Appoint> Appointments なんでも屋 目的特化 どこでも使える 業務固有の言葉
  • 19. if を使わない 強力 enum タイプごとに異なる振る舞いを、どこにも、If 文なしで記述 strategy/state パターン Missing Object パターン (null object) Map,Set 強力 If 文なしで必須/範囲/形式のチェック。 Bean Validator 入力値だけでなくロジック内部でも使える。 契約による設計 (防御的プログラミングと逆の発想) Assert assert date != null : “有効な日付のみ” ; 前提条件は表明するだけ。 if 文では書かない。
  • 20. 定石 for を使わない ファーストクラスコレクション コレクション操作ロジックの置き場所 new Appoints( List<Appoint> ) Collection フレームワーク API の復習 TreeMap, LinkedHashSet, Deque,… ひと手間かければ、for/if いらず Comparable の実装 Comparator の実装 equals()/hashCode() の override
  • 21. setter を使わない 定石 完全コンストラクタ Value Object パターン 生成時に必要な値をすべてセット new Money( amount, currency ); setXXX() で状態を変えない ・新しいオブジェクトを作る ・ライフサイクルの短いオブジェクトの導入 (状態を固定できるまで細分化)
  • 22. getter を使わない @Deprecated フレームワークは使っていいよ アプリケーションでは使っちゃだめよ get したいときは、役割分担がおかしい。 ロジックの移動 (データにロジックを寄せる) フィールドの移動 (ロジックにデータを寄せる)
  • 24. 構造の変更に備える習慣 構造は安易にコードに埋め込まない。 初期の構造はまちがっていることが多い。 構造の変更を簡単にする準備をしておく。 委譲メソッド 面倒でも隣人とだけ話す × person.contactInfo().phones().mobile() ◎ person.primaryContact() 実装継承 控え目に。もっと控えめに。 パッケージ階層 フラットに。もっとフラットに。
  • 25. パッケージスコープを好む public 宣言 控え目に。もっと控えめに。 パッケージスコープにできないか? パッケージの依存関係に改善の余地は? import 文 少なく。もっと少なく。 クラスの分割が必要では?(責任の持ちすぎ) パッケージの依存関係の改善の余地は?
  • 27. ドメインオブジェクト 設計パターン ユースケースの実装 シンプルなトランザクションスクリプト Policy 基本の Event Repository Transfer Reference (判断) 部品 (出来事) (記録) (通知) (参照) (制約) 日付 予定日 場所 商品種類 単価 部門 地域 形状 数量 ここが 期間 役割 税率 翌月 拠点 育つほど 型式 担当者 楽になる 有効期限 端数 キャンペーン 超重要 ファンダメンタルなオブジェクト
  • 29. Domain-Driven Design (DDD) ドメイン駆動設計