Aikido

コードの重複を排除する方法:技術的負債の削減

ロジックバグ

ルール
排除する 明らかな ファイル内の 重複を排除する。
重複する コード ブロック を増やす メンテナンス
負担 そして を増加させます。 リスク リスク 一貫性のない 更新の不整合リスク。
対応言語 45+

はじめに

単一ファイル内のコピー&ペーストされたコードは、時間の経過とともに増大するメンテナンスの悪夢を生み出します。同じロジックが複数の場所に現れる場合、バグ修正や機能更新はすべての出現箇所に適用されなければなりません。開発者は必然的に重複箇所の一つを見落とし、実行されるコードパスによって同じ操作が異なる結果を生み出すという一貫性のない動作につながります。この一貫性のなさは、重複したロジックが一見すると同じに見え、注意深く比較して初めて違いが明らかになるため、デバッグが困難です。

なぜ重要なのか

バグの伝播: 重複したコードにバグが存在する場合、1箇所で修正してもすべてが修正されるわけではありません。開発者は、他の場所にコピーが存在することに気づかずに最初の発生箇所を修正し、異なる条件下でバグが活動したままになります。

メンテナンス負担: 重複するブロックごとにメンテナンスコストが倍増します。ロジックを変更するには、すべてのコピーを見つけて更新する必要があり、ファイルが増えるにつれて重複の追跡が困難になります。

コード例

❌ 非準拠:

class OrderProcessor {
    async processStandardOrder(order) {
        if (!order.items || order.items.length === 0) {
            throw new Error('Order must have items');
        }
        const total = order.items.reduce((sum, item) => 
            sum + (item.price * item.quantity), 0);
        const tax = total * 0.08;
        const finalAmount = total + tax;
        return { total: finalAmount, tax };
    }
    
    async processExpressOrder(order) {
        if (!order.items || order.items.length === 0) {
            throw new Error('Order must have items');
        }
        const total = order.items.reduce((sum, item) => 
            sum + (item.price * item.quantity), 0);
        const tax = total * 0.08;
        const expressfee = 15.99;
        const finalAmount = total + tax + expressFee;
        return { total: finalAmount, tax, expressFee };
    }
}

誤っている理由: 検証ロジックと合計計算が重複しています。税率が変更されたり、検証の強化が必要になったりした場合、両方のメソッドを更新する必要があります。開発者が一方のメソッドで税計算を更新しても、もう一方を忘れる可能性があり、価格設定の不整合を引き起こします。

✅ 準拠済み:

class OrderProcessor {
    validateOrder(order) {
        if (!order.items || order.items.length === 0) {
            throw new Error('Order must have items');
        }
    }
    
    calculateSubtotal(items) {
        return items.reduce((sum, item) => 
            sum + (item.price * item.quantity), 0);
    }
    
    calculateTax(amount) {
        return amount * 0.08;
    }
    
    async processStandardOrder(order) {
        this.validateOrder(order);
        const subtotal = this.calculateSubtotal(order.items);
        const tax = this.calculateTax(subtotal);
        return { total: subtotal + tax, tax };
    }
    
    async processExpressOrder(order) {
        this.validateOrder(order);
        const subtotal = this.calculateSubtotal(order.items);
        const tax = this.calculateTax(subtotal);
        const expressFee = 15.99;
        return { total: subtotal + tax + expressFee, tax, expressFee };
    }
}

これが重要な理由:検証、計算、および税ロジックは単一のメソッドに一元化されています。税率を変更するには、ファイルを検索して重複を探すのではなく、1つのメソッドを変更するだけで済みます。各ヘルパーメソッドは独立してテストでき、両方の注文タイプは、改善やバグ修正を自動的に継承します。

まとめ

ファイル内の重複は、修正が最も容易で、即座にメリットをもたらします。パターンに気づいたらすぐに、重複したロジックをヘルパー関数やメソッドに抽出してください。スリー・オブ・スリーの法則は、コードが3回現れたらリファクタリングの時期であることを示唆しています。重複がファイル全体に広がるのを待たずに、対処しましょう。

よくある質問

ご質問がありますか?

リファクタリングの前に、どの程度の重複が許容されますか?

スリー・オブ・スリーの原則は良いガイドラインです。類似のコードが3回現れたら、それを抽出します。ただし、判断を用いる必要があります。2つの複雑な重複ブロックは即座の抽出を正当化するかもしれませんが、3つの単純な変数宣言はそうではないかもしれません。変更の可能性と不整合のコストを考慮してください。セキュリティ上重要なロジックや複雑なビジネスルールは直ちに重複排除すべきです。

重複したコードにわずかなバリエーションがある場合はどうなりますか?

差異をパラメーター化します。2つのコードブロックが変数のみで異なる場合、それらを共有関数へのパラメーターとして渡します。ロジックフローがわずかに異なる場合は、ストラテジーパターンまたは適切なデフォルト値を持つオプションパラメーターを使用します。時には、意図を不明瞭にする複雑な抽象化よりも、明確な差異を持つ重複の方が優れている場合もあるため、DRY原則と可読性のバランスを取ることが重要です。

コードが長くなっても重複を抽出すべきですか?

通常はそうです。記述的な名前を持つ関数は、たとえ総行数が増加しても、インラインの重複コードよりも意図を明確にすることがよくあります。単一箇所での保守の利点は、簡潔さへの懸念を上回ります。ただし、抽出によってコードを読むために複数の関数呼び出しをたどる必要が生じるような過度な間接性が生まれる場合は、その抽象化が適切かどうかを再検討してください。

大規模なファイル内の重複コードをどのように特定しますか?

繰り返されるif条件、同一のループ、または類似の関数構造のようなコピー&ペーストパターンを探してください。多くのIDEは構造的な重複を強調表示します。コードレビュー中に、ファイルを読み進める中で見覚えのあるコードを見つけたら、それを検索してください。ファイル内の重複については、手動での検査が最も速いことが多いです。リファクタリングを行う際は、ファイル内で近くに現れる最も明白な重複から始めてください。

重複するエラー処理コードについてはどうですか?

エラーハンドリングを再利用可能な関数として抽出するか、デコレーター/ミドルウェアパターンを使用します。複数の関数が同一のエラーロギングと変換を伴う同じtry-catch構造を共有している場合、それは排除すべき重複です。一貫したロギング、リトライ、またはフォールバック動作で操作をラップするエラーハンドリングユーティリティを作成し、エラーハンドリングロジックを繰り返す代わりにそれらのユーティリティを使用します。

積極的に変更していないレガシーコードの重複をリファクタリングする価値はありますか?

ボーイスカウトルールを適用します。コードは発見したときよりもきれいにしますが、触れていないコードはリファクタリングしません。関数を修正していて、同じファイル内に重複があることに気づいた場合は、変更の一部として修正します。技術的負債が新機能の妨げになっていない限り、レガシーコードに対して大規模なリファクタリングPRを作成しないでください。通常開発における漸進的な改善は、より持続可能です。

そもそも、重複をどのように防ぎますか?

コードをコピー&ペーストする前に、代わりに機能を抽出するべきか検討してください。コードレビュー中に重複するパターンにフラグを立て、抽出を要求します。2回以上繰り返される操作にはヘルパー関数を必須とするなど、重複を避けるためのチームの慣習を確立します。重複を具体的に探すコードレビューチェックリストを使用してください。予防は修正よりも簡単です。

今すぐ、安全な環境へ。

コード、クラウド、ランタイムを1つの中央システムでセキュアに。
脆弱性を迅速に発見し、自動的に修正。

クレジットカードは不要です | スキャン結果は32秒で表示されます。