Python代码重构技术
重构是在不改变代码外部行为的前提下改善其内部结构的技术。
重构原则
何时重构
Python
# 重构时机:
# 1. 添加新功能前(整理现有代码)
# 2. 代码理解困难时(提高可读性)
# 3. 修复Bug后(消除问题根源)
# 4. Code Review时(接受建议)
# 5. 性能优化前(先让代码清晰)
# 重构三定律:
# 1. 小步前进:每次只做一个小改动
# 2. 测试驱动:每次重构后运行测试
# 3. 功能不变:不改变外部行为
提取方法
长方法拆分
Python
# 重构前:长方法难以理解
def process_order(order):
# 验证订单
if order.items is None or len(order.items) == 0:
raise ValueError("Order has no items")
for item in order.items:
if item.quantity <= 0:
raise ValueError("Invalid quantity")
if item.price <= 0:
raise ValueError("Invalid price")
# 计算总价
total = 0
for item in order.items:
total += item.quantity * item.price
tax = total * 0.1
final_price = total + tax
# 应用折扣
if order.customer.is_premium:
discount = final_price * 0.1
final_price -= discount
# 更新库存
for item in order.items:
inventory = get_inventory(item.product_id)
inventory.quantity -= item.quantity
save_inventory(inventory)
# 创建支付记录
payment = create_payment(order, final_price)
# 发送通知
send_email(order.customer.email, "Order confirmed")
if order.customer.is_premium:
send_sms(order.customer.phone, "Premium discount applied")
return payment
# 重构后:职责清晰
def process_order(order):
validate_order(order)
final_price = calculate_price(order)
update_inventory(order)
payment = create_payment(order, final_price)
send_notifications(order)
return payment
def validate_order(order):
if not order.items:
raise ValueError("Order has no items")
for item in order.items:
validate_item(item)
def validate_item(item):
if item.quantity <= 0:
raise ValueError("Invalid quantity")
if item.price <= 0:
raise ValueError("Invalid price")
def calculate_price(order):
total = sum(item.quantity * item.price for item in order.items)
tax = total * 0.1
final_price = total + tax
return apply_discount(final_price, order.customer)
def apply_discount(price, customer):
if customer.is_premium:
return price * 0.9
return price
def update_inventory(order):
for item in order.items:
inventory = get_inventory(item.product_id)
inventory.quantity -= item.quantity
save_inventory(inventory)
def send_notifications(order):
send_email(order.customer.email, "Order confirmed")
if order.customer.is_premium:
send_sms(order.customer.phone, "Premium discount applied")
提取重复代码
Python
# 重构前:重复代码
def calculate_employee_salary(employee):
base = employee.base_salary
bonus = 0
if employee.performance == 'excellent':
bonus = base * 0.2
elif employee.performance == 'good':
bonus = base * 0.1
return base + bonus
def calculate_manager_salary(manager):
base = manager.base_salary
bonus = 0
if manager.performance == 'excellent':
bonus = base * 0.2
elif manager.performance == 'good':
bonus = base * 0.1
team_bonus = manager.team_size * 100
return base + bonus + team_bonus
# 重构后:提取通用逻辑
def calculate_bonus(base_salary, performance):
rates = {'excellent': 0.2, 'good': 0.1, 'normal': 0}
return base_salary * rates.get(performance, 0)
def calculate_employee_salary(employee):
base = employee.base_salary
bonus = calculate_bonus(base, employee.performance)
return base + bonus
def calculate_manager_salary(manager):
base = manager.base_salary
bonus = calculate_bonus(base, manager.performance)
team_bonus = manager.team_size * 100
return base + bonus + team_bonus
简化条件表达式
分解条件
Python
# 重构前:复杂条件
def get_discount(customer, order):
if customer.is_premium and order.total > 1000 and customer.order_count > 10:
return 0.15
elif customer.is_premium and order.total > 500:
return 0.1
elif order.total > 1000:
return 0.05
return 0
# 重构后:提取条件方法
def get_discount(customer, order):
if is_elite_customer(customer, order):
return 0.15
if is_premium_large_order(customer, order):
return 0.1
if is_large_order(order):
return 0.05
return 0
def is_elite_customer(customer, order):
return customer.is_premium and order.total > 1000 and customer.order_count > 10
def is_premium_large_order(customer, order):
return customer.is_premium and order.total > 500
def is_large_order(order):
return order.total > 1000
合并条件
Python
# 重构前:多个条件分支
def should_send_notification(user):
if user.email_verified:
if user.notification_enabled:
if not user.is_suspended:
return True
return False
# 重构后:合并条件
def should_send_notification(user):
return user.email_verified and user.notification_enabled and not user.is_suspended
使用字典替代条件
Python
# 重构前:大量if-elif
def get_status_text(status):
if status == 'pending':
return '等待处理'
elif status == 'processing':
return '正在处理'
elif status == 'completed':
return '已完成'
elif status == 'failed':
return '处理失败'
else:
return '未知状态'
# 重构后:字典映射
STATUS_TEXT = {
'pending': '等待处理',
'processing': '正在处理',
'completed': '已完成',
'failed': '处理失败'
}
def get_status_text(status):
return STATUS_TEXT.get(status, '未知状态')
重构数据结构
提取类
Python
# 重构前:数据与逻辑混杂
class Order:
def __init__(self, items, customer):
self.items = items
self.customer = customer
def calculate_total(self):
total = sum(item.price * item.quantity for item in self.items)
tax = total * self.customer.tax_rate
discount = total * self.customer.discount_rate
return total + tax - discount
# 重构后:职责分离
class PriceCalculator:
def calculate(self, items, customer):
subtotal = self._calculate_subtotal(items)
tax = self._calculate_tax(subtotal, customer)
discount = self._calculate_discount(subtotal, customer)
return subtotal + tax - discount
def _calculate_subtotal(self, items):
return sum(item.price * item.quantity for item in items)
def _calculate_tax(self, subtotal, customer):
return subtotal * customer.tax_rate
def _calculate_discount(self, subtotal, customer):
return subtotal * customer.discount_rate
class Order:
def __init__(self, items, customer, calculator=None):
self.items = items
self.customer = customer
self.calculator = calculator or PriceCalculator()
def calculate_total(self):
return self.calculator.calculate(self.items, self.customer)
封装字段
Python
# 重构前:直接访问字段
class Customer:
pass
customer = Customer()
customer.name = 'Alice'
customer.email = 'alice@example.com'
# 重构后:属性封装
class Customer:
def __init__(self, name, email):
self._name = name
self._email = email
@property
def name(self):
return self._name
@name.setter
def name(self, value):
if not value:
raise ValueError("Name cannot be empty")
self._name = value
@property
def email(self):
return self._email
@email.setter
def email(self, value):
if not self._validate_email(value):
raise ValueError("Invalid email format")
self._email = value
def _validate_email(self, email):
return '@' in email
消除魔法值
替换魔法数
Python
# 重构前:魔法数字
def calculate_shipping(weight):
if weight <= 1:
return 5
elif weight <= 5:
return 10
elif weight <= 10:
return 20
return weight * 2.5
# 重构后:常量命名
LIGHT_WEIGHT_THRESHOLD = 1
MEDIUM_WEIGHT_THRESHOLD = 5
HEAVY_WEIGHT_THRESHOLD = 10
LIGHT_SHIPPING_FEE = 5
MEDIUM_SHIPPING_FEE = 10
HEAVY_SHIPPING_FEE = 20
HEAVY_RATE = 2.5
def calculate_shipping(weight):
if weight <= LIGHT_WEIGHT_THRESHOLD:
return LIGHT_SHIPPING_FEE
if weight <= MEDIUM_WEIGHT_THRESHOLD:
return MEDIUM_SHIPPING_FEE
if weight <= HEAVY_WEIGHT_THRESHOLD:
return HEAVY_SHIPPING_FEE
return weight * HEAVY_RATE
移除死代码
删除未使用代码
Python
# 重构前:包含死代码
def process_data(data):
# 未使用的变量
unused_config = load_config()
result = transform(data)
# 已废弃的逻辑
if False: # 永不执行
legacy_process(data)
# 注释掉的代码
# old_result = old_transform(data)
return result
# 重构后:清理干净
def process_data(data):
return transform(data)
重构流程
小步重构法
Python
# 1. 确保有测试覆盖
# 2. 选择一个小改动
# 3. 实施改动
# 4. 运行测试
# 5. 提交改动
# 6. 继续下一个改动
# 示例流程:
# Step 1: 提取validate_order方法
# 运行测试 → 成功
# Step 2: 提取calculate_price方法
# 运行测试 → 成功
# Step 3: 提取apply_discount方法
# 运行测试 → 成功
# ...每个步骤都有测试验证
IDE重构工具
Python
# VS Code / PyCharm 重构功能:
# 1. 重命名变量/方法(F2)
# 2. 提取方法
# 3. 提取变量
# 4. 内联变量/方法
# 5. 移动类/方法
# 6. 改变方法签名
# 使用IDE工具可以安全、快速完成重构
重构检查清单
| 检查项 | 说明 |
|---|---|
| 长方法 | 提取为多个小方法 |
| 重复代码 | 提取为通用方法 |
| 大类 | 分拆为多个职责清晰的类 |
| 长参数列表 | 封装为参数对象 |
| 魔法值 | 使用命名常量 |
| 复杂条件 | 提取条件方法或使用策略模式 |
| 死代码 | 删除无用代码 |
注意:重构前必须有测试覆盖,每次重构后运行测试确保行为不变。
要点总结
- 提取方法:长方法拆分、重复代码抽取、职责单一化
- 简化条件:分解复杂条件、合并重复分支、字典替代if-elif
- 重构数据:提取类分离职责、属性封装验证、命名常量替代魔法值
- 小步重构:每次只改一小处、测试驱动验证、渐进式改善
- 使用IDE工具:重命名、提取方法、内联变量等自动化重构
- 重构时机:添加功能前、理解困难时、修复Bug后、Code Review时
存放路径:articles/PYTHON/专家/架构与设计/代码重构技术.md
📝 发现内容有误?点击此处直接编辑