在写代码写久了,我越来越觉得,常量元素表这几个字,其实有点像一个程序员的“世界观清单”。它看起来只是几行配置、几条枚举,实则暗中支配着无数业务规则、无数 Bug 的生死。
一、常量写在散处的人生,真的很累
先从一个很常见、也有点狼狈的经验说起。
早年接手一个老系统,页面上的状态文案、颜色、按钮可不可点击,全都散落在各个角落:
- 某个 Vue 组件里写死:
status === 1 ? '启用' : '停用' - 另一个 React 组件里写:
if (status === 2) { /* 禁用 */ } - 后端 Java 里还有一堆:
if (status == 3) { ... }
当时没人说什么 常量元素表,只知道“这个需求不难,改几行判断就好”。结果三年之后,全组人被这些魔法数字追着打。
那天产品说:“状态从三种扩到五种,多加两个:待审核、审核失败。”
我打开代码,心里咯噔一下:完了,又要满仓库搜 1、2、3。你知道那种感觉,就像找前任借走却没还的书——模糊记得在某个角落,却怎么也想不起是哪个。
那一刻我第一次真切地意识到:如果当初我们老老实实做一份 常量元素表,把状态值、含义、展示文案、颜色统统集中定义,后面所有人都会轻松很多。
二、什么是“常量元素表”?别急着套书面定义
很多教材会说:常量元素表是系统中各类固定值(状态码、枚举、配置项等)的集中说明与维护表,用于统一含义与使用方式。
听着很对,但也有点空。
我更愿意这样形容它:
常量元素表,就是项目里“别再问”的那一页。
- 状态码是啥意思?看常量元素表。
- 这个
role=4是什么身份?看 常量元素表。 - 错误码
E1023的文案在哪里改?还是看 常量元素表。
从工程实践的角度,它往往长这样:
- 一张文档表:字段名、常量值、描述、前端展示、备注;
- 一组代码枚举:
StatusEnum、RoleEnum、ErrorCode; - 一些前后端共享的配置:JSON、TS 类型、protobuf 描述等。
真正成熟的团队,会让“先定义 常量元素表 再写逻辑”变成一种默认流程,而不是写完逻辑再去补文档的临时抱佛脚。
三、为什么不把常量散着写?因为代价太隐蔽
很多人会反驳:
“这种小系统,写个 if 就完了,搞什么 常量元素表,太重了吧?”
我以前也这么想。后来踩坑踩多了,慢慢发现这玩意不是“有没有”的问题,而是“什么时候补课”的问题。
1. 没有统一表,沟通成本爆炸
产品问:“现在系统里一共有多少种订单状态?”
如果有 常量元素表,你可以淡定地把链接甩过去。如果没有,你得:
- 在代码里
rg 'status'; - 一个文件一个文件点进去;
- 想半天:
status = -1到底有没有在某个边角逻辑里用过?
时间一点点耗掉,心情一点点变差。并且最可怕的是——你给出的答案,很可能还不准。
2. 魔法数字会慢慢腐蚀代码
0 代表啥?1 又代表啥?你当然可以记在脑子里。
但项目一大,脑子根本记不住。
真正的可怕之处在于,新同事也记不住,他们会凭感觉复制粘贴,于是同一个状态在不同文件中出现了不同解释。最后,只剩下一片混乱。
而有 常量元素表 的项目,代码通常会长这样:
ts
if (status === ORDER_STATUS.PENDING_REVIEW) {
// 待审核逻辑
}
哪怕你是刚进组的新手,一眼也知道这段判断的意思。你不会猜,不会脑补,也不会在心里骂人。
3. 不统一,就很难设计出稳定接口
API 的长期稳定,靠的其实不是框架、不是库,而是对常量的敬畏。
当你在接口文档里看到:
status: number,取值参考“内部实现”;
你多半会想转身离开。而如果有一份清晰的 常量元素表:
0– 待支付1– 支付成功2– 已取消
并且接口返回中明确写着:status 对应“订单状态常量表 v2”,那种安心感,是肉眼可见的。
四、怎么设计一份靠谱的常量元素表
我这几年踩过不少坑,总结下来,有几个要点特别关键。
1. 别只写“值”,一定要写“语义”
所谓 常量元素表,不是把 0/1/2/3 排成一列就算完事。
更有用的写法是:
字段名:order_status常量名:PENDING/PAID/CANCELED值:0 / 1 / 2业务含义:待支付 / 支付完成 / 用户主动取消前端展示文案:待支付 / 已支付 / 已取消颜色:#F59E0B / #16A34A / #6B7280是否可编辑:是 / 否 / 否
当 常量元素表 长成这样的“多维度说明书”,你会发现后续改动爽很多:
- 产品要改文案:只要更新这一行即可;
- 设计要统一颜色:一眼看到所有规则;
- 新人要理解流程:直接看表,比看代码舒服多了。
2. 前后端共用的常量,尽量同源
理想状态是:
- 有一个“源头描述”(例如 JSON、YAML、TS 类型),
- 后端读取生成枚举,
- 前端通过脚本同步生成常量与类型,
- 文档也可以从这份数据自动导出。
这样 常量元素表 就不再是一个“可能过期的 Confluence 页面”,而是整个系统的单一事实来源。
当然,现实里很多团队做不到完全自动化,那也没关系,至少要做到:
- 常量命名一致;
- 数值对应一致;
- 文档和代码中,引用的是同一个 常量元素表 链接。
不统一会怎样?很简单:有人改了前端的常量,忘记改后端,某一天线上突然出现一种“幽灵状态”,谁也说不清它是哪来的。
3. 为未来预留一点空间
一个小建议:设计 常量元素表 时,别那么抠门。
- 状态值可以留出一些空挡,比如用 10、20、30 这种步进;
- 错误码可以按模块划分区间;
- 预留字段:
deprecated、version、created_at。
你现在觉得“就这么点状态,够用了”,一年后回头看,十有八九会想揍当初的自己。
五、常量元素表背后,其实是一个团队的思维方式
说了这么多,你可能会觉得我在吹毛求疵,为一张 常量元素表 写这么长。
但对我来说,这事不只是“好不好用”的问题,而是一个团队到底怎么对待“规则”这件事。
- 有的团队习惯“写完再说”,规则散落在代码里,靠人的记忆和口耳相传;
- 有的团队会坚持先把 常量元素表 立起来,再在其上堆逻辑,把“规则”从第一天就写清楚。
前一种做法,短期开发快,长期维护痛;
后一种一开始略显慢吞吞,越往后越稳,越写越轻松。
我这几年更偏爱后者。也许是年龄大了,不太想再因为一堆 status == 1 的破事加班。
六、如果你现在正准备新项目,可以这样做
如果你刚好在启动一个新系统,或者准备做一次大重构,不妨花半天时间认真整理一份 常量元素表。
你可以先从几个最核心的维度入手:
- 用户角色:
USER_ROLE - 订单状态:
ORDER_STATUS - 支付方式:
PAY_METHOD - 错误码:
ERROR_CODE
写的时候,不要只写“值”,多写一点背景和边界:
- 这个状态在什么场景下出现?
- 是否对外暴露?是否稳定?
- 是否允许未来扩展?
把这些想清楚,写进 常量元素表,你会发现很多架构问题,在真正写代码之前就已经被解决了一半。
七、写在最后:常量看似死的,背后却是活的协作
常量元素表 这个词听上去挺冷冰冰的,但每次我认真维护它的时候,心里其实是松弛的。
因为我知道:
- 这是在替未来的自己减轻负担;
- 也是在帮队友避免无意义的猜测;
- 更是在给整个项目一点“可以依赖的秩序”。
代码世界里,变量是不断变化的剧情,而那些写在 常量元素表 里的东西,则像小说作者悄悄立好的“世界观设定”。
你可以改剧情,可以调角色,可以删减某些桥段,但只要世界观稳住,这个故事就不容易垮。
如果你问我,什么算是一个成熟项目的标志之一?
我会很认真地回答:
有一份被大家真正使用、真正认同、持续更新的 常量元素表。那是一种默契,也是一种长期主义。
发表回复