Slide 1

Slide 1 text

現場で実践すべき
 DDDモデリングのポイント3つ
 〜4年間の実績からの気づき〜
 2020-02−16
 ホワイトプラス 八巻紘士


Slide 2

Slide 2 text

氏名:八巻 紘士 (@yamak1i)
 所属:株式会社ホワイトプラス システム開発G グループマネージャー
 経歴:
 大手化学会社のシステム子会社でSIer、Webの受託会社を経て
 2016年よりホワイトプラスにJoin
 リネット全般のサービス開発を担当する
 ホワイトプラスにおけるDDDの導入を主導
 3歳と1歳の2人の息子のお父さん
 趣味:読書
 特技:積ん読(読めていない)
 自己紹介


Slide 3

Slide 3 text

話すこと
 ✓ DDDでモデリングをするモチベーション
 ✓ モデリング適用のながれ
 ✓ モデリングの実例
 ✓ 導入のポイント


Slide 4

Slide 4 text

ホワイトプラスについて


Slide 5

Slide 5 text

No content

Slide 6

Slide 6 text

ハウスクリーニング比較・依頼
 プラットフォーム
 ネット型 宅配クリーニング


Slide 7

Slide 7 text

今回の話


Slide 8

Slide 8 text

お客様 工場 (検品&クリーニング) 店舗 (検品) リネットの事業モデル


Slide 9

Slide 9 text

問合せ管 理
 受注
 顧客
 管理
 在庫
 管理
 認証
 認可
 集荷
 連携
 商品
 管理
 配送
 連携
 ロケ
 管理
 決済
 検品
 出荷
 生産
 支援
 システムの機能


Slide 10

Slide 10 text

プロジェクトについて


Slide 11

Slide 11 text

お客様 工場 (検品&クリーニング) 店舗 (検品) 生産フローの追加


Slide 12

Slide 12 text

工場の新しい生産フローの追加
 
 ✓ 新しい生産フローは新規追加
 ✓ 既存機能との連携も
 いわゆる追加開発


Slide 13

Slide 13 text

プロジェクトの方針
 ✓ 新規追加部分はモデリングして作る
 ✓ 既存との連携部分はインターフェースを切り、
 既存ロジックと疎結合にする
 (腐敗防止層の導入)


Slide 14

Slide 14 text

問合せ管 理
 受注
 顧客
 管理
 在庫
 管理
 認証
 認可
 集荷
 連携
 商品
 管理
 配送
 連携
 ロケ
 管理
 決済
 検品
 出荷
 生産
 支援
 プロジェクトのスコープ


Slide 15

Slide 15 text

DDDでモデリングする
 モチベーション


Slide 16

Slide 16 text

入社当時(2016年)のリネットの状況
 ✓ ファットなコントローラー、ファットなORM
 ✓ ユニットテストは書きづらい、もしくはとても書きづらい (ほぼ書けない)


Slide 17

Slide 17 text

なんとかコードを整理したい


Slide 18

Slide 18 text

DDDの導入
 ✓ レイヤードアーキテクチャ、リポジトリ、サービスを導 入
 
 ☀ ドメインロジックを書く場所を確保


Slide 19

Slide 19 text

DDDを導入したけど
 ✓ モジュール設計が業務の実情にあっていない
 ✓ 実装基準でパターンを適用している
 
 ☂ コードの理解に時間がかかる


Slide 20

Slide 20 text

コードが業務を表現できていないので
 
 ✓ 業務の変更に弱い
 ✓ 影響範囲の把握に時間がかかる


Slide 21

Slide 21 text

業務とコードを近づけるために
 取り入れたのが
 型によるモデリング


Slide 22

Slide 22 text

業務のロジックにそって
 コードを整理する


Slide 23

Slide 23 text

モデリング適用の流れ


Slide 24

Slide 24 text

モデリング適用の流れ
 
 ✓ RDRAで要件定義
 ✓ 業務にそったモジュール定義
 ✓ コアドメインのモデリング
 ✓ ユースケースの開発
 ✓ 入出力(画面・DB)の開発


Slide 25

Slide 25 text

RDRAで要件定義


Slide 26

Slide 26 text

システムコンテキスト図
 開発対象と周辺システムの関係
 ビジネスコンテキスト図
 システムが使われる環境


Slide 27

Slide 27 text

ビジネスユースケース図
 利用シーンや業務フローの
 記述場所を洗い出す
 着荷の利用シーン


Slide 28

Slide 28 text

利用シーン図
 業務の内容を表現する
 ユースケースの入出力を定義する


Slide 29

Slide 29 text

モデリングに必要な用語がみつかる
 (ユビキタス言語)


Slide 30

Slide 30 text

業務にそったモジュール設計


Slide 31

Slide 31 text

全体の構成
 
 Cleaning
 ├── App
 │ ├── ACL
 │ ├── Coordinator
 │ ├── Repository
 │ └── Service
 ├── Domain
 │ ├── Model
 │ ├── Service
 │ └── Type
 └── Infra
 ├── API
 └── DB
 レイヤード
 アーキテクチャ


