SE(たぶん)の雑感記

一応SEやっている筆者の思ったことを書き連ねます。会計学もやってたので、両方を生かした記事を書きたいと考えています。 でもテーマが定まってない感がすごい。

プログラムを修正したときの影響範囲を考える

プログラム修正を依頼し、テスト仕様まで作ってもらった*1後輩との、とある会話。


後輩:修正箇所はこの部分とこの部分で、こう修正しました

筆者:はい*2

後輩:このソース(修正対象ソース)のこの部分は修正していないので、テストしません

筆者:いやまって、それじゃ不十分だよ


修正していないから、影響もないはずという気持ちはとても分かります。

しかし、そうは言っていられないのがプログラム修正です。

本当にバグは無いのか

結論から言えば、否です。

自分の修正で、自分が思ったところ以外のところがバグるなんてことは、よくある話です。

プログラムの階層構造、たとえばMVVMが厳密に守られていたとして、Viewの文言を一つ直しただけなら、バグはほかの場所でまず発生し得ないでしょう。

しかし、処理が内部に入り込むほど、影響の測定は難しくなります。

影響がないと言い切るには、どうしたらいいのでしょうか。

結論:変わっていないことを確認する

影響がないと言い切るには、直していない部分は何ら変わっていないことを確認すればよいです。

ソースを修正していないという事実ではなく、結果が変わっていないという事実をもって、影響がないと言い切るのがあるべき姿です。

変わっていないことを確認するテストを、リグレッションテスト(退行テスト)といいます。

では、それをどうやって担保すればよいでしょうか。

手動で担保

手段1:使用箇所の検索

文字検索等で、呼び出し箇所をすべて確認し、問題ないと担保を取る方法です。

これはこれで、なかなか効果あります。

ただ、可能なら事前に分析しましょう。

また、Visual StudioC#の開発をやっている場合には、参照の検索もとても有効な方法です。

修正したメソッド等を呼び出している箇所を参照検索で見つけ、その部分の影響を見る方法です。

きつい

これは、ソースが大規模だととてもしんどいです。

  • メソッドのネストが深い
  • 高度な抽象化、階層化

等の場合、地獄のような確認ラッシュが始まります。

手段2:ブレークポイントを置いて確認する

Viewから起動し、修正箇所にブレークポイントを置いて、デバッグ実行で呼び出し箇所を特定する、という方法もあります。

処理が呼び出されればそこで処理を止めてくれます。
呼び出されているかどうか確認するには、確実な方法です。

やっぱりきつい

良い方法なのですが、予想もしないところから呼ばれている場合もあるので…

いくらViewからデバッグするといっても、巨大なシステムの場合、全機能を触るというわけにもいきません。

デバッグは、あくまで「不具合確認」や「開発中の確認」に使うものと考えたほうが良いです。間違ってもリグレッションテストのためには使いわないようにしましょう。

どうやってもハードルになるもの

いろいろ書いていますが、最大のハードルは条件網羅がほぼ不可能である点にあります。

例えば、通常の運用では入ってこないデータに対するテストが必要な場合、何らかの手段で不正値を渡さねばなりません。

手動でプログラム修正の影響を検査するのは、最初は大したことなくても、徐々に難しくなっていきます。

また、動的言語の場合、手動で影響調査するのは地獄としか言いようがありません。

じゃあどうするの

設計段階の考慮

いくつかあります。

  • 階層を深くしない
  • 階層間を疎結合にする
  • 契約による設計を徹底する

プログラムの品質に関わる部分です。

そもそも、システム設計やプログラム設計の多くは、いかに安全に素早く変更するかを主軸に置いています。

裏側には、リグレッションテストで苦しんだ先人たちの苦労があるのだろうと思っています。
本を読めば、そのあたりの話はいくらでもわかります。『達人プログラマー』とかおすすめです。あまり苦労話は書いていないですが。

もっとも、修正が大変という理由で、設計に手を入れるのは、勇気が必要だろうと思います。

テストそのものを自動化する

自動化しましょう。単体テスト使いましょう。

正直、システムが通常受け付ける値のみを、システムから入力してテストするのは、無理があります。

正常値と異常値の範囲を定めて、その両方で想定通りの動きをするテストを作成し、関係ない修正を行った際に毎回テストを実行すれば、自動的に修正の影響がないことを確認できます。

テストがあることで、安心して修正できるのです。間違ってもテストで発見できるのです。

このような心理的安全性の確保はすごく大事です。

まあ、そのためには良い設計にしておき、ソースはちゃんとソース管理システムで管理するとか、他の環境も整備する必要はあります。

おわりに

プログラム修正の影響がないことは、自動テストで確保するのが最良だと思っています。

心理的安全性というのは本当に大事です。修正を間違っても気づけるという安心感は、一度体験してほしいです。

一方、自動テストでは担保しづらい部分があるのも事実です。
Viewのテストは相変わらず簡単ではないですし、DB単体テストSQL Server Data Toolsで見たことあるものの、これは無理だなぁと思った印象があります。

自動テストできない場合は、泥臭い検索とかやるしかない場合もあります。
そういうときは、「変わっていないこと」の担保方法には、十分に気を付けたいところです。(戒め)

*1:自動テストは、自動化困難な箇所であるため、無い

*2:この時点で条件間違っていたが、それは今回は省略