Slide 1

Slide 1 text

©2023 Junichi Kato 1 / 98 いかに開発効率と品質を高めるか: ドメイン駆動設計と組織パターンの視点から考える レバレジーズ株式会社様 テックフェス2023春基調講演 2023/6/7 加藤潤一(@j5ik2o)

Slide 2

Slide 2 text

©2023 Junichi Kato 2 / 98 アジェンダ 1. 自己紹介 2. 発表の目的・想定対象者・大前提 3. 本日の主な参考資料 4. ドメイン駆動設計について思い出す 5. このスライドでの開発効率と品質の定義 6. テーマ1: 選択と集中のサブドメイン戦略 7. テーマ2: モデリングのツール: ドメインイベント 8. テーマ3: DDDのためのアーキテクチャパターン: CQRS/Event Sourcing 9. テーマ4:『組織パターン』のコンウェイの法則から考えるアーキテクチャと組織構造 10. 付録: Chatworkでの取り組み事例

Slide 3

Slide 3 text

©2023 Junichi Kato 3 / 98 自己紹介 Chatwork テックリード。ウェブ業界に転身後、ScalaやDDDを採用した 開発に従事。現在は次期アーキテクチャの設計に携わる 執筆 WEB+DB PRESS Vol.126 - 21周年記念エッセイ 今も読み続ける1冊の 本 レビュー エリックエヴァンスのドメイン駆動設計 Akka実践バイブル ドメイン駆動設計入門 良いコード/悪いコードで学ぶ設計入門 WEB+DB PRESS Vol.132 - 特集1 オブジェクト指向神話からの脱却 趣味はRustでアクターシステムを実装すること twitter: j5ik2o github: j5ik2o

Slide 4

Slide 4 text

©2023 Junichi Kato 4 / 98 発表の目的・想定対象者・大前提 目的 開発効率と品質を高めるために、ドメイン駆動設計と組織パターンをどう使うとよいのかを掘り下げる 想定対象者 開発経験が3年以上あるエンジニア(そうじゃない人もこれを考える機会に🙏) 大前提 この資料で提案されることは、私の経験から得た仮説に基づいています。その意味では発表者の主観が大いに混じっ ているのでご留意ください この資料で提案されることが、実際の現場で適用できるかは、個別の事象や状況を十分に踏まえたうえで判断して行 ってください

Slide 5

Slide 5 text

©2023 Junichi Kato 5 / 98 本日の主な参考資料 DDDといえばこの本。ソフトウェア開発者が複雑なドメ インを扱うアプリケーションを設計および構築するため の書籍(以下、DDD本) ソフトウェアを開発する上で「人間」とその「組織」に 着目し、ソフトウェアを開発する際にどのような組織で あるべきなのかを、実際の観察に基づいて書いている書 籍

Slide 6

Slide 6 text

©2023 Junichi Kato 6 / 98 ドメイン駆動設計について思い出す

Slide 7

Slide 7 text

©2023 Junichi Kato 7 / 98 ドメイン駆動設計とは ドメイン駆動設計とは、成功の鍵となるドメインモデルを核とした設計哲学のことである 設計のための意志決定フレームワークと設計を議論するためのテクニカルな語彙を、提供する

Slide 8

Slide 8 text

©2023 Junichi Kato 8 / 98 ドメイン駆動設計の3本柱 コアドメイン ユビキタス言語 モデル駆動設計 三本柱で言えば、モデル駆動設計やユビキタス言語を話す機会は多いです。 今回はコアドメインから考えていき、モデル駆動設計の話は直接しませんが、モデリングという観点で最新の取り組み をお話したいと思います。

Slide 9

Slide 9 text

©2023 Junichi Kato 9 / 98 アプリケーションは何らかのドメインに属している 釈迦に説法ですが・・・ アプリケーションの存在意義は、そのアプリケーションが提供する「価値」によって定義される この「価値」とは、利害関係者の要求を満たす能力 であり、その要求は通常、特定の問題または課題 として設定さ れる アプリケーションが問題や課題を解決する過程は、「問題ドメイン」と「解決ドメイン」の2つの領域に分けられる すべてのアプリケーションは、何らかの問題や課題を解決する目的を持つはずである。 その問題や課題が具体的(例えば効率的なスケジューリング)であれ抽象的(例えばエンターテイメントやリラクゼー ションの提供)であれ、全てのアプリケーションは特定のドメインにおける問題を解決することを目指している、と考 えるのが自然である

Slide 10

Slide 10 text

©2023 Junichi Kato 10 / 98 ドメインとドメインモデル 問題領域(問題ドメイン, DDDではドメイン) 問題の定義や価値について定める領域や範囲のこと 解決領域(解決ドメイン, DDDでは境界づけられたコンテキスト) ソフトウェアが解決する問題の領域や範囲のこと 問題領域 解決領域 ドメインモデル ドメインモデルの意味 バージョン管理 Git コミット ローカル時リポジトリへの変更登録 Subversion コミット セントラルリポジトリへの変更登録 「ファイル」の定義は問題ドメインに依存するかもしれないが、「コミット」の定義は解決ドメインに依存する いずれにしても、ドメインモデルは、問題ドメインのモデルと解決ドメインのモデルの両方を含む。「深いモデル」 は後者であることが多い 出典: 「ドメイン駆動設計 ~ユーザー、モデル、エンジニアの新たな関係~」

Slide 11

Slide 11 text

©2023 Junichi Kato 11 / 98 ドメインを完全に理解しましたね

Slide 12

Slide 12 text

©2023 Junichi Kato 12 / 98 このスライドの観点は開発効率と品質

Slide 13

Slide 13 text

©2023 Junichi Kato 13 / 98 このスライドでの開発効率と品質の定義 開発効率(無駄なく開発を進めること) 不必要な作業を排除し、必要な機能のみを効率的に開発することを意味する 品質(間違いなく開発を行うこと) 開発されたシステムがビジネス要件を正確に満たし、ユーザーの期待に応える能力を指す 要は無駄なく・間違いなくのために、ドメイン駆動設計や組織パターンで何ができるのかという観点 一般的な定義と異なるので注意

