ハロー、@seto_hi です。
最近は業務でリファクタリングをやっており、できるだけデグレをせずにリファクタする方法を考えてきました。
言語化のため、記事にしたいと思います。
リファクタリングの分類
まず、リファクタリングは2つに分類ができると思っています。
動作の変更がない修正(非破壊的修正)と、動作の変更が入る修正(破壊的修正)です。
例えばメソッドを別クラスに移動させたり、クラスに切り出したりするだけではほとんどの場合に動作の変更がないので、非破壊的修正と言えます。
アルゴリズムを変えたり、コードを全部書き換える場合などは破壊的修正になります。
では非破壊的修正だけすればいいのか
非破壊的修正だけを繰り返せば理論的にはデグレは発生しません。
しかし現実は破壊的修正も行わないとコードは綺麗にならないと思います。
破壊的修正の安全性を高める方法があります。テストをすることです。
可能な範囲はテストを書き、コードだけでカバー仕切れない場合はアプリを実行して手でテストをします。
破壊的修正によってコードを全部書き換えたとしても、テストで動作が保証されていればデグレを起こす可能性は下げることができます。
テストで動作の同一性が完全に保証されている場合はコードを全て書き換えても非破壊的修正と言えると思います。
手順化
リファクタリングをするにあたって大事なことは、手順を明確にすることです。
特に、各手順が非破壊的修正と破壊的修正のどちらであるかを分類することが大事です。
デグレが発生しやすいのは破壊的修正の部分であるため、そこを厚くテストするなどといった対策を立てやすくするためです。
現状の実装から理想的な実装に持って行くにあたり、どんな修正が必要なのか、手順に依存関係はあるのか、どこに破壊的変更を入れる必要があるのか、を洗い出して手順に落とします。
だいたいの場合は一段階で理想的な実装に持って行くのは難しいと思います。非破壊的修正を数手順行い、破壊的修正の範囲をできるだけ小さくすることによってデグレの可能性を減らすことができます。
実例
簡単な例ですが、MVCのコードをAndroidのRecommended app architectureにする例を考えます。
まずは通信などのロジックをRepositoryに切り出します。これはロジックをクラスに切り出すだけなので非破壊的修正です。AndroidStudioのRefactor機能を使えばより安全にできると思います。
ロジックが気に食わない場合、Repositoryのテストを書いてから修正をしていきます。これは破壊的修正ですが、テストによってデグレの可能性を減らすことができます。
次にViewModelを作成します。
通信などの処理をViewModelからRepository経由で行うようにし、結果をLiveDataに入れ、ActivityなどでObserveします。これは破壊的修正です。
Repositoryが返す結果によってLiveDataに何が入る、というテストを書くとViewModelに関する処理はデグレの可能性を減らすことができます。
ViewModelの動作は保証できても、ActivityでObserveする部分でデグレしている可能性が残ります。テストでも保証することが難しい部分であるため、この部分については実機でのテストなどで保証をすればよいのではないかと思っています。
こういった手順を踏めば、デグレを起こす可能性を減らすことができます。
注意すべき点を意識し、安全なリファクタリング生活を送りましょう。
以上!