1. ゴッドクラス(God Class)

一つのクラスがあらゆる処理を担う「何でも屋」になる状態。行数が数千行に膨らみ、単体テストが難しくなり、変更の影響が予測できなくなる。

❌ NG
Python — 責務が混在したゴッドクラス
class OrderManager:
    def create_order(self, items): ...        # ドメインロジック
    def validate_items(self, items): ...      # バリデーション
    def calculate_tax(self, amount): ...      # 税計算
    def send_confirmation_email(self): ...    # メール送信(外部IO)
    def save_to_database(self, order): ...    # DB永続化
    def generate_pdf_receipt(self): ...       # PDFレポート生成
    def update_inventory(self, items): ...    # 在庫管理
    def apply_coupon(self, code): ...         # クーポン処理
    def log_order_event(self, event): ...     # ログ記録
    # ...他100メソッド
✅ OK
Python — 責務ごとにクラスを分割する
class OrderService:           # 注文ユースケースの調整役
    def __init__(self, repo, notifier, tax_calc):
        self.repo = repo
        self.notifier = notifier
        self.tax_calc = tax_calc

    def place_order(self, items, coupon=None):
        order = Order.create(items)
        order.apply_coupon(coupon)
        order.total_tax = self.tax_calc.calculate(order)
        self.repo.save(order)
        self.notifier.send_confirmation(order)
        return order

class TaxCalculator: ...       # 税計算に専念
class OrderRepository: ...     # DB操作に専念
class OrderNotifier: ...       # 通知に専念

💡 単一責任の原則(SRP)

クラスを変更する理由は一つだけにする。変更の理由が「税法改正」「メール仕様変更」「DB変更」と複数あるなら、それだけクラスを分ける根拠になる。

2. 散弾銃手術(Shotgun Surgery)

一つの仕様変更を加えると、関係のない複数のクラスに修正が必要になる状態。ゴッドクラスとは逆に「一つの責務が複数クラスに散らばっている」ことが原因。

❌ NG
Python — 価格計算ロジックが複数クラスに散在
# 消費税率が変わったら 4 ヶ所修正が必要
class CartService:
    TAX_RATE = 0.10   # ← ここと

class InvoiceService:
    TAX_RATE = 0.10   # ← ここと

class ReceiptPrinter:
    TAX_RATE = 0.10   # ← ここと

class TaxReport:
    TAX_RATE = 0.10   # ← ここを変える
✅ OK
Python — 税率は一ヶ所に集約する
# tax_config.py(唯一の変更箇所)
TAX_RATE = 0.10

# 各クラスはインポートして参照するだけ
from tax_config import TAX_RATE

class CartService:
    def subtotal_with_tax(self, price): return price * (1 + TAX_RATE)

class InvoiceService:
    def invoice_total(self, price): return price * (1 + TAX_RATE)

3. 特性の横恋慕(Feature Envy)

あるメソッドが、自分のクラスよりも別クラスのデータやメソッドを多用している状態。そのメソッドは本来「移住すべき場所」が別にある合図だ。

❌ NG
Python — ReportService が Order のデータを過剰に参照
class ReportService:
    def generate_summary(self, order):
        # Order のデータばかり触っている → Order に移すべき
        total = sum(item.price * item.qty for item in order.items)
        discount = order.coupon.discount if order.coupon else 0
        tax = (total - discount) * order.tax_rate
        return {"subtotal": total, "discount": discount, "tax": tax}
✅ OK
Python — サマリ計算を Order クラス自身に持たせる
class Order:
    def summary(self):   # データを持つクラス自身がロジックを持つ
        total = sum(item.price * item.qty for item in self.items)
        discount = self.coupon.discount if self.coupon else 0
        tax = (total - discount) * self.tax_rate
        return {"subtotal": total, "discount": discount, "tax": tax}

class ReportService:
    def generate_summary(self, order):
        return order.summary()   # 委譲するだけ

4. マジックナンバー・マジック文字列

コード中に意味のない数値・文字列リテラルが直接埋め込まれている状態。「3」が何を意味するか、後から読む人には分からない。また値の変更が漏れやすくなる。

❌ NG
Python — マジックナンバーが散らばる
def get_discount(user):
    if user.age < 18:        # なぜ 18?
        return 0.2            # 20% 割引?
    if user.tier == 3:        # 3 は何のティア?
        return 0.15
    if user.status == "gold": # "gold" は何を表す?
        return 0.1
    return 0
✅ OK
Python — 定数・Enum で意図を明示する
from enum import IntEnum

MINOR_AGE_THRESHOLD = 18
MINOR_DISCOUNT_RATE  = 0.20
PREMIUM_DISCOUNT_RATE = 0.15
GOLD_DISCOUNT_RATE   = 0.10

class UserTier(IntEnum):
    STANDARD = 1
    PREMIUM  = 2
    ELITE    = 3

class UserStatus:
    GOLD   = "gold"
    SILVER = "silver"

def get_discount(user):
    if user.age < MINOR_AGE_THRESHOLD:
        return MINOR_DISCOUNT_RATE
    if user.tier == UserTier.ELITE:
        return PREMIUM_DISCOUNT_RATE
    if user.status == UserStatus.GOLD:
        return GOLD_DISCOUNT_RATE
    return 0

5. 深すぎる継承

継承の階層が 3 層を超えると、親クラスの変更がどこに影響するか追いにくくなる(脆弱な基底クラス問題)。多くの場合、継承よりコンポジション(has-a) が保守しやすい。

❌ NG
Python — 5 階層の継承
class Entity:       pass   # 第1層
class Person(Entity): pass # 第2層
class User(Person): pass   # 第3層
class AdminUser(User): pass # 第4層
class SuperAdmin(AdminUser): pass  # 第5層 — 変更が辛い
✅ OK
Python — コンポジションで権限を組み合わせる
class User:
    def __init__(self, profile, permissions):
        self.profile = profile            # コンポジション
        self.permissions = permissions    # コンポジション

# 権限を組み合わせて「管理者ユーザー」を作る
admin = User(
    profile=UserProfile(name="田中"),
    permissions=PermissionSet([Permission.READ, Permission.WRITE, Permission.ADMIN])
)

6. 命名のアンチパターン

6.1 意味のない名前

❌ NG
Python — 意図が伝わらない変数名
def calc(x, y, z):
    tmp = x * y
    ret = tmp - z
    return ret
✅ OK
Python — 意図が読める名前
def calculate_discounted_price(unit_price, quantity, discount_amount):
    subtotal = unit_price * quantity
    final_price = subtotal - discount_amount
    return final_price

6.2 誤解を招くブール名・関数名

❌ NG✅ OK理由
is_not_invalidis_valid二重否定は混乱を招く
check_user()is_user_active()戻り値の型が読めない
data, infouser_profile, order_summary何のデータかが不明
process()validate_and_save_order()何を処理するか不明
flag, flghas_paid, is_cancelled意味のないフラグ名

⚠️ 「後でリファクタリングすれば OK」は幻想

意味不明な名前は書いた直後なら本人にしか分からない。1ヶ月後は本人も忘れる。名前を付ける時間のケチりが、デバッグで何倍もの時間を奪う。