Slide 1

Slide 1 text

#modelinglt ©2022 RAKUS Co., Ltd. RDRAとDDDで Goのモジュラーモノリス アプリを設計してみた話 株式会社ラクス 今本光

Slide 2

Slide 2 text

#modelinglt 今本光(いまもとひかる) SI企業でのエンジニア経験を経て 2021/10にラクスに入社。 SRE課 BusinessPlatform チーム所属。 社内の複数サービスを横断したビ ジネス基盤となるアプリケーション の開発に携わっています。 趣味:野球観戦、サウナ、日向坂46 休日はコワーキングスペースでGo のコードを書いたり資格の勉強を することが多いです。 Twitter: @imamotohikaru GitHub: @kudagonbe

Slide 3

Slide 3 text

#modelinglt 設計したアプリケーションの概要

Slide 4

Slide 4 text

#modelinglt 設計したアプリケーションの概要 ● 2021年10月の入社直後からアサイン ● 業務運用課の要望を元に現在開発中の新規システム ● 運用コスト削減や運用作業品質向上を目的としたWebアプリ ○ 現在は人の手で判断・作業している運用業務を削減 ● 現在の運用は複雑化されたデータ構造のシステムに依存してい て、今回のシステム化でも脱却しないため外部システムとの連携 が必要

Slide 5

Slide 5 text

#modelinglt フェーズごとの戦略 フェーズ 戦略 効果 要件定義 RDRA (リレーションシップ駆動要求分析 ) ・要求元の要求と整合性を取る形で、  業務やビジネスユースケースを洗い出し ・業務フロー図+UC複合図で  必要な画面やシステムの機能洗い出し ・要求元との要件合意の迅速化 設計 DDD (ドメイン駆動設計) ・RDRAをインプットとした  コンテキスト分割やドメイン名 ・コンテキストマップで責務を集約 実装 Goでモジュラーモノリス (WorkspaceModeを使用) ・コンテキストマップ上のコンテキスト名や  コンテキスト間の依存関係を元に  そのままモジュール化できる ・モノレポでデプロイを 1つのアプリとなるが、  モジュール分割しているので並行開発も容易

Slide 6

Slide 6 text

#modelinglt 全体のアウトプットイメージ

Slide 7

Slide 7 text

#modelinglt 要件定義フェーズ

Slide 8

Slide 8 text

#modelinglt 要件定義フェーズ:RDRAを実践 ● RDRA(リレーションシップ駆動要求分析)とは ○ 神崎善司さん(@zenzengood)が提唱している要件分析手法 ■ 本資料での説明も RDRA2.0ハンドブック を参考にしています。 ○ 要件定義には4つの視点があり、RDRAではそれぞれの視点を「レイヤー」 として定義 ■ システム価値>システム外部環境>システム境界>システム ○ 上位レイヤーは下位レイヤーの”Why”となり、下位レイヤーは上位レイヤー の”What”となる ○ 上位レイヤーから要求分析することで、網羅的な要件定義が可能

Slide 9

Slide 9 text

#modelinglt レイヤーごとの視点 ● システム価値レイヤー ○ システムが「誰にとっての価値を実現するのか」を明らかにする ■ 関連するアクターや外部システム、システム化目的等を定義 ● システム外部環境レイヤー ○ システムが「どのように使われるのか」を明らかにする ■ 業務やビジネスユースケースを洗い出し、業務フローや利用ケースを定義する ● システム境界レイヤー ○ システムと「どう関わるか」を明らかにする ■ 誰がどのようにシステムを利用するかや、システムの処理の単位(ユースケース)を定義する ● システムレイヤー ○ システム化する「情報」とその情報が取り得る「状態」でシステムを明示する

Slide 10

Slide 10 text

#modelinglt RDRAの表現手法と記述例 ● アイコン ○ レイヤーごとに定義されるモデルを 表す ● ダイアグラム ○ レイヤーごと明らかにすべき事柄を 示すための図 ● 右図はシステムコンテキスト図 ○ 「システムコンテキスト図」はシステム 価値レイヤーで定義されるダイアグラ ム ○ システムに関わるアクター、外部シス テムをアイコンとして定義する ○ システム化の目的を認識合わせする

Slide 11

Slide 11 text

#modelinglt 今回作成した ダイアグラム ● 「業務フロー+UC複合図」のみ複数 レイヤーを跨ぐダイアグラム ● 作図はdraw.ioで行った上で、 GoogleSpreadSheetに集約 ● それぞれの詳しい説明は時間の関係 上できないため、RDRA2.0ハンド ブック 等をご参照ください。

Slide 12

Slide 12 text

#modelinglt RDRAを実践してみた感想 ● 「要件定義」にとどまらず「基本設計」まで踏み込んだドキュメント が完成される ○ 内容が具体的になるので要求元との要件合意がより迅速・明確にできる ○ 入社直後の私にとっては社内システムやルールの学習にも有用だった ● 「業務」や「ビジネスユースケース」の分割は難しい ○ 最終的には決めの問題なので、試行錯誤して決定する必要がある ● ビジネスとシステムのバランス感覚が必要 ○ システムに寄りすぎると、ビジネス側の人に内容を理解してもらえない

Slide 13

Slide 13 text

