Slide 1

Slide 1 text

DDDでレガシーコードに立ち向かうリアル 〜躓きと学び〜 2024年3月24日 Object-Oriented Conference 2024 株式会社コドモン 中田 義人

Slide 2

Slide 2 text

2 経歴 プロダクト開発チームにて請求・決済関連機能のアプリケーション開 発に携わる。整理整頓が好き。最近の趣味はガンプラ。 自己紹介 中田 義人 なかた よしと 2009.04 前職のSIerに新卒入社 2022.11 コドモンに開発エンジニアとして入社

Slide 3

Slide 3 text

3 Mission

Slide 4

Slide 4 text

4 すべての先生に 子どもと向き合う 時間と心のゆとりを こんなプロダクトを開発しています メインプロダクトは、保育・教育施設向けWebアプリケーション。 保護者と施設のやり取りを支えるモバイルアプリケーションや、施設職員向けモバイル版 アプリケーション、外部サービスと連携するAPIなども開発しています。

Slide 5

Slide 5 text

5 はじめに

Slide 6

Slide 6 text

6 レガシーコードにDDDの考え方を取り入れたいけど どこからどう手をつけたらよいかわからない

Slide 7

Slide 7 text

7 DDDを取り入れてはみたが いろいろな概念や設計パターンを ちゃんと理解して、上手く使えているか、自信がない

Slide 8

Slide 8 text

8 そんなあなたの背中を押したい!

Slide 9

Slide 9 text

9 コドモンではどんな感じなのか 赤裸々にお伝えします

Slide 10

Slide 10 text

10 今日話すこと コドモンのレガシーコードの現状 DDDの実践と躓き 得られた学びとこれから 1 2 3

Slide 11

Slide 11 text

11 ● DDDを組織にどのように導入したか ● DDDの概念や設計パターンの詳細説明 今日話さないこと

Slide 12

Slide 12 text

12 今日話すこと コドモンのレガシーコードの現状 DDDの実践と躓き 得た学びとこれから 1 2 3

Slide 13

Slide 13 text

13 CONFIDENTIAL - © 2022 CoDMON Inc. 13 1. コドモンのレガシーコードの現状 プロダクトと開発組織の急速な成長 エンジニア数 65人 2024年3月現在 業務委託含む

Slide 14

Slide 14 text

14 CONFIDENTIAL - © 2022 CoDMON Inc. 14 1. コドモンのレガシーコードの現状 保守性の重要度があがってきた

Slide 15

Slide 15 text

15 CONFIDENTIAL - © 2022 CoDMON Inc. 15 Domain Usecase Presentation Infrastructure Tests E2E/IT 1. コドモンのレガシーコードの現状 File File File File Class Class Class Class Class Class Class API API API API API API API API ● API Endpointごとに 1ファイルにほぼ全処理が書 かれている ● 手動テスト(E2Eのみ) gauge gauge gauge gauge ほぼ 手動 モノリス(バックエンド)はモジュラーモノリスを目指す ● コンテキスト × レイヤーでモ ジュールを分割 ● 自動テスト(E2E/IT/UT) gauge gauge Class Bounded Context A Bounded Context B リファクタ前の領域 リファクタ後の領域

Slide 16

Slide 16 text

16 CONFIDENTIAL - © 2022 CoDMON Inc. 16 Domain Usecase Presentation Infrastructure Tests E2E/IT 1. コドモンのレガシーコードの現状 File File File File Class Class Class Class Class Class Class API API API API API API API API ● API Endpointごとに 1ファイルにほぼ全処理が書 かれている ● 手動テスト(E2Eのみ) gauge gauge gauge gauge ほぼ 手動 モノリス(バックエンド)はモジュラーモノリスを目指す ● コンテキスト × レイヤーでモ ジュールを分割 ● 自動テスト(E2E/IT/UT) gauge gauge Class Bounded Context A Bounded Context B リファクタ前の領域 リファクタ後の領域 改修する部分から順次リファクタして移す

Slide 17

Slide 17 text

17 CONFIDENTIAL - © 2022 CoDMON Inc. 17 1. コドモンのレガシーコードの現状 リファクタリングの優先度 基本的には、改修が必要な部分からやる(ボーイスカウト・ルール) いま改修が必要な部分 ≒ 近々、追加改修が必要になる可能性も高い部分 ただし、 リファクタリングを集中的に やる場合もある。 OOC2024ガイドブック記事

