デグレードについて

デグレ(デグレード)とは?

システムやソフトウェアがアップデートや変更を加えた際に性能が低下したり、機能が後退してしまうことを指します。例えば、ネットショッピング用のWebアプリの商品ページにフィルター機能を追加した結果、商品画像が見切れて表示されてしまうというような、何らかの変更が品質を下げてしまう状態を意味します。

デグレードとほぼ同じ意味でリグレッションという言葉があります。英語圏ですとこちらの方が普及しています。意味は日本語のデグレードと変わらず、「変更により引き起こされた、コンポーネントやシステムの品質の悪化」を指します。

デグレードが起きる主な原因

デグレードには様々な原因がありますが、不具合がおこる場所で大別すると以下の3つに分けることができます。

コードの問題

この部分では、プログラムを実装・改修した際に誤ったコードが埋め込まれたことによって発生するデグレについて紹介します。このようなデグレは、誤ったコードが埋め込まれた部分だけでなく、ほかの部分に影響を与えることがあります。たとえば、ある新機能を追加・改修したときに、変更していない機能が動かなくなったなどがありえます。改修した機能がその部分で閉じていたと考えていたコードが、実際にはほかのプログラムでも使われていて、想定外の影響がでることもあります。機能の追加・修正の際には、変更箇所に気をとられて、変更箇所でない部分の確認が不十分になることがあります。機能の実装・改修の際には、既存の機能全体に影響がないか確認をすることが必要です。

また、リファクタリングや最適化を図った結果、意図せず動作が遅くなることや、既存コードと新しく追加・変更したコードの間で互換性がなくなり、既存の機能が動かなくなるといったことも生じることがあります。

環境の問題

この部分では、複数のインフラや多数のサービスの結合でなりたつシステムで発生するデグレについて紹介します。このようなデグレは主に、環境設定値の変更、環境に適用しているミドルウェアやライブラリのバージョンアップ、環境の移行といったタイミングで発生することが多いです。

他にも、OSやクラウド環境の変更、データ量の変更、連携している外部システムの変更などの際も発生しやすいです。

これらのデグレは、環境変化にあわせて対応するべき作業が漏れると発生します。または、その変更に合わせようとプログラムを修正しようとした結果として生じることもあります。特に、確認に十分な時間がとれず、インフラの変更後のテストが不十分なまま終わってしまうと、システムダウンのような大きな問題に発展することもあります。

環境に起因するデグレは影響範囲が広範囲にわたることが多々あります。影響範囲が大きくなるであろうといことを考慮し、デグレが発生しないことを広い範囲で確認しながら、環境変化にあわせるための作業を行って行くようにしましょう。

データ変更の問題

データの変更もデグレの発生の要因となりえます。ソフトウェアの実装に問題がなくとも、データのフォーマット変更、データの値や制約の変更、データの参照元の変更などにより、システムがスローダウンしたり、想定以上にメモリやストレージを使ってしまい、容量不足となる場合もあります。

また、データ量の少ないテスト環境では問題なく応答したとしても、データ量の多い本番環境では、正常に応答しないケースもあります。こういった事態を避けるためにも、テスト環境と本番環境のデータの整合がとれるようにしておきましょう。

デグレードが起きる具体的な原因

ここではデグレを引き起こす原因を6つ取り上げます。

影響範囲の見落とし

ソフトウェアの変更が及ぼす影響範囲について正しく把握できていない場合、デグレが発生します。たとえば、変更を加えた機能で使用しているデータが、ほかの機能でも使用されているときに、その変更の影響をうけて、データを共用しているほかの機能が応答しないことがありえます、また、パラメーターやデータの扱い方を変更した結果、以前の計算式を前提とした処理が正常に完了しないといったデグレが生じえます。ソフトウェアの規模が大きくなればなるほど、機能間の関係性が複雑になっていくので、既存のソフトウェアに変更を加える場合は、影響範囲を十分に考慮するようにしましょう。

手作業によるヒューマンエラー

コードの修正やデプロイ時に手動操作を行ったときに、設定ミスやコードの適用漏れが発生することがあります。どんなに熟達したプログラマーであっても絶対にケアレスミスをしないとは限りません。たとえば、セミコロンのつけ忘れ・余分なセミコロン、=と==の取り違え、breakやreturnの書き忘れなどがあります。

ミスがでないようなルールや体制作りはある程度の効果が見込めます。しかし、完全にミスをゼロにすうことはできませんので、ミスは起こるものとして、チームでミスを事前に発見できるようにしていきましょう。

バージョン管理の不備

