1行の変更は、どこまで届くか:影響分析のやり方【第4回】
この記事を読み終えると、変更を入れる前に波及範囲を4方向で洗い出し、grepでは見つからない参照を見つける方法を持ち、「消す変更」を安全に進める段取りを説明できるようになります。ジュニアエンジニア向け 成果の出し方シリーズ(全12回)の第4回です。
🎯 テーマの主役:「影響分析」
今回の主役は影響分析(change impact analysis)です。一言で言えば、影響分析とは「この変更によって、何が壊れうるかを、変更する前に列挙する作業」です。壊してから気づく作業ではありません。壊す前に見積もる作業です。
日常の例えで言うなら、建物の配管工事です。ある部屋の水道管を止めたいとき、配管工はその部屋のバルブだけを閉めません。まず配管図を見ます。同じ系統につながっている部屋はどこか。上の階に影響は出ないか。給湯と給水は別系統か。配管図がない建物で工事をするのは、事故を前提にした作業です。そして、図面を見ずに「たぶん大丈夫」で締めたバルブが、別の階の業務を止める——これが、ソフトウェアで毎日起きていることです。
エンジニアリングの世界では、これを「1行の変更が誰を壊すか」という問いに置き換えます。1行の変更が1人を壊すことも、100万人を壊すこともあります。そして重要なのは、壊れる範囲は変更の行数に比例しないことです。1行の変更が全サービス停止を引き起こした事例は、毎年のように報告されています。
この記事の仮説はこうです。変更の安全性は「慎重さ」ではなく「配管図を持っているかどうか」で決まる。したがって影響分析とは、気合いではなく、依存関係を列挙する手順である。もしこれが正しければ、あなたが身につけるべきは注意深さではなく、調べる順番になります。
なお第3回で扱った切り分けの技術は、そのまま影響分析の道具になります。第3回は「壊れた後」に候補を消す技術でしたが、今回は「壊す前」に候補を列挙する技術です。同じ依存関係の知識を、逆向きに使うだけです。
動機:「影響範囲は?」と聞かれて答えられない
ジュニアエンジニアが設計レビューやリリース前確認で必ず聞かれる質問があります。「これ、影響範囲は?」です。
この質問に「この機能だけです」と答えて、後で別の機能が壊れる。あるいは「たぶん大丈夫です」と答えて、上長の顔が曇る。この経験は、多くの人が通る道です。そして厄介なことに、影響範囲の見落としは、本人には見えません。見えていないものは、見ようとしない限り見つかりません。
第3回(scope change の回・理不尽シリーズ)で、変更は「追加・変更・削除」の3種類があり、削除が最も高くつくと書きました。この記事はその続きです。なぜ削除が高くつくのか——それは削除の影響範囲が最も見えにくいからです。追加は「使われていなければ影響なし」と言えますが、削除は「使われていない」ことの証明が必要になります。そして使われていないことの証明は、使われていることの証明より難しいのです。
この記事のゴールは、「影響範囲は?」に対して、根拠のある答えを返せるようになることです。
🔍 検証①:変更は4方向に波及する
まず、波及の方向を整理します。変更の影響は4方向に広がります。これを全部見れば、見落としは激減します。
下流(呼び出し先)は、あなたの変更が使っているものです。あなたが関数の仕様を変えれば、あなたの呼び出し方が壊れる可能性があります。これは自分で気づきやすい方向です。
上流(呼び出し元)は、あなたの変更を使っているものです。関数の引数を変えれば、呼び出している全員が壊れます。ここが最も見落とされます。第1回(CS入門・階層モデル)で扱ったとおり、上の階はあなたの変更に気づけません。
横(同じものを使っているもの)は、同じ資源を共有している相手です。同じテーブル、同じ設定値、同じキャッシュ、同じ外部API。あなたの変更が、関係ないと思っている機能を壊します。
時間(過去と未来)は、すでに作られたデータと、これから動く予定のものです。過去に保存されたデータが新しい形式を読めない、3か月後に動くバッチが古い前提で書かれている。時間方向の影響は、誰も見ていないので最も遅れて発覚します。
| 方向 | 内容 | 見つけ方 | 見落としやすさ |
|---|---|---|---|
| 下流 | 自分が使っているもの | コードを読めば分かる | 低い |
| 上流 | 自分を使っているもの | 参照検索・呼び出し元の列挙 | 中 |
| 横 | 同じ資源を共有しているもの | テーブル・設定・APIの利用者一覧 | 高い |
| 時間 | 過去のデータ・将来の予定 | データの中身・スケジュール・期限の確認 | 最も高い |
「横」と「時間」を見る習慣が、ベテランとジュニアの差になりやすい部分です。コードを読めば分かる範囲(下流と、せいぜい上流)で止まらず、「同じものを使っている人は誰か」「過去と未来は大丈夫か」まで問うてください。
🔍 検証②:上流は「検索して出てこない場所」に隠れている
次に、上流の探し方です。ここが実務の核心です。
参照検索(grepやIDEの「参照を検索」)で出てこない呼び出しが、世の中には大量にあります。これを知らないと、「検索して0件だったから安全」と判断して事故を起こします。
見つからない参照の代表例を並べます。動的な呼び出し(文字列でメソッド名を組み立てて呼ぶ、設定ファイルに書かれたクラス名を読み込む)。設定ファイルやデータベースの中(コードではないのでコード検索に出ません)。SQLやビューやストアドプロシージャ(アプリのコードの外側)。外部システムとの連携(他チームのサービスが、あなたのAPIを呼んでいる)。シリアライズされたデータ(過去に保存されたJSONやバイナリが、古い形式の前提で読まれる)。テンプレートやシートやドキュメント(社内の手順書、表計算、BIツールのダッシュボード)。
そして最後の「人の記憶」が最も厄介です。「このバッチは、あの人が手で動かしている」という情報は、どこにも書かれていません。だから影響分析では、人に聞くという作業が省略できません。第7回(理不尽シリーズ・レガシーコード)で「退職者に聞く」と書いたのと同じ理由です。コードに書かれていない依存は、人にしか分かりません。
🔍 検証③:「消す」変更は、証明の仕事になる
次に、変更の種類による難易度差を見ます。第3回(理不尽シリーズ)で扱った追加・変更・削除の3種類は、影響分析の難易度がまったく違います。
追加は最も安全です。既存の挙動を変えなければ、影響範囲は「新しい部分」に限定されます。ただし例外があります。同じ名前を使ってしまう(既存の関数名・テーブル名・設定キーと衝突する)、同じ資源を取り合う(同じテーブルを重く使う、同じ外部APIのレート制限を食う)。追加でも、横方向の影響は起こりえます。
変更は中程度です。インタフェースを変えるか、中身だけ変えるかで難易度が変わります。インタフェース(引数・戻り値・形式・エラー)を変えるなら、上流の全列挙が必要です。中身だけなら、同じ入力で同じ出力かを確かめれば済みます(これを振る舞いの保存と呼びます)。
削除が最も危険です。理由は先に書いたとおりで、「使われていない」ことの証明が必要になります。そして証明には3つの根拠が要ります。検索で見つからない、実行時に呼ばれていない(ログ・メトリクスで確認)、関係者に確認した。この3つが揃って初めて、削除は安全になります。
| 種類 | 必要な確認 | 難易度 | 安全にする工夫 |
|---|---|---|---|
| 追加 | 名前の衝突・資源の取り合い | 低い | 既存の挙動を変えない |
| 変更(中身のみ) | 同じ入力で同じ出力か | 中 | 振る舞いをテストで固定してから変える |
| 変更(インタフェース) | 上流の全列挙 | 高い | 旧形式を一定期間併存させる(第5回) |
| 削除 | 使われていない証明(3根拠) | 最も高い | いきなり消さず、警告を出してから消す |
削除の安全策として強力なのが「警告を出してから消す」です。いきなり機能を消すのではなく、呼ばれたら警告ログを出す状態にして、数週間観測します。警告が出なければ、「実行時に呼ばれていない」という証拠が得られます。観測してから消す——この一手間が、削除事故のほとんどを防ぎます。
🔍 検証④:「同じ」を疑う
次に、見落としの大きな原因である重複を扱います。
同じ処理が2か所に書かれていることがあります。コピー・アンド・ペースト、別チームによる再実装、移行期の新旧併存。この状態で片方だけ直すと、もう片方が古いまま残ります。そして厄介なのは、両方が動き続け、条件によって使われる方が変わることです。「直したのに、特定の条件でまだ壊れる」という報告は、たいていこれが原因です。
見つけ方は3つです。同じテーブル・同じ外部APIを触っているコードを列挙する。同じ名前の関数・同じ役割の処理を探す(命名が違うので見つけにくい)。同じ設定値を読んでいる箇所を探す。そして「この処理と同じことをしている場所は他にないか」を関係者に聞く。
| 重複の型 | 起きる事故 | 見つけ方 |
|---|---|---|
| コードのコピー | 片方だけ直り、条件によって再発する | 同じテーブル・同じAPIの利用箇所を列挙 |
| 新旧の併存 | 古い経路でだけ不具合が残る | フラグ・設定による分岐を洗う |
| 仕様の二重管理 | コードと手順書が食い違う | 手順書・BI・表計算を確認 |
| 同じ資源の共有 | 片方の負荷が他方を壊す | テーブル・API・キャッシュの利用者一覧 |
「同じ」を疑うという姿勢は、影響分析の精度を一段上げます。「これは1か所だけの話だ」と信じた瞬間に、見落としが始まります。
🔍 検証⑤:時間軸の影響——過去のデータと、未来の予定
最後に、最も見落とされる時間方向の影響です。これは2つに分かれます。
過去方向は、すでに作られたデータです。データ形式を変えると、過去に保存された古い形式のデータが読めなくなる可能性があります。ここで必要な確認は「本番には、いま何が入っているか」です。開発環境にはきれいな新形式のデータしかないことが多く、古い形式のデータは本番にだけ存在します。だから開発環境でテストしても見つかりません。確認すべきは、件数・分布・最古のレコード・想定外の値です。
未来方向は、これから動く予定のものです。数か月後に動くバッチ、年末に動く集計、契約更新時に動く連携、特定の日付にだけ動く処理。これらは普段は静かに眠っています。変更時にも、テスト時にも、目に入りません。そしてその日が来たときに壊れます。
| 時間方向 | 具体例 | なぜ見落とすか | 確認方法 |
|---|---|---|---|
| 過去 | 古い形式のレコード、過去の添付ファイル | 開発環境に古いデータがない | 本番データの件数・分布を確認する |
| 未来 | 年次バッチ、期限付きの連携、定期処理 | 普段動いていないので目に入らない | スケジュール一覧と期限一覧を確認する |
| 境界 | 閏年、月末、年始、タイムゾーン変更 | 普段は発生しない条件だから | 日付・時刻・桁あふれの前提を洗う |
境界は特に厄介です。普段は起きない条件で壊れるからです。日付や時刻の扱いは、この種の事故の宝庫です。閏日、月末、年始、夏時間、タイムゾーン。「今日は動いている」ことは、明日も動く証明になりません。変更を入れるときは、「この処理が動くすべての日付」を一度確認してください。
結果:影響分析の手順表
ここまでの内容を、実行できる手順にします。
STEP 1|変更の種類を宣言する
追加 / 変更(中身)/ 変更(インタフェース)/ 削除
→ 種類によって、必要な確認が変わる(検証③)
STEP 2|4方向を順に洗う(第3回の切り分け軸を逆向きに使う)
下流:自分が使っているもの(コードを読む)
上流:自分を使っているもの(参照検索+人に聞く)
横 :同じ資源を共有しているもの(テーブル・設定・APIの利用者)
時間:過去のデータ・未来の予定・境界の日付
STEP 3|検索で見つからない6か所を確認する
動的呼び出し/設定・環境/SQL・ビュー/外部システム/保存済みデータ/ドキュメント
STEP 4|「同じ」を疑う
同じ処理・同じ設定・同じテーブルの二重実装がないか
STEP 5|影響の一覧を書く(3列表)
影響を受けるもの/起きうる症状/確認方法
→ 「たぶん大丈夫」を「この方法で確認済み」に置き換える
STEP 6|削除なら、3根拠を揃える
検索で見つからない/実行時に呼ばれていない/関係者に確認した
STEP 7|影響の大きさに応じて段取りを決める
影響が広い → 段階的に出す・戻し方を用意する(第5回)
この手順で最も価値があるのはSTEP 5です。影響の一覧を書くことで、「確認方法」という具体物が生まれます。そしてSTEP 7につながります。影響分析の目的は、変更を止めることではありません。安全に進める段取りを決めることです。
考察:影響範囲の見積もりは、信頼残高に直結する
ここまでを踏まえて、1つ踏み込んだ話をします。影響分析の能力は、技術力の指標ではなく、信頼の指標として扱われます。
考えてみてください。同じ「影響範囲は限定的です」という答えでも、Aさんが言う場合とBさんが言う場合で、重みが違います。Aさんが過去に何度も当ててきたなら信じられます。Bさんが先週見落としたばかりなら疑われます。つまり、影響分析の精度は、あなたの発言の信頼性そのものです。
そしてこの信頼は、当てることだけでなく、外したときの扱い方でも作られます。「影響なしと言ったのに壊れました。原因は、外部の連携先も同じAPIを使っていたことです。確認方法を追加します」。この報告は、信頼を下げません。むしろ「この人は外れた原因を理解し、次に備える人だ」という評価につながります。逆に、「想定外でした」で終わらせると、次に同じことが起きたときにあなたの見積もりは誰にも信じてもらえません。
もう1つの考察は、影響分析は「調べる量」ではなく「どこを調べるかの知識」だということです。この記事で挙げた4方向と6か所は、あなたの現場のすべてではありません。あなたの現場には固有の隠れ場所があります。「この設定は誰も触らない」「このバッチは特定の人が手で動かす」「このテーブルは別チームが読んでいる」。これらを記録していくことが、そのままチームの資産になります。第1回で扱った「成果」の観点で言えば、影響範囲の一覧を残すことは、極めて効果の高い成果です。作業は地味で、効果は何年も残ります。
📌 注目ポイント
核心は4点です。第一に、変更の影響は4方向(下流・上流・横・時間)に広がること。第二に、参照検索で見つからない呼び出しが6か所に隠れていること。第三に、削除は最も難しく、「使われていない証明」が必要であること。第四に、時間方向(過去のデータ・未来の予定・境界の日付)が最も見落とされること。
特に第四点は、経験を積んでも見落とし続ける領域です。「今日動いているから大丈夫」という推論は、明日の条件を保証しません。変更を入れるときは、「この処理が動く日付を全部言えるか」を自問してください。
💡 活用事例:顧客1社の設定変更が、世界規模の障害を起こした事例
影響分析の難しさを示す事例として、2021年6月8日の大規模CDN障害があります。この障害では、特定の顧客の設定変更が引き金となって、ソフトウェアの潜在的な不具合が引き出され、広範囲のサービスが約1時間利用不能になりました。公式の説明では、設定変更そのものは通常の操作であり、問題は変更を受け取った側の処理にあったとされています。
この事例の教訓は明快です。「普通の操作」が、想定外の組み合わせで大規模障害を起こしえます。つまり影響分析は、操作の大きさではなく、経路の広さを見る必要があります。
| 事例 | 変更の大きさ | 波及の形 | 教訓 |
|---|---|---|---|
| CDN障害(2021-06-08) | 顧客1社の設定変更 | 共有基盤の不具合を通じて広範囲に波及 | 普通の操作でも経路が広ければ大事故になる |
| 分散システム基盤の障害(2021-10-28、73時間) | 基盤ソフトの負荷増加 | サービス全体が長時間停止 | 依存が深いと、影響範囲が全系になる |
| 古い形式のデータと新形式の混在 | データ形式の変更 | 特定のレコードだけ読めなくなる | 影響は「書いた人」ではなく「過去のデータ」に出る |
3つの事例に共通するのは、影響が「変更した場所」から遠く離れた場所で発生したことです。だから影響分析では、「自分から遠い場所」を意識的に見る必要があります。自分の変更を、他人の立場で想像する——これが影響分析の本質です。そして第5回では、影響が広い変更を安全に出す技術を扱います。影響分析は「危険を知る」技術、第5回は「危険を小さくする」技術です。
✅ 要点まとめ
- 影響分析は変更する前に行う。壊れてからでは遅い
- 波及は4方向:下流(自分が使う)・上流(自分を使う)・横(資源の共有)・時間(過去と未来)
- 参照検索で見つからない参照が6か所にある:動的呼び出し/設定/SQL/外部システム/保存済みデータ/ドキュメント
- 削除が最も難しく、「使われていない証明」に3根拠(検索・実行時・関係者)が要る
- 「同じ」を疑う。重複実装は、条件によって片方だけ壊れる事故を生む
- 過去のデータは本番にだけある。開発環境では古い形式が再現しない
- 未来の予定(定期処理・期限)と境界(閏・月末・時刻)は最も見落とされる
- 影響範囲の発言精度は、あなたの信頼残高そのもの
🚀 取り込み方:明日から使う3段階
今日(5分でできること):次に触る予定のコードについて、「この関数を誰が呼んでいるか」を列挙してください。IDEの参照検索で出たものに加えて、「検索で出ない場所」を1つだけ確認します(設定ファイル、SQL、他チームへの聞き取り)。1つ確認するだけで、見えていなかった依存が1つ見えます。
今週(小さく試す):小さな変更を1つ選び、STEP 5の3列表(影響を受けるもの/起きうる症状/確認方法)を書いてみます。書き終えたら、「確認方法」の列が空欄の行だけをつぶします。空欄がある行が、あなたの見落とし候補です。この表は、そのままレビューの材料になります。
今月(業務に組み込む):チームに「削除の手順」を提案します。警告ログを出す→数週間観測する→消すの3段階です。あわせて、影響範囲の記録(この設定は誰が使うか、このバッチは誰が動かすか)を1枚の表に残す仕組みを作ります。これはあなた個人の成果であると同時に、チームの資産です。新人が入るたびに同じ調査を繰り返すコストを、あなたの1枚が消します。第1回で書いた「知られていないを解消する仕事」の最も分かりやすい例です。
🔥 ハマりポイント:影響分析で外す3つの型
その1:「検索して出てこなかったから安全」と思いがちだが、実は検索は出発点にすぎない
症状は、参照検索0件を根拠に削除し、数週間後に外部システムが壊れる。原因は検索の届く範囲を過信していることです。対処は、検索以外の3つの確認を必ず行うことです。実行時のログ・メトリクスで呼ばれていないか、設定やSQLに書かれていないか、他チームが使っていないか。「検索した」ではなく「この3つを確認した」と言えるようにします。証明の質が、回答の質です。
その2:「影響は小さい変更だ」と思いがちだが、実は影響の大きさは変更の大きさと無関係
症状は、1行の設定変更で広範囲が止まる。原因は「変更の大きさ=影響の大きさ」という前提です。対処は、「経路の広さ」で影響を測ることです。共有されている設定か、全リクエストが通る処理か、全データに触るか。もし全員が通る経路を触るなら、1文字の変更でも最大級の影響があります。変わった量ではなく、通る量を見てください。
その3:「テストが通ったから大丈夫」と思いがちだが、実はテストは本番の条件を再現しない
症状は、全テスト成功でリリースし、本番だけ壊れる。原因はテスト環境に本番固有の条件(古いデータ・負荷・外部連携)がないことです。対処は、「本番にしかないもの」を列挙することです。古い形式のレコード、大量データ、他チームの連携、実際の利用パターン。これらはテストでは再現できません。だから段階的に出す・一部にだけ出すという工夫が必要になります。それが第5回のテーマです。
🔄 代替アプローチとの比較:影響分析のやり方
影響分析には複数のやり方があります。組み合わせて使うものです。
| やり方 | 内容 | 向いているケース | 弱い点 |
|---|---|---|---|
| 静的な参照追跡 | コード上の参照を辿る | コードが整理されている | 動的・外部の参照が見えない |
| 実行時の観測 | ログ・メトリクス・トレースで確認 | 実際に何が使われているか知りたい | 観測点がないと使えない |
| 人への聞き取り | 関係者に利用状況を確認する | 暗黙の依存・手作業がある | 時間がかかり、属人的 |
| テストによる固定 | 現状の振る舞いをテストで保存する | 中身だけの変更 | テストがないと作る必要がある |
| 段階的リリース | 一部にだけ出して影響を観測する | 影響が読み切れない | 影響が広いと一部で済まない |
段階的リリースが向いているケースは多くあります。影響が完全には読み切れないときは、読む努力を増やすより、出す範囲を狭めるほうが確実です。読む努力には限界がありますが、範囲を狭めることは確実に効きます。これは「分析で解く」か「設計で解く」かの選択です。そして両方やるのが最も安全です。
📅 今後の展望:依存関係は「自動で見える」方向へ
影響分析の道具は、この10年で大きく進歩しました。依存関係を自動で可視化する仕組み(サービス間の呼び出し関係を自動記録する仕組み、コードの依存グラフを解析するツール、データの系譜を追う仕組み)が一般化しつつあります。「誰がこのAPIを呼んでいるか」を、自分で聞いて回らずに一覧できる環境が増えています。
ただし、自動で見えるのは「観測されている依存」だけです。動的な呼び出し、設定ファイルの中身、人の手作業は、依然として見えません。むしろ自動化が進むほど「自動では見えない依存」が相対的に重要になります。あなたが今、「この処理は誰が使っているか」を人に聞いて記録することは、将来の自動化の入力データにもなります。
もう1つの流れは、変更のリスクに応じて手続きを変える考え方です。すべての変更に同じ重い手続きを課すのではなく、影響範囲の広い変更には段階的リリースと戻し方を必須にする。逆に影響の狭い変更は素早く出す。この考え方は第5回で扱う可逆性の設計と直結します。リスクの大きさに、手続きの重さを比例させる——これが、速さと安全を両立させる方向です。
まとめ
この記事では、変更前に影響を洗い出す技術を扱いました。影響は4方向(下流・上流・横・時間)に広がり、参照検索で見つからない参照が6か所に隠れています。削除は最も難しく、時間方向(過去・未来・境界)は最も見落とされます。そして影響分析の目的は、変更を止めることではなく、安全に進める段取りを決めることです。
これを読んだあなたは、「影響範囲は?」と聞かれて、4方向と6か所の観点から根拠のある答えを返せるようになりました。次の第5回では、影響が広い変更を安全に出す技術を扱います。戻せない変更は、安全にできない——それが次のテーマです。
参考文献
- Shawn A. Bohner & Robert S. Arnold『Software Change Impact Analysis』(IEEE Computer Society Press, 1996) — 影響分析を体系化した基礎文献。
- Michael Feathers『Working Effectively with Legacy Code』(2004) — 振る舞いの保存と、変更の安全な進め方。 https://www.oreilly.com/
- Martin Fowler『Refactoring』(第2版, 2018) — 振る舞いを変えない変更の原則。 https://martinfowler.com/
- Google『Site Reliability Engineering』 — カナリアリリースと段階的展開。 https://sre.google/
- Google『The Site Reliability Workbook』第16章 Canarying Releases — 段階的リリースの実務。 https://sre.google/
- Fastly 公式ポストモーテム(2021年6月8日のサービス障害に関する声明) — 顧客の設定変更が引き金となった広範囲障害の一次説明。 https://www.fastly.com/
- Roblox 公式ポストモーテム(2021年10月28日〜31日の障害) — 73時間に及んだ依存関係起因の障害。 https://corp.roblox.com/
- John Allspaw「Blameless PostMortems and a Just Culture」(2012) — 影響の分析と責任の分離。
- NIST SP 800-30『Guide for Conducting Risk Assessments』 — リスク評価の標準的な考え方。 https://csrc.nist.gov/
- ISO 31000『リスクマネジメント — ガイドライン』 — リスクの特定・分析・評価の枠組み。 https://www.iso.org/
- GAO『Year 2000 Computing Crisis』関連報告(1990年代後半) — 影響範囲の調査が社会規模で行われた歴史的事例。 https://www.gao.gov/
- IERS『Bulletin C』(閏秒の告知) — 日付・時刻の前提が崩れる境界条件の一次情報。 https://www.iers.org/
- The Twelve-Factor App「III. Config」 — 設定をコードから分離する原則。 https://12factor.net/
- Melvin E. Conway「How Do Committees Invent?」(1968) — 組織構造が依存構造を決めるという法則の原典。
- Nicole Forsgren, Jez Humble, Gene Kim『Accelerate』(2018) — 変更失敗率とリードタイムの測定。 https://dora.dev/
- IPA『iコンピテンシ ディクショナリ』 — 変更管理と影響分析に関する能力定義。 https://www.ipa.go.jp/
Rui Software