36
ULS Powered by Copyright © 2015 UL Systems, Inc. All rights reserved. Proprietary & Confidential 概概概概概概概概概概 + DDD 概概概概概概概概概概概概概概概概概 ~~ ウウウウウウウウウウウ ウウ ウウ 概概概概概概概概概 概概概概概概概概概概概概概概概概 「」、

概念モデリング再入門 + DDD

Embed Size (px)

Citation preview

ULS Powered byCopyright © 2015 UL Systems, Inc. All rights reserved. Proprietary & Confidential

概念モデリング再入門 + DDD~今さら聞けない人のための基礎講座~

ウルシステムズ株式会社河野 正幸

情報システム部門を「強く」し、次世代リーダを育成する

ULS Copyright © 2015 UL Systems, Inc. All rights reserved. Proprietary & Confidential Powered by

概念モデリングやってますか? システム化の対象業務や問題に対して深く本質的な理解を得る上

で概念モデリングは非常に有効な活動河野の場合は概念モデリング抜きにシステム化の検討をすることはもは

や考えられないほど、自分の中に定着しているDDD( ドメイン駆動設計 ) に取り組むのなら必須でしょう!

もしやっていない人がいるのなら、本当にもったいない。ぜひ一度やってみてほしい

まずは始めてみることが大切。始める前から腰が引けている人が多いと感じる

プロジェクトの皆で一緒に始めようとするから敷居が高くなる。まずは自分一人でこっそりと描くところから始めよう

本日の私の目標は「明日から概念モデリングやってみようかな」という気になってもらうこと

ULS Copyright © 2015 UL Systems, Inc. All rights reserved. Proprietary & Confidential Powered by

本日の内容

自分一人でこっそりと概念モデリングをスタートする際に

この位知っておけば十分でしょうという1. スタートする上での最低限の基礎知識

始めてみたもののうまく描けないという人のための2. 要領良くモデルを描くために知っておくと良いこと

DDD に興味がある人のために3. ドメインモデル設計のポイント

この 3 点を今日はお話しします

ULS Copyright © 2015 UL Systems, Inc. All rights reserved. Proprietary & Confidential Powered by

1.最低限の基礎知識

ULS Copyright © 2015 UL Systems, Inc. All rights reserved. Proprietary & Confidential Powered by

UML で描いた概念モデルの例

概念名

属性

概念の種類を表す線

概念同士の関連を表す線

関連の多重度

関連の役割名

注釈 ( ノート )

自動車ディーラーの見積業務

重要な概念は属性ではなくクラスとして記述する

関連の多重度は絶対に記述する 注釈 ( ノート ) はできるだけ多く、詳しく

記述する

重要な概念は属性ではなくクラスとして記述する

関連の多重度は絶対に記述する 注釈 ( ノート ) はできるだけ多く、詳しく

記述する

ULS Copyright © 2015 UL Systems, Inc. All rights reserved. Proprietary & Confidential Powered by

概念モデリングの手順

1. テーマの選定

2. 概念の識別

3. 属性の定義

4. 関係の定義

6

ULS Copyright © 2015 UL Systems, Inc. All rights reserved. Proprietary & Confidential Powered by

1.テーマの選定

何をテーマに概念モデルを描くのかをまず決める

テーマの広さによってモデルの目的や詳細度は変えた方が良い 全体概要モデル

会社全体を対象にしたり、販売管理・生産管理といった広い業務領域を対象に全体像をざっくりと把握するために描く

詳細な情報は切り捨てて主要な概念だけで全体像をわかりやすく表現する 個別詳細モデル

見積、受注、出荷、請求などビジネスユースケース位の単位で業務の詳細を正確に把握するために描く

業務の詳細理解のために必要な情報は漏れなく記述する。最終的には論理データモデルの元ネタとできるレベルまで詳細化する

7

ULS Copyright © 2015 UL Systems, Inc. All rights reserved. Proprietary & Confidential Powered by

2.概念の識別 以下の概念分類を参考に選定したテーマに存在する概念を識別する

8

大分類 説明 小分類 説明

リソース

経営資源に関連する概念

パーティ ・他のパーティと契約を締結してビジネスを遂行する能力を有する「法人」や「個人」に関わる概念・法人や個人が特定の取引に参加する時のロール(役割)に着目して概念を識別する・顧客、仕入先、商社、メーカー、配送業者、委託加工業者など

もの ・ビジネスで消費したり生産したりする「もの」に関わる概念・商品、副資材、原材料、生産設備など

