リファクタリングって、どこから手をつければいいんでしょうか?
コードの外から見た動作を変えずに、内部の構造を整理することですね。やり方さえ知れば、今日から少しずつ実践できますよ。
この記事では、リファクタリングの意味・やり方・現場での実践知識までを解説します。

本記事の専門性
現役エンジニアのZettoです。フリーランスエンジニアとして業務システム開発を複数経験しています。現場でリファクタリングの重要性を身をもって学んできました。
この記事を読めば、リファクタリングの意味・具体的なやり方・現場で使える実践知識が一通りわかります。
ぜひ参考にしてみてください。
リファクタリングとは

リファクタリングとは、「プログラムの動作を変えずに、コードの内部構造を整理すること」です。
この章では、リファクタリングの基礎を押さえていきます。
- リファクタリングの定義と目的
- バグ修正・機能追加との違い
- リファクタリングのメリット
それぞれ解説します。
リファクタリングの定義と目的
リファクタリングの定義はシンプルです。
「外から見た動作は変えずに、コードの中身を読みやすく・保守しやすく整理すること」
たとえば、動いているコードの変数名が`x`や`tmp`のような意味不明な名前になっていたとします。これを`userName`や`totalPrice`のような意味のある名前に変えるだけで、立派なリファクタリングです。
目的は主に2つです。
- コードの可読性を上げる:誰が読んでもわかりやすい状態にする
- 保守性を高める:将来の機能追加やバグ修正を楽にする
「動くコード」と「良いコード」は別物です。リファクタリングは、動くだけのコードを良いコードに育てる作業といえます。
バグ修正・機能追加との違い
リファクタリングと混同しやすいのが、バグ修正と機能追加です。
整理すると次のようになります。
- リファクタリング:動作を変えずに内部構造だけを整える
- バグ修正:誤った動作を正しい動作に修正する(動作が変わる)
- 機能追加:新しい機能を加える(動作が増える)
この違いは現場でも重要です。リファクタリング中に「ついでにバグを直そう」とすると、何が原因でテストが落ちたかわからなくなります。
作業を混ぜないことが、安全なリファクタリングの第一歩です。
リファクタリングのメリット
リファクタリングを定期的に行うことで、開発全体がスムーズになります。
主なメリットは次の通りです。
- コードが読みやすくなる:チームメンバーが理解しやすくなり、引き継ぎも楽になる
- バグが見つかりやすくなる:整理されたコードはバグの隠れ場所が少ない
- 機能追加が速くなる:構造が整っていると、新しい実装の見通しが立ちやすい
- 技術的負債(後述)が減る:放置すると後で何倍もコストがかかる問題を早めに解消できる
プログラミングの現場では「後で直せばいい」が積み重なり、手がつけられない状態になることがよくあります。リファクタリングはその予防策でもあるんですよね。
リファクタリングって、最初は「今すぐ必要?」と感じるかもしれません。でも、半年後・1年後のコードの状態を想像すると、やっておいた方がいいと体感でわかってきますよ。現場で汚いコードに向き合うたびに、「リファクタリングの習慣があれば…」と思うことが正直よくあります。
リファクタリングの具体的なやり方

