代码是写给人看的,只是恰好能被机器执行
有一个著名的段子:程序员的大部分时间不是在写代码,而是在阅读代码。这个说法一点也不夸张。研究表明,程序员平均花费 70% 的时间在理解已有代码上,只有 30% 的时间在写新代码。
这意味着什么?你的代码被阅读的次数,远远超过它被编写的次数。
代码质量不是一种可有可无的“锦上添花”,而是决定项目长期健康度的核心要素。低质量的代码会带来:
Bug 频发:混乱的逻辑隐藏着各种边界问题
开发效率下降:改一个地方要小心翼翼地测试多个地方
新人上手困难:复杂的代码让团队扩展变得艰难
技术债务累积:越欠越多,最终系统难以维护
而重构,就是偿还技术债务、持续保持代码质量的关键手段。
本文将全面深入地探讨代码质量的评估标准、优秀代码的特征、重构的时机与方法,以及如何在日常开发中持续提升代码质量。
一、代码质量的衡量标准
1.1 可读性(Readability)
代码首先是给人看的,其次才是给机器执行的。可读性是最基础也最重要的质量指标。
糟糕的可读性示例:
def f(a, b, c):
d = []
for x in a:
if x['t'] == 'A':
d.append(x)
e = 0
for y in d:
e += y['v'] * b
if e > c:
return True
return False
这段代码的问题:
变量名毫无意义(a、b、c、d、e、x、y)
魔法字符串 'A' 没有解释
逻辑意图不清晰
没有文档说明
改进后的版本:
def should_apply_premium_discount(
cart_items: List[Dict],
discount_rate: float,
max_discount_amount: Decimal
) -> bool:
"""
判断是否应该应用会员折扣
Args:
cart_items: 购物车中的商品列表
discount_rate: 折扣率(如0.2表示8折)
max_discount_amount: 最大折扣金额上限
Returns:
True表示应该应用折扣,False表示不应用
"""
# 筛选出适用折扣的商品(类型为普通商品,非特价品)
eligible_items = [
item for item in cart_items
if item['type'] == ProductType.NORMAL
]
# 计算可折扣的总金额
total_discountable_amount = sum(
item['price'] * item['quantity']
for item in eligible_items
)
# 计算折扣后节省的金额
saved_amount = total_discountable_amount * discount_rate
# 如果节省金额超过上限,仍然可以应用折扣(只是实际节省会被限制)
# 但如果节省金额为0或负数,则不应应用折扣
return saved_amount > 0
1.2 可维护性(Maintainability)
可维护性衡量修改代码的难易程度。高可维护性的代码具有以下特征:
1.单一职责
# ❌ 糟糕:一个函数做了太多事情
def process_order(order_data):
# 验证订单
if not order_data.get('user_id'):
raise ValueError("缺少用户ID")
if not order_data.get('items'):
raise ValueError("订单为空")
# 计算价格
total = 0
for item in order_data['items']:
total += item['price'] * item['quantity']
# 应用折扣
if order_data.get('coupon'):
if order_data['coupon']['type'] == 'percentage':
total = total * (1 - order_data['coupon']['value'] / 100)
elif order_data['coupon']['type'] == 'fixed':
total = total - order_data['coupon']['value']
# 保存到数据库
conn = get_db_connection()
cursor = conn.cursor()
cursor.execute(
"INSERT INTO orders (user_id, total, status) VALUES (?, ?, ?)",
(order_data['user_id'], total, 'pending')
)
order_id = cursor.lastrowid
conn.commit()
# 发送通知
send_email(order_data['user_id'], f"订单{order_id}已创建")
# 更新库存
for item in order_data['items']:
update_inventory(item['product_id'], -item['quantity'])
return order_id
# ✅ 优秀:职责分离
class OrderProcessor:
"""订单处理器 - 协调各个组件完成订单处理"""
def __init__(
self,
validator: OrderValidator,
calculator: PriceCalculator,
repository: OrderRepository,
notifier: NotificationService,
inventory_service: InventoryService
):
self.validator = validator
self.calculator = calculator
self.repository = repository
self.notifier = notifier
self.inventory_service = inventory_service
def process(self, order_data: Dict) -> str:
# 1. 验证
self.validator.validate(order_data)
# 2. 计算价格
total = self.calculator.calculate(order_data)
# 3. 保存订单
order = Order.create(order_data['user_id'], order_data['items'], total)
self.repository.save(order)
# 4. 发送通知(异步)
self.notifier.notify_order_created(order)
# 5. 扣减库存
self.inventory_service.reserve(order)
return order.id
class OrderValidator:
"""订单验证器 - 只负责验证"""
def validate(self, order_data: Dict):
if not order_data.get('user_id'):
raise ValidationError("缺少用户ID")
if not order_data.get('items'):
raise ValidationError("订单为空")
if len(order_data['items']) > 100:
raise ValidationError("订单商品数量超过限制")
# 更多验证规则...
class PriceCalculator:
"""价格计算器 - 只负责价格计算"""
def __init__(self, discount_strategy: DiscountStrategy):
self.discount_strategy = discount_strategy
def calculate(self, order_data: Dict) -> Decimal:
subtotal = self._calculate_subtotal(order_data['items'])
discount = self.discount_strategy.calculate(subtotal, order_data.get('coupon'))
return subtotal - discount
def _calculate_subtotal(self, items: List[Dict]) -> Decimal:
return sum(
Decimal(item['price']) * item['quantity']
for item in items
)
2.低耦合
# ❌ 糟糕:紧耦合,订单模块直接依赖具体的外部服务
class OrderService:
def create_order(self, order_data):
# 直接调用具体实现
db = MySQLDatabase() # 硬编码数据库类型
db.save(order_data)
mq = RabbitMQ() # 硬编码消息队列
mq.publish("order.created", order_data)
cache = RedisCache() # 硬编码缓存
cache.set(f"order:{order_data['id']}", order_data)
# ✅ 优秀:依赖抽象,便于替换和测试
from abc import ABC, abstractmethod
class DatabasePort(ABC):
@abstractmethod
def save(self, data: Dict): pass
class MessageQueuePort(ABC):
@abstractmethod
def publish(self, topic: str, message: Dict): pass
class CachePort(ABC):
@abstractmethod
def set(self, key: str, value: Any, ttl: int = 3600): pass
class OrderService:
def __init__(
self,
database: DatabasePort, # 依赖抽象
message_queue: MessageQueuePort,
cache: CachePort
):
self.db = database
self.mq = message_queue
self.cache = cache
def create_order(self, order_data):
self.db.save(order_data)
self.mq.publish("order.created", order_data)
self.cache.set(f"order:{order_data['id']}", order_data)
# 不同的实现可以轻松切换
class MySQLDatabase(DatabasePort):
def save(self, data: Dict):
# MySQL具体实现
pass
class PostgreSQLDatabase(DatabasePort):
def save(self, data: Dict):
# PostgreSQL具体实现
pass
1.3 可测试性(Testability)
代码是否容易编写单元测试,是衡量质量的重要指标。
# ❌ 糟糕:难以测试
def process_payment(order_id):
# 硬编码的数据库连接
conn = psycopg2.connect("dbname=orders user=postgres")
cur = conn.cursor()
cur.execute("SELECT * FROM orders WHERE id = %s", (order_id,))
order = cur.fetchone()
# 直接调用外部API
response = requests.post(
"https://api.stripe.com/v1/charges",
headers={"Authorization": "Bearer sk_test_xxx"},
json={"amount": order['amount'], "currency": "usd"}
)
# 硬编码邮件发送
smtp = smtplib.SMTP('smtp.gmail.com', 587)
smtp.sendmail(...)
return response.json()
# ✅ 优秀:易于测试
class PaymentProcessor:
def __init__(
self,
order_repository: OrderRepository, # 可mock
payment_gateway: PaymentGateway, # 可mock
notification_service: NotificationService # 可mock
):
self.order_repo = order_repository
self.payment_gateway = payment_gateway
self.notifier = notification_service
async def process_payment(self, order_id: str) -> PaymentResult:
order = await self.order_repo.find_by_id(order_id)
if not order:
raise OrderNotFoundError(order_id)
result = await self.payment_gateway.charge(
amount=order.amount,
currency="USD",
payment_method=order.payment_method
)
if result.success:
order.mark_as_paid()
await self.order_repo.save(order)
await self.notifier.send_payment_confirmation(order)
return result
# 单元测试
class TestPaymentProcessor:
@pytest.mark.asyncio
async def test_process_payment_success(self):
# 创建mock对象
mock_repo = Mock(OrderRepository)
mock_gateway = Mock(PaymentGateway)
mock_notifier = Mock(NotificationService)
# 设置mock行为
order = Order(id="123", amount=100.00, status="pending")
mock_repo.find_by_id.return_value = order
mock_gateway.charge.return_value = PaymentResult(success=True, transaction_id="tx_123")
# 执行测试
processor = PaymentProcessor(mock_repo, mock_gateway, mock_notifier)
result = await processor.process_payment("123")
# 验证结果
assert result.success is True
assert order.status == "paid"
mock_repo.save.assert_called_once_with(order)
mock_notifier.send_payment_confirmation.assert_called_once_with(order)
1.4 可扩展性(Extensibility)
好的代码应该对扩展开放,对修改封闭。
# ❌ 糟糕:添加新的支付方式需要修改现有代码
class PaymentService:
def pay(self, method: str, amount: Decimal):
if method == "credit_card":
# 信用卡支付逻辑
pass
elif method == "paypal":
# PayPal支付逻辑
pass
elif method == "wechat":
# 微信支付逻辑
pass
# 每增加一种支付方式,都要修改这里
# ✅ 优秀:策略模式,易于扩展
from abc import ABC, abstractmethod
class PaymentStrategy(ABC):
@abstractmethod
async def pay(self, amount: Decimal, payment_info: Dict) -> PaymentResult:
pass
class CreditCardPayment(PaymentStrategy):
async def pay(self, amount: Decimal, payment_info: Dict) -> PaymentResult:
# 信用卡支付实现
pass
class PayPalPayment(PaymentStrategy):
async def pay(self, amount: Decimal, payment_info: Dict) -> PaymentResult:
# PayPal支付实现
pass
class WeChatPayment(PaymentStrategy):
async def pay(self, amount: Decimal, payment_info: Dict) -> PaymentResult:
# 微信支付实现
pass
class PaymentService:
def __init__(self):
self._strategies: Dict[str, PaymentStrategy] = {}
def register_strategy(self, method: str, strategy: PaymentStrategy):
self._strategies[method] = strategy
async def pay(self, method: str, amount: Decimal, payment_info: Dict) -> PaymentResult:
strategy = self._strategies.get(method)
if not strategy:
raise UnsupportedPaymentMethodError(method)
return await strategy.pay(amount, payment_info)
# 使用:新增支付方式只需注册,无需修改PaymentService
service = PaymentService()
service.register_strategy("credit_card", CreditCardPayment())
service.register_strategy("paypal", PayPalPayment())
service.register_strategy("wechat", WeChatPayment())
# 新增:service.register_strategy("crypto", CryptoPayment())
1.5 代码质量度量指标
来源:
https://yvyus.cn/