C#上級

上級 C#で学ぶリファクタリング|アンチパターン編

導入

リファクタリングはソフトウェア開発における重要なプロセスであり、コードの可読性や保守性を向上させるために行われます。しかし、実務においては多くのアンチパターンが存在し、それらは開発者の意図とは裏腹に、コードの品質を低下させる原因となります。本記事では、C#を用いた具体的なシチュエーションを通じて、リファクタリングにおけるアンチパターンを掘り下げます。

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

重要な概念の整理

リファクタリングは、既存のコードの内部構造を改善しつつ、外部の動作を変えないことを目的としています。これにより、コードの理解が容易になり、将来的な変更がスムーズになります。ただし、リファクタリングのプロセスには注意が必要で、特にアンチパターンを避けることが重要です。

コード例(C#)


// アンチパターン例:長いメソッド
public class OrderProcessor
{
    public void ProcessOrder(Order order)
    {
        // 注文の検証
        if (order == null || order.Items.Count == 0)
        {
            throw new ArgumentException("無効な注文です");
        }

        // 支払い処理
        var paymentResult = PaymentService.ProcessPayment(order);
        if (!paymentResult.IsSuccess)
        {
            throw new InvalidOperationException("支払いに失敗しました");
        }

        // 注文の配送手配
        ShippingService.ShipOrder(order);

        // 注文の履歴を記録
        OrderHistory.Add(order);
    }
}

コードの行ごとの解説

  1. メソッドが一つの責任を持たず、複数の処理を行っている。
  2. エラーハンドリングがメソッド内に散在しており、可読性が低い。
  3. 将来的に処理が増えると、メソッドがますます肥大化する恐れがある。

アンチパターン編

上記のコード例には、いくつかのアンチパターンが見られます。特に「長いメソッド」は、リファクタリングにおいて避けるべき典型的な問題です。このメソッドは、注文の処理に関連する複数の責任を一つのメソッドに押し込めており、結果として可読性が低下しています。メソッドを小さく分割し、それぞれに明確な責任を持たせることで、可読性と保守性を向上させることができます。

例えば、以下のようにリファクタリングを行うことが考えられます。


// リファクタリング後:責任を分けたメソッド
public class OrderProcessor
{
    public void ProcessOrder(Order order)
    {
        ValidateOrder(order);
        ProcessPayment(order);
        ShipOrder(order);
        RecordOrderHistory(order);
    }

    private void ValidateOrder(Order order)
    {
        if (order == null || order.Items.Count == 0)
        {
            throw new ArgumentException("無効な注文です");
        }
    }

    private void ProcessPayment(Order order)
    {
        var paymentResult = PaymentService.ProcessPayment(order);
        if (!paymentResult.IsSuccess)
        {
            throw new InvalidOperationException("支払いに失敗しました");
        }
    }

    private void ShipOrder(Order order)
    {
        ShippingService.ShipOrder(order);
    }

    private void RecordOrderHistory(Order order)
    {
        OrderHistory.Add(order);
    }
}

このようにメソッドを分割することで、各メソッドは単一の責任を持つようになり、テストやデバッグが容易になります。

まとめ

  • リファクタリングはコードの品質を向上させるために不可欠なプロセスである。
  • 長いメソッドなどのアンチパターンを避けることで、可読性と保守性を改善できる。
  • 各メソッドに明確な責任を持たせることで、将来的な変更にも柔軟に対応できる。