場所 ・「場所」に関わる概念・在庫場所、店舗、倉庫、配送先、保管棚など

ルールポリシー

・ビジネスを遂行する上での「ポリシー」や「ルール」に関わる諸々の概念・決済方法、受渡方法、契約、為替レート、工程、配送ルートなど

イベント

ビジネスにおいて人やものや場所といったリソースが相互作用して引き起こされるビジネス上の事象

通常イベント

・ビジネスの目標を達成するための重要なイベント。口座型データストアを増減する。・受注、出荷指示、出荷、販売、請求、発注、入荷、入荷案内、仕入、支払、加工 /梱包指示、加工 /梱包実績など

異動イベント

・リソースのライフサイクルを通じた重要な状態変化の履歴を表し、長期間にわたって保存する必要があるイベント・単価改訂、人事異動、設計変更、設備修理など

データストア

ビジネスを円滑に遂行する上で把握しておくことが必要な情報

口座型データストア

・経営資源の現状を示す、常時増加や減少を繰り返す口座的な情報を記録する概念・商品在庫、銀行口座、受注残高、勘定口座など

B/S型データストア

・リソースや口座型データストアの特定時点(日末、月末、期末、年度末など)の状態を記録する概念・貸借対照表 (B/S: Balance Sheet) のように時系列で推移を見る目的で使用する・在庫、資産、債権債務などの特定時点での記録

P/L型データストア

・生産高や売上高などのイベントをカテゴリ(製品、場所、期間、顧客など)ごとに要約して記録する概念・損益計算書 (P/L: Profit and Loss Statement) のようにある期間での業績を評価する目的で使用する・月次商品別売上高や部門別間接費などの記録

ULS Copyright © 2015 UL Systems, Inc. All rights reserved. Proprietary & Confidential Powered by

3.属性の定義

概念の特性をよく表している主要な属性を定義する(名称、日付、数量、金額など)

コードや区分などで表現される情報はそれ自体が独立した概念になることが多い。こういったものはなるべくクラスとして表現する

データベースの設計をしているわけではないので、すべての属性をこの時点で詳細に洗い出す必要はない(後の論理データモデル設計で実施すればよい)

概念のアイデンティティを把握する上で主キーは意識した方が良い。ナチュラルキーの主キーに含まれる属性を定義して主キーを把握しておく

9

ULS Copyright © 2015 UL Systems, Inc. All rights reserved. Proprietary & Confidential Powered by

4.関係の定義 概念同士の関係とその多重度を定義する。多重度はビジ

ネスルールを示している場合も多いので必ず定義する

種類を明示したいものについて「汎化」関係で表現する

基本的には「関連(アソシエーション ) 」「汎化」の 2種類の関係だけで十分概念モデルは表現できる

「関連(アソシエーション)」のうち「集約(アグリゲーション)」「複合(コンポジション)」まで細かく識別することは、概念のライフサイクルを意識してより深く概念構造を理解するためには有用だが、無理やり使おうとしてかえって混乱することも多いので割愛してよい

10

ULS Copyright © 2015 UL Systems, Inc. All rights reserved. Proprietary & Confidential Powered by

2.要領良くモデルを描くために

ULS Copyright © 2015 UL Systems, Inc. All rights reserved. Proprietary & Confidential Powered by

概念モデリングが習慣づかない人の NG行動 (1) 理論武装してから始めようとする

UML などの表記法やモデリングのやり方を教科書等できっちりと理論武装してからでないと始められないと思う人は、上手に描きたいという気持ちが強すぎてなかなか始められれない。とにかく下手でも良いから描いてみる。そのためには最初に余計な知識は無い方が良い

自分の描いたモデルが正解かどうかにこだわり過ぎる 世の中のどこを探しても自分の描いたモデルの正解は載っていない。同じ業務を対象にして

も前提とするルールが異なれば異なるモデルになるのが当たり前 いわゆる教科書に載っているようなリファレンスモデルはあくまでも参考情報であって、そ

のモデルの置く前提と自分が対象としているものの前提が異なれば違うモデルになる。それを「どうして自分のモデルは教科書 (= 正解と思い込んでいる ) と違うのだろう?」と悶々と悩んでも答えは永遠に出ない。自分が理解した内容で描いたモデルがその問題の正解のモデルなのだと割り切るべき

12

教科書に載っていたモデル

自分で描いてみたモデル

1回の注文を分納することを想定注文が無くても出荷は発生する。例えば工場から倉庫への移動

