There are only two hard things in Computer Science: cache invalidation and naming things. —— Phil Karlton
前言
开发人员习惯性的对设计、架构、微服务夸夸其谈,却很少关注设计、架构如何完完整整的落地到代码本身。架构和设计固然重要,代码并非不重要。正如 Robert C.Martin
所言:“代码即设计”。透过好的代码,就能看到其背后精美的设计。
好的代码,第一步是为每一个类、函数、变量起一个好的名字。可惜的是,大多数人对于如何起一个好名字不得其法。毕竟严格上来说,命名并非计算机科学的范畴。好的命名一个词就可以简单、形象、直观表明其功用甚至原理,例如:
- SYN flood:洪水一样的SYN请求
- Pipeline:管道一样传输数据、依次且单向
以上还只是问题解决域,还不是最难的。最难的是,在实际研发中,还要面对问题分析域。如果你的思路结构、层次不清晰,抽象出的各种状态不正交,相互重叠,交差,此时再想起出比较好的名字,则回天乏术;如果你不知道一个事物应该叫什么,你就不可能知道它是什么(A Rose by Any Other Name Will End Up As a Cabbage),所以命名的过程也是整理思路的过程。
根据过往的经验总结,可以将命名分为三个Level,前两个 Level 覆盖 Solution Space 的困境,最后一个 Level 覆盖 Problem Space 的困境
- Level 1:坏味道,嗅出坏味道才能意识到需要改变
- Level 2:命名技巧,一些简单的命名技巧,明白有哪些渠道可以改进
- Level 3:领域语言,命名的道,命名是可以系统化的从业务过渡到研发。
Level 1: 坏味道
- 无意义的命名
i.e.
data
、info
、record
- 抽象的命名
i.e.
data
、object
、helper
、tool
、manager
、processor
、handler
、maker
、util
、conf
、thing
、info
、amount
、details
、do
、execute
、perform
、operate
、manage
、handle
不够精确,毫无疑问,你确实命名了数据和对象,但即使没有此模糊的名称你也早知道的。将
data
重命名为更具描述性的名称,以标识数据
- 简称
i.e.
mod
mod
像是某个单词的简称,你可能无法确认到底是mode
或module
- 含糊
i.e.
Manager
命名模糊,谁知道经理到底是干什么的?可以更有意义的替代方案,如:牧民(Herder)、主管(Supervisor)、策划人(Planner)、建筑商(builder)
- 多个单词
i.e.
company_person
代表公司人员重命名
company_person
为staff
更为合适,或者更新一步employee
或director
- 被动语态
i.e.
PlanEvents
重命名
PlanEvents
为主动语EventPlanner
更好,或者更进一步Scheduler
Level 2: 命名技巧
增加词汇量
命名只是写作的一部分,主要是词汇。你可能还记得学习外语的一部分就是学习词汇。不用学外语是利弊并存之事。
- 阅读开源、基础库代码
- 例如:Linux 内核、C++ STL 库 等等
- 查找业务关联概念
- 例如,库存单位:
sku
( Stock Keeping Unit );搜索简称:qv
(Query View Count)
更好的命名方法
- 遵从惯例、标准
不要使用
identifier
,而是使用业界惯例id
作为唯一标识命名。类似的:
ptr
为pointer
的缩写;i
、j
、k
常常是完美的循环计数变量命名。size
、capacity
、resize
、reserve
、push
、pop
、top
、back
,作为容器的接口,久经考验。要自定义容器不应该使用GetSize
等命名。
- 遵从约束
- 语言约束:例如,Go 语言 使用
驼峰
风格,代码中就不要使用C语言的大写下划线连词
风格 - 团队约束:对同一个概念,团队内已经有对应的称呼,应该遵从,而是不是任性夹带私货,例如:直播中(
ongoing
vsliving
),已经命名为ongoing
,要么替换为living
;就全部替换掉,要么继续使用ongoing
,虽然后者更确切。 - 框架约束:使用 Shopify/sarama 作为 kafka 的 客户端就应该使用
Consumer
、ConsumerGroup
、ConsumerGroupHandler
,命名三个层级,而不是自撰 三个层级:Dao
、Consumer
、Processor
- 对齐、对称
对齐: Golang 标准库包名,httptest、httputil、httptrace
对称:典型的对称,
producer
/consumer
、begin
/end
、create
/destory
、destination
/source
、get
/release
、increment
/decrement
、insert
/delete
、next
/previous
、old
/new
、old
/new
、open
/close
、put
/get
、show
/hide
、start
/stop
、target
/source
、
Level 3: 领域语言(Domain language)
人对名字的反应是潜意识的…所以如果对一个名字有疑惑,可能很难确切地表达原因。我们的设计系统命名应该符合预期。… 但是谁的期望?所有利益相关者,系统的利益相关者,包括但不限于:
- 产品经理
- 开发(前端、后端、客户端)
- 测试
- 用户
代码应该自动使用与业务或领取模型相同的名称。例如,如果一个旅游企业使用 “venue” 作为咖啡馆、酒店和旅游景点的通用名称,那么在代码中使用 “place” 是一个坏主意
- 其一,因为使用两种不同的语言,使得沟通变得更复杂
- 其二,如果一个词汇,产品经理和用户等不理解软件开发同学的都能直观的理解,那么此命名将是一个好的名字
- 其三,将代码命名与领域模型关联起来,所有命名跟业务是契合的
- 其四,随着需求迭代,打磨领域模型的同时,可以保证命名随之重构符合语义,保持常新
使用领域语言统一开发流程,可以从根本上解释命名来源以及合理性。相比一般的技巧,是系统的有理论支撑的。如果技巧是工程派的产出,那么领域语言指导命名就像是学院派的产出。
具体如何在项目中实施DDD,后续详解。
本文作者 : cyningsun
本文地址 : https://www.cyningsun.com/07-04-2020/how-to-naming-things.html
版权声明 :本博客所有文章除特别声明外,均采用 CC BY-NC-ND 3.0 CN 许可协议。转载请注明出处!