事情是这样的
上周五下午,我做了一个疯狂的决定:把项目里80%的接口文档全删了。是的,你没看错,删了。不是整理,不是重构,是直接删。
结果呢?开发效率反而提升了,bug少了,联调时间从三天变成三个小时。产品经理看我的眼神都不对了,仿佛我在代码里藏了什么黑魔法。
其实真相很简单——那些文档,大部分都是垃圾。
你的文档可能是最大的技术债
我见过太多项目,一上来先写二十页的接口文档,画复杂的流程图,定义各种枚举值,制定严格的命名规范。然后呢?代码迭代三版,文档还是第一版的。测试环境用a.com,生产环境用b.com,文档里写的是c.com。
这种文档有什么用?用来欺骗领导检查?用来给自己心理安慰?
代码和文档不一致,是杀伤力最大的技术债。因为它会在最关键的时刻——上线、交接、排查问题——给你致命一击。你以为在看文档,实际上在看科幻小说。
好文档的标准只有一个
好文档只有一个标准:它是代码的真实反映,而且跟着代码一起变化。
做不到这点的文档,写得越详细越害人。你花三天写的架构文档,两周后就变成了一份精美的谎言合集。
那怎么办?放弃文档?当然不是。
Rule 1:代码即文档
TypeScript的interface就是最好的文档。看看这个:
// 烂文档写法
/**
* 用户服务
* 用于处理用户相关业务
* @author 张三
* @date 2024-01-01
*/
class UserService {
/**
* 获取用户信息
* @param id 用户ID
* @returns 用户信息对象
*/
async getUserInfo(id: any): Promise<any> {
// ...
}
}
// 好文档写法
interface User {
id: string;
name: string;
email: string;
createdAt: Date;
}
async function getUser(id: string): Promise<User | null> {
// 代码即文档,类型即说明
}
看第二种写法,参数类型、返回值、是否可能为空,全在代码里。你甚至不需要一行注释。
Rule 2:只记录"为什么",不记录"是什么"
代码告诉你怎么做,文档应该告诉你为什么这么做。
比如这个:
// 为什么要先查缓存,而不是直接查库?
// 因为这个表有2000万数据,QPS高峰期直接打库会雪崩
// 缓存命中率约95%,足以应对大部分场景
// 如果缓存失效,用分布式锁避免击穿
这种注释才是有价值的。它记录了代码里看不出来的业务决策和性能考量。
Rule 3:用工具代替人工维护
Swagger、OpenAPI、GraphQL schema、自动生成的SDK——让工具来生成文档,而不是人。
人维护文档,文档一定会过期。工具跟着代码走,文档永远不会落后。
实际案例:我是怎么删文档的
我的删除标准就三条:
- 这个接口还有人在调用吗?
- 这个文档最近一次更新是什么时候?
- 这个文档描述的功能,代码里还有吗?
最后发现,80%的接口文档,对应的代码早就重构了八百遍,文档还是三年前的版本。留着的意义是什么?等着误导新人吗?
删完之后发生了什么
删文档之后,反而做了一些更有价值的事:
- 花一天时间,把核心业务的TypeScript类型定义全部补全
- 写了一份5页的架构决策记录(ADR),只记录为什么做这些选择
- 配置了CI流程,确保API变更必须同步更新schema
结果是:新人入职第二天就能上手开发,因为看代码就够了。那些花里胡哨的文档,新人第一周就会全部忽略——他们发现文档和代码对不上之后。
给团队的真心话
我理解为什么很多人热衷于写文档。写文档有成就感,看起来很忙,而且写完就觉得自己完成了任务。
但技术团队的核心价值不是产出文档,是解决问题。
如果你现在手头有一份三年前写的架构文档,强烈建议你打开IDE,对照代码一条条核对。我赌五毛钱,至少一半内容是错的。
文档是用来消除歧义的,不是用来展示自己技术水平的。把写二十页文档的时间,用来把代码写得更自解释,这才是真正的专业。
总结
删掉那些没人看的文档吧。留下那些代码里表达不了的决策过程,用工具生成机器可读的规范,把类型系统用好,让代码自己说话。
好的代码不需要翻译。好的团队,不需要那么多纸面上的约定。