ドメイン駆動設計 基本を理解する

134
ドメイン駆動設計 基本を理解する 増田亨(@masuda220) ギルドワークス株式会社 取締役 有限会社システム設計 代表 2016年3月18日(金) 1

Upload: -

Post on 16-Apr-2017

24.494 views

Category:

Software


0 download

TRANSCRIPT

ドメイン駆動設計基本を理解する

増田亨(@masuda220)

ギルドワークス株式会社 取締役

有限会社システム設計 代表

2016年3月18日(金)

1

本日の内容

• ドメイン駆動設計の「考え方」• 「まえがき」を中心に

– オブジェクト指向、エクストリームプログラミング

• ドメイン駆動設計の「3つの原則」• 1章 2章 3章から

– ドメイン知識の習得、言葉による意図伝達、コードで表現

• ドメイン駆動設計の「基本スキル」• 4章 5章 6章 7章から

– ドメイン層の隔離、ドメインオブジェクトの設計、総合演習

2※「基本スキル」は、時間が足りなくなる見込み。あらかじめご了承ください。

はじめに

3

そんな人のためにこの本の要点を

実践経験をまじえながら紹介します

⇒読み解くのが困難⇒実践でどう活用するか迷っている⇒やってみたがうまくいかない

4

5

• 出会ったのは10年前

–よくわからなかった

• 現場で取り組み始めて8年–8つの開発プロジェクト

–4つの現場コーチ

ドメイン駆動設計の手ごたえ

• 業務を学びながらソフトウェアを開発する面白さ

• ソフトウェアが育っていく楽しさ

• 業務知識とコードが一致している時のコードのわかりやすさ

• 変更が楽で安全になる気持ちよさ

• 正しい仕事をしている安心感

6

ドメイン駆動設計のハードル

• 発想の転換– 「技術」駆動から「ドメイン」駆動へ

– 「優れた設計」の基準の変化

• 設計・開発手法の切り替え– オブジェクト指向へ

– エクストリームプログラミングへ

• 実装の制約との戦い

– フレームワークやプログラミング言語の制約

7

ドメイン駆動設計の考え方

「まえがき」から

8

「ドメイン駆動設計」とは

厳しい現実の中で、ソフトウェア設計を習得しようと奮闘してきた技術者の物語。

不完全な状況の中で、抽象的な設計原則を、現実のソフトウェアに適用するための助言。

「日本語版への序文」 by エリック・エヴァンス

9

エヴァンスが取組んだ技法

オブジェクト指向

エクストリームプログラミング

10

想定読者

• オブジェクト指向とエクストリームプログラミングに、ある程度の知識がある技術者

• オブジェクト指向とエクストリームプログラミングの原則を、実際のアプリケーション開発に適用しようとして、理屈通りにいかないことを経験した技術者

「まえがき」

11

オブジェクト指向

エクストリームプログラミング

12

私が「ドメイン駆動設計」を初めて読んだ時は、DOA/手続き型/ウォータフォール系の技術者。OOもXPもある程度の知識はあったが未経験。

「ドメイン駆動設計」を読んでもわからない所がいっぱいあった。

でも「実践的でかつ優れた設計」の香りを感じた。

「オブジェクト指向」と「エクストリームプログラミング」を勉強しながら、現場でいろいろ挑戦しているうちに「ドメイン駆動設計」の考え方とやり方がだんだんと理解できるようになった。

勉強になる本

Wabi Sabiを読み解く

オブジェクト指向へ エクストリームプログラミングへ

13

ソーシャルチェンジソフトウェアの構造と工法の転換

オブジェクト指向

エクストリームプログラミング

成長と変化を続ける創発型のソフトウェア開発

この3つの底流にある共通の考え方・価値観

14

ドメイン駆動設計

オブジェクト指向の「変更容易性」

エクストリームプログラミングの「変化適応性」

• 「ドメイン駆動設計」も「エクストリームプログラミング」も、「オブジェクト指向」のコミュニティで生まれ育った

• オブジェクト指向の「変更容易性」が「創発型」の開発をうみだす

• 3つは相互に補強しあう

創発型のソフトウェア開発

15

ドメイン駆動設計の「成長を続ける」ソフトウエア

オブジェクト指向「変更容易性」の工夫

16

ドメイン駆動設計の土台となる技術

オブジェクト指向の「変更容易性」

• 抽象データ型

– 人間の知りたいこと/やりたいことを定義する

• 内部の実装(データ型と処理手続き)は見せない

• モジュール構造

