跳转至

Ch15 §03 代码库设计 · 讲解稿

章节定位: Ch15 架构层。教"如何设计可维护的代码库": 模块化 / API 设计 / 设计模式 / 文档。 承接: §02 Git → §03 代码组织 走向: §04 测试 / §05 DevOps 篇幅: ~3700 字 / 阅读 11 分钟 / 讲解 22-25 分钟


一 · 一句话总览

代码设计 = "如何让代码活得久": 模块化 (包/库) + API (REST/gRPC) + 设计模式 (SOLID) + 文档。AI 工程师的项目 = 模型 + 数据 + 服务, 三者都需好设计。


二 · 章节主线 (5 段)

第 1 段 · 模块化与项目结构 (8 分钟)

3.1.1 Python 包结构

my_ai_project/
├── pyproject.toml          # 依赖 + 元数据
├── README.md
├── src/
│   └── mypkg/
│       ├── __init__.py
│       ├── model.py
│       ├── data.py
│       ├── train.py
│       └── api.py
├── tests/
│   ├── test_model.py
│   ├── test_data.py
│   └── conftest.py
├── configs/                # YAML 配置
├── scripts/                # 入口脚本
└── docs/

3.1.2 src layout 优势

  • 避免 import 混乱
  • 强制包路径, 利于测试
  • 业界标准

3.1.3 依赖管理

工具 特点
pip + requirements.txt 简单
poetry 依赖 + 打包 + lock
uv 快 (10× pip)
conda 适合 ML + GPU
pip-tools 编译 requirements

3.1.4 配置管理

# 用 Pydantic
from pydantic import BaseModel

class TrainConfig(BaseModel):
    lr: float = 1e-3
    batch_size: int = 32
    epochs: int = 10
    device: str = "cuda"

优于 hard-code 或 argparse。


第 2 段 · API 设计 (10 分钟)

3.2.1 REST API

资源导向, HTTP 方法:

方法 用途 例
GET 读 GET /users/1
POST 创建 POST /users
PUT 全量更新 PUT /users/1
PATCH 部分更新 PATCH /users/1
DELETE 删除 DELETE /users/1

3.2.2 REST 状态码

码 含义
200 OK
201 Created
400 Bad Request
401 Unauthorized
404 Not Found
500 Server Error

3.2.3 FastAPI 示例

from fastapi import FastAPI, HTTPException
from pydantic import BaseModel

app = FastAPI()

class User(BaseModel):
    name: str
    email: str

users = {}

@app.post("/users", status_code=201)
async def create_user(user: User):
    users[user.email] = user
    return user

@app.get("/users/{email}")
async def get_user(email: str):
    if email not in users:
        raise HTTPException(404, "User not found")
    return users[email]

自动生成 OpenAPI 文档 (/docs)。

3.2.4 GraphQL

客户端定字段, 一次查询拿全部。

query {
  user(id: 1) {
    name
    posts {
      title
    }
  }
}

适用: 多端, 字段多变。

3.2.5 gRPC

Protobuf + HTTP/2, 强类型, 流式。

service LLMService {
  rpc Generate (GenerateRequest) returns (GenerateResponse);
  rpc Stream (StreamRequest) returns (stream StreamResponse);
}

适用: 微服务内部通信。


第 3 段 · SOLID 与设计模式 (10 分钟)

3.3.1 SOLID 五原则

原则 含义 例子
Single Responsibility 一个类一个职责 UserRepository 只管用户数据
Open/Closed 扩展开放, 修改关闭 通过继承扩展功能
Liskov Substitution 子类可替换父类 Square extends Rectangle
Interface Segregation 接口要小 拆分大接口
Dependency Inversion 依赖抽象, 不依赖具体 DI 容器

3.3.2 常用模式

工厂 (Factory):

class ModelFactory:
    @staticmethod
    def create(name: str):
        if name == "gpt":
            return GPTModel()
        elif name == "llama":
            return LlamaModel()
        raise ValueError(name)

单例 (Singleton):

class Config:
    _instance = None
    def __new__(cls):
        if cls._instance is None:
            cls._instance = super().__new__(cls)
        return cls._instance

策略 (Strategy):

class LossStrategy:
    def compute(self, pred, target): ...

class MSELoss(LossStrategy):
    def compute(self, p, t):
        return ((p - t) ** 2).mean()

# 运行时切换
loss_fn = MSELoss() if task == "regression" else CrossEntropyLoss()

装饰器 (Decorator):

import functools
import time

