第4部:実務スキル / 第2章:実装作業

Step6: リファクタリングする

コードが動くようになったら、「より良いコード」にするためのリファクタリングを検討します。ただし、1年目は過度なリファクタリングは避け、基本的な改善に留めることが重要です。

📖 読了目安 約15分 対象:実装に取り組む方

リファクタリングとは

リファクタリング = 外部から見た動作を変えずに、コードの内部構造を改善すること

目的

  • 読みやすくする
  • 保守しやすくする
  • バグを減らしやすくする

注意

  • 機能を追加することではない
  • パフォーマンスを上げることではない(別の話)

なぜリファクタリングが必要なのか

「動くコード」と「良いコード」は違う

動くコード

  • とりあえず期待通りの結果が出る
  • 自分だけが分かる

良いコード

  • 期待通りの結果が出る
  • 誰が読んでも分かる
  • 修正しやすい
  • バグが入りにくい

1年目の現実

注意

1年目は「完璧なコード」を目指す必要はありません

1年目の優先順位

  1. 動くコードを書く(最優先)
  2. 基本的な読みやすさを確保
  3. 明らかな問題を修正

やりすぎ注意

  • ❌ 完璧なリファクタリングを目指す
  • ❌ 先輩が書いたコードを勝手に大きく変える
  • ❌ 時間をかけすぎる

1年目で押さえるべきリファクタリング

改善1: 意味のある名前に変更する

なぜ重要か:名前が悪いと、コードを読むたびに「これは何?」と考える必要がある

// Before: 何のことか分からない
int d = 30;
String s = "John";
List<Order> list = getOrders();

// After: 意味が明確
int daysUntilExpiry = 30;
String customerName = "John";
List<Order> pendingOrders = getOrders();

ポイント

  • 略語を避ける(cntcountbtnbutton
  • 何を表しているか分かる名前にする
  • 長くなっても意味が伝わる方が良い

改善2: マジックナンバーを定数に

なぜ重要か:数字だけでは意味が分からず、修正時に漏れが生じる

// Before: 30って何?0.1って何?
if (days > 30) {
    discount = price * 0.1;
}

// After: 意味が明確
private static final int PREMIUM_THRESHOLD_DAYS = 30;
private static final double PREMIUM_DISCOUNT_RATE = 0.1;

if (days > PREMIUM_THRESHOLD_DAYS) {
    discount = price * PREMIUM_DISCOUNT_RATE;
}

ポイント

  • 意味のある名前をつける
  • 同じ値を複数箇所で使う場合は特に重要
  • 仕様変更時に1箇所の修正で済む

改善3: 長いメソッドを分割する

なぜ重要か:長いメソッドは理解が難しく、テストも困難

// Before: 100行のメソッド
public void processOrder(Order order) {
    // バリデーション(20行)
    ...
    // 在庫チェック(15行)
    ...
    // 計算処理(30行)
    ...
    // DB登録(20行)
    ...
    // 通知送信(15行)
    ...
}

// After: 役割ごとに分割
public void processOrder(Order order) {
    validateOrder(order);
    checkStock(order);
    calculateTotal(order);
    saveToDatabase(order);
    sendNotification(order);
}

private void validateOrder(Order order) {
    // バリデーション処理
}

private void checkStock(Order order) {
    // 在庫チェック処理
}
// ...

ポイント

  • 1つのメソッドは1つの責任
  • 目安は20〜30行以内
  • メソッド名で何をするか分かるように

改善4: ネストを減らす

なぜ重要か:深いネストは読みにくく、バグを見逃しやすい

// Before: 深いネスト
public void process(Order order) {
    if (order != null) {
        if (order.getItems() != null) {
            if (!order.getItems().isEmpty()) {
                for (Item item : order.getItems()) {
                    if (item.getStock() > 0) {
                        // 処理
                    }
                }
            }
        }
    }
}

// After: 早期リターンでフラットに
public void process(Order order) {
    if (order == null) return;
    if (order.getItems() == null) return;
    if (order.getItems().isEmpty()) return;

    for (Item item : order.getItems()) {
        if (item.getStock() <= 0) continue;
        // 処理
    }
}

ポイント

  • 異常系は早期リターン
  • ループ内の条件はcontinueで抜ける
  • ネストは2〜3階層が目安

改善5: 重複コードをまとめる

なぜ重要か:同じコードが複数あると、修正漏れが発生する

// Before: 同じ処理が重複
public void createUser(User user) {
    if (user.getName() == null || user.getName().isEmpty()) {
        throw new ValidationException("名前は必須です");
    }
    // ...
}

public void updateUser(User user) {
    if (user.getName() == null || user.getName().isEmpty()) {
        throw new ValidationException("名前は必須です");
    }
    // ...
}

// After: 共通メソッドに抽出
public void createUser(User user) {
    validateUserName(user);
    // ...
}

public void updateUser(User user) {
    validateUserName(user);
    // ...
}

private void validateUserName(User user) {
    if (user.getName() == null || user.getName().isEmpty()) {
        throw new ValidationException("名前は必須です");
    }
}

ポイント

  • 2回以上同じコードがあれば検討
  • ただし、たまたま同じだけで意味が違う場合は分けたまま

リファクタリングの進め方

1. 動作確認できる状態を維持

重要:リファクタリング前と後で、動作が変わっていないことを確認する

方法

  • 自動テストがあれば実行
  • なければ手動で動作確認

2. 小さく、少しずつ

  • ❌ 悪い進め方:大規模な変更を一気に行う → どこで壊れたか分からない
  • ✅ 良い進め方:小さな改善を1つずつ行う → 問題があればすぐに戻せる

3. コミットを細かく

# リファクタリングごとにコミット
git commit -m "変数名をより明確な名前に変更"
git commit -m "calculateTotalメソッドを抽出"
git commit -m "早期リターンでネストを削減"

1年目がリファクタリングで注意すべきこと

注意1: 他人のコードを大きく変えない

  • ❌ やってはいけない:先輩が書いた100行のコードを「読みにくいから」と勝手に書き換える
  • ✅ やっていいこと:
  • 自分が書いたコードを改善
  • レビューで指摘されたコードを修正
  • 先輩に相談してから変更

注意2: 時間をかけすぎない

  • ❌ 完璧を目指して何時間もかける → 本来のタスクが終わらない
  • ✅ 基本的な改善にとどめる → 動くコード > 完璧なコード

注意3: 機能追加と混ぜない

  • ❌ リファクタリングと機能追加を同時にやる → バグの原因が分からなくなる → レビューが大変
  • ✅ 分けてコミット:
  1. リファクタリングだけをコミット
  2. 機能追加を別コミット

リファクタリングのタイミング

やるべきタイミング

  • コードレビュー前:指摘を減らせる
  • バグ修正のついで:原因となった分かりにくいコードを改善
  • 新機能追加の前:追加しやすい構造に整える

避けるべきタイミング

  • 締め切り直前:リスクが高い
  • よく分からないコード:意図を理解してから
  • テストがないコード:壊れても分からない

実践チェックリスト

リファクタリング時は、以下を確認:

基本

改善内容

注意点


次のステップ

コードを整えたら、提出前の最終確認としてセルフチェックを行います。

Step7: セルフチェック


関連ページ