はじめに
こちらの記事は「リファクタリングでシステムを安定化!日頃の取り組みや工夫を教えてください by カオナビ Advent Calendar 2022」の 8 日目の記事として投稿しています。
私(@changeworlds)からは、私が普段から行っている取り組みや工夫についてご紹介いたします。
前提
よく機能追加とリファクタリング (refactoring) をごっちゃにして理解している人がいるため、リファクタリング (refactoring) とはどういうものなのかについてご説明します1。
リファクタリング (refactoring)
プログラムの外部から見た動作を変えずにソースコードの内部構造を整理すること
です。
リファクタリング (refactoring) の際に最も重要なこと
リファクタリング (refactoring) の際に最も重要なことはリファクタリング (refactoring) の定義をご覧いただければ分かる通り、「プログラムの外部から見た動作を変えずに」行うということです。
プログラムの外部から見た動作を変えずに行わないと、リファクタリング (refactoring) したことが害悪にさえなります(=「プログラムの外部から見た動作を変えてしまった」)。
そのため、リファクタリング (refactoring) の際は自動テストで、「プログラムの外部から見た動作を変えずに」行っているかどうかチェックできるようにしておくことが大事になってきます。
リファクタリング (refactoring) と自動テストの関係
リファクタリング (refactoring) における自動テストとは「プログラムの外部から見た動作を変えない = 挙動/振る舞いが変わっていないことをテストするもの」になります。
そのため、リファクタリング (refactoring) において自動テスト(を行っているテストコードへ)の変更をしてはいけないということです。
もし、あなたがリファクタリング (refactoring) の最中にテストコードの変更が必要になったのであれば、それは「プログラムの外部から見た動作を変えてしまっているため、リファクタリング (refactoring) ではない」か「自動テストのテストコードが適切なレベルで書かれていなかった」ことを意味しています。
リファクタリング (refactoring) における適切なテストコード
プログラムの外部から見た動作を変えてしまっている、いないは簡単に分かることです。では、適切なレベルのテストコードとはどういうものかと言われてすぐに答えられる人はいないと思います。
リファクタリング (refactoring) における適切な自動テストコードとは end-to-end のテスト をするテストコードになります。
end-to-end のテストが何かわからない人はいないと思うのですが、「リファクタリング (refactoring) 際に end-to-end のテストコードを変更しないとテストに失敗する」とおっしゃる人が時々いらっっしゃいます。
実際、テストコードを見せてもらうのですが、常にそのテストコードは end-to-end のテストコードではありませんでした。
end-to-end のテストのつもりで、 end-to-end のテストになっていないケースは
- 直接関数を呼んでテストしている
- 状態をテストしていない
といったことがよくあります。
機能追加とリファクタリング (refactoring) の流れ違い
ここまでリファクタリング (refactoring) の際に大事なことをご紹介してきました。最後に実際に私自身が行っている機能追加とリファクタリング (refactoring) の流れについてご紹介します。
機能追加の場合
- 機能追加するプロダクトコードを書く前にテストコードを書き、それが失敗することを確認する
- テストに成功するように機能追加のプロダクトコードを書く
リファクタリング (refactoring) の場合
- リファクタリング (refactoring) する箇所の自動テストコードがあるか確認する
- なければリファクタリング (refactoring) する箇所の自動テストコードを追加し、テストに成功することを確認する
- テストコードとプログラムの振る舞いを変えずに、プロダクトコードを整理する
おわりに
今回、私自身がリファクタリング (refactoring) の際に大事にしていることと、実際に私自身が行っている流れをご紹介しました。
ご紹介したリファクタリング (refactoring) の際に大事なことを行ってリファクタリング (refactoring) をすることで、システムが不安定になったり、ましてデグレードすることがなくなります。
適切なテストコードのレベルなど考える要素は増えてしまいますが、それによってシステムが不安定になったり、ましてデグレードすることがなくなるのであれば、みなさんにとって少しでも好ましい状況に変わるのではないかと思っていますので、今までされていなかったみなさんは今後試してみてください。
-
違いは十分理解しています!と多くの方がおっしゃるのですが、そういう人に限って、機能追加の Pull Request で機能追加と既存機能のリファクタリング (refactoring) やリアーキテクティング (re-architecting)の変更を同時にされるので、念の為ここでどういう意味でこの用語を使っているのかご説明しています。 ↩