# Refactoring

> Martin Fowlerのリファクタリング方法論に基づいた体系的なコード改善スキル。 コードスメルの検出から安全なリファクタリングの実施まで、テストを安全網として 段階的に品質を向上させます。「2つの帽子」を意識し、機能追加と分離して実施。

- Skill: `majiayu000/refactoring` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds add majiayu000/refactoring`
- Raw SKILL.md: https://api.skillmd.com/api/skills/majiayu000/refactoring/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: majiayu000 (https://skillmd.com/u/majiayu000)
- Updated: 2026-09-09
- Page: https://skillmd.com/skills/majiayu000/refactoring

---


# Refactoring Skill

外部から見た振る舞いを変えずに、内部の構造を改善するスキル。

## 対応領域

| 領域 | フォーカス | 詳細ガイド |
|------|-----------|-----------|
| Code Smell Detection | コードスメルの特定と優先順位付け | `./agents/code-smell-detector.md` |
| Backend | Python/FastAPIコードのリファクタリング | `./agents/backend-refactorer.md` |
| Frontend | TypeScript/SvelteKitコードのリファクタリング | `./agents/frontend-refactorer.md` |

## 判断フロー

```
リファクタリングが必要な状況は？
│
├─ 大規模コードベースの改善 ────────→ ✅ サブエージェント並列実行
│
├─ Backend/Frontend両方の改善 ────→ ✅ サブエージェント並列実行
│
├─ 単一の関数/クラスの改善 ────────→ ✅ 直接リファクタリング
│
├─ 変数名/メソッド名の変更のみ ───→ ✅ 直接リファクタリング（軽量）
│
├─ テストがない/不十分 ────────────→ ❌ 先にテストを追加
│
├─ 本番リリース直前 ───────────────→ ❌ リファクタリング延期
│
└─ 機能追加と同時に行おうとする ──→ ❌ 別々に実施
```

## サブエージェント並列リファクタリング

大規模なリファクタリングが必要な場合、専門サブエージェントを並列起動。

```
┌──────────────────────────────────────────────────────────────┐
│ 1. 分析フェーズ                                              │
│    └── Code Smell Detector でコードスメルを特定              │
├──────────────────────────────────────────────────────────────┤
│ 2. 計画フェーズ                                              │
│    └── 検出結果に基づいてリファクタリング計画を策定          │
├──────────────────────────────────────────────────────────────┤
│ 3. 実行フェーズ（並列可能）                                  │
│    ├── Backend Refactorer  → Pythonコードのリファクタリング  │
│    └── Frontend Refactorer → TypeScriptコードのリファクタリング│
├──────────────────────────────────────────────────────────────┤
│ 4. 検証フェーズ                                              │
│    └── テスト実行と動作確認                                  │
└──────────────────────────────────────────────────────────────┘
```

## 基本原則（Martin Fowler）

### リファクタリングとは

> 「外部から見た振る舞いを変えずに、内部の構造を改善すること」

**重要な特性**:
- 小さなステップで進める
- 各ステップ後にテストが通ることを確認
- 新機能の追加とリファクタリングを混ぜない

### 2つの帽子

```
🎩 機能追加の帽子          🧢 リファクタリングの帽子
├── 新しい機能を追加       ├── コードの構造を改善
├── 既存コードは変更しない  ├── 機能は追加しない
└── テストを追加           └── 既存のテストが通り続ける

⚠️ 両方の帽子を同時にかぶらない！
```

### 3回の法則

```
1回目: とにかく実装する
2回目: 似たようなことをする時、重複を感じつつも進める
3回目: 同じことを3回目にする時、リファクタリングする
```

## リファクタリングワークフロー（5ステップ）

```
    ┌───────────────────────────────────────────────────────┐
    │                                                       │
    ▼                                                       │
┌────────┐   ┌────────┐   ┌────────┐   ┌────────┐         │
│準備    │──→│テスト  │──→│小さな  │──→│繰り返し│         │
│        │   │確認    │   │ステップ│   │        │         │
└────────┘   └────────┘   └────────┘   └────────┘         │
                                            │              │
                                            ▼              │
                                       ┌────────┐         │
                                       │完了確認│─────────┘
                                       └────────┘