1回の注文を必ず 1 度の出荷で満たすことを想定注文が無ければ出荷は絶対にしない

注文 出荷

注文 出荷

0..1 0..*

1 0..1

ULS Copyright © 2015 UL Systems, Inc. All rights reserved. Proprietary & Confidential Powered by

概念モデリングが習慣づかない人の NG行動 (2)

うまくモデルが描けなくて途中で投げ出す 「知らないことはモデルには描けない」。この単純な事実を受け入れて「自分が理

解できていないことがわかって良かった」と前向きに転嫁して必要な知識・情報を積極的に仕入れる。知らないことは恥ずかしいことではない

河野が新しいテーマで概念モデルを始める時には以下の 2つの知識をまず仕入れることにしている。前提知識としてこの 2つがある程度理解できていれば、比較的スムーズにモデルを描くことができる

対象企業が扱っている商品 (製品、サービス ) 対象企業を取り巻くパーティ ( 自社組織、取引先 )

13

商品

新車販売

中古車販売

点検・修理

用品販売

保険販売

パーティ

自社部門

取引先

本社

店舗

顧客

サプライヤ

個人顧客

法人顧客

自動車メーカー

用品メーカー

修理工場

損保会社

クレジット会社

自動車ディーラーの商品とパーティ

ULS Copyright © 2015 UL Systems, Inc. All rights reserved. Proprietary & Confidential Powered by

概念モデリングが習慣づかない人の NG行動 (3) 最初から綺麗な最終形を描こうとする

あるテーマで最終モデルを作成するまで、河野の場合は以下の 3段階くらいのモデルを描いてみる

1. 全体をざくっと把握するための概要のモデル

2. 業務を深く理解する目的で抽象化をせずになるべく詳細に表現したモデル

3. 業務を深く理解した上でデータ設計につなげるために抽象化をして整理したモデル(最終形) 世の中で紹介されているモデルは最終形がほとんどなので、最初からそういう内容のモデ

ルを描こうとしがちだが、これだと業務や問題を深く理解できないこともある。初期の 2段階のモデルをきちんと描く方が実は業務がよく理解できる

14

部品表の最終モデル

品目

- 品目コード- 名称

品目構成

- 員数- 適用期間

品目種別 品目構成種別

完成品、ユニット部品、末端部品等の品目の種別

品目の構成の親子の組み合わせのルールに応じて設定する構成の種別

*

+親品目

1

*

+子品目

1

1

*

1

*

部品表理解のための初期概要モデル

完成品 ユニット部品 末端部品

-完成品 ユニット部品構成

-完成品 末端部品構成

ユニット部品間構成

-ユニット部品 末端部品構成*

+親 1

*

+子 1+親 1

* *

+子 1*

+親 1

*

+子 1 +親 1

* *

+子 1

抽象化

ULS Copyright © 2015 UL Systems, Inc. All rights reserved. Proprietary & Confidential Powered by

概念モデルを要領良く描くコツ (1) まずイベントを見つけ 5W3H を考えてざくっとモデルを描く

イベント概念は通常5W3Hを表すので、この観点から整理することでイベントに関わる主要なリソースに関する情報を洗い出せる。構造は後から精査すれば良い。とにかくモデルにしてみることが肝要

15

例:「受注」というイベント概念の 5W3HWhen( いつ、いつまでに )   : 受注日、希望納期Who(誰が )   : 営業担当者Whom(誰に ) : 顧客、商社What( 何を ) : 商品Where( どこに ) : 納品場所How( どうやって ) : 決済条件How much( どれだけ ) : 金額How many( どれだけ ) : 数量

受注

- 受注番号- 受注日- 希望納期- 数量- 金額

商品

顧客

商社

納品場所

決済条件

営業担当者

1

*

*1

*0..1

* 1

* 1*

1

受注

- 受注番号- 受注日

受注明細

- 数量- 単価- 希望納期

商品

取引先

商社が商流に入るケースについては請求先が商社になる。それ以外は販売先と請求先は同じ取引先になる

社員

納品場所

取引先毎にあらかじめ納品場所を複数設定しておき、受注時に選択できるようにする

決済条件

決済条件はあらかじめ取引先との基本契約で一意に決まるので受注単位で保持する必要はない

1

*

* 1

*

+販売先

1..*

*

+請求先

1

+受注担当者

1*

1

*

*1

1

*

1. 5W3H でまずざくっと描いてみる

2.業務をよく分析してモデルを洗練する

