14
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

モノリスは「退化」ではない ― 小さく始めるアーキテクチャ4選

14
Posted at

はじめに

新しいプロジェクトのアーキテクチャを決めるとき、最初に「マイクロサービスにしよう」と思ったことはありませんか?

技術ブログやカンファレンスではマイクロサービスの成功事例が目立ちます。
Netflixがやっている、Amazonがやっている。じゃあうちもやろう。
モノリスなんてレガシーでしょ ―― そう思うのは自然なことです。

でも、実際の現場で「とりあえずマイクロサービス」で始めたプロジェクトが、サービス間通信のデバッグだけで開発が止まった、という話を聞いたことはないでしょうか。
5人のチームなのに、分散システムのインフラ維持だけで手一杯になってしまうケースもあります。

問題は「マイクロサービスが悪い」ことではありません。プロジェクトの状況に合ったスタイルを選べていないことが問題です。

この記事では、モノリス系の4つのアーキテクチャスタイルを紹介します。
それぞれの構造・強み・弱みを比較し、「どんな場面で選ぶべきか」を、自分が学んだ内容をもとに整理していきます。

分散アーキテクチャ(マイクロサービスやイベント駆動など)との比較は、この記事では扱いません。

TL;DR

  • モノリス系アーキテクチャは「古い」のではなく、シンプルさ・低コスト・立ち上げ速度に特化したスタイル
  • レイヤード、モジュラーモノリス、パイプライン、マイクロカーネルの4つは、それぞれ異なる問題に適合する
  • 共通の弱点はスケーラビリティ・弾力性・耐障害性。独立デプロイできる最小単位が1つしかないことが根本原因
  • 「コードをどう分けるか」(技術分割かドメイン分割か)は、将来の変更しやすさを左右する重要な選択
  • チーム規模が小さい、予算が限られている、ドメインがまだ固まっていない ―― こうした状況ではモノリスから始めるのが合理的

Section 1: そもそもモノリスとは何か

4つのスタイルを比較する前に、「モノリス」という言葉の意味を正確にしておきましょう。

1.1 「モノリス」の定義

モノリスとは、アプリケーション全体が1つのデプロイ単位としてまとめられているアーキテクチャのことです。

┌─────────────────────────────────────────┐
│           モノリス(1つのデプロイ単位)      │
│                                         │
│  ┌──────────┐ ┌──────────┐ ┌─────────┐  │
│  │    UI    │ │ ビジネス  │ │ データ   │  │
│  │          │ │ ロジック  │ │ アクセス  │  │
│  └──────────┘ └──────────┘ └─────────┘  │
│                                         │
│        → まとめてビルド・デプロイ           │
└─────────────────────────────────────────┘

対義語は「分散アーキテクチャ」。こちらはアプリケーションが複数のデプロイ単位に分かれています。マイクロサービスが代表例です。

モノリスであること自体は良くも悪くもありません。大事なのは、プロジェクトの制約に合っているかどうかです。

1.2 モノリス系スタイルに共通する強みと弱み

モノリス系の4スタイルには、共通した傾向があります。

強み

  • シンプルさ: 分散システム特有の問題(ネットワーク遅延、サービス間の整合性など)を考えなくてよい
  • 低コスト: インフラ構成がシンプルなので、構築・運用コストが抑えられる
  • 理解しやすさ: 1つのコードベースで全体を把握できる
  • 立ち上げの速さ: 複雑な基盤構築なしに開発を始められる

弱み

  • スケーラビリティ・弾力性(負荷に応じて処理能力を伸縮させる能力)・耐障害性: 一部の機能だけを独立してデプロイ・スケールすることが難しい
  • デプロイ容易性: 3行の変更でも全体をデプロイし直す必要があり、デプロイ頻度に制約がある

これらの弱みがなぜ生じるのかについては、Section 6で根本原因を分析します。

1.3 これから紹介する4つのスタイル

この記事で取り上げるのは、以下の4つのモノリス系アーキテクチャスタイルです。

スタイル ひとことで言うと
レイヤード 「何も決まっていないが今すぐ書き始めたい」ときの最もシンプルな出発点
モジュラーモノリス 「業務の変更に強くしたい」「将来の分散化に備えたい」ときの選択肢
パイプライン 「データを決まった順序で段階的に加工する」処理に特化したスタイル
マイクロカーネル 「基本動作は共通だが、ユーザーごとにカスタマイズが必要」なときの設計