```

### Step 1: 準備

| 項目 | 内容 |
|------|------|
| テストカバレッジ確認 | 対象コードのテストが存在するか確認 |
| コードスメル特定 | 問題のあるコードパターンを識別 |
| 範囲決定 | 影響範囲を特定、小さな単位に分割 |

### Step 2: テストの確認

```bash
# Backend
poetry run pytest
poetry run pytest --cov=src --cov-report=term-missing

# Frontend
npm run test
```

- すべてのテストがグリーンであること
- カバレッジが十分であること（目標: 80%以上）

### Step 3: 小さなステップで変更

1. **1つのリファクタリングを選択** → 最小単位に分解
2. **変更を適用** → コンパイル/構文チェック
3. **テストを実行** → `poetry run pytest -x`
4. **コミット** → 小さな単位でコミット

### Step 4: 繰り返し

- Step 3を繰り返す
- 各ステップ後にテストを実行
- 問題があれば即座にロールバック

### Step 5: 完了確認

- 全テストを実行
- コードレビュー（変更前後の比較）
- 動作確認（開発サーバーでの確認）

## コードスメル一覧

### Bloaters（肥大化）

| コードスメル | 症状 | 対処法 |
|-------------|------|--------|
| Long Method | 長すぎるメソッド | Extract Method |
| Large Class | 責務が多すぎるクラス | Extract Class |
| Primitive Obsession | プリミティブ型の多用 | Replace Primitive with Object |
| Long Parameter List | パラメータが多すぎる | Introduce Parameter Object |

### Object-Orientation Abusers（OOP違反）

| コードスメル | 症状 | 対処法 |
|-------------|------|--------|
| Switch Statements | 条件分岐の多用 | Replace Conditional with Polymorphism |
| Temporary Field | 時々しか使わないフィールド | Extract Class |
| Refused Bequest | 継承の誤用 | Replace Inheritance with Delegation |

### Change Preventers（変更困難）

| コードスメル | 症状 | 対処法 |
|-------------|------|--------|
| Divergent Change | 1つのクラスが複数の理由で変更 | Extract Class |
| Shotgun Surgery | 1つの変更が複数クラスに影響 | Move Method, Move Field |

### Dispensables（不要なもの）

| コードスメル | 症状 | 対処法 |
|-------------|------|--------|
| Duplicate Code | 重複コード | Extract Method, Pull Up Method |
| Dead Code | 使われていないコード | 削除 |
| Speculative Generality | 過剰な汎用化 | 不要な抽象化を削除 |

### Couplers（結合度の問題）

| コードスメル | 症状 | 対処法 |
|-------------|------|--------|
| Feature Envy | 他クラスのデータを多用 | Move Method |
| Inappropriate Intimacy | クラス間の過度な結合 | Move Method, Extract Class |
| Message Chains | 長いメソッドチェーン | Hide Delegate |

## 主要リファクタリングカタログ

### Extract Method（メソッドの抽出）

```python
# Before: 長いメソッド
def print_owing(self):
    print("***********************")
    print("*** Customer Owes ***")
    print("***********************")
    outstanding = sum(order.amount for order in self._orders)
    print(f"name: {self._name}")
    print(f"amount: {outstanding}")

# After: メソッドを抽出
def print_owing(self):
    self._print_banner()
    outstanding = self._calculate_outstanding()
    self._print_details(outstanding)

def _print_banner(self): ...
def _calculate_outstanding(self) -> float: ...
def _print_details(self, outstanding: float): ...
```

### Extract Class（クラスの抽出）

```python
# Before: 責務が多すぎるクラス
class Person:
    def __init__(self, name: str, office_area_code: str, office_number: str):
        self._name = name
        self._office_area_code = office_area_code
        self._office_number = office_number

# After: 電話番号を別クラスに抽出
@dataclass
class TelephoneNumber:
    area_code: str
    number: str