Slide 14

Slide 14 text

©2023 Junichi Kato 14 / 98 テーマ1: 選択と集中のサブドメイン戦略 〜 どのサブドメインから手を付けるべきか 〜

Slide 15

Slide 15 text

©2023 Junichi Kato 15 / 98 ドメインがサブドメインを持つことがある 例えば、ECサイトの場合は、ドメインは「オンライン販売」となるが、一つの領域として扱うのには大きすぎる。 「オンライン販売」というドメインは、以下の要素(サブドメイン)に分割できる(サブドメインは、ドメインの中で、特 定の問題領域を表現する) 商品のレコメンド 商品の購⼊フロー レビュー インベントリ管理 顧客管理 ID ・認証・認可 決済 ログ管理 通知 なにから手をつけるか。何が重要なのだろうか

Slide 16

Slide 16 text

©2023 Junichi Kato 16 / 98 サブドメインの種類 コアドメインをサポート 一般的な問題を解決 一般的な問題を解決 コアドメイン 支援サブドメイン 汎用サブドメイン コアドメインは「重要なビジネス価値を提供」する。競争優位性を持つかどうかが決まる領域 支援サブドメインはコアドメインを「サポート」する 汎用サブドメインは「一般的な問題を解決」することで、コアドメインと支援サブドメインをサポートする ECサイト:コアドメイン 「商品のレコメンド」「商品の購入フロー」 ECサイト:支援サブドメイン 「レビュー」「インベントリ管理」「顧客管理」 ECサイト:汎用サブドメイン 「ID・認証・認可」「決済」「ログ管理」「通知」

Slide 17

Slide 17 text

©2023 Junichi Kato 17 / 98 QCDSの観点から見たコアドメイン戦略 コアドメインは、QCDSの観点から以下のような選択と集中を可能にするのではないか Quality(品質) コアドメインに注力することで、最も重要な機能やビジネスルールを適切にモデル化し、実装することができる Cost(コスト) コアドメインにリソースや開発労力を集中させることにより、コスト効率を向上させることができる Delivery(納期) コアドメインにフォーカスすることで、開発プロセスを最適化し、納期遅延を最小限に抑えることができる Scope(範囲) コアドメインの明確な定義と設計により、プロジェクトのスコープを特定の領域に絞り込むことができる

Slide 18

Slide 18 text

©2023 Junichi Kato 18 / 98 コアドメインに対する疑問 疑問1: コアドメイン以外のサブドメインは重要ではないのか? 疑問2: ユーザ側にとって重要な部分は必ずしもコアドメインに該当しない?

Slide 19

Slide 19 text

©2023 Junichi Kato 19 / 98 疑問1: コアドメイン以外のサブドメインは重要ではないのか? 重要なのは、コアドメインと他のサブドメインの関係性や依存関係を理解し、適切にバランスを取ること コアドメインをサポート 一般的な問題を解決 一般的な問題を解決 コアドメイン 支援サブドメイン 汎用サブドメイン コアドメインが競争上の優位性を提供する一方で、他のサブドメインはそのコアドメインを支える役割を果たす。コ アドメインと他のサブドメインの組み合わせが、総合的なシステムの機能と価値を最大化する。したがって、コアド メインの重要性を認識しつつも、他のサブドメインも十分に重要であると考えるべき 絶対的な優劣を付けるのではなく、ビジネスの要件や目標に応じて、コアドメインと他のサブドメインを適切に組み 合わせてプロダクトを設計し、バランスを取ることが求められる

Slide 20

Slide 20 text

©2023 Junichi Kato 20 / 98 疑問2: ユーザ側にとって重要な部分は必ずしもコアドメインに該当しない? ユーザ側にとって重要な部分は必ずしもコアドメインに該当しないのは事実 サブドメインは事業者としての視点で分類される(SoR的な価値観) 競争優位性以外に、成長性・顧客満足度・ブランド・CSRなどの観点もある ユーザの視点に立つと、コアドメインは違ってみえるかもしれない。ユーザは複数のドメインに横断的に関与す ることが多い。 ECサイトでは商品カタログ、ショッピングカート、決済システムなどと横断的にやり取りをすることとなる つまり、事業者の価値とユーザの価値は別。物差しが違うので別の指標が必要(SoE的な価値観) 例えばUXがその一つ。優れたUXは基礎なるドメインの複雑さに寄らず、ユーザにとってシームレスで直感的な インターフェイスを提供することができる 非UXのユーザ価値としては、価格・製品の性能や品質・ブランドの評判や信頼性・製品のアクセシビリティが考 えられる

Slide 21

Slide 21 text

©2023 Junichi Kato 21 / 98 テーマ1のまとめ 「サブドメイン」の考え方をベースに、コアドメインの「商品の購入フロー」から手を付ける場合もあるし、他のサ ービスとの連携を想定して汎用サブドメインの「ID・認証・認可」から手を付ける場合もある。もしくは、サブド メインごとにチームがわかれていれば同時並行開発になるかもしれない。身も蓋もないが「サブドメイン」をどう選 ぶかは「戦略」による さらに、競争優位性を担保する「コアドメイン」だけあればよいか、という問いに対しては、明らかに「No」と言 える。コアドメインは他のサブドメインからのサポートがない限り機能しないし、プロダクトとしての本来の役目を 果たせないから その意味から冒頭に挙げた「何から手を付けるか(優先順位付け)」の問いに対して、「サブドメイン」の考え方が完 全な答えにはならないが、問題領域をより深く理解し戦略をサポートするツールとしては十分に有用であると考える

Slide 22

Slide 22 text

©2023 Junichi Kato 22 / 98 テーマ2: モデリングのツール: ドメインイベント 〜 どのモデルから手を付けるべきか 〜

Slide 23

Slide 23 text

©2023 Junichi Kato 23 / 98 モデリングの際、どこから手をつけますか? ユースケース上のユビキタス言語からモデル候補を抽出する場合、ほとんどの場合エンティティから探し始めます これでうまくいくこともあります。もっと複雑なサブドメインではエンティティから始めると迷子になることがあり ます…

