ここまでたくさんのコードを紹介したよね。動くコードは素晴らしいんだけど、それだけで満足しちゃダメなんだ。今回は、もっと良いコードを書くための「リファクタリング」について解説していくよ。リファクタリングは、コードの見た目をきれいにしたり、わかりやすくしたりする作業のこと。機能を変えずにコードを改善するイメージだね。
なんでリファクタリングが大切なの?
「動くならこのままでいいじゃん!」って思うかもしれないけど、リファクタリングにはたくさんのメリットがあるんだ。
1. バグが減る!
ごちゃごちゃしたコードは、バグの温床になりやすいんだ。例えば、もしあなたが書いたコードがこんな感じだったらどうかな?
Java
public class Calculator {
public int calculate(int a, int b, String operation) {
if (operation.equals("add")) {
return a + b;
} else if (operation.equals("subtract")) {
return a - b;
} else if (operation.equals("multiply")) {
return a * b;
} else if (operation.equals("divide")) {
if (b != 0) {
return a / b;
} else {
System.out.println("Error: Cannot divide by zero.");
return 0;
}
} else {
System.out.println("Error: Invalid operation.");
return 0;
}
}
}
このcalculateメソッド、ちょっとごちゃっとしてるよね? もし新しい演算を追加しようとしたら、さらに条件分岐が増えて、どこかにバグが紛れ込んじゃう可能性が高くなるんだ。でも、リファクタリングしてコードを整理すると、それぞれの処理が明確になってバグを見つけやすくなるし、新しい機能を追加するときもミスが減るんだ。
2. コードが読みやすくなる!
数週間後、数ヶ月後に自分の書いたコードを見返してみて、「これ、何のために書いたんだっけ?」ってなった経験はないかな? コードが読みやすいと、そんな悩みも減るんだ。他の人があなたのコードを読むときも、スムーズに理解できるから、チームでの開発もしやすくなるよ。
例えば、こんなコードがあったとしよう。
Java
public class UserProcessor {
public void p(String n, int a, String e) {
// ユーザー情報を処理する
// ...
}
}
メソッド名がp、引数がn, a, eじゃ、何をしているのか全然わからないよね。これをリファクタリングして、もっと分かりやすくするんだ。
Java
public class UserProcessor {
public void processUser(String userName, int userAge, String userEmail) {
// ユーザー情報を処理する
// ...
}
}
これなら、一目で何をするメソッドで、どんな情報を受け取るのかがわかるよね!
3. 開発スピードが上がる!
一見すると、「リファクタリングに時間を使うなら、新しい機能を作った方がいいじゃん!」って思うかもしれない。でも、コードがきれいだと、後から機能を追加したり修正したりする手間がグッと減るんだ。結果的に、開発全体のスピードが上がるんだよ。
例えるなら、ごちゃごちゃした部屋で探し物をするのと、きちんと整理された部屋で探し物をするのと、どっちが早く見つかるかな? コードも同じで、整理されている方が作業がスムーズに進むんだ。
リファクタリングの具体的なテクニック(Java編)
じゃあ、具体的にどんな風にリファクタリングしていくのか、いくつかのテクニックを紹介するね。
1. 変数名やメソッド名を分かりやすくする
さっきの例でも出したけど、これが一番基本中の基本。何をしているか一目でわかるような名前に変えよう。
・悪い例:
Java
int x = 10; // 数値 String s = "hello"; // 文字列
・良い例:
Java
int quantity = 10; // 数量 String greetingMessage = "hello"; // 挨拶メッセージ
メソッド名も同じだよ。
・悪い例:
Java
public void calc() { ... } // 計算
良い例:
Java
public double calculateTotalPrice() { ... } // 合計金額を計算する
2. 長いメソッドを分割する
一つのメソッドにたくさんの処理が詰め込まれていると、何をしているのか分かりにくくなるんだ。そういう時は、役割ごとに小さなメソッドに分割しよう。
元のコード:
Java
public class OrderProcessor {
public void processOrder(Order order) {
// 1. 在庫チェック
if (!checkStock(order)) {
System.out.println("在庫が足りません。");
return;
}
// 2. 注文金額の計算
double totalAmount = calculateAmount(order);
// 3. 支払い処理
if (!processPayment(order, totalAmount)) {
System.out.println("支払い処理に失敗しました。");
return;
}
// 4. 注文履歴の保存
saveOrderHistory(order);
System.out.println("注文が正常に処理されました。");
}
private boolean checkStock(Order order) {
// 在庫チェックのロジック
return true; // 仮
}
private double calculateAmount(Order order) {
// 金額計算のロジック
return 100.0; // 仮
}
private boolean processPayment(Order order, double amount) {
// 支払い処理のロジック
return true; // 仮
}
private void saveOrderHistory(Order order) {
// 注文履歴保存のロジック
}
}
このprocessOrderメソッドは、在庫チェック、金額計算、支払い処理、注文履歴の保存と、たくさんのことをやっているよね。これを、それぞれ別のメソッドに分けてみよう。
リファクタリング後:
Java
public class OrderProcessor {
public void processOrder(Order order) {
if (!isStockAvailable(order)) {
System.out.println("在庫が足りません。");
return;
}
double totalAmount = calculateOrderAmount(order);
if (!makePayment(order, totalAmount)) {
System.out.println("支払い処理に失敗しました。");
return;
}
saveOrder(order);
System.out.println("注文が正常に処理されました。");
}
private boolean isStockAvailable(Order order) {
// 在庫チェックのロジック
return true; // 仮
}
private double calculateOrderAmount(Order order) {
// 金額計算のロジック
return 100.0; // 仮
}
private boolean makePayment(Order order, double amount) {
// 支払い処理のロジック
return true; // 仮
}
private void saveOrder(Order order) {
// 注文履歴保存のロジック
}
}
こうすることで、processOrderメソッドの役割は「注文を処理する」という上位の概念になり、それぞれの詳細な処理は別のメソッドに任せることができたね。これなら、もし在庫チェックのロジックだけ変更したくなったとしても、isStockAvailableメソッドだけを見ればいいから、影響範囲も小さくなるんだ。
3. 重複するコードをまとめる
同じようなコードが何箇所にも書かれている場合、それを一つのメソッドにまとめてしまおう。こうすることで、変更があったときに一箇所だけ修正すればよくなるし、コード量も減らすことができるんだ。
悪い例:
Java
public void printWelcomeMessageForAdmin() {
System.out.println("--- Welcome to Admin Panel ---");
System.out.println("You have admin privileges.");
}
public void printWelcomeMessageForUser() {
System.out.println("--- Welcome to User Panel ---");
System.out.println("You are a regular user.");
}
「— Welcome to … —」の部分が重複しているよね。
良い例:
Java
public void printWelcomeMessage(String panelName, String userTypeMessage) {
System.out.println("--- Welcome to " + panelName + " ---");
System.out.println(userTypeMessage);
}
public void printWelcomeMessageForAdmin() {
printWelcomeMessage("Admin Panel", "You have admin privileges.");
}
public void printWelcomeMessageForUser() {
printWelcomeMessage("User Panel", "You are a regular user.");
}
共通する部分をprintWelcomeMessageメソッドにまとめたことで、スッキリしたよね。
4. コメントを整理する
コメントはコードを理解するのに役立つけど、多すぎたり、情報が古かったりすると、かえって邪魔になることもあるんだ。リファクタリングしてコードが分かりやすくなれば、コメントの量を減らせることもあるよ。そして、コメントを書くなら、「何を」しているかではなく、「なぜ」そうしているのかを書くように心がけよう。
・悪い例:
Java
// ユーザー名を設定する user.setUserName(name);
こんなコメントは、コードを見ればわかるからいらないよね。
・良い例:
Java
// ユーザー名が20文字を超える場合は短縮する(表示上の制約のため) if (name.length() > 20) { name = name.substring(0, 20);} user.setUserName(name);
これは「なぜ」短縮するのかが書かれているから、意味のあるコメントだね。
いつリファクタリングするの?
リファクタリングは、いつでも好きな時にやればいいわけじゃないんだ。おすすめのタイミングはいくつかあるよ。
- 機能を追加する前: 新しい機能を追加する前に、既存の関連コードをきれいにすると、新しい機能をスムーズに組み込めるよ。
- バグを修正した後: バグが見つかった箇所は、コードが複雑になっていることが多い。修正するついでに、その周辺もきれいにすると良いね。
- コードレビューの時: チームでコードレビューをする際に、リファクタリングの提案をしたり、提案されたりすることもあるよ。
- 「ちょっと変だな」と感じた時: 自分でコードを書いていて、「なんか読みにくいな」「もっと良い書き方があるはず」と感じたら、それがリファクタリングのチャンス!
ただし、動かないコードをリファクタリングするのはNGだよ。まずは動くコードを書いて、テストで問題ないことを確認してからリファクタリングしようね。
まとめ
リファクタリングは、コードをきれいに保つための大切な習慣だよ。最初から完璧なコードを書くのは難しいから、後から見直して改善していく意識が重要なんだ。
- バグを減らす
- コードを読みやすくする
- 開発スピードを上げる
これらのメリットを理解して、少しずつリファクタリングを実践してみてほしいな。初めは難しく感じるかもしれないけど、慣れてくると「きれいなコードを書く楽しさ」がわかってくるはずだよ。
このブログの他の記事も読んでみてね!


コメント