この記事の目次
Step6: リファクタリングする
コードが動くようになったら、「より良いコード」にするためのリファクタリングを検討します。ただし、1年目は過度なリファクタリングは避け、基本的な改善に留めることが重要です。
リファクタリングとは
リファクタリング = 外部から見た動作を変えずに、コードの内部構造を改善すること
目的:
✅ 読みやすくする
✅ 保守しやすくする
✅ バグを減らしやすくする
注意:
❌ 機能を追加することではない
❌ パフォーマンスを上げることではない(別の話)
なぜリファクタリングが必要なのか
「動くコード」と「良いコード」は違う
動くコード:
- とりあえず期待通りの結果が出る
- 自分だけが分かる
良いコード:
- 期待通りの結果が出る
- 誰が読んでも分かる
- 修正しやすい
- バグが入りにくい
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();
ポイント:
- 略語を避ける(
cnt→count、btn→button) - 何を表しているか分かる名前にする
- 長くなっても意味が伝わる方が良い
改善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. 機能追加を別コミット
リファクタリングのタイミング
やるべきタイミング
✅ コードレビュー前
→ 指摘を減らせる
✅ バグ修正のついで
→ 原因となった分かりにくいコードを改善
✅ 新機能追加の前
→ 追加しやすい構造に整える
避けるべきタイミング
❌ 締め切り直前
→ リスクが高い
❌ よく分からないコード
→ 意図を理解してから
❌ テストがないコード
→ 壊れても分からない
実践チェックリスト
リファクタリング時は、以下を確認:
基本
- [ ] 動作が変わっていないことを確認した
- [ ] 小さな単位で改善している
- [ ] コミットを細かく分けている
改善内容
- [ ] 意味のある名前に変えた
- [ ] マジックナンバーを定数にした
- [ ] 長いメソッドを分割した
- [ ] 深いネストを減らした
- [ ] 重複コードをまとめた
注意点
- [ ] 他人のコードを勝手に大きく変えていない
- [ ] 時間をかけすぎていない
- [ ] 機能追加と混ぜていない
次のステップ
コードを整えたら、提出前の最終確認としてセルフチェックを行います。