– 抽象データ型を部品として全体を組み立てる

• 「機能」や「手続き」を部品の単位にしない

17

抽象データ型

18

抽象データ型の例 : Java 標準API

19

抽象データ型インタフェース

知りたいこと/やりたいこと内部に隠された

データ型

String文字列

isEmpty()substring()

split()...

char[] valueint count

BigInteger任意精度の整数

add()subtract()multiply()

….

int[] valueint signum

LolcaDate日付

isBefore()isAfter()

plusDays()...

int yearshort month

short day

ArrayList配列

isEmpty() add()

contains()…

Object[] dataint size

LocalDate

「日付」を汎用的に扱うクラス

int year;short month;short day;

LocalDateの内部

DateOfBirth

「誕生日」に特化したクラス

人間の関心事を表現する抽象データ型を定義する

実装技術

もっと抽象化人間の関心事に近づける

Boolean 今月が誕生月()Days 誕生日まであと何日()

plusDays(long days)plusMonths(long months)

20

Java言語仕様基本データ型

Java標準API汎用の抽象データ型

ドメインオブジェクト

if( day > 31 ) … ;

抽象データ型による「変更容易性」

• 人間の関心事と、プログラミングの単位が一致

– どこに何が書いてあるかわかりやすい

– 関心事の変更と、コードの変更箇所が1対1に対応

• 変更がコードのあちこちに飛火しなくなる

• 実装(内部のデータ構造やロジック)を隠す

– データ構造やロジックを変更しても外部に波及しない

– 変更した時の影響範囲を局所に限定できる

21

モジュール構造と変更容易性

22

アンチパターン

機能単位にモジュール化

機能単位のモジュール化機能クラスAと、機能クラスBに、同じデータを扱うロジックが重複する変更時に、読む範囲が広がり、変更箇所が増え、テスト範囲が広がる

23

ビューコントローラサービスデータアクセス…

ビューコントローラサービスデータアクセス…

カプセル化をしているが単なるデータ構造体

抽象データ型によるモジュール化

抽象データ型:◎知りたいこと/やりたいことだけを公開◎内部のデータ構造やロジックは見えない◎判断・計算・加工のロジックが一箇所に集まる◎変更時に、一箇所を読み、一箇所を変更し、一箇所テストする

24

オブジェクト指向への道

• 抽象データ型を設計するスキルを磨く

• 抽象データ型の「利用者」から「生産者」になる– LocalDateを使って、年齢を計算するロジックを書い

てみる(利用者)

– LocalDateを持つDateOfBirthクラスを作って、年齢の計算ロジックを内側に隠す(生産者)

– DateOfBirthクラスを利用してみる(利用者)

– 使ってみた感触を元に、DateOfBirthクラスを改良する:コンストラクタの追加とか、今月が誕生月かの判定とか、… (生産者)

25

オブジェクト指向への道

• アンチパターンへの気づき– 言語の基本データ型(int, boolean, [], … ) と、標準API

( LocalDate, BigDecimal, ArrayList, … ) に執着したプログラミング– 「変数名」で意図を表現するプログラミング– コードの重複に無頓着なプログラミング

• 処方箋– 基本データ型、標準APIのクラスをラップした独自の抽象デー

タ型を定義して利用することを習慣にする

– 変数名ではなく、「型(クラスとインタフェース)」と「メソッド名」で意図を表現することを習慣にする

– コードの重複を減らして、変更が楽で安全になる設計を習慣にする

26

ドメイン駆動設計への道

• 業務の関心事を抽象データ型として表現する• 「顧客」クラス

• 「商品」クラス

• 「注文」クラス

• 「数量」クラス

• 「期日」クラス

• 業務の「知りたいこと」「やりたいこと」をクラス名とメソッド名で表現する

• 実装の詳細は意識しない/させない

– 内部のデータ構造とロジックを見せない/推測しない

27getter/setter を使わない

「変化に適応する」ソフトウェア開発

28

エクストリームプログラミング

ドメイン駆動設計の土台となる技術

「適応型」のソフトウェア開発開発

スタイル方法論

ソフトウェアの最終形

開発サイクル

予測型ウォータフォール

事前に厳密に定義固定する 分析/設計/製造

反復・漸進型

RUPそれなりに定義

反復ごとに精緻化

方向付/推敲/作成/移行

各フェーズで分析/設計/製造を、N回「反復」する

適応創発型

XPざっくりと定義

日々更新日、週、四季

(人間の生活リズム)

29

フェーズに分けない

• 分析・設計・実装を「毎日」やる