Slide 18

Slide 18 text

18 今日話すこと コドモンのレガシーコードの現状 DDDの実践と躓き 得た学びとこれから 1 2 3

Slide 19

Slide 19 text

19 今日話すこと コドモンのレガシーコードの現状 DDDの実践と躓き 得た学びとこれから 1 2 3

Slide 20

Slide 20 text

20 CONFIDENTIAL - © 2022 CoDMON Inc. 20 2. DDDの実践と躓き ご紹介する事例 コドモンにおいて、DDDの設計パターンを取り入れて レガシーコードのリファクタリングを行った開発事例として、 2023年度に行ったインボイス制度対応での出来事をご紹介します。

Slide 21

Slide 21 text

21 CONFIDENTIAL - © 2022 CoDMON Inc. 21 2. DDDの実践と躓き インボイス制度とは ● 2023年10月1日から施行された、新しい仕入税額控除の制度 ● 適格請求書は正確な適用税率や消費税額等を伝える必要がある 国税庁サイトより

Slide 22

Slide 22 text

22 CONFIDENTIAL - © 2022 CoDMON Inc. 22 2. DDDの実践と躓き コドモンにおけるインボイス制度対応 消費税計算ロジックの変更が必要 改修するうえで厄介だったこと ● 複数の画面・APIで消費税計算が実装されている ● 修正が必要なAPIの多くがレガシーコード(先述のリファクタ前の領域) ● 制度の施行開始までに開発を間に合わせる必要がある

Slide 23

Slide 23 text

23 CONFIDENTIAL - © 2022 CoDMON Inc. 23 2. DDDの実践と躓き コドモンにおけるインボイス制度対応 どうする? ● 今後の保守性向上のため、ロジックが散らばった状態は是正したい ● 改修対象が多いので、本開発のテスト・実装の効率観点でも、 ドメインロジックの共通化が必要 ↓ ロジック変更と合わせてリファクタリングも行う

Slide 24

Slide 24 text

24 CONFIDENTIAL - © 2022 CoDMON Inc. 24 2. DDDの実践と躓き リファクタリングの進め方 開発担当チームではリファクタガイドラインを用意していた レガシーコードをリファクタ後の領域に移す手順

Slide 25

Slide 25 text

25 CONFIDENTIAL - © 2022 CoDMON Inc. 25 2. DDDの実践と躓き リファクタガイドラインの概要 既存APIのコード(リファクタ前) Test 自動テスト作成 Step 1 Step 2 Step 3 Step 4 Step 5

Slide 26

Slide 26 text

26 CONFIDENTIAL - © 2022 CoDMON Inc. 26 2. DDDの実践と躓き リファクタガイドラインの概要 既存APIのコード(リファクタ前) Controller Test Test UseCase そのまま移す APIパスだけ変更 Step 1 Step 2 Step 3 Step 4 Step 5

Slide 27

Slide 27 text

27 CONFIDENTIAL - © 2022 CoDMON Inc. 27 2. DDDの実践と躓き リファクタガイドラインの概要 既存APIのコード(リファクタ前) Controller Test Test UseCase Controller UseCase Repositories Models DBアクセスを切り出し Step 1 Step 2 Step 3 Step 4 Step 5

Slide 28

Slide 28 text

28 CONFIDENTIAL - © 2022 CoDMON Inc. 28 2. DDDの実践と躓き リファクタガイドラインの概要 既存APIのコード(リファクタ前) Controller Test Test UseCase Controller UseCase Repositories Models Controller UseCase Repositories Models ドメインロジックを移す Step 1 Step 2 Step 3 Step 4 Step 5

Slide 29

Slide 29 text

29 CONFIDENTIAL - © 2022 CoDMON Inc. 29 2. DDDの実践と躓き リファクタガイドラインの概要 既存APIのコード(リファクタ前) Controller Test Test UseCase Controller UseCase Repositories Models Controller UseCase Repositories Models Controller UseCase Repositories Models req/res検証・変換や認証を移す Step 1 Step 2 Step 3 Step 4 Step 5

Slide 30

Slide 30 text

