核心问题

命名到底是在描述代码,还是在塑造系统?

很多人把命名当成最后的润色:

代码写完了,把变量名改好看一点。

但在软件工程里,命名不是装饰。命名是设计本身。

因为名字会决定:

  • 团队如何理解一个概念
  • 后续需求会被塞到哪里
  • 哪些状态看起来合法
  • 哪些关系会被隐藏
  • 哪些错误会变得容易发生

一个坏名字不只是“不优雅”,它会持续把系统引向错误方向。

名字会吸附需求

如果系统里有一个很宽的名字:

User

新需求来了,大家会自然地把东西塞进去:

user.role
user.companyId
user.subscriptionStatus
user.isInstructor
user.isCustomer
user.permissions
user.metadata

这叫名字的吸附效应。

越宽泛的名字,越容易变成垃圾桶。

相反,如果名字边界清楚,需求会自然流向正确位置:

Account
Credential
OrganizationMembership
InstructorProfile
Subscription
CourseAccessGrant

好名字像路标。它告诉后来的人:

这个变化应该放这里,不应该放那里。

名字应该回答边界问题

好名字不只是“看得懂”,还要回答边界问题。

例如:

Customer

这个名字看似常见,但边界不清:

  • 下过单就是 customer 吗?
  • 当前付费才是 customer 吗?
  • 退款后还是 customer 吗?
  • 企业合同里的员工算 customer 吗?
  • 免费试用用户算 customer 吗?

如果这些问题没有答案,Customer 就不是好名字。

更清楚的名字可能是:

PayingAccount
ActiveSubscriber
Purchaser
OrganizationContractHolder

这些名字更窄,但更可验证。

原则:

好名字应该让边界争议显形,而不是把争议藏起来。

名字应该绑定事实

日常语言容易含糊,工程语言必须落到事实。

例如:

Student

在课程平台里,Student 很可能不够精确。

更好的名字取决于事实:

Enrollment
CourseAccessGrant
LessonProgress
CourseCompletion

如果你想表达“正在学习某门课”,可能是:

Enrollment

如果你想表达“有权访问某门课”,可能是:

CourseAccessGrant

如果你想表达“学完了某门课”,可能是:

CourseCompletion

这些名字的优势是:它们不是印象,而是事实。

避免万能名词

万能名词通常是坏设计的温床。

高危词包括:

Manager
Handler
Processor
Service
Helper
Util
Data
Info
Context
Object
Record
Entity
Relation
Metadata

这些词不是绝对不能用,但它们往往说明我们还没想清楚。

例如:

CourseManager

它管理什么?

  • 课程创建?
  • 课程发布?
  • 课程访问?
  • 课程内容编辑?
  • 课程推荐?
  • 课程归档?

更好的名字可能是:

CoursePublisher
CourseAccessPolicy
CourseCatalog
CourseEditor
CourseArchiver

名字越具体,职责越难乱跑。

避免过度技术化命名

有些名字过于工程内部化:

AbstractActorRelationResolver
GenericResourceBinding
UnifiedSubjectContext

这些名字的问题不是长,而是它们没有领域含义。

领域系统里的核心名字应该尽量来自业务语言:

Enrollment
Purchase
Refund
Subscription
OrganizationMembership
CourseAccessGrant
InstructorProfile

技术词可以出现在基础设施层:

Repository
EventBus
OutboxWorker
CacheAdapter
PolicyEvaluator

但如果业务层充满 GenericAbstractBaseContext,通常说明设计正在离开领域。

名字应该暴露层级

一个好名字能让人知道它在哪一层。

例如:

事实层

CoursePurchased
PaymentRefunded
LessonCompleted
OrganizationMemberInvited

这些名字通常是过去式,因为它们表示已经发生的事实。

状态层

SubscriptionStatus
EnrollmentStatus
CoursePublicationStatus

这些名字表示生命周期阶段。

规则层

canAccessCourse
canEditCourse
canInviteMember
isSubscriptionActiveAt

这些名字通常是谓词或动作判断。

效果层

CourseAccessGrant
PermissionGrant
NotificationRecipient

这些名字表示多个事实共同产生的效果。

机制层

OutboxEvent
RetryPolicy
MessageConsumer
Repository

这些名字属于技术机制。

如果不同层级混名,系统会变难理解。

例如:

UserEventStatusManager

这个名字里同时出现对象、事件、状态、管理器,但没有说清楚它到底负责什么。

布尔命名要小心

布尔值尤其容易制造假简单。

坏例子:

isActive
isValid
isEnabled
isComplete

这些名字的问题是语义不完整。

isActive 对账号、订阅、课程、企业合同可能含义完全不同。

更好的名字:

canSignIn
isSubscriptionBillable
isCoursePublished
isEnrollmentCompleted
isContractInForce

布尔命名最好包含判断对象和判断标准。

如果一个布尔值需要读文档才知道意思,名字还不够好。

状态命名要表达生命周期

状态名要能看出流转。

例如:

type CoursePublicationStatus = "draft" | "published" | "archived"

比:

type CourseStatus = "active" | "inactive"

更好。

因为前者表达了课程发布生命周期,后者只是模糊开关。

好的状态命名应该满足:

  1. 状态集合互斥。
  2. 每个状态有明确含义。
  3. 状态之间能画出流转图。
  4. 不依赖外部解释才能理解。

函数命名要表达意图,不只表达动作

坏例子:

processUser(user)
handleCourse(course)
updateData(data)
syncStatus(id)

这些名字只说“做了点事”,没有说明为什么做。

更好的名字:

grantCourseAccessFromPurchase(purchaseId)
expireInactiveEnrollments(now)
publishCourse(courseId)
revokeAccessAfterRefund(refundId)
inviteOrganizationMember(organizationId, email)

好函数名应该让调用者知道业务意图。

命名是一种压缩

一个名字是对一组规则的压缩。

例如:

canAccessCourse(accountId, courseId)

这个名字背后可能包含:

  • 是否购买
  • 是否退款
  • 是否订阅有效
  • 是否企业分配
  • 是否课程下架
  • 是否账号被封禁

调用者不需要知道这些细节,只需要相信这个名字。

所以命名的质量决定了压缩是否可靠。

坏名字会压掉关键差异。

好名字会隐藏细节,但不隐藏边界。

改名是低成本重构

很多重构不需要先改架构,先改名字就能让问题显形。

例如把:

User

改成:

Account

你会立刻发现哪些字段不属于账号:

legalName
companyRole
courseProgress
billingAddress

再比如把:

isActive

改成:

canSignIn

你会立刻发现它和订阅是否有效不是一回事。

改名的价值是:

它强迫系统承认真实边界。

命名检查清单

给一个新概念命名时,可以问:

  1. 这个名字对应事实、状态、规则、效果还是机制?
  2. 它有没有独立生命周期?
  3. 它有没有独立不变量?
  4. 它的反例是什么?
  5. 它和相邻概念有什么区别?
  6. 它是否依赖上下文?
  7. 它是否太宽,容易吸附未来需求?
  8. 它是否太技术化,脱离业务语言?
  9. 它能否让调用者少知道细节?
  10. 未来看到这个名字的人,会不会把新需求放错地方?

小结

  1. 命名不是润色,而是设计。
  2. 宽泛名字会吸附需求,最终变成垃圾桶。
  3. 好名字让边界争议显形。
  4. 日常语言要落到系统事实。
  5. 避免万能名词和过度技术化命名。
  6. 不同层级应该有不同命名风格。
  7. 布尔命名要包含判断对象和标准。
  8. 改名是低成本但高价值的重构。