14-3
条件を読みやすく抽出する
not や比較演算子が生のまま並んだ条件式は、読むたびに頭の中で「アクティブでない、つまり利用停止…」と翻訳させられる。条件式を目的を表す名前のメソッドに抽出し、データを持っているクラス側に置けば、ガード節が仕様書の文章のように読めるようになる。
否定演算子と比較式をそのまま読ませる貸出判定
✕ Bad
def register_loan(member: Member, book: Book) -> LoanRecord:
if not member.is_active:
raise LoanError("利用停止中の会員です")
if not book.in_stock:
raise LoanError("この蔵書は貸出中です")
if len(member.loans) >= LOAN_LIMIT:
raise LoanError("同時貸出の上限に達しています")
...✓ Good
class Member:
@property
def is_suspended(self) -> bool:
return not self.is_active
def has_reached_loan_limit(self) -> bool:
return len(self.loans) >= LOAN_LIMIT
def register_loan(member: Member, book: Book) -> LoanRecord:
if member.is_suspended:
raise LoanError("利用停止中の会員です")
if book.is_on_loan:
raise LoanError("この蔵書は貸出中です")
if member.has_reached_loan_limit():
raise LoanError("同時貸出の上限に達しています")
return LoanRecord(member_id=member.id, book_id=book.id,
due_date=date.today() + LOAN_PERIOD)抽出した名前は実装の説明(not is_active)ではなく業務の語彙(利用停止中か?)にする。Python では引数のない単純な判定は @property、引数や計算を伴う判定は通常のメソッドにすると自然。条件の持ち主にロジックを寄せる点で、低凝集の解消(第5章・第8章)にもつながる。