密結合
8-5

可視性は最小にする(情報隠蔽)

内部用のつもりで作ったクラスや属性でも、公開されていれば誰かが使う。一度外部から参照されると、内部の都合で変更できない「動かせないコード」になる。外に見せる面は最小限に絞り、残りは隠すのが情報隠蔽。Python には強制機構がないからこそ、アンダースコア接頭辞と __all__ で意図を宣言する。

ポートフォリオ評価額の内部レートテーブル

Bad

内部用の為替レートテーブルが公開され、別モジュールから直接書き換えられている

全部公開のモジュール
# portfolio/valuation.py
class FxRateTable:
    """評価額計算の内部用テーブル(のつもり)"""

    def __init__(self) -> None:
        self.rates: dict[str, float] = {}


# 別モジュール側 — 公開されているので悪気なく直接いじれてしまう
from portfolio.valuation import FxRateTable

table = FxRateTable()
table.rates['USD'] = 150.0  # 検証なしの書き換えが素通り
Good

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

公開面を最小化したモジュール
# portfolio/valuation.py
__all__ = ['PortfolioValuation']  # 外に見せるのはこれだけ


class _FxRateTable:
    """先頭アンダースコアでモジュール内部用と宣言"""

    def __init__(self) -> None:
        self._rates: dict[str, float] = {}


class PortfolioValuation:
    def __init__(self) -> None:
        self._table = _FxRateTable()

    def amount_in_jpy(self, currency: str, amount: float) -> int:
        ...  # レートへのアクセスはこの面からだけ

Java なら package private を基本にして必要なものだけ public にする発想。Python の _ 接頭辞は強制力こそないが、linter や IDE が警告してくれるので「最初から全部公開」よりはるかに事故が減る。公開は後からでもできるが、非公開に戻すのは利用箇所が増えるほど難しくなる。

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

可視性は最小にする(情報隠蔽)

内部用のつもりで作ったクラスや属性でも、公開されていれば誰かが使う。一度外部から参照されると、内部の都合で変更できない「動かせないコード」になる。外に見せる面は最小限に絞り、残りは隠すのが情報隠蔽。Python には強制機構がないからこそ、アンダースコア接頭辞と __all__ で意図を宣言する。

ポートフォリオ評価額の内部レートテーブル

Bad

内部用の為替レートテーブルが公開され、別モジュールから直接書き換えられている

全部公開のモジュール
# portfolio/valuation.py
class FxRateTable:
    """評価額計算の内部用テーブル(のつもり)"""

    def __init__(self) -> None:
        self.rates: dict[str, float] = {}


# 別モジュール側 — 公開されているので悪気なく直接いじれてしまう
from portfolio.valuation import FxRateTable

table = FxRateTable()
table.rates['USD'] = 150.0  # 検証なしの書き換えが素通り
Good

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

公開面を最小化したモジュール
# portfolio/valuation.py
__all__ = ['PortfolioValuation']  # 外に見せるのはこれだけ


class _FxRateTable:
    """先頭アンダースコアでモジュール内部用と宣言"""

    def __init__(self) -> None:
        self._rates: dict[str, float] = {}


class PortfolioValuation:
    def __init__(self) -> None:
        self._table = _FxRateTable()

    def amount_in_jpy(self, currency: str, amount: float) -> int:
        ...  # レートへのアクセスはこの面からだけ

Java なら package private を基本にして必要なものだけ public にする発想。Python の _ 接頭辞は強制力こそないが、linter や IDE が警告してくれるので「最初から全部公開」よりはるかに事故が減る。公開は後からでもできるが、非公開に戻すのは利用箇所が増えるほど難しくなる。

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