Slide 24

Slide 24 text

©2023 Junichi Kato 24 / 98 分析ツールとしてのドメインイベント

Slide 25

Slide 25 text

©2023 Junichi Kato 25 / 98 ドメインイベントはドメイン上の「出来事」

Slide 26

Slide 26 text

©2023 Junichi Kato 26 / 98 FYI:「出来事」とは何か 「出来事」はモノではなくコト 「出来事」とは 「起こった事態(事柄)」 つまり 「成立した事態(事柄)」 のこと 2020年 コロナウィルスが流行した 論理的に可能であれば成立していなくても 「事態(事柄)」 になる 不成立でも言語にして意味が通れば 論理空間の扱い 2021年 関東が沈没する

Slide 27

Slide 27 text

©2023 Junichi Kato 27 / 98 イベントは過去形で表現される イベントとは、ドメイン内で何か重要なことが起こったときに発生するもので、動詞の過去形で表現される 商品が注文された(ProductPurchased) 商品が出荷された(ProductShipped) イベントはビジネスの重要な振る舞いを表すため、それらに注目することでドメインの本質的な側面を理解しやすく なります

Slide 28

Slide 28 text

©2023 Junichi Kato 28 / 98 DDD本(2004年)にはドメインイベントは出てこない 2014年『Domain-Driven Design Reference: Definitions and Pattern Summaries』にて初めて紹介された。

Slide 29

Slide 29 text

©2023 Junichi Kato 29 / 98 イベントを重視するモデリング手法は昔からある T字形ER 『T字形ERデータベース技法』(1998年) REAモデル 『Model-Driven Design Using Business Patterns』(2006年) 『ビジネスパターンによるモデル駆動設計』(2007年) 現在絶版 Event Storming 『Introducing EventStorming』(考案自体は2012年ごろ?現在執筆中) TM 『モデル作成技術TM入門』(2022年) これらの設計手法はすべてイベントを重要な要素として扱う。具体的には、システムやプロセスで発生する「何かが起 こる」という事象や状態の変化を「イベント」と捉え、それらをモデル化することで、システムの振る舞いやビジネス のフローを理解・設計するのが特徴。

Slide 30

Slide 30 text

©2023 Junichi Kato 30 / 98 REAモデル Pavel Hruby著『ビジネスパターンによるモデル駆動設計』にて紹介された構造と振る舞いのモデルパターン。経済 活動をResource, Event, Agentのモデルを中心に記述する 図の引用: REAとビジネスパターン入門(1)

Slide 31

Slide 31 text

©2023 Junichi Kato 31 / 98 FYI: REAに関する関連資料 “寿司屋”には「交換」「変換」の2パターンがある Scalaでモデル駆動を実現するために知っておきたいREAモデル の捉え方 部屋の予約はREAモデルだけでは説明できない 『ビジネスパターンによるモデル駆動設計』から学ぶ実装課題点

Slide 32

Slide 32 text

©2023 Junichi Kato 32 / 98 モデル作成技術TM入門 佐藤正美著『事業分析・データ設計のためにモデル作成技術TM入門』 「T字形ER法」の進化形。構文論・意味論の観点から見直して、「関数」 を中核に再体系かされた技術体系 第5章 「関係」文法 1. R(Event, Resource): R(受注, 顧客)など 2. R(Event, Event): R(受注,請求)など 3. R(Resource, Resource): R(従業員, 部門)など 1:EtoR 2:EtoE 3:RtoR 受注 顧客 請求 従業員 部門

Slide 33

Slide 33 text

©2023 Junichi Kato 33 / 98 FYI: リソースとイベントの区別方法 【簡易的な方法】見つけたモデルがリソース(モノ)かイベント(コト)かを迷った場合は、モデル名に「○○する」と いう動詞句を追加する 「配属する」は意味が通るので、配属はイベント 「部署する」は意味不明なので、部署はリソース 「分類する」は意味が通るが、分類はリソース 【厳密な方法】「タイムスタンプが採取できること」もしくは「監査証跡が保管されていること」。どちらかを満た すものはイベントとなる 「分類」はどちらもみたされないので、リソースとなる 出典: 『T字形ERデータベース技法』

Slide 34

Slide 34 text

©2023 Junichi Kato 34 / 98 Event Storming ビジネスのプロセスをモデル化し知識を共有し、セッションの終わりには参加者全員がメンタルモデルを同期させ、ユ ビキタス言語の利用へ一歩踏み出すことができる 後ほど概要を説明します

Slide 35

Slide 35 text

©2023 Junichi Kato 35 / 98 そもそもなぜイベント(コト)に注目するのか 出典『現場で役立つシステム設計の原則 〜変更を楽で安全にするオブジェクト指向の実践技法』

Slide 36

Slide 36 text

©2023 Junichi Kato 36 / 98 イベント(コト)に注目すると全体の関係を整理しやすい(1/3) コトはヒトとモノとの関係として出現する 入荷イベントには注文商品・注文者などが紐付く コトがモノ・ヒトと関連する 注⽂商品( モノ) ⼊荷( コト) 注⽂者( ヒト)

Slide 37

Slide 37 text

©2023 Junichi Kato 37 / 98 コトに注目すると全体の関係を整理しやすい(2/3) コトは時間軸に沿って明確な前後関係を持つ 入荷イベントの前に注文イベントがある。逆転はない イベントの順序 ⼊荷( コト) 注⽂( コト)

Slide 38

Slide 38 text

©2023 Junichi Kato 38 / 98 コトに注目すると全体の関係を整理しやすい(3/3) ヒトやモノから分析すると発散しがち コトを手がかりにすると効率的 ⼊荷 出荷 ⼊荷( コト) 出荷( コト) 商品( モノ) 担当者( ヒト)

Slide 39

Slide 39 text

