命名一直是我写代码时最磨蹭的环节之一。名字起糊了,后面读代码的人(包括一个月后的我)会一直付税。AI 很擅长甩出一串候选名,也很容易甩出看起来专业、读起来空洞的名字。这篇文章记我让它起名时留下的几条规矩——不是语法规范全文,是品味上的取舍。
先说结论:AI 是候选机,不是命名官
我愿意让 AI 起名,前提是:
我已经能用一句话说明“这个东西在业务里干什么”
我要的是 3–5 个候选,不是一个“最佳答案”
最终选定权在我,尤其是会进公共 API、表字段、事件名的那些
一上来就说“给个好名字”,它常会给你 handleUserData、processInfo、manageService 这类语法正确但语义稀释的词。候选机模式能逼它发散,也逼我比较。

图:AI 起名:候选机 vs 直接要一个最佳名(原创示意图)
规矩一:先写职责,再要名字
我会先用大白话写职责,再让它起名。例如:
这个函数:根据订单当前状态和支付回调,决定要不要把订单推进到“已支付”,并写出一条审计日志。它不负责发邮件。
然后才说:“按上面职责,给函数名和两个关键局部变量名各 3 个候选;避免用 process/handle/data/info/manager 当核心词。”
职责写不清,名字一定虚。 AI 填的是你描述里的空洞。你若只说“处理一下用户相关逻辑”,它也只能回敬你一个同样糊的名字。
有个副作用很好:写职责的过程里,我偶尔会发现函数本身该拆。名字难起,常常是因为职责在打架——这比起名失败更值得修。
规矩二:拒绝空心动词和万金油名词
我有一份个人黑名单(会随项目微调),大致包括:
空心动词:
process、handle、manage、do、deal万金油名词:
data、info、object、entity、item(在已有更具体词时)假精确:
util、common、helper当主名(作后缀有时勉强可接受,作主名我基本不用)
不是这些词永远禁用,而是它们不该成为名字的唯一信息量。handlePaymentCallback 比 handleData 好,是因为中间还有 PaymentCallback;若连这个都没有,就该回去补职责。
我会把黑名单直接贴进提示词。AI 仍可能擦边,但频率会下降。选定时我再人工扫一眼:读完名字,能否猜到输入输出边界?猜不到就换。
规矩三:和项目里已有词对齐,不要发明方言
AI 不知道你们仓库的“土话”。同一个概念,库里已经叫 Ledger,它却建议 AccountBook;库里事件叫 OrderPaid,它建议 PaymentSuccessEvent。每个单独看都挺好,放一起就是方言分裂。
所以我起名前会先丢上下文:
同模块里 5–10 个相近函数/类型名
关键术语表(若有)
“请优先复用已有词汇,不要近义替换”
对齐不是懒,是降低读者切换成本。新词只在引入真正新概念时才值得。

图:命名三关:职责清楚、避开空词、对齐仓库土话(原创示意图)
规矩四:作用域越大,名字越要经得起误解
局部变量可以短一点;跨模块的类型、公开方法、数据库列、消息主题,名字要按“可能被断章取义”来设计。
我的经验规则:
函数内临时变量:允许短,依赖邻近代码
文件/类内私有方法:要能表达步骤意图
包对外 API / 事件名 / 表字段:假设读者只看到名字和签名,看不到你的心情
AI 常对局部和全局一视同仁,都起得很“正式”。我会明确告诉它作用域:“这是私有辅助方法”或“这是对外 REST 资源名”,候选风格会不一样。对外名字我还会多问一句:“有没有可能被理解成别的职责?”有歧义就改,哪怕变长一点。
规矩五:中英与缩写,先定团队习惯再问 AI
若团队已经约定英文命名,就不要让 AI 自由发挥中英混搭。缩写也一样:cfg / config、idx / index、qty / quantity,混用比选哪个更糟。
我的做法是:在提示词里写明“缩写白名单”和“禁止缩写列表”。没有团队约定时,我个人偏向少缩写,除非是领域里人人认识的(如 id、url、http)。
一套我常用的起名对话
我用三到五句话写清职责与非职责
贴同模块已有命名样例
甩黑名单与作用域
只要 3–5 个候选,并让它为每个候选写半句“为何贴切”
我删掉空心的,留下两个,睡一觉或过一会再定(重要公开名才这么做)
第 5 步听起来矫情,但对公共 API 很值。很多后悔的名字,都是当场觉得“挺酷”的那一个。