def timer(func):
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        t0 = time.time()
        result = func(*args, **kwargs)
        print(f"{func.__name__} took {time.time()-t0:.4f}s")
        return result
    return wrapper

@timer
def train():
    ...

依赖注入 (DI):

class Trainer:
    def __init__(self, model, optimizer, scheduler):
        self.model = model
        self.opt = optimizer
        self.sched = scheduler

依赖由外部传入, 便于测试和替换。

3.3.3 反模式

  • God Object: 一个类做所有事
  • Spaghetti Code: 逻辑混乱
  • Magic Number: 硬编码
  • Premature Optimization: 过早优化

第 4 段 · 文档与可维护性 (8 分钟)

3.4.1 README 标准

# Project Name

简短描述 (1 句话)

## 安装
pip install mypkg

## 快速开始
\`\`\`python
import mypkg
\`\`\`

## 文档
docs.example.com

## 许可
MIT

3.4.2 Docstring (Google 风格)

def tokenize(text: str, max_len: int = 512) -> list[str]:
    """分词函数.

    Args:
        text: 输入文本
        max_len: 最大长度

    Returns:
        token 列表

    Raises:
        ValueError: text 为空时
    """

3.4.3 类型提示

from typing import Optional, List, Dict

def predict(
    model: nn.Module,
    inputs: torch.Tensor,
    threshold: float = 0.5
) -> List[int]:
    ...

mypy 静态检查。

3.4.4 ADR (Architecture Decision Records)

# ADR-001: 选择 vLLM 作为推理引擎

## 状态
已采纳 (2026-01-15)

## 背景
LLM 推理服务需要高吞吐, 低延迟。

## 决策
采用 vLLM, 因其 PagedAttention 节省显存 4×。

## 后果
- 优点: 吞吐 +24×
- 缺点: 学习曲线
- 风险: 项目活跃度依赖 Berkeley

记录关键决策, 避免重复争论。


第 5 段 · AI 项目特定设计 (8 分钟)

3.5.1 模型与代码分离

src/mypkg/
├── model.py       # 模型定义
├── data.py        # 数据加载
├── train.py       # 训练循环
├── evaluate.py    # 评估
└── inference.py   # 推理 (与 train 解耦)

3.5.2 配置外置

# configs/train.yaml
model:
  name: resnet50
  num_classes: 1000

train:
  lr: 0.001
  batch_size: 64
  epochs: 100

data:
  root: /data/imagenet
  workers: 8

用 hydra / omegaconf 加载。

3.5.3 日志与监控

import logging
import wandb

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
wandb.init(project="myproj")

for epoch in range(epochs):
    loss = train_one_epoch(...)
    logger.info(f"epoch {epoch}: loss={loss:.4f}")
    wandb.log({"loss": loss})

3.5.4 错误处理

try:
    model = load_model(path)
except FileNotFoundError:
    logger.error(f"Model not found: {path}")
    raise
except RuntimeError as e:
    logger.error(f"CUDA error: {e}")
    # fallback CPU

不静默吞错, 用结构化日志。


三 · 易错点 (5 条)

  1. 全局变量: 难测试, 用依赖注入。
  2. 混合关注点: 数据加载与训练混在一起, 难复用。
  3. 缺文档: 一个月后自己看不懂。
  4. 硬编码路径: 用配置。
  5. 过度工程: 小项目别用微服务。

四 · 跨章连接

章节 关联
Ch13 §05 编程语言 类型 / 范式
Ch14 §04 测试 单元测试
Ch15 §05 DevOps Docker 化

五 · 自测 5 题

  1. SOLID 五原则?
  2. FastAPI 与 Flask 区别?
  3. REST GET vs POST?
  4. 单例模式适用?
  5. ADR 用途?

六 · 一句话总结

代码设计 = 模块化 + API + SOLID + 文档。AI 工程师的代码 = 模型 + 数据 + 服务, 三者都需要好架构。Ch15 §04 进入测试。


七 · 板书建议

[板书 1: 包结构]
   src layout
   pyproject.toml

[板书 2: API]
   REST GET/POST
   FastAPI 类型提示

[板书 3: SOLID]
   单一职责 + 开闭 + ...

[板书 4: 文档]
   README + docstring
   ADR

八 · 参考资料

  1. Robert C. Martin, "Clean Architecture"
  2. FastAPI 官方文档
  3. Google Python Style Guide
  4. hydra (配置管理)
  5. Ch13 §05 编程语言 (本套书)