Skip to main content

第01章:はじめに:モジュラーモノリスって何?🏠✨

今日のゴール🎯

  • 「モジュラーモノリス」を一言で説明できるようになる😊
  • 「モノリス / モジュラーモノリス / マイクロサービス」の違いをパッと比較できるようになる👀
  • 「変更が怖い😵」の正体(なぜ怖い?)を言語化できるようになる🗣️✨

1) モジュラーモノリスの一言定義🧩

モジュラーモノリスの定義

**“デプロイは1つのアプリのまま”**なんだけど、中身はモジュール(小さなまとまり)にきれいに区切って、 モジュール同士は 決められた窓口(公開API)だけで会話するようにした設計だよ🏠🪟✨ (「同じアプリ内で、ちゃんと“境界”を作る」のがポイント!)

似た言い方だと、

  • 1つのアプリとして動く ✅
  • でも内部は「小さなアプリが集まってる」みたいに区切る ✅
  • 境界を越えるときはルールがある ✅ …って感じだね😊 (milanjovanovic.tech)

2) 3兄弟を整理しよ:モノリス / モジュラーモノリス / マイクロサービス🧠✨

まず「モノリス」って悪口じゃないよ😇

モノリスは「コアの動きが1つのプロセスで完結していて、だいたい1つの単位でデプロイする」形のことだよ📦 ちゃんと設計されてれば、モノリスでも十分強い💪✨ (Microsoft Learn)

「マイクロサービス」は?

マイクロサービスは「小さく独立したサービスの集合」で、各サービスが**1つの業務能力(境界)**を持って、別々に動いたりデプロイできる考え方だよ🚚📦📦 (Microsoft Learn)


ざっくり比較表📋✨

| マイクロサービス | 複数 | ネットワーク越し | チーム分割・独立スケールに強い | 分散システムのコスト増💸 |

「え、最初からマイクロサービスでよくない?」って思うかもだけど、最初はモノリス(ちゃんとしたモノリス)からが良いケースが多い、って意見も有名だよ📌 (martinfowler.com)


3) よくある悩み:変更が怖い😵 の正体

「変更が怖い」って、だいたいこれ👇

  • どこが影響範囲かわからない🕵️‍♀️
  • “ついで修正”が連鎖して止まらない🧶
  • ある機能を直したら別の機能が壊れる💥
  • 「誰が何を責任持つの?」が曖昧で、コードが混ざる🍲
  • リリースが儀式化して、みんなビビる😱

モジュラーモノリスが狙うのはここ! **「影響範囲を小さく」「会話ルートを限定」「責任の境界をはっきり」**させて、変更を怖くなくするんだよ😎✨


4) まずダメ例😇 → 良い例😎(“境界が溶ける”ってこういうこと)

ダメ例😇:全部まぜまぜサービス🍲💥

  • 1つのクラスが、注文も、在庫も、支払いも、メールも…全部やる
  • しかも他の機能も直接触り放題 → どこを直してもどこかが壊れる “怖いアプリ” になりがち😵

イメージ(超ざっくり)

public class OrderService
{
public void PlaceOrder(int productId, int userId)
{
// 注文ロジック
// 在庫も直接いじる
// 支払いも直接呼ぶ
// メール送信もここ
// DBもここで直接SQL...
}
}

良い例😎:モジュールごとに“部屋”を作って、窓口で会話🪟✨

  • 「注文は注文の部屋(Ordering)」
  • 「商品は商品(Catalog)」
  • Ordering が Catalog の中身を勝手に触るのは禁止🙅‍♀️
  • 触りたいなら Catalogの“窓口”(公開API)だけ通す

これだけで、影響範囲が読みやすくなるよ👀✨ (※次章以降で、この“禁止”をコードで強制する方法までやるよ🧩)