それぞれの詳細をこれから見ていきましょう。

Section 2: レイヤードアーキテクチャ ― 「役割で分ける」最もシンプルなスタイル

おそらく多くの方が無意識に使っているスタイルです。
「何も考えずにコードを書き始めた」とき、自然とこの形になることが多いです。
だからこそ、意識的にその構造と限界を知ることに価値があります。

2.1 トポロジー: 4つの層が積み重なる

レイヤードアーキテクチャは、コードを技術的な役割ごとに水平の層(レイヤー)として分離する設計です。典型的には以下の4層で構成されます。

┌─────────────────────────────────┐
│       Presentation 層           │  画面表示・ユーザー操作の受付
├─────────────────────────────────┤
│         Business 層             │  ビジネスルールの実行
├─────────────────────────────────┤
│       Persistence 層            │  データの読み書き(SQLなど)
├─────────────────────────────────┤
│        Database 層              │  データベース
└─────────────────────────────────┘

このように、技術的な関心事ごとにコードを分ける方式を技術分割と呼びます。「画面を表示する部分」「ビジネスロジックを処理する部分」「データを保存する部分」のように、技術的な役割が分離の基準になっています。

物理的なデプロイの仕方にはバリエーションがあります。

パターン1(最も一般的)         パターン2                  パターン3
┌──────────────────┐    ┌──────────┐            ┌──────────────────┐
│ Presentation     │    │Presentat.│            │ Presentation     │
│ Business         │    └──────────┘            │ Business         │
│ Persistence      │    ┌──────────┐            │ Persistence      │
└──────────────────┘    │ Business │            │ Database         │
┌──────────────────┐    │ Persiste.│            │  (組み込みDB)     │
│ Database(別サーバ)│    └──────────┘            └──────────────────┘
└──────────────────┘    ┌──────────┐
                        │ Database │
                        └──────────┘
  • パターン1: 3層を1つにまとめ、DBだけ分離。Webアプリでよくある構成です
  • パターン2: Presentationを分離し、Business/Persistenceを統合。フロントエンドとバックエンドを分けるケース
  • パターン3: DBも含めて全部を1つにまとめる。モバイルアプリや組み込みDB(SQLiteなど)のケース

2.2 レイヤーの分離(Layers of Isolation)

レイヤードアーキテクチャには重要なルールがあります。各層は基本的に 閉じている(closed) ということです。

リクエストの流れ(全層がclosed)

     Presentation
         │ ← 層を飛ばせない
         ▼
      Business
         │ ← 必ず順番に通過
         ▼
     Persistence
         │
         ▼
      Database

「閉じている」とは、リクエストが層を飛ばせないことを意味します。Presentation層がDatabase層に直接アクセスしたほうが速いケースもありますが、それを許すとどうなるでしょうか? Persistence層を変更したとき、Business層だけでなくPresentation層にも影響が波及してしまいます。層同士が密結合になり、変更が困難なシステムになるのです。

各層を閉じておくことで、ある層の変更が他の層に影響しない状態を保てます。これが「レイヤーの分離」という概念です。たとえば、UIフレームワークを新しいものに差し替えたいとき、Presentation層の中だけで完結できます。

ただし、例外的に「開く(open)」層を設けることもあります。たとえば、日付操作やログ出力などの共通ユーティリティを集めたServices層を追加し、この層を「開いて」Business層がバイパスできるようにする、といったケースです。どの層が開いていてどの層が閉じているかをドキュメントに明記しておかないと、意図しない依存関係が生まれます。

2.3 弱点: Architecture Sinkholeアンチパターン

レイヤードアーキテクチャには有名な弱点があります。Architecture Sinkhole(アーキテクチャの落とし穴) と呼ばれるアンチパターンです。

たとえば、ユーザーの名前と住所を単純に表示するだけのリクエストを考えてみてください。Presentation層がリクエストを受け取り、Business層に渡す。でもBusiness層では何もせず、そのままPersistence層に渡す。Persistence層がDBからデータを取得して、結果がそのまま上に戻っていく。どの層でも処理が「素通り」しているだけです。

