リファクタリングというもの

インターフェースを変更しなけりゃ中身を書き換えてよい、という話の解説。
インターフェースとは契約であり、入力は引数だけじゃなくて、内部コード(フレームワーク含)以外のすべて。出力は戻り値だけじゃなくて、内部コード以外に影響を与えるものすべて。しかしシンプルなコードを作るよう努力すれば、インターフェース(つまりメソッドだな)はお仕事を一つだけやる。そして大抵は引数と戻り値だけが入力と出力になって、それぞれデータじゃん。であれば、契約はコードでかけるじゃん。ということで、契約をコードで書いた。契約ってつまり外部設計であって、テストケースの集合体だな。ここまで頑張れば自動テストができる。よかったね。
自動テストができると何が嬉しいか。昨日徹夜してテストケース(としてのテストコード)が全部成功した。けど朝起きてみたらなんかコードがきたねえ。じゃあ、書き換えよう。でも、せっかく作ったんだし・・・書き換えるとまたバグがでるんじゃない?ここで自動テストの登場です!テストを1回行うのに1分しかかからない!であれば、書き換えてテストが全部成功すれば品質は同じ!すごい!
現実を見てみる。「書き換えてテストが全部成功すれば品質は同じ!すごい!」はい、ダウトです。テストケースの網羅性というものがありまして、テストが足りないテストケースに全部成功したからって、インターフェースが契約を満たしていることは保障できないのであった。まる。つまり、「テストケースの集合としてのテストコードがインターフェースの契約をすべて満たしていることを俺よりプログラムとビジネスが理解できている人にレビューしてもらってOKもらった」上でなければ、だめなんですねー。まあ問題は、大抵の場合プログラム書いている人以上にそのビジネスを理解している人はいない、ということですが。
あと契約を満たしていることの網羅性(まあ正常系と業務エラーフロー系)がうまく作れていたとしても、怪しい入力値が出てきたときにちゃんと例外として弾けるのか?という問題もあり、これもおさえる必要があります。そしてこれがめんどい。怪しい入力値を作り出すために境界値を洗ってテストケースをかけ算していくわけ。ただし、コード上でif文とかがネストしていない変数同士を組み合わせてテストケース作っても、たいてい意味がないので気をつけて!データ上独立事象なら、テストケースは足し算だよ!
最後にコードとテストケースの対応づけがぐちゃぐちゃになるからカバレッジを計測してテスト漏れがないかどうか確かめる。と、ここまでやったコードについては、リファクタリング・・・いらねーよ。リファクタリングが必要なコードになる前に修正するだろ。勝負はリリース前についているってこった。
さてここまでは簡単な話。自分が頑張ればいいから。一方他人があんまり頑張らなかったコードを書き換えるか否か問題について。
コードに手を入れた時点で、そのインターフェース(まあメソッドでいいか)を呼び出した人は影響を受ける。汚れる。汚されちゃう。じゃあどこまで汚されるのか?それは、一番外側までだ。フロントエンドだ。たとえばWebアプリであり、Greasemonkeyスクリプトだったりする。その範囲をまず調べましょうということになる。.NETなら、NDepend使ってぐりぐりぐりー。俺大学生(偽)ー。とか。その結果、変更範囲が大したものじゃないと感じたなら、勇気を持ってマネージャーと闘うのだ。一方奥深くのコードだったら?とりあえず、単体テストをやってみて、結果が一致することを確かめて。。