ULS Copyright © 2015 UL Systems, Inc. All rights reserved. Proprietary & Confidential Powered by

概念モデルを要領良く描くコツ (2) 双方向で関連を精査して適切な概念構造を導き出す

片方から見ると妥当に思えても逆方向から見ると結果的に多対多関連になることがある

多対多関連は放置せず、その 2つの概念の間に存在する関連を管理する概念をきちんと導き出すとすっきりと整理できる

16

2.注文から商品の関連を考える1件の注文で複数の商品を注文できるだから多重度は多になる

1.商品から注文の関連を考えるある商品は色々な人から注文できるだから多重度は多になる

3.多対多関連になってしまったので解決する注文は複数の商品明細を保持し、各明細が注文対象の商品を知っていると考えると解決する商品はマスタなので独立に存在できる注文明細は固有の注文に属する情報だと切り分けるとすっきりする

注文商品*

注文商品**

注文明細商品

注文

1

*

*1

ULS Copyright © 2015 UL Systems, Inc. All rights reserved. Proprietary & Confidential Powered by

概念モデルを要領良く描くコツ (3) 双方向で関連を精査して適切な概念構造を導き出す ( の続き )

前頁の例とは異なり、最初はイベントに従属する情報だと思っていたものが、逆方向から眺めるとマスタとして別概念を切り出した方が良いと気付く場合もある

17

1.検査実績から不良理由明細の関連を考える1回の検査で複数の不良理由 ( 割れ、変形、サビなど ) が発見される可能性があるので、検査理由明細として複数の理由が記録できるようにした

2.不良理由明細から検査実績への関連を考える不良理由の記録が各検査実績に含まれる情報だと最初は考えたので一つの検査実績に関連すると考えた

3.不良理由という観点から関連を見直してみた視点を変えて不良理由を条件に該当する検査実績を全て調査したいという要求があると考えてみたこの場合、不良理由は独立して存在する概念として考えた方がその要求を満たすモデルとしてはふさわしいと考えて見直した

検査実績 検査実績不良理由明細

*

検査実績 検査実績不良理由明細1

*

検査実績

検査実績不良理由明細 不良理由

1

*

* 1

ULS Copyright © 2015 UL Systems, Inc. All rights reserved. Proprietary & Confidential Powered by

概念モデルを要領良く描くコツ (4) 2つの概念間に別の種類の複数の関連が無いかを精査してみる

あるモノに対していくつかのイベントが発生する場合は、イベント側の多重度は多になる。基本的にはそれで問題が無いが、情報をどう活用したいかという観点で関連を深堀りしてみると「過去の履歴を参照する」「最新の状態を参照する」という 2つの用途が求められることが多い。こういったこともモデルにきちんと表現しておくとわかりやすくなる

18

1.製造ロットは複数工程の作業実績を  持つので 多重度を多とした

2.履歴だけではなく最新の仕掛工程も  知りたいので関連を 2 種類定義した

製造ロット

品目

工程順序

工程実績

製造ロットが前の工程の作業を完了した時点で工程マスタを参照して、次の仕掛工程の情報を追加で作成する

実際に該当工程順序で作業が行われた時に実績を作成する

1

*

1

*

1

0..1

製造ロット

品目

工程順序

工程実績

過去の工程実績を参照するために使用する

最新の仕掛工程を参照するために使用する

1

0..1

1

*

1

+履歴 *

1

+仕掛工程0..1

ULS Copyright © 2015 UL Systems, Inc. All rights reserved. Proprietary & Confidential Powered by

概念モデルを要領良く描くコツ (5) 概念同士の関連においてロールを意識してうまく表現する。ただしシンプルに!

概念同士の関連がただ一つしか無い場合にはその関連の意味は明確であるが、複数の関連が存在するケースもある。その場合にはその関連において概念がどのようなロールを担うのかをモデルに記述することで的確に表現することが可能になる

業務を理解する目的とロールそのものをどう管理するかという目的が混同するとわかりづらくなるので目的を切り分けてシンプルにモデルを描く

19

1.自動車の見積には 3 種類の顧客情報が必要 2.販売契約には 3 種類の取引先が参加する見積顧客

*

+契約者

1

*

+使用者

1

*

+紹介者

0..1

販売契約

販売先

請求先

注文者

取引先

*1

*1

*1

*ある一つの取引先が複数のロールを取り得る場合(普通はそう)厳密に UML の規則に従うと汎化では表現できない。でもわかりやすけりゃこれでもいいんじゃないというのが河野の考え方