バージョン管理に不備がある場合もデグレの発生原因となりえます。変更を加えたファイルが正しくバージョン管理されていない、あるいはマージ時の競合処理を誤ったことで、古いコードが残ったり、新しい変更が適用されなかったりすることがあります。新しいファイルが入っていた、直近の変更がなかったことになる場合もあり得ます。このような原因をもつデグレの場合、過去の不具合が再発することが多いです。

環境の違いによる問題

開発環境の変化もデグレにつながることがあります。開発環境、テスト環境、本番環境によって異なる設定や依存関係があれば本番環境で不具合が生じます。たとえば、ライブラリやフレームワークのバージョンアップ、OSやミドルウェアのバージョンアップ、環境変数の違い、ファイルパスの違いなど様々な要因が挙げられます。開発しているソフトウェアと関わる要素の変更であれば、少なからず影響をうけることになるので、あらかじめ環境の変化を想定しておくことが重要です。

仕様変更や要件変更の認識ミス

仕様変更や要件変更がされた場合に、開発チーム内で正しく共有されないとき、既存のプログラム内に古い仕様・要件に基づいたコードが残ることで不整合が生じ、デグレが発生します。また、要件のハードルが高く、場当たり的な対応になった場合もこの種のデグレが発生しやすいです。既存のプログラムに大きな影響を与えるため、影響範囲が拡大し、プログラムが複雑化していきます。仕様変更・要件変更の際には、デグレの発生に細心の注意を払うようにしましょう。

テスト不足・不適切なテスト

変更後のシステムに対する単体テスト・統合テスト・回帰テストが不十分で、不具合を事前に検出できなかった場合にもデグレが発生します。特に、境界値のチェック漏れや例外ケースの未考慮が原因でバグが見逃されることがよくあります。テストを充実させることが重要です。この種のデグレを防ぐためにも、境界値や異常値についてのテストを追加したり、エラーハンドリングのテストを強化しましょう。また、テストの自動化やカバレッジ計測も役立てていくようにしましょう。

デグレが招くリスク

この部分では、デグレが起こることで生じる影響の大きなリスクについて具体的に説明します。

工数・コストの増加

デグレの対応には、多くの労力が必要とされます。早急に修正対応せねばならず、また、修正の際にデグレが発生しないように慎重な対応が求められます。デグレが起こると修正作業の工数増加は避けられません。バグの調査・原因特定、コードの修正作業、テストの再実施、また、これらに伴う資料作成などに本来は予定していなかった工数・コストがかかることになります。

工数・コストが増加した結果、期限に間に合わなくなってしまうと、プロジェクトの予算オーバーを招き利益を圧迫しかねません。受託プロジェクトの場合、期限に間に合わないと請求自体ができない可能性や、損害賠償を請求されるリスクもありえます。

顧客・エンドユーザーからの信頼を失う

デグレが発生すると、顧客やエンドユーザーの信頼を失う原因となります。ソフトウェアやサービスの品質が低下すると、ユーザーの満足度が下がり、最悪の場合、競合サービスへ乗り換えられてしまう可能性があります。使える想定でいたものが使えないという状況はお客様の期待に答えられず、満足度をさげてしまうことになります。また、1つのデグレがみつかると、ほかにもあるのでは?という疑心を抱かせてしまうことになります。

セキュリティ関連やデータの損失破壊をともなうような重大なデグレの場合、企業価値にも影響を及ぼしかねません。デグレは開発チームだけでなく、企業、顧客、エンドユーザーにまで不利益をもたらしかねないものです。

開発メンバーのモチベーション低下

デグレへの対応が続くと、開発メンバーは修正作業の繰り返しによって疲弊していきます。また、顧客やエンドユーザーからのクレーム処理や、上司からの追及により、ストレスの増大が予想されます。デグレが頻発すると、「どれだけ頑張っても品質が上がらない」と感じるようになり、無力感や諦めの感情が生まれます。結果として、開発メンバー全体でのモチベーションの低下へとつながっていってしまうことがあります。最悪の場合、エンジニアの離職といった事態も招きかねません。

デグレの再発

デグレに対応した結果、デグレを生み出すというケースも存在します。デグレが起きる部分はバグが多く潜む部分かもしれません、それで、再度同じような問題が発生しやすい部分とも言えます。デグレへの対応は早急かつ慎重なものであるべきですが、想定外の対応のため、人為的なミスも起こりやすくなります。

時間にもコストや工数にも追われる難しい状況ですが、場当たり的な対処ではなく、問題の本質的な原因を追及することと、テストの再実施などに力を注ぐようにしましょう。

デグレを防ぐには?