• 分析・設計・実装を「同じ人」がやる

• なぜ「毎日」やるのか?– 効率的だから

• 経験をもとに次の行動を決めたほうが、予測し事前準備するより費用対効果が高い

• なぜ「同じ人」がやるのか?– 効率的だから

• 伝言ゲームをなくせる

• 同じ人がやるとドキュメントの必要性が激減

30

毎日、少しずつ成長する

• 最終の着地点と、現在の進行方向を確認しながら進む– 何か新しいことが起きていないか、「毎日」見直す

– 進む方向がずれていないか、「毎日」見直す

– 「週」で見直す、「季節」で見直す

• 人も、ソフトウェアも、事業も、毎日/毎週/春夏秋冬で、少しずつ成長する

• それが自然で理にかなったやり方– 長続きする

– 人間らしく暮らせる31

エクストリームプログラミングへの道

• 効率を追求する

– 専門家による分業が効率的か

– コードを書かずに図やドキュメントの作成に時間をかけることが効率的か

– ドキュメントのレビューと承認に時間をかけることが効率的か

– ルールを詳細に決めることが効率的か

– 会議を増やすことが効率的か

32

エクストリームプログラミングへの道

• 「変化」と「成長」を健全性の尺度にする

– 人、ドメインの理解、仕様、コード、…

– 変化と成長が止まるのは「異常」で「不健全」

• 変化を楽で安全にするためのスキルを磨く

– オブジェクト指向

– 抽象データ型によるモジュール化

33

34

OO+XP=DDD?

OO+XP=ドメイン駆動設計?

• YES !

• 「ドメイン駆動設計」は「オブジェクト指向」と「エクストリームプログラミング」の合わせ技

– エクストリームなオブジェクト指向プログラミング

• 「ドメイン駆動設計」は、OO+XPの考え方とやり方の「強調」する点をずらしている

by エリック・エヴァンス

35

「ドメイン駆動設計」が強調する点

• 「ドメインの知識」の継続的な学習

• 「言葉」を使った「モデリング」

• 「モデル」と「コード」を一致させる

この三つを重視してソフトウェアを開発するそれが「ドメイン駆動設計」

36

ドメインの知識をコードで表現

オブジェクト指向設計

インクリメンタルな設計(XP)

ドメイン駆動設計

37

ドメイン駆動設計

ドメインを分析する人がコードを書く

毎日、分析し、毎日、コードを書く

コードを書く人がドメインを分析する

分析・設計・実装を「フェーズ」に分けない分析・設計・実装の「担当者」を別にしない

分析と実装を、同じ人が毎日やるなら、ドキュメントは不要

オブジェクト指向/XP

38

保守の現場ではあたりまえ?

ドメインを学び学んだことを

コードで表現する

ドメイン駆動設計

39

オブジェクト指向/XP

第1部ドメインモデルを

機能させる

40

「ドメイン駆動設計」の3原則

• 第1章 知識をかみ砕く(ドメインを学ぶ)

• 第2章 コミュニケーションと言葉の使用

• 第3章 モデルと実装を結びつける

41

言葉の整理

• ドメイン

• ドメインとソフトウェア

• モデル

• ドメインモデル

42

ドメイン• ソフトウェアウェアを利用する人

たちの「活動」と「関心事」– ソフトウェアの利用は、活動全体の一部

– 関心事の焦点は、ビジネスや業務上の成果

• ドメインではないこと– ソフトウェアを作る活動

– コンピュータの仕組みや挙動

– 画面仕様書/機能一覧/ユーザーストーリー/…43

ドメインとソフトウェア

利用する人たちの活動と関心事

ソフトウェア

44

活動の目的/背景

活動の文脈

ソフトウェア

利用する人たちの活動と関心事

45活動の文脈まで視野を広げたほうが、ドメインを早く理解できる

モデル• 膨大な知識を「要約」した

シンプルでわかりやすい説明

• モデリングのスキル=「要約力」

–重要な要素を発見する力

–本質的でないものを削る力

–厳密に組み立てる力

ドメイン駆動設計を実践する勘所:「要約力」を磨く 46

ドメインモデル• ソフトウェアを利用する人たちの「活動」

と「関心事」の本質を簡潔に表したもの

• 表現

–チームでかわす会話

–ラフスケッチ

–コード

–(文章や図)

47

ドメインモデルを活用する

ドメインモデル

ドメインの「重要な関心事」を鋭く説明する

選び抜かれた重要な関心事をコードで表現する

会話を繰り返して「要点」を明確にする

