責務の集中
説明(どんな問題か)
どんな状態か?
- 1 つのクラスやモジュールが過剰な責任を持ちすぎている
- あらゆる処理がそのクラスの中にあり、変更や拡張時に全体に影響が及ぶ
- データ保持、処理実行、状態管理など全部入り
なぜ問題か?
- クラスの目的が曖昧になり、読みづらく変更が怖いコードになる
- テストが困難(多くの依存や前提を持つ)
- 再利用不可・責務分離失敗 → スパゲッティ化の温床
アンチパターンのコード例
- TypeScript
- PHP
- Python
// Godクラス:責務が全部入り
class OrderManager {
private orders: string[] = [];
private userEmail: string = "";
private discountType: string = "none";
setUser(email: string) {
this.userEmail = email;
}
addOrder(productId: string) {
this.orders.push(productId);
}
applyDiscount(type: string) {
this.discountType = type;
}
calculateTotal(): number {
let basePrice = this.orders.length * 1000;
if (this.discountType === "student") {
return basePrice * 0.8;
} else if (this.discountType === "member") {
return basePrice * 0.9;
}
return basePrice;
}
confirmOrder() {
// 1. 在庫調整
console.log("在庫を減らす");
// 2. メール通知
console.log(`メールを ${this.userEmail} に送信`);
// 3. ログ出力
console.log("注文完了ログ");
}
}
<?php
class OrderManager {
private array $orders = [];
private string $userEmail = "";
private string $discountType = "none";
public function setUser(string $email): void {
$this->userEmail = $email;
}
public function addOrder(string $productId): void {
$this->orders[] = $productId;
}
public function applyDiscount(string $type): void {
$this->discountType = $type;
}
public function calculateTotal(): float {
$basePrice = count($this->orders) * 1000;
if ($this->discountType === "student") {
return $basePrice * 0.8;
} elseif ($this->discountType === "member") {
return $basePrice * 0.9;
}
return $basePrice;
}
public function confirmOrder(): void {
// 1. 在庫調整
echo "在庫を減らす\\n";
// 2. メール通知
echo "メールを {$this->userEmail} に送信\\n";
// 3. ログ出力
echo "注文完了ログ\\n";
}
}
class OrderManager:
def __init__(self):
self.orders = []
self.user_email = ""
self.discount_type = "none"
def set_user(self, email: str):
self.user_email = email
def add_order(self, product_id: str):
self.orders.append(product_id)
def apply_discount(self, discount_type: str):
self.discount_type = discount_type
def calculate_total(self) -> float:
base_price = len(self.orders) * 1000
if self.discount_type == "student":
return base_price * 0.8
elif self.discount_type == "member":
return base_price * 0.9
return base_price
def confirm_order(self):
# 1. 在庫調整
print("在庫を減らす")
# 2. メール通知
print(f"メールを {self.user_email} に送信")
# 3. ログ出力
print("注文完了ログ")
問題点
- 注文データ管理・割引ロジック・通知処理・ログ記録すべてが同一クラスにある
- 「何をしてるクラスなのか」が曖昧
- 修正が波及しやすく、テスト不能な巨大クラスに成長しがち
パターン別のリファクタリング
対応可能なデザインパターン例
パターン | 概要 | 主な解決アプローチ |
---|---|---|
Facade | 共通 API を作って内部の複雑さを隠す | 複数機能を外部から簡潔に呼び出せるようにする |
Strategy | 振る舞い(戦略)を差し替え可能にする | 拡張しやすく、テストしやすい設計にする |
State | 状態ごとの処理を分離する | 条件分岐の代わりに状態クラスで処理 |
Composite | ツリー構造に整理し「個」と「集合」を統一的に扱う | 階層構造の責務を整理して、責任範囲を明確に |
Iterator | 内部構造の走査方法を抽象化 | 走査処理の統一とカプセル化によって、保守性向上 |