低凝集
5-6

マジックナンバーを定数に

ロジックの中に直書きされた数値は、書いた本人にしか意味が分からず、同じ数値があちこちに複製される。仕様変更のとき grep で全部を探し当てる賭けになる。意図を表す名前を付けた定数として1か所で宣言する。

報酬の源泉徴収計算

Bad

0.1021 や 1_000_000 が複数の関数に直書きされ、意味も改定時の修正範囲も不明

意味不明な数値の散らばり
def withholding_tax(fee: int) -> int:
    if fee <= 1_000_000:
        return int(fee * 0.1021)
    return int(1_000_000 * 0.1021 + (fee - 1_000_000) * 0.2042)


def net_payment(fee: int) -> int:
    # 同じ 0.1021 がここにも。税率改定で片方だけ直すと事故る
    return fee - int(fee * 0.1021)
Good

名前付き定数を1か所で宣言し、計算ロジックごと報酬クラスに集める

定数+値オブジェクトに集約
from dataclasses import dataclass
from decimal import Decimal

WITHHOLDING_RATE = Decimal("0.1021")        # 源泉徴収税率(100万円以下)
WITHHOLDING_RATE_OVER = Decimal("0.2042")   # 100万円超過分の税率
HIGH_RATE_THRESHOLD = 1_000_000


@dataclass(frozen=True)
class ProfessionalFee:
    amount: int

    def withholding_tax(self) -> int:
        base = min(self.amount, HIGH_RATE_THRESHOLD)
        over = max(self.amount - HIGH_RATE_THRESHOLD, 0)
        return int(base * WITHHOLDING_RATE + over * WITHHOLDING_RATE_OVER)

    def net_payment(self) -> int:
        return self.amount - self.withholding_tax()

定数化はゴールではなく入口。その定数を使う計算ロジックごと値オブジェクトに寄せると、税率改定が定数1行の修正で完結する。定数だけ共通モジュールに置いてロジックを散らかすと、低凝集に逆戻りする。

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

マジックナンバーを定数に

ロジックの中に直書きされた数値は、書いた本人にしか意味が分からず、同じ数値があちこちに複製される。仕様変更のとき grep で全部を探し当てる賭けになる。意図を表す名前を付けた定数として1か所で宣言する。

報酬の源泉徴収計算

Bad

0.1021 や 1_000_000 が複数の関数に直書きされ、意味も改定時の修正範囲も不明

意味不明な数値の散らばり
def withholding_tax(fee: int) -> int:
    if fee <= 1_000_000:
        return int(fee * 0.1021)
    return int(1_000_000 * 0.1021 + (fee - 1_000_000) * 0.2042)


def net_payment(fee: int) -> int:
    # 同じ 0.1021 がここにも。税率改定で片方だけ直すと事故る
    return fee - int(fee * 0.1021)
Good

名前付き定数を1か所で宣言し、計算ロジックごと報酬クラスに集める

定数+値オブジェクトに集約
from dataclasses import dataclass
from decimal import Decimal

WITHHOLDING_RATE = Decimal("0.1021")        # 源泉徴収税率(100万円以下)
WITHHOLDING_RATE_OVER = Decimal("0.2042")   # 100万円超過分の税率
HIGH_RATE_THRESHOLD = 1_000_000


@dataclass(frozen=True)
class ProfessionalFee:
    amount: int

    def withholding_tax(self) -> int:
        base = min(self.amount, HIGH_RATE_THRESHOLD)
        over = max(self.amount - HIGH_RATE_THRESHOLD, 0)
        return int(base * WITHHOLDING_RATE + over * WITHHOLDING_RATE_OVER)

    def net_payment(self) -> int:
        return self.amount - self.withholding_tax()

定数化はゴールではなく入口。その定数を使う計算ロジックごと値オブジェクトに寄せると、税率改定が定数1行の修正で完結する。定数だけ共通モジュールに置いてロジックを散らかすと、低凝集に逆戻りする。

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