Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

ドメイン駆動設計 失敗したことと成功したこと

15,573 views

Published on

その時は最善の実装だと思っていたことでも、月日が立つことで、それは間違いだったと気づくことがあります。
5年という歳月はそれを気づかせるには十分な時間で、
DDDをやり始めた初期の頃に書かれたコードは良くディスられたりしています。
そのコードは何を失敗していたのか?そして、それは改善するために改善した事とは?
BIGLOBEにおける"今"のいいコードの書き方をできる限り具体的な事例を元に紹介します。

Published in: Engineering
  • Be the first to comment

ドメイン駆動設計 失敗したことと成功したこと

  1. 1. © BIGLOBE Inc. ドメイン駆動設計 失敗したことと成功したこと 2018/9/26 ビッグローブ株式会社 小林 映里奈
  2. 2. 2 © BIGLOBE Inc. 自己紹介 小林 映里奈(こばやし えりな) • @eri_twin • 2015年度入社の4年目 所属、担当業務 • ITシステム本部 ビッグローブ光開発チーム • ビッグローブ光の業務システムの開発
  3. 3. 3 © BIGLOBE Inc. 今日のテーマ 失敗したことと成功したこと
  4. 4. 4 © BIGLOBE Inc. ドメイン駆動設計への愛をこめて!
  5. 5. 5 © BIGLOBE Inc. agenda ◆ ドメイン欠乏症との戦い ~実践と結果~ ◆ つらい現実からドメインを守る 3つの盾 ・Form ・Converter ・Adapter
  6. 6. 6 © BIGLOBE Inc. ドメイン欠乏症との戦い ~実践と結果~ 「ドメインにロジックを書く」を実現するための試行錯誤
  7. 7. 7 © BIGLOBE Inc. ドメイン欠乏症 手続き型のイメージで、ドメイン以外にロジックを書いてしまう ↓アプリケーション層にロジックがある例
  8. 8. 8 © BIGLOBE Inc. ドメイン欠乏症 ドメインが出てこない… 👉 業務ロジックなど、業務の関心事は ドメインに書こう! たとえば、 前提条件のチェックは業務ロジック。 他には?
  9. 9. 9 © BIGLOBE Inc. なにをドメインに書くべきか Q. どこまでがドメイン(=業務ロジック)なのか 業務ロジックに該当しそうなもの、たとえば - 業務に関連するドメインを取得する - 各ドメインが業務の前提条件を満たしているかチェック - ドメインの状態を変更する - 変更された状態のドメインを永続化する etc…
  10. 10. 10 © BIGLOBE Inc. なにをドメインに書くべきか Q. どこまでがドメイン(=業務ロジック)なのか 業務ロジックに該当しそうなもの、たとえば - 業務に関連するドメインを取得する - 各ドメインが業務の前提条件を満たしているかチェック - ドメインの状態を変更する - 変更された状態のドメインを永続化する etc… A. 関連ドメインの取得・チェック・状態変更までを ドメインで扱う業務とする
  11. 11. 11 © BIGLOBE Inc. ドメインの責務はここ
  12. 12. 12 © BIGLOBE Inc. ドメイン欠乏症対策 👉 関連ドメイン取得のためドメイン層でリポジトリのDI 👉 前提条件チェック、変更後のエンティティ返却がドメインの責務 ↓ドメイン層のOrderDateにロジックを委譲
  13. 13. 13 © BIGLOBE Inc. ドメイン欠乏症対策 👉 業務ロジックをドメインに委譲 👉 if文がなくなって見通しが良くなった ↓アプリケーション層はシンプルに
  14. 14. 14 © BIGLOBE Inc. ドメイン欠乏症対策 🙆 ドメイン層にビジネスロジックがまとまる 🙆 アプリケーション層の見通しを良くできた 🙅‍リポジトリへのアクセスが入るため副作用が多く、 ドメイン層のテストがつらい → モック化すればいいと思ってたけど、それも大変だった → 実際やってみると、ドメインに集めすぎた感がある どこまでを業務(ドメイン)とみなすか、考え直す
  15. 15. 15 © BIGLOBE Inc. 続:なにをドメインに書くべきか Q. どこまでがドメイン(=業務ロジック)なのか 業務ロジックに該当しそうなもの、たとえば - 業務に関連するドメインを取得する - 各ドメインが業務の前提条件を満たしているかチェック - ドメインの状態を変更する - 変更された状態のドメインを永続化する etc… A. リポジトリへのアクセスはアプリケーション層へ チェック・状態変更までをドメインで扱う業務とする
  16. 16. 16 © BIGLOBE Inc. 続:ドメインの責務はここ
  17. 17. 17 © BIGLOBE Inc. ドメイン 👉 必要な情報を受け取り、 イベント = 永続化に必要な情報をまとめたクラス を作る 👉 ドメインの内部に閉じたロジックはドメインに書く
  18. 18. 18 © BIGLOBE Inc. ドメインサービス 👉 ドメインサービス(ドメイン層) 👉 ドメインサービスは業務の単位で分けている。 例では申込のユースケースなので、申込に関する業務ロジックを持つ
  19. 19. 19 © BIGLOBE Inc. APサービス全体像 イベントを作る 永続化
  20. 20. 20 © BIGLOBE Inc. ドメイン欠乏症対策2 🙆 サービス層の見通しが良い 🙆 リポジトリアクセス→イベント作成→永続化 の流れが わかりやすい 🙆‍副作用がないので、ドメイン層はテストしやすい これが今のところ良いかんじなので、継続中 Q.‍最初にすべてのエンティティを取得するのは冗長? 余計なリポジトリアクセスが多いのでは? A. そうでもない。 想定よりも無駄になるエンティティはかなり少なかった。
  21. 21. 21 © BIGLOBE Inc. 中身のつまったドメインをつくろう!
  22. 22. 22 © BIGLOBE Inc. つらい現実からドメインを守る 3つの盾 内部ではドメインを充実させていく一方、 外部からはさまざまな現実が攻めてきます
  23. 23. 23 © BIGLOBE Inc. 現実の世界 domain service infrastructure 現実は想定外のさまざまなことが起きる お店の説明と違う! クーリングオフ したいです オーダー修正する時は XXのYYをZZZにして さらにAAAのBBを… このパターンの番号体系 が昨⽇日からS-­inしました K社 N社 ドメインの状態にはないけど、 契約開始後キャンセルが必要… ⼀一旦オーダーを取消 してやりなおします ええー!!
  24. 24. 24 © BIGLOBE Inc. domain application infrastructure user interface DB formAPI File converter adapter つらい現実からドメインを守る💪 3つの盾 👉 form/request: 複雑なバリデーションルールから守る 👉 converter: 複雑なIF仕様から守る 👉 adapter: 物理データ構造から守る
  25. 25. 25 © BIGLOBE Inc. domain application infrastructure user interface DB formAPI File converter adapter つらい現実からドメインを守る💪 3つの盾 👉 form/request: 複雑なバリデーションルールから守る 👉 converter: 複雑なIF仕様から守る 👉 adapter: 物理データ構造から守る
  26. 26. 26 © BIGLOBE Inc. 複雑なバリデーションルールのつらみ 😭 APIが多すぎる! → 申込経路によってサービス仕様が違う → 経路Aと経路Bでバリデーションを分けたい → APIをユースケース単位で作成するので数が増える → 同じ商品の新規申込APIが50本とかあるような規模 😭 ドメイン層がバリデーションルールで汚れてしまう 🎈 form/requestとは バリデーションルールをユーザインターフェース層に出し APIや経路ごとにバリデーションを管理する!
  27. 27. 27 © BIGLOBE Inc. Form 👉 @Patternにオブジェクトのバリデーションルールを書く 👉 ドメインオブジェクトに変換して返すgetterを用意 パラメータごとにXX(ドメイン名)Formを作る ex) ユーザIDを受け取るためのUserIdForm
  28. 28. 28 © BIGLOBE Inc. Request 👉 先述のFormクラスをまとめたリクエストクラス API単位のリクエストパラメータを表現している 👉 API固有のパラメータの必須/非必須や相関チェックをここで管理する 👉 Formの値がnullだとオブジェクトをgetしたときに例外になるので nullの場合はバリデーションエラーにするアノテーションを作った (@ValueObjectNotEmpty)
  29. 29. 29 © BIGLOBE Inc. API 👉 リクエストで受け取ったパラメータを バリデーション済みのオブジェクトとして取り出す
  30. 30. 30 © BIGLOBE Inc. domain application infrastructure user interface DB formAPI File converter adapter つらい現実からドメインを守る💪 3つの盾 👉 form/request: 複雑なバリデーションルールから守る 👉 converter: 複雑なIF仕様から守る 👉 adapter: 物理データ構造から守る 💪 守った!
  31. 31. 31 © BIGLOBE Inc. domain application infrastructure user interface DB formAPI File converter adapter つらい現実からドメインを守る💪 3つの盾 👉 form/request: 複雑なバリデーションルールから守る 👉 converter: 複雑なIF仕様から守る 👉 adapter: 物理データ構造から守る 💪
  32. 32. 32 © BIGLOBE Inc. 複雑なIF仕様のつらみ 😭 大企業様から提供されるIF仕様書はむずかしい → 写し間違えて項目ずれるの怖い → 項目数が多いと確認も大変 😭 社内と社外では世界観が違う → ドメインモデルと異なる形のデータ群を求められる → せっかく作ったモデルはIF仕様に引っ張られたくない… 🎈 Converterとは 複雑なIF仕様をそのままコードに落とす! 外部都合のIFから自分たちのドメインモデルを守る!
  33. 33. 33 © BIGLOBE Inc. Converter: 複雑なIF仕様から守る IF仕様書をそのままコードに落とす 👉 外部のドメインと自分たちのドメインの言葉を紐付ける このクラスのコードが言葉の差を埋める設計資料そのものになる 👉 どのエンティティのフィールドかひと目でわかる ex) v.会員()は会員エンティティにあるデータを使っている 👉 サンプルデータをそのまま期待値に使ったテストが書ける! ↑外部のドメイン ⾃自分たちのドメイン
  34. 34. 34 © BIGLOBE Inc. Converter: 複雑なIF仕様から守る ドメインモデルの世界観を守る 👉 IFの契約者住所はアパート名を含むが、モデルは住所とアパート名が別 👉 converterで住所とアパート名を繋げたデータを作る 👉 モデルは変えず、IF仕様との世界観の差はconverterが吸収する
  35. 35. 35 © BIGLOBE Inc. domain application infrastructure user interface DB formAPI File converter adapter つらい現実からドメインを守る💪 3つの盾 👉 form/request: 複雑なバリデーションルールから守る 👉 converter: 複雑なIF仕様から守る 👉 adapter: 物理データ構造から守る 💪 💪
  36. 36. 36 © BIGLOBE Inc. domain application infrastructure user interface DB formAPI File converter adapter つらい現実からドメインを守る💪 3つの盾 👉 form/request: 複雑なバリデーションルールから守る 👉 converter: 複雑なIF仕様から守る 👉 adapter: 物理データ構造から守る 💪 💪
  37. 37. 37 © BIGLOBE Inc. 物理データのつらみ 前提:O/RマッパーはMyBatisを使っている 😭 データをエンティティに変換するマッピングがつらい
  38. 38. 38 © BIGLOBE Inc. 物理データのつらみ Q. Javaのクラス自動生成してくれるO/RM使わないの? A. 扱うデータ量が非常に多いので、チューニング必須。 SQLをカスタマイズしやすいO/RMを使いたい。 MyBatisのよいところ 👉 SQLを直に書ける(チューニングできる) (超大事) MyBatisのつらいところ 👉 xmlでマッピングを書くのが大変 👉 コンパイルエラーにならないので実行時エラーが出る 👉 エラーがわかりにくいので原因の調査に苦労する 🎈 Adapterとは よいところだけを活かす! MyBatisを使いながらマッピングはJavaで行う!
  39. 39. 39 © BIGLOBE Inc. Adapter Javaの基本的なクラスでDBから値を取得する。 👉 VARCHER型はString, DATE型はLocalDate(LocalDateTime) 👉 値を取得する段階ではバリューオブジェクトへの変換処理はしない バリューオブジェクトへの変換ロジックはadapterに集める
  40. 40. 40 © BIGLOBE Inc. domain application infrastructure user interface DB formAPI File converter adapter つらい現実からドメインを守る💪 3つの盾 👉 form/request: 複雑なバリデーションルールから守る 👉 converter: 複雑なIF仕様から守る 👉 adapter: 物理データ構造から守る 💪 💪 💪
  41. 41. 41 © BIGLOBE Inc. domain application infrastructure user interface DB formAPI File converter adapter つらい現実からドメインを守る💪 まとめ 3つの盾 👉 form/Request: 複雑なバリデーションルールから守る 👉 converter: 複雑なIF仕様から守る 👉 adapter: 物理データ構造から守る 💪 💪 💪
  42. 42. 42 © BIGLOBE Inc. こうしてドメインは守られた…☆
  43. 43. 43 © BIGLOBE Inc. ドメインに愛をこめて! 業務ロジックで充実&外部要因から守る!
  44. 44. 44 © BIGLOBE Inc. まとめ これまでの取り組みの一部を紹介しました。 5年を経た失敗と成功をまとめましたが、 これは『今のところ』の結果です。 明日にはまたより良い成功が見つかるかもしれません。 社内ではいろんなチームが日々、試行錯誤しています。 ビッグローブの失敗と成功はまだまだ続いていきます。 一緒にDDDやっていきましょう 💪
  45. 45. BIGLOBE Internal Use Only

×