この素通りが問題なのは、各層を通過するたびにオブジェクトの生成・変換が発生し、メモリと処理時間を無駄に消費するからです。

目安として、80-20ルールが参考になります。リクエストの20%が素通りする程度なら許容範囲。でも80%が素通りしているなら、レイヤードアーキテクチャがそもそもそのアプリに合っていない可能性が高いです。

2.4 レイヤードが向いている場面

  • 小規模でシンプルなアプリケーションやWebサイト
  • 予算と納期が厳しい場面: 最も低コストなスタイルの1つ
  • まだ最適なアーキテクチャが決まっていないが、開発を始めなければならない場面: 出発点として使い、後から別のスタイルに移行する想定

アプリが大きくなるにつれて、保守性・テスト容易性・デプロイ容易性は急速に低下します。レイヤードアーキテクチャは「小さく保つ」ことが前提のスタイルです。

Section 3: モジュラーモノリス ― 「業務で分ける」もう一つのモノリス

レイヤードアーキテクチャの技術分割には、ある種の不便さがあります。たとえば「顧客管理」に関する機能を変更したいとき、Presentation層・Business層・Persistence層のすべてを横断して修正が必要になります。1つの業務変更なのに、コードベース全体に手を入れなければならないわけです。

「業務の単位でコードをまとめたらどうか?」 ―― この発想がモジュラーモノリスの出発点です。

3.1 トポロジー: ドメインごとにモジュールを分ける

モジュラーモノリスは、デプロイ単位は1つのまま、内部をドメイン(業務領域)ごとのモジュールに分割するスタイルです。

┌─────────────────────────────────────────────────────┐
│              1つのデプロイ単位                         │
│                                                     │
│  ┌──────────┐  ┌───────────┐  ┌──────────────────┐  │
│  │  注文管理  │  │  在庫管理  │  │   決済処理        │  │
│  │          │  │           │  │                  │  │
│  │ UI       │  │ UI        │  │ UI               │  │
│  │ ロジック  │  │ ロジック    │  │ ロジック          │  │
│  │ データ    │  │ データ     │  │ データ            │  │
│  └──────────┘  └───────────┘  └──────────────────┘  │
│                                                     │
└─────────────────────────────────────────────────────┘

レイヤードとの違いは、コードの整理方法(名前空間)にはっきり表れます。

方式 名前空間の例 分離の基準
技術分割(レイヤード) com.app.presentation.customer.profile 技術的な役割が先
ドメイン分割(モジュラーモノリス) com.app.customer.profile 業務ドメインが先

このように業務ドメインごとにコードをまとめる方式をドメイン分割と呼びます。業務ドメインを中心に設計する考え方(ドメイン駆動設計: DDD)の普及に伴い、近年注目度が急上昇したスタイルです。

3.2 2つの構造オプション

モジュラーモノリスの内部構造には2つの選択肢があります。

ここでの「モノリシック」「モジュラー」は、モジュラーモノリスの内部のコード管理方式の話です。アーキテクチャ全体のデプロイ単位(Section 1.1で説明した意味のモノリス)とは別の観点なので、区別して読んでください。

モノリシック構造

全モジュールが1つのコードベースに格納されます。シンプルで開発しやすい反面、開発者がモジュールの境界を越えてコードを再利用しすぎると、モジュール間の境界が曖昧になる危険があります。厳密なガバナンス(コードレビューやアーキテクチャテスト)が欠かせません。

モジュラー構造

各モジュールが独立したアーティファクト(Javaなら JAR ファイル、.NETなら DLL ファイルなど)として開発され、デプロイ時に1つに結合されます。モジュールの境界が物理的に明確になる一方、モジュール間の通信が複雑になります。

どちらを選ぶかは、モジュール間の依存度によります。モジュール同士がほぼ独立しているならモジュラー構造が向いていますし、モジュール間の通信が多いならモノリシック構造のほうが効率的です。

3.3 モジュール間通信

ここでの「通信」はすべてプロセス内の関数・メソッド呼び出しです。分散アーキテクチャのようなネットワーク越しのHTTPやメッセージキューではなく、同一プロセス内で完結する点がモノリスたる所以です。

