---
name: code-refactor
description: Proactively detect and execute code refactoring to maintain DDD architecture and code quality. Triggers: RF, refactor, 重構, 拆分, split, 模組化, modularize, 太長, cleanup.
---

# 程式碼重構技能

## 描述
主動偵測並執行程式碼重構，維持 DDD 架構和程式碼品質。

## 觸發條件
- 「重構這段程式碼」、「refactor」
- 「這個檔案太長了」
- 「模組化」、「拆分」
- **主動觸發**：偵測到程式碼超過閾值時

---

## 核心原則

> 📜 依據憲法第 7.3 條「主動重構原則」

```
重構不是改天換地，而是持續的小步快跑
每次提交都應該比上次更乾淨
```

---

## 閾值設定

### 📏 長度閾值

| 類型 | 警告 | 強制重構 |
|------|------|----------|
| 檔案 | > 200 行 | > 400 行 |
| 類別 | > 150 行 | > 300 行 |
| 函數 | > 30 行 | > 50 行 |
| 目錄檔案數 | > 10 個 | > 15 個 |

### 🔄 複雜度閾值

| 指標 | 警告 | 強制重構 |
|------|------|----------|
| 圈複雜度 | > 10 | > 15 |
| 巢狀深度 | > 3 層 | > 4 層 |
| 參數數量 | > 4 個 | > 6 個 |
| 依賴數量 | > 5 個 | > 8 個 |

---

## 重構模式庫

### 1️⃣ Extract Method（提取方法）

**觸發條件**：函數過長、重複邏輯

```python
# Before
def process_order(order):
    # 驗證訂單 (10 行)
    if not order.items:
        raise ValueError("Empty order")
    if order.total < 0:
        raise ValueError("Invalid total")
    # ... 更多驗證

    # 計算價格 (15 行)
    subtotal = sum(item.price * item.qty for item in order.items)
    tax = subtotal * 0.05
    total = subtotal + tax
    # ... 更多計算

    # 儲存訂單 (10 行)
    # ...

# After
def process_order(order):
    self._validate_order(order)
    total = self._calculate_total(order)
    self._save_order(order, total)

def _validate_order(self, order):
    """驗證訂單有效性"""
    if not order.items:
        raise ValueError("Empty order")
    # ...

def _calculate_total(self, order) -> Decimal:
    """計算訂單總金額（含稅）"""
    subtotal = sum(item.price * item.qty for item in order.items)
    return subtotal * Decimal("1.05")
```

### 2️⃣ Extract Class（提取類別）

**觸發條件**：類別職責過多、超過 150 行

```python
# Before: User 類別包含太多職責
class User:
    def __init__(self, name, email, ...):
        self.name = name
        self.email = email
        self.address_line1 = ...
        self.address_line2 = ...
        self.city = ...
        self.postal_code = ...

    def validate_email(self): ...
    def format_address(self): ...
    def calculate_shipping(self): ...

# After: 提取 Address 值物件
@dataclass(frozen=True)
class Address:
    """地址值物件"""
    line1: str
    line2: str | None
    city: str
    postal_code: str

    def format(self) -> str:
        return f"{self.line1}\n{self.city} {self.postal_code}"

class User:
    def __init__(self, name: str, email: Email, address: Address):
        self.name = name
        self.email = email
        self.address = address
```

### 3️⃣ Replace Conditional with Polymorphism（多態取代條件）

**觸發條件**：大量 if-elif-else 或 switch

```python
# Before: 條件地獄
def calculate_shipping(order):
    if order.shipping_type == "standard":
        return order.weight * 10
    elif order.shipping_type == "express":
        return order.weight * 25 + 50
    elif order.shipping_type == "overnight":
        return order.weight * 50 + 100
    elif order.shipping_type == "international":
        # 複雜計算...
        pass

# After: 策略模式
class ShippingStrategy(ABC):
    @abstractmethod
    def calculate(self, order) -> Decimal: ...

class StandardShipping(ShippingStrategy):
    def calculate(self, order) -> Decimal:
        return order.weight * 10

class ExpressShipping(ShippingStrategy):
    def calculate(self, order) -> Decimal:
        return order.weight * 25 + 50

# 使用
shipping_strategies = {
    "standard": StandardShipping(),
    "express": ExpressShipping(),
    # ...
}
cost = shipping_strategies[order.shipping_type].calculate(order)
```

