生成AIで重要性が増す、システムのレバレッジポイント
『Staff Engineer』で紹介されていた「システムのレバレッジポイント」が非常に印象的で有用だと感じた。
経験上「ミスるとじわじわ効いてくる」と感じていたポイントだったし、生成AI時代にも通用する内容だと考えたからだ。
原文はこちら にあるが、あまり詳細な説明は書かれていないため、自身の解釈や補足を添えて、思考を整理したい。
システムのレバレッジポイントとは
一言で表現すると「一度決めると変えづらいが、システム全体の変更コストや品質に長く効き続ける部分」のこと。
原文では以下の 3 つがレバレッジポイントとして挙げられている。
- インターフェース
- 状態管理
- データモデル
そして、これらに共通する特徴として以下のようなものが挙げられる。
- レバレッジポイント自体は、変更コストが大きい
- 将来の開発コストやバグの件数などは、レバレッジポイントの設計によって何倍にも左右される
そのためアーキテクチャレビューや技術的意思決定の場では、このレバレッジポイントを見る価値が大きい。
インターフェース
原文の日本語訳は以下。
インターフェースはシステム間の契約である。
効果的なインターフェースは、クライアントをカプセル化された実装から切り離す。
耐久性のあるインターフェースは、根底にある本質的複雑性をすべて露出させ、偶発的複雑性は一切露出させない。
優れたインターフェースは、熱心に見極め、見極めながら熱心である。
インターフェースについて、自身の経験・考えは以下の通り。
インターフェースとはシステムやモジュールの接続点であり、優れたインターフェースを備えたシステムは変更に強くなる。
優れたインターフェースは仕様変更の影響範囲を最小限に抑えてくれるため、設計・実装・テストの工数も抑えることができる。
インターフェースがイマイチだと僅かな変更でも多くの箇所に影響が及び、計画や影響調査すら大変になる。
インターフェースを変更するコストは大きい。
例えばシステム間のAPIを変更する場合、チームを横断して調整・周知・テスト・リリースが必要となる。
そのためインターフェース仕様の変更は発生回数が少ないほうが好ましく、変更する場合は後方互換性を保つことが望ましい。
状態
原文の日本語訳は以下。
状態は、あらゆるシステムにおいて変更が最も困難な部分である。
そしてその変更への抵抗が、状態を持つシステムをもう一つの重要なレバレッジポイントにしている。
状態は他のシステムよりも速く複雑化し、後から改善するには比較的コストがかかる慣性を持つ。
セキュリティ、プライバシー、コンプライアンスに関するビジネス上の義務を組み込むと、状態を持つシステムの変更はさらに困難になる。
状態について、自身の経験・考えは以下の通り。
最も重要なのは、むやみに状態を増やさないことである。その理由は大きく2つある。
1つ目は、状態を減らすには既存のデータの移行や変換が必要であり、設計で考慮すべき事項が増えるということ。
状態を増やすのは簡単だが、減らそうと思うと高くつくということだ。
もう1つの理由は、複雑性は状態数の2乗に比例すること。これは状態遷移表でのパターン設計をイメージすれば分かりやすい。
状態遷移表のセルが多くなるということは、それだけ考慮すべきパターンが増加するということだ。
当然、障害対応などで不正な状態が発生した場合にも、復旧に向けて考慮すべきパターンは増加する。
またステート(State)とステータス(Status)を区別し、DBにはステートを持たせることも重要である。
- ステート(State): DB やストレージに保持する、生データ的な状態
- ステータス(Status): ビジネスロジック側で解釈した、今こういうフェーズにいるというラベル
DBにはステートだけを記録し、APIやアプリケーションでステートを解釈して表示用のステータスに変換するのが理想的。
ついステータスをDBに持たせてしまうと「日付を跨いだ瞬間にバッチ処理で遅延に書き換え」などの処理を行うことになる。1
データモデル
原文の日本語訳は以下。
データモデルは、インターフェースと状態の交差点である。
それは、あなたの状態を持つシステムの能力を、アプリケーションが正当とみなすものに制約する。
優れたデータモデルは厳格である:真に支援できることだけを露出させ、無効な状態の表現を防ぐ。
優れたデータモデルは、時間の経過とともに進化することに寛容である。
効果的なデータモデルは、巧妙さよりも明快さを選ぶ。
データモデルについて、自身の経験・考えは以下の通り。
最も重要なのは、極力データの不整合が起こらないようなデータモデルやスキーマ設計にすることである。
できるだけRDBレベルで制約を持たせることで、堅牢な設計にすることができる。
アプリケーションコードのバリデーションだけだと、別経路から混入したり、データ移行時のパッチなどで壊れることがある。
また制約だけでなく「ありえない組み合わせ」をスキーマ上で許さないような設計も重要だ。
例えば「カラムAとカラムBはどちらかしか使わず、もう片方は必ず NULL にする」といったデータ構造は不整合の温床となる。
このようなデータ構造を排除したデータモデルに落とし込むことが鍵となる。
レバレッジポイントを意識すると効果的な場面
レバレッジポイントは以下のような場面で効果的だと考えている。
- システムの引き継ぎ
- チームに入って何もわからないとき
- チーム外からレビューなどを通じて品質を担保したい場合
引き継ぎ・レクチャー・レビューでは使える時間が限られていることが多く、短時間で最大の効果が期待される。
このような場面ではレバレッジポイントを意識することで大きな成果を得られる。
生成AI時代におけるレバレッジポイントの重要性
生成AIが活用されるようになったいま、レバレッジポイントの重要性はさらに高くなると考える。その理由は以下の通り。
- AIによるコード生成スピードが上がるため、レバレッジポイントの影響を受けるコードが増加する
- シンプルな変更であればAIで完結できる作業を、人間が介入しなければならなくなる
- 他チームとの調整、障害対応や復旧作業は人間が行う必要がある
レバレッジポイントを雑に決めたり成り行きで決めたりせず、しっかりと設計・意思決定することが重要になる。
状態をあまり意識せずにコーディングエージェントで実装すると、破綻した状態設計になってしまったこともある。
その際は結局自分で状態を読み解いて修正し直すことになったため、予め設計したほうが効率的である。
状態の定義などはAGENT.mdやCLAUDE.mdに書くことで、少ないトークン数で大きな効果を得られるだろうと考えている。
おわりに
もっと前にレバレッジポイントを知っていれば、もっとうまくできた場面は多かったと感じている。
生成AI時代のエンジニアはアーキテクトの役割が大きくなると考えているため、今後は意識的にコントロールしていきたい。
なお個人的には第4のレバレッジポイントとして システム間の依存関係 を推したいと考えている。
これについては、また機会があれば書いてみようと思う。
もちろん一瞬で書き換えることはできないので、一時的に正しいデータが参照・表示できないことになる ↩︎