「重要な語彙」をチームで合意する

1章2章3章

48

第1章

ドメインの知識をかみ砕く第3章

モデルと実装を結びつける

第2章

言葉を使った意図の伝達

第1章知識をかみ砕く

49

ドメインモデルを活用する

ドメインモデル

ドメインの「重要な関心事」を鋭く説明する

選び抜かれた重要な関心事をコードで表現する

会話を繰り返して「要点」を明確にする

「重要な語彙」をチームで合意する

1章2章3章

50

第1章

ドメインの知識をかみ砕く第3章

モデルと実装を結びつける

第2章

言葉を使った意図の伝達

第1章の基本メッセージ

51

ソフトウェアを作るためにはドメインを学び続けること

より広くより深く

最初は何もわかっていない

かろうじて聞き取れた言葉

52

知識の広がり

PCB設計者と会話をしながら聞き取れる語彙がちょっと増えてきた

53

ある程度理解できたら「モデル」が役に立つかコードで実験

だいぶ意思疎通ができるようになってきた段階のモデルPCB設計者の関心事をうまく説明し、かつ、設計として役に立ちそうか実験

54

本質的な関心事にたどり着いた深いモデル

PCB設計者の本質的な関心事をうまく説明しつつ、ソフトウェアの基本構造としてそのまま使える「深いモデル」 55

知識をかみ砕きながらモデルとコードを少しずつ成長させる

56

第1章 知識をかみ砕く

ソフトウェアを作るためにドメインを学び続ける

知識のないところから出発する

語彙を増やす(知識を広げる)

コードで表現して確認する

本質的な関心事を探求する(深く理解する)

57

第2章コミュニケーションと

言葉の使い方

58

ドメインモデルを活用する

ドメインモデル

ドメインの「重要な関心事」を鋭く説明する

選び抜かれた重要な関心事をコードで表現する

会話を繰り返して「要点」を明確にする

「重要な語彙」をチームで合意する

1章2章3章

59

第1章

ドメインの知識をかみ砕く第3章

モデルと実装を結びつける

第2章

言葉を使った意図の伝達

第2章の基本メッセージ

60

ソフトウェアを作るためにドメインの言葉を活用する

いつでもどこでも誰とでも

ユビキタス言語• ドメインの言葉を使う

– 技術用語を使わない

• いつでも、どこでも、誰とでも

– 技術者だけで話をする時もドメインの言葉で

– コードもドメインの言葉で

• 一つのチームに一つの言語

– 語彙

– 言い回し

61

一つのチームに一つの言語

• 一つ言葉を同じ意味で

– 要求仕様や画面に現れる「用語」と、ソフトウェアを利用する人たちが使う「言葉」の意味の食い違いに注意

• 一つの意味は同じ言葉で

– 同じ意味に思える「別の言葉」に敏感に

• 同じ言葉を使うチームが「境界づけられたコンテキスト(第14章)」を形作る

62

Not ユビキタス言語• フレームワークやプログラミングの用語は、ユ

ビキタス言語ではない– String や LocalDate はユビキタス言語ではない

– Boolean もユビキタス言語ではない

– Stream も Optional もユビキタス言語ではない

– null はユビキタス言語ではない

– Entity や Value Object はユビキタス言語ではない

• こういうものがドメイン層のクラスに表だって登場してはいけない

63

声に出してモデリングする• 良いモデルを見つける実践的な方法

– しゃべりにくい⇒良いモデルではない– 耳障りが悪い⇒良いモデルではない

• 言葉の不一致を手掛かりに適切なモデルを探す– もう一回しゃべる

同じ言葉、同じ言い回しにならない

– 会話にでてくる「話し言葉」と、コード/コミットログ/チャット/メールなどに「書かれた言葉」が一致しない

– 最初は、笑っちゃうくらう一致していない

– チームのドメインの学習が進むにつれて、言葉とコードが一致してくる

64

言葉たいせつ• 「エクストリームプログラミング」では、言葉を

使った会話がドキュメントの代わり

– 意図伝達のもっとも効率的な手段

• 「言葉」が、そのままクラス/メソッド/パッケージの候補になる

• あらゆる場所で同じ「言葉」を、同じ「意図」で

– 会話/チャット/メール/コミットログ/ソースコード

– 品質保証のもっとも効率的な手段

65

言葉たいせつ

• 開発者が、利用者の「重要な関心事」をよどみなく語り始める安心感

• 技術用語ばかり使う開発者が書くコードへの恐怖感

66

