密結合
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

内部クラスはアンダースコア接頭辞で隠し、公開面を __all__ で宣言する

公開面を最小化したモジュール
# 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 が警告してくれるので「最初から全部公開」よりはるかに事故が減る。公開は後からでもできるが、非公開に戻すのは利用箇所が増えるほど難しくなる。

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

内部クラスはアンダースコア接頭辞で隠し、公開面を __all__ で宣言する

公開面を最小化したモジュール
# 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 が警告してくれるので「最初から全部公開」よりはるかに事故が減る。公開は後からでもできるが、非公開に戻すのは利用箇所が増えるほど難しくなる。

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