30 CONFIDENTIAL - © 2022 CoDMON Inc. 30 2. DDDの実践と躓き リファクタガイドラインの概要 既存APIのコード(リファクタ前) Controller Test Test UseCase Controller UseCase Repositories Models Controller UseCase Repositories Models Controller UseCase Repositories Models Step 1 Step 2 Step 3 Step 4 Step 5 繰り返し 拡充

Slide 31

Slide 31 text

31 CONFIDENTIAL - © 2022 CoDMON Inc. 31 2. DDDの実践と躓き リファクタガイドラインの概要 既存APIのコード(リファクタ前) Controller Test Test UseCase Controller UseCase Repositories Models Controller UseCase Repositories Models Controller UseCase Repositories Models Step 1 Step 2 Step 3 Step 4 Step 5 どのステップまでやるか、どの部分を切り出すか 見積の際にチームで認識を合わせる

Slide 32

Slide 32 text

32 CONFIDENTIAL - © 2022 CoDMON Inc. 32 ドメインの概要 2. DDDの実践と躓き

Slide 33

Slide 33 text

33 CONFIDENTIAL - © 2022 CoDMON Inc. 33 インボイス対応で扱ったドメインモデルの概要 2. DDDの実践と躓き

Slide 34

Slide 34 text

34 CONFIDENTIAL - © 2022 CoDMON Inc. 34 インボイス対応で扱ったドメインモデルの概要 2. DDDの実践と躓き 2024年3月の山田太郎(園児)さん分の請求 園児ごと月単位の 「請求情報」 項目名 単価 数量 価格 税種別 税率 月極保育料 15,000 1 15,000 非課税 延長保育料 2,000 1 2,000 非課税 教材費 500 1 500 税抜 10% バス送迎 1,000 1 1,000 税抜 10% 「請求情報」は 「請求明細」 を複数もつ 請求額(消費税)の 計算単位

Slide 35

Slide 35 text

35 CONFIDENTIAL - © 2022 CoDMON Inc. 35 2. DDDの実践と躓き 項目名 税抜金額 消費税額 税率 月極保育料 40,000 - 非課税 延長保育料 10,000 - 非課税 バス送迎 3,105 311 10% 教材費 645 65 10% 非課税 計 50,000 - 10%対象計 3,750 376 項目名 税抜金額 消費税額 税率 月極保育料 40,000 - 非課税 延長保育料 10,000 - 非課税 バス送迎 3,105 - 10% 教材費 645 - 10% 非課税 計 50,000 - 10%対象計 3,750 375 ×0.1 ×0.1 合算 合算 ×0.1 請求額 請求額 ¥54,126 ¥54,125 認められない計算例(変更前) 認められる計算例(変更後) ※上記は計算例を示したものです。適格請求書の要件は他にもあります。 1 2 1 2 消費税計算ロジックの変更点

Slide 36

Slide 36 text

36 CONFIDENTIAL - © 2022 CoDMON Inc. 36 ドメインロジックも大して複雑じゃないし 共通化できてしまえば差し替えは簡単でしょ🙂 2. DDDの実践と躓き ↓ 思ったほど上手くいかなかった🫠

Slide 37

Slide 37 text

37 CONFIDENTIAL - © 2022 CoDMON Inc. 37 参照・更新の単位がまちまち 1つのAPIの責務が大きい 思った以上に重複が多い 1 2 3 躓いてわかったコドモンのレガシーコードの課題 2. DDDの実践と躓き

Slide 38

Slide 38 text

38 CONFIDENTIAL - © 2022 CoDMON Inc. 38 参照・更新の単位がまちまち 1つのAPIの責務が大きい 思った以上に重複が多い 1 2 3 躓いてわかったコドモンのレガシーコードの課題 2. DDDの実践と躓き

Slide 39

Slide 39 text

39 CONFIDENTIAL - © 2022 CoDMON Inc. 39 参照・更新の単位がまちまち 躓いたAPI その1 園児の絞り込み テスト用データです こども施設に所属する複数園児の請求額の合計の情報を取得するAPI

Slide 40

Slide 40 text

40 CONFIDENTIAL - © 2022 CoDMON Inc. 40 既存コードがやっていたこと 園児 テーブル クラス テーブル 請求情報 テーブル ・ ・ ・ JOIN 対象園児の絞り込み 入園前・卒園後 所属クラス 当月の請求状態 etc 請求額(消費税)の計算 いろんなテーブルを一度にJOINして取得してから、いろいろ処理している 参照・更新の単位がまちまち