デグレを防ぐためには、**発生を未然に防ぐための「防止策」**と、**発生した際に迅速に対応するための「対応策」**の両方が必要です。通常、十分なテストが計画されるため、デグレは起きないという前提でプロジェクトの工数を計画していきますが、リスクを抱えるプロジェクトの場合は、、想定外のデグレは起こりうるものと考えて工数を計画することは大切です。この点で、未然に防ぐ防止策だけでなく、発生したデグレの影響を小さく収め、迅速に対応するための対応策も必要となってきます。

防止策

デグレに対しての防止策を考える場合は、デグレが発生してしまう原因に焦点をあてて考えていくことになります。下に紹介する対応策は基本的な一部のもので、複数の対策をとりいれることで、よりデグレを発生させづらくなります。特に開発プロセスの最適化と品質管理の強化について検討することが重要です。

開発プロセスの最適化①【十分な影響範囲の調査】

デグレの発生の多くは影響範囲の調査ミスや考慮不足が原因となっています。プログラムの実装を行う際には、どの機能やモジュールに影響するのかを明確にしてから行うようにしましょう。変更の影響を事前に把握できるだけでなく、開発後の手戻りを減らす効果もあります。デグレの影響範囲を調査する際には、事前に作業のルール、方針、ミス防止の仕組みを決めておくことが効果的な防止策となります。正しい仕様情報、正しい理解が、調査には必須になってきます。不確実な部分は、仕様情報にもとづいて現新比較を行ったり、可能であれば静的解析ツールなどを用いてミスの発生を抑止しましょう。

開発プロセスの最適化②【開発体制の見直し】

開発体制にデグレを引き起こす問題があることもあります。その場合は、開発体制を見直すことでデグレへの防止策となります。例えば、チームの役割と責任を明確化することができます。各人の役割と責任が明確になれば、開発メンバーのレベルに対して難しすぎる仕事を割り振った結果、ケアレスミスを起こすという事態を避けられます。また、ナレッジ共有の仕組みを整えたり、テスト自動化のチームを編成することも役立つでしょう。

品質管理の強化①【管理ルールの徹底】

管理ルールを徹底することは、デグレ防止に効果的です。変更管理や構成管理についての管理ルールをチーム全体に周知するようにしましょう。これにより、不正な管理による誤解を避けることができます。また、トレーサビリティを確保することも必要です。

具体的にどのようなことができるかといえば、例えば、バージョン管理のルールやコードレビューのルールを定めておくこと、プロジェクトのプロセスに更新確認やレビューを組み込むこと、回帰テストの自動化や、テスト結果の管理とレポート化などを行っていくことができます。

品質管理の強化②【開発チーム内での情報共有・指導】

開発チーム内での情報共有や指導もデグレの防止策となります。適切なナレッジ共有と指導を行うことで、チーム全体の品質意識を向上させ、デグレを未然に防ぐことができます。ソフトウェアの内部構造などをチーム全体で把握できるなら、誤解によるデグレを防ぐことができます。また社内勉強会、メンター制度などを通じて、影響範囲を意識したソースコードの変更などのノウハウを共有していくことができます。Slackなどのコミュニケーションツールを用いて、リアルタイムでの情報共有も役立ちます。

対応策

デグレの対応策としては、デグレを最終的なリリースまでにどうコントロールできるか、ということを考えていきます。また、デグレがあったとしても、お客様に影響しないようにすること、または、リリースへの影響を最小限にとどめることを考えます。

リグレッションテストの徹底

リグレッションテストとは、デグレを検出するためのテストです。これを徹底することはデグレへの対応策として欠かせません。回帰テスト、無影響テストと呼ばれることもあります。基本的には、変更が影響しうる既存の機能に対して、既存のテストケースを再実施することになります。特に気を付けたいのは、影響範囲の見定めです。影響範囲の見定めを誤ると、プログラム中に混入された問題を見落とすことになります。また、リグレッションテストを行う際は、リリースまでに対応可能なスケジュールを組むこと、検出された不具合に対しての対応方針を決めておくことも重要です。

そのほかにも、自動化されたリグレッションテストや、変更の影響範囲を可視化できるように変更箇所と関連するモジュールの依存関係をドキュメント化すること、テストカバレッジの可視化も役に立ちます。

自動テスト・CI活用

CIとは継続的インテグレーションのことを指します。開発者が頻繁にコードをリポジトリに統合し、自動でビルドやテストを実行する開発手法です。コードの統合と検証を素早く行うことができるので、バグの早期発見や開発効率の向上を図ることができます。テストに関しては、自動テストコードを用意することが必要で、メンテナンスも欠かせませんが、リグレッションテストをより効率的に行うことができますし、検出しやすいデグレは早期に発見することができるようになります。

また、CIによって頻繁に自動テストを行えるなら、影響範囲外だと考えられていた部分でのデグレがみつかったり、APIの挙動変化の検出も行えます。

