程序员进阶工程师必备技能之代码质量与重构能力(二)

简介: 教程来源 https://vrhyh.cn/ 本文系统阐述优秀代码的五大核心特征:命名需名副其实、可读可搜;函数应短小专注、参数精简、无副作用、抽象层次统一;注释重在解释“为什么”而非“是什么”;错误处理要显式、安全、可恢复;格式风格须一致,借助Black等工具自动化保障。

二、优秀代码的核心特征

2.1 命名艺术
命名是编程中最难的事情之一(有句名言:计算机科学中只有两件难事:缓存失效和命名)。好的命名让代码自文档化。

命名原则:

名副其实:名字要准确表达意图

避免误导:不要用容易混淆的名字

有意义的区分:Product 和 ProductInfo 没有区别

读得出来:方便讨论和搜索

可搜索性:避免魔法数字和单字母变量

# ❌ 糟糕的命名
def d(x, y):
    t = 0
    for i in x:
        t += i * y
    return t

# ✅ 优秀的命名
def calculate_total_price(item_prices: List[Decimal], tax_rate: Decimal) -> Decimal:
    """
    计算含税总价
    """
    subtotal = sum(item_prices)
    tax = subtotal * tax_rate
    return subtotal + tax

# 更多命名示例
class BadNames:
    def proc(self, d1, d2):
        self.a = d1
        self.b = d2
        self.f = True

class GoodNames:
    def process_payment(self, order_amount: Decimal, user_balance: Decimal) -> PaymentResult:
        self.order_amount = order_amount
        self.user_balance = user_balance
        self.payment_successful = True

# 魔法数字 vs 命名常量
# ❌ 糟糕
if user.age > 18:
    grant_access()

# ✅ 优秀
LEGAL_AGE_THRESHOLD = 18
if user.age >= LEGAL_AGE_THRESHOLD:
    grant_access()

# 布尔变量命名
# ❌ 糟糕
is_not_valid = True
no_error = False

# ✅ 优秀
is_valid = True
has_error = False
can_edit = True
should_retry = False

2.2 函数设计
函数是代码组织的基本单元。好的函数应该短小、专注、只做一件事。

函数设计原则:

短小:函数应该只做一件事,并且把这件事做好

参数少:理想情况下0-2个参数,3个参数需要仔细考虑,超过3个应该封装成对象

无副作用:函数要么修改对象状态,要么返回计算结果,不要两者都做

单一抽象层次:函数内不要混合高层和低层抽象

# ❌ 糟糕的函数设计
def process_user_data(user_data):
    # 验证 - 高层抽象
    if not user_data.get('email'):
        raise ValueError("Email required")
    if '@' not in user_data['email']:
        raise ValueError("Invalid email")

    # 数据库操作 - 低层抽象
    conn = sqlite3.connect('users.db')
    cursor = conn.cursor()
    cursor.execute("SELECT * FROM users WHERE email = ?", (user_data['email'],))
    existing = cursor.fetchone()

    # 业务逻辑 - 中层抽象
    if existing:
        return "User already exists"

    # 密码哈希 - 低层抽象
    hashed = hashlib.sha256(user_data['password'].encode()).hexdigest()

    # 更多数据库操作
    cursor.execute("INSERT INTO users (email, password_hash) VALUES (?, ?)", 
                   (user_data['email'], hashed))
    conn.commit()

    # 发送邮件 - 高层抽象
    smtp = smtplib.SMTP('smtp.gmail.com', 587)
    smtp.login('me@gmail.com', 'password')
    smtp.sendmail(...)

    return "User created"


# ✅ 优秀的函数设计(单一抽象层次)
def register_user(user_data: Dict) -> RegistrationResult:
    """
    注册用户 - 高层协调函数
    只负责编排,具体细节交给其他函数
    """
    # 1. 验证输入(同一抽象层次)
    validation_result = validate_user_input(user_data)
    if not validation_result.is_valid:
        return RegistrationResult.failure(validation_result.errors)

    # 2. 检查用户是否存在(同一抽象层次)
    if user_exists(user_data['email']):
        return RegistrationResult.failure("User already exists")

    # 3. 创建用户(同一抽象层次)
    user = create_user(user_data)

    # 4. 发送欢迎邮件(同一抽象层次)
    send_welcome_email(user)

    return RegistrationResult.success(user)