Slide 41

Slide 41 text

41 CONFIDENTIAL - © 2022 CoDMON Inc. 41 既存コードがやっていたこと 園児 テーブル クラス テーブル 請求情報 テーブル ・ ・ ・ JOIN 対象園児の絞り込み 入園前・卒園後 所属クラス 当月の請求状態 etc 請求額(消費税)の計算 いろんなテーブルを一度にJOINして取得してから、いろいろ処理している リポジトリ経由に 変えたいところ ドメインモデルに 変えたいところ 参照・更新の単位がまちまち

Slide 42

Slide 42 text

42 CONFIDENTIAL - © 2022 CoDMON Inc. 42 困ったこと 園児絞り込み条件と請求額計算の実装が絡み合っている ↓ 請求情報の取得のみをリポジトリに差し替えるのが難しい ただし、 園児の絞り込みに関わるデータ取得やロジックの全体を リファクタリングしている時間的余裕はない... 参照・更新の単位がまちまち

Slide 43

Slide 43 text

43 CONFIDENTIAL - © 2022 CoDMON Inc. 43 どうしたか 園児 テーブル クラス テーブル 請求情報 テーブル ・ ・ ・ JOIN 対象園児の絞り込み 請求額(消費税)の計算 既存のテーブル取得処理は残しつつ、別途リポジトリからモデルを取得する リポジトリ経由で取得 園児IDリストを 引数として渡す 請求額(消費税)の計算 テーブルアクセスが冗長だが 高負荷処理ではないので妥協 参照・更新の単位がまちまち

Slide 44

Slide 44 text

44 CONFIDENTIAL - © 2022 CoDMON Inc. 44 id child_id target_date confirm_flag price tax_percentage item_name … 11111113 2000 2023-12-01 0 500 8 おやつ 11111112 2000 2023-12-01 0 3000 10 送迎バス 11111111 2000 2023-11-01 1 2000 0 一時保育 11111110 3000 2023-11-01 1 1000 0 延長保育料 請求 情報 請求情報テーブルを確認したら レコードの単位は「請求明細」(正規化されていない) 明細 明細 既存コードは「請求明細」単位で取得・更新している😕 参照・更新の単位がまちまち

Slide 45

Slide 45 text

45 CONFIDENTIAL - © 2022 CoDMON Inc. 45 請求情報の更新はどうする? 「請求情報」の整合性は更新時にどうチェックしてる?🤔 参照・更新の単位がまちまち

Slide 46

Slide 46 text

46 CONFIDENTIAL - © 2022 CoDMON Inc. 46 請求情報の更新はどうする? 参照・更新の単位がまちまち 請求情報 テーブル 更新APIのコードを見ると 更新API a 更新API b 受け取った請求明細 のみチェック 請求明細 1 請求明細 2 更新API c 請求明細 1 請求明細 2 請求明細 3 請求明細 3 請求情報のまとまりを 意識していないAPIもある

Slide 47

Slide 47 text

47 CONFIDENTIAL - © 2022 CoDMON Inc. 47 請求情報の更新はどうする? 参照・更新の単位がまちまち 請求情報 テーブル フロントエンドのコードまで見ると 更新API 全ての請求明細を取得 請求情報のまとまり 請求明細 1 請求明細 2 請求明細 3 参照API フロントエンド 全ての請求明細を送信 請求情報単位で チェック・処理 請求情報のまとまり 請求明細 1 請求明細 2 請求明細 3 受け取った請求明細 のみチェック

Slide 48

Slide 48 text

48 CONFIDENTIAL - © 2022 CoDMON Inc. 48 請求情報の更新はどうする? 「請求情報」の整合性は更新時にどうチェックしてる?🤔 ↓ 複数APIが各々でチェック + Frontendで全体チェック ただし、 複数APIやFrontendに散らばっているチェック仕様をかき集めて、 ドメインモデルに確実に移している時間的余裕はない 参照・更新の単位がまちまち

Slide 49

Slide 49 text

49 CONFIDENTIAL - © 2022 CoDMON Inc. 49 どうしたか 今回は参照処理のみをDDDでリファクタリングすることにした ● リポジトリは、findメソッドのみ ● ドメインモデルは、参照系メソッド(消費税の計算を含む)のみ 今後、更新処理も改修する機会があればリファクタリングしたい... 参照・更新の単位がまちまち