5) 手を動かす(C#)⌨️✨:超ミニ「2モジュールっぽい形」を作る

ここでは“雰囲気”をつかむ用に、CatalogOrderingの2つを用意するね🛒🧾 (まだ厳密な強制はしないよ。強制は後の章でやる!👌)

フォルダ(または名前空間)イメージ📁

App/
Modules/
Catalog/
CatalogApi.cs
Internal/
ProductStore.cs
Ordering/
OrderingApi.cs
Internal/
OrderStore.cs

Catalog(商品側)🛒✨

namespace App.Modules.Catalog;

// ✅ 他モジュールが触っていい“窓口”
public sealed class CatalogApi
{
private readonly Internal.ProductStore _store = new();

public bool IsSellable(int productId)
=> _store.Exists(productId) && !_store.IsDiscontinued(productId);
}

namespace App.Modules.Catalog.Internal;

// ❌ 外から触られたくない中身(“部屋の奥”)
internal sealed class ProductStore
{
private readonly HashSet<int> _products = new() { 1, 2, 3 };
private readonly HashSet<int> _discontinued = new() { 3 };

public bool Exists(int productId) => _products.Contains(productId);
public bool IsDiscontinued(int productId) => _discontinued.Contains(productId);
}

Ordering(注文側)🧾✨

namespace App.Modules.Ordering;

using App.Modules.Catalog;

public sealed class OrderingApi
{
private readonly CatalogApi _catalog;
private readonly Internal.OrderStore _orders = new();

public OrderingApi(CatalogApi catalog)
=> _catalog = catalog;

public string PlaceOrder(int productId, int userId)
{
// ✅ Catalogの“窓口”だけ使う
if (!_catalog.IsSellable(productId))
return "ごめんね🙏 その商品は今は買えないみたい…";

var orderId = _orders.Create(productId, userId);
return $"注文OK🎉 OrderId={orderId}";
}
}

namespace App.Modules.Ordering.Internal;

internal sealed class OrderStore
{
private int _nextId = 1000;

public int Create(int productId, int userId)
{
// 本当はDBに保存…だけど今は雰囲気だけ😊
return _nextId++;
}
}

実行してみる(雰囲気テスト)🏃‍♀️💨

using App.Modules.Catalog;
using App.Modules.Ordering;

var catalog = new CatalogApi();
var ordering = new OrderingApi(catalog);

Console.WriteLine(ordering.PlaceOrder(productId: 1, userId: 10)); // 注文OK🎉
Console.WriteLine(ordering.PlaceOrder(productId: 3, userId: 10)); // 買えない🙏(終売)

✅ ここで大事なのは、OrderingがCatalogのInternalに手を出さず、CatalogApiだけ見てること! この「窓口だけね🪟」が、モジュラーモノリスの基本ムーブだよ😊✨ (milanjovanovic.tech)


6) ミニ演習📝✨

演習1:境界を言葉で👄

次のうち「境界が溶けてる」兆候はどれ?(複数OK)

  • A) 注文モジュールが商品モジュールのDBテーブルを直接UPDATEする
  • B) 注文モジュールが商品モジュールの公開APIで在庫可否だけ聞く
  • C) どの機能も Utils にどんどん入っていく

👉 答え:A と C が危険寄り😵💥(Bは方向性OK)

演習2:コードで“窓口”を増やす🪟

CatalogApi に GetProductName(int productId) を追加して、 Ordering側のメッセージに商品名を入れてみてね😊 (Internalを直接触らない縛りで!)


7) AI活用プロンプト例🤖✨(コピペOK)

  • 「この機能分割(Catalog/Ordering/Identity)は境界として自然?理由も添えて候補を3案出して」
  • 「このコード、どこが“境界越え”になってる?直し方を“公開API経由”に寄せて提案して」
  • 「“モジュラーモノリスの公開API”として、最小のメソッド設計案を出して。引数・戻り値も」
  • 「いまの設計のままだと将来マイクロサービス化するとき何が辛い?先に直せる点は?」(※“将来の可能性”として聞くのがコツ😊)

まとめ(覚える1行)📌✨

モジュラーモノリス = デプロイは1つのまま、内部は“境界つきの部屋”に分けて、窓口だけで会話する🏠🪟🧩

次章は「“フォルダ分けじゃないよ📦🙅‍♀️”」を、もっと具体例で刺していくよ〜😊✨

おまけ:C#の最新は **C# 14(.NET 10対応)**だよ🆕✨ (Microsoft Learn)