ただし、テストを実装していない内容でテストを行うことができないので、柔軟に対応できる手動テストと上手に組み合わせて品質を高めていくことができます。

デグレの振り返り

過去に発生したデグレや類似した不具合はよく起きます。それで、起こってしまったデグレについてよく分析し、対応策を整理しておくことで、今後起こりうるデグレへの有効な解決策となることがあります。デグレを振り返ることは、デグレへの対応策として有効なものです。発生したデグレの情報(原因・対応策・影響範囲)をデータベース化し、「過去にどんなデグレがあったか?」を開発メンバーが参照できるようにしましょう。デグレの分析をするときには、個人のミスや問題で片づけるのではなく、それを起こした仕組み、体制まで考慮するようにしましょう。分析した原因に対応する改善策をたて、実際に導入し、その効果を計測できるようにするなら、よりデグレへの対応策として有効なものとなります。

リリースコントロール

デグレが発生した際に、すぐに元のバージョンに戻せる仕組み(ロールバック)を構築できるなら、デグレの影響を最小化することができます。クラウド環境下であれば、品質を確認しながらリリースしていくことも可能です。そのような場合には次のような手法が役立ちます。

■フィーチャーフラグ(Feature Flags)

新機能を特定のユーザーや環境でのみ有効化し、リスクを抑えながら展開する手法。バグが発生した場合、すぐに無効化(ロールバック)できることが特徴。ベータユーザー、内部テスト用などの特定のユーザーグループにのみ適用することができ、リリース後も動的にオンオフを切り替えられるように設計される。

■ブルーグリーンデプロイメント(Blue-Green Deployment)

2つの本番環境を用意し、安全にリリースを切り替える手法。万が一、問題が発生した場合はすぐに元のバージョンに戻すことができる。Blue環境(現在稼働中のシステム)とGreen環境(新バージョン)を同時に運用し、Green環境で十分なテストを行い、問題なければトラフィックを移行します。問題が発生した場合は、即座にBlue環境に戻すことができます。

■カナリアテスト

カナリアテストは、新機能を一部のユーザーや環境にのみ展開して、リスクを抑えながらテストする手法です。現行のシステムと更新後の新システムを同時に稼働させ、ロードバランサーを使って利用割合をコントロールします。主な目的は、新しい機能や変更が本番環境で問題なく動作するかを、少数のユーザーで確認することです。炭鉱のカナリアが異常を検知したなら、労働者が避難するように、デグレを検出したら、すべてのユーザーを現状のシステムに戻すことができます。問題が発生した場合、迅速に無効化できるため、本番システムへの影響を最小限に抑えられます。新システムに問題がないようなら、徐々に新システムを利用するユーザーの割合を増やしていき、最終的にはすべてのユーザーを新システムに移行することを目標にします。

■シャドーテスト

シャドーテストは、実際のユーザーからのトラフィックを新しいシステムや機能に流し込み、その挙動を監視するテスト手法です。新しいシステムはユーザーには公開せず、新しいシステムのレスポンスはユーザーには返しません。ユーザーには現行のシステムからの出力を返しますが、同時に新しいシステムと現行のシステムの出力を比較します。裏で動作確認を行うため、ユーザーには影響を与えません。主な目的は、本番環境のトラフィックを使って新しいシステムの動作やパフォーマンスを検証することで、新しいシステムと現行のシステムの出力に違いがあれば、その詳細を調査することになります。

■A/Bテスト

A/Bテストは、2つ以上の異なるバージョンのシステムをユーザーにランダムに提供し、どちらが効果的かを比較するテスト手法です。ユーザーを半々に分けて、それぞれのシステムにルーティングします。ユーザーの反応に基づいて最適な選択肢を見つけることを目的としたもので、ユーザーの挙動をモニタリングして、新システムと現行のシステムのどちらがよいか判断します。

まとめ

デグレとは、ソフトウェアの変更が意図せず、ほかの部分に影響を及ぼし、品質を低下させることです。デグレが起きると、工数・コストの増加、信頼の失墜、開発チームのモチベーションの低下など様々なリスクを呼び込んでしまいます。変更の影響範囲を見誤ったことや、バージョン管理の不備、環境の変化など様々な要因があります。すべてのデグレをなくすことはできませんが、それを未然に防ぐための防止策と、影響を最低限にとどめる対応策を組み上げることは可能です。特に、大規模なプロジェクトであれば、事前にある程度のデグレは起きるものであることを踏まえて、計画を立てていきましょう。そして、デグレへの対策には、テストが欠かせません。テストの重要性を踏まえ、対策を練り上げるようにしましょう。