3.取引先のロールを厳密に管理することを意図し しかも販売契約との関連も表現してみたモデル

*販売契約という概念を理解することが目的なら、取引先ロールの部分はやり過ぎ。 1 のモデルと同じようにシンプルに関連を直接張ってロール名を記述するのが一番分かり易いと思う

取引先

取引先ロール 販売契約

取引先ロール種別注文者、販売先、請求先、出荷先、仕入先等の取引先がビジネスに参

( )加する際の役割 ロール を定義する。どの取引先がどのロールを取り得るかのチェックがしたいので、そのルールを定義する概念

1 *

*

+注文者

1

+販売先

1 *

*

+請求先

1

1

*

ULS Copyright © 2015 UL Systems, Inc. All rights reserved. Proprietary & Confidential Powered by

概念モデルを要領良く描くコツ (6)

モノに関連している概念を考える場合、それがモノの「種類」を扱っているのか「現品」を扱っているのかを精査することで正しい理解が得られる モノの種類を指定して行う仕事と、現品を直接扱う仕事とをしっかりと区別しな

いと業務を正しく理解できないリスクが高いので注意する

20

1.一見正しく思えるが間違った  理解をしているモデル

2.モノの種類と現品をきちんと区別して  理解しているモデル

( )注文 新車

( )注文 中古車

1

*

1

*

( )注文 新車

車種

- 車種コード- 主要諸元

( )注文 中古車

車両

- VIN- 年式- 車検年月

モノの種類を表す概念 ( )現品 現実に存在する個体 を表す概念

新車はまだ存在しない車両の種類を指定して注文

USする。ただし、 のように新車も店頭在庫から販売する場合は中古車と同じモデルになる

中古車は既に市場に流通している特定の車両を指定して注文する

( & )納車 新車 中古車

納車は既に存在する特定の車両をターゲットに実施

/するので新車 中古車の違いはない

1

+履歴 *

10..11 0..1

1

*

1 *

1

*

ULS Copyright © 2015 UL Systems, Inc. All rights reserved. Proprietary & Confidential Powered by

概念モデルを要領良く描くコツ (7)-(1) ある仕事を遂行するためのルールや手順・ポリシーなどを管理する「知識レベル」の概

念と、それらを適用して実際に業務を実行する際のオペレーションを管理する「操作レベル」の概念は混同しがちなので、しっかりと精査して切り分ける マスタ的な情報と、そのマスタを適用して特定のオペレーションを制御するために必要な情

報が混同すると、一見正しいモデルに見えて細部では色々と矛盾があるモデルになっている可能性があるので注意する

「知識レベル」「操作レベル」という言葉はファウラーがアナリシスパターンで使用した

21

1.「知識レベル」「操作レベル」が切り分けられていないモデル

航空便

- 便名- 運航日- 出発予定時刻- 到着予定時刻

空港

予約

- 予約番号

予約便明細

顧客予約搭乗者明細

機材

座席

+出発空港

1 *

*

+到着空港

1

1

*

*

+搭乗者

1

*11

1..*

*

1

1

1..*

*0..1

*

+予約者 1

このあたりが整理できていない

ULS Copyright © 2015 UL Systems, Inc. All rights reserved. Proprietary & Confidential Powered by

概念モデルを要領良く描くコツ (7)-(2) 前頁から続く

22

航路

- 便名- 出発予定時刻- 到着予定時刻

空港

予約

- 予約番号

予約便明細

顧客予約搭乗者明細

機種マスタ

座席マスタ

航空便

- 運航日

予約機種

予約座席

実機材

1 *

*

+到着空港

1

+出発空港

1 *

1

*

*

+予約者 1

*

+搭乗者

1

1

*

1 *

1

0..1

1

*

1 *

*0..1

1

*0..1

*

1

*

2.「知識レベル」「操作レベル」を切り分けて整理したモデル

知識レベルの世界 操作レベルの世界元々一つだった概念を知識レベルと操作レベルに分割するとすっきりした

ULS Copyright © 2015 UL Systems, Inc. All rights reserved. Proprietary & Confidential Powered by

概念モデルを要領良く描くコツ (8)-(1)

口座型データストア (銀行口座、商品在庫、受注残など ) は銀行口座における「預金通帳」に相当する受払の記録を概念として出し、それと残高の増減をもたらした業務イベントとの関連で表現するとすっきり表現できる 口座型データストアと増減の源泉となった業務イベントをどう関連づけるかで迷いが

ち 「預金通帳」的な汎用的な受払の記録の概念を業務イベントと在庫の間に挟むこと

