低凝集
5-4

インスタンス変数を使わないメソッドの置き場所

自分のインスタンス変数を一切使わず、引数で受け取ったデータばかりを読み書きするメソッドは、置き場所を間違えているサイン。ロジックを引数のデータ側クラスへ移せば、データとロジックが同居して凝集する。

請求書の早期支払割引

Bad

Manager は自分の状態を何も持たず、引数の請求書データを直接書き換えている

よそのデータをいじるだけのメソッド
class InvoiceManager:
    def apply_early_payment_discount(self, invoice: InvoiceData) -> None:
        # self を一度も使っていない=このクラスに居る理由がない
        invoice.amount -= 2_000
        if invoice.amount < 0:
            invoice.amount = 0


invoice = InvoiceData(amount=1_500)
InvoiceManager().apply_early_payment_discount(invoice)
# 呼び出し側からは invoice が書き換わったことが見えにくい
Good

割引ロジックを請求書クラス自身に移し、結果は新しいインスタンスで返す

データ側クラスにロジックを引き取らせる
from dataclasses import dataclass

EARLY_PAYMENT_DISCOUNT = 2_000


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

    def apply_early_payment_discount(self) -> "Invoice":
        discounted = max(self.amount - EARLY_PAYMENT_DISCOUNT, 0)
        return Invoice(discounted)


invoice = Invoice(amount=1_500).apply_early_payment_discount()

メソッド内に self が一度も登場しなかったら要注意。そのロジックが本当に使っているデータは引数の側にあり、引っ越し先はそのデータのクラスだ。

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

インスタンス変数を使わないメソッドの置き場所

自分のインスタンス変数を一切使わず、引数で受け取ったデータばかりを読み書きするメソッドは、置き場所を間違えているサイン。ロジックを引数のデータ側クラスへ移せば、データとロジックが同居して凝集する。

請求書の早期支払割引

Bad

Manager は自分の状態を何も持たず、引数の請求書データを直接書き換えている

よそのデータをいじるだけのメソッド
class InvoiceManager:
    def apply_early_payment_discount(self, invoice: InvoiceData) -> None:
        # self を一度も使っていない=このクラスに居る理由がない
        invoice.amount -= 2_000
        if invoice.amount < 0:
            invoice.amount = 0


invoice = InvoiceData(amount=1_500)
InvoiceManager().apply_early_payment_discount(invoice)
# 呼び出し側からは invoice が書き換わったことが見えにくい
Good

割引ロジックを請求書クラス自身に移し、結果は新しいインスタンスで返す

データ側クラスにロジックを引き取らせる
from dataclasses import dataclass

EARLY_PAYMENT_DISCOUNT = 2_000


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

    def apply_early_payment_discount(self) -> "Invoice":
        discounted = max(self.amount - EARLY_PAYMENT_DISCOUNT, 0)
        return Invoice(discounted)


invoice = Invoice(amount=1_500).apply_early_payment_discount()

メソッド内に self が一度も登場しなかったら要注意。そのロジックが本当に使っているデータは引数の側にあり、引っ越し先はそのデータのクラスだ。

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