| name | code-refactor |
| description | Proactively detect and execute code refactoring to maintain DDD architecture and code quality. LOAD THIS SKILL WHEN: Code file exceeds 200 lines | function exceeds 30 lines | User says "refactor", "重構", "拆分", "模組化", "太長" | cyclomatic complexity > 10 | deeply nested code. CAPABILITIES: Extract Method, Extract Class, Split Module, Replace Conditional with Polymorphism, DDD architecture compliance. |
程式碼重構技能
描述
主動偵測並執行程式碼重構,維持 DDD 架構和程式碼品質。
觸發條件
- 「重構這段程式碼」、「refactor」
- 「這個檔案太長了」
- 「模組化」、「拆分」
- 主動觸發:偵測到程式碼超過閾值時
核心原則
📜 依據憲法第 7.3 條「主動重構原則」
重構不是改天換地,而是持續的小步快跑
每次提交都應該比上次更乾淨
閾值設定
📏 長度閾值
| 類型 | 警告 | 強制重構 |
|---|---|---|
| 檔案 | > 200 行 | > 400 行 |
| 類別 | > 150 行 | > 300 行 |
| 函數 | > 30 行 | > 50 行 |
| 目錄檔案數 | > 10 個 | > 15 個 |
🔄 複雜度閾值
| 指標 | 警告 | 強制重構 |
|---|---|---|
| 圈複雜度 | > 10 | > 15 |
| 巢狀深度 | > 3 層 | > 4 層 |
| 參數數量 | > 4 個 | > 6 個 |
| 依賴數量 | > 5 個 | > 8 個 |
重構模式庫
1️⃣ Extract Method(提取方法)
觸發條件:函數過長、重複邏輯
# 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 行
# 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
# 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 個
# 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 原則:
❌ 常見違規
# 違規 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️⃣ 偵測階段
🔍 偵測到重構需求:
- 檔案:`src/domain/services/order_service.py`
- 問題:檔案長度 342 行(超過 200 行警告閾值)
- 複雜度:圈複雜度 12(超過 10 警告閾值)
2️⃣ 分析階段
📊 分析結果:
- `process_order()` 函數 85 行,建議拆分
- 發現 3 處重複邏輯,建議提取
- 識別出 2 個隱藏的 Value Object
3️⃣ 規劃階段
📋 重構計畫:
1. 提取 `OrderValidator` 類別
2. 提取 `PricingCalculator` 服務
3. 建立 `OrderStatus` Value Object
4. 更新測試確保覆蓋
4️⃣ 執行階段
🔧 執行重構:
- [x] 建立 `OrderValidator` 類別
- [x] 遷移驗證邏輯
- [x] 更新測試
- [x] 確認測試通過
- [ ] 提取 `PricingCalculator`
- [ ] ...
5️⃣ 驗證階段
✅ 重構完成:
- 測試:全部通過(42/42)
- 覆蓋率:85%(+3%)
- 複雜度:8(-4)
- 架構:符合 DDD ✓
主動建議範本
當偵測到需要重構時,AI 應主動建議:
💡 **重構建議**
偵測到 `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 |
記錄重構決策 |