第3章モデルと実装を結びつける

67

ドメインモデルを活用する

ドメインモデル

ドメインの「重要な関心事」を鋭く説明する

選び抜かれた重要な関心事をコードで表現する

会話を繰り返して「要点」を明確にする

「重要な語彙」をチームで合意する

1章2章3章

68

第1章

ドメインの知識をかみ砕く第3章

モデルと実装を結びつける

第2章

言葉を使った意図の伝達

第3章の基本メッセージ

69

ソフトウェアを作るために分析モデルと実装モデルを

一致させる

ドメイン駆動設計が求めるモデル

• 初期の分析を支援するだけでなく、設計において土台になるモデル

• 分析と設計の両方に役に立つモデルを探す

– 簡単には見つからない

– 少しずつ学習し、実験し、良いモデルに育てる

– 言葉による実験/コードによる実験

70

モデリングのパラダイム

• オブジェクト指向– 分析と実装を一致させる

• 分析クラス=実装クラス

– しかし、理屈通りにはなかなかうまくいかない

– そこで「ドメイン駆動設計」

• 手続き型プログラミング– 基本データ型と、その操作になりがち

– 動かすだけならてっとり早い

– プログラムの構造と、人間の関心事が一致しない

– 変更コストが膨らむ

71

※論理型プログラミングは「述語論理」と一致する。しかし、広くは採用されていない

ドメイン層の骨格を見せる

• 「モデル」が、利用者の「重要な関心事」を反映していれば、ドメイン層の主要なクラスを、利用者がそのまま理解できる

– 利用者自身にドメイン層の設計をレビューしてもらう効果は大きい

72

クラスのスケッチ図を、画面レイアウトや画面遷移風に説明すると意図が伝わりやすい

画面はドメインオブジェクトのビュー主要な画面=主要なドメインオブジェクト

実践的モデラ

• コードを書く人がドメインを学び、業務の重要な関心事を正しく理解する

• それが、もっとも確実で、もっとも効果的なソフトウェア開発手法

73

コードを書かない人が、利用者の活動や関心事をどんなに理解しても、良いソフトウェアは生まれない

第1部のまとめ

74

ドメインモデルを活用する

ドメインモデル

ドメインの「重要な関心事」を鋭く説明する

選び抜かれた重要な関心事をコードで表現する

会話を繰り返して「要点」を明確にする

「重要な語彙」をチームで合意する

1章2章3章

75

第1章

ドメインの知識をかみ砕く第3章

モデルと実装を結びつける

第2章

言葉を使った意図の伝達

第2部モデル駆動設計の

構成要素

76

第3章 「モデルと実装を結びつける」 ための実践スキル

第2部 モデル駆動設計の構成要素

• 第4章 ドメインを隔離する

• 第5章 ソフトウェアで表現されたモデル

• 第6章 ドメインオブジェクトのライフサイクル

• 第7章 言語を使用する:応用例

77

モデルと実装の一致

• モデルと実装の一致は非常に難しい

• では何をすべきか?

–ドメインの隔離

–モデルをコードで表現する基本スキル

–ドメインオブジェクトのライフサイクル

–モデル駆動設計の進め方

78

第2部は基礎練習• ボールを蹴って止める基本の練習

• 相手に囲まれても確実にできる

• 90分走りぬいたあとでも確実できる

• ぬかるんだピッチでも確実にできる

• 第2部の基本スキルを、厳しい現実やさまざまな制約の中で、確実に使えるようになることが、「第3部 深いモデル」、「第4部 戦略的設計」を実践する土台になる。

79

第4章ドメインを隔離する

80

第4章の基本メッセージ

81

ソフトウェアを作るためにドメインの複雑な知識をドメイン層に集約して

整理する

レイヤ化アーキテクチャ

82

ドメインの「隔離」

• ドメイン層を「しっかり」分離する• 業務知識の他の層へのまぎれこみを防ぐ

– プレゼンテーション層の業務ルール• ビュー定義内の if 文

– 太ったサービスクラス• トランザクションスクリプト• データの入れものだけのドメイン層のクラス

– データソース層の業務知識• where 句に埋め込まれた業務ルール• 動的SQLの組み立てに埋め込まれた業務ルール

– テーブルの区分やフラグ• アンチパターンの宝庫

83

継続的にドメイン層に移動する

• てっとり早く修正するために、コントローラやビューに業務知識を記述するアンチパターンが横行する

• 地道に、業務知識をプレゼンテーション層から抽出して、ドメイン層に移動する努力を続ける

