概要
オライリーから出ている 「ソフトウェアアーキテクチャ・ハードパーツ」
を読んだので、重要な章を抜き出してノウハウをメモする。
と言いたいところだが、重要な部分が多すぎるのでこの記事では書きやすい部分だけを抜き出している。
書籍の内容を拾いきれているとは到底言えないので、是非読んでもらいたい。
ある程度システム設計に明るく、アーキテクチャに課題を抱えている人にはぴったりな内容になっていると感じた。
1章 「ベストプラクティス」がないとどうなる?
全ての解決策はトレードオフである。
アーキテクトは、自分の問題に対する「銀の弾丸」を探し求めてはならない。
アーキテクトの問題はそれぞれユニークなため、ベストプラクティスが存在しない。
だからこそ「ハード」パーツである。
- 難しい問題
- 堅い、システムの土台となる部分
決して最善のアーキテクチャを狙ってはいけない。むしろ、少なくとも最悪でないトレードオフの組み合わせを狙おう。
多くのアーキテクチャにおいて、データこそが全てである。
アーキテクチャデシジョンレコード(Architecture Decision Records:ADR)(https://adr.github.io)を記入せよ。
アーキテクチャ統制のため、アーキテクチャ適応度関数を設計、運用せよ。
2章 ソフトウェアアーキテクチャにおける結合の見分け方
結合の定義
一方の変更が他方の変更を引き起こす可能性がある場合、ソフトウェアシステムの2つの部分は結合している。
結合を発見、分析し、トレードオフを評価せよ。
アーキテクチャ量子の定義
アーキテクチャ量子とは、高度な機能的凝集、高度な静的結合、同期/非同期による動的結合を持つ、独立してデプロイが可能なアーティファクトを指す。アーキテクチャ量子の一般的な例には、あるワークフロー内の整ったマイクロサービスなどがある。
これはすなわち、データベースを共有しているアプリケーションは全て1つのアーキテクチャ量子である。
4章 アーキテクチャの分解
モノリスからサービスベースアーキテクチャを経てマイクロサービスへ移行していく上で、2つのアプローチが紹介されている。
- コンポーネントベース分解
- まずはリファクタリングし、モジュールを分けていく。
- 分けられたモジュールをサービスに切り出す。
- 戦術的フォーク
- まるっと別アプリケーションとしてコピーして立て、それぞれ1部の機能しか使っていない状態にする。
- その後、不要な機能をリファクタリングによって削除していく。
- コンポーネントベース分解と比べて
- メリット
- 事前の分析が不要なので作業開始が早い
- コードは抽出するより消す方が簡単 (と書かれていたが本当か?)
- デメリット
- 不要なコードを消す努力が必要
- ロジックは汚いまま
- メリット
6章 業務データの分解
データベースを分けるか?分けないか?もトレードオフである。
データを分解する要因として以下のようなものがある。
- 変更制御
- カラムの変更等の影響が多岐にわたる
- コネクション管理
- 1つのデータベースだけを使うとコネクション数の管理が難しい
- スケーラビリティ
- コネクション数
- 容量
- スループット
- パフォーマンス
- 耐障害性
- 1つのデータベースだけを使うとデータベースが単一障害点となってしまう
- アーキテクチャ量子
- 1つのデータベースだけを使うと1つのアーキテクチャ量子となってしまう (つまり独立してデプロイできない、等)
- データベース種別の最適化
- 1つのデータベースだけを使うと1つの保存方法だけしか使えない (つまりデータ特性ごとに最適な選択肢が取れない)
逆に、データを統合する要因としては以下のようなものがある。
- データ関係
- 密結合な外部キー等があるか?
- トランザクション
- 単一のトランザクション単位が必要か?
モノリスなデータベースを分解するには5段階のプロセスを踏むと良い。
- 分析し、ドメインを特定する
- ドメインごとにテーブルを割り当て、移動する
- コネクションをドメインごとに分離する
- スキーマをそれぞれのデータベースに移動する
- コネクションを切り替える
7章 サービスの粒度
マイクロサービスの粒度を大きくするか?小さくするか?もトレードオフである。
粒度を小さくする要因としては以下のようなものがある。
- サービスの範囲と機能
- 凝集性が高い状態になっているか?
- コード変動率
- 一部のコードだけ変更頻度が高くないか?
- スケーラビリティとスループット
- 一部だけスケールする必要があるか?
- 耐障害性
- 一部の故障で全体が故障してしまわないか?
- セキュリティ
- 一部だけ高いセキュリティが必要か?
- 拡張性
- どの程度拡張されるか?
粒度を大きくする要因としては以下のようなものがある。
- トランザクション
- サービスをまたいだトランザクションが必要か?
- ワークフローとコレオグラフィ
- サービス同士がやりとりする必要はあるか?
- 共有コード
- サービス同士がコード共有の必要はあるか?
- データ関係
- データは分解できるか?
9章 データの所有権と分散トランザクション
サービス間で共有するデータが存在するとき、どちらのサービスが所有権を持つのか、どのように共有データを管理するのかをトレードオフによって決めなければならない。
分散トランザクションはACID特性をサポートしないため、代わりに結果整合性を検討せよ。
10章 分散データアクセス
所有していないデータにサービスが読み取りアクセスするためには様々な方法があり、その間にもトレードオフがある。
- サービス間通信パターン
- サービス間がWEB API等で通信してDBを隠蔽する
- 列スキーマレプリケーションパターン
- 非正規化する
- レプリケーションキャッシュパターン
- 分散キャッシュする
- データドメインパターン
- 愚直に一緒にDBを見てしまう
11章 分散ワークフローの管理
分散システムどうしを調整する方法については基本的には2種類あり、トレードオフがある。
- オーケストレーション
- 調整役を別途立てる
- コレオグラフィ
- 最初のサービスが調整役となる
12章 トランザクショナルサーガ
通信、整合性、調整についてそれぞれ2パターンあり、組み合わせると合計8パターンのサーガ (アーキテクチャの大別) がある。
パターン名 | 通信 | 整合性 | 調整 | 結合度 | 複雑さ | 応答性/可用性 | スケーラビリティ |
---|---|---|---|---|---|---|---|
エピックサーガ | 同期 | アトミック | オーケストレーション | とても高い | 低い | 低い | とても低い |
伝言ゲームサーガ | 同期 | アトミック | コレオグラフィ | 高い | 高い | 低い | 低い |
おとぎ話サーガ | 同期 | 結果整合性 | オーケストレーション | 高い | とても低い | 中程度 | 高い |
時間旅行サーガ | 同期 | 結果整合性 | コレオグラフィ | 中程度 | 低い | 中程度 | 低い |
ファンタジーサーガ | 非同期 | アトミック | オーケストレーション | 高い | 高い | 低い | 低い |
ホラーストーリーサーガ | 非同期 | アトミック | コレオグラフィ | 中程度 | とても高い | 低い | 中程度 |
パラレルサーガ | 非同期 | 結果整合性 | オーケストレーション | 低い | 低い | 高い | 高い |
アンソロジーサーガ | 非同期 | 結果整合性 | コレオグラフィ | とても低い | 高い | 高い | とても高い |
13章 コントラクト
ハードパーツとしてのコントラクトの定義は以下である。
アーキテクチャの部品が情報や依存関係を伝えるために使用するフォーマット。
コントラクトとして例えば以下の様なものがあり、トレードオフがある。
- 堅い
- 例
- gRPC
- メリット
- 型
- バージョニング
- 検証が用意
- ドキュメント
- デメリット
- 密結合
- 例
- 緩い
- 例
- JSON
- メリット
- 疎結合
- 進化しやすさ
- デメリット
- 型がない
- コンシューマ駆動契約等の適応度関数が必要
- 例
帯域幅は無限だと思うな。
15章 独自のトレードオフ分析を構築する
MECEに分析せよ。
技術の過度な売り込みを避けよ。
何かを伝道する立場をとってはいけない。トレードオフに立ち返ろう。
銀の弾丸を追い求めるのではなく、トレードオフを分析するスキルに磨きをかけることで、アーキテクトは組織に真の価値を提供できるのだ。
まとめ
アーキテクトというふわっとした分野において地に足ついた良い本だった様に感じた。
全てはトレードオフである、というのは自分も読む前から感じていたことではあったため、裏付けが取れて嬉しい気持ちになった。
そして、そのトレードオフをこれでもかと投げつけてくる本書は実際にアーキテクチャを考える上で非常に参考になるだろう。
最近「マイクロサービスって間違いだったんじゃね?」等が話題になったりもしたが、そういうことに振り回されず淡々とトレードオフを分析できるエンジニアになりたい。