モジュール間の通信は「ゼロが理想」ですが、現実には必要なケースがあります。たとえば、注文管理モジュールは在庫管理モジュールと連携して在庫数を調整する必要があります。通信方式には2つの選択肢があります。

ピアツーピア方式

モジュール同士が直接メソッドを呼び出します。手軽ですが、通信が増えすぎるとモジュール間が密結合になり、どこからどこへでも依存がある無秩序な状態に陥る危険があります。

メディエータ方式

仲介役のコンポーネント(メディエータ)がリクエストを受け取り、適切なモジュールに振り分けます。モジュール同士は直接知り合わないので疎結合を保てますが、代わりにメディエータへの依存が生まれます。

いずれの方式でも、モジュール間通信は最小限に保つのが原則です。通信が多すぎるなら、ドメインの境界の引き方を見直すべきサインかもしれません。

3.4 モジュラーモノリスが向いている場面

  • 予算・時間に制約があるが、ドメイン指向のチーム構成で開発したい場面: チームを業務ドメインごとに分けて、各チームが自分のモジュールに集中できる
  • 将来的に分散アーキテクチャへの移行を見据えている場面: モジュール境界がそのままサービス境界の候補になる
  • 変更の大半がドメイン起点の場合: 「ウィッシュリストに有効期限を追加したい」のような業務要件の変更が、1つのモジュール内で完結しやすい

逆に、UIフレームワークの差し替えやDB技術の変更のような技術的な横断変更が頻繁な場合は、全モジュールに影響が及ぶため、レイヤードアーキテクチャのほうが向いています。

Section 4: パイプラインアーキテクチャ ― 一方向にデータを流す

Unixのシェルで cat access.log | grep "ERROR" | sort | uniq -c のようにコマンドを |(パイプ)でつないだ経験はないでしょうか。「前の出力を次の入力にする」仕組みを、アプリケーション全体の設計に適用したのがパイプラインアーキテクチャです。データ変換やETL処理など、「決まった手順でデータを加工していく」タイプの問題に強いスタイルです。

4.1 トポロジー: フィルターとパイプ

パイプラインアーキテクチャは、フィルターパイプという2種類のコンポーネントだけで構成されます。

  • フィルター: 1つの処理を行う自己完結的なコンポーネント。基本的にステートレス(状態を持たない)
  • パイプ: フィルター間をつなぐ一方向の通信チャネル
┌──────────┐    ┌───────────┐    ┌──────────┐    ┌──────────┐
│ Producer │ ──→│Transformer│ ──→│  Tester  │ ──→│ Consumer │
│          │pipe│           │pipe│          │pipe│          │
│ データ取得 │    │ データ変換 │    │ 条件判定   │    │ 結果出力  │
└──────────┘    └───────────┘    └──────────┘    └──────────┘

フィルターには4つの種類があります。

フィルター種別 役割 関数型プログラミングで言うと
Producer パイプラインの開始点。データソースからデータを取り出す -
Transformer データを変換・加工する map
Tester 条件に基づいてデータを通すか判定する filter
Consumer パイプラインの終点。DBへの保存や画面表示など -

具体例として、サービスのテレメトリデータ(通信時間や稼働率などの運用データ)を処理するパイプラインを考えてみましょう。

  ┌───────────┐     ┌──────────┐     ┌─────────────┐     ┌──────────┐
  │ データ受信  │ ──→ │ 時間帯で  │ ──→ │ トレンド     │ ──→ │ グラフ    │
  │ (Producer)│     │ 絞り込み  │     │ 分析         │     │ 出力     │
  │           │     │ (Tester) │     │(Transformer)│     │(Consumer)│
  └───────────┘     └──────────┘     └─────────────┘     └──────────┘

データ受信フィルターが取得したデータを、時間帯で絞り込み、トレンドを分析し、最終的にグラフとして出力する。各フィルターは自分の仕事だけに集中しており、前後のフィルターの内部実装を知る必要がありません。

4.2 リスクと制約

パイプラインアーキテクチャにはいくつか注意すべき点があります。

  • フィルターの責務肥大: 1つのフィルターに複数の処理を詰め込むと、パイプラインの利点であるモジュラリティが損なわれます。「1フィルター1責務」が原則です
  • 一方向のみ: パイプは一方向の通信だけをサポートします。フィルター間で双方向のやり取りが必要な場合、このスタイルは適していません
  • エラーハンドリングの難しさ: パイプラインの途中でエラーが起きたとき、どこまで処理を巻き戻すのか、どうやってリカバリするのかを事前に設計しておく必要があります

