Hanatare's PaPa

Make life a little richer.

Virtual Space of Hanatare's PaPa

人生をほんの少しだけ充実させる

【Architecture】アーキテクチャパターンを整理する

前々回の記事でソフトウェアソフトウェアアーキテクチャの概要とその重要性を紹介しました。

www.hanatare-papa.jp

前回の記事ではモノリシックアーキテクチャ、分散アーキテクチャの違いを紹介しました。 www.hanatare-papa.jp

今回の記事では、マイクロサービスや、モジュラーモノリスといった最近よく目にするアーキテクチャパターンについて紹介をしていきたいと思います。

記事のポイント
  • マイクロサービスアーキテクチャのアプローチと利点・課題
  • モジュラーモノリスアーキテクチャのアプローチと利点・課題
  • ドメイン中心設計アーキテクチャのアプローチと利点・課題

マイクロサービスアーキテクチャ:スケーラビリティの標準形

アプリケーションをビジネス機能に基づいて小さな独立したサービスの集合に分解し、独立してデプロイ可能にするアーキテクチャのアプローチです。独立したサービスはAPIを通じて相互に連携することが特徴です。

理念と構造

マイクロサービスには以下のような重要な原則に基づいて支えられています。

単一責任と境界づけられたコンテキスト (Bounded Context)

各サービスは、明確に定義された単一のビジネス責務を持って分けられます。例えば、ECサイトをマイクロサービスで構築すると、「顧客管理」、「商品カタログサービス」、「注文管理」、「決済管理」、「発注管理」など各ビジネス用途毎にサービスを分けて分割することで、責任範囲を明確して分けられます。

独立したデプロイメント

各サービスは個別のコードベースを持ち、他のサービスとは独立してビルド、テスト、デプロイが可能です。これにより、特定の機能改修が他の機能に影響を与えることなく、迅速なリリースサイクルを実現できます。

データの分散管理

「サービスごとにデータベースを持つ」ことが原則です。これにより、サービス間のデータレベルでの密結合を防ぎ、各サービスが自身のデータモデルを自律的に管理できるようになります。共有データベースというアンチパターンを回避することが極めて重要です 。

疎結合の促進

各サービスがビジネスロジックを内包し、エンドポイントと呼ばれるアクセスポイントを通じて、サービス間の通信を行います。通信に際しては、APIや軽量なメッセージキューのような単純な転送メカニズムに徹します。

マイクロサービスのメリット

この原則を遵守することで、マイクロサービスは以下のようなメリットを享受することができます。

チームの自律性とスケーラビリティ

明確に定義されたビジネス責務の範囲に応じて作成されたサービスを、その責任範囲を扱う組織(チーム)が所有することが可能となり、開発の並行性と速度を劇的に向上させます。また、負荷の高いサービスだけを個別にスケールさせることができるため、リソース効率が最大化されます 。

技術の多様性

各サービスは独立しているため、その機能に最適なプログラミング言語、フレームワーク、データストアを自由に選択できます 。

回復力(レジリエンス)

各サービスは独立しているため、障害の分離が実現されます。ある一つの非基幹的なサービスが停止しても、システム全体がダウンすることを防げます 。

マイクロサービスのデメリット

マイクロサービスアーキテクチャの導入は、しばしば過小評価されがちな重大なコストと複雑性を伴います。

分散システムとしての複雑性

ネットワークの遅延、部分的な障害、データの一貫性といった、分散システム固有のあらゆる課題がアーキテクチャの中心的な関心事となります 。

運用オーバーヘッド

成熟したDevOpsプラクティスが不可欠です。サービスディスカバリ(例: Netflix Eureka)、サーキットブレーカー(例: Hystrix)、APIゲートウェイ、そして高度な監視、ロギング、分散トレーシングの仕組みを構築・運用する必要があります 。

データ一貫性の維持

複数のデータベースにまたがるトランザクションの一貫性を保証することは、極めて困難な課題です。これを解決するためには、SagaパターンやTransactional Outboxパターンといった高度なデザインパターンを適用し、結果整合性を管理する必要があります 。

設計の難易度

サービスの境界を適切に定義することは非常に難しく、初期の設計ミスは後から修正困難です。不適切な分割は、Monolith in microservices(各サービスが密結合し、独立してデプロイできない状態)やChatty microservices(一つの処理のためにサービス間で過剰な通信が発生する状態)といったアンチパターンを生み出します 。

vfunction.com

マイクロサービスのケーススタディ:Netflix

Netflixは、マイクロサービスアーキテクチャを大規模に採用し、成功を収めた代表的な企業です。同社は、単一のモノリシックなDVDレンタルシステムから、数百のマイクロサービスで構成されるグローバルなストリーミングプラットフォームへと移行しました。このアーキテクチャにより、Netflixは驚異的なスケーラビリティ、高い可用性、そして迅速な機能開発とイノベーションを実現しています 。

