はじめに
分散アーキテクチャの設計をしていると、「で、結局どっちがいいんですか?」という問いに何度もぶつかります。サービスはどこまで細かく割るべきか、データベースは分けるべきか、トランザクションはどう担保するか。どれも正解が一つに定まらない問いです。
本書『ソフトウェアアーキテクチャ・ハードパーツ』は、まさにその「正解がない領域」を正面から扱った一冊です。ベストプラクティスを提示するのではなく、トレードオフを分析する能力そのものを鍛えることを目的としています。
読み終えたあと、設計判断に対する自分の語彙がはっきり増えたと感じられる本でした。以下、全体構成と各章の要点、そして実務での使いどころを整理していきます。
書誌情報
| 項目 | 内容 |
|---|---|
| 書名 | ソフトウェアアーキテクチャ・ハードパーツ ―分散アーキテクチャのためのトレードオフ分析 |
| 著者 | Neal Ford、Mark Richards、Pramod Sadalage、Zhamak Dehghani |
| 訳者 | 島田 浩二 |
| 出版社 | オライリー・ジャパン |
| 発行 | 2022年10月25日 初版第1刷 |
| ISBN | 978-4-8144-0006-5 |
著者陣は『ソフトウェアアーキテクチャの基礎』のNeal FordとMark Richardsに加え、データ/DevOps領域のPramod Sadalage、そしてデータメッシュの提唱者であるZhamak Dehghaniという顔ぶれです。アーキテクチャとデータの両輪が、一冊のなかで同じ言葉で語られているのは、この著者構成があってこそだと思います。
本書が扱う「ハードパーツ」とは何か
1章はタイトルからして挑戦的で、「ベストプラクティス」がないとどうなる? という問いから始まります。
著者らの立場ははっきりしています。ソフトウェアアーキテクチャに時代を超えて通用する助言があるとすれば、それは「すべてはトレードオフである」という一点であり、それ以外の助言は文脈に依存する、というものです。技術は変化し、ツールは入れ替わり、昨日のベストプラクティスは今日のアンチパターンになります。だからこそ、パターンの暗記ではなく、自分の状況に合わせて選択肢を評価する手続きが必要になる、という主張です。
本書ではその手続きを支える道具として、以下の2つが繰り返し登場します。
- アーキテクチャデシジョンレコード(ADR):決定そのものではなく、決定の背景・検討した代替案・結果を短い文書として残す仕組み
- アーキテクチャ適応度関数:設計上守りたい特性を、自動的に検証可能な形で表現したもの
どちらも「決めたあとに腐らせない」ための仕組みです。トレードオフ分析は一度やって終わりではなく、前提が変わったら見直すものだ、という姿勢が全編に通底しています。
Sysops Squadサーガという語り口
本書の大きな特徴が、Sysops Squadという架空の企業を舞台にした物語形式の解説です。家電の保守サポートを行う会社のチケット管理システムが、モノリスのまま限界を迎えている、というところから話が始まります。
アーキテクトのアディソンとオースティン、そして助言役のローガンが登場し、各章の理論パートのあとに「では自分たちのケースではどう判断するか」という会話が挿入されます。ここで実際にADRが書かれ、トレードオフ表が更新されていきます。
正直なところ、技術書のストーリーパートは飛ばし読みしがちなのですが、本書に関してはここが本編だと感じました。理論だけ読むと「どれも一長一短ですね」で終わってしまうところが、具体的な業務要件と制約が与えられることで、なぜその選択に落ち着いたのかが追える構成になっています。
全体構成
本書は大きく2部構成です。
- 第I部 分解する … 主に「構造」と静的結合を扱う(2章〜7章)
- 第II部 つなぎ合わせる … 主に「通信」と動的結合を扱う(8章〜15章)
まずシステムをバラバラにし、次にそれを機能させるために結び直す、という流れです。第II部の冒頭に置かれたLarry Constantineの指摘、すなわち凝集度の高いモジュールを無理に分割しても結合が増えて可読性が下がるだけだ、という趣旨の言葉が、後半全体のトーンを決めています。
第I部:分解する
2章 結合の見分け方 ― アーキテクチャ量子
本書全体を貫く中心概念が アーキテクチャ量子 です。定義としては、次の3つを満たす独立デプロイ可能な単位とされます。
- 独立してデプロイできる
- 機能的凝集度が高い
- 静的結合度が高い
ここでいう静的結合とは、動作するために必要な依存関係の総体です。フレームワーク、ライブラリ、そしてデータベースも含まれます。この「データベースを共有しているなら、それは同じ量子である」という視点が非常に効きます。サービスを10個に割っても単一DBを共有していれば、デプロイの単位は1つのままだからです。
そして動的結合、つまりサービス同士が実行時にどう呼び合うかを、本書は3つの次元に分解します。
| 次元 | 取り得る値 |
|---|---|
| 通信 | 同期 / 非同期 |
| 整合性 | アトミック / 結果整合性 |
| 調整 | オーケストレーション / コレオグラフィ |
この3次元は12章のサーガパターンの分類軸として再登場します。「分散システムの難しさ」という漠然とした話題が、3つの独立した選択に分解される瞬間で、個人的にはここが本書で一番の収穫でした。
3章 モジュール化の推進要因
そもそもなぜ分解するのか、という動機の整理です。挙げられているのは以下の5つです。
- 保守性
- テスト性
- デプロイ性
- スケーラビリティ
- 可用性・耐障害性
重要なのは、これらが「やるべき理由」ではなく「ビジネス側に説明できる理由」として扱われている点です。Sysops Squadの物語でも、アーキテクトが「もう他に手がないから」と主張して却下される場面から始まります。分解には時間と予算がかかる以上、事業上の便益に接続されていなければ承認されない、という現実的な描写になっています。
4章 そもそも分解できるコードベースなのか
いきなり分割に入る前に、対象のコードベースが分解に耐えるかを測る章です。ここで登場するのがRobert C. Martinの指標群です。
- 求心性結合/遠心性結合:どれだけ依存されているか、どれだけ依存しているか
- 抽象度と不安定度:抽象的な要素の比率と、変更されやすさ
- 主系列からの距離:抽象度と安定度のバランスが理想線からどれだけ離れているか
これらの指標が最悪な、いわゆる「泥団子」状態のコードベースであれば、そもそも分解を試みるべきではない、という判断もあり得ます。その場合の選択肢として提示されるのが 戦術的フォーク です。共通部分を切り出すのではなく、システム全体を丸ごと複製し、それぞれから不要な部分を削っていくというアプローチで、依存関係を解きほぐすより「削るほうが簡単」というエンジニアの直感に沿った手法です。
これに対し、構造がある程度きれいなら コンポーネントベース分解 を選びます。
5章 コンポーネントベース分解の6パターン
第I部で最も実務寄りの章です。モノリスを段階的に分解するための6つのパターンが、適用順序を持った一連の流れとして提示されます。
- コンポーネントの特定およびサイズ調整
- ドメイン共通コンポーネントの収集
- コンポーネントのフラット化
- コンポーネントの依存関係判断
- コンポーネントドメインの作成
- ドメインサービスの作成
各パターンには適応度関数の例が添えられており、「サイズが基準を超えたら警告する」「循環依存が発生したらビルドを失敗させる」といった形で、分解の途中経過を自動検証できるようになっています。
いきなりマイクロサービスにするのではなく、まずモノリス内部で境界を整え、サービス化はその後という順序が徹底されています。モジュラーモノリスを経由する移行の具体的な手順書として読める章です。
6章 業務データの分解
データベースを分けるべきか、という判断を扱います。分解する方向に働く要因と、統合したままにしておく方向に働く要因が、それぞれ列挙されます。
分解要因(分けたくなる理由)
- 変更制御:スキーマ変更の影響範囲を狭めたい
- コネクション管理:コネクションプールの枯渇を避けたい
- スケーラビリティ:データストア単位で個別にスケールさせたい
- 耐障害性:単一障害点を排除したい
- アーキテクチャ量子:デプロイ単位を独立させたい
- データベース種別の最適化:用途に合ったDBを選びたい
統合要因(分けたくない理由)
- データ関係:外部キー、ビュー、トリガ、ストアドプロシージャ
- データベーストランザクション:ACIDを維持したい
コネクション管理の議論は特に実践的でした。サービス数が増えるとコネクションはサービス数分だけ必要になるわけではなく、インスタンス数との掛け算で効いてきます。均等割り当てから可変割り当てへ、という具体的な設計指針が示されています。
後半はデータベース種別の比較で、リレーショナル、キーバリュー、ドキュメント、列指向、グラフ、NewSQL、クラウドネイティブ、時系列の8種を、学習コスト・データモデリング・スケール・可用性・整合性・分割耐性・プログラミング言語サポート・コミュニティといった軸で評価しています。星取表として手元に置いておく価値があります。
7章 サービスの粒度
「マイクロサービスはどこまで小さくすべきか」という頻出の問いに対する、本書の回答です。
まず粒度とモジュール性を明確に区別します。モジュール性は「どう分けるか」、粒度は「どのくらいの大きさにするか」で、別の問題だという整理です。そのうえで、粒度を細かくする方向の要因と、粗くする方向の要因を対置します。
粒度分解要因(小さくする理由)
| 要因 | 適用理由 |
|---|---|
| サービスの範囲と機能 | 単一目的で凝集度の高いサービスにしたい |
| コード変動率 | 変更頻度の高い部分だけを切り出したい |
| スケーラビリティとスループット | 負荷特性が異なる部分を個別にスケールさせたい |
| 耐障害性 | 障害の影響範囲を限定したい |
| セキュリティ | 機微データへのアクセス経路を絞りたい |
| 拡張性 | 将来の機能追加を局所化したい |
粒度統合要因(大きくする理由)
| 要因 | 適用理由 |
|---|---|
| データベーストランザクション | ACIDトランザクションを維持したい |
| ワークフローとコレオグラフィ | サービス間の呼び出し連鎖を減らしたい |
| 共有コード | 共有ライブラリの管理コストを避けたい |
| データ関係 | テーブル間の関係を分断したくない |
粒度の判断とは、この2つの力のどちらが強いかを見極める作業だ、というのが本書の立場です。「1つのサービスは1つのことをすべき」といった標語より、はるかに運用可能な判断基準になっています。
第II部:つなぎ合わせる
8章 再利用パターン
分散システムにおけるコード再利用の手段を4つ比較します。
- コードレプリケーション:同じコードを各サービスにコピーする
- 共有ライブラリ:ビルド時に依存させる
- 共有サービス:実行時に呼び出す
- サイドカー/サービスメッシュ:横断的関心事を別プロセスに寄せる
とくにサイドカーの扱いが印象的でした。ログ、監視、認証、サーキットブレーカーといった運用上の関心事は、ドメインロジックとは性質が異なるため、共通の基盤として切り出す価値が高い、という整理です。
一方で、ドメインロジックの共有については慎重な立場を取ります。再利用は結合を生み、結合はデプロイ単位を縛るからです。「再利用はどのようなときに価値が生まれるか」という節が独立して置かれているのは象徴的で、再利用は目的ではなく手段だという当たり前のことを、改めて言語化してくれます。
9章 データの所有権と分散トランザクション
テーブルの所有者を決める章です。基本原則は、書き込みを行うサービスがそのテーブルを所有する、というものです。
- 単独所有:1サービスが書き込む。最も単純
- 全体共有:多数のサービスが書き込む。共通データサービスの導入などで対処
- 共同所有:2〜3サービスが書き込む。テーブル分割/データドメイン/委譲/サービスコンソリデーションの4つの解法を比較
後半は分散トランザクションの話で、結果整合性を実現する3つのパターンが提示されます。
- バックグラウンド同期パターン:バッチで後から揃える
- リクエストベースのオーケストレーションパターン:リクエスト内で調整役が揃える
- イベントベースパターン:イベント駆動で伝播させる
境界づけられたコンテキストを跨いでバックグラウンド同期を使うとコンテキスト境界を壊す、といった指摘があり、DDDの語彙と接続されています。
10章 分散データアクセス
自分が所有していないデータを読む手段の比較です。
| パターン | 概要 |
|---|---|
| サービス間通信 | 所有サービスに問い合わせる |
| 列スキーマレプリケーション | 必要な列を自分のテーブルに複製する |
| レプリケーションキャッシュ | インメモリキャッシュを複製して保持する |
| データドメイン | 複数サービスで所有するデータドメインを共有する |
それぞれに結合度・データ量・スケーラビリティ・整合性・パフォーマンスのトレードオフが整理されています。「読むだけだから」と安易にサービス間通信を選ぶと、ネットワーク遅延と可用性の連鎖が発生する、という話は身に覚えのある方も多いはずです。
11章 分散ワークフローの管理
オーケストレーションとコレオグラフィの比較です。
- オーケストレーション:中央の調整役がワークフローを指揮する。状態管理とエラー処理が集中し、可読性が高い。一方でボトルネックになりやすい
- コレオグラフィ:各サービスが次のサービスを呼び出す、あるいはイベントに反応する。結合は緩いが、状態がどこにあるのか分かりにくくなる
コレオグラフィでワークフローの状態を管理する方法として、フロントコントローラー(最初のサービスが調整役を兼ねる)、ステートレスコレオグラフィ、スタンプ結合(メッセージに状態を載せる)の3つが提示されます。
12章 トランザクショナルサーガ ― 本書の白眉
2章で定義した動的結合の3次元(通信/整合性/調整)を掛け合わせると、8通りの組み合わせが得られます。本書はそれぞれに名前を与え、体系的に比較します。
| パターン名 | 通信 | 整合性 | 調整 |
|---|---|---|---|
| エピックサーガ (sao) | 同期 | アトミック | オーケストレーション |
| 伝言ゲームサーガ (sac) | 同期 | アトミック | コレオグラフィ |
| おとぎ話サーガ (seo) | 同期 | 結果整合性 | オーケストレーション |
| 時間旅行サーガ (sec) | 同期 | 結果整合性 | コレオグラフィ |
| ファンタジーサーガ (aao) | 非同期 | アトミック | オーケストレーション |
| ホラーストーリーサーガ (aac) | 非同期 | アトミック | コレオグラフィ |
| パラレルサーガ (aeo) | 非同期 | 結果整合性 | オーケストレーション |
| アンソロジーサーガ (aec) | 非同期 | 結果整合性 | コレオグラフィ |
カッコ内は3次元の頭文字(synchronous / asynchronous、atomic / eventual、orchestrated / choreographed)です。名前を暗記させるのが目的ではなく、8通りの組み合わせが漏れなく存在することを示すための命名だと明言されています。
各パターンは結合度・複雑さ・応答性/可用性・スケール/弾力性の4軸で評価されます。傾向としては次の通りです。
- 最も馴染み深いエピックサーガは、モノリスの挙動を模倣するため理解しやすい反面、結合度が最も高く、スケールと弾力性が最も低い
- 非同期・アトミック・コレオグラフィという組み合わせのホラーストーリーサーガは、名前の通り最も扱いが難しい
- おとぎ話サーガや時間旅行サーガのように、結果整合性を受け入れると評価が大きく改善する組み合わせがある
「分散トランザクションは避けられるなら避けたほうがよい」という結論そのものは目新しくありません。ただ、なぜそうなるのかを8パターンの比較として提示されると、納得の度合いがまったく違います。
13章 コントラクト
サービス間の取り決めを、厳格なコントラクトと緩いコントラクトの軸で整理します。
- 厳格なコントラクト(gRPC、GraphQLスキーマ、SOAPなど):型が保証され、契約違反を早期に検出できる。一方でバージョン管理と密結合を招く
- 緩いコントラクト(名前と値のペア、スキーマレスなJSONなど):進化しやすく結合が緩い。一方で契約の検証が難しい
緩いコントラクトの検証手段としてコンシューマー駆動コントラクトが紹介されます。
もう一つの主題が スタンプ結合 です。必要以上に大きなペイロードを渡すことで、実際には使わないフィールドまで結合してしまう問題です。ただし本書は、スタンプ結合を単純な悪とはしません。ワークフローの状態をメッセージに載せて運ぶ用途では、コレオグラフィにおける有効な選択肢になり得る、と両面から評価します。この「アンチパターンにも使いどころがある」という姿勢が、本書らしいところです。
14章 分析データの管理
分析系データの扱いを、歴史的な変遷とともに追います。
- データウェアハウス:中央集権的に統合するが、ドメイン知識が極端に分断される
- データレイク:変換を後回しにするが、場当たり的な変換が積み上がる
- データメッシュ:ドメインごとにデータをプロダクトとして所有する
データメッシュの中核として登場するのが データプロダクト量子(DPQ) です。運用系サービスの隣に、そのドメインの分析用データを提供する独立した量子を置く、という構成です。マイクロサービスの原則を分析データの世界に適用したものだと理解すると腑に落ちます。
トレードオフとしては、DPQとのコントラクト調整が必要になること、非同期通信と結果整合性を前提とすること、が挙げられています。データメッシュの提唱者本人が著者に加わっているだけあり、記述は具体的です。
15章 独自のトレードオフ分析を構築する
締めくくりは、本書で示したパターンを超えて、自分でトレードオフ分析を行うための方法論です。ここが本書の主題そのものだと言えます。
提示される手順は次のようなものです。
- 絡み合う次元を発見する — 何と何が結合しているのかを見つける
- 結合点を分析する — 変更が伝播する接点を特定する
- トレードオフを評価する — 各次元を独立に評価する
そして分析を歪めないための実践的な注意点が続きます。
- 定性的分析と定量的分析:分散システムでは測定できないことが多いため、定性的な評価に頼らざるを得ない場面がある
- MECEリスト:比較対象が漏れなく重複なく並んでいるかを確認する
- 「コンテキスト外」の罠:一般論として優れた選択肢が、自分の文脈では劣ることがある
- 関連するドメインのシナリオをモデル化する:抽象論ではなく具体的なユースケースで比較する
- 根拠は示し過ぎず、肝心なものに絞る:ステークホルダーに全部見せると判断できなくなる
- 過度な売り込みやエバンジェリズムを避ける:アーキテクトは技術の伝道師ではない
とくに「根拠を示し過ぎない」と「エバンジェリズムを避ける」の2点は、技術者としてのコミュニケーションに関わる指摘です。トレードオフ表を作る技術と、それを人に伝える技術は別物だという当たり前の事実を、最後に念押しされた気分になりました。
印象に残ったポイント
1. 「アーキテクトの答えはすべて『場合による』」を実装可能にした
「場合による」で終わらせず、その「場合」を構成する変数を洗い出し、名前を付け、表にする。本書がやっているのはこれに尽きます。トレードオフ表という成果物の形が具体的に示されているので、明日から真似できます。
2. データがアーキテクチャの一級市民として扱われている
アーキテクチャの本でありながら、DB種別の選定、テーブルの所有権、分散データアクセス、分析データまでを射程に収めています。サービス分割の議論がデータ分割の議論と不可分であることを、構成そのもので示しています。
3. パターン名を覚えさせようとしていない
サーガの8パターンには奇妙な名前が付いていますが、著者らは「暗記させたいわけではない」と明言しています。重要なのは3次元の組み合わせが8通りある、という構造のほうです。この誠実さは好感が持てました。
4. 意思決定を記録する文化への接続
各判断にADRが添えられ、付録Bにすべてがまとめられています。「なぜこの構成なのか」が失われたシステムの保守で苦労した経験があると、この付録の価値は身に染みます。
実務でどう使うか
読了後、自分の手元で使えそうだと感じたのは次の3点です。
分割の議論を3次元に分解する
「非同期にするか」「整合性をどこまで求めるか」「調整役を置くか」は独立した論点です。まとめて議論すると空中戦になるので、分けて合意を取っていくだけで会議の質が変わりそうです。
分解要因と統合要因を対で並べる
粒度でもデータでも、本書は必ず「分ける理由」と「分けない理由」を対で提示します。設計レビューのテンプレートとして、この形式はそのまま使えます。片側だけ並べた資料は結論が先にある資料だ、という自己点検にもなります。
ADRに「検討したが採用しなかった案」を残す
採用案だけを書いたドキュメントは、半年後に読むと「なぜ他の選択肢を選ばなかったのか」が分からなくなります。トレードオフ表をそのままADRに添付するのが、最も安価な対策になりそうです。
どんな人におすすめか
| 読者 | おすすめ度 | コメント |
|---|---|---|
| モノリスの分割を検討中の方 | ◎ | 4〜7章がそのまま計画書の骨子になります |
| すでにマイクロサービスを運用中の方 | ◎ | 9〜13章で現在の設計を検証できます |
| データ基盤に関わる方 | ○ | 6章と14章が該当します |
| アーキテクチャを学び始めた方 | △ | 先に『ソフトウェアアーキテクチャの基礎』を読むのがおすすめです |
本書は前著『ソフトウェアアーキテクチャの基礎』の用語を前提としており、付録Aに対応表が用意されています。コナーセンス、アーキテクチャ特性、レイヤードアーキテクチャといった語彙に馴染みがないと、読み進めるのに苦労するかもしれません。
併読するなら次の順序が良さそうです。
- 『ソフトウェアアーキテクチャの基礎』(語彙と基礎)
- 『ソフトウェアアーキテクチャ・ハードパーツ』(本書・トレードオフ分析)
- 『データメッシュ』『マイクロサービスパターン』(各論の深掘り)
まとめ
本書は、分散アーキテクチャの「答え」を教えてくれる本ではありません。むしろ、答えがないことを前提に、それでも決断しなければならない立場の人間が、何をどう検討すればよいかを示す本です。
読み終えて一番残ったのは、8つのサーガパターンでも6つの分解パターンでもなく、「絡み合う次元を発見し、結合点を分析し、トレードオフを評価する」という3ステップでした。パターンは陳腐化しますが、この手続きは残ります。著者らが最終章にこれを置いたのは、そういう意図だと受け取りました。
分散アーキテクチャの設計判断に手応えのなさを感じている方には、強くおすすめできる一冊です。
参考
- ソフトウェアアーキテクチャ・ハードパーツ ―分散アーキテクチャのためのトレードオフ分析(オライリー・ジャパン、2022)
- ソフトウェアアーキテクチャの基礎 ―エンジニアリングに基づく体系的アプローチ(オライリー・ジャパン、2022)