4.3 パイプラインが向いている場面

  • ETL処理(Extract-Transform-Load): データベース間のデータ移行・変換
  • ストリーム処理: リアルタイムデータの段階的な加工
  • 決まった順序のワークフロー: 入力 → 加工 → 検証 → 出力のように手順が明確な処理

条件分岐が多い処理や、前後のフィルター間でやり取りが必要な非決定的ワークフローには向いていません。そうしたケースではイベント駆動アーキテクチャのほうが適切です。

Section 5: マイクロカーネルアーキテクチャ ― コア + プラグインで拡張する

「基本の動作はシンプルだが、ユーザーやクライアントごとにカスタマイズが必要」 ―― そんな問題に直面したことはないでしょうか。Eclipse IDEを使ったことがあれば、プラグインを追加するとエディタがJava開発環境に変身するあの仕組みをイメージしてみてください。あれがまさにマイクロカーネルアーキテクチャの実例です。

5.1 トポロジー: コアシステムとプラグインコンポーネント

マイクロカーネルアーキテクチャは、コアシステムプラグインコンポーネントの2つで構成されます。

                  ┌────────────────────────────┐
                  │       コアシステム           │
                  │   (最小限の基本機能)          │
                  │                            │
┌──────────┐      │   ┌────────┐               │      ┌──────────┐
│プラグインA │ ←──→ │   │レジストリ│               │ ←──→ │プラグインC │
└──────────┘      │   └────────┘               │      └──────────┘
                  │                            │
┌──────────┐      │                            │      ┌──────────┐
│プラグインB │ ←──→ │                            │ ←──→ │プラグインD │
└──────────┘      └────────────────────────────┘      └──────────┘

コアシステム

アプリケーションの最小限の機能を担います。
たとえば Eclipse IDE のコアシステムは「ファイルを開いて、テキストを編集して、保存する」という基本的なテキストエディタです。
プラグインを追加して初めて、本格的な開発環境になります。

もう1つの考え方として、コアシステムをハッピーパス(カスタマイズや例外処理を含まない、標準的な処理フロー)として捉えることもできます。
条件分岐やカスタムロジックをコアから切り離してプラグインに置くことで、コアをシンプルに保ちます。

このように、マイクロカーネルは技術的な機能追加(IDEプラグイン)にも、ドメイン固有のルール追加(地域ごとの税率計算など)にも適用できる柔軟なスタイルです。

プラグインコンポーネント

カスタム処理や追加機能を担う独立したコンポーネントです。
理想的にはプラグイン同士に依存関係がなく、それぞれが自己完結しています。

コアシステム自体の内部構造には自由度があり、レイヤードアーキテクチャやモジュラーモノリスで実装できます。

5.2 プラグインの実装方式

プラグインとコアシステムの通信方式には、大きく2つの選択肢があります。

ポイントツーポイント方式

プラグインを共有ライブラリ(JAR / DLL など)やパッケージとして実装し、メソッド呼び出しで直接通信します。

  • コンパイル時プラグイン: プラグインの追加・変更時にアプリ全体の再デプロイが必要。管理はシンプル
  • ランタイムプラグイン: モジュールシステムのフレームワークを使い、実行時にプラグインを着脱できる。再デプロイ不要

リモートアクセス方式

RESTやメッセージングでプラグインをサービスとして呼び出します。スケーラビリティや非同期通信が可能になりますが、分散システムの複雑さ(ネットワーク遅延、サービスの死活監視など)を抱えることになります。

リモートアクセス方式でも、すべてのリクエストはコアシステムを経由します。ただし、プラグイン自体は独立してデプロイ可能なため、純粋なモノリスというよりハイブリッドな性質を持ちます。アーキテクチャの分類上はモノリス系として扱われますが、分散システムの複雑さも一部引き受ける点に注意が必要です。

5.3 レジストリとコントラクト

コアシステムが適切なプラグインを呼び出すには、2つの仕組みが必要です。

レジストリ