class Person:
    def __init__(self, name: str, telephone: TelephoneNumber):
        self._name = name
        self._telephone = telephone
```

### Replace Conditional with Polymorphism

```python
# Before: switch文による条件分岐
def calculate_pay(employee_type: str, hours: int) -> float:
    if employee_type == "engineer":
        return hours * 50
    elif employee_type == "manager":
        return hours * 75 + bonus()
    # ...

# After: ポリモーフィズムを使用
class Employee(ABC):
    @abstractmethod
    def calculate_pay(self, hours: int) -> float: pass

class Engineer(Employee):
    def calculate_pay(self, hours: int) -> float:
        return hours * 50
```

## 安全なリファクタリングルール

### DO ✅

- **テストファースト**: リファクタリング前にテストがグリーンであることを確認
- **小さなステップ**: 1つのリファクタリングを完了 → テスト → コミット → 次へ
- **機能追加との分離**: リファクタリングを完了してから機能追加
- **ロールバック準備**: `git reset --hard HEAD` で即座に戻れる状態を維持

### DON'T ❌

- 複数のリファクタリングを同時に実施
- テストを実行せずに進める
- 「ついでに機能も追加しよう」
- 「このバグも一緒に直そう」

## レイヤー別リファクタリング

### Domain層

```python
# Before: プリミティブ型の多用
class Order:
    def __init__(self, amount: float, currency: str): ...

# After: 値オブジェクトの抽出
@dataclass(frozen=True)
class Money:
    amount: Decimal
    currency: str

class Order:
    def __init__(self, total: Money): ...
```

### UseCase層

```python
# Before: 複数の責務を持つユースケース
class UserUseCase:
    def create_user(self, data): ...
    def update_user(self, id, data): ...
    def delete_user(self, id): ...

# After: 単一責務に分割
class CreateUserUseCase:
    def execute(self, input: CreateUserInput) -> CreateUserOutput: ...
```

### API層

```python
# Before: ルーターにロジックが混在
@router.post("/users")
async def create_user(data: dict):
    if not data.get("email"):
        raise HTTPException(400, "Email required")
    # ビジネスロジックがここに...

# After: ルーターは薄く
@router.post("/users", response_model=UserResponse)
async def create_user(
    data: UserCreateRequest,
    usecase: CreateUserUseCase = Depends(get_create_user_usecase)
):
    return await usecase.execute(data)
```

## リファクタリングチェックリスト

### 🔴 開始前（必須）

- [ ] テストが存在し、すべてグリーン
- [ ] コードスメルを特定した
- [ ] リファクタリングの範囲を決めた
- [ ] 影響範囲を把握した

### 🟡 各ステップ（推奨）

- [ ] 1つのリファクタリングのみを実施
- [ ] テストを実行した
- [ ] テストがグリーン
- [ ] 変更をコミットした

### 🟢 完了時

- [ ] すべてのテストがグリーン
- [ ] コードの可読性が向上した
- [ ] 新たなコードスメルが発生していない

## ベストプラクティス

### DO ✅

- テストを安全網として活用
- 小さなステップで進める
- 各ステップ後にコミット
- 80%の改善で良しとする
- 残りは次のイテレーションで

### DON'T ❌

- テストなしでリファクタリング
- 大きな変更を一度に実施
- 機能追加と同時に実施
- 完璧主義に陥る
- 範囲を広げすぎる

## 参照ファイル

| ファイル | 説明 |
|---------|------|
| `./agents/code-smell-detector.md` | コードスメル検出詳細 |
| `./agents/backend-refactorer.md` | Backendリファクタリング詳細 |
| `./agents/frontend-refactorer.md` | Frontendリファクタリング詳細 |
| `.claude/rules/code-style.md` | コードスタイル規約 |
| `.claude/rules/backend/layer-rules.md` | Backendレイヤールール |

## 参考資料

- Martin Fowler『リファクタリング（第2版）』
- Refactoring Guru: https://refactoring.guru/

