Java上級

上級 Javaで学ぶリファクタリング|ケーススタディ編

導入

リファクタリングは、既存のコードを改善し、可読性や保守性を高めるための重要なプロセスです。特に大規模なプロジェクトでは、コードが複雑化しやすく、リファクタリングの必要性が増します。本記事では、架空のプロジェクトを通じて、リファクタリングの実践的なアプローチを探ります。

教科書レベルの解説(リファクタリング)

重要な概念の整理

リファクタリングとは、機能を変えずにコードの内部構造を改善することを指します。これにより、バグの発生を抑えたり、将来的な機能追加を容易にしたりすることが可能になります。一般的なリファクタリング手法には、メソッドの抽出、クラスの分割、インターフェースの導入などがあります。

コード例(Java)


// クラスのリファクタリング前のコード例
public class Order {
    private List items;
    
    public Order(List items) {
        this.items = items;
    }

    public double calculateTotalPrice() {
        double total = 0;
        for (Item item : items) {
            total += item.getPrice() * item.getQuantity();
        }
        return total;
    }

    public void printReceipt() {
        for (Item item : items) {
            System.out.println(item.getName() + ": " + item.getPrice() + " x " + item.getQuantity());
        }
        System.out.println("Total: " + calculateTotalPrice());
    }
}

コードの行ごとの解説

  1. Orderクラスは、アイテムのリストを持ち、合計金額を計算するメソッドとレシートを印刷するメソッドを含んでいます。
  2. calculateTotalPriceメソッドは、アイテムの価格と数量を用いて合計金額を計算します。
  3. printReceiptメソッドは、各アイテムの詳細を表示し、合計金額を表示します。
  4. このコードは機能的には問題ありませんが、責任が集中しており、テストや拡張が難しくなっています。

ケーススタディ編

あるEコマースサイトのプロジェクトで、注文処理のクラスが複雑になり、開発チームはリファクタリングを決定しました。特に、計算と印刷のロジックが同じクラスに含まれているため、各機能のテストが困難でした。この状況では、単一責任の原則に従い、クラスを分割することが求められます。

まず、合計金額を計算する責任を持つクラスを新たに作成します。次に、印刷の機能を担当するクラスも作成します。これにより、各クラスが明確な責任を持ち、テストが容易になります。


// リファクタリング後のコード例
public class Order {
    private List items;

    public Order(List items) {
        this.items = items;
    }

    public List getItems() {
        return items;
    }
}

public class OrderCalculator {
    public double calculateTotalPrice(Order order) {
        double total = 0;
        for (Item item : order.getItems()) {
            total += item.getPrice() * item.getQuantity();
        }
        return total;
    }
}

public class ReceiptPrinter {
    public void printReceipt(Order order) {
        for (Item item : order.getItems()) {
            System.out.println(item.getName() + ": " + item.getPrice() + " x " + item.getQuantity());
        }
        OrderCalculator calculator = new OrderCalculator();
        System.out.println("Total: " + calculator.calculateTotalPrice(order));
    }
}

まとめ

  • リファクタリングにより、クラスの責任を分割し、可読性と保守性を向上させることができました。
  • 明確な責任を持つクラスを設計することで、テストが容易になり、将来的な機能追加もスムーズに行えるようになります。