現場で実践すべきDDDモデリングのポイント3つ / Three points of DDD modeling

現場で実践すべきDDDモデリングのポイント3つ / Three points of DDD modeling

OOC2020での発表資料です

現場でDDDと型によるモデリングを実践するにあたり、導入するためにしたこと、導入のポイントを実践した経験を元に紹介しています。

内容
- DDDモデリング導入のモチベーション
- DDD導入の流れ
- 実践例
- DDD導入のポイント

33977264d18863fff5608189b475f1aa?s=128

Yamaki Hiroshi

February 16, 2020
Tweet

Transcript

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


  2. 氏名:八巻 紘士 (@yamak1i)
 所属:株式会社ホワイトプラス システム開発G グループマネージャー
 経歴:
 大手化学会社のシステム子会社でSIer、Webの受託会社を経て
 2016年よりホワイトプラスにJoin
 リネット全般のサービス開発を担当する


    ホワイトプラスにおけるDDDの導入を主導
 3歳と1歳の2人の息子のお父さん
 趣味:読書
 特技:積ん読(読めていない)
 自己紹介

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


  4. ホワイトプラスについて


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


  7. 今回の話


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


  9. 問合せ管 理
 受注
 顧客
 管理
 在庫
 管理
 認証
 認可
 集荷


    連携
 商品
 管理
 配送
 連携
 ロケ
 管理
 決済
 検品
 出荷
 生産
 支援
 システムの機能

  10. プロジェクトについて


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


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


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


  14. 問合せ管 理
 受注
 顧客
 管理
 在庫
 管理
 認証
 認可
 集荷


    連携
 商品
 管理
 配送
 連携
 ロケ
 管理
 決済
 検品
 出荷
 生産
 支援
 プロジェクトのスコープ

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


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


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


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


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


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


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


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


  23. モデリング適用の流れ


  24. モデリング適用の流れ
 
 ✓ RDRAで要件定義
 ✓ 業務にそったモジュール定義
 ✓ コアドメインのモデリング
 ✓ ユースケースの開発


    ✓ 入出力(画面・DB)の開発

  25. RDRAで要件定義


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


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


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


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


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


  31. 全体の構成
 
 Cleaning
 ├── App
 │ ├── ACL
 │ ├──

    Coordinator
 │ ├── Repository
 │ └── Service
 ├── Domain
 │ ├── Model
 │ ├── Service
 │ └── Type
 └── Infra
 ├── API
 └── DB
 レイヤード
 アーキテクチャ

  32. ドメインモデルの構成
 Cleaning/Domain/Model
 ├── Capacity
 ├── Item
 ├── Order
 ├── Pickup


    ├── Scheduling
 ├── Shipping
 ├── Ticketing
 └── Washing
 
 
 業務の用語で整理
 

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


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


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


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


  37. まずは必要な部品の整備


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


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


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


  41. ユースケースの開発


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


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


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


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


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


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


  48. まとめると


  49. モデリング適用の流れ
 
 ✓ RDRAで要件定義
 ✓ 業務にそったモジュール定義
 ✓ コアドメインのモデリング
 ✓ ユースケースの開発


    ✓ 入出力(画面・DB)の開発

  50. ドメインモデルの実例


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


  52. 作業予定日の算出


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


  54. 式で表すと
 
 作業予定日 = 
 前工程の作業日 + 前工程の作業日数 + 


    工程の移動にかかる日数

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


  56. これをコードで表現する


  57. 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)

  58. 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());

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


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


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


  62. 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

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


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


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


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


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


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

  69. 予定・実績・差異


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


  71. なぜこうしたか?


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


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


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


  75. 型を使ったモデリング


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


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


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


  79. Dateだけでも実装は可能


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


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


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


  83. ドメインから始める


  84. 画面、DBを最後につくる


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


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


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


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


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


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


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


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


  93. 小さな型を用意する


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


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


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


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


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


  99. まとめ


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


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


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


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