【ITニュース解説】When every check blocks, verifying a small change costs an hour
2026年09月24日に「Dev.to」が公開したITニュース「When every check blocks, verifying a small change costs an hour」について初心者にもわかりやすく解説しています。
ITニュース概要
システム開発で確認作業が増え、小さな変更でも検証に1時間かかる問題があった。そこで、確認を「各作業で素早く行うもの」と「デプロイ前にまとめて行うもの」の2段階に分け、個々の作業時間を数分に短縮し、開発を効率化した。
ITニュース解説
ソフトウェア開発の現場では、新しい機能を作ったり、既存のプログラムを修正したりするたびに、その変更が正しく動くか、他の部分に悪影響を与えないかを確認するための様々なチェックが行われる。この一連の自動化された工程を「パイプライン」と呼ぶ。このパイプラインが、最初は非常に速く動いていたにもかかわらず、いつの間にか小さな修正の検証に1時間もの時間がかかるようになってしまうことがある。
なぜこのような問題が起こるのか。それは、実際に役に立つチェックが次々と追加されていったからである。例えば、プログラム全体の機能が正しく動くかを確認するエンドツーエンドテストや、セキュリティ上の問題がないかをチェックするレビューなどが、発見されたバグや脆弱性に対応するために、ひとつずつ必須の工程として追加されていった。それぞれのチェックは確かに重要で、もしこれらを怠れば、より大きな問題が後で発生してしまうだろう。だから誰も「このチェックは不要だ」とは言わない。しかし、その結果として、たとえプログラムのたった2つのファイルを変更しただけであっても、その検証にコードを書く時間よりもはるかに長い時間がかかってしまう状況が生まれる。これは、数ヶ月の間に数回、このようなチェックが追加されるだけで簡単に起こりうる問題である。
この問題を解決するために、チェックの数を減らしたり、個々のチェックを速くしたりするだけでは不十分だった。本当に必要なのは、「このチェックは役に立つか?」という問いを変えることだった。なぜなら、全てのチェックは確かに有用だからだ。新しい問いは「このチェックはどの意思決定をブロックしているか?」というものだった。つまり、あるチェックは個々のプログラムの変更が完了するのをブロックする必要があるかもしれないが、別のチェックは、開発中のプログラムを実際に動かす環境(本番環境)にデプロイするのをブロックするだけで十分かもしれないのだ。この二種類のブロックするタイミングを混同してしまうことが、パイプラインを遅延のボトルネックに変えてしまう最大の原因だった。
そこで考え出されたのが、チェックを2つの段階に分ける方法である。
最初の段階は「Tier 1」と呼ばれ、個々の開発タスクの完了をブロックするチェックが含まれる。このTier 1のチェックは、速く、予測可能で、タスクごとに実行される点が特徴である。具体的には、プログラムの内部的な動きを検証するバックエンドのテスト全体、そして、そのタスクで変更された部分だけを対象としたエンドツーエンドテスト(画面表示を伴わないヘッドレスモードで実行)、さらにセキュリティ上の簡単なチェックなどがこれに含まれる。ここで最も重要なのは「そのタスクに関連する部分のみ」をテストするという点だ。これにより、検証にかかる時間は1時間から数分へと劇的に短縮される。
次の段階は「Tier 2」と呼ばれ、プログラムを本番環境にデプロイするのをブロックするチェックが含まれる。このTier 2のチェックは、時間とコストがかかるものが多く、まとめて(バッチ処理で)実行される。ここには、プログラム全体の機能を検証するフルエンドツーエンドテストや、AIなどを利用してインターフェース(ユーザーが触れる画面や操作)が期待通りに見え、動くかを評価するモデル支援のインターフェースレビューなどが含まれる。このTier 2のチェックは、デプロイの前と、毎晩自動的に実行される。もしこのチェックで問題が見つかっても、それは日中の開発作業を妨げるものではない。デプロイをブロックするだけなので、開発者は普段通り作業を続けられる。つまり、これらの時間のかかるチェックは、実際にそのチェックが最も重要となるデプロイの段階で実行されることで、効率的な運用が実現されるのだ。このTier 1とTier 2の区別は、画面上でも二つの異なる列として明確に表示され、それぞれの状態がわかるようにされた。これにより、たとえあるチェックがタスクの完了を直接ブロックしなくても、その結果が存在し、誰かが確認する責任があることが明確になった。
この変更は、単にチェックを振り分けるだけでなく、既存のシステムに大きな影響を与えずに安全に実施することが非常に難しかった。なぜなら、これまでの品質ゲート(タスクの完了条件)は、特定のインターフェースレビューの結果が「合格」であることを明示的に要求していたからだ。もしこのインターフェースレビューをタスクごとのチェックから単純に外してしまうと、システムはインターフェースレビューの結果を見つけられなくなり、全てのタスクが完了できなくなるという致命的な問題が発生してしまう。
そこで、この変更は綿密な計画に基づき、以下の5つの段階を経て実行された。 最初の段階は、直感に反するように思えるかもしれないが、品質ゲートがインターフェースレビューの結果を必須としないように、まず要求自体を緩めることだった。これは、互換性を保つ変更である。もしインターフェースレビューの結果が存在すれば、システムはそれを無視し、もし結果が存在しなくても、タスクの完了をブロックしない。この時点では、システムは以前と全く同じように動作する。 次に、新しいTier 1のチェックを追加する。これは純粋な追加であり、既存の動作には影響を与えない。 そして、この2段階を経て安全になった後、初めてインターフェースレビューがタスクごとの結果を生成するのを停止する。これは、すでに2つのステップ前で誰もその結果を要求しなくなっているため、安全に実施できる。 最後に、画面表示の変更や、Tier 2のチェックを実行するバッチランナーの追加を行う。これらは新しい機能であり、既存のパスには影響しない。 このように、一見すると回りくどいようにも見える手順を踏むことで、全てのプロジェクトで同時にタスク完了機能が停止するという大惨事を回避できたのだ。
また、実装において重要な細部として、新しいチェックがプロジェクトごとに適切に動作するように配慮された点がある。全てのプロジェクトが同じ種類のテストやレビューを必要とするわけではない。例えば、一部のプロジェクトではエンドツーエンドテストが全く存在しない場合もある。もし品質ゲートがそれらのテストを無条件に要求した場合、それらのプロジェクトは永遠にタスクを完了できなくなってしまう。そのため、新しいチェックは、プロジェクトの設定を読み込み、もしプロジェクトが特定のチェックを必要としないと宣言している場合は、そのチェック自体を適切にスキップするように作られた。これは当たり前のことのように聞こえるが、様々な特性を持つプロジェクトに対して同じメカニズムを適用する際には、非常に重要な考慮事項である。
これらの変更の結果、タスクごとの検証時間は、全てのプロジェクトで同時に、約1時間から数分へと大幅に短縮された。パイプラインの速度が改善されたことで、これまで遅さに隠れて見えなかった別の問題が明らかになった。それは、サーバーを再起動するたびに、その日の作業計画全体が失われるという問題である。このように、一つの問題を解決すると、その影に隠れていた次の問題が顔を出すのが、ソフトウェア開発の常である。