走到这一章,你已经有了设备、配好了环境、学会提问、用上了顺手的工具、也懂得在 linux 上把服务跑起来。万事俱备,最后一个问题来了:写什么,怎么写。

正确

正确是第一要求,Test Driven Development (TDD) 是一种开发规范,用测试保证你代码的正确性。不过虽然测试很重要,但要牢记过犹不及。过多的测试会变得冗余,拖累开发进度,实际帮助却不大。

可读性

“Any fool can write code that a computer can understand. Good programmers write code that humans can understand.” - Martin Fowler

  • 命名要有意义:别用 atmp2data1 这种名字。变量叫 user_count,函数叫 calculate_average_score,一眼就知道其作用。
  • 命名长度要合适:导出给外部的接口要详细,内部变量可适当精简,date_of_birthdob 好懂,除非 dob 在你的领域里是约定俗成的。
  • 函数要短小:遵守单一职责原则,一个函数最好只做一件事。函数参数也别太多,超过三四个就考虑用一个结构体或字典收着,否则调用时容易把顺序搞错。
  • 用常量或枚举代替魔法数字:与其写 if age > 18,不如写成 ADULT_AGE = 18 再比较,魔法数应当是代码中严禁出现的东西。

提前退出

有些教程主张少用 continuebreak,尽量只有一个 return,保证函数单一出口,但实际写代码通常不会严格遵守这些要求。与其写一大坨嵌套的 if,不如把不满足条件的情况先 return 掉,主体逻辑自然就平铺下来。这种反转 if 判断、提前退出的写法叫卫语句(guard clause),能大幅减少缩进层级。

反面例子,层层嵌套:

def process(user):
    if user is not None:
        if user.is_active:
            if user.has_permission:
                do_work(user)

改成提前退出,立刻清爽:

def process(user):
    if user is None:
        return
    if not user.is_active:
        return
    if not user.has_permission:
        return
    do_work(user)

从例子中就可以看出,此方法对于 Python 这种需要拿游标卡尺写代码的语言的可读性有极大提升。

注释

注释不是为了凑字数,而是解释为什么——那些从代码本身看不出来的意图。

# 错误示范:复述代码
i = i + 1  # i 加 1

# 正确示范:解释原因
i = i + 1  # 跳过已下线的用户,避免统计脏数据

和测试一样,注释也要牢记过犹不及。过多的注释会起反作用,尤其是过时的注释比不写更糟。个人经验是:每个方法、接口、类以及类中的字段最好都有注释;逻辑复杂的方法,在方法中每个阶段写一个注释即可。

DRY

同一段逻辑出现在五个地方,改一处就得改五处,漏一个就是 bug。把重复的逻辑抽成一个函数,谁要用谁调用。DRY 即 Don’t Repeat Yourself,别重复自己。

反过来也别走极端:为了复用把两个其实不太相干的东西硬揉在一起,反而更乱。

KISS

Keep It Simple, Stupid。能简单就别复杂。初学者常犯的毛病是还没写几行就想上各种抽象、设计模式、泛型,结果代码绕来绕去,自己都看不懂。先写出能跑的直白版本,真遇到重复或扩展压力时再考虑抽象。最简单的方案往往最不容易出错,也最容易被别人接手。

实际写代码要分析场景,用最小的代价完成最多的事,软件工程没有 silver bullet,适合的才是最好的,trade-off 是贯穿全流程的判断。

错误处理要诚实

初学者常写:

try:
    do_something()
except:
    pass  # 吞掉所有错误

except 后面什么都不做,等于把问题藏进黑洞,将来排错会极为痛苦。要么真的处理(比如重试、用默认值),要么把错误原样抛出来或记到日志里,让问题暴露出来。

版本管理

前面章节提到过 git,这里再强调一次:从第一行代码开始就用 git。每次完成一个小功能就 commit 一次,写上清楚的提交信息。

git 给了你两样东西:出事了能回滚,协作时不会互相覆盖。这是写出可持续维护的好代码的基础设施,不是可选项。

CLAUDE.md

下面是笔者最近开发过程中整理出的一个 CLAUDE.md

# 全局规则 (Global Instructions)

以下规则适用于所有项目、所有会话,除非用户明确指示 otherwise。

## Git 与提交

- **不要私自执行 `git commit`、`git push` 或暂存改动(`git add`)。** 仅在用户明确要求时才提交或推送。
- 不要主动创建分支、stash 或改动工作区状态,除非任务需要或用户要求。

## 编码过程

- **编码过程中不要过度 review,也不要反复停下测试。** 实现完成后再进行统一的 review 和测试;中途只做必要的最小验证。
- 过程中频繁停下 review/测试会打断实现节奏,集中在结束时一次性做更高效。
- 实现完成后,先跑 `make fix` / `gofmt -w` 等格式化(如适用),再做统一 review。

## 代码复用

- **写代码时优先复用当前已有的代码,尤其是工具类、数据库类等通用方法。** 先搜索仓库中是否已有可实现相同功能的工具方法、DAO/service 或公共函数,确认没有再新写;避免重复造轮子导致同一逻辑存在多份实现、后续难以维护。

## Python 运行环境

- **运行 Python 代码时禁止直接运行,必须在 conda 环境下运行。** 不要直接使用系统 `python` 或裸 `python3` 执行,必须先激活一个明确的 conda 环境。
- 如果不确定应该使用哪个 conda 环境,先询问用户,不要擅自猜测或默认使用 `base`
## 注释

- **注释简洁,不要长篇大论。** 只写必要的注释,避免多段 docstring 或多行注释块,能用一行说清就不用多行。
- **修改代码时同步更新对应注释。** 代码改了注释没改等于误导,保持二者一致。
- **注释与代码不一致时,以代码为准并更新注释。** 不要照着过时注释去理解或改代码,先核实代码实际行为,再修正注释。
- **不要完全相信注释。** 注释可能过时、不准或本身就错,以代码实际行为为依据;发现错误注释时顺手修正。

## 子 Agent

- **使用子 agent 时,所有子 agent 必须与主 agent 使用相同模型。** 不要给子 agent 指定不同的 model(如 haiku/sonnet/opus 切换),保持与主 agent 一致,避免不同模型能力差异导致结果不可控。

## 测试

- **只写必要的测试。** 优先针对真实行为和边界情况写少量有针对性的测试,而不是为每个方法都做覆盖。只在行为不确定、容易出错的地方写测试;确定无疑的逻辑可以不写。
- **执行测试时,精确指定目标**——具体文件、测试名或 `-t` 过滤模式。禁止一次性执行整个测试套件或与当前改动无关的测试。
- **避免执行会写数据库的测试**(除非用户明确要求)。运行前先确认测试是否会修改持久化数据;若不确定,先问用户。
- 测试失败时如实报告输出,不要谎报通过。

项目分层

在大型项目中合理地对模块分层能提高你的开发效率和代码的可读性,浅谈后端项目分层 这篇是我对后端项目分层的一些拙见。