### 4️⃣ Introduce Parameter Object（參數物件）

**觸發條件**：參數超過 4 個

```python
# Before: 參數過多
def create_user(
    name: str,
    email: str,
    phone: str,
    address_line1: str,
    address_line2: str,
    city: str,
    postal_code: str,
    country: str,
):
    ...

# After: 使用參數物件
@dataclass
class CreateUserCommand:
    name: str
    email: str
    phone: str
    address: Address

def create_user(command: CreateUserCommand):
    ...
```

### 5️⃣ Split Module（拆分模組）

**觸發條件**：目錄超過 10 個檔案

```
# Before
src/Domain/
├── User.py
├── Order.py
├── Product.py
├── Payment.py
├── Shipping.py
├── Review.py
├── Coupon.py
├── Notification.py
├── ...  # 太多了！

# After: 按子領域拆分
src/Domain/
├── Identity/
│   └── User.py
├── Ordering/
│   ├── Order.py
│   └── Payment.py
├── Catalog/
│   ├── Product.py
│   └── Review.py
├── Promotion/
│   └── Coupon.py
└── Communication/
    └── Notification.py
```

---

## DDD 架構守護

重構時必須檢查是否違反 DDD 原則：

### ❌ 常見違規

```python
# 違規 1: Domain 層依賴 Infrastructure
# Domain/Services/OrderService.py
from infrastructure.database import db  # ❌ 禁止！

# 違規 2: Presentation 直接存取 Domain
# Presentation/API/routes.py
from domain.repositories import UserRepository  # ❌ 應透過 Application

# 違規 3: Entity 包含持久化邏輯
class User:
    def save(self):  # ❌ 應在 Repository
        db.session.add(self)
```

### ✅ 正確依賴方向

```
Presentation → Application → Domain
                    ↓
              Infrastructure
```

---

## 重構流程

### 1️⃣ 偵測階段
```markdown
🔍 偵測到重構需求：
- 檔案：`src/domain/services/order_service.py`
- 問題：檔案長度 342 行（超過 200 行警告閾值）
- 複雜度：圈複雜度 12（超過 10 警告閾值）
```

### 2️⃣ 分析階段
```markdown
📊 分析結果：
- `process_order()` 函數 85 行，建議拆分
- 發現 3 處重複邏輯，建議提取
- 識別出 2 個隱藏的 Value Object
```

### 3️⃣ 規劃階段
```markdown
📋 重構計畫：
1. 提取 `OrderValidator` 類別
2. 提取 `PricingCalculator` 服務
3. 建立 `OrderStatus` Value Object
4. 更新測試確保覆蓋
```

### 4️⃣ 執行階段
```markdown
🔧 執行重構：
- [x] 建立 `OrderValidator` 類別
- [x] 遷移驗證邏輯
- [x] 更新測試
- [x] 確認測試通過
- [ ] 提取 `PricingCalculator`
- [ ] ...
```

### 5️⃣ 驗證階段
```markdown
✅ 重構完成：
- 測試：全部通過（42/42）
- 覆蓋率：85%（+3%）
- 複雜度：8（-4）
- 架構：符合 DDD ✓
```

---

## 主動建議範本

當偵測到需要重構時，AI 應主動建議：

```markdown
💡 **重構建議**

偵測到 `order_service.py` 已達 250 行，建議進行模組化：

### 建議拆分方案

| 新檔案 | 內容 | 行數 |
|--------|------|------|
| `order_validator.py` | 訂單驗證邏輯 | ~50 行 |
| `pricing_calculator.py` | 價格計算邏輯 | ~60 行 |
| `order_service.py` | 服務編排 | ~80 行 |

### 預期效益
- ✅ 單一職責原則
- ✅ 更易測試
- ✅ 降低認知負荷

是否要我執行這個重構？
```

---

## 與其他 Skills 整合

| Skill | 整合方式 |
|-------|----------|
| `code-reviewer` | 審查時觸發重構建議 |
| `test-generator` | 重構前先生成測試 |
| `ddd-architect` | 確保重構符合 DDD |
| `memory-updater` | 記錄重構決策 |