Slide 50

Slide 50 text

50 なぜこうなった? どうすればよい?

Slide 51

Slide 51 text

51 CONFIDENTIAL - © 2022 CoDMON Inc. 51 「集約」とは DDDの「集約」の考え方を取り入れてみる 参照・更新の単位がまちまち エンティティと値オブジェクトを集約の中にまとめ、各集約の周囲に境界 を定義すること。〜〜〜 〜〜〜 〜〜〜 どんな状態変化においても、集約内にあるオブジェクトと集約全体に対し て、不変条件をすべて強制する〜〜〜 「エリック・エヴァンスのドメイン駆動設計」より抜粋

Slide 52

Slide 52 text

52 CONFIDENTIAL - © 2022 CoDMON Inc. 52 集約の観点で見ると 参照・更新の単位がまちまち 請求明細は集約ルートでもエンティティでもない 集約の境界 集約ルート

Slide 53

Slide 53 text

53 CONFIDENTIAL - © 2022 CoDMON Inc. 53 うまくいかなかった要因 いろんなテーブルをJOINして まとめて取得している ↓ 集約より広い範囲を まとめて操作している ↓ 責務が混ざって複雑になる 「請求明細」のレコード単位で 取得・更新している ↓ 集約の一部だけを 個別に操作している ↓ 不変条件を制御しづらい 参照・更新の単位がまちまち

Slide 54

Slide 54 text

54 CONFIDENTIAL - © 2022 CoDMON Inc. 54 参照・更新の単位がまちまち ↓ 集約単位で参照・更新する 学び 参照・更新の単位がまちまち

Slide 55

Slide 55 text

55 CONFIDENTIAL - © 2022 CoDMON Inc. 55 参照・更新の単位がまちまち 1つのAPIの責務が大きい 思った以上に重複が多い 1 2 3 躓いてわかったコドモンのレガシーコードの課題 2. DDDの実践と躓き

Slide 56

Slide 56 text

56 CONFIDENTIAL - © 2022 CoDMON Inc. 56 参照・更新の単位がまちまち 1つのAPIの責務が大きい 思った以上に重複が多い 1 2 3 躓いてわかったコドモンのレガシーコードの課題 2. DDDの実践と躓き

Slide 57

Slide 57 text

57 CONFIDENTIAL - © 2022 CoDMON Inc. 57 1つのAPIの責務が大きい 躓いたAPI その2 請求情報を確定して請求額(消費税を含む)を決定するAPI テスト用データです

Slide 58

Slide 58 text

58 CONFIDENTIAL - © 2022 CoDMON Inc. 58 1つのAPIの責務が大きい 請求情報を変更・確定 確定した請求情報を 保存 保存した請求情報を 再取得 請求情報を受信 請求額(消費税)を計算 請求額を入金管理に 登録 処理の流れ billsテーブルのrecordデータ作成 UPDATE bills SELECT FROM bills APIリクエストbody $bill->price * $bill->tax_percentage INSERT INTO payments 既存コード

Slide 59

Slide 59 text

59 CONFIDENTIAL - © 2022 CoDMON Inc. 59 1つのAPIの責務が大きい 請求情報を変更・確定 確定した請求情報を 保存 保存した請求情報を 再取得 請求情報を受信 請求額(消費税)を計算 請求額を入金管理に 登録 処理の流れ billsテーブルのrecordデータ作成 UPDATE bills SELECT FROM bills APIリクエストbody $bill->price * $bill->tax_percentage INSERT INTO payments 既存コード 修正イメージ $bills = BillRepository->findByChildIds() $bill->priceTotal() リポジトリ取得にする モデルに計算させる

Slide 60

Slide 60 text

60 CONFIDENTIAL - © 2022 CoDMON Inc. 60 1つのAPIの責務が大きい 修正はあっさり完了、しかし E2Eテストが ローカル環境(docker)だと通るのに 検証環境(AWS)だと通らない

Slide 61

Slide 61 text

61 CONFIDENTIAL - © 2022 CoDMON Inc. 61 1つのAPIの責務が大きい 請求情報を変更・確定 確定した請求情報を 保存 保存した請求情報を 再取得 請求情報を受信 請求額(消費税)を計算 請求額を入金管理に 登録 テストが、ローカル環境だと通るのに、検証環境だと通らない billsテーブルのrecordデータ作成 UPDATE bills SELECT FROM bills APIリクエストbody $bill->price * $bill->tax_percentage INSERT INTO payments 既存コード 修正イメージ $bills = BillRepository->findByChildIds() $bill->priceTotal() 請求額の変更が反映されない! 変更・確定の保存は成功している

