定義
プログラムの振る舞い(外から見える動作)は変えずに、コードの構造だけを整える作業のことです。画面に表示される結果が変わってしまうなら、それはリファクタリングではありません。次に読む人が理解しやすく、新しい機能を追加しやすい状態にすることが目的です。
キッチンの引き出しを整理し直すこと
キッチンの引き出しを思い浮かべてみてください。使い始めのうちは、お玉やハサミを適当に入れてもすぐに見つかります。でも、調理器具が増えてくると話は別です。スプーンを1本取り出すだけでも、引き出し全体をひっくり返して探さなければならなくなります。
プログラムのコードも同じように散らかっていきます。急ぎで作った場当たり的な処理や、似たような記述があちこちに散らばったまま残ってしまうのです。後からそのコードを読む人は、どこを直せばいいのかを探すだけで時間を使い果たしてしまいます。
そこで開発者は、時々手を止めて引き出しの中を整理し直します。仕切りを入れて似た道具を一箇所にまとめるように、散らばったコードを用途ごとに名前をつけた小さな塊にまとめていくのです。
このとき、引き出し本来の役割は一切失われないという点がとても重要です。お玉でスープをよそうという使い道はそのまま変わりません。重複した道具をまとめたり不要なものを片付けたりして配置や整理法を変えても、できること自体は元のままなのです。
動作はそのまま、中身だけを変える
この作業には鉄則が1つあります。それは、外から見える動作を絶対に変えないことです。ボタンを押したときに表示される画面や計算結果は、作業前とまったく同じでなければなりません。
だからこそ、コードに手をつける前にまず安全ネットを張ります。コードが正しく動いているかを自動で確認してくれるテストを用意しておくのです。整理の途中でどこかに狂いが生じたら、そのテストがすぐに赤信号を点灯して知らせてくれます。
作業は細かく刻んで進めます。意味のわかりにくい変数名を明確な名前に変えたり、長く伸びきったコードの塊を名前のついた関数として切り出したり、3箇所にコピーされていた同じ計算を1箇所にまとめたりします。1つひとつは小さな手直しに見えても、積み重なるとコードを読むスピードが劇的に変わります。
一度に1つずつ手を入れて、その都度テストを実行するのが安全なやり方です。小さく変更して、すぐ確認するというサイクルを繰り返せば、もし問題が起きてもすぐに元の状態へ戻せます。
もう少し詳しく:新機能の追加やバグ修正との違い
コードを整理していると、バグを見つけることもあります。ついでに直したくなりますが、2つの作業を同時に混ぜてしまうと後で困ったことになります。もし不具合が起きたとき、整理のせいなのか、バグ修正のせいなのかが分からなくなってしまうからです。
もう少し正確に言うと、リファクタリングは機能の追加でもバグ修正でもありません。この3つは別のタイミングに分けて行い、記録(コミット履歴)も別々に残すのが鉄則です。そうすることで、後から不具合が見つかったときにも、どの時点まで巻き戻せばよいのかを特定しやすくなります。
この作業が必要なのは、単に見た目をきれいにしたいという好みの問題ではありません。読みにくいコードのままでは、新機能を1つ追加するのにかかる時間が雪だるま式に増えていきます。「触るのが怖いコード」が増えると、開発チーム全体の動きがどんどん鈍くなってしまうのです。
だからこそ多くの開発チームは、新しい機能を作る前にその周辺のコードをまず整えます。直しやすくしてから直すことこそが、結果として一番の近道になるのです。
よくある誤解
リファクタリングは、プログラムの処理速度を上げるパフォーマンス改善のことだ。
副次的に処理速度が上がることもありますが、それが本来の目的ではありません。動作はそのままで、コードを理解しやすく改修しやすい構造に整えることが目的です。
コードを最初から全部書き直すこともリファクタリングと呼ぶ。
ゼロから作り直す作業は「リライト(再作成)」と呼び、区別されます。リファクタリングは、既存のコードを小さな単位で少しずつ整えていく手法です。
日常で出会う場面
「a」や「tmp」のような曖昧な変数名を、「orderAmount(注文金額)」や「remainingStock(残りの在庫数)」のように意味がひと目でわかる名前に付け替えること。
3つの画面にそれぞれコピーされていた同じ計算式を1つの関数にまとめ、今後は1箇所を修正するだけで済むようにすること。
つまり ひとことで
リファクタリングとは、プログラムの動作は一切変えずにコードの内部構造だけを整え、以後の変更や機能追加をしやすくする作業のことです。