ソフトウェアアーキテクチャについて
『ソフトウェアアーキテクチャの基礎』と
『アーキテクトの教科書: 価値を生むソフトウェアのアーキテクチャ構築』
を踏まえて、ソフトウェアアーキテクチャに関する基本事項を整理する。
設計とアーキテクチャ
ソフトウェア開発では、「設計」と「アーキテクチャ」はしばしば近い意味で使われる。
一方で、一般にはアーキテクチャはシステム全体に大きな影響を与える重要な設計判断を指すことが多い。
たとえば、以下のような内容はアーキテクチャ上の関心事に含まれる。
- システムをどの単位で分割するか
- どのような構造で責務を分離するか
- どのようにコンポーネント間を連携させるか
- 性能、可用性、保守性、セキュリティなどの品質特性をどう満たすか
一方、設計は、そのアーキテクチャの方針のもとで、クラス・関数・モジュールなどを具体的にどう構成するかという詳細化を含む。
ソフトウェアアーキテクチャとは
ソフトウェアアーキテクチャは、システム全体の構造と、その構造に関する重要な設計判断を扱う。
主な観点として、以下が挙げられる。
1. システム構造
システムを構成する主要な要素と、それぞれの責務や配置を定義する。
たとえば、アプリケーション、データベース、外部サービス、メッセージ基盤などの関係を整理する。
2. 相互作用
要素間がどのように連携するかを定義する。
API 呼び出し、イベント通知、メッセージング、データフローなどが含まれる。
3. 制約と原則
技術選定、セキュリティ方針、運用要件、スケーラビリティ要件など、システム全体に適用される制約や原則を定める。
4. 品質特性
性能、可用性、保守性、拡張性、セキュリティ、テスト容易性などの品質特性を満たすための土台を定める。
なぜアーキテクチャが重要か
アーキテクチャは、現在の実装だけでなく、将来の変更容易性や運用性にも影響する。
初期段階での重要な設計判断は、後から変更しづらく、システム全体のコスト構造に影響しやすい。
アーキテクチャが重要である理由として、次の点がある。
- 将来の変更や拡張に対応しやすくなる
- 変更時の影響範囲を抑えやすくなる
- チームでの分担や保守を行いやすくなる
- 品質特性を初期段階から考慮しやすくなる
アーキテクチャが不適切な場合に起こりやすいこと
アーキテクチャ上の責務分離や境界設定が不十分な場合、開発や保守で次のような問題が起こりやすい。
1. 複雑性の増大
依存関係が増え、全体像の把握が難しくなる。
その結果、理解コストや不具合混入リスクが高くなる。
2. 変更容易性の低下
一部の修正が広範囲に影響しやすくなり、局所的な変更が難しくなる。
3. 属人化
特定の担当者しか構造や背景を理解していない状態になると、保守性が下がる。
4. テスト容易性の低下
密結合な構造では、ユニットテストや統合テストの対象を分離しづらくなる。
これらは、いわゆる技術的負債の蓄積と結びつくことが多い。
代表的なアーキテクチャスタイル
アーキテクチャスタイルとは、共通した特徴を持つアーキテクチャの類型である。
システムの規模、変更頻度、チーム構成、品質要件などに応じて選択する。
モノリシックアーキテクチャ
単一のアプリケーションとして構築・デプロイされる構成である。
比較的シンプルに開発・デプロイしやすく、小規模から中規模のシステムで採用しやすい。
ただし、責務分離やモジュール化が不十分な場合、機能追加や変更に伴って構造が肥大化しやすい。
一方で、適切にモジュール化されたモノリスは、現在でも有力な選択肢である。
レイヤードアーキテクチャ
責務ごとに層を分ける構成である。
一般的には、プレゼンテーション層、アプリケーション層、ドメイン層、インフラストラクチャ層などに分けて設計する。
この構成により、責務分離や変更影響の局所化を図りやすい。
ただし、過剰な抽象化や不要な層分割を行うと、シンプルなシステムでは実装コストが増えることもある。
マイクロサービスアーキテクチャ
独立して変更・デプロイ可能な複数のサービスでシステムを構成するスタイルである。
単に細かく分割するのではなく、ビジネス上の責務や境界に基づいてサービスを分けることが重要になる。
一般に、各サービスは特定の責務を担い、サービス境界は bounded context と整合することが望ましい。
適切に設計されれば、独立した開発・デプロイやスケーリングがしやすくなる。
一方で、分散システムとしての複雑さが増すため、監視、障害対応、データ整合性、テスト、運用の難易度は上がりやすい。
設計アプローチとしての DDD
DDD(Domain-Driven Design、ドメイン駆動設計)は、複雑な業務領域を扱うための設計アプローチである。
モノリシック、レイヤード、マイクロサービスのようなアーキテクチャスタイルと同列というより、ドメインモデルを中心に設計するための考え方として位置づけられる。
DDDでは、次のような考え方が重要になる。
- ドメインの概念をソフトウェアモデルに反映する
- 業務用語と実装上の用語をそろえる
- bounded context を定義してモデルの境界を明確にする
- 複雑なビジネスルールをドメイン層に集約する
そのため、DDDはレイヤードアーキテクチャやマイクロサービスと組み合わせて利用されることが多い。
既存システムの設計意図を読み解く方法
既存システムのアーキテクチャを理解するには、複数の観点から確認する必要がある。
1. ドキュメントを確認する
設計書、構成図、運用資料、ADR などから、システム構造や意思決定の背景を確認する。
2. コードを確認する
ディレクトリ構成、命名規則、依存関係、レイヤー分割、モジュール境界などから、実際の構造を把握する。
コードは実装の実態を反映しているため、ドキュメントとあわせて確認することが重要である。
3. 関係者に確認する
歴史的経緯、過去の制約、見送られた選択肢、トレードオフの判断などは、ドキュメントやコードだけでは分からないことがある。
そのため、設計者や保守担当者へのヒアリングも有効である。
設計の意思決定を記録する ADR
ADR(Architecture Decision Record)は、アーキテクチャ上の重要な意思決定を記録するためのドキュメントである。
ADR は通常、1つの意思決定を1つの短い文書として記録する。
一般的に、ADR には以下のような項目が含まれる。
- Title: 何に関する意思決定か
- Status: 提案中、採用済み、廃止、後続のADRで置き換え済み、などの状態
- Context: その意思決定が必要になった背景
- Decision: 何を選択したか
- Consequences: その決定による影響、利点、不利益、注意点
必要に応じて、代替案や比較対象を含めることもある。
たとえば認証方式を決める場合には、次のような内容を ADR に残せる。
- 自前実装ではなく外部認証基盤を採用する理由
- 比較対象とした選択肢
- セキュリティ、運用、コストへの影響
- 将来的な制約やリスク
このような記録を残すことで、後から参加したメンバーでも、なぜその判断になったかを追いやすくなる。
システム全体を見渡す視点
アーキテクチャを学ぶ目的のひとつは、個別機能だけでなく、システム全体を見渡して設計判断を行う視点を持つことである。
そのためには、次のような観点が必要になる。
俯瞰的に考える
個々の機能や実装だけではなく、全体構造に対する影響を考える。
品質特性を意識する
性能、可用性、保守性、セキュリティ、運用性などを構造レベルで考える。
責務分離と境界を意識する
どこまでを1つの責務とするか、どこで分割するかを意識して設計する。
意思決定の理由を残す
なぜその構造や技術を選んだのかを、後から追える形で残す。
まとめ
ソフトウェアアーキテクチャは、システム全体の構造と、それに関する重要な設計判断を扱う。
主な対象は、構造、相互作用、制約、品質特性である。
また、代表的なアーキテクチャスタイルには、モノリシック、レイヤード、マイクロサービスなどがある。
DDD はそれらと同列のスタイルというより、複雑なドメインを扱うための設計アプローチとして整理できる。
既存システムを理解するには、ドキュメント、コード、関係者への確認を組み合わせることが有効である。
さらに、重要な設計判断は ADR として記録することで、継続的な保守やチーム開発に役立てやすくなる。