Slide 62

Slide 62 text

62 CONFIDENTIAL - © 2022 CoDMON Inc. 62 1つのAPIの責務が大きい 請求情報を変更・確定 確定した請求情報を 保存 保存した請求情報を 再取得 請求情報を受信 請求額(消費税)を計算 請求額を入金管理に 登録 原因 billsテーブルのrecordデータ作成 UPDATE bills SELECT FROM bills APIリクエストbody $bill->price * $bill->tax_percentage INSERT INTO payments 既存コード 修正イメージ $bills = BillRepository->findByChildIds() $bill->priceTotal() 全体が1トランザクション WriterDBに接続 SELECTクエリの場合は 自動でReaderDBに接続 トランザクションの途中なので 再取得結果(ReaderDB)には 変更が反映されていない

Slide 63

Slide 63 text

63 CONFIDENTIAL - © 2022 CoDMON Inc. 63 ● 既存コードとリポジトリ実装で、 トランザクション(DBClientインスタンス)が別になっていた →同一のトランザクションを使うように修正した ● ローカル環境はDBとReader/Writerが同一コンテナだった →ローカル環境もReader/Writeを分けて不具合を検出可能とした 1つのAPIの責務が大きい どうしたか

Slide 64

Slide 64 text

64 なぜこうなった? どうすればよい?

Slide 65

Slide 65 text

65 CONFIDENTIAL - © 2022 CoDMON Inc. 65 1つのAPIの責務が大きい なぜバグを作り込んでしまったのか? ● トランザクション範囲の確認不足? ● フレームワークの仕様の確認不足? それはそう でも、そもそも ● トランザクション範囲が広すぎでは? ● 1API、1ユースケースの責務が大きすぎでは? ※ここで言う「ユースケース」は、実装文脈の「アプリケーションサービス」

Slide 66

Slide 66 text

66 CONFIDENTIAL - © 2022 CoDMON Inc. 66 1つのAPIの責務が大きい 請求情報を変更・確定 確定した請求情報を 保存 保存した請求情報を 再取得 請求情報を受信 請求額を計算 請求額を入金管理に 登録 トランザクション範囲を再考する 請求情報を 変更・確定する 確定請求額を 入金管理に登録する この境界線で トランザクション範囲 は分けられるはず 別の集約 集約

Slide 67

Slide 67 text

67 CONFIDENTIAL - © 2022 CoDMON Inc. 67 1つのAPIの責務が大きい API・ユースケースの責務を再考する ユースケースを前半と後半で2つに分けたい ただし、 ● ユーザ操作は1アクションのままにしたい ● フロントからのAPIリクエストも、 1つのままにしたい 請求情報を 変更・確定する 確定請求額を 入金管理に登録する 入金管理は別コンテキスト になりそう

Slide 68

Slide 68 text

68 CONFIDENTIAL - © 2022 CoDMON Inc. 68 1つのAPIの責務が大きい DDDの「ドメインイベント」の考え方を取り入れてみる 「ドメインイベント」とは 「ドメインエキスパートが気にかける、何かの出来事」 ドメインエキスパートの話の中に出てくるフレーズ ● 「・・・するときに、」 ● 「もしそうなったら、・・・」 ● 「・・・の場合は、私に知らせてほしい」「・・・の場合は、通知してほしい」 ● 「・・・が発生したときに」 「実践ドメイン駆動設計」より抜粋

Slide 69

Slide 69 text

69 CONFIDENTIAL - © 2022 CoDMON Inc. 69 1つのAPIの責務が大きい DDDの「ドメインイベント」の考え方を取り入れてみる 請求情報を 変更・確定する 確定請求額を 入金管理に登録する < event > 請求が確定した ドメインイベントを介して、2つのユースケースを繋げる ObserverパターンまたはMessaging Serviceを介してイベント連携する 1つのユースケースの責務を小さく保ちつつ、 ユーザ操作やAPI呼び出しも最小限に抑えることが可能 Publish Subscribe

Slide 70

Slide 70 text

