ソフトウェアアーキテクチャの記事を書き続けてきましたが、今回で一旦最終回です。
最初の記事でソフトウェアソフトウェアアーキテクチャの概要とその重要性を紹介しました。
前々回の記事ではモノリシックアーキテクチャ、分散アーキテクチャの違いを紹介しました。 www.hanatare-papa.jp
前回の記事ではアーキテクチャパターンとしてどういったものがあるのかを紹介しました。 www.hanatare-papa.jp
今回は色々と紹介してきたアーキテクチャのどれを使うのかを決定していくプロセスについてまとめたいと思います。
構造化された意思決定プロセス
ソフトウェアアーキテクチャの選定に正解はありません。選定にあたっては、プロジェクトを取り巻く様々な要因の理解が必要です。その中で、何が最適かを見極めることが今のシステムアーテキトに求められる力になります。
とはいえ、最初からすべてを正確に見極めることは困難です。また、場当たり的な判断では再現性がありません。そのため、構造化されてプロセスが不可欠です。そのために考えるポイントを提示させていただこうと思います。
1. ビジネス要件と制約の特定
アーキテクチャ設計の出発点は、ビジネスが何をゴールとし、どのような制約の中でそれを実現するのかを明確にすることです。
ビジネス要件と機能要件
システムが「何をするべきか」を定義します。これは、アーキテクチャが達成すべき第一の目標です 。
品質特性(非機能要件)
システムが「どのように振る舞うべきか」を定義します。性能、スケーラビリティ、保守性、可用性、セキュリティ、テスト容易性などが含まれます。定量的な数字を用いて、測定可能な指標を定義することが重要です。
制約条件
予算、納期、利用可能な技術スタック、法規制、業界標準、連携がある場合の周辺システムによる制約など、プロジェクトが考慮しなければいけない制約条件です。
2. 人的要因の考慮
生成AIが台頭しているとはいえ、システムを最終的に使ったり、作ったり、運用するのは「人」です。この人の能力を超えたアーキテクチャは必ず失敗します。
チームのスキルと経験
チームが分散システムや特定の技術に不慣れな場合、マイクロサービスのような高度なアーキテクチャを導入するのは高いリスクを伴います。チームの現状のスキルセットに合った、あるいは現実的な学習期間で習得可能なアーキテクチャを選択することが重要です 。
システムの寿命と進化の予測
短期間で破棄されるプロトタイプと、10年以上の運用が期待される基幹システムでは、保守性や拡張性に対する要求が根本的に異なります。人の能力と合わせてシステムのライフサイクルを考慮に入れる必要があります 。
3. パターンの評価と比較
特定したビジネス要因と制約、人的要因を基準に前回のブログで紹介したアーキテクチャパターンを評価します。評価を体系的に行うためには、マトリクス表のようなものを用いて、アーキテクチャパターンとそれぞれの特徴・強み・弱み・プロジェクトにおける効果することで、視覚的にわかりやすい検討になると思います。
以下の表がイメージになります。あくまで一般的な傾向を元に書いていますので、個々のプロジェクトによって変動する可能性が高いことに注意してください。
| アーキテクチャ名 | 全体的な複雑性 | スケーラビリティ | 保守性 | テスト容易性 | チームの自律性 | 主な適用ケース |
|---|---|---|---|---|---|---|
| モノリシック | 低 | 低 | 低 | 低 | 低 | 小規模アプリケーション、MVP、プロトタイプ |
| レイヤード | 低〜中 | 低 | 中 | 中 | 低 | 伝統的なエンタープライズアプリケーション、責務分離が明確なシステム |
| マイクロサービス | 高 | 高(粒度による) | 高 | 高 | 高 | 大規模で複雑なシステム、自律的なチームによる高速な開発 |
| モジュラーモノリス | 中 | 中 | 高 | 高 | 中 | 中〜大規模システム、マイクロサービスへの段階的移行、運用複雑性の回避 |
| イベント駆動 | 高 | 高 | 中 | 中 | 高 | 非同期処理、リアルタイムシステム、疎結合なサービス連携 |
| マイクロカーネル | 中 | 中 | 高 | 高 | 中 | プラグイン形式の製品、機能拡張が頻繁なシステム(例:IDE、ブラウザ) |
| クリーン/ヘキサゴナル | 中〜高 | 中 | 高 | 最高 | 中 | ビジネスロジックが複雑なシステム、長期的な保守性・テスト容易性を最優先する場合 |
4. 意思決定の記録
アーキテクチャに関する決定やそれまでのプロセスは必ず記録に残すべきです。プロセスには、「なぜ」その決定に至ったのか、どのような代替案を検討し、なぜそれらを棄却したのか、そしてその決定がもたらす「結果(トレードオフ)」が含まれます。
プロジェクトが長く続くものであれば、それだけ長く使われるアーキテクチャになります。その間プロジェクトの中の人は入れ替わることが考えられます。入れ替わった際でも、この記録を残しておくことで、将来のメンバーがアーキテクチャ設計の意図を理解し、一貫性のある開発を続けるための拠り所になります。
アンチパターン
アーキテクチャを設計していく上で、陥りがちなアンチパターンというのがあります。ここでは、一般的なアンチパターンを紹介しますので、自信の設計がアンチパターンに陥っていないかを振り返る参考にしてもらえたらと思います。
分散モノリス (Distributed Monolith)
マイクロサービスアーキテクチャ導入における、最も一般的で致命的な失敗です。
見た目は複数のサービスに分割されていますが、サービス間が密な同期的呼び出しや共有ライブラリによって強く結合してしまっている状態を指します。
結果、分散システムの欠点(ネットワーク遅延、運用の複雑さ)と、モノリスの欠点(デプロイの依存関係、変更の困難さ)の両方を兼ね備えた、最悪のシステムが生まれます
この根本原因は、ビジネスの境界を正しく見極めず進めた結果、不適切な単位でサービスを分割してしまうことにあります。
共有データベース (Shared Database)
マイクロサービスアーキテクチャにおいて、複数のマイクロサービスが単一のデータベーススキーマを共有する、あるいは直接アクセスすることを言います。これは密結合となり、あるサービスのデータベーススキーマ変更が、他のすべてのサービスに影響を及ぼします。
そのため、マイクロサービスの最大の利点である「独立したデプロイ」が不可能になり、サービス間の自律性が完全に失われます 。各サービスは自身のデータを完全に所有し、外部には安定したAPIを通じてのみデータを提供すべきです。
Chatty Servicesと過剰な分割
サービスを過度に細かく分割することで、単一のユーザーリクエストを処理するために、多数のサービス間で数十回ものネットワーク呼び出しを行うことです。これは結果的にシステムレイテンシの増大を招きパフォーマンスに影響を与える要因となります。
単一のユーザーリクエストを処理するために、多数のサービス間で数十回ものネットワーク呼び出しが必要です。
イベント駆動アーキテクチャの落とし穴
イベント駆動アーキテクチャについてはあまり触れてはきませんでしたが、最近のアーキテクチャでは採用されることも多いパターンです。イベント駆動アーキテクチャにも気を付けるパターンがありますのでご紹介します。
順序保証の欠如
多くのメッセージブローカーは、パーティション内(1つの処理レーン)での順序は保証しますが、トピック全体(パーティションの集合体)での厳密な順序は保証しません。ビジネスロジックがイベントの発生順序に依存する場合、これを考慮しない設計はデータ不整合を引き起こします 。
べき等性の欠如
ネットワークの問題などにより、同じイベントが複数回配信される可能性があります。コンシューマ側で、同じイベントを複数回処理しても結果が変わらない「べき等性」が担保されていない場合、重複レコードが生まれるなどの問題が発生します。
可視性の喪失
同期的なリクエスト/レスポンスとは異なり、イベント駆動のワークフローは非同期に進行するため、ビジネスプロセス全体の流れや現在の状態を追跡することが困難になります。分散トレーシングなどの高度な監視ツールなしでは、問題発生時のデバッグが非常に難しくなります 。
まとめ
4回に分かったソフトウェアアーキテクチャについて記事にしてきました。ソフトウェアアーキテクチャの基本概念から、代表的なパターン、そしてそれらを選択するための実践的なプロセスといった流れで、説明をしてきました。
今回の説明の中でも述べていますが、ソフトウェアアーキテクチャに正解はなく、プロジェクトを取り巻く状況や制約によって取捨選択をしながら決めていくものです。
モノリシック、マイクロサービス、モジュラーモノリス、ドメイン中心といった多様な選択肢の長所と短所を深く理解し、それらを現実にあてはめ適用できる力が今のエンジニアに求められている気がします。
今回の記事がソフトウェアアーキテクチャを考えようとされている方の参考になっていれば幸いです。