で、固有の業務取引の情報管理と汎用的な口座管理とをうまく紐づけて表現できる このモデルはファウラーのアナリシスパターンでは「勘定パターン」と呼ばれている

もの。業務イベントによって残高が増減するような口座をモデル化する時にはほぼこのパターンが適用できるので覚えておくと使い道が多い

23

1.業務イベントと在庫が遠くてしっくりこないモデル

受注明細

商品

場所別商品在庫

出荷明細 発注明細入荷明細

生産実績在庫移動実績

1

*

1 0..* 10..*

1

*

1

*

1

*

1

*

ULS Copyright © 2015 UL Systems, Inc. All rights reserved. Proprietary & Confidential Powered by

概念モデルを要領良く描くコツ (8)-(2) 前頁から続く

24

2.業務イベントと在庫を無理やり関連づけてはみたが、まだすっきりしないモデル

受注明細

商品

場所別商品在庫

出荷明細 発注明細入荷明細

生産実績在庫移動実績

1

*

*

減らす

1

*

増やす

1

*

減らす1

10..*

1

*

1

*

1

*

1 0..*

1

*

1

増やす

*

*

増やす

1

ULS Copyright © 2015 UL Systems, Inc. All rights reserved. Proprietary & Confidential Powered by

商品

場所別商品在庫

在庫受払実績

生産実績

業務イベント

入荷実績

1つの業務イベントで受入と払出が同時に発生する場合

2には多重度が になる

受入イベント

&受入 払出イベント

払出イベント

在庫移動実績

出荷実績

発注明細

受注明細

銀行口座で言うと「預金通帳」の位置づけの概念。口座の残高の増減を全て記録しておく

口座の残高の増減をもたらした源泉となった取引(イベント)の記録

在庫場所

1

*

*1

1 *

1 1..2

1

*

1

*

*

1

概念モデルを要領良く描くコツ (8)-(3) 前頁から続く

25

3.「勘定パターン」を適用して汎用的な口座情報管理と業務イベント毎に固有な業務取引情報管理を  切り分けて、その間の関連をすっきりと表現したモデル

このような形で業務イベント管理と在庫管理の間にきちんと境界を設けておくと、新しい業務イベント(例えば、棚卸結果にもとづく在庫廃棄のイベント)が増えても在庫管理の構造に影響を与えない

ULS Copyright © 2015 UL Systems, Inc. All rights reserved. Proprietary & Confidential Powered by

概念モデリング 最後に つべこべ考えずまずは描いてみましょう。上手い下手を気にせ

ず、数をこなすことで自然と上手になります。ツールも不要です。紙とペンだけあればいつでもスタートできます

慣れてきたらその問題をよく理解している人に見せて、理解の誤りや情報の過不足を指摘してもらいましょう。それが習慣づくとコミュニケーションの質が上がってくるのが実感できると思います

問題の本質を理解するための概念モデルとデータ設計のための概念モデルは分けて考えると良いでしょう。前者の概念モデルで問題を十分理解した上で、システムの都合を考慮した後者の概念モデルを作成しましょう

ULS Copyright © 2015 UL Systems, Inc. All rights reserved. Proprietary & Confidential Powered by

3.(おまけ)ドメインモデル設計のポイント

ULS Copyright © 2015 UL Systems, Inc. All rights reserved. Proprietary & Confidential Powered by

Why DDD? DRY(Don’t Repeat Yourself) な構造にするために一番適

しているから。以上!ファウラーの PofEAA(Pattern of Enterprise Application

Architecture) に紹介されている以下の 3つのパターンのうち、もっとも DRY な構造が実現しやすいと考えている

トランザクションスクリプト (Transaction Script) テーブルモジュール (Table Module) ドメインモデル (Domain Model)

DDD は基本的には上記のドメインモデルパターンをベースにしているため、ビジネスロジックの置き場所を明確に決めやすい。結果的に同じロジックを重複して別の場所に書いてしまうことを防ぎやすい

ULS Copyright © 2015 UL Systems, Inc. All rights reserved. Proprietary & Confidential Powered by

DDD のポイント : 右へ!もっと右へ!

DDD のポイントはドメイン層の中のなるべく右側の責務のクラスに多くのメソッドを配置するように考えて設計すること。以上!

Entity と ValueObject になるべくビジネスロジックを置くようにして、その 2つに書けないロジックのみ DomainService に置くと考えることが重要

