リファクタリング
リファクタリングとは
リファクタリングは、外から見た動作を変えずにコードの内部構造を改善する作業です。機能追加でもバグ修正でもなく、「同じ動きをする、より読みやすく変更しやすいコード」に書き換えることを指します。
コードは機能追加や修正を重ねるうちに複雑になり、[[技術的負債]] として蓄積していきます。リファクタリングは、その負債を計画的に返済し、開発スピードを維持するための日常的な手入れです。
代表的なリファクタリングの例
| 手法 | 内容 |
|---|---|
| 名前の変更 | 意図が伝わる変数名・関数名に直す |
| 関数の抽出 | 長い処理の一部を意味のある単位で関数に切り出す |
| 重複の除去 | 同じロジックのコピーを1か所にまとめる |
| 条件式の単純化 | 深いネストを早期リターンなどで平らにする |
| マジックナンバーの定数化 | 86400 を SECONDS_PER_DAY のような名前付き定数にする |
// Before: 何の数字か分からない
if (elapsed > 86400) { expire(); }
// After: 意図が名前で伝わる
const SECONDS_PER_DAY = 86400;
if (elapsed > SECONDS_PER_DAY) { expire(); }
安全に進めるための原則
- テストを先に用意する — [[自動テスト]] が「動作が変わっていない」ことの証明になります。テストのないリファクタリングは危険です。ただし内部の呼び出し手順まで [[テストダブル(モック・スタブ)]] で固定したテストは、動作が同じでも赤くなり安全網として働きません
- 小さいステップで進める — 一度に大改造せず、1手ずつ変更してはテストを回します
- 機能追加と混ぜない — 「動作を変える変更」と「構造を変える変更」を同じコミットに入れると、問題発生時の切り分けが困難になります
初学者向けポイント
- リファクタリングは「時間が余ったらやる特別作業」ではなく、[[テスト駆動開発]] のサイクルに組み込まれた日常の作業です
- 「動いているコードに触るな」と言われることもありますが、テストという安全網があれば話は変わります。触れないコードこそ負債の温床です
- どこを直すべきかの嗅覚は、[[クリーンコード]] の原則(良い名前・小さい関数・重複排除)が指針になります
- 改善の方向性に迷ったら「次にこのコードを変更する人が理解しやすいか」を基準にしましょう
関連技術とのつながり
- [[テスト駆動開発]] — サイクルの中にリファクタリングが組み込まれている
- [[自動テスト]] — 動作が変わっていないことを保証する安全網
- [[技術的負債]] — リファクタリングが返済する対象
- [[クリーンコード]] — 目指すべきコードの姿を示す指針
Q: リファクタリングの定義として正しいのはどれ?
- [x] 外から見た動作を変えずに内部構造を改善すること
- [ ] 新しい機能を追加すること
- [ ] バグを修正して動作を変えること
解説: リファクタリングは動作を保ったままコードを読みやすく変更しやすくする作業で、機能追加やバグ修正とは区別されます。
Q: 安全にリファクタリングするための前提として本文で挙げられているのはどれ?
- [ ] 一度に大規模な書き換えを行う
- [x] 自動テストを用意してから小さいステップで進める
- [ ] 機能追加と同じコミットにまとめて効率化する
解説: テストが「動作が変わっていない」証明になります。小さく進め、機能追加とは分離するのが原則です。
Q: マジックナンバーの定数化とはどんな改善?
- [ ] 数値をすべて文字列に変換すること
- [ ] 計算結果をキャッシュして高速化すること
- [x] 意味の分からない数値に名前付き定数を与えること
解説: `86400` を `SECONDS_PER_DAY` とするように、数値の意図を名前で伝える改善です。