70 CONFIDENTIAL - © 2022 CoDMON Inc. 70 1つのAPIの責務が大きい ↓ 適切にユースケース分割して 必要に応じてドメインイベントで連携する 1つのAPIの責務が大きい 学び

Slide 71

Slide 71 text

71 CONFIDENTIAL - © 2022 CoDMON Inc. 71 参照・更新の単位がまちまち 1つのAPIの責務が大きい 思った以上に重複が多い 1 2 3 躓いてわかったコドモンのレガシーコードの課題 2. DDDの実践と躓き

Slide 72

Slide 72 text

72 CONFIDENTIAL - © 2022 CoDMON Inc. 72 参照・更新の単位がまちまち 1つのAPIの責務が大きい 思った以上に重複が多い 1 2 3 躓いてわかったコドモンのレガシーコードの課題 2. DDDの実践と躓き

Slide 73

Slide 73 text

73 CONFIDENTIAL - © 2022 CoDMON Inc. 73 思った以上に重複が多い 無事にインボイス対応を終えた後 私は、決済基盤を新規開発する別チームに異動しました このチームでは、Kotlinで新しいマイクロサービスを開発しています そんなある日のこと 「今日やるストーリーでは この画面を作ろう!」 また消費税計算つくるの?今度はKotlinで? 開発中の画面です

Slide 74

Slide 74 text

74 CONFIDENTIAL - © 2022 CoDMON Inc. 74 思った以上に重複が多い ● 請求管理機能で消費税計算の修正を、長い時間を かけてやっていた ● 他の機能でもそれぞれ消費税計算を実装している ↓ でも、ユーザ価値はなにも増えてない 振り返れば

Slide 75

Slide 75 text

75 なぜこうなった? どうすればよい?

Slide 76

Slide 76 text

76 CONFIDENTIAL - © 2022 CoDMON Inc. 76 思った以上に重複が多い DDDの「汎用サブドメイン」の考え方を取り入れてみる 「汎用サブドメイン」とは 設計中のプロジェクトにとって動機となっていない、高凝集のサブドメインを識別 すること。そうしたサブドメインから汎用的なモデルを括り出して、別のモジュー ルに入れること。その中に特化した要素を一切残してはならない。 いったん分離したら、その部分に対して継続される開発の優先順位をコアドメイン より下げ、その作業にコアとなる開発者を割り当てるのを避けること(そこから得 られるドメインについての知識はほとんどないからだ)。 「エリック・エヴァンスのドメイン駆動設計」より抜粋

Slide 77

Slide 77 text

77 CONFIDENTIAL - © 2022 CoDMON Inc. 77 思った以上に重複が多い 請求管理機能の価値とは? 多様な 保育料形態 への対応 複雑な 延長保育料の 自動計算 各種保育実績 と連動した 請求額計算 請求管理機能が 提供したい価値 消費税計算 必要だが本質ではない 固有性はない コアドメイン 汎用サブドメイン

Slide 78

Slide 78 text

78 CONFIDENTIAL - © 2022 CoDMON Inc. 78 思った以上に重複が多い 汎用サブドメインの対応方法 「エリック・エヴァンスのドメイン駆動設計」より ● 選択肢1:既製品による解決 ● 選択肢2:公表されている設計やモデル ● 選択肢3:実装のアウトソーシング ● 選択肢4:自社での実装 汎用サブドメインに力をかけずコアドメインに注力したい

Slide 79

Slide 79 text

79 CONFIDENTIAL - © 2022 CoDMON Inc. 79 思った以上に重複が多い ↓ 汎用サブドメインを見分けて戦略的に開発する 思った以上に重複が多い 学び

Slide 80

Slide 80 text

80 CONFIDENTIAL - © 2022 CoDMON Inc. 80 参照・更新の単位がまちまち 1つのAPIの責務が大きい 思った以上に重複が多い 1 2 3 躓いてわかったコドモンのレガシーコードの課題 2. DDDの実践と躓き

Slide 81

Slide 81 text

81 今日話すこと コドモンのレガシーコードの現状 DDDの実践と躓き 得た学びとこれから 1 2 3

Slide 82

Slide 82 text

82 今日話すこと コドモンのレガシーコードの現状 DDDの実践と躓き 得た学びとこれから 1 2 3

Slide 83

Slide 83 text

