把单位写进接口文档这个建议我认同,但它其实属于“靠人记住”的那一层防御,而这次出 bug 恰恰就是人没记住、或者两边记岔了。文档写得再清楚,约束力也只在读它的人身上。嗯我更想接着你说的那个现象聊——它“不报错、界面不崩、静静错给你看”——这才是真正该被干掉的东西。
工程上有个老概念叫 fail-fast:当底层假设被违反时,系统应该立刻、大声地挂掉,而不是带着错误值继续跑。new Date(1700000000) 这种调用,JS 引擎完全有能力发现“你喂进来一个 10 位数,按毫秒解析出来是 1970 年”,但它选择闷头算下去。嗯从某种角度看,这类 silent failure 比直接抛异常更难查,因为异常至少把堆栈甩你脸上。
所以“先看单位约定”作为排查顺序没问题,但更稳的做法是让“单位对不上”这件事从根本上不可能悄悄发生。几条具体路子:
嗯
一是把单位编码进格式本身,而不是编码进文档。接口直接走 ISO 8601 字符串(比如 “2023-11-14T08:30:00Z”),时间戳自描述,前后端拿到的是同一形态,根本不存在“秒还是毫秒”的默契问题。
二是把约定下沉到 schema。JSON Schema 或 protobuf 一旦定义好字段语义,一个 10 位整型灌进期望 13 位的字段,校验阶段就该红。把检查从“人脑记忆”挪到“工具执行”,fail-fast 才算真正落地。
三是静态检查层面拦一下 new Date(某个整型变量) 这类写法,不少团队的 lint 规则已经能抓。
顺带一个观察:前端 Date.now()、Java 的 System.currentTimeMillis() 给的是毫秒,而 Go、Python 的 time.time()、以及大量 Unix 系后端接口习惯用秒。这种“前端毫秒、后端秒”的组合几乎是行业默认雷区,不是个例,所以你才会说本地造数据用 Date.now() 一顺就对了、换真实字段就露馅。
你们组联调现在是靠文档为主,还是已经上了 schema 校验那一层了?