• ドメイン層の業務知識が豊かになるほど、他の層はすっきりしてくる

– コードを複雑にする主因は、ドメインの複雑さ

– その複雑さを、ドメイン層に集約して整理する

84

第4章のまとめ• ドメイン層にドメインの知識を集め続ける

• ドメイン層が膨らみ複雑になってくる– 良い兆候

• ドメイン層の整理を繰り返す– 「重要」な関心事と「些細」な関心事を、クラスやパッ

ケージを使って分離する工夫を続ける

– 関係性(クラスやパッケージの依存関係)をシンプルにする工夫を続ける

– その過程で業務モデルの基本構造を発見できる

• ドメインを深く理解したモデルとコードに成長する

85

第5章ソフトウェアで表現されたモデル

86

第5章の基本メッセージ

87

ソフトウェアを作るために分析と実装を一致させる

そのための基本テクニック

ドメインの関心事の抽出

関心事を抽出する

88

何が違うのか?

89

関心事を分けて深堀する

• 「顧客」

– 基本属性は何か

– どうやって識別するか

• 「住所」

– どう表現するか

– 住所がない場合?

– 複数の住所?

– 住所が変わる時?

90

第5章に登場する関心事の抽出のテクニック

エンティティ(参照オブジェクト)

値オブジェクト

ドメインサービス

モジュール(package)

91

エンティティ(参照オブジェクト)

92

参照オブジェクトドメイン駆動設計の Entity

93

集約のルート オブジェクトのコラボレーションの元締め

関心事への参照点

顧客との会話の語彙の起点

参照オブジェクト

値オブジェクト

参照オブジェクトの設計

• 「識別」という関心事に集中する

– 関心の対象の特定方法や発見方法

• 一覧の表示順

• 重要な検索軸の特定

– 技術的な一意識別とは別の視点

– 関心の対象の「内容」「状態」は「値オブジェクト」にまかせる

• 異なる関心事

• 別クラスに分けて議論し設計する

94

値オブジェクト

95

ドメイン駆動設計の基本中の基本

値オブジェクト

StringList<String>

BigDecimalInteger…

LocalDateLong

起算日 InitialDate期限 DueDate有効期間 ValidTerm

金額 Money数量 Quantity単位 Unit

品名 ProductName備考 Remarks摘要 Abstract

言語で用意された「型」(汎用)

独自に定義した「型」(目的特化)

96

値オブジェクトの設計

• 完全コンストラクタ

– すべてのインスタンス変数は、生成時に設定

• 不変

– setter を書かない(状態を変えない)

– 値を変更する時は、別のオブジェクトを生成して返す

– 不変による「安定」

• ロジックの置き場所

– インスタンス変数を使った、判断・加工・計算

– 何もしないで素のデータを返す getter はNG

97

値オブジェクト

• 業務の関心事の基本語彙の抽出手段目的を限定した抽象データ型

– String, BigDecimal, LocalDateの値の範囲、文字種、形式、計算範囲を業務に合わせて制限する

– 用途を限定するとプログラムが安定する

– コードの重複がなくなり、変更が楽になる

• 関心事を豊かに表現する手段

– メソッドの戻す値の「型」

– メソッドの引数の「型」

98

ドメイン層のサービスクラス

99

ドメイン層のサービス• 「参照オブジェクト」や「値オブジェクト」に置く

べき場所に迷う業務知識

• その業務知識に名前を付けてクラスとして抽出してみる(実験)

– XxxPolicy

– XxxRule

– XxxProcedure…

100

ドメイン層のサービス 危険!

• 「手続き」にドメインの「関心事」が隠ぺいされがち– 深いモデルの探求の手掛りを見失う

• 同じ「ロジック」が複数サービスに重複しがち– 変更コストがあがる– モデルとコードの成長の障害になる

• 処方箋– メソッドの引数と型は「ドメインオブジェクト」にする

• long や Stringを使わない

– 基本用途は区分オブジェクトの振る舞いの実装• 区分ごとのビジネスルールを記述するクラス

– それ以外の場合、リファクタリングの候補としておく• より適切な置き場所を模索する

101

モジュール(パッケージ)

102

モジュール(Packages)

• 関心事の抽出手段

– 関連するドメインオブジェクトのグループ化

– 利用者の関心事の「境界」の表現

– 業務上の依存関係の表現(パッケージ依存関係)

• リファクタリングの対象

– 業務知識が増え、業務の理解が深まるたびに、パッケージ名/パッケージ構成を変更する

103第4部「戦略的設計」の主要ツール

