在这里插入图片描述

你一定见过这种项目:

  • 本地能跑,换台机器就报错(路径、依赖、环境变量全靠缘分)。
  • 脚本能出结果,但没人敢改(改一行崩一片,回滚靠记忆)。
  • 代码写完“交付”给同事,结果对方问的第一句是:入口在哪?怎么复现?

数据分析与 AI 工程的真实门槛,从来不是“写出第一版”。

而是能不能把它变成:可复现、可验证、可监控、可维护的交付物。

本章给你一份可直接落地的「代码质量清单」,把“工程化”这件事从抽象口号变成可执行检查项。


0. 本章目标与适用场景

学完你应该能做到:

  1. 把一个脚本型项目,整理成“可交付工程包”的最小形态
  2. 为数据/AI项目建立质量门槛:格式、测试、类型、日志、配置、性能
  3. 用一套清单驱动 Code Review,减少“个人风格争论”
  4. 把交付物写成“别人 10 分钟能跑通”的标准

1. 交付的定义:不是“能跑”,而是“可控”

我把“可交付”拆成四个层级:

能跑: 本机能出结果

可复现: 换环境也能跑

可验证: 有测试/指标/回归

可运维: 有日志/配置/监控/故障定位

大部分 AI/数据项目停在 A。

真正可交付,至少要到 C;上线服务要到 D。


2. 项目结构清单:入口清晰,依赖可控

2.1 最小工程结构(建议)

这套结构适用于训练脚本、离线特征、RAG 数据管道、小型推理服务:

myproj/
  src/myproj/
    __init__.py
    cli.py
    config.py
    pipeline/
    utils/
  tests/
  scripts/
  data/           (可选:仅放小样本/示例)
  pyproject.toml  (或 requirements.txt)
  README.md

硬要求:

  • 业务代码放 src/,避免 import 混乱
  • README.md 必须能让别人跑通
  • tests/ 至少有一组“最小回归”

3. README 交付清单:让别人 10 分钟跑通

README 不需要写长,但必须写对:

  • 项目一句话用途(解决什么问题)
  • 环境要求(Python 版本/系统)
  • 安装方式(一个命令)
  • 运行方式(一个命令)
  • 示例输入/输出(最好有一行示例)
  • 常见问题(最容易踩坑的 3 个)

你可以用这个模板:

# myproj

## What
一句话说明:做什么、输入是什么、输出是什么。

## Setup
python -m venv .venv && source .venv/bin/activate
pip install -U pip
pip install -e .

## Run
python -m myproj.cli run --config configs/dev.yml

## Example
输入:data/sample.csv
输出:out/result.parquet

## FAQ
1) ...
2) ...
3) ...


4. 代码规范清单:减少“风格争论”,提高一致性

质量不是“写得优雅”,而是一致

4.1 格式化与静态检查(必选)

建议工具组合:

  • ruff:lint + 部分格式能力(快)
  • black:统一格式(可选,看团队习惯)
  • isort:导入排序(如果不用 ruff 的 import 规则)

原则:不靠人记规范,靠工具强制

4.2 命名与模块边界(工程规则)

  • pipeline/ 放流程编排,不放复杂逻辑
  • utils/ 只能放通用工具,禁止放业务规则(后面会讲怎么拆)
  • 数据字段/特征名集中管理(避免散落全项目)

5. 测试清单:数据/AI工程的“最小测试金字塔”

你不需要一开始就写很多测试,但必须有“能兜底”的那几类:

单元测试: 纯函数/边界/异常

组件测试: 特征/指标/解析模块

集成测试: 小样本跑通pipeline

回归测试: 固定数据+固定阈值

最低交付线:

  • 核心函数的边界/异常测试(例如分母为 0、字段缺失、NaN)
  • 一条小样本集成测试(几十行数据跑完整链路)
  • 一条回归断言(输出 schema 不变、关键指标不退化)