モジュラーモノリスアーキテクチャ:現実的な中間地点

マイクロサービスのメリットと、それに伴う運用上の複雑性との間で、より現実的でバランスの取れた選択肢として注目を集めているのが「モジュラーモノリス」アーキテクチャです。これは、モノリスの運用上のシンプルさと、マイクロサービスの設計上のモジュール性を両立させることを目指した、戦略的なアプローチです。

位置づけと設計思想

モジュラーモノリスは、単一のデプロイメントユニットとして構築されるという点ではモノリスと同じです。しかし、その内部構造は、明確に定義された境界を持つ独立した「モジュール」の集合体として構成されます 。各モジュールは特定のビジネスドメインに特化しており、モジュール間の通信は公開されたAPI(インターフェース)などを通じて行われます。これにより、分散システムがもたらすネットワークや運用の複雑性を回避しつつ、コードレベルでの高い凝集度と密結合度低下を実現します。

主な特徴と利点

モジュラーモノリスは、多くの実用的な利点を提供します。

運用複雑性の低減

サービスディスカバリ、分散トレーシング、サービスメッシュといった複雑なインフラストラクチャが不要であり、デプロイや監視がモノリスと同様にシンプルです 。

明確な境界

モジュール間の依存関係がコードレベルで強制されるため、アプリケーション全体が「巨大な泥団子」になるのを防ぎます。これにより、コードの可読性、保守性、解析性が向上します。

開発ワークフローの改善

各チームは担当するモジュールに集中して並行開発を進めることができ、モジュール間の明確なインターフェースがコンフリクトのリスクを低減します 。

進化的アーキテクチャへの道

モジュラーモノリスは、マイクロサービスへの段階的な移行パスを提供します。将来、特定のモジュールが独立したスケーリングやデプロイを必要とするようになった場合、その明確に定義された境界を利用して、比較的容易にマイクロサービスとして切り出すことが可能です 。

モジュラーモノリスのケーススタディ:Shopify

世界最大級のECプラットフォームであるShopifyは、モジュラーモノリスアーキテクチャを大規模に採用していることで知られています。同社は、巨大で複雑なシステムを管理しながらも、高い開発速度とシステムの安定性を維持するためにこのアプローチを選択しました。単一のデプロイメントユニットを維持しつつ、内部のモジュール性を高めることで、マイクロサービスの運用負荷を避けながら、アジリティを確保しています 。

モジュラーモノリスからマイクロサービスへの移行

多くのプロジェクトがマイクロサービスの導入に失敗する根本原因は、その技術的な魅力に惹かれ、チームの成熟度やビジネスの必要性が追いついていない段階で、分散化に伴う莫大な運用コストと複雑性を抱え込んでしまう点にあります 。モジュラーモノリスは、この問題を回避するための賢明な選択肢を提供します。それは、マイクロサービスのコードレベルでの利点(モジュール性、チームの責務分離)の大部分を享受しつつ、分散化という最もコストのかかる決断を、ビジネス上の明確な要求(特定の機能の独立したスケーリングなど)が発生するまで「先送り」することを可能にするからです 。

アーキテクチャの意思決定を段階的にする

アーキテクチャは一度決めて進めてしまうと、途中で変更することは非常に困難です。しかし、モジュラーモノリスの考え方はアーキテクチャの意思決定を二者択一から段階的なプロセスへと変えます。

  • フェーズ1: まずモジュラーモノリスから始める。これにより、プロジェクトの初期段階から優れた設計原則とチーム間の明確な境界を強制しつつ、運用コストを最小限に抑える。
  • フェーズ2: システムが成長し、特定のモジュールが独立したスケーリングやデプロイを本当に必要とすることがデータで示された場合に限り、その明確に定義されたモジュール境界を利用してマイクロサービスとして切り出す。

このように、モジュラーモノリスは、マイクロサービスへの移行を、初期段階でのハイリスクな賭けではなく、データに基づいた慎重かつ意図的な戦略的判断へと昇華させる、リスク管理アーキテクチャです。

ドメイン中心アーキテクチャ(クリーン、ヘキサゴナル、オニオン)

最近では、ソフトウェアの保守性、テスト容易性、そして長期的な進化能力を最大化するための設計思想として、ドメイン中心のアーキテクチャ群が注目を集めています。 以下にその代表的なものを3つ挙げます。

  • クリーンアーキテクチャ
  • ヘキサゴナルアーキテクチャ(別名:ポートとアダプタ)
  • オニオンアーキテクチャ

これらは、細部こそ異なりますが、すべて同じ哲学を共有しています。それは、「アプリケーションの中核をなすビジネスロジックとドメインルールを、UI、データベース、フレームワークといった外部の技術的詳細から徹底的に隔離する」というものです。

共通の哲学:中核の保護