そのほかの関心事の抽出テクニック

一覧オブジェクト(ファーストクラスコレクション)

区分オブジェクト(場合ごとのビジネスルールの表現)

HowよりWhat(意図の明白なインタフェース)

104

一覧オブジェクト(ファーストクラスコレクション)

105

一覧オブジェクト(ファーストクラスコレクション)

• ListやSetをラップしたドメインオブジェクト• Offers

• MailBox

• SkillSet

• 「一覧」や「履歴」という関心事の表現

– 「一覧」は利用者の関心事が集中する場所

– 「一覧」の議論は、重要な関心事の発見の良い機会

• コレクションの操作は、コードがごちゃごちゃしやすく、変更の副作用が多い

– クラスとして独立させ、そのクラスに閉じ込める106

9章 概念を掘り出す10章 概念の輪郭

区分オブジェクト(場合ごとのビジネスルールの表現)

107

区分オブジェクト

• 振る舞いを持った Enum• 区分ごとのロジックを別クラスに記述• Java言語使用に組み込まれた

Strategy/Stateパターン

説明とコード例は、googleで「場合わけの書き方あれこれ」で検索。

または「オブジェクト指向をきちんと使いたいあなたへ」

場合ごとのビジネスルールの表現

108

区分オブジェクトの効果

• 関心事の明示的なコード表現

• 複雑な if文記述の解消– 区分ごとの分岐記述( if文 or switch文 )は、一箇所

になる

– 場合によっては、まったく書かなくてよくなる

• どこに何が書いてあるかわかりやすくなる– 区分ごとの業務ルールや知識のロジックの置き場所

をクラス単位で分離

• 区分の追加や削除をした時の、変更の副作用が少ない

109

9章 概念を掘り出す10章 概念の輪郭

How より What(意図の明確なインタフェース)

110

expireDate.add(-1);

expireDate.previousDay();

expireDate.dayOfFinalAlert ();

業務要件:期限切れの前日にアラートメールを送る

How より What業務の関心事を明示的に表現する

111

課金ポリシー

適用する()

シーズン料金

レート()

夏料金

レート()

冬料金

レート()

料金

計算() <<interface>>

計算方法(How)を記述

料金の用語(What)をクラスで表現

計算()メソッドに埋もれ、暗黙化する業務知識

シンプルな設計に見えるが、ルールの変更・追加のたびに計算()メソッドが肥大化し、if 文が増殖する

業務知識をそのまま、クラスとして表現複雑に見えるが、ルール変更・追加が、楽で安全になる

How より What

112

9章 概念を掘り出す10章 概念の輪郭

モデリングパラダイム

113

第5章 ソフトウェアで表現されたモデル

• なぜオブジェクトパラダイムが主流なのか

– モデリングの手法としても実装の手法としてもうまく使える実践的な技法だから

– 広範囲に使われ成熟してきたから

• ツール、モデリングや設計のノウハウ、実例

• オブジェクト世界のオブジェクトではないもの

– 述語論理、ワークフロー、関係データベース、…

• オブジェクト指向を軸にして非オブジェクトの要素を混ぜ合わせる4つの経験則

– パラダイムの混在には慎重にかつ保守的に

114

第5章のまとめ

• 「モデル」と「実装」の一致は難しい

• オブジェクト指向の基本を学び、体で覚えながら、関心事の分離とコード表現のスキルを磨く

• それが第3部、第4部の土台になる

– 役に立つのは「深いモデル」を見つけた時

– 大きな効果がでるのは「戦略的」に取り組んだ時

115

第6章ドメインオブジェクトの

ライフサイクル

116

第6章の基本メッセージ

117

オブジェクトの生成と永続化はコードを複雑にしがちドメインオブジェクトの

意図と役割を明確にする工夫(生成や永続化を分離する)

第6章の問題意識と解決方法

• 複雑になりがち

– オブジェクトのライフサイクル管理

• 生成/格納・再構成/修正/削除

• オブジェクト間の整合性

• 「モデル」をこの複雑さから守る

– ドメインオブジェクトを「集約」としてグルーピング

– オブジェクトの生成は「ファクトリ」にまかせる

– オブジェクトの永続化は「リポジトリ」にまかせる

118

「集約」

• ドメインオブジェクトのネットワーク– 利用者の「活動」や「関心事」の結びつきを反映

– 必然的に複雑になる

• 「集約」してオブジェクトのグループとして扱う– 「ひとかたまり」として扱うべきオブジェクトの集合を探

