モジュラモノリス - 現代システム開発の実用的アプローチ
🎯 目的
モジュラモノリスについて解説し、他の方がモジュラモノリスの設計に関する意思決定を行えるようにする
👤 自己紹介
2018年から2025年までヤフーやBASE株式会社などで、システムアーキテクチャ/アプリケーションアーキテクチャ設計、開発、保守運用を行いました。システムアーキテクチャ/アプリケーションアーキテクチャ/DDDについてのお仕事は下記の Wantedly や LinkedIn , X まで気軽にご連絡ください!
企業 | 活動内容 |
---|---|
❗ヤフー 18年4月~22年5月 |
・ヤフーショッピングのマーケティングシステムの設計/開発/保守運用を行いました。 ・マイクロサービスアーキテクチャの設計/開発を行いました ・ドメイン駆動設計を導入したアプリケーションの設計を行い、開発効率を向上させました ・15,000rpsのシステムの負荷対策や開発、保守運用を1人で行いました |
🛍️ BASE 22年6月~25年1月 |
・モジュラモノリスアーキテクチャのシステム設計/開発を行いました ・テックリードとしてドメイン駆動設計を用いた設計を行い、開発効率を向上させました |
🚀 起業 25年1月~現在 |
・フリーランスのアーキテクトとして独立 ・マイクロサービス,モジュラモノリスなどのシステムアーキテクチャの設計コンサル ・ドメイン駆動設計の導入コンサル |
🏘 モジュラモノリス - 現代システム開発の実用的アプローチ
モジュラモノリスは、「モノリシックアーキテクチャ」と「モジュール性」を組み合わせたアーキテクチャパターンです。従来のモノリシックアーキテクチャは一つの巨大なコードベースから成り立っていますが、モジュラモノリスでは、機能やドメインごとにモジュール化されており、各モジュールが独立して開発・テストが可能です。しかし、これらのモジュールは一つのアプリケーションとして一緒にデプロイされます。
近年、マイクロサービスアーキテクチャの人気が高まる中でも、多くの企業がモジュラモノリスを採用しているのは、その実用性とバランスの良さが理由です。
👉 モジュラモノリスの特徴
特徴 | 説明 |
---|---|
単一デプロイ | アプリケーション全体を一度にデプロイします。各モジュールが個別に独立していても、システム全体は一つのプロセスとして動作します。 |
モジュール性 | コードベースが機能別またはドメイン別にモジュールとして分割されており、モジュールごとに責任範囲が明確です。これにより、開発やメンテナンスが容易になります。 |
明確な境界 | 各モジュールは明確なAPIや境界を持ち、他のモジュールとの依存関係が制限されています。これが秩序あるコード構造の維持に役立ちます。 |
パフォーマンスの一貫性 | システムは一つのプロセス内で実行されるため、ネットワーク遅延や分散システムの複雑さがなく、モジュール間の通信は高速です。 |
段階的な進化 | システム全体を一度に再設計することなく、個々のモジュールを段階的に改良したり、必要に応じてマイクロサービスに分割したりすることが可能です。 |
🤔マイクロサービスとの違い
https://xtech.nikkei.com/atcl/nxt/column/18/02744/020800001/ より引用
モジュラモノリスとマイクロサービスは一見似ているように見えますが、いくつかの重要な違いがあります。
違い | 説明 |
---|---|
デプロイ | モジュラモノリスは一つのアプリケーションとしてデプロイされるのに対し、マイクロサービスは個々のサービスが独立してデプロイされます。 |
通信 | モジュラモノリスではモジュール間の通信が同一プロセス内で行われますが、マイクロサービスではサービス間の通信はネットワークを介して行われます。 |
運用負荷 | マイクロサービスは独立したサービスごとにスケーリングやモニタリングが必要なため、運用の複雑さが増します。モジュラモノリスはシンプルな運用が可能です。 |
技術選択 | マイクロサービスでは各サービスごとに異なる技術スタックを選択できますが、モジュラモノリスでは基本的に同じ技術スタックを共有します。 |
データ管理 | モジュラモノリスでは通常データベースを共有しますが、マイクロサービスでは各サービスが独自のデータストアを持つことが多いです。 |
🚀 モジュラモノリスのメリット/デメリット
👍メリット
👍 メリット | 説明 |
---|---|
開発スピード | モジュールごとに責任が分かれているため、開発の分担がしやすく、変更の影響範囲も小さくなります。 |
シンプルな運用 | マイクロサービスと比べ、運用やデプロイの負荷が少なく、シンプルな運用が可能です。 |
パフォーマンス | 同一プロセス内で動作するため、モジュール間の通信は高速で、パフォーマンスが安定しています。 |
段階的な移行 | モノリスからマイクロサービスへの移行の中間ステップとして活用でき、リスクを分散させながら進化させることができます。 |
一貫したトランザクション | 単一のデータベースを使用することが多いため、複雑なトランザクション管理が比較的容易です。 |
デバッグの容易さ | システム全体が一つのプロセスで動作するため、問題の追跡やデバッグが容易です。 |
👎 デメリット
👎 デメリット | 説明 |
---|---|
スケーリングの制約 | 一部のモジュールだけを独立してスケールすることが難しいため、全体のスケーラビリティがマイクロサービスほど高くないことがあります。 |
複雑化の可能性 | アーキテクチャやモジュール設計が適切でない場合、結局はモジュール同士が依存し合い、モノリシックのデメリットを抱える可能性があります。 |
技術スタックの制約 | 基本的に単一の技術スタックを使用するため、モジュールごとに最適な技術を選択する柔軟性がマイクロサービスよりも低いです。 |
デプロイの一括性 | 小さな変更でもシステム全体の再デプロイが必要になるため、デプロイの頻度や安全性に影響する可能性があります。 |
💻 モジュラモノリスの実装アプローチ
モジュラモノリスを効果的に実装するためには、いくつかの重要なアプローチがあります:
1. ビジネス要求やビジネスロジックを洗い出す
新たに開発する新サービスや既存のシステムをリニューアルする際に、ビジネス要求やビジネスロジック、仕様などを全て洗い出します。この段階では、ドメイン駆動設計のドメインモデリングの手法が有効です。
2. モジュールの分割(境界づけられたコンテキストへ)
洗い出したビジネス要求やビジネスロジックを独立性の高い単位(境界づけられたコンテキスト)に分割します。この分割は以下の基準で行います。
- ビジネス機能: 類似するビジネス機能や関連する業務プロセスをグループ化
- 変更の頻度: 同じタイミングで変更されることが多い機能をグループ化
- チーム構造: 開発チームの組織構造に合わせた分割も考慮
- データの凝集性: 密接に関連するデータを同じモジュールに配置
例えば、ECサイトであれば、「商品管理」「注文処理」「支払い」「顧客管理」などの境界づけられたコンテキストが考えられます。
3. モジュール間の依存関係を定義する
モジュール間の関係性を明確にし、循環依存を避けるために依存関係グラフを作成します。依存関係は一方向にし、できるだけ疎結合になるよう設計します。
4. モジュール内部のアーキテクチャ選択
各モジュールは、ビジネス要求やドメインの複雑さやビジネス的な価値(競争優位性のある機能やサービス)によって、異なるアーキテクチャパターンを採用できます。これにより、モジュールごとに最適な内部構造を実現できます。
モジュールごとに異なるアーキテクチャを採用する場合は、以下の点に留意してください。
- モジュール間のインターフェースを明確に定義し、内部実装の詳細が漏れないようにする
- 共通のドメインモデルや共有ライブラリの使用方法を標準化する
- チーム間の知識共有を促進し、異なるアーキテクチャパターンへの理解を深める
アーキテクチャ図 | 適している状況 |
---|---|
ヘキサゴナルアーキテクチャ![]() |
😵💫複雑なビジネスロジックを持つコアドメイン 🔌外部システムとの統合が多いモジュール 🛡️技術的な詳細からビジネスロジックを保護したい場合 |
レイヤードアーキテクチャ![]() |
💡比較的単純で直感的な構造が必要な場合 🔌外部システムとの統合が少ないモジュール 😁チームが伝統的なエンタープライズパターンに慣れている場合 |
MVCアーキテクチャ | ✨シンプルなCRUD操作が主体のモジュール 複雑なドメインロジックがない場合 ビジネス的な価値提供が少ないモジュール |
アーキテクチャ選択の基準
モジュールのアーキテクチャを選択する際の考慮点を挙げます。
- ビジネス価値: 競争優位性のある機能を含むモジュールには、より柔軟で拡張性の高いヘキサゴナルアーキテクチャが適しています。
- ビジネスロジックの複雑さ: 複雑なビジネスロジックを扱うモジュールなどは、レイヤードアーキテクチャやヘキサゴナルアーキテクチャが適しています。
- 変更頻度: 頻繁に変更されるモジュールには、テスト容易性と変更の局所化が優れたアーキテクチャを選びます。
- チームのスキルセット: チームが特定のアーキテクチャパターンに精通している場合、生産性を考慮してそのパターンを採用します。
- モジュールの寿命: 長期的に維持するコアモジュールには、保守性の高いアーキテクチャを選びます。
- 技術的制約: 使用するフレームワークやライブラリによって、特定のアーキテクチャが自然に適合することがあります。
🔄 移行戦略
モノリスからモジュラモノリスへ
-
境界の識別: まず、システム内の自然な境界やドメインを識別します。
- イベントストーミングやドメインモデリングを活用
- 変更の頻度が同じものをグループ化
- データの凝集度に注目
-
段階的なリファクタリング: 一度に全体を変更するのではなく、一部ずつモジュール化していきます。
- 最も独立性の高い領域から始める
- 既存コードをリファクタリングしながら境界を明確にする
- 各モジュールの責任を明確にドキュメント化する
-
依存関係の整理: 既存の依存関係を整理し、一方向の依存関係を確立します。
- 循環依存を特定し、解消する
- 共通ライブラリを適切に抽出する
- 静的解析ツールを導入して依存関係を監視する
-
内部APIの確立: モジュール間の通信のための明確なAPIを確立します。
- 各モジュールの公開インターフェースを定義
- モジュールの内部実装を隠蔽
- 必要に応じてイベント駆動パターンを導入
モジュラモノリスからマイクロサービスへ
必要に応じて、モジュラモノリスの一部をマイクロサービスとして切り出すことも可能です。
-
独立性の高いモジュールから: まずは独立性が高く、他への影響が少ないモジュールからマイクロサービス化します。
- 依存関係が少ないモジュールを特定
- 負荷パターンが特殊なモジュール(例:高いスケーリング要件を持つモジュール)
- ビジネス的に頻繁に変更が発生するモジュール
-
段階的な移行: 一度にすべてを変更するのではなく、徐々に移行します。
- ストラングラーパターンを使用して徐々に機能を移行
- モノリスとマイクロサービスが共存する期間を設ける
- 新機能はマイクロサービスとして実装するアプローチも検討
-
データの分離: 共有データベースからサービス固有のデータストアへの移行を慎重に計画します。
- データの重複と整合性の課題に対処
- 必要に応じてCQRSパターンを検討
- イベントソーシングを導入してデータ同期の課題を解決
👥 チーム構成とモジュラモノリス
モジュラモノリスは、チーム構成とも密接に関連しています。一般的には以下のようなチーム構成が効果的です。
チーム | 役割 |
---|---|
📁モジュールごとのチーム | 各モジュールに専任チームを割り当てて、チームはそのモジュールの設計、開発、テストに責任を持ちます。 |
⚙️SRE/インフラチーム | システムのインフラ部分を担当します。CI/CDパイプラインの構築・維持やマイクロサービス化する際のインフラ構築なども行います。 |
🗺️アーキテクチャチーム | モジュール間の境界を監視したり、技術的負債を管理したり、アーキテクチャの決定をガイドしたりとモジュラモノリス全体が上手く機能するようになんでもやるチームです。 |
🎯 まとめ
モジュラモノリスは、モジュールごとに責任を分離しつつ、全体としてシンプルなデプロイや運用を保つアーキテクチャです。特に以下のような場合に適した選択肢となります。
- マイクロサービスの複雑な運用を避けたい場合
- 開発チームのサイズが中小規模の場合
- ビジネスドメインがまだ流動的で頻繁に変更される可能性がある場合
- 将来的にマイクロサービスへの移行を検討しているが、一度に移行するリスクを避けたい場合
最適なアーキテクチャは常にプロジェクトの特性、チームの経験、ビジネス要件によって異なります。モジュラモノリスはその中間的な位置づけとして、多くの状況でバランスの取れた選択肢となるでしょう。
Discussion