5-4
インスタンス変数を使わないメソッドの置き場所
自分のインスタンス変数を一切使わず、引数で受け取ったデータばかりを読み書きするメソッドは、置き場所を間違えているサイン。ロジックを引数のデータ側クラスへ移せば、データとロジックが同居して凝集する。
請求書の早期支払割引
✕ Bad
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 が一度も登場しなかったら要注意。そのロジックが本当に使っているデータは引数の側にあり、引っ越し先はそのデータのクラスだ。