機会主義的なリファクタリング
2011年11月1日
私がリファクタリングについて語り、書き始めた当初から、リファクタリングをより広範なソフトウェア開発プロセスにどのように組み込むべきか、という質問がよく寄せられていました。ソフトウェア開発ライフサイクルにリファクタリングのフェーズを設けるべきか、イテレーションの何割をリファクタリングタスクに費やすべきか、リファクタリングの担当者をどのように決めるべきか、といったことです。計画的なリファクタリングを行うべき場所もありますが、私はリファクタリングは機会主義的な活動として、コードを整理する必要があるときにはいつでも、誰でも行うことを推奨しています。

これは、誰かがコードが明確でないと感じたときはいつでも、その場で、少なくとも数分以内に修正する機会を利用すべきだということです。この機会主義的なリファクタリングは、「キャンプ場のルール」に従うとよく言われます。つまり、コードを来たときよりも良い状態にして去るということです。チームの全員がこれを行えば、毎日、コードベースの健全性に小さな貢献をすることになります。
この機会は、新しい機能を実装したり、バグを修正したりするさまざまな場面で訪れます。1つは準備的なリファクタリングで、何かを実装する前に、既存のクラスのAPIが異なる構造であれば、このタスクが簡単になることに気づく場合です。まず、あるべき姿にリファクタリングしてから、機能を追加し始めます。
機能を追加しているうちに、追加しているコードの一部に既存のコードとの重複があることに気づき、既存のコードをリファクタリングして整理する必要がある場合があります。このコードへの継続的な注意は重要ですが、テストがグリーンになったときだけリファクタリングする必要があることを忘れないでください。
何かを機能させたとしても、既存のクラスとのインタラクションを変更した方が良いことに気づくかもしれません。完了したと考える前に、その機会を利用して変更してください。
何か他のことをしている最中に機会を見つけることもあります。現在の思考を中断するのではなく、それをメモしておき、準備ができたら戻ってくるのが便利です。長く放置せず、その日のうちに、完了する前に戻ってきてください。
このようなリファクタリングは、価値のある機能の開発時間を奪うと反論する人もいます。しかし、リファクタリングの要点は、コードベースを扱いやすくし、チームがより迅速に価値を追加できるようにすることです。リファクタリングの機会を利用する時間を費やさないと、コードベースは徐々に劣化し、進捗が遅くなり、リファクタリングのイテレーションについてスポンサーと難しい会話をすることになります。
ここで、うさぎの穴に迷い込んでしまう危険性があります。1つ修正すると、別のもの、さらに別のものが見つかり、あっという間に深みに陥ってしまいます。熟練した機会主義的なリファクタリングには、いつ終わりにするかを判断する優れた判断力が必要です。コードを来たときよりも良い状態にしたいと思うでしょうが、本当に理想的な状態にするには、別の機会に訪れるのを待つこともできます。常に少しずつ改善していけば、頻繁に訪れる領域、つまり、クリーンなコードが最も価値のある領域に焦点を当てた大きな影響を与えることができます。プログラミングのほとんどの側面と同様に、この決定には思慮深さが必要です。
機会主義的なリファクタリングの特徴の1つは、作業中のコードベースのどの部分にも影響を与える可能性があることです。ほとんどの作業を1つのクラスで行っているかもしれませんが、コードのまったく異なる領域にあるクラスに問題を見つけることがあります。その局所性の欠如が、今すぐ変更を加えるのを妨げるべきではありません。コードベースの別の部分への変更を別の日に任せたいという誘惑がよくありますが、別の日はしばしば来ません。
リファクタリングは、優れた回帰テストスイートがあることに依存しており、テストが本来あるべき姿よりも弱いアプリケーションの一部に触れようとしている場合は注意が必要です。この場合、うさぎの穴にあまり深く入り込むことなく追加のテストを1つか2つ投入することは非常に理にかなっていることを覚えておいてください。また、テストがキャッチするかどうかを確認するために、意図的にエラーを発生させてみることは、セーフティネットの良さを感じるための方法になります。
私は、強力なコード所有権やフィーチャーブランチの使用など、機会主義的なリファクタリングに摩擦を引き起こすような開発プラクティスには警戒しています。これは実際、フィーチャーブランチを使用する上での私の主な懸念事項です。フィーチャーブランチを使用している場合、マージがより困難になるため、機会主義的なリファクタリングを控えさせられることがよくあります[1]。特に、ブランチが数日以上存続する場合はそうです。
私の感覚では、ほとんどのチームはリファクタリングを十分に実施していないため、リファクタリングを躊躇させるようなものには注意することが重要です。これを洗い出すのに役立つのは、ほんの1、2分しかかからないと確信している小さなリファクタリングを行うことを躊躇したと感じたときを認識することです。そのような障壁は、議論を促すべきサインです。したがって、躊躇したことをメモして、チームで話し合ってください。少なくとも、次の振り返り会で議論する必要があります。
私は最初から、リファクタリングはif文をタイプするのと同じくらい、プログラミングの定期的で不可分の要素として継続的に行うものだと考えてきました。しかし、リファクタリングには計画が必要だという誤解があります。確かに、計画的なリファクタリングの取り組みや、数ヶ月間全員の邪魔になっていた厄介なコードの塊を攻撃するために1、2日を費やす場所もあります。しかし、リファクタリングをうまく活用しているチームは、リファクタリングを計画する必要はほとんどなく、代わりに、プロジェクトを設計スタミナ仮説の幸福な曲線に保つための小さな調整の絶え間ない流れとしてリファクタリングを見るべきです。
参考文献
リファクタリングのワークフローに関する私の情報デッキでは、リファクタリングを仕事に組み込むことができるさまざまな方法について説明しています。
Ron Jeffriesは、散らかったコードを徐々にリファクタリングしていくこと、そしてなぜリファクタリングタスクをバックログに含めるべきではないのかを説明する素晴らしい視覚化を考案しました。
技術的負債のメタファーは、これらの問題に非常によく当てはまります。
注記
1: 最新のツールは役立ちますが、それでも意味的な競合によってつまずきます。