これらのアーキテクチャの心臓部には、 依存性逆転の原則(Dependency Inversion Principle)があります。依存性逆転の原則とは、「具体的な実装」ではなく「抽象的なルール(インターフェース)」に依存しよう、という設計原則に基づきます。

「上位の機能(例:レポート作成機能)が、下位の機能(例:データベースからデータを読み取る機能)を利用する」という流れでプログラムを書きます。このとき、依存関係は「上位 → 下位」へと向かいます。依存性の原則とはその関係を逆転させます。

逆転前:上位モジュール → 下位モジュール

逆転後:上位モジュール → 抽象(ルール) ← 下位モジュール

この時の抽象(ルール)はAというインプットを渡せば、Bを返すというようなインターフェースで、APIに考え方が近いものになります。

ヘキサゴナルアーキテクチャ

このアーキテクチャは、アプリケーションのコアを「六角形(ヘキサゴン)」として捉えるメタファーを用います。この六角形の各辺には「ポート」と呼ばれるインターフェースが存在し、アプリケーションが外部とどのように対話するかを定義します。そして、具体的な技術(例:RESTコントローラ、データベースリポジトリ)は、これらのポートを実装する「アダプタ」として六角形の外側に配置されます。これにより、コアロジックはアダプタの詳細を知ることなく、抽象的なポートとのみ対話します 。

クリーン/オニオンアーキテクチャ

これらはヘキサゴナルアーキテクチャの考え方を、より具体的な同心円状のレイヤー構造として規定したものです。最も内側にはビジネスの根幹をなす「エンティティ」があり、その外側にアプリケーション固有のビジネスルールである「ユースケース」、さらにその外側に「インターフェースアダプタ」、そして最も外側に「フレームワーク&ドライバ」が配置されます。ここでも、依存関係は常に外側のレイヤーから内側のレイヤーへと向かいます 。

ここでは、クリーンアーキテクチャとオニオンアーキテクチャの違いや詳細については省略したいと思います。今回はこういったアーキテクチャもあるんだなぐらいに考えていただけたらと思います。

メリット

厳格な依存関係のルールは、開発プロセスに大きなメリットをもたらします。

テスト容易性

中核となるビジネスロジックは、特定の技術に一切依存しない純粋なコードモジュール(Plain Old Java Object - POJOなど)となります。これにより、データベースを起動したり、Webサーバーを立ち上げたりすることなく、ビジネスロジックを単体で高速かつ安定的にテストすることが可能になります 。

技術からの独立性

データベースをMySQLからPostgreSQLに変更したり、WebフレームワークをSpringからQuarkusに移行したりといった技術的な決定を、ビジネスロジックに影響を与えることなく行うことができます。必要なのは、新しい技術に対応する「アダプタ」を実装し、差し替えることだけです 。

高い保守性と再利用性

ビジネスロジックが外部の関心事から隔離されているため、コードは非常にクリーンで理解しやすくなります。また、中核となるビジネスロジックは、異なるUIやデプロイ環境を持つ複数のアプリケーションで再利用することも可能です 。

課題と考慮事項

一方で、これらのアーキテクチャは万能薬ではなく、導入にはいくつかの課題が伴います。

複雑性と定型コードの増加

高度な抽象化を導入するため、インターフェース、DTO(Data Transfer Object)、マッパーといった定型的なコード(ボイラープレート)が増加します。単純なCRUD(作成、読み取り、更新、削除)機能が中心のアプリケーションにとっては、過剰設計(Over-engineering)と感じられる可能性があります 。

学習曲線

SOLID原則、特に依存性逆転の原則に対する深い理解が求められます。経験の浅いチームにとっては、この設計思想を正しく理解し、実践することが大きなハードルとなる場合があります 。

まとめ

今回の記事では、現代的なソフトウェアアーキテクチャであるマイクロサービス、モジュラーモノリス、そしてドメイン中心設計について解説しました。

  • マイクロサービスは、高いスケーラビリティと柔軟性を実現しますが、分散システム特有の複雑さや高い運用コストが課題です。
  • モジュラーモノリスは、モノリシックな構成で運用のシンプルさを保ちつつ、内部をモジュール化することで保守性を高める、現実的でバランスの取れたアプローチです。将来的なマイクロサービスへの移行の足がかりともなります。
  • クリーンアーキテクチャなどのドメイン中心設計は、ビジネスロジックを技術的詳細から守る設計思想です。これにより、テストのしやすさや長期的な保守性を大幅に向上させます。

それぞれのアーキテクチャにはメリットとデメリットが存在します。プロジェクトの状況やチームの成熟度に応じて、これらの特徴を理解し、戦略的に選択することが重要です。次の記事ではアーキテクチャを選定するにあたってのポイントについてまとめたいと思います。 次回も是非読んでいただけましたら幸いです。