– 他のオブジェクトグループ(集約)との境界を検討する

– 独立性の高い、意図の明確な「集約」の発見が、ドメイン層の見通しをよくし、プログラムを安定させる

119

生成を「ファクトリ」にまかせる

• オブジェクトの集約の生成– エンティティ(集約のルート)が、自分で生成に責任を

持ち始めると、エンティティ本来の関心事(識別)があいまいになる

• 生成ロジックの置き場所の選択肢– 「集約のルート」の static なファクトリメソッド

– 「集約の生成」に関わるオブジェクトのファクトリメソッド

– コンストラクタ

– 独立したファクトリクラス…

120

永続化を「リポジトリ」にまかせる

• 必要なオブジェクトの集約を入手する

• あたかもすべてのドメインオブジェクトがメモリ上にあるように設計する

– データベース設計やORマッピングをいったん忘れる

– interface 宣言で実装を分離する

• やりたいことをシンプルに宣言する• 注文 findBy(管理番号)

• 注文一覧 lookFor(検索条件)

• void register(注文)

121

第7章言語を使用する:応用例

122

第7章 言語を使用する:応用例

• 4章、5章、6章の「基本構成要素」を組み合わせる実戦に近い練習

• 仮想的なチームが要求と実装の問題に対処しながら「モデル駆動設計」で開発をしていく例

• その過程で生じる「さまざまな問題」と「どう解決」されるかを見ていく

• 第7章の書かれた意図を読み取るのはたいへん– その分、ドメイン駆動設計の考え方とやり方の発見と

学びが多い章

123

第7章のストーリ展開

1. 貨物輸送システムの概要2. ドメインを隔離する:アプリケーション層の導入3. エンティティと値オブジェクトを区別する4. 輸送ドメインの「関連」を設計する5. 「集約」の境界を検討する6. 「リポジトリ」を選択する7. シナリオをウォークスルーする8. オブジェクトの生成9. リファクタリングのために立ち止まる10. 輸送モデルにおける「モジュール」11. 新機能を導入する:配分チェック12. 最後に

124

第7章はより実戦に近い練習

• 「モデル」と「実装」が育っていく過程とリズム

• 「モデル駆動」で設計するということ

– まず「アプリケーション層」を導入する

• 「ドメイン層」の議論を「機能」視点から隔離する

• 機能(処理)の詳細化からの設計ではない

– 入出力項目(画面帳票)の定義は登場しない

• プレゼンテーション層無しのドメイン層の設計と実装

– データモデル/テーブル設計は登場しない

• データモデルから独立したドメイン層の設計と実装

125

関連・集約・リポジトリ

• 第7章の議論のハイライト• 「関連」を設計する

– 関連の方向の議論はドメインに対する洞察– 複雑な実装を避ける(成長容易性の確保)

• 「集約」の境界を検討する– ドメインオブジェクトの「かたまり」の定義– 概念(関心事)の境界の明確化– 開発単位

• 「リポジトリ」を選択する– 機能視点が登場するタイミング

• 検索/選択/登録 …

126

本日のまとめ

127

ドメイン駆動設計

エクストリームなオブジェクト指向プログラミングでドメイン層を構築する少しずつソフトウェアを成長させる「適応創発型」の開発スタイル

オブジェクト指向

エクストリームプログラミング

128

ドメインの知識をコードで表現する

ドメインモデル活用する

ドメインモデル

ドメインの「重要な関心事」を鋭く説明する

選び抜かれた重要な関心事をコードで表現する

会話を繰り返して「要点」を明確にする

「重要な語彙」をチームで合意する

1章2章3章

129

第1章

ドメインの知識をかみ砕く第3章

モデルと実装を結びつける

第2章

言葉を使った意図の伝達

より深く、より広く

第3部「より深い洞察に向かうリファクタリング」

深いモデルの価値

ドメイン知識の表現力を改良するリファクタリング

第4部「戦略的設計」

より広い範囲で長期的に実践するための工夫

130

ドメイン駆動設計への道

131

できない理由?

• 今のプロジェクトでは無理

• 今のチームでは無理

• 今の会社では無理

• 今の自分の力では無理…

132

• どんな状況でも改善できる

• どんなときでも「あなた」から改善を始められる

• どんなときでも「今日」から改善を始められる

ケント・ベックのメッセージ

133

ドメイン駆動設計への道

134

どんな状況でも「ドメインの知識」を学ぶことはできる

どんな時でも「ドメインの言葉」で話すことはできる

どんな時でもドメインの言葉を「コード」に反映できる