Slide 32

Slide 32 text

ドメインモデルの構成
 Cleaning/Domain/Model
 ├── Capacity
 ├── Item
 ├── Order
 ├── Pickup
 ├── Scheduling
 ├── Shipping
 ├── Ticketing
 └── Washing
 
 
 業務の用語で整理
 


Slide 33

Slide 33 text

コアドメインのモデリング


Slide 34

Slide 34 text

要件定義を進める中で核となる
 業務ロジックを見つける


Slide 35

Slide 35 text

今回のプロジェクトでは
 
 ✓ 注文のキャパシティ管理
 ✓ 作業予定・実績管理
 ✓ 在庫管理


Slide 36

Slide 36 text

最初にここから手を付ける


Slide 37

Slide 37 text

まずは必要な部品の整備


Slide 38

Slide 38 text

日時(DateTime)
 日付(Date)
 出荷日(ShippingDate)
 キャパシティ(Capacity)
 注文数(OrderCount)
 etc...


Slide 39

Slide 39 text

コアとなるロジックを開発


Slide 40

Slide 40 text

日程計算
 予定・実績比較
 キャパシティ算出
 配賦比率算出
 etc...


Slide 41

Slide 41 text

ユースケースの開発


Slide 42

Slide 42 text

開発したドメインロジックを含む
 ユースケースを開発
 
 入出力はインターフェースで定義
 (実装はしない)


Slide 43

Slide 43 text

ユースケースの開発を通して
 使う側の視点でドメインロジックが
 使えるものになっているか
 検証する


Slide 44

Slide 44 text

入出力(画面、DB)の開発


Slide 45

Slide 45 text

ユースケースで定義した
 インターフェースを実装


Slide 46

Slide 46 text

今回のプロジェクトでは
 画面とDBで作業を分担


Slide 47

Slide 47 text

インターフェースを定義しているので、
 コンフリクトを最小にして開発できる


Slide 48

Slide 48 text

まとめると


Slide 49

Slide 49 text

モデリング適用の流れ
 
 ✓ RDRAで要件定義
 ✓ 業務にそったモジュール定義
 ✓ コアドメインのモデリング
 ✓ ユースケースの開発
 ✓ 入出力(画面・DB)の開発


Slide 50

Slide 50 text

ドメインモデルの実例


Slide 51

Slide 51 text

事例1:作業予定日の算出


Slide 52

Slide 52 text

作業予定日の算出


Slide 53

Slide 53 text

生産管理の核となるロジック


Slide 54

Slide 54 text

式で表すと
 
 作業予定日 = 
 前工程の作業日 + 前工程の作業日数 + 
 工程の移動にかかる日数


Slide 55

Slide 55 text

たとえば、工場へ荷物がくる日
 (着荷日)
 
 着荷日 = 集荷日 + 移動にかかる日数


Slide 56

Slide 56 text

これをコードで表現する


Slide 57

Slide 57 text