#modelinglt 設計フェーズ

Slide 14

Slide 14 text

#modelinglt 設計フェーズ:DDDを実践 ● DDD(ドメイン駆動設計)とは ○ ドメイン(≒システム化対象となる業務の世界)の専門家からの入力を元に、ドメインの世界 に一致するようにドメインをモデル化する設計手法 ● 戦略的DDD ○ ドメインをモデリングするための設計戦略 ■ 境界づけられたコンテキスト、ユビキタス言語の定義等 ● 戦術的DDD ○ 設計した内容を実装するためのモデリング ■ エンティティや値オブジェクトを定義するドメインモデリングはここに属する

Slide 15

Slide 15 text

#modelinglt 戦略的DDDの実践 ● コンテキストマップの作成 ○ RDRAの「ビジネスコンテキスト」「業務フロー+UC複合図」を主なインプットとして、 分割できる業務領域を洗い出して境界付けられたコンテキストを定義 ○ コンテキスト間の依存関係も含めたコンテキストマップを作成 ■ コンテキスト間が相互依存or循環参照にならないように設計 ○ コンテキストごとの責務を明確化してコンテキストマップに付記 ● ユビキタス言語となる用語集の作成 ○ RDRAの「情報モデル」を主なインプットとして、コンテキストごとに「用語説明」とい う形で主なユビキタス言語を付記

Slide 16

Slide 16 text

#modelinglt コンテキストマップイメージ

Slide 17

Slide 17 text

#modelinglt コンテキストごとの設計資料 ● レイヤーごとにインプット資料を作成 ○ コンテキストごとにレイヤードアーキテクチャ構成をとる想定のため ● Domain層:ドメインモデル図 ● UserInterface層、Application層:シーケンス図 ● Infrastructure層:テーブル設計

Slide 18

Slide 18 text

#modelinglt DDDを実践してみた感想 ● 前フェーズのRDRAの資料をインプットとして活用できた点が良かった ○ RDRAで基本設計まで踏み込んでいるので、モデリングがしやすかった ○ 開発のためのDDDから一歩前進できた ● テキストベースでの用語説明や設計意図説明も残しておいた方が良い ○ 「ドメインモデル図さえあれば実装できる!」という人はドメインモデルの作成者しかいな い ● mermaid.jsを使ってmarkdownファイル内で書いたので、レビューもし てもらいやすかった ○ GitHubがmermaidの自動レンダリングに対応している

Slide 19

Slide 19 text

#modelinglt 実装フェーズ

Slide 20

Slide 20 text

#modelinglt 実装フェーズ:Goでモジュラーモノリス ● Goには「module」というコード管理 単位が存在 ● go.modというファイルにmodule名 や依存するmoduleを記載 ● go.modが置かれているフォルダ配下 はすべて同moduleに属する ● ただしサブフォルダに別のgo.mod ファイルが置かれている場合は、別の moduleとなる ● module間の依存解決の手段として Workspace modeを利用 Main Module Module A Module B Main Module Workspace 管理

Slide 21

Slide 21 text

#modelinglt GoのWorkspace mode ● Go1.18から導入 ● Moduleの解決をgo.workファイルに記述できる

Slide 22

Slide 22 text

#modelinglt 実装の基本方針 ● 設計時に定義したコンテキストの単位でGo Moduleを作成することで、モジュ ラーモノリスを実現する ○ Module名やModule間の依存関係はコンテキストマップを踏襲 ○ 1つのリポジトリ(モノレポ)で複数Moduleを管理 ○ Workspace modeで同一リポジトリ内のModuleにも依存可能 ● Moduleごとにレイヤードアーキテクチャ構成にする ● コンテキストごとにDBも分割 ○ PostgreSQLで同一DBクラスタで複数DBを作成 ● 外部からのHTTPSリクエストはメインのModuleで受けて、各コンテキストの UI層にリクエスト情報を渡す形でAPI呼び出しを実現

Slide 23

Slide 23 text

#modelinglt 未来の話:モジュラーモノリスをMSA化 ● 今後、必要性を感じてMSA化する場合はModuleを別リポジトリに切 り出してIN/OUTを調整することで実現可能 ○ 作成済みのAPIを呼び出すエンドポイントを準備 ■ UI層まで作成済みなので、工数としては大きくない ○ 切り出したModuleのメソッドをInfrastructure層で呼び出していた箇所を、API 呼び出しに切り替える ■ レスポンスのフォーマットは基本的に変わらず、改修箇所の特定も容易なので、工数としては大き くない ○ DBは既に分離済みのため、大きなマイグレーション不要

Slide 24

Slide 24 text

#modelinglt Goでモジュラーモノリスを実践してみた感想 ● DDDの境界づけられたコンテキストがソースコードにも対応づけられる ので、要件定義・設計フェーズとの一貫性が出て良かった ● Go ModuleやWorkspace modeでモジュール化が容易なので、モ ジュラーモノリス構成を実現するのにGoは適した言語だと思う ● GoでDDDを実践するための実装手法についてもある程度方向が定 まったが、手探りになる場面が多かった ○ 知見を更に貯めて別の機会に発表したい

Slide 25

Slide 25 text

#modelinglt ご清聴ありがとうございました。