©2023 Junichi Kato 39 / 98 「世界は事実の総体である」はモデリングにも当てはまる ヴィトゲンシュタインの哲学から 「世界は、事実 の総体である。事物 の総体ではない。」 世界が事物の総体であり、事実の総体ではないとしたら、「ここにリンゴがある」 という事実 すらも世界には含まれなくなってしまう 世界を記述する際には、「事実」が中心的な要素となり、事物はその「事 実」の一部として存在する。 ソフトウェア設計のモデリングでは、動作や機能を理解するために、システ ム内の事物(エンティティなど)を単にリストアップするのではなく、それ らがどのように相互作用し、どのような結果を生み出すかという「事実」に 注目すべき。 これは、システムの本質的な動作と機能を理解し、適切な設計と解決策を導 き出すために非常に重要なアプローチである。

Slide 40

Slide 40 text

©2023 Junichi Kato 40 / 98 イベントに注目する効果 1. 【品質】明確なビジネス要件 イベントはビジネスプロセスの重要な部分を表す。それらを理解し明確にすることで、ビジネス要件をより正確 に表現し、誤解を避けることができる 2. 【効率】共通の理解 イベントに注目する技法は、ビジネスアナリスト、開発者、プロジェクトマネージャーなどの さまざまなステー クホルダー間で共通の理解を生み出すのに役立つ 3. 【効率・品質】変更の容易さ イベントに基づいたモデリングではイベントが独立して存在するため、ビジネスプロセスや要件が変更された場 合でもその影響を最小限に抑えることができる 以降は、イベントを利用したモデリング手法の、Event Stormingの概要を解説する

Slide 41

Slide 41 text

©2023 Junichi Kato 41 / 98 イベントを起点としたモデリングする手法の一つ Event Storming

Slide 42

Slide 42 text

©2023 Junichi Kato 42 / 98 Event Storming Introducing EventStorming - EventStorming EventStorming is a flexible workshop format for collaborative exploration of complex business domains. EventStormingは、複雑なビジネスドメインを共同で探索するための柔 軟なワークショップ形式です。 DDD著者のEricさんも強力な手法であると説明している。 考案者はAlberto Brandolini氏で2013年にはブログに最初の投稿がされています。 海外での 認知度は高く、Eric Evans氏のプレゼンテーションの中でも強力な手法であると言及されてい ます。 [1] 1. 新しいモデリング手法: EventStorming (イベントストーミング) をはじめるための準備

Slide 43

Slide 43 text

©2023 Junichi Kato 43 / 98 ワークショップの形式が複数ある ビッグピクチャー システム価値・システム外部環境(コンテキスト)の観点 プロセスモデリング システム境界の観点(アクターとシステムの関係) システム設計レベル システムの観点(システム内部の機能とデータ構造の関係) 詳しくは『Introducing Event Storming』を参照してください。 今回は『Learning Domain-Driven Design』の簡便 な方法を紹介します。

Slide 44

Slide 44 text

©2023 Junichi Kato 44 / 98 主に登場にする付箋の種類

Slide 45

Slide 45 text

©2023 Junichi Kato 45 / 98 最終的に導きたいのは集約 最終的にCQRS/Event Sourcingで実装することが最も自然な流れになる(他の選択肢もある。後述します) テーブルモデルがどうなるか気になる人は、リードモデルも注目するとよい

Slide 46

Slide 46 text

©2023 Junichi Kato 46 / 98 『Learning Domain-Driven Design』で紹介されている方法

Slide 47

Slide 47 text

©2023 Junichi Kato 47 / 98 1.イベントを列挙する 漏れダブりを気にしないで、ブレインストーミングで考えながらイベントを列挙する イベントが出尽くしたら、似たようなものを集めてまとめる 漏れダブりを会話しながら整理する。用語のブレもある程度統一する

Slide 48

Slide 48 text

©2023 Junichi Kato 48 / 98 2.タイムラインをつくる 時間の経過が左から右となることを前提に、イベントをビジネスドメインで発生する順序で並べる。同時に発生しそ うなイベントは縦に並べる イベントはハッピーシナリオから始める。それができたら別のシナリオも追加してみる 並べたときに、イベントの抜け漏れに気付いた場合は適宜イベントを追加/修正する

Slide 49

Slide 49 text

©2023 Junichi Kato 49 / 98 3.問題点をみつける 気になることを問題点として追加する

Slide 50

Slide 50 text

©2023 Junichi Kato 50 / 98 4.フェーズを区切る 重要と思われるイベントの背後に縦の線を入れる

Slide 51

Slide 51 text

©2023 Junichi Kato 51 / 98 5.コマンドを追加する イベントの引き金となった、コマンド(命令)を青い付箋で追加する 必要ならアクターも追加する。スイムレーンでもよい(ただし自明でない場合追加する必要はない)

Slide 52

Slide 52 text

©2023 Junichi Kato 52 / 98 6.ポリシーを追加する アクターのないコマンドには、イベントとコマンドの間に、ポリシー(実行シナリオ)をつける 判断基準を満たしたのみコマンドを実行する場合は、その判断基準をポリシーに明記する(例えば、ビジネスプラン のみ)

Slide 53

Slide 53 text

©2023 Junichi Kato 53 / 98 7.リードモデルを追加する アクターがコマンドの実行を決定するために使用するデータビューである、リードモデルを追加する。例えば、顧客 (アクター)は、ショッピングカート(リードモデル)の中身を見た上で、精算(コマンド)する

Slide 54

Slide 54 text

©2023 Junichi Kato 54 / 98 8.外部システムを追加する 調査対象外の外部システムを追加する。例えば、決済システムや配送システムなど

Slide 55

Slide 55 text

©2023 Junichi Kato 55 / 98 9.集約を見つける すべてのイベントとコマンドが分かれば、集約を発見できる 集約の名前は問題ドメインから発見できるとは限りません。解決ドメインとして新たな言葉をつくる必要があるかも 知れません。(バージョン管理の「コミット」のように) FYI: 「集約の設計と実装」

Slide 56

Slide 56 text

©2023 Junichi Kato 56 / 98 10.コンテキスト境界を見つける 重要なイベントを境界にする 関連性の強い集約を見つける それらを考慮しコンテキスト境界を見つける

Slide 57

Slide 57 text

