8-5
可視性は最小にする(情報隠蔽)
★★★内部用のつもりで作ったクラスや属性でも、公開されていれば誰かが使う。一度外部から参照されると、内部の都合で変更できない「動かせないコード」になる。外に見せる面は最小限に絞り、残りは隠すのが情報隠蔽。Python には強制機構がないからこそ、アンダースコア接頭辞と __all__ で意図を宣言する。
消費税計算の内部税率テーブル
✕ Bad
# tax/consumption_tax.py
class TaxRateTable:
"""消費税計算の内部用テーブル(のつもり)"""
def __init__(self) -> None:
self.rates: dict[str, Decimal] = {}
# 別モジュール側 — 公開されているので悪気なく直接いじれてしまう
from tax.consumption_tax import TaxRateTable
table = TaxRateTable()
table.rates['reduced'] = Decimal("0.09") # 軽減税率の誤更新が素通り✓ Good
# tax/consumption_tax.py
__all__ = ['ConsumptionTaxCalculator'] # 外に見せるのはこれだけ
class _TaxRateTable:
"""先頭アンダースコアでモジュール内部用と宣言"""
def __init__(self) -> None:
self._rates: dict[str, Decimal] = {
'standard': Decimal("0.10"),
'reduced': Decimal("0.08"),
}
class ConsumptionTaxCalculator:
def __init__(self) -> None:
self._table = _TaxRateTable()
def tax_on(self, amount: Decimal, category: str) -> Decimal:
... # 税率へのアクセスはこの面からだけJava なら package private を基本にして必要なものだけ public にする発想。Python の _ 接頭辞は強制力こそないが、linter や IDE が警告してくれるので「最初から全部公開」よりはるかに事故が減る。公開は後からでもできるが、非公開に戻すのは利用箇所が増えるほど難しくなる。