83 CONFIDENTIAL - © 2022 CoDMON Inc. 83 参照・更新の単位がまちまち ↓ 集約単位で参照・更新する 3. 得た学びとこれから 学び①

Slide 84

Slide 84 text

84 CONFIDENTIAL - © 2022 CoDMON Inc. 84 3. 得た学びとこれから モデリングにおいて、集約の単位・境界を重視し、集約を中心に考えてみる

Slide 85

Slide 85 text

85 CONFIDENTIAL - © 2022 CoDMON Inc. 85 集約の境界・関連を強調したモデル図を作成 3. 得た学びとこれから

Slide 86

Slide 86 text

86 CONFIDENTIAL - © 2022 CoDMON Inc. 86 1つのAPIの責務が大きい ↓ 適切にユースケース分割して 必要に応じてドメインイベントで連携する 3. 得た学びとこれから 学び②

Slide 87

Slide 87 text

87 CONFIDENTIAL - © 2022 CoDMON Inc. 87 3. 得た学びとこれから イベントストーミングによるモデリングを取り入れてみる 成瀬さんにワークショップを実施いただき、チャレンジ中 弊社テックブログ記事:https://tech.codmon.com/entry/2024/03/19/204440

Slide 88

Slide 88 text

88 CONFIDENTIAL - © 2022 CoDMON Inc. 88 3. 得た学びとこれから Amazon API Gateway Microservice Amazon EventBridge Event Bus Rule Rule Rule API Destination Rule API Destination API Destination Monolith UseCase Aggregate Publisher Forwarder Subscriber Controller Microservice create update delete publish event イベント駆動のモデルに適したアーキテクチャを検討中 モノリスとマイクロサービスを繋ぐMessaging Serviceの案

Slide 89

Slide 89 text

89 CONFIDENTIAL - © 2022 CoDMON Inc. 89 思った以上に重複が多い ↓ 汎用サブドメインを見分けて戦略的に投資する 3. 得た学びとこれから 学び③

Slide 90

Slide 90 text

90 CONFIDENTIAL - © 2022 CoDMON Inc. 90 3. 得た学びとこれから 汎用サブドメインの対応方法 「エリック・エヴァンスのドメイン駆動設計」より ● 選択肢1:既製品による解決 ● 選択肢2:公表されている設計やモデル ● 選択肢3:実装のアウトソーシング ● 選択肢4:自社での実装 汎用サブドメインに力をかけずコアドメインに注力したい まずは 社内で公表されたモデルの ドキュメントを用意する モノリス・マイクロサービスで 複数のプログラミング言語が混在

Slide 91

Slide 91 text

91 最後に

Slide 92

Slide 92 text

92 CONFIDENTIAL - © 2022 CoDMON Inc. 92 改めて振り返ると DDDのパターンを使用して、レガシーコードのリファクタリングを行なった  ↓ レガシーコードの課題が浮き彫りになった  ↓ 浮き彫りになった課題の解決策もまた、DDDの中にあった  ↓ DDDの理解が深まり、新規開発でもより良い設計ができるようになった

Slide 93

Slide 93 text

93 CONFIDENTIAL - © 2022 CoDMON Inc. 93 改めて振り返ると ● 自分たちが当事者である課題 ● 仮定でなく、現実に起きている課題 ● ビジネスとともに成長してきた複雑な課題 リアルな 設計課題とは レガシーコードはリアルな設計課題の宝庫 ● 解決したい課題が実感しやすい ● 設計パターンの必要性や使い所がわかる ● 設計パターンを実際に開発現場で試せる 読書や演習 と比べて ↓

Slide 94

Slide 94 text

94 CONFIDENTIAL - © 2022 CoDMON Inc. 94 つまり リポジトリ エンティティ 値オブジェクト レガシーコード 負債との闘い リアルな設計課題 設計課題の解決策を探る 新たな武器を得て再度潜入 初期装備 集約 ドメイン イベント 汎用サブ ドメイン レガシーコードの リファクタリングは 「宝探し」

Slide 95

Slide 95 text

95 楽しそうじゃないですか?

Slide 96

Slide 96 text

96 ちなみに

Slide 97

Slide 97 text

97 コドモン採用ページ 開発ブログ コドモンでは一緒に働きたい仲間を募集しています!

Slide 98

Slide 98 text

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

Slide 99

Slide 99 text

No content