©2023 Junichi Kato 57 / 98 リソースからは振る舞いの抽出が可能か 通常、システム設計ではリソース(または「モノ」)に注目しがち 例えば、顧客、商品、注文などのエンティティに焦点を当てる しかし、このアプローチでは、システムの振る舞いやビジネスルール、ビジネスプロセスなどを理解するのは困難な 場合があります 注文 注文の作成???( コマンド) 注文の挿入???( イベント) 注文の更新???( コマンド) 注文の更新???( イベント) 注文の削除???( コマンド) 注文の削除???( イベント) ドメイン知識が乏しいと、データを操作することにフォーカスしてしまいがち

Slide 58

Slide 58 text

©2023 Junichi Kato 58 / 98 イベントによって振る舞いを抽出し理解する 一方、Event Stormingではこれらの「コト」を直接モデリングし、それらがどのように相互作用するかを理解します。 これにより、システム全体の振る舞いを把握し、それがビジネスの要件とどのように一致するかをよりよく理解するこ とができます。 注文( 集約) 商品を注文する( コマンド) 商品が注文された( イベント) 注文数を訂正する( コマンド) 注文数が訂正された( イベント) 商品を取消する( コマンド) 商品が取り消された( イベント) コマンドが受理されるとイベントが発生する。集約のビジネスルールに合致しないコマンドは受理されない

Slide 59

Slide 59 text

©2023 Junichi Kato 59 / 98 テーマ2のまとめ イベントはドメインの動的な側面を分析する強力なツールといえる イベントは分析だけではなく設計・実装にも活用できる(詳しくは次のパートで解説)

Slide 60

Slide 60 text

©2023 Junichi Kato 60 / 98 テーマ3: DDDのためのアーキテクチャパターン: CQRS/Event Sourcing 〜Event Stormingをそのまま設計・実装する〜

Slide 61

Slide 61 text

©2023 Junichi Kato 61 / 98 まずは問題提起から

Slide 62

Slide 62 text

©2023 Junichi Kato 62 / 98 DDDでの、クエリ実装の問題 クエリ要件を満たすことでリポジトリの実装が複雑になる 複数の集約から非正規型のDTOを得るのでN+1クエリが発生する 集約から非正規型のDTOへの変換が非効率

Slide 63

Slide 63 text

©2023 Junichi Kato 63 / 98 クエリ要件を満たすことでリポジトリの実装が複雑になる 取得した集約の集合を使ってドメインロジックを実行しないで、ドメインのデータを目的にリポジトリを使う例。 様々 なクエリ要件を満たすために、リポジトリの実装が複雑になる。 val employees: List[Employee] = employeeRepository.findByDeptIdsWithEmployeeNamePatterns(deptIds, employeeNamePatterns) // ドメインロジックは使わず、レスポンス用DTO に詰め込む

Slide 64

Slide 64 text

©2023 Junichi Kato 64 / 98 複数の集約から非正規型のDTOを得るのでN+1クエリが発生する 以下はホテルの予約リストを取得する例。予約集約にはホテル名や顧客名は含まれていないため、ホテルIDと顧客IDか ら対応する集約を取得する必要がある リポジトリは正規化された集約を返すので、複数の集約から非正規型のDTOを得るためにN+1クエリが発生する。 val resavationDtos = reservationRepository.findByIds(ids) // SQL 発行 .map { reservation => val hotel = hotelRepository.findById(reservation.hotelId) // SQL 発行 val customer = customerRepository.findById(reservation.customerId) // SQL 発行 new ReservationDto(reservation, hotel, customer) }

Slide 65

Slide 65 text