どのプラグインが利用可能で、どうやってアクセスするかを管理する仕組みです。シンプルな実装ではコア内部のマップ(キーとプラグイン参照のペア)で済みますし、大規模な場合はサービスディスカバリツールを使うこともあります。

コントラクト

プラグインとコア間の入出力データの取り決めです。たとえば税率計算プラグインであれば、「入力: 商品カテゴリと金額、出力: 税額」というデータ形式の取り決めがコントラクトにあたります。地域ごとの税率計算プラグインは、すべてこの同じコントラクトに従います。サードパーティ製のプラグインでコントラクトが異なる場合は、アダプターパターン(外部のインターフェースを自分たちの標準インターフェースに変換する設計パターン)で吸収します。

5.4 マイクロカーネルが向いている場面

  • プロダクト型アプリケーション: IDE、Webブラウザ、税務ソフトなど、ユーザーが機能を選んで使うタイプのソフトウェア
  • 地域・クライアントごとにルールが異なるビジネスアプリ: 保険金処理で州ごとにルールが違う、国際物流で国ごとに規制が違う、といったケース
  • カスタマイズと拡張性が重要な場面

コアシステムが頻繁に変わる場合は、このスタイルの哲学に反します。マイクロカーネルの前提は「コアが安定していること」です。コアが不安定だと、プラグインとの整合性を保つコストが跳ね上がります。

Section 6: 4つのスタイルの比較と分析

個々のスタイルを知っただけでは、「どれを選ぶか」は決められません。ここで4スタイルを横に並べて特性の強弱を比較し、その後、モノリスに共通する弱点の根本原因と、コード分割の方針についても整理します。

6.1 特性比較表

以下の表は、各スタイルの星評価を定性的にまとめたものです。

特性 レイヤード モジュラーモノリス パイプライン マイクロカーネル
コスト 低い 低い 低い 低い
シンプルさ 高い 高い 高い 高い
モジュラリティ 低い 高い 高い 中程度
テスト容易性 低い やや低い 中程度 中程度
デプロイ容易性 低い やや低い 中程度 中程度
スケーラビリティ 低い 低い 低い 低い
弾力性 低い 低い 低い 低い
耐障害性 低い 低い 低い 低い
進化容易性 低い 中程度 中程度 中程度
応答性 中程度 中程度 中程度 中程度

この表でまず目を引くのは、4スタイル全てが「コストが低い」「シンプルさが高い」という点で共通していること。そして、スケーラビリティ・弾力性・耐障害性が全て低い点も共通しています。差が出るのは、モジュラリティ・テスト容易性・デプロイ容易性・進化容易性のあたりです。

6.2 共通の弱点とその根本原因

4スタイル全てで低い評価になっている「スケーラビリティ」「弾力性」「耐障害性」。なぜでしょうか?

Section 1で触れた弱みの根本原因を、アーキテクチャ量子(Architecture Quantum) という概念で説明します。アーキテクチャ量子とは、独立してデプロイ可能で、高い機能的結合度を持つ最小のアーキテクチャ単位のことです。

モノリス系のスタイルでは、UI・バックエンド・データベースがすべて1つのデプロイ単位に含まれるため、アーキテクチャ量子は常に 1 です。

 アーキテクチャ量子 = 1(モノリス)

 ┌─────────────────────────────────────┐
 │  UI + バックエンド + DB               │  ← 全部まとめて
 │                                     │    デプロイ/スケール
 │  一部だけスケールアウト → できない       │
 │  一部だけフェイルオーバー → できない     │
 └─────────────────────────────────────┘

量子が1つしかないということは、注文処理だけ負荷が高いからそこだけスケールアウトする、といったことができません。決済処理で障害が起きても、アプリケーション全体が巻き込まれます。これがモノリス系スタイルに共通する弱点の根本原因です。

比較表で「スケーラビリティ」と「弾力性」が別項目になっている点が気になったかもしれません。スケーラビリティは「最大どこまで処理能力を伸ばせるか」、弾力性は「負荷に応じて伸び縮みできるか」を指します。似た概念ですが、観点が異なります。

6.3 技術分割 vs ドメイン分割