def validate_user_input(user_data: Dict) -> ValidationResult:
    """验证用户输入 - 单一职责"""
    errors = []

    if not user_data.get('email'):
        errors.append("Email is required")
    elif not is_valid_email(user_data['email']):
        errors.append("Invalid email format")

    if not user_data.get('password'):
        errors.append("Password is required")
    elif len(user_data['password']) < 8:
        errors.append("Password must be at least 8 characters")

    return ValidationResult(is_valid=len(errors) == 0, errors=errors)

def user_exists(email: str) -> bool:
    """检查用户是否存在 - 单一职责"""
    # 低层抽象在辅助函数内部
    with get_db_connection() as conn:
        cursor = conn.cursor()
        cursor.execute("SELECT 1 FROM users WHERE email = ?", (email,))
        return cursor.fetchone() is not None

def create_user(user_data: Dict) -> User:
    """创建用户 - 单一职责"""
    hashed_password = hash_password(user_data['password'])

    user = User(
        email=user_data['email'],
        password_hash=hashed_password,
        created_at=datetime.now()
    )

    with get_db_connection() as conn:
        # 保存到数据库...
        pass

    return user

def send_welcome_email(user: User):
    """发送欢迎邮件 - 单一职责"""
    # 邮件发送细节...
    pass

函数参数设计:

# ❌ 参数过多
def create_order(user_id, product_ids, quantities, prices, shipping_address, billing_address, coupon_code, gift_wrap):
    pass

# ✅ 使用数据类封装参数
@dataclass
class OrderRequest:
    user_id: str
    items: List[OrderItem]
    shipping_address: Address
    billing_address: Address
    coupon_code: Optional[str] = None
    gift_wrap: bool = False

def create_order(request: OrderRequest) -> Order:
    pass

# ✅ 使用建造者模式处理复杂参数
class OrderBuilder:
    def __init__(self, user_id: str):
        self.user_id = user_id
        self.items = []
        self.shipping_address = None
        self.coupon_code = None

    def add_item(self, product_id: str, quantity: int, price: Decimal) -> 'OrderBuilder':
        self.items.append(OrderItem(product_id, quantity, price))
        return self

    def ship_to(self, address: Address) -> 'OrderBuilder':
        self.shipping_address = address
        return self

    def with_coupon(self, coupon_code: str) -> 'OrderBuilder':
        self.coupon_code = coupon_code
        return self

    def build(self) -> Order:
        return create_order(self)

# 使用
order = OrderBuilder("user_123") \
    .add_item("product_1", 2, Decimal('19.99')) \
    .add_item("product_2", 1, Decimal('49.99')) \
    .ship_to(Address(...)) \
    .with_coupon("SAVE10") \
    .build()

2.3 注释的最佳实践
注释不是用来弥补坏代码的。好的代码应该是自解释的,注释用来解释"为什么"而不是"是什么"。

# ❌ 糟糕的注释(重复代码)
# 将价格乘以数量得到小计
subtotal = price * quantity  # 这行代码已经很清楚

# 循环遍历订单项
for item in order.items:  # 循环,很明显
    # 增加总价
    total += item.price  # 增加,也很明显

# ✅ 有用的注释(解释为什么)
# 使用Decimal而不是float来避免浮点数精度问题
price = Decimal(str(raw_price))

# 用户可能在多个设备同时登录,所以使用乐观锁
UPDATE inventory SET quantity = quantity - %s, version = version + 1 
WHERE product_id = %s AND version = %s

# 临时方案:由于支付网关的bug,需要将金额向上取整到分
# TODO(zhangsan): 支付网关修复后移除这个hack
amount = amount.quantize(Decimal('0.01'), rounding=ROUND_UP)

# 为什么选择这种算法:用户量在百万级别,布隆过滤器可以在O(1)时间内判断,
# 且内存占用只需要约10MB,如果使用Set需要数百MB
def is_duplicate_user(user_id: str) -> bool:
    return bloom_filter.contains(user_id)

# 文档注释(API文档)
def calculate_shipping_cost(
    weight: Decimal, 
    destination: Address, 
    method: ShippingMethod
) -> Decimal:
    """
    计算运费

    根据商品重量、目的地和配送方式计算运费。
    支持标准配送、快速配送和次日达三种方式。

    Args:
        weight: 商品总重量(千克)
        destination: 收货地址,用于计算距离
        method: 配送方式

    Returns:
        运费金额(元)

    Raises:
        InvalidAddressError: 当地址不支持配送时抛出
        WeightLimitExceededError: 当重量超过限制时抛出

    Example:
        >>> cost = calculate_shipping_cost(
        ...     weight=Decimal('2.5'),
        ...     destination=Address(city="Beijing"),
        ...     method=ShippingMethod.EXPRESS
        ... )
        >>> print(cost)
        23.50
    """
    pass