ここからは、実際にどうやってリファクタリングするかを解説します。
- 変数名・関数名を意味のある名前にする
- 重複コードを関数にまとめる
- 複雑な条件分岐を整理する
- 多重ループを回避する
- リファクタリングをするタイミング
- 取り組む前の注意点
ひとつずつ見ていきましょう。
変数名・関数名を意味のある名前にする
一番取り組みやすいリファクタリングが、命名の改善です。
ブラウザでも動かしやすい JavaScript で解説しますね。
リファクタリング前(悪い例)
function calc(a, b) {
const x = a * b;
const y = x * 0.1;
return x + y;
}`calc`・`a`・`b`・`x`・`y`…何を計算しているのか、コードを読んでも全くわかりません。
リファクタリング後(良い例)
function calculatePriceWithTax(unitPrice, quantity) {
const subtotal = unitPrice * quantity;
const taxAmount = subtotal * 0.1;
return subtotal + taxAmount;
}関数名を`calculatePriceWithTax`(税込み価格を計算する)にするだけで、コードの意味が一目でわかります。変数名も`unitPrice`(単価)・`quantity`(数量)・`subtotal`(小計)・`taxAmount`(税額)と整理しました。
命名ルールのポイントをまとめます。
- 動詞+名詞で関数名をつける:`getUser`・`calculateTotal`・““html validateEmail`など
- 省略しすぎない:`usrNm`より`userName`の方が読みやすい
- 誤解を招かない名前にする:`flag`より`isLoggedIn`の方が明確
命名は地味に見えて、実はコードの品質を大きく左右すると感じています。良い命名ができているコードは、コメントがほぼなくても意図が伝わります。逆に命名が悪いと、コメントで補おうとして余計ごちゃごちゃになるんですよね。
重複コードを関数にまとめる
同じ処理が複数の場所に書かれているコードは、リファクタリングの一番のターゲットです。
リファクタリング前(悪い例)
// 商品Aの税込み価格を表示
const priceA = 1000;
const taxA = priceA * 0.1;
console.log(priceA + taxA);
// 商品Bの税込み価格を表示
const priceB = 2000;
const taxB = priceB * 0.1;
console.log(priceB + taxB);
// 商品Cの税込み価格を表示
const priceC = 3000;
const taxC = priceC * 0.1;
console.log(priceC + taxC);同じ計算ロジックが3箇所に重複しています。税率が変わったとき、3箇所全部直す必要があります。これが10箇所・100箇所になると修正漏れが起きます。
リファクタリング後(良い例)
function displayPriceWithTax(price) {
const taxIncludedPrice = price + price * 0.1;
console.log(taxIncludedPrice);
}
displayPriceWithTax(1000);
displayPriceWithTax(2000);
displayPriceWithTax(3000);関数にまとめることで、税率が変わっても1箇所の修正で済みます。DRY原則(Don’t Repeat Yourself=同じことを繰り返すな)と呼ばれる、プログラミングの基本的な考え方です。
プログラミングの関数についての基礎知識は、以下の記事で解説しています。関数がまだよくわからない方はあわせて読んでみてください。

複雑な条件分岐を整理する
条件分岐(if文)が深くなりすぎているコードも、よくあるリファクタリング対象です。
リファクタリング前(悪い例)
function getDiscount(user) {
if (user.isLoggedIn) {
if (user.isMember) {
if (user.purchaseCount >= 10) {
return 0.2;
} else {
return 0.1;
}
} else {
return 0.05;
}
} else {
return 0;
}
}ネスト(入れ子)が深くなると、どの`if`がどの`else`に対応しているか、追うのが大変になります。
リファクタリング後(良い例)
function getDiscount(user) {
if (!user.isLoggedIn) return 0;
if (!user.isMember) return 0.05;
if (user.purchaseCount >= 10) return 0.2;
return 0.1;
}条件を満たさない場合に早期リターン(処理を早めに抜ける)することで、ネストをなくしました。コードの行数も減り、一目でロジックが把握できます。この手法は「早期リターン」または「ガード節」と呼ばれます。
多重ループを回避する
ループの中にループを入れる「多重ループ」は、コードが複雑になるだけでなく処理が遅くなる原因にもなります。
リファクタリング前(悪い例)
const orders = [
{ userId: 1, amount: 1000 },
{ userId: 2, amount: 2000 },
{ userId: 1, amount: 500 },
];
const users = [
{ id: 1, name: "田中" },
{ id: 2, name: "鈴木" },
];
// ユーザーごとの合計金額を計算(二重ループ)
for (const user of users) {
let total = 0;
for (const order of orders) {
if (order.userId === user.id) {
total += order.amount;
}
}
console.log(`${user.name}: ${total}円`);
}リファクタリング後(良い例)
const orders = [
{ userId: 1, amount: 1000 },
{ userId: 2, amount: 2000 },
{ userId: 1, amount: 500 },
];
const users = [
{ id: 1, name: "田中" },
{ id: 2, name: "鈴木" },
];
// まず注文をユーザーIDで集計しておく
const totalByUser = {};
for (const order of orders) {
totalByUser[order.userId] = (totalByUser[order.userId] || 0) + order.amount;
}
// ユーザー一覧と組み合わせて表示
for (const user of users) {
const total = totalByUser[user.id] || 0;
console.log(`${user.name}: ${total}円`);
}先に注文データを集計しておくことで、二重ループをなくしています。データ量が増えるほど、この差は大きくなります。
多重ループって、小規模なデータだと全然気にならないんですよね。でも実務でデータ件数が増えてきたとき、突然パフォーマンスが落ちて初めて「あのループが原因か」となることがあります。書くときから意識する習慣が大事だなと感じています。
リファクタリングをするタイミング
リファクタリングをいつやるかは、現場でよく話題になります。
一般的に言われているタイミングは次の3つです。
- 機能追加・バグ修正の前:「同じ場所を触るついでに整理する」という考え方。変更する箇所の周辺だけを対象にすることで、安全かつ効率的に進められる
- コードレビューで指摘を受けたとき:レビュアーの指摘は改善のヒント。指摘された箇所だけでなく、同じ問題がないか全体を確認する
- テストが通っている状態のとき:テストがある状態でやるのが安全。テストがない状態でリファクタリングを始めると、変更後に壊れているかどうかの判断ができない
逆に、リファクタリングに向かないタイミングもあります。
- 納期直前:「整理しようとしたらバグが出た」は最悪のタイミング
- テストがまったくない状態:動作保証ができないため、変更が怖くて進められなくなる
取り組む前の注意点
リファクタリングに入る前に、確認しておくべき点があります。
重要なのは、「テストが通っている状態を必ず確認してから始める」ことです。
テストがあれば、リファクタリング後に同じテストを走らせることで「動作が変わっていないか」を確認できます。テストなしでリファクタリングを進めると、変えたつもりがない動作が変わっていても気づけません。
また、次の点も意識しておくといいです。
- 一度に広い範囲を変えない:小さく変えて、こまめにテストを走らせる
- バージョン管理(Gitなど)を使ってこまめにコミットする:「戻せる状態」を保ちながら進める
- リファクタリングと機能追加を同時にやらない:問題が起きたとき、原因の切り分けができなくなる
現場に入りたてのころ、リファクタリングしながらバグ修正もして、テストも通っていない状態で「よし、完了」とコミットしてしまったことがあります。案の定、後からどこで何が壊れたかわからなくなって、かなり苦労しました。小さく・安全にがリファクタリングの鉄則だと、その経験から学びましたね。
現場エンジニアが知っておくべき実践知識

コードの書き方だけでなく、現場での立ち回りにも関わる知識を解説します。
- 技術的負債を後回しにするとどうなるか
- リファクタリングとテストコードの関係
- チーム開発でリファクタリングを提案する方法
- 初学者が今日から始められる練習ステップ
具体的に解説します。
技術的負債を後回しにするとどうなるか
技術的負債(ぎじゅつてきふさい)とは、「いま急いで書いた粗いコード」が将来の開発コストを押し上げる状態を、借金に例えた言葉です。
技術的負債は放置すると雪だるま式に膨らみます。
具体的にどうなるかを挙げると、次のような状態になっていきます。
- 小さな修正に時間がかかる:どこを変えると何が壊れるかわからないため、調査だけで半日かかる
- バグが増える:コードが複雑に絡み合っているため、1つ直すと別が壊れる
- 新機能が作れなくなる:土台が崩れかけているので、上に積み上げられない
- チームのモチベーションが下がる:「このコードは触りたくない」という雰囲気が広がる
僕が経験した現場でも、過去に急ぎで作られたコードに後から触れると、変数の意味もわからず、コメントもなく、テストも存在しない状態になっていることがありました。調査と修正で想定の3倍の時間がかかったこともあります。
リファクタリングは「綺麗にしたい」という趣味の話ではなく、開発速度を維持するための投資です。
リファクタリングとテストコードの関係
リファクタリングとテストコードはセットで考えるのが基本です。
テストコードとは、「このコードが正しく動くか自動で確認するプログラム」のことです。たとえば「税込み価格を計算する関数に1000円を渡したら1100円が返ってくること」をコードで検証する仕組みです。
テストがある状態でリファクタリングをすると、次のメリットがあります。
- リファクタリング後に自動でテストを走らせるだけで、動作が壊れていないか確認できる
- 安心して大胆にコードを整理できる
- バグが入り込んでも即座に気づける
逆にテストがない状態でリファクタリングをすると、「変えた後に正しく動いているかどうか」を手動で全部確認するしかありません。規模が大きくなるほど現実的でなくなります。
テストコードが書けない状況であれば、まずスコープを小さく絞り、「この関数の動作だけ確認できればいい」というレベルから始めるのが現実的です。
チーム開発でリファクタリングを提案する方法
チーム開発では、自分がリファクタリングしたいと思っても、勝手にやるとトラブルになることがあります。
理由は2つあります。
- 他のメンバーが同じコードを触っているとコンフリクト(競合)が起きる
- 「なぜ急に変えたのか」という混乱が生じる
チームでリファクタリングを進めるときは、次の流れが安全です。
- 対象の範囲と理由を明確にする:「この関数の命名が曖昧で、バグの温床になっている」など、具体的に説明できる状態にする
- チームに共有してから進める:コードレビューやミーティングで「ここをこう整理したい」と先に話す
- レビューを受ける:リファクタリングもプルリクエスト(変更申請)を出してレビューしてもらう
- 動作が変わっていないことをテストで証明する:「見た目は変えたけど、テストは全部通っています」と示せると信頼される
コードの話は感情的になりやすいので、「誰のコードが悪い」ではなく「このコードをこう改善するとチームの開発速度が上がる」という前向きな伝え方が大切です。
リファクタリングの提案は、言い方一つで受け取られ方が全然違います。「このコードは読みにくい」という言い方より「この部分を整理すると次の機能追加がスムーズになる」という言い方の方が、チームに受け入れられやすいですね。
初学者が今日から始められる練習ステップ
「リファクタリングって、実務じゃないとできないの?」と思う方もいるかもしれません。でも、初学者でも今日から練習できます。
おすすめのステップは次の通りです。
- STEP1:過去に自分が書いたコードを見返す:「1ヶ月前の自分のコード」を読み返すと、改善点がよく見えます。変数名や関数名を整理するだけでも立派な練習です
- STEP2:命名を直す:「x」「tmp」「data」のような変数名を、意味のある名前に変えてみます。動作は変えない、名前だけ変える、というルールを守りながら進めます
- STEP3:重複している処理を関数にまとめる:同じ処理が複数箇所に書かれていたら、関数として切り出してみます
- STEP4:変えた前後でテストを走らせる:テスト環境がない場合は、ブラウザのコンソールや簡単なスクリプトで動作確認する習慣をつけます
最初から完璧を目指さなくて大丈夫です。命名を1つ変えるだけでもリファクタリングです。スポーツと同じで、毎日の小さな積み重ねが力になります。
僕も最初のうちは「リファクタリング」という言葉すら意識せずにコードを書いていました。でも意識し始めてから、過去のコードを見返して「これは命名が雑だった」「ここは関数にできた」と気づく習慣がついてきて、コードの質が上がっていった感覚がありますね。
プログラミング学習をどこから始めればいいか迷っている方は、以下の記事もあわせて読んでみてください。学習の進め方を体系的にまとめています。

よくある質問

よくある質問と回答をまとめました。
- リファクタリングはどのくらいの頻度でやるべきですか?
- リファクタリングしてバグが増えた場合の対処法
- リファクタリングと「コードの書き直し」の違い
リファクタリングはどのくらいの頻度でやるべきですか?
「都度やる」が基本の答えです。
まとめてやろうとすると、対象が大きくなりすぎてリスクが高くなります。
機能追加・バグ修正のタイミングで「触ったついでに周辺を整理する」という習慣が、一番現実的で効果的です。
プロジェクトによっては、定期的に「リファクタリング週間」を設けているチームもあります。しかしそれが難しい場合は、コードレビューの中でリファクタリングの指摘・改善を行うだけでも積み重ねになります。
「いつかまとめてやろう」は、ほぼやらずに終わります。小さく・こまめにが習慣化のコツです。
リファクタリングしてバグが増えた場合の対処法
まず、落ち着いてテストを走らせることです。
バグが増えた場合は、次の手順で対処します。
- Gitで変更前の状態に戻す(`git revert`または`git reset`)
- 変更箇所を一つずつ確認しながら、小さく変えて都度テストを走らせる
- テストが落ちた変更を特定して修正する
「まとめて変えて一気にテスト」というやり方だと、どの変更がバグの原因かわかりにくくなります。1つ変えたら1回テストを走らせる細かいサイクルを守ることで、問題の特定が格段に楽になります。
バグが増えたこと自体は失敗ではなく、テストによって早期発見できたということです。
問題を後工程まで持ち越さずに済んだと前向きに捉えてください。
リファクタリングと「コードの書き直し」の違い
一言で言うと、「動作を変えるかどうか」の違いです。
リファクタリングは動作を変えません。変えるのはコードの中身(構造・命名・重複など)だけです。
一方、コードの書き直しは「今の動作も設計も全部捨てて、ゼロから作る」行為です。書き直しは動作が変わる可能性があり、テストも全部やり直す必要があります。
現場では、「リファクタリングするつもりで始めたのに、いつの間にか書き直しになっていた」というケースが起きやすいです。リファクタリングの範囲はあくまで「動作を変えない整理」に留める意識が大切です。書き直しが必要な場合は、チームで合意を取ってから計画的に進める方が安全です。
小さな改善の積み重ねがコードの質を変える

この記事では、プログラミングのリファクタリングについて解説しました。
ポイントを振り返ります。
- リファクタリングとは:動作を変えずにコードの内部構造を整えること
- 具体的なやり方:命名の改善・重複コードの関数化・条件分岐の整理・多重ループの回避
- 実践知識:技術的負債の怖さ・テストコードとの関係・チームでの提案方法・今日からできる練習ステップ
リファクタリングは、一気にやるものではありません。コードを触るたびに「この変数名はわかりやすいか?」「同じ処理が重複していないか?」と少しずつ意識していくだけで、コードの質は確実に上がっていきます。
まずは「変数名を1つ直してみる」から始めてみてください。
命名を直したり関数にまとめたりするだけで、コードってこんなに読みやすくなるんですね。今すぐ過去のコードを見返してみます。
その感覚が大事ですよ。過去の自分のコードを「読み返してみる」ことがリファクタリングの第一歩ですね。続けていくうちに、書くときから意識できるようになっていきます。
プログラミングの考え方全般についてさらに深めたい方は、以下の記事もあわせて読んでみてください。現場で使える思考法をまとめています。

また、リファクタリングが自然にできるレベルを目指すなら、スキルを体系的に磨く環境も重要です。プログラミングスクールの選び方は以下の記事で詳しく解説しています。

