低凝集
5-1

static メソッドはデータと離れる

static メソッドはインスタンス変数を使えないため、データはむき出しのまま別の場所に置かれ、計算ロジックだけが切り離される。データを守る者がいなくなり、不正な値の混入や重複ロジックの温床になる。データとそれを操作するロジックは同じクラスに同居させる。

仕訳金額の合算

Bad

ロジックは static メソッド、データは生の dict。金額の整合性を誰も守っていない

データとロジックが別々の場所に
class JournalAmountLogic:
    @staticmethod
    def add(amount1: int, amount2: int) -> int:
        return amount1 + amount2


# データはむき出しの dict として別の場所に存在する
travel = {"account": "旅費交通費", "amount": 3_000}
extra = {"account": "旅費交通費", "amount": 1_200}

total = JournalAmountLogic.add(travel["amount"], extra["amount"])
travel["amount"] = -500  # 不正な値を入れても誰も止められない
Good

金額クラスにデータと検証と計算を同居させる。不正値は生成時点で遮断される

データとロジックを1つのクラスに
from dataclasses import dataclass


@dataclass(frozen=True)
class JournalAmount:
    value: int

    def __post_init__(self) -> None:
        if self.value < 0:
            raise ValueError("仕訳金額は0以上にしてください")

    def add(self, other: "JournalAmount") -> "JournalAmount":
        return JournalAmount(self.value + other.value)


total = JournalAmount(3_000).add(JournalAmount(1_200))

@staticmethod 自体が悪なのではなく、「データと一緒に動くべきロジック」をデータから引き離すのが問題。static にしたくなったら、そのロジックがどのデータの近くに居るべきかを先に考える。

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

static メソッドはデータと離れる

static メソッドはインスタンス変数を使えないため、データはむき出しのまま別の場所に置かれ、計算ロジックだけが切り離される。データを守る者がいなくなり、不正な値の混入や重複ロジックの温床になる。データとそれを操作するロジックは同じクラスに同居させる。

仕訳金額の合算

Bad

ロジックは static メソッド、データは生の dict。金額の整合性を誰も守っていない

データとロジックが別々の場所に
class JournalAmountLogic:
    @staticmethod
    def add(amount1: int, amount2: int) -> int:
        return amount1 + amount2


# データはむき出しの dict として別の場所に存在する
travel = {"account": "旅費交通費", "amount": 3_000}
extra = {"account": "旅費交通費", "amount": 1_200}

total = JournalAmountLogic.add(travel["amount"], extra["amount"])
travel["amount"] = -500  # 不正な値を入れても誰も止められない
Good

金額クラスにデータと検証と計算を同居させる。不正値は生成時点で遮断される

データとロジックを1つのクラスに
from dataclasses import dataclass


@dataclass(frozen=True)
class JournalAmount:
    value: int

    def __post_init__(self) -> None:
        if self.value < 0:
            raise ValueError("仕訳金額は0以上にしてください")

    def add(self, other: "JournalAmount") -> "JournalAmount":
        return JournalAmount(self.value + other.value)


total = JournalAmount(3_000).add(JournalAmount(1_200))

@staticmethod 自体が悪なのではなく、「データと一緒に動くべきロジック」をデータから引き離すのが問題。static にしたくなったら、そのロジックがどのデータの近くに居るべきかを先に考える。

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