class ArrivalDate
 {
 private $value;
 public function __construct(Date $value) 
 {
 $this->value = $value; 
 }
 public static function create( 
 PickupDate $pickupDate, 
 DeliveryDayCount $deliveryDayCount): self 
 {
 return (new self( $pickupDate->value()))
 ->add($deliveryDayCount->value());
 }
 ....
 着荷日(PHP)


Slide 58

Slide 58 text

class ArrivalDate
 {
 private $value;
 public function __construct(Date $value) 
 {
 $this->value = $value; 
 }
 public static function create( 
 PickupDate $pickupDate, 
 DeliveryDayCount $deliveryDayCount): self 
 {
 return (new self( $pickupDate->value()))
 ->add($deliveryDayCount->value());
 }
 ....
 着荷日(PHP)
 return (new self($pickupDate->value())) ->add($deliveryDayCount->value());


Slide 59

Slide 59 text

着荷日クラスで着荷日の算出を表現
 
 ドメインルールと実装が一致する


Slide 60

Slide 60 text

作業日は算出されるだけではない
 
 DBに記録され、呼び出される


Slide 61

Slide 61 text

記録した作業日を呼び出す
 
 コンストラクタでは
 ✓ DBに記録された作業日
 ✓ 画面から渡される作業日
 これらを呼び出すことを想定している


Slide 62

Slide 62 text

class ArrivalDate
 {
 private $value;
 public function __construct(Date $value) 
 {
 $this->value = $value; 
 }
 public static function create( 
 PickupDate $pickupDate, 
 DeliveryDayCount $deliveryDayCount): self 
 {
 return (new self($ pickupDate->value()))
 ->add($deliveryDayCount->value());
 }
 ...
 ここ
 ここの話はTechブログにも載せてます 
 DDDで生産日程のモデリング 
 https://blog.wh-plus.co.jp/entry/2019/12/17/000000


Slide 63

Slide 63 text

算出だけにこだわると
 毎回計算して出すことになる
 
 現実のシナリオに合わせて実装を
 用意する必要がある


Slide 64

Slide 64 text

事例2:予定・実績の比較


Slide 65

Slide 65 text

いきなりですが、
 物事は予定通りいきません


Slide 66

Slide 66 text

予定通りいけば、管理なんていりません


Slide 67

Slide 67 text

生産管理の基本は
 予定と実績の差異の把握


Slide 68

Slide 68 text

予定・実績・差異
 こちらで紹介されていたパターンを 参考にしました

Slide 69

Slide 69 text

予定・実績・差異


Slide 70

Slide 70 text

差異の検出はポリシーで対応
 
 ✓ 差異検出のルールは個別のクラス
 ✓ ポリシーはルールのリストを保持
 ✓ ポリシーで差異を検出する


Slide 71

Slide 71 text

なぜこうしたか?


Slide 72

Slide 72 text

ルールは業務に合わせて頻繁に変わる


Slide 73

Slide 73 text

個別の型でルールを表現
 ✓ ポリシーはルールの集合
 ✓ ルールの集合なので、追加・削除が容易
 ✓ 個別のルールに分かれることでルールの変更も容易


Slide 74

Slide 74 text

モデリング導入における
 3つのポイント


Slide 75

Slide 75 text

型を使ったモデリング


Slide 76

Slide 76 text

固有の型をクラスで表現する
 
 クラスが増える
 
 本当に必要?という心理的障壁


Slide 77

Slide 77 text

たとえば、集荷日、着荷日、出荷日
 全部Dateでも良いでのは?


Slide 78

Slide 78 text

実際に着荷日などの振る舞いは
 ほとんどDateに委譲している


Slide 79

Slide 79 text

Dateだけでも実装は可能


Slide 80

Slide 80 text

それでも着荷日があると
 ✓ 着荷日の算出を着荷日に定義できる
 ✓ Dateの中で着荷日に必要な操作を定義できる
 ✓ 他のクラスで着荷日を使うことを宣言できる


Slide 81

Slide 81 text

オブジェクト指向設計の
 視点の転換が必要


Slide 82

Slide 82 text

オブジェクト指向を使って
 
 ✘ 実装を共通化
 
 ⭕ 型を使ってモデリング


Slide 83

Slide 83 text

ドメインから始める


Slide 84

Slide 84 text

画面、DBを最後につくる


Slide 85

Slide 85 text

これも心理的な障壁が高い


Slide 86

Slide 86 text

ドメインから始めるために
 作業日の算出、差異の検出のような
 解くべき問題を探すことが大事


Slide 87

Slide 87 text

部品がそろったら、ユースケース


Slide 88

Slide 88 text

ここでは画面、DBの入出力は
 インターフェースを定義する
 
 実装の詳細に立ち入らない


Slide 89

Slide 89 text

インターフェースを使って
 ドメインロジックがユースケースとして
 使えるようにする


Slide 90

Slide 90 text

画面、DBの実装よりも
 ドメインロジックの完成に
 意識を集中する


Slide 91

Slide 91 text

とはいえ、
 インターフェースを実装してみたら
 DBでは保存できない
 
 なんてことにならないように
 配慮は必要です


Slide 92

Slide 92 text

作る順番の転換
 
 ✘ 画面、DBを含めたユースケースから
 
 ⭕ コアドメインを含むドメインから


Slide 93

Slide 93 text

小さな型を用意する


Slide 94

Slide 94 text

日付、数量、IDなど
 共通で使う小さな型を先に定義する


Slide 95

Slide 95 text

言語の基本型(int, string...)がドメインに入ると
 ✓ 後から取り除くのが難しい
 ✓ モデリングが崩れる
 ✓ 型の導入が必要か不要か議論が頻繁に起きる
 (そして不要に流れる)


Slide 96

Slide 96 text

これを防ぐため
 
 ✓ 先に小さな型を用意する
 ✓ 参照実装となる小さな型でモデリングしている部分を 作る
 ✓ 可能であればペアプロで


Slide 97

Slide 97 text

小さな型が浸透すると
 ✓ ドメインの中で言語の基本型を使用するのは割れ窓 になる
 ✓ 言語の基本型がドメインの中で使われるのを防ぐこと ができる


Slide 98

Slide 98 text

型を導入するタイミング
 
 ✘ 必要になったら型を導入する
 
 ⭕ あらかじめ小さな型を導入する


Slide 99

Slide 99 text

まとめ


Slide 100

Slide 100 text

今回はプロジェクトでの
 モデリングの事例を話しました


Slide 101

Slide 101 text

ホワイトプラスでは
 2016年からDDDの導入を進めています


Slide 102

Slide 102 text

今日は現場でドメインモデリングを
 導入する際の
 ✓ プロジェクトの進め方
 ✓ 導入のポイント
 を紹介しました


Slide 103

Slide 103 text

ご清聴ありがとうございました