でも、 DomainService に色々書きたくなっちゃうよね?どうしたら良い?

29

プレゼンテーション層 アプリケーション層 ドメイン層

インフラストラクチャ層

DDD をベースとしたアーキテクチャの例

Application Service

Domain Service

EntityValueObject

RepositoryFactory

ULS Copyright © 2015 UL Systems, Inc. All rights reserved. Proprietary & Confidential Powered by

GRASP を意識して設計してみよう!

30

Entity, Value Object

Entity(Aggregation)

Application Service

Domain Service

GRASP(General Responsibility Assignment Software Patterns)– クラスの責務配置の基本原則。これを理解しておく必要がある– クレーグ・ラーマンが「実践UML 」という著書で紹介している 正式には

Information Expert

ULS Copyright © 2015 UL Systems, Inc. All rights reserved. Proprietary & Confidential Powered by

Value Object を積極的に活用してみる 品目コード (10桁 ) の頭一桁で「規格品」「専用品」の判定をしなけれ

ばならないとする

品目コードを String型で定義すると判定が必要な都度、 substring の関数などで頭一桁を切り出して判定するようなコードを書く必要がある

品目コードをユーザ定義型のクラス (Value Object) にして is規格品 ()とか is専用品 () というメソッドで判定させるようにすると substringでいちいち値を判定するようなコードを書かなくても済む。また「規格品」には元々” 1” の値を割り当てていたが桁数が不足したために” 3” も規格品の扱いにしたくなったとしても、品目コードValueObject クラスだけを修正すれば対応できる

品目コードのような項目は色々な Entity の属性として利用される。各Entity のメソッドとして判定メソッドを作成しても良いが、利用するEntity の数だけ同じようなコードを重複して書くことになる。このような使われ方をする情報項目は基本 ( プリミティブ )型ではなくユーザ定義型としての Value Object としてクラス化しておいた方が何かと便利

31

ULS Copyright © 2015 UL Systems, Inc. All rights reserved. Proprietary & Confidential Powered by

Entity になるべく多くの仕事をさせろ (1)

Entity に属性とその属性の getter, setter しか持たせないような設計をしていないか?(ただのデータの入れ物)

Entity こそドメイン層の主役であり、多くのビジネスロジックの実行を担うべきスタープレイヤーである。 Entity にろくな仕事をさせていないモデルは「ドメイン欠乏症」、つまり真の意味での DDD とはいえない

じゃあ Entity にどういう仕事を任せるべきなのか?

32

ULS Copyright © 2015 UL Systems, Inc. All rights reserved. Proprietary & Confidential Powered by

Entity になるべく多くの仕事をさせろ (2)

33

注文管理の Entity クラス 注文

- 注文番号- 注文日- 受注担当者コード- 顧客コード- ( , )注文ステータス 受理 受注済

+ ( , , , )注文明細登録 明細番号 商品コード単価 数量- get Entity( )注文明細 明細番号- getAll Entity()注文明細+ ()受注確認+ ( , )注文数量変更 明細番号 数量+ ( )注文明細削除 明細番号+ ()注文削除- get Entity()顧客マスタ+ get ()顧客名- get Entity()担当者マスタ+ get ()担当者名+ get ( )商品コード明細番号+ get ( )商品名 明細番号+ calc ( )明細金額明細番号+ calc ()合計金額+ is ()受理+ is ()受注+ is ()一部出荷済+ is ()全部出荷済+ is ( )数量変更可能 明細番号+ is ( )明細削除可能 明細番号+ is ()注文削除完了

顧客マスタ

- 顧客コード- 顧客名- 性別- 住所

担当者マスタ

- 担当者コード- 担当者名

注文明細

- 注文番号- 注文明細番号- 商品コード- 単価- 数量- 出荷フラグ

- get Entity()商品マスタ+ get ()商品名+ calc ()金額+ is ()出荷済+ ( )数量変更数量

商品マスタ

- 商品コード- 商品名* 1

1..*

1

*1 * 1

ULS Copyright © 2015 UL Systems, Inc. All rights reserved. Proprietary & Confidential Powered by

Entity になるべく多くの仕事をさせろ (3) Entity を利用したい人(クラス)たちが、なるべく”Don’t talk to strangers.” な環境で過ごせるよ

うなインタフェースを提供してあげよう。次頁の例のように注文番号と明細番号位を知っている人( 注文コントローラクラス ) はその情報を元に「注文Entity 」だけ取得すれば、その背後のドメインクラスの構造を知らなくても「注文Entity 」に何でも頼めるようにしてあげる

