悪しき構造の弊害
1-1

意図が伝わらない命名(技術駆動・連番)

型名やコンピュータ用語をそのまま名前にする「技術駆動命名」、番号を振るだけの「連番命名」は、コードから業務の意図を消し去る。読み解くのに時間がかかり、理解が不十分なまま変更すればバグになる。名前と仕様の対応表を別ドキュメントで管理しても、メンテナンスが追いつかずドキュメントが嘘をつき始める。

01 売掛金管理クラスの命名

Bad

型名と通し番号だけの名前。売掛金の管理コードだとは誰にも読み取れない

技術駆動命名
class IntDataManager:
    int_value_01: int = 0
    int_value_02: int = 0
    bool_flag_03: bool = False

    def update_int_value_01(self, new_value: int) -> None:
        self.int_value_01 += new_value
        if self.int_value_01 > self.int_value_02:
            self.bool_flag_03 = True
Good

業務の言葉で命名する。フィールドもメソッドも「売掛金の与信管理」だと一目でわかる

意図が伝わる命名
class ReceivableBalance:
    """得意先ごとの売掛金残高"""
    balance: int = 0
    credit_limit: int = 0
    is_over_credit_limit: bool = False

    def record_sale(self, amount: int) -> None:
        self.balance += amount
        if self.balance > self.credit_limit:
            self.is_over_credit_limit = True

構造はまったく同じでも、名前だけで読解コストが桁違いに変わる。意図や目的にもとづいて名前を設計する方法は第10章で体系的に扱う。

02 連番で名付けられたバッチ処理

Bad

処理の中身は別管理のスプレッドシートを見ないとわからない。その対応表もやがて更新されなくなる

連番命名
class Batch001:
    def exec_01(self) -> None: ...
    def exec_02(self) -> None: ...
    def exec_03(self) -> None: ...

# 呼び出し順を変えていいのか、コードからは判断できない
batch = Batch001()
batch.exec_01()
batch.exec_03()
Good

メソッド名が処理内容そのもの。順序の妥当性もコードを読むだけで検討できる

処理内容を語る命名
class MonthlyClosing:
    """月次決算の締め処理"""
    def import_bank_statements(self) -> None: ...
    def reconcile_accounts(self) -> None: ...
    def lock_journal_entries(self) -> None: ...

closing = MonthlyClosing()
closing.import_bank_statements()
closing.reconcile_accounts()
closing.lock_journal_entries()

「コードとは別の対応表があるから大丈夫」は通用しない。仕様変更のたびに表の更新が漏れ、嘘の書かれたドキュメントが後任者にバグを埋め込ませる。

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

コーディング原則

章を選んで原則の Good/Bad コード対比を確認できます