リリース直前に見つかるバグには典型的なものがあります。フロントエンドは割引率を10%、バックエンドは15%で計算する、文書では必須のフィールドが実際のAPIから消えている、といったケースです。コード自体はどちらも正常です。問題は同じ情報が2か所に存在し、一方だけが変更されたことです。
こうした事故を構造的に防ぐ原則がSingle Source of Truth、略してSSOTです。名前は大げさですが、内容は一文で済みます。すべての情報片には、権威ある原本が正確に1つだけ存在しなければならない。
要点をまとめます。
- SSOTは「情報の原本は1つ」という原則であり、保存先を1つに限定する意味ではない
- 重複した情報は必ず食い違う。問題は食い違った瞬間ではなく、どちらが正しいか誰にも分からなくなる瞬間だ
- コピーが必要なら「派生物」として作る。手で2回書かず、原本から自動生成する
- キャッシュや複製はSSOT違反ではない。原本の場所と更新方向が明確ならよい
なぜ重複は必ず食い違うのか
情報を2か所に置いた瞬間、同じ状態を保つ責任は人に移ります。ツールもコンパイラもその約束を知らないからです。修正のたびに「この値はほかのどこにあったっけ」と覚えておく必要があり、一度でも忘れれば2つの値は別の道を進みます。
さらに厄介なのは、食い違った後です。コード2か所で定数が異なる値になっていても、どちらが正しいかはコードだけでは分かりません。gitの履歴を調べ、当時の担当者を探し、企画文書を確認する考古学が始まります。SSOT崩壊の本当のコストはバグ修正ではなく、「どれが真実か」を判定する時間です。
よくある例をいくつか見てみましょう。
- 定数の重複: 最大アップロードサイズ10MBを、フロント検証・バックエンド検証・エラーメッセージにそれぞれハードコード
- 検証ロジックの重複: メール形式の検証を、クライアントとサーバーが異なる正規表現で実行
- 文書とコード: API仕様書と実装が別々。数か月後、文書は小説になる
- DBとキャッシュ: 原本更新後のキャッシュ無効化を忘れ、古いデータを配信し続ける
- デザインとコード: デザイン案の色値とアプリにハードコードした色値が微妙に異なる
形は違っても構造は同じです。原本が2つあり、同期が人の手に依存しています。
原則は「コピー禁止」ではなく「派生」
SSOTを「情報は1か所だけに保存すること」と誤解しがちです。するとキャッシュもリードレプリカもビルド成果物も違反に見えます。実際の原則は異なります。複数か所に存在してもよい。ただし原本は1つで、残りはすべて原本から派生しなければならない。
派生物を作る代表的な方法がコード生成です。
- スキーマから型を生成: OpenAPI仕様からクライアント型とサーバースタブを生成すれば、仕様が原本となり、文書とコードが食い違う余地がなくなる
- デザイントークン: 色とタイポグラフィを1つのトークンファイルに定義し、iOS・Android・Webコードを個別に生成する
- 共有定数モジュール: フロントエンドとバックエンドが同じパッケージから定数をimportするようにし、ハードコードのコピーを根本から防ぐ
- コードから文書を抽出: コメントや型からAPI文書を生成すれば、文書は常にコードに追従する
共通しているのは、「人が2回書く」箇所を「機械が1回生成する」箇所に変えることです。同期の責任が人の記憶からビルドパイプラインへ移り、食い違えばCIが先に気づきます。
キャッシュや複製も同じ枠組みで整理できます。原本の場所が宣言され、更新が原本→コピーの一方向だけに流れ、コピーが古くなり得る時間(TTL・無効化戦略)が定義されていれば、SSOTは守られています。違反は「コピーが存在するとき」ではなく、「コピーを直接変更し始めたとき」に起きます。
組織にも同じ原則を適用する
SSOTはコードだけの話ではありません。マイクロサービス設計で「このデータの所有者はどのサービスか」を決めること、社内Wiki・Notion・Slackに散在するポリシー文書から「公式版」を指定することも、すべて同じ問題です。
特に文書はコードより食い違いやすいものです。コンパイラもテストもないからです。だから組織レベルのSSOTでは、ツールより合意が先です。「オンボーディング手順の原本はWikiのこの1ページで、ほかにはリンクだけ置く」といったルールです。コピーの代わりにリンクを置くことが、文書世界の派生です。
実践チェックリスト
明日から適用できる判断基準にまとめると、次のとおりです。
- 同じ値を2回目に入力する瞬間がサイン: 定数・検証ルール・設定値をコピーしているなら、共有モジュールへ移すか生成に変えられないか、まず検討する
- 原本を宣言する: キャッシュ・複製・要約自体は問題ではない。「原本はここ」とコードと文書に明記され、更新が一方向か確認する
- 食い違いを人ではなくツールに検出させる: スキーマ検証、契約テスト、生成コードのdiffチェックをCIに入れれば、同期失敗がマージ前に判明する
- 完璧主義には注意する: すべての重複をなくそうと過剰な抽象化を作れば、それ自体がコストになる。頻繁に変わる情報や、食い違うと損失が大きい情報からSSOTを整える
リファクタリングでいうDRY(Don’t Repeat Yourself)原則と根は同じです。DRYがコードロジックの重複を対象にするのに対し、SSOTはデータや知識の重複まで広げた上位原則といえます。次に「この値はあちらにもあるが、一緒に直すべきか」と思ったら、そこがSSOTを整える場所です。