6. 类型与接口清单:输入/输出要“讲得清楚”

数据工程最常见的事故来自“接口不清晰”:

  • 入参类型漂移(int→str)
  • 约束缺失(允许空?允许 NaN?)
  • 输出 schema 靠猜(列名/单位/范围不稳定)

建议每个模块都明确三件事:

  1. 输入类型
  2. 输出类型
  3. 边界与异常策略

可以抽象成:

f : X → Y , X 需满足约束 ; C ( X ) f: X \rightarrow Y,\quad X \text{需满足约束} ; \mathcal{C}(X) f:XY,X需满足约束;C(X)

当约束不满足时,你要么抛异常,要么返回可恢复的错误对象(见下一节)。


7. 错误处理清单:可恢复 vs 不可恢复(别全靠 raise)

交付的本质是“出了问题能定位”。

建议把错误分层:

可恢复

可重试

不可恢复

输入错误: 参数/字段/schema

返回默认/跳过/降级

外部依赖: DB/网络/文件

重试+退避+超时

内部逻辑: 不变量被破坏

抛异常+报警

最低交付线:

  • IO 操作必须有超时与重试策略(至少在代码层预留接口)
  • 异常必须带上下文(哪个文件、哪个batch、哪个样本)
  • 不允许“吞异常后继续跑”,除非明确写了降级规则

8. 日志与可观测性清单:别让 print 负责上线

数据/AI工程一旦上线,问题通常出在:

  • 某批数据 schema 变了
  • 某个上游接口返回异常
  • 某次模型版本切换导致指标下滑

最低交付线:

  • 使用 logging,不要用 print
  • 日志至少包含:run_id/batch_id/step/time_cost
  • 关键输出要做“摘要统计”:行数、缺失率、分位数、topK 类别
  • 对外服务要有请求级 trace(哪怕先做简版)

9. 配置与环境清单:把“魔法常量”赶出代码

最常见的“不可交付”原因:配置散落在代码里。

建议分层:

  • config.yml:业务参数(阈值、路径、开关)
  • 环境变量:密钥/连接串(禁止写死)
  • 代码:默认值与校验规则

并建立“配置校验入口”:启动即校验(fail fast)。


10. 依赖与可复现清单:能装、能锁、能升级

最低交付线:

  • 明确 Python 版本范围(例如 >=3.10,<3.13
  • 依赖要锁版本(至少在生产环境)
  • 给出一键安装命令(pip install -e .pip-sync

进阶(付费栏目的工程建议):

  • 区分 dev/prod 依赖
  • 提供 Dockerfile(哪怕是基础版)
  • 用 CI 跑 lint + test + minimal pipeline

11. CI 自检清单:让质量“自动发生”

CI 的本质是:把质量检查变成默认路径

最低 CI 流程:

push/PR

lint/format

unit tests

smoke pipeline on sample

build artifact

你不需要一次把 CI 做到很复杂,但至少要做到:

“有人提交代码,就自动告诉你会不会把项目弄坏”。


12. 一份可直接复制的交付检查表(Review 用)

你可以把它贴到 PR 模板里:

  • README:新人 10 分钟能跑通
  • 入口明确:cli.pymain() 清晰
  • 配置外置:路径/阈值/开关不写死
  • 日志齐全:step + run_id + time_cost
  • 测试最小集:单元 + 小样本集成 + 回归断言
  • schema 稳定:输入输出列名/类型/单位有定义
  • 依赖可复现:版本范围与锁定策略明确
  • CI 通过:lint/test/smoke 均绿
  • 性能有底线:至少有 baseline(见第13章)

13. 小结:质量清单的价值,是“让团队省时间”

很多人把工程化理解成“更复杂”。

但真正的工程化是:让沟通成本降低,让变更风险可控,让交付变得可复制。

脚本能跑很容易;

把它变成可交付资产,才是你在数据/AI工程里真正的竞争力。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