图:公开命名流水线:职责→样例→黑名单→候选→冷放置(原创示意图)
几个真实味道的对比(虚构业务,真实偏好)
下面这些对比不来自某个开源项目,是我按自己品味编的示例,用来说明“空心”和“贴切”差在哪。
| 场景 | 我不太喜欢 | 我更倾向 |
|---|---|---|
| 把支付回调落成订单状态 | handleCallback |
applyPaidCallbackToOrder |
| 过滤已关闭店铺 | filterData |
excludeClosedShops |
| 算购物车优惠后金额 | processAmount |
calcPayableAfterCoupons |
| 发领域事件 | sendEvent |
publishOrderPaidEvent |
长名字有代价,但比短而空更划算——尤其是调用点分散时。局部循环变量 i、shop 仍可短;上表针对的是带业务含义的动作名。
AI 看到“更倾向”列,有时会矫枉过正,起出一行写不下的名字。那时我会加约束:“不超过四个实词,优先动宾结构。”品味是区间,不是越长越好。
布尔与集合:特别容易被 AI 带偏
布尔名我要求能读成是非句:isExpired、hasPaid、canRetry。AI 有时给 expiredFlag、checkStatus,读起来像名词或像动作,调用处就变成 if (expiredFlag) 这种需要猜极性的代码。
集合名要能看出元素:paidOrderIds 比 list、ids、orderData 清楚。若元素是配对关系,我会宁可 userIdToSession 这种啰嗦映射名,也不用 map 了事。
这些细节提示词里要写明。不写,模型会按“常见教程命名”给你一套平均水平的名字——能跑,但偏糊。
和代码生成绑在一起时怎么做
很多时候起名不是单独一轮,而是“顺便实现函数”。这时风险更大:AI 会先写实现,再倒着起一个贴合实现的名字;实现若偏了,名字会把偏差钉死。
我的习惯是:先定名字与签名,再生成函数体。 或者生成后,把名字当一等公民单独审一遍,不默认“能编译就收”。签名审查的checklist很短:
名字是否泄露了不该泄露的实现细节?
是否把两个职责缝进一个动词?
是否和模块内近义函数撞车?
撞车时不要靠 2、Ex、New 后缀和解,回去拆职责或统一旧名。
什么时候不要纠结名字
也有反过来的时候:探索性脚本、一次性迁移、明确会删的实验代码,名字及格就行,别让品味拖延实验。我会在文件头注明“临时”,避免临时名泄漏进主干对外接口。
另一类是:重构中的过渡名。可以先 XxxV2 或 XxxLegacy,但要有删除计划。AI 很爱建议永久留下 V2,那是技术债命名法,我一般拒绝。
有一次我让 AI 给“重算用户积分”起名,它连续给出 recalculateUserPoints、refreshScore、syncPoints。单独看都还行,可项目里“积分”一直叫 credit,从未叫 points/score。若当时图快收下,就会在仓库里埋一个同义方言。从那以后,术语对齐被我写成起名前的固定动作,不再靠临场想起来。
品味是约束,不是灵感崇拜
我并不相信存在“唯一正确”的名字。规矩的作用是缩小糟糕集合,让候选落在可讨论的区间。AI 提供的是速度和发散;品味来自你对读者成本的敏感。
留给我自己的检查句是:这个名字删掉注释后,还能不能让下一个读者少问一句“这是干啥的”? 能,就过;不能,就让 AI 再出一轮候选——别急着收下第一个“专业”的空心词。


2026-10-14鱼鱼