©2023 Junichi Kato 65 / 98 集約から非正規型のDTOへの変換が非効率 クライアントへ返す非正規型のDTOは、集約の一部のみの場合もある。そういうケースでデータ取得のためだけにリポ ジトリを使うケース。 集約の一部を読み取り、他は捨てることになる val customerNames = customerRepository.findByIds(ids).map{ customer => customer.name // 他のプロパティは捨てる }

Slide 66

Slide 66 text

©2023 Junichi Kato 66 / 98 クエリのためだけにドメインモデルを使うのは非効率 クエリ要件を満たすことでリポジトリの実装が複雑になる 複数の集約から非正規型のDTOを得るのでN+1クエリが発生する 集約から非正規型のDTOへの変換が非効率 ※ これらの問題が本当に問題なのか推測せずに計測したほうがいいし、仮に問題だとしても別の利点とトレードオフで きるのではあればCQRSを使う必要はない val employees: List[Employee] = employeeRepository .findByDeptIdsWithEmployeeNamePatterns(deptIds, employeeNamePatterns) // ドメインロジックは使わず、レスポンス用DTO に詰め込む val resavationDtos = reservationRepository.findByIds(ids) // SQL 発行 .map { reservation => val hotel = hotelRepository.findById(reservation.hotelId) // SQL 発行 val customer = customerRepository.findById(reservation.customerId) // SQL 発行 new ReservationDto(reservation, hotel, customer) } val customerNames = customerRepository.findByIds(ids).map { customer => customer.name // 他のプロパティは捨てる }

Slide 67

Slide 67 text

©2023 Junichi Kato 67 / 98 コマンド(ドメイン)側とクエリ側 それぞれに独立した最適化ができないか

Slide 68

Slide 68 text

©2023 Junichi Kato 68 / 98 それがCQRS

Slide 69

Slide 69 text

©2023 Junichi Kato 69 / 98 CQRSとは Command and Query Responsibility Segregation=コマンド・クエリ責務分離(2010年 Greg Young氏) CQRSはDDDのためのアーキテクチャパターンの一つ Separation ではなく、Segregationなので、C/Qをそれぞれ隔離することを意味する 単なるモデルの分離ではない。モデルだけ分離して、隔離の境界がないものはCQRSとは言いがたい 隔離をするので、Event Sourcingと組み合わせることが多い

Slide 70

Slide 70 text

©2023 Junichi Kato 70 / 98 なぜコマンドとクエリを分離するのか そもそもCとQで要件が異なるので、混ぜないで隔離するほうが望ましい 特にクエリ要件が複雑なシステムでは効力を発揮する コマンド クエリ 一貫性/可 用性 一貫性重視。最新の書き込みが反映されるなければなら ない。トランザクション整合性(強い整合性)を使う 可用性重視。つまりちょっと古いデータ見え てもよい。結果整合性(弱い整合性)を使う データ形 式 正規化されたデータを保存する(集約単位≒概念単位) 非正規化されたデータ形式取得する(クライア ント要求に合わせる) スケーラ ビリティ 全体のリクエストに対して少ない比率。必ずしもスケー ラビリティは重要ではない 全体のかなりのリクエスト比率を占めるた め、スケーラビリティが必要

Slide 71

Slide 71 text

©2023 Junichi Kato 71 / 98 CQRSでのシステム構成の例 Pros コマンドとクエリを別々にデプロイできる、耐障害性が高くな る コマンドとクエリを別々に最適化できるため、スケーラビリテ ィが高くなる Cons 分散システムとして、構成要素が多くなる ネットワーク分断時に 一貫性 or 可用性 どちらを優先する か選択を迫られる

Slide 72

Slide 72 text

©2023 Junichi Kato 72 / 98 リードモデルの形式変換をしない場合の問題点 C/Qでデータベースまで分ける必要があるのでしょうか?これは明確に理由があります。例えば、入社日が EpocTime(Long値)としてDBに保存される場合、そのままではクエリのレスポンスに含めることができない。しかしク エリ側から値オブジェクトに依存ができないケースで問題があります。 エンコードされたドメインオブジェクト 属性 種別 値 EmployeeId String “123456789” JoinedDate Long 1585039714572 クエリ側で値オブジェクトを使って値を形式変換する必要がある joinedDate.asFormattedString → "2020年03月24日 08:48" つまり、クエリがドメインに依存してしまうことになる。 これを回避するためには、C/Qでデータベースを分けて、 RMUで事前に形式変換する必要がある

Slide 73

Slide 73 text

©2023 Junichi Kato 73 / 98 C/Qのモデル間の変換・同期の問題はイベントで解決 C/Qを隔離したら、どうやってデータをクエリサイドに同期させるかという問題がある。考案者のGregさんとしてはイ ベントを使うことを推奨している。 The model that is best suited is the introduction of events, events are a well known integration pattern and offer the best mechanism for model synchronization. 最も適したモデルはイベントの導入であり、イベントはよく知られた統合パターンであり、モデルの同期化に最適なメカニズムを提供します。 Eventを中核においてアーキテクチャを考えたほうが、全体の設計のバランスがよくなります。そこでEvent Sourcing の話になります。 拙作 CQRSはなぜEvent Sourcingになってしまうのか になぜEvent Souringが必要になるか詳細に書いてあります。

Slide 74

Slide 74 text

©2023 Junichi Kato 74 / 98 Event Sourcing 過去に起きた出来事=イベント イベントは不変で追記のみ イベントを再生(リプレイ)すると最新状態が手に入る CounterInitialized(value=0) -> CounterAdded(value = 3) -> CounterSubtracted(value = 2) Counterの最新状態は1(この状態はコマンドのために利用される, クエリ側では別の仕組みを利用する)

Slide 75

Slide 75 text

©2023 Junichi Kato 75 / 98 Event Sourcingでのシステム構成の例 Pros CとQのモデル間の変換・同期の問題を解決できる ドメインとしてはインピーダンスミスマッチを解消しなくても よい(RMUがシンプルに解決する) C側でRDBを使う必要がなくなる。NoSQLと相性が良く、書き 込みのスケールアウトも容易になる 書き込みは追記のみになるため、スケーラビリティを確保しや すい(レコードを一切ロックしない) イベントを使って他のマイクロサービスとの連携が容易になる 監査や分析に利用できる Cons 長大なイベントから状態をリプレイする際に時間がかかる すべてのイベントをストレージに保存する必要がある

Slide 76

Slide 76 text

©2023 Junichi Kato 76 / 98 性能劣化はある程度カバーできる Consの性能劣化は、ライブラリやフレームワークによる仕組みで解消できるになっている 長大なイベントから状態をリプレイする際に時間がかかる あらかじめN件ごとにスナップショットを保存しておく リプレイ時に最新のスナップショット+差分イベントだけを読み込むことでパフォーマンス劣化を最小化できる すべてのイベントをストレージに保存する必要がある 最新のスナップショットより古いイベントは削除することが可能 イベントを削除すると、イベントからリードモデルを再構築することができなくなる

Slide 77

Slide 77 text

©2023 Junichi Kato 77 / 98 コマンドプロセッサの実装イメージ (1)〜(3)は以下のように抽象化可能。 この実装では、スナップショットが利用されているとはいえ、ユースケースの実行ごとにリプレイが行われるところが 難点。Akka/Scalaではアクターとしてキャシュすることでジャーナルやスナップショットと完全に同期した状態を維持 できる。つまり、(1)から(3)が初回実行以外は不要となる。 class AddCartItemUseCase(cartPersistenceService: CartPersistenceService) { def execute(cartId: CartId, cartVersion: Version, itemId: ItemId, num: ItemNum): Unit = { // (1) スナップショット取得 val snapshot = cartPersistenceService.getLatestSnapshotById(cartId) // (2) スナップショット以後のイベント取得 val events = cartPersistenceService.getEventsByIdAndSeqNr(cartId, snapshot.seqNr) // (3) 最新状態に再生( リプレイ) val cart = Cart.from(snapshot, events) // (4) 集約の振る舞いを実行 val (newCart, itemAdded) = cart.addItem(itemId, num) // (5) 新しい集約状態とイベントを永続化 cartPersistenceService.store(newCart, itemAdded, cartVersion) // DynamoDB などに書き込まれる } } val cart = cartPersistenceService.replay(cartId, cartVersion)

Slide 78

Slide 78 text

©2023 Junichi Kato 78 / 98 具体的な実装はどうしたらよいのか 時間の関係ですべてを話せないので、以下のリンクを参考にしてください Akka/Scala CQRS Event Sourcing Proto.Actor/Golang プログラミング言語非依存 AWS データベースブログの記事 「Amazon DynamoDBによる CQRSイベントストアの構築」 を勝手に読み解 く

Slide 79

Slide 79 text

©2023 Junichi Kato 79 / 98 でも、いきなりシステムを分けるのは難しい・・・

Slide 80

Slide 80 text

©2023 Junichi Kato 80 / 98 明確な境界がないCQRSに似た妥協パターン(有用な場合もある) コマンド側ではドメインロジックの起動に専念する。クエリ側では原則的にリポジトリを含めてドメインを利用しな い。ただし前述したフォーマット変換などにVOを使うことを許容する C/Qの境界線を明確に引くことができないので、モジュールの依存関係の制御が難しくなりがちだが、分散システム にいきなり移行できない場合は選択肢に入る

Slide 81

Slide 81 text

©2023 Junichi Kato 81 / 98 テーマ3のまとめ CQRSはDDDのためのアーキテクチャパターンの一つ C/Qごとの要件に合わせて独立して最適化できる利点がある。一方でそれなりの手間がかかる ほとんどのスタートアップで、最初から分散システムを構築するのは難しい CQRSの基本原理を抑えつつ、明確な境界がないCQRSに似た妥協パターンも有用な場合もある

Slide 82

Slide 82 text

©2023 Junichi Kato 82 / 98 テーマ4:『組織パターン』のコンウェイの法則から考える アーキテクチャと組織構造

Slide 83

Slide 83 text

©2023 Junichi Kato 83 / 98 『組織パターン』 ソフトウェアを開発する上で「人間」とその「組織」に着目し、ソフトウェアを開発する際にどのような組織であるべ きなのかを、実際の観察に基づいて書いている書籍。 経験が乏しいと読むのが非常に難しい本…

Slide 84

Slide 84 text

©2023 Junichi Kato 84 / 98 DDDと関係がありそうなパターン一覧 『組織パターン』と『エリックエヴァンスのドメイン駆動設計』は、「システムと組織の複雑さを管理し、価値のある ソフトウェアソリューションを効果的に実現する」という、共通の目標を持つ、と考えられる サブドメインや境界づけられたコンテキストに関連するパターン コンウェイの法則 信頼で結ばれた共同体 一つのタスクに一つのチーム スキルに応じたサブシステム 実践的モデラに関係するパターン アーキテクトも実装する 今回は「コンウェイの法則」について議論します。

Slide 85

Slide 85 text

©2023 Junichi Kato 85 / 98 メルヴィン・コンウェイの「コンウェイの法則」 「システムを設計するあらゆる組織は、必ずその組織のコミュニケーション構造に倣った構造を生み出す」という法 則。組織のコミュニケーションを阻害するような、システム構造であってはならない (※ 「システムを設計する組織」を 念頭におかないと認識がずれやすいので注意)。 組織のコミュニケーション構造 地域A 地域B 組織A 組織B 組織C 密 疎 疎 実際にできあがるシステム構造 組織A のコンポーネント 組織B のコンポーネント 組織C のコンポーネント 密 疎 疎 左側の組織構造に倣ったアーキテクチャが作 られる 地域(コミュニケーションの構造)が同じ場合はコミュニケーションが密になり、異なる場合は疎になっている。 よくも 悪くも組織の構造をシステムに反映されてしまうということ

Slide 86

Slide 86 text

©2023 Junichi Kato 86 / 98 逆コンウェイ作戦 引用: 『エンジニアリング組織論への招待 ~不確実性に 向き合う思考と組織のリファクタリング』 コンウェイの法則は、悪い組織構造が、悪いアーキテクチャを生み 出すというような文脈です。 これは取引コストの高い組織が、取引コストの高いアーキテクチャ を生み出してしまい、「技術的負債」現象を引き起こしてしまうと いうことを意味しています。 一方で、コンウェイの法則を経営活動にとってポジティブに利用し ようとする考えが近年では生まれてきました。この関係性を逆手に とって、積極的な組織設計やコミュニケーション設計をビジネス戦 略に基づいて行うことで、アーキテクチャ自身をより良いものに変 えていこうとする考え方です。 コンウェイの法則自体は悪い組織構造が悪いアーキテクチャを生み出すという考え方。逆コンウェイではこのネガティ ブな理由を逆手にとり、組織設計やコミュニケーション設計を基にアーキテクチャをよりよいものとして設計するとい う考え方

Slide 87

Slide 87 text

©2023 Junichi Kato 87 / 98 『組織パターン』での「コンウェイの法則」 問題サマリ 組織の構成要素(たとえば、チームや部署、課など)がプロダクトの本質的な構成要素を反映していない場合、あるいは組織間の関係がプロダク トの構成要素間の関係を反映していない場合には、そのプロジェクトは困ったことになるだろう。 システムのアーキテクチャにより、組織のコミュニケーションパスが形作られる。事実上の組織構造が正式な組織構造を形作るのだ。そして、正 式な組織構造が今度はアーキテクチャを作る。早期に行われるアーキテクチャの制定は、推測でしかなく、不安定だ。しかし、このアーキテクチ ャは、ある一定のリズムに支配されていて、そのリズムがコアビジネスコンピテンシーとなる領域を反映している。そして、ビジネスに関わるこ のレベルの関心は、アーキテクチャ構造全体に対する幅広い関心と結びつくよりも、組織の構造と密接に結び付くのだ。 解決サマリ それゆえ: 組織をプロダクトのアーキテクチャと対比できるようにしよう。パターン言語におけるこの時点では、アーキテクチャが組織を駆動する べきであり、組織に応じてアーキテクチャを定めるべきではない。 ソフトウェアの設計とその必要性が組織構造を決定すべきである考え方。メルヴィンとは逆向きの視点になっている。 組織構造はソフトウェアのアーキテクチャによって最適化されるべきで、その逆(組織構造がソフトウェアのアーキテ クチャを決定する)は避けるべきだという主張

Slide 88

Slide 88 text

©2023 Junichi Kato 88 / 98 「アーキテクチャが組織を駆動するべき」とは? 例えば、一つの大きなソフトウェアプロジェクトがあり、そのアーキテクチャが複数の独立したサービスまたはコンポ ーネントによって構成されると想定する。これらの独立したサービスやコンポーネントそれぞれに対応する形で組織を 分割し、各チームがそのコンポーネントに専念するようにするべきだと提案している。 これにより各チームが特定のサービスやコンポーネントに専念でき、それによって生じる課題に集中的に取り組むこと ができる。(DDDのサブドメインや境界づけられたコンテキストと通じる考え方) ビジネス要求を満たすアーキテクチャが最適であるなら、組織構造はそのアーキテクチャをサポートする形に調整する べきだということ。これは コンウェイの法則の「組織構造がソフトウェアのアーキテクチャを形成する」現象を逆に利 用し、ソフトウェアのアーキテクチャが最適な組織構造を作るというもの

Slide 89

Slide 89 text

©2023 Junichi Kato 89 / 98 組織とアーキテクチャには戦略が必要 メルヴィンは組織を基にアーキテクチャ、コプリエンはアーキテクチャを基に組織を考える必要性と説いている。どち らも事実である。しかし、組織かアーキテクチャかという極端な二項対立的思考に陥らないように「戦略」を意識する ことが重要 「組織は戦略に従う」と、経営史学者アルフレッド・チャンドラーは提言 しました。後に、経営学者イゴール・アンゾフが「戦略は組織に従う」 と 考えました。どちらかが正しいのではありません。どちらも事実であり、 組織は戦略と深い関係があります。 さらにもう1つ、メルヴィン・コンウェイの言葉を足してみましょう。 「システムを設計する組織は、その構造をそっくりまねた構造の設計を生み 出してしまう」。これは、コンウェイの法則として知られている法則です。 チャンドラー、アンゾフ、コンウェイの考えをつなぎ合わせると、組 織は戦略に、戦略は組織に従います。そして、システムは組織を映す鏡となります。 引用: 『エンジニアのためのマネジメント入門』 組織は戦略に従い戦略は組織に従う システムは戦略に従う 組織はシステムに従う 組織 戦略 システム

Slide 90

Slide 90 text

©2023 Junichi Kato 90 / 98 テーマ4のまとめ 組織からアーキテクチャ、アーキテクチャから組織への相互作用を意識することで、組織とアーキテクチャの両方を 改善していくことができる 組織 vs アーキテクチャの二項対立的思考ではなく、一貫した「戦略」に基づいて組織もアーキテクチャも設計して いく必要がある

Slide 91

Slide 91 text

©2023 Junichi Kato 91 / 98 付録: Chatworkでの取り組み事例

Slide 92

Slide 92 text

©2023 Junichi Kato 92 / 98 Chatworkでの次世代アーキテクチャの概要 開発チームに対応した分散型アーキテクチャを前提にしている。コマンドサイドは、Akka/ScalaのCQRS/Event Sourcingを採用。クエリサイドは、RustもしくはGoを使う想定

Slide 93

Slide 93 text

©2023 Junichi Kato 93 / 98 アーキテクチャに対応する組織もスケールできるように変化させてい く Scrum@Scaleは単一のスクラムチームをそのままスケールすることにより拡張する。単一のスクラムチームの最適な 構成人数が4, 5人程度であると言われているように、複数のスクラムチームの最適な構成数は4つか5つをまずは上限と 考えられる。これがScrum of Scrumチーム。 このScrum of Scrumチームは、仮想的なスクラムチームとして振る舞う。つまり、Scrum of Scrumチームはスプリ ントの終わりに統合されたインクリメントに対して責任を持つことになる。また、仮想的なスクラムチームとして、各 スクラムイベントを執り行う。Scaled Daily Scrum (SDS)、Scaled Retrospectiveなど。

Slide 94

Slide 94 text

©2023 Junichi Kato 94 / 98 アーキテクチャに対応する組織もスケールできるように変化させてい く このように、Scrum@Scaleはフラクタル的な構造をとり、理論上は無限にスケールさせる(スケールフリー)

Slide 95

Slide 95 text

©2023 Junichi Kato 95 / 98 FYI: 次期アーキテクチャ向け開発関連の資料 2020-07-16 リアクティブ・アーキテクチャ基礎講座 2020-11-20 リアクティブは難しいが役に立つ 2021-05-26 リアクティブシステムと次世代基盤について 2021-06-07 ChatworkにおけるScrum@Scale導入への挑戦 2022-03-23 Chatworkのリライトプロジェクトをやっている 2022-03-24 Scrum@Scaleによる組織構造の変遷

Slide 96

Slide 96 text

©2023 Junichi Kato 96 / 98 まとめ 本資料では、ドメイン駆動設計と組織パターンを切り口に、無駄と間違いを避けるの観点について説明した。 サブドメイン戦略:「サブドメイン」の考え方が完全な答えにはならないが、問題領域をより深く理解し戦略をサポ ートするツールとしては十分に有用であると考える モデリングのツールとしてのドメインイベント:ドメインイベントを用いたモデリング手法を採用し、ビジネスの重 要な振る舞いをフォーカスできる。また、具体的な手法の一つとしてEvent Stormingの概要を紹介した CQRS/Event Sourcing:CQRSはDDDのためのアーキテクチャパターンの一つ。C/Qごとの要件に合わせて独立し て最適化できる利点がある。一方でそれなりの手間がかかる。CQRSの基本原理を抑えつつ、明確な境界がない CQRSに似た妥協パターンも視野に コンウェイの法則:相互作用があるが、組織 vs アーキテクチャの二項対立的思考ではなく、一貫した「戦略」に基 づいて組織もアーキテクチャも設計していく必要がある

Slide 97

Slide 97 text

©2023 Junichi Kato 97 / 98 著作権表示とライセンス 著作権者は加藤潤一です。 このライセンスは クリエイティブ・コモンズ 表示 - 改変禁止 4.0 国際 ライセンスの下に提供されています。改変し ない限り自由に配布・利用が可能です

Slide 98

Slide 98 text

©2023 Junichi Kato 98 / 98 END