設計を蝕む悪魔たち
9-2

YAGNI: 先回り実装をしない

「いずれ必要になりそう」と先回りで作り込んだロジックは、ほとんどの場合予測が外れて使われないまま残る。使われないコードは誰にも検証されず、仕様変更の拍子に動き出すと高確率でバグになる。YAGNI(You Aren’t Gonna Need It)は「実際に必要になったときにだけ実装せよ」という原則。今の仕様だけを作れば、構造は単純になり保守も速くなる。

経費精算に作り込まれた「いつかの外貨対応」

Bad

現仕様は円建てのみなのに、外貨換算と多段承認を見越したパラメータが居座っている

使われない先回り実装
class ExpenseReport:
    def __init__(
        self,
        amount: int,
        category: str,
        currency: str = "JPY",        # 海外出張対応「いずれ要りそう」
        exchange_rate: float = 1.0,   # 為替換算(呼び出し元は誰も渡さない)
        approval_route: list[str] | None = None,  # 多段承認(構想のみ)
    ) -> None:
        self.amount = amount
        self.category = category
        self.currency = currency
        self.exchange_rate = exchange_rate
        self.approval_route = approval_route or ["manager"]

    def amount_in_jpy(self) -> int:
        # 円建てしか来ないので、この換算が正しいか誰も検証していない
        return round(self.amount * self.exchange_rate)
Good

確定している仕様(円建て・上長1名承認)だけを最小の構造で実装する

今必要な分だけの実装
from dataclasses import dataclass

@dataclass(frozen=True)
class ExpenseReport:
    amount_jpy: int
    category: str

def needs_receipt(report: ExpenseReport) -> bool:
    return report.amount_jpy >= 5_000

外貨対応が本当に決まったら、そのとき確定した仕様(レート基準日や端数処理など)に合わせて設計し直すほうが結局速くて正確。言語化されていない要求への先回りは、デッドコードと複雑さを増やすだけで終わることが多い。

参考: 『良いコード/悪いコードで学ぶ設計入門』(ミノ駆動 著、技術評論社)第9章。コード例は原則を自分の題材で表現し直したオリジナル。
9-2

YAGNI: 先回り実装をしない

「いずれ必要になりそう」と先回りで作り込んだロジックは、ほとんどの場合予測が外れて使われないまま残る。使われないコードは誰にも検証されず、仕様変更の拍子に動き出すと高確率でバグになる。YAGNI(You Aren’t Gonna Need It)は「実際に必要になったときにだけ実装せよ」という原則。今の仕様だけを作れば、構造は単純になり保守も速くなる。

経費精算に作り込まれた「いつかの外貨対応」

Bad

現仕様は円建てのみなのに、外貨換算と多段承認を見越したパラメータが居座っている

使われない先回り実装
class ExpenseReport:
    def __init__(
        self,
        amount: int,
        category: str,
        currency: str = "JPY",        # 海外出張対応「いずれ要りそう」
        exchange_rate: float = 1.0,   # 為替換算(呼び出し元は誰も渡さない)
        approval_route: list[str] | None = None,  # 多段承認(構想のみ)
    ) -> None:
        self.amount = amount
        self.category = category
        self.currency = currency
        self.exchange_rate = exchange_rate
        self.approval_route = approval_route or ["manager"]

    def amount_in_jpy(self) -> int:
        # 円建てしか来ないので、この換算が正しいか誰も検証していない
        return round(self.amount * self.exchange_rate)
Good

確定している仕様(円建て・上長1名承認)だけを最小の構造で実装する

今必要な分だけの実装
from dataclasses import dataclass

@dataclass(frozen=True)
class ExpenseReport:
    amount_jpy: int
    category: str

def needs_receipt(report: ExpenseReport) -> bool:
    return report.amount_jpy >= 5_000

外貨対応が本当に決まったら、そのとき確定した仕様(レート基準日や端数処理など)に合わせて設計し直すほうが結局速くて正確。言語化されていない要求への先回りは、デッドコードと複雑さを増やすだけで終わることが多い。

参考: 『良いコード/悪いコードで学ぶ設計入門』(ミノ駆動 著、技術評論社)第9章。コード例は原則を自分の題材で表現し直したオリジナル。