2.4 错误处理
优秀的代码能够优雅地处理错误,而不是崩溃或隐藏错误。

# ❌ 糟糕的错误处理
def divide(a, b):
    return a / b  # 如果b=0会崩溃

def get_user(user_id):
    return users[user_id]  # 如果key不存在会崩溃

def parse_json(data):
    return json.loads(data)  # 如果data不是有效JSON会崩溃

# ✅ 优秀的错误处理
from typing import Optional, Union
from dataclasses import dataclass

# 方式1:返回Optional/Result类型
def divide(a: float, b: float) -> Optional[float]:
    """安全除法,b为0时返回None"""
    if b == 0:
        return None
    return a / b

# 方式2:返回Result类型(类似Rust的Result)
@dataclass
class Result[T, E]:
    success: bool
    value: Optional[T] = None
    error: Optional[E] = None

    @classmethod
    def ok(cls, value: T) -> 'Result[T, E]':
        return cls(success=True, value=value)

    @classmethod
    def err(cls, error: E) -> 'Result[T, E]':
        return cls(success=False, error=error)

    def unwrap(self) -> T:
        if not self.success:
            raise ValueError(f"Called unwrap on error result: {self.error}")
        return self.value

    def unwrap_or(self, default: T) -> T:
        return self.value if self.success else default

def divide_result(a: float, b: float) -> Result[float, str]:
    if b == 0:
        return Result.err("Division by zero")
    return Result.ok(a / b)

# 使用
result = divide_result(10, 2)
if result.success:
    print(f"Result: {result.value}")
else:
    print(f"Error: {result.error}")

# 方式3:使用自定义异常
class DivisionError(Exception):
    """除法运算错误"""
    pass

def divide_raise(a: float, b: float) -> float:
    if b == 0:
        raise DivisionError("Cannot divide by zero")
    return a / b

# 调用方处理异常
try:
    result = divide_raise(10, 0)
except DivisionError as e:
    logger.error(f"Division failed: {e}")
    result = 0

# 方式4:使用装饰器统一处理
def handle_errors(default_value=None, log_error=True):
    """错误处理装饰器"""
    def decorator(func):
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            try:
                return func(*args, **kwargs)
            except Exception as e:
                if log_error:
                    logging.error(f"Error in {func.__name__}: {e}")
                if default_value is not None:
                    return default_value
                raise
        return wrapper
    return decorator

@handle_errors(default_value=0, log_error=True)
def risky_operation(data):
    # 可能抛出异常的操作
    return 1 / data['value']

2.5 代码格式化与风格
一致的代码风格让团队协作更顺畅。

# 使用工具自动格式化
# - Black: 自动格式化Python代码
# - isort: 自动排序import
# - ruff: 快速linting

# .pre-commit-config.yaml 示例
repos:
  - repo: https://github.com/psf/black
    rev: 23.3.0
    hooks:
      - id: black
        language_version: python3

  - repo: https://github.com/pycqa/isort
    rev: 5.12.0
    hooks:
      - id: isort
        args: ["--profile", "black"]

  - repo: https://github.com/astral-sh/ruff-pre-commit
    rev: v0.0.270
    hooks:
      - id: ruff
        args: [--fix, --exit-non-zero-on-fix]

# 格式化后的代码示例
# 导入分组:标准库 → 第三方库 → 本地模块
import json
import sys
from datetime import datetime
from typing import Dict, List, Optional

import pandas as pd
import requests
from fastapi import FastAPI, HTTPException

from myapp.models import Order, User
from myapp.utils import calculate_total, validate_email

def function_with_proper_formatting(
    param1: str,
    param2: int,
    param3: Optional[Dict] = None,
    param4: List[str] = None
) -> Dict[str, Any]:
    """函数文档字符串"""
    if param2 > 100:
        return {
            "status": "error",
            "message": "Parameter too large"
        }

    result = {
        "param1": param1,
        "param2": param2,
        "timestamp": datetime.now().isoformat()
    }

    return result

来源:
https://bgnno.cn/