Section 2で触れた技術分割と、Section 3で触れたドメイン分割を、ここで改めて横並びで比較します。4つのスタイルがそれぞれどちらの分割に属するのか、そして変更の方向に応じてどちらを選ぶべきかを整理します。

技術分割(レイヤード、パイプラインが該当)

  • 技術的な関心事ごとにコードを分ける。レイヤードではUI / ビジネスロジック / データアクセスという役割で分離し、パイプラインではデータ処理の役割(取得・変換・検証・出力)で分離する。いずれも業務ドメインではなく処理の技術的な性質が分離の基準
  • メリット: 技術スペシャリストが自分の担当領域に集中しやすい。層単位の差し替えがやりやすい
  • デメリット: 1つの業務変更(例: 「顧客にポイント機能を追加」)が全層に波及する

ドメイン分割(モジュラーモノリスが該当)

  • 業務ドメインごとにコードをまとめる
  • メリット: 業務起点の変更が1モジュール内で完結しやすい。チーム分割と自然に対応する
  • デメリット: 技術的な横断変更(DBの差し替えなど)が全モジュールに影響する

マイクロカーネルは両方の性質を持ちうる点がユニークです。Eclipse IDEのプラグインは技術的な機能(デバッガ、バージョン管理連携など)を追加するので技術分割的です。一方、保険金処理で地域ごとのルールをプラグインにするのはドメイン分割的です。

どちらが優れているかではなく、変更が起きる方向に合わせて選ぶのがポイントです。業務要件の変更が頻繁ならドメイン分割、技術基盤の変更が頻繁なら技術分割が有利になります。

Section 7: モノリスを選ぶべきとき

比較表を眺めるだけでは、実際のプロジェクトでは決断できません。ここでは「モノリス系を選ぶかどうか」を判断するための具体的な問いを整理します。

7.1 モノリスを選ぶべき5つのシグナル

1. チーム規模が小さい(5-10人以下)

分散システムの運用には、サービス間通信の監視、分散トレーシング、デプロイパイプラインの構築など、多くの追加作業が伴います。少人数のチームでは、これらの運用オーバーヘッドを担うリソースが足りません。

2. 予算・時間に強い制約がある

投資家からの資金で動いていて、とにかく早くプロダクトを出す必要がある。そんなとき、最も低コストなスタイルで素早く立ち上げるのが合理的です。

3. ドメインがまだ固まっていない

ビジネスの境界が曖昧な段階でサービスを分割すると、間違った境界で切ってしまうリスクが高くなります。モノリスでドメインを探索してから分割するほうが安全です。

4. 高いスケーラビリティ・弾力性が不要

数千〜数万の同時接続を捌く必要がなければ、モノリスで十分に対応できます。

5. まず動くものを見せたい

MVP(Minimum Viable Product: 実用最小限の製品)やプロトタイプには、モノリスの立ち上げ速度が大きな武器になります。

7.2 モノリスから始めるときの注意点

モノリスを選ぶのは正しい判断だとしても、将来を見据えた工夫は必要です。

「将来は分散化するかもしれない」と思うなら、モジュラーモノリスを選ぶのがおすすめです。ドメインごとにモジュール境界を定義しておけば、その境界がサービス分割の出発点になります。

レイヤードで始める場合は、コードの再利用を最小限に、継承階層を浅く保つことを意識してください。過度な再利用や深い継承は、後からスタイルを移行するときの障壁になります。

そして、モノリスが「大きくなりすぎた」サインを見逃さないことが大切です。

  • 変更に時間がかかりすぎる
  • 1箇所の変更が他の部分を壊す
  • チームメンバーが互いの変更を邪魔し合う
  • 起動時間が長くなりすぎる

これらの兆候が出始めたら、アーキテクチャの見直しを検討するタイミングです。

おわりに

この記事では、モノリス系4スタイル(レイヤード、モジュラーモノリス、パイプライン、マイクロカーネル)の構造と特性を比較し、「どんなときにモノリスを選ぶか」を整理しました。

まずは自分のプロジェクトの制約(チーム規模、予算、ドメインの成熟度)を棚卸しして、どのスタイルが合いそうか考えてみてください。Section 7の5つのシグナルが、その判断の出発点になるはずです。

この比較軸を持っておくと、分散スタイルと比較するときにも判断がしやすくなります。

14
9
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?