2026/02/08 19:19
デグレはなぜ起きるのか
──「実装ミス」ではなく「構造の問題」として考える
ソフトウェア開発をしていると、
「前は動いていたのに、なぜか動かなくなった」という経験を避けて通ることはできません。
いわゆる デグレ(デグレーション / regression) です。
「前は動いていたのに、なぜか動かなくなった」という経験を避けて通ることはできません。
いわゆる デグレ(デグレーション / regression) です。
デグレという言葉はよく使われますが、その原因が個人のミスや注意不足として片付けられてしまうことも少なくありません。
しかし本当にそうでしょうか。
しかし本当にそうでしょうか。
本記事では、デグレを「実装者の問題」ではなく、開発の構造そのものが生み出す現象として整理してみます。
デグレとは何か
デグレとは、新しい変更を加えた結果、以前は正常に動いていた機能が動かなくなってしまうことを指します。
重要なのは、デグレは単なる「バグ」とは違うという点です。
重要なのは、デグレは単なる「バグ」とは違うという点です。
バグは、最初から正しく動いていなかった状態を指します。一方デグレは、「以前は確かに動いていた」という前提があり、その状態から後退してしまうことです。
つまりデグレには、必ず時間軸が含まれています。
つまりデグレには、必ず時間軸が含まれています。
技術的な原因の奥にあるもの
デグレが起きたとき、原因として挙げられるのは、条件分岐の追加、状態管理の複雑化、初期化順の変更など、技術的な要因であることが多いでしょう。
もちろんそれらは事実ですが、多くの場合、それは表に現れた結果にすぎません。
もう一段深く見ていくと、技術以前の「構造的な問題」が見えてきます。
もう一段深く見ていくと、技術以前の「構造的な問題」が見えてきます。
本質的な原因は「全体を保証する役割が存在しないこと」
多くの開発現場では、役割分担が明確です。
Issue を作る人、実装する人、レビューする人、進捗を管理する人がそれぞれ存在します。
Issue を作る人、実装する人、レビューする人、進捗を管理する人がそれぞれ存在します。
その結果、作業者は与えられた Issue を正しく実装し、レビュアーはコードの差分を確認し、進捗担当はタスクが前に進んでいることを確認します。
ここまで見ると、誰も間違ったことはしていません。
ここまで見ると、誰も間違ったことはしていません。
それでもデグレは起きます。
なぜなら、「変更後もプロダクト全体として成立しているか」を保証する責務が、どこにも明示されていないからです。
なぜなら、「変更後もプロダクト全体として成立しているか」を保証する責務が、どこにも明示されていないからです。
PL や PM といった立場の人はいますが、実際には全ての実装差分を追い、すべての動線を通すことは現実的ではありません。
結果として、全体を保証する責務そのものが空席になる。
これが、デグレが見落とされる最大の理由です。
結果として、全体を保証する責務そのものが空席になる。
これが、デグレが見落とされる最大の理由です。
デグレは「確認不足」ではない
デグレが起きると、「レビューが甘かった」「確認が足りなかった」と振り返られることがあります。
しかし多くの場合、それは正確な表現ではありません。
しかし多くの場合、それは正確な表現ではありません。
正しくは、
確認する工程そのものが、最初から存在していなかった
という状態です。
誰かがサボったわけでも、手を抜いたわけでもありません。
ただ、見るべき場所が定義されていなかっただけなのです。
ただ、見るべき場所が定義されていなかっただけなのです。
解消の出発点は「保証」という考え方
ここでいう解消とは、デグレを完全になくすことではありません。
デグレはプロダクトが成長する限り、避けられないものです。
デグレはプロダクトが成長する限り、避けられないものです。
目指すべきなのは、デグレが起きにくく、起きても早く気づける構造を作ることです。
その中心になるのが「保証」という考え方です。
その中心になるのが「保証」という考え方です。
保証とは、ルールを守るように人に注意することではありません。
ルールが守られていない状態では、プロセスが物理的に先へ進めない構造を作ることを意味します。
ルールが守られていない状態では、プロセスが物理的に先へ進めない構造を作ることを意味します。
Issue の時点で全体確認は始まっている
全体確認は、レビューやマージの段階から始まるものではありません。
Issue を書く瞬間から始まっています。
Issue を書く瞬間から始まっています。
Issue は単なる作業指示ではなく、「この変更をプロダクトにどう組み込むか」を宣言する場です。
そのため、Issue には最低限、どのロールに影響するのか、どの画面や機能と関係しているのか、今回触らないが影響を受けそうな箇所はどこか、といった視点が含まれている必要があります。
そのため、Issue には最低限、どのロールに影響するのか、どの画面や機能と関係しているのか、今回触らないが影響を受けそうな箇所はどこか、といった視点が含まれている必要があります。
完璧である必要はありません。
重要なのは、「想像した痕跡」が残っていることです。
重要なのは、「想像した痕跡」が残っていることです。
影響範囲が書かれていない Issue は Ready にしない。
Ready でない Issue には着手しない。
これが「保証」です。
Ready でない Issue には着手しない。
これが「保証」です。
マージ前のレビューで確認するべきこと
マージ前のレビューでは、コードの正しさだけを見るのでは不十分です。
ここで確認すべきなのは、「全体への影響を考えたかどうか」です。
ここで確認すべきなのは、「全体への影響を考えたかどうか」です。
Issue に書かれた影響範囲が妥当か、実装によって影響が広がっていないか、今回確認していない範囲が明示されているか。
レビューとは、コードだけでなく思考の前提を確認する行為でもあります。
レビューとは、コードだけでなく思考の前提を確認する行為でもあります。
それが書かれていない PR はマージしない。
これもまた、保証の一部です。
これもまた、保証の一部です。
Done に含めるべきもの
マージ後には、必ず全体確認の工程が必要です。
ここで確認するのは、新しく追加した機能ではありません。
ここで確認するのは、新しく追加した機能ではありません。
以前は成立していた動線が、今も成立しているか。
想定したロールで、主要な操作が問題なく行えるか。
状態遷移が破綻していないか。
想定したロールで、主要な操作が問題なく行えるか。
状態遷移が破綻していないか。
「壊れていないこと」も、立派な成果です。
それを Done の定義に含めなければ、デグレは必ず後から見つかります。
それを Done の定義に含めなければ、デグレは必ず後から見つかります。
今回のデグレを振り返ると
今回起きたデグレも、実装そのものが間違っていたわけではありません。
Issue の要件は満たされており、レビューで異常を見つけるのも難しい内容でした。
Issue の要件は満たされており、レビューで異常を見つけるのも難しい内容でした。
それでも問題が起きたのは、既存の動線が壊れていないかを確認する工程が、どこにも存在しなかったからです。
これは個人のミスではなく、構造の問題でした。
これは個人のミスではなく、構造の問題でした。
完全防止はできない
最後に、とても重要なことを書いておきます。
デグレを完全になくすことはできません。
影響範囲の想像には限界があり、状態や依存関係は増え続け、人もコードも変わっていきます。
影響範囲の想像には限界があり、状態や依存関係は増え続け、人もコードも変わっていきます。
それでも、「誰も見ていなかった」という状態をなくすことはできます。
おわりに
デグレは避けられません。
しかし、早く気づき、小さいうちに止め、同じ構造で繰り返さないことはできます。
しかし、早く気づき、小さいうちに止め、同じ構造で繰り返さないことはできます。
そのために必要なのは、優秀な個人ではなく、
全体確認が自然に行われる構造です。
全体確認が自然に行われる構造です。