相关文章
|
2月前
|
人工智能 自然语言处理 安全
阿里云云部署OpenClaw集成钉钉
本文详解OpenClaw开源AI助手与钉钉的深度集成:支持群聊/单聊中自然语言交互,涵盖环境部署、钉钉应用创建、通道配置、机器人测试及多Agent绑定等全流程,并强调使用前须评估安全与合规性。
|
2月前
|
数据采集 机器学习/深度学习 运维
从“秒封”到“日爬十万”:谈谈5个风控机制
这篇文档讨论了Python爬虫常见问题和反爬策略。作者提出五个关键点:1. 控制请求频率;2. 轮换IP;3. 伪装请求头;4. 模拟真实访问路径;5. 使用高匿名代理。这些策略需综合运用,提高爬虫生存率。
410 5
|
3月前
|
SQL 人工智能 自然语言处理
什么是低代码 v2.0 时代?JeecgBoot低代码用 Skills 把"一句话生成系统"做成了现实
一句话先说清楚:低代码 v1.0 阶段,是用"拖拽设计"代替"代码开发";低代码 v2.0 阶段,是用 AI Skills 把"拖拽设计"也省掉, 一句话生成功能。![低代码迈入 v2.0 时代 — Skills 加持一句话搭建系统](https://oscimg.oschina.net/osc
217 5
什么是低代码 v2.0 时代?JeecgBoot低代码用 Skills 把"一句话生成系统"做成了现实
|
2月前
|
SQL 存储 关系型数据库
覆盖索引:让你的查询直接从索引返回,彻底告别回表
覆盖索引是SQL优化中性价比较高的技巧,让查询直接从索引返回所需列,避免回表操作。本文解释覆盖索引的原理,通过EXPLAIN的“Using index”判断是否生效。结合复合索引设计、深分页优化(延迟关联)等场景,给出覆盖索引的使用方法和注意事项。用好覆盖索引,不改SQL逻辑,仅调整索引设计即可显著提升查询性能。
|
3月前
|
人工智能 IDE API
阿里云百炼Coding Plan产品简介:支持模型、收费标准及购买和使用常见问题解答
阿里云百炼Coding Plan是面向开发者和团队的AI编程订阅服务,采用固定月费模式,Pro套餐200元/月提供9万次调用额度,整合千问、Kimi、GLM、MiniMax等顶级模型,全面兼容Claude Code、OpenClaw、Cursor等主流编程工具。额度采用5小时滚动恢复、每周及每月定期重置机制,兼顾开发连续性与成本可控性。其折算成本远低于按量计费,并通过多层级额度设计和华北2地域绑定有效防范欠费风险。适合日常代码生成、智能体开发及IDE插件集成等场景,是开发者以可预期预算拥抱AI编程的高性价比选择。
阿里云百炼Coding Plan产品简介:支持模型、收费标准及购买和使用常见问题解答
|
2月前
|
人工智能 安全 测试技术
别再让 Claude 乱改代码了!Claude Code 这 7 个权限配置让你的项目再也不翻车
还在为 Claude Code 的混乱操作头疼?本文总结 7 个核心权限配置,从上下文管理、提示技巧到环境配置全覆盖,让你的 AI 编程助手真正听话不翻车。
645 5
|
3月前
|
SQL 关系型数据库 MySQL
【MySQL百日打怪升级第20天】行锁 vs 表锁 —— InnoDB 什么时候锁行、什么时候锁表?
【第20天】MySQL锁机制精讲!深入解析InnoDB行锁与表锁的本质区别:行锁依赖索引,无索引则全表扫描→实际锁全表;详解Record/Gap/Next-Key三种行锁、意向锁作用及锁诊断实战(PS视图+INNODB STATUS)。避坑指南:UPDATE/DELETE务必走索引!
244 3
|
2月前
|
开发工具
【Application Insights】采样率对Function App日志收集的影响和解决方法
Azure Functions日志在Application Insights中缺失,主因是默认启用的采样功能(每秒限采20项遥测)。可通过`host.json`配置`excludedTypes`排除Request/Exception等关键类型,或查询`RetainedPercentage`确认采样状态。
191 6
|
3月前
|
人工智能 算法 搜索推荐
深度集成 AI 面部分析 API 的技术路径与实践
玩美移动AI面部分析API,支持亚像素级关键点追踪、肤色量化(Hex/ITA)及语义化脸型/五官识别,输出结构化3D面部数据。开发者可快速集成,实现智能粉底匹配、脸型自适应推荐等超个性化美妆场景,跨端一致、开箱即用。(239字)
207 6