上記のように「なるべく少ない情報・知識でなるべく多くの仕事をさせる」ために、エントリポイントとなるクラスから関連のある背後のクラスに処理をどんどん委譲して多くの仕事をこなせるように考えて設計する

34

注文コントローラ 注文

注文明細

商品マスタ

1明細番号 番の商品名称を取得する

1. Entity 1 Entity注文 から明細番号 番の注文明細 を取得する2. Entity Entity取得した注文明細 から商品マスタ を取得する3. Entity取得した商品マスタ から商品名を取得する

UI注文検索

1.get Entity( )注文明細 明細番号

2.get Entity()商品マスタ

3.get ()商品名

( , )注文明細検索 注文番号 明細番号

注文コントローラが 3つのクラスに話しかけている例

ULS Copyright © 2015 UL Systems, Inc. All rights reserved. Proprietary & Confidential Powered by

Entity になるべく多くの仕事をさせろ (4) 前頁の続き GRASP でいうところの” Information Expert” としての各 Entity クラスがそれぞれの責務を

連携して実現することでクライアントの要求を満たす 注文 Entity が DDD でいうところの Aggregation の役割で注文情報管理の単一のエントリポ

イントになることで”Don’t talk to strangers.” な環境をクライアントに提供する

35

注文コントローラはただ 1つのクラスにしか話しかけていない例

注文コントローラ 注文

注文明細 商品マスタ

UI注文検索

1明細番号 番の商品名称を取得する

1. Entity 1注文 から明細番号 番の商品名を取得する 1.1. Entity 1 Entity注文 が明細番号 番の注文明細 を取得する 1.2. Entity取得した注文明細 から商品名を取得する 1.2.1 Entity Entity注文明細 が商品マスタ を取得する 1.2.2. Entity取得した商品マスタ から商品名を取得する

1.get ( )商品名 明細番号1.1.get Entity( )注文明細 明細番号

1.2.get ()商品名

1.2.1.get Entity()商品マスタ

1.2.2.get ()商品名

( , )注文明細検索 注文番号 明細番号

ULS Copyright © 2015 UL Systems, Inc. All rights reserved. Proprietary & Confidential Powered by

Entity になるべく多くの仕事をさせろ (5) クラスの属性の値を単独で編集できるsetterは作らない(公開しない) クラスの状態の変更はビジネス上の何らかの意味のあるイベントに対して行われるはず。それを意識して属性値を変更するメソッドを作る

以下の例では、注文コントローラが自分で注文明細Entityを取得してそのオブジェクトの setterを使って数量を変更するのではなく、GRASPでいうところの”Creator”の役割を果たしている注文Entityの提供する注文数量変更 ()というメソッドを通じて、最終的には注文明細Entityの数量変更 ()で数量を変更している

36

Entity に単独属性の setter ではなく業務上意味のある単位の更新メソッドを提供させる例

UI注文変更 注文コントローラ 注文

注文明細

1明細番号 番の注文明細の数量を変更する

1. Entity注文コントローラが注文 に注文数量変更を依頼する 1.1. Entity注文 は当該注文変更を受け付け可能かをチェックする 1.1.1. Entity ( )注文 が全部出荷済で完了しているかをチェックする 全部出荷済なら変更不可 1.1.1. Entity 1 Entity注文 が明細番号 番の注文明細 を取得する 1.1.3. Entity )注文明細 が自分が既に出荷済であるかどうかをチェックする(出荷済なら変更不可 [ ]上記で数量変更可能な場合以下を実施する 1.2. Entity 1 Entity注文 が明細番号 番の注文明細 を取得する 1.3. Entity Entity注文 が注文明細 に数量変更を依頼する 1.3.1. Entity )注文明細 が自分が既に出荷済であるかどうかをチェックする(出荷済なら変更不可 [ ]上記で未出荷の場合以下を実施する 1.3.2. Entity注文明細 が数量を編集する 1.3.3. Entity update注文明細 が自分を する

( , , )注文変更 注文番号 明細番号 数量 1. ( , )注文数量変更 明細番号 数量

1.1.is ( )数量変更可能 明細番号

1.1.1.is ()全部出荷済

1.1.3.is ()出荷済

1.1.2.get Entity( )注文明細 明細番号

[True ]:1.2.get Entity( )の場合 注文明細 明細番号

1.3. ( )数量変更 数量

1.3.1.is ()出荷済

[False ]:1.3.2.setValue( )の場合 数量

1.3.3.update()