テストとコード品質

レガシーコードは既存動作を固定してから直す

割引関数の境界値9件を実行し、動作を保つリファクタリングと業務ルールの変更を切り分けます。負の金額を含む観察結果の扱い方も確認します。

読了 2 分
レガシーコードは既存動作を固定してから直すのカバー画像

レガシーコードを安全に変更するには、現在の結果を記録し、構造変更と方針変更を分けます。既存動作を記録するテストは、その業務ルールが正しいことの保証ではありません。

仕組みと設計の判断基準

リファクタリングは、外部から観察できる動作を保って内部構造を変える作業です。ルールが不明なら、通常の入力だけでなく分岐の境界、値の欠落、失敗経路を記録します。ここでは顧客区分Bの正の金額から30を引く関数を扱います。 一次資料

再現コード

実験用の割引関数を条件式による実装へ変えます。-1、0、1、29、30、31、100と別の顧客区分を含む9件を比較します。期待値は旧関数の呼び出し結果から作らず、表に独立して記述しました。

この独立したサンプルは2026-10-23に、arm64 macOS向けのApple Swift 6.4をSwift 6言語モードで実行しました。ネットワーク接続や追加パッケージは不要です。

Swiftファイル全体をダウンロード

ダウンロード先のフォルダーで実行してください。検証条件を満たさない場合はpreconditionで停止します。検証が削除されるため、-Ouncheckedは使用しないでください。

swift -swift-version 6 legacy-code-maintenance-problems.swift
func legacyPrice(kind: String, amount: Int) -> Int {
    if kind == "B" && amount > 0 { return amount - 30 }
    return amount
}

func refactoredPrice(kind: String, amount: Int) -> Int {
    let discount = kind == "B" && amount > 0 ? 30 : 0
    return amount - discount
}

let cases: [(String, Int, Int)] = [
    ("B", -1, -1), ("B", 0, 0), ("B", 1, -29),
    ("B", 29, -1), ("B", 30, 0), ("B", 31, 1),
    ("B", 100, 70), ("A", 100, 100), ("A", 0, 0)
]
var clampDifferences = 0
for (kind, amount, expected) in cases {
    precondition(legacyPrice(kind: kind, amount: amount) == expected)
    precondition(refactoredPrice(kind: kind, amount: amount) == expected)
    let changed = kind == "B" && amount > 0 ? max(0, amount - 30) : amount
    if changed != expected { clampDifferences += 1 }
}
precondition(clampDifferences == 2)
print("cases=9 preserved=9 clamp-differences=2")

実行結果と読み取り方

cases=9 preserved=9 clamp-differences=2

両実装は9件すべてで一致しました。負の合計を0に丸めると、金額1と29の結果が変わります。clamp-differences=2は失敗の隠蔽ではなく、その方針変更が既存の契約を2か所で変えることを確認する別の検証です。

適用範囲と注意点

負の請求額を許可すべきという結論ではありません。実際の割引方針は担当者に確認してください。小さい整数だけを使っており、税金、通貨の丸め、オーバーフロー、DBの副作用は未検証です。9件で全入力の同等性も証明できません。

次に確認すること

実際には呼び出し元と保存データを調べて観察例を増やします。負の金額を禁止するなら新しい期待値に合意し、別の変更として適用します。DBがテストを妨げる場合は、保存先の依存性注入へ進んでください。

関連する実験

出典と確認基準

  • Definition of RefactoringMartin Fowler · 著者の原文 · 確認日 2026年10月23日根拠: 実装の契約と説明の根拠です。出力は、この記事に掲載した実験で別途確認しました。