Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Learning Domain-Driven Design輪読会 #最終回

issei
January 12, 2023

Learning Domain-Driven Design輪読会 #最終回

issei

January 12, 2023
Tweet

More Decks by issei

Other Decks in Programming

Transcript

  1. Learning Domain-Driven Design 輪読会 #最終回 Appendix A. Applying DDD: A

    Case Study 株式会社Showcase Gig 寺田 一生
  2. Appendix A. Applying DDD: A Case Study • この付録は、著者のドメイン駆動設計の旅路がどう始まったかを紹介する •

    Marketnovus(仮)というスタートアップ企業の話 • Marketnovusは、設立当初からDDDを採用していた • 長年に渡ってDDDのありとあらゆる間違いを犯してきたし、そこから学び修正する 機会もあった • こんな例からDDDパターンやDDDの実践がソフトウェアプロジェクトの成功に与え る効果を示したい
  3. Appendix A. Applying DDD: A Case Study • このケーススタディは2つのパートで構成される •

    第一部はMarketnovusの5つの境界付けられたコンテキストについて、どのような デザイン上の決定がなされ、どのような結果が出たのか、そのストーリーを紹介す る • 第二部で、これらのストーリーが本書で学んだ内容をどのように反映しているかを 説明する • Marketnovusはすでに存在しない会社です
  4. Business Domain • あなたが製品やサービスを作っているとする • Marketnovusでは、マーケティング関連の雑務をすべてアウトソースすることができる • Marketnovusの専門家は、あなたの製品のマーケティング戦略を考え出す • コピーライターやグラフィックデザイナーが、バナーやランディングページなどを大量に作成し、そ

    れを使って製品を宣伝する広告キャンペーンを展開する • これらのキャンペーンで発生したすべてのリードは、Marketnovusの販売代理店が担当し、彼らが 電話をかけて製品を販売することになる • このプロセスを右図に示す
  5. Business Domain • 最も重要なことは、このマーケティングプロセスには最適化できる箇所が多くあること ◦ そして、これこそ分析部門が担当していたこと • 最も効果のあるキャンペーンを特定したり、最も効果的なクリエイティブ素材を評価したり、販売代 理店が最も有望なリードに取り組むようにするなど、Marketnovusとその顧客が最大の利益を得 られるように、すべてのデータを分析した

    • Marketnovusは自己資金で運営されている会社なので、できるだけ早く活動を開始する必要が あった • その結果、会社設立直後のソフトウェアシステムの最初のバージョンは、バリューチェーンの最初 の3分の1を実装しなければならなかった ◦ 外部の出版社との契約と統合を管理するシステム ◦ デザイナーがクリエイティブ素材を管理するためのカタログ ◦ 広告キャンペーンを実施するためのキャンペーン管理ソリューション
  6. Business Domain • 私はやることの多さに圧倒され、この複雑なビジネス領域のすべてを理解する方法を見つけなけ ればならなかった • 幸いなことに、仕事を始める少し前に、適切な本を読んだ • Eric Evansの代表作である「Domain-Driven

    Design」 • 私が長い間求めていた「ビジネスロジックの設計と実装の方法」の答えを提供してくれた • とはいえ、一読して理解できるほど簡単な本ではなかった • しかし、「戦術設計」の章を読んだだけで、DDDをしっかり理解できたような気がした • 当初、どのようにシステムが設計されたと思いますか?
  7. Bounded Context #1: Marketing • 私たちの最初のアーキテクチャスタイルは、「あらゆるところに集約する」という言葉に集約される • 代理店、キャンペーン、プレースメント、ファネル、パブリッシャーなど、要件に含まれるあらゆる名 詞が集合体であると宣言されていた •

    これらの集合体はすべて、巨大で単一な、境界付けられたコンテキストに存在しており最近誰もが 警告する大きくて怖いモノリスになっていた • そしてもちろん、それらは集約ではない • トランザクションの境界を提供することもなく、振る舞いもほとんどありませんでした • すべてのビジネスロジックは、巨大なサービスレイヤーに実装されていました。 •
  8. Bounded Context #1: Marketing • ドメインモデルの実装を目指したものの、アクティブレコードパターンで終わってしまった場合、それ はしばしば「ドメインモデル貧血症」というアンチパターンだと言われる • 今にして思えば、この設計はドメインモデルを実装してはいけないという規則でもあったかのような 例であった

    • しかし、ビジネスの観点から見ると、状況はまったく違っていた • ビジネスの観点からすれば、このプロジェクトは大成功だった • アーキテクチャに欠陥があったにもかかわらず、実用的なソフトウェアを非常にアグレッシブな市 場投入期間で提供することができた • どうやって実現したのか?
  9. Bounded Context #1: Marketing • 私たちは、どうにかして堅牢なユビキタス言語を作り上げた • 私たちは誰もオンライン・マーケティングの経験がありませんでしたが、専門家と会話を交わすこと ができた •

    このように、ドメインエキスパートとの円滑なコミュニケーションにより、私たちはあっという間にビジ ネスドメインを把握し、そのビジネスロジックを実装することができた • 確かに、かなり大きなモノリスでしたが、ガレージにいる2人の開発者にとっては、これで十分だっ た • 非常にアグレッシブな市場投入への時間の中で、実用的なソフトウェアを作り上げることができた A kind of magic
  10. Bounded Context #2: CRM • キャンペーン管理ソリューションを導入して間もなく、リードが流れ込んできて、あわただしくなって きた • 営業担当者は、リードとそのライフサイクルを管理するための堅牢な顧客関係管理(CRM)システ ムを必要としていた

    • CRMは、送られてくるすべてのリードを集約し、さまざまなパラメータに基づいてグループ化し、世 界中の複数のセールスデスクに配信する必要があった • また、リードのライフサイクルの変化をクライアントに通知したり、リードの追加情報を補完するた めに、クライアントの社内システムと統合する必要があった
  11. Bounded Context #2: CRM • 最初の実装アプローチは、戦術的なパターンに焦点を当て続けることだった • ここでも、あらゆる名詞を集合体とし、同じモノリスに押し込んでいった • しかし、今回は最初から何か違和感があった

    • 例えば、CRMLeadやMarketingLead、MarketingCampaignやCRMCampaignといった具合に、 「集合体」の名前に厄介な接頭辞を付けていることがあまりにも多くなった • 興味深いことに、専門家との会話では、このような接頭辞を使うことはありませんでした。なぜか、 彼らはいつも文脈から意味を理解していた • そこで、ドメイン駆動設計には、これまで無視してきた境界付きコンテキストという概念があることを 思い出した More “aggregates”!
  12. Bounded Context #2: CRM • Evansの本の関連する章を読み返すと、境界付きコンテキストは、私たちが経験していた問題と全 く同じ問題を解決するものであり、ユビキタス言語の一貫性を守るものであることを知った • その頃、Vaughn Vernonは「Effective

    Aggregate Design」という論文を発表していました。この論 文は、私たちが集約を設計する際に犯していたすべての誤りについて書かれていた • 私たちは集約をデータ構造として扱っていたが、集約はシステムのデータの一貫性を守るという、 より大きな役割を担っていた • 私たちはこの発見を反映してCRMソリューションの設計をやり直した More “aggregates”!
  13. Bounded Context #2: CRM • 私たちはまず、モノリスをMarketingとCRMという2つの異なる境界のあるコンテキストに分割する ことから始めた • もちろん、ここでマイクロサービス化するのではなく、ユビキタス言語を保護するための必要最低 限のことをしただけ

    • しかし、新しいコンテキストであるCRMでは、マーケティング・システムで犯したのと同じ過ちを繰り 返さないようにした • ドメインモデル貧血症はもういらない Solution design: Take two
  14. Bounded Context #2: CRM • ここでは、規則通りな集約を持つ本物のドメインモデルを実装する • 特に、こう誓った ◦ 各トランザクションは、集約の1つのインスタンスにのみ影響する

    ◦ ORMの代わりに、各集約自体がトランザクションのスコープを定義する ◦ サービスレイヤーは非常に厳しいダイエットを行い、すべてのビジネスロジックは対応する集 約にリファクタリング Solution design: Take two
  15. Bounded Context #2: CRM • 私たちは、正しい方法で物事を行うことに熱中していた • しかし、すぐに、適切なドメインモデルをモデリングするのは難しいことが分かった • マーケティングシステムと比較すると、すべてに時間がかかった

    • トランザクションの境界を最初に正しく設定するのはほとんど不可能で、少なくともいくつかのモデ ルを評価し、テストして、後々考えてもみなかったモデルが正しいということになった • 「正しい」方法で物事を行う代償として、多くの時間が必要だったのです。そのうちに、納期に間に 合わないことが誰の目にも明らかになった。そこで、経営陣はいくつかの機能の実装を、データ ベース管理者チームに任せることにした。 • Solution design: Take two
  16. Bounded Context #2: CRM • この状況により、最も複雑なビジネス・エンティティの1つであるリードが、暗黙のうちに境界線を持 つコンテキストに分割されることになった • その結果、2つのチームが同じビジネス・コンポーネントに取り組み、密接に関連する機能を実装し ていたが、チーム間の交流は最小限にとどまっていた

    • ユビキタス言語?勘弁してくださいよと言わんばかりに、各チームはビジネス・ドメインとそのルー ルを記述するための独自の語彙を持っていた • モデルには一貫性がなく共有された理解はなかった • 知識は重複し、同じルールが二度実装され、ロジックが変わると、すぐに実装が狂ってしまう Tower of Babel 2.0
  17. Bounded Context #2: CRM • 言うまでもなく、このプロジェクトは納期に間に合わず、バグだらけだった • 何年間も水面下で進行していた生産上の問題が、我々の最も貴重な資産であるデータを破壊して しまった •

    この混乱から抜け出す唯一の方法は、リード集約を完全に書き直すことだった • それは簡単なことではありませんでしたが、この混乱はとてもひどく、他に方法はなかった Tower of Babel 2.0
  18. Bounded Context #3: Event Crunchers • CRM システムの導入後、暗黙のサブドメインがMarketingとCRMにまたがっていることが疑われ た •

    顧客からのイベントを処理するプロセスを変更する必要がある場合、MarketingとCRMの両方の コンテキストに変更を加える必要があった • このプロセスは概念的にはどちらにも属さないので、図に示す「event crunchers」という専用のコ ンテキストに、このロジックを抽出することにした
  19. Bounded Context #3: Event Crunchers • 私たちはデータを移動させることで利益を得ているわけではありませんし、既製のソリューションを 利用することもできないので、Event Crunchersはサポート用のサブドメインに似ており、そのよう に設計した

    • 今回は派手さはなく、レイヤードアーキテクチャといくつかのシンプルなトランザクションスクリプト だ • このソリューションはとてもうまくいきましたが、それはしばらくの間だけだった • ビジネスが進化するにつれて、Event Crunchersにはより多くの機能が実装されるようになりまし た。ビジネス・インテリジェンス(BI)担当者が、新しいコンタクトをマークするフラグ、様々な初回イ ベントをマークするフラグ、ビジネス上の不確定要素を示すフラグなどを要求したのが始まりだった • 最終的には、これらのシンプルなフラグが、複雑なルールと不変条件を持つ真のビジネスロジック へと発展していった
  20. Bounded Context #3: Event Crunchers • 最初はトランザクションスクリプトだったものが、本格的なコアサブドメインに発展した • 残念ながら、複雑なビジネスロジックをトランザクションスクリプトとして実装すると、良いことは何も ない

    • 複雑なビジネスロジックに対応できるような設計をしなかったため、非常に大きな泥の塊になって しまった • コードベースを修正するたびにコストがかさみ、品質も低下し、Event Crunchersの設計を見直す ことを余儀なくされた • 私たちは1年後にそれを実行し、その頃には、ビジネスロジックは非常に複雑になっており、イベン トソーシングでしか対応できなくなっていた • 私たちは、イベントクランチャーのロジックをイベントソース型のドメインモデルにリファクタリング し、他の境界付けられたコンテキストがそのイベントをサブスクライブするようにした
  21. Bounded Context #4: Bonuses • ある日、セールスデスクのマネージャーから、これまで手作業で行っていた単純かつ退屈な作業、 つまり販売代理店の手数料計算を自動化してほしいという依頼があった • 月に一度、各代理店の売上高に占める割合を計算し、管理者に報告するだけという簡単なもの だった

    • 前回同様、これがコアサブドメインになるのかどうか、検討し、答えは「ノー」だった • 私たちは何も新しいことを発明していないし、このプロセスでお金を稼いでいるわけでもない • もし、既存の実装を購入することが可能であれば、間違いなくそうするだろう • コアでもなく、汎用でもなく、サポートする別のサブドメインです。次図に示すように、「スマート」な サービスレイヤーによって管理されるアクティブレコードオブジェクトというソリューション
  22. Bounded Context #4: Bonuses • このプロセスが自動化されると、社内の誰もがクリエイティブになった • アナリストたちは、このプロセスを徹底的に最適化しようと考えた • さまざまなパーセンテージを試してみたり、販売額や価格とパーセンテージを結びつけてみたり、

    さまざまな目標を達成することで追加のコミッションを受け取れるようにしたり、いろいろなことを考 えた • 最初の設計がうまくいかなかったのはいつだったと思いますか? • またしても、コードベースが手に負えない泥の塊になってしまったのだ。お金を扱う以上、小さなバ グが大きな結果を生むこともある
  23. Bounded Context #4: Bonuses • Event Crunchersプロジェクトと同様に、ある時点で私たちはもう耐え切れなくなった • 古いコードを捨て、今度はイベントソースドメインモデルとして、ソリューションを一から書き直さな ければならなかった

    • そして、Event Crunchersプロジェクトと同じように、ビジネスドメインも最初はサポートに分類され た。しかし、システムが進化するにつれて、このドメインは次第にコアサブドメインに変化していきま した。しかし、この2つの境界付けられたコンテキストの間には、顕著な違いがある Design: Take two
  24. Bounded Context #5: The Marketing Hub • 当社の経営陣は、収益性の高い新しい業種を探していた • そこで、大量のリードを生成する当社の能力を活用し、これまで取引のなかった小規模なクライア

    ントに販売することにした • このプロジェクトは、 “marketing hub”と呼ばれていた • 経営陣はこの事業領域を新たな収益機会として定義していたので、明らかにコアサブドメインで あった • そこで、設計面ではイベントソースドメインモデルとCQRSという大鉈を振るった • また、当時はマイクロサービスという新しいバズワードが流行り始めており、試してみることにした • 私たちのソリューションは、次図に示すような実装だった
  25. Bounded Context #5: The Marketing Hub • 私たちは、サービスが小さければ小さいほど良いと考え、積極的にマイクロサービスに取り組んだ • そこで、集約の周りにサービス境界を作りました

    • DDDの用語で言うと、各集約はそれ自体が境界付けられたコンテキストになる • 当初、この設計は素晴らしいものだった • この設計によって、それぞれのサービスを特定のニーズに従って実装することができた • イベントソーシングを使うのは1つだけで、残りはステートベースの集約で、さらに、これらのサービ スはすべて独立して保守・進化させることができた Micro what?
  26. Bounded Context #5: The Marketing Hub • しかし、システムが大きくなるにつれて、それらのサービスはどんどんおしゃべりになっていった • 最終的には、ほぼすべてのサービスが、その操作の一部を完了するために、他のすべてのサー

    ビスからデータを必要とするようになった • その結果、分離されたシステムのつもりが、結局は分散型モノリスになってしまい、メンテナンスが 大変なことになった • 残念ながら、このアーキテクチャにはより根本的な問題がもう一つあった • Marketing Hubを実装するために、ビジネスドメインをモデリングするための最も複雑なパターンで ある、ドメインモデルとイベントソースドメインモデルを使用してそれらのサービスを丁寧に作り込ん でいった • しかし、それはすべて無駄だった Micro what?
  27. Bounded Context #5: The Marketing Hub • この企業はMarkting Hubをコアサブドメインとみなしていたにもかかわらず、技術的な複雑さは皆 無だった

    • その複雑なアーキテクチャの背後には、非常にシンプルなビジネスロジックがあり、それは単なる アクティブレコードを使って実装できたほどシンプルなものだった • 結局のところ、ビジネスパーソンは、巧妙なアルゴリズムを使ってではなく、他社との既存の関係を 活用して利益を得ようと考えていたのだ • 結局、技術的な複雑さの方がビジネス的な複雑さよりはるかに大きかった • このような複雑性の不一致を、私たちは「偶発的複雑性」という言葉で表現していますが、私たち の最初の設計は、まさにそのようなものになってしまった • このシステムは、オーバーエンジニアリングだった The real problem
  28. Part2: Discussion • Marketing、CRM、Event Crunchers、Bonuses、The Marketing Hubという5つの境界コンテクス トについて話した • もちろん、Marketnovusのような広いビジネス・ドメインには、もっとたくさんの境界付けられたコン

    テクストがあるが、私たちが最も多く学んだ境界コンテクストを共有した • さて、今度は別の視点から見てみましょう • ドメイン駆動設計の中核となる要素の適用や誤用は、私たちの成果にどのような影響を与えたの でしょうか
  29. Ubiquitous language • 私の経験では、ユビキタス言語はドメイン駆動設計の「コアサブドメイン」である • ドメインエキスパートと同じ言語で会話できることは、私たちにとって必要不可欠なものだった • テストやドキュメントよりも、はるかに効果的な知識共有の方法であることが判明した • さらに、ユビキタス言語の存在は、私たちにとってプロジェクトの成功を予見する大きな要素となっ

    ている • Marketingシステムの実装は、開始当初は完璧とは言い難いものだったが、堅牢なユビキタス言 語がアーキテクチャの欠点を補い、プロジェクトの目標を達成することができた • CRMの分野では意図せずして、同じビジネスドメインを記述する言語が2つできてしまった。コミュ ニケーションの問題から、結局は大混乱に陥った
  30. Subdomains • 第1章で学んだように、サブドメインにはコア、サポート、汎用の3つのタイプがあり、ソリューション を設計する際には、どのサブドメインかを特定することが重要 • 種類の特定は難しいかもしれないが、第1章で説明したように、構築するソフトウェアシステムに関 連する粒度のサブドメインを特定することが重要 • 例えば、マーケティングハブの構想は、会社の追加的な利益源となることを意図していた •

    しかし、この機能のソフトウェア的側面はサポートサブドメインであり、他社との関係や契約を活用 することが実際の競争力であり、真のコアサブドメインであった • さらに、第11章で学んだように、サブドメインの種類を特定するだけでは十分ではない • そのサブドメインが別のタイプに進化する可能性にも注意する • Marketnovusでは、サブドメインのタイプの変化について、考えられる組み合わせのほとんどを体 験した
  31. Subdomains • 一方、そのサブドメインがサポートと考えられていても、高度なモデリング技術であるドメインモデ ルやイベントソースドメインモデルを使わないと実装できない場合は、事態が面白くなります。 • まず、ビジネスパーソンが要件を創造しすぎて、偶然にビジネスを複雑にしてしまった可能性があ ります。 • このような場合、要件を単純化することができますし、おそらく単純化する必要があります。 •

    第二に、ビジネスパーソンは、このサブドメインを利用してさらなる競争力を獲得していることにま だ気づいていないのかもしれません。これは、ボーナス・プロジェクトのケースで起こったことです。 • このミスマッチを明らかにすることで、ビジネスが新しい利益源をより早く特定できるようになるので す。 Mapping design decisions to subdomains
  32. Subdomains • 最も重要なことは、システムのビジネスロジックを実装する際に「痛み」を無視してはいけないとい うことです。これは、ビジネスドメインのモデルを進化させるか、戦術的な設計上の決定を改善する ための重要な信号です • 後者の場合、サブドメインが進化したことを意味し、その種類と実装戦略を再考する時期に来てい ます • タイプが変わった場合は、ドメインの専門家と話し合って、ビジネスコンテキストを理解する。新しい

    ビジネスの現実に対応するために実装を再設計する必要がある場合、この種の変化を恐れては いけません。 • ビジネスロジックをどのようにモデル化するかを意識的に決定し、考えられるすべての選択肢を意 識すれば、このような変化に対応し、実装をより精巧なパターンにリファクタリングすることがはる かに容易になります。 Don’t ignore pain
  33. Boundaries of Bounded Contexts • Marketnovusでは、境界付けられたコンテキストの境界を設定するために、様々な戦略を試みまし た。 • 言語的な境界 ◦

    最初のモノリスをマーケティングとCRMのコンテキストに分割し、それぞれのユビキタス言語 を保護しました。 • サブドメインベースの境界 ◦ サブドメインの多くは、イベントクランチャーやボーナスなど、それぞれの境界のあるコンテキ ストで実装されました。
  34. Boundaries of Bounded Contexts • エンティティベースの境界 ◦ 先に述べたように、このアプローチはマーケティングハブプロジェクトでは限られた成功しか 収められませんでしたが、他のプロジェクトでは成功しました。 •

    自滅的な境界線 ◦ CRMの初期実装では、集合体を2つの異なる境界付けられたコンテクストに分解したことを 覚えている人もいるかもしれません。決してこれを試してはいけませんよ
  35. Boundaries of Bounded Contexts • どのような戦略が推奨されるのでしょうか?すべてのケースに当てはまるものはありません。 • 私たちの経験では、小さすぎるサービスから始めるよりも、大きなものからサービスを抽出する方 がずっと安全でした。したがって、私たちは大きな境界から始めて、ビジネスについてより多くの知 識を得るにつれて、後でそれを分解することを好んだのです。

    • 最初の境界線はどのくらい広いのか?第11章で説明したように、すべてはビジネス領域に帰結し ます。ビジネス領域についてあまり知らないほど、最初の境界は広くなります。このヒューリス ティックは、私たちにとても役に立ちました。 • 例えば、マーケティングとCRMの境界のコンテキストは、それぞれが複数のサブドメインを含んで いた。時間が経つにつれて、最初は広かった境界を徐々にマイクロサービスに分解していった。第 14章で定義したように、境界づけられたコンテキストの進化を通じて、安全な境界の範囲に留まり ました。ビジネスドメインに関する十分な知識を得てからリファクタリングを行うことで、安全な境界 を超えないようにすることができました。
  36. Conclusion • 私たちは常に、ビジネスドメインについてできるだけ多くを学ぶために、ドメインエキスパートと一緒 にユビキタス言語を構築することから始めました。 • 矛盾するモデルの場合、ユビキタス言語の言語的境界に従って、解決策を境界づけられたコンテ キストに分解しました。 • 各境界コンテキストにおけるサブドメインの境界とその種類を特定しました。 •

    各サブドメインに対して、戦術的な設計ヒューリスティックを用いて実装戦略を選択した。 • その結果、サブドメインの種類と戦術設計の結果を比較することで、サブドメインの種類を確認し た。不一致の場合は、ビジネス側と議論しました。この対話によって、プロダクトオーナーに新たな 視点を提供することができ、要求の変更につながることもありました。 • より多くのドメイン知識が得られ、それが必要な場合は、境界づけられたコンテキストをさらに分解 しました。
  37. Conclusion • このドメイン駆動設計のビジョンを、私たちが始めたものと比較すると、大きな違い は、"aggregates everywhere "から "ubiquitous language everywhere "になったことでしょうか。

    • 最後に、Marketnovusがどのように始まったかをお話ししましたので、どのように終わったかをお 話ししたいと思います。この会社はあっという間に黒字になり、最終的には最大のクライアントに買 収されました。もちろん、ドメイン・ドリブン・デザインだけがその成功の理由とは言えません。しか し、その間、私たちは常に "スタートアップ・モード "にあったのです。 • イスラエルで「スタートアップ・モード」と呼ばれるものは、他の国では「カオス」と呼ばれています。 常に変化するビジネス要件と優先順位、アグレッシブな時間枠、そして小さな研究開発チーム。 DDDのおかげで、私たちはこれらすべての複雑な問題に取り組み、実用的なソフトウェアを提供し 続けることができたのです。ですから、振り返ってみると、私たちがドメイン駆動設計に賭けたこと は、完全に報われたのです。