《代码整洁之道》第 2 章 有意义的命名
第 2 章 有意义的命名
2.2 名副其实
如果名称需要注释来补充,那就不算是名副其实。
public List<int[]> getThem() { List<int[]> list1 = new ArrayList<int[]>() ; for (int[] x : theList) if (x[0] == 4) list1.add(x) ; return list1; }
为什么难以说明上列代码要做什么事?里面并没有复杂的表达式。空格和缩进中规中矩。只用到三个变量和两个常量。甚至没有涉及任何其他类或多态方法,只是(或者看起来是) 一个数组的列表而已。问题不在于代码的简洁度,而是在于代码的模糊度:即上下文在代码中未被明确体现的程度。上列代码要求我们了解类似以下问题的答案:
(1) theList 中是什么类型的东西?
(2) theList 零下标条目的意义是什么?
(3) 值 4 的意义是什么?
(4) 我怎么使用返回的列表?
问题的答案没体现在代码段中,可那就是它们该在的地方。
修改方法:
-
零下标条目是一种状态值,而这种状态值为 4 表示“已标记”。
if (cell[STATUS_VALUE] == FLAGGED) flaggedCells.add(cell); -
另写一个类,该类包含一个名副其实的函数(isFlagged)从而掩盖住 "4" 这个魔术数。
if (cell.isFlagged()) flaggedCells.add(cell)
2.3 避免误导
- 应当避免使用与本意相悖的词。
- 提防使用不同之处较小的名称。比如用小写字母
l
和大写字母O
作为变量名。
2.4 做有意义的区分
以数字系列命名(a1、 a2,...N)是依义命名的对立面。这样的名称纯属误导一完全没有提供正确信息;没有提供导向作者意图的线索。
public static void copyChars(char a1[], char a2[]) { for (int i = 0; i < a1.length; i++) { a2[i] = a1[i] ; } }
如果参数名改为 source
和 destination
,这个函数就会像样许多。
假设你有一个 Product
类。如果还有一个 ProductInfo
或 ProductData
类,那它们的名称虽然不同,意思却无区别。Info 和 Data 就像 a、an 和 the 一样,是意义含混的废话。
废话都是冗余。Variable
一词永远不应当出现在变量名中。Table 一词永远不应当出现在表名中。NameString
会比 Name
好吗? 难道 Name
会是-一个浮 点数不成?如果是这样,就触犯了关于误导的规则。设想有个名为 Customer
的类,还有一个名为 CustomerObject
的类。区别何在呢? 哪一个是表示客户历史支付情况的最佳途径?
2.5 使用读得出来的名称
命名时不要使用傻乎乎的自造词,要使用恰当的英语词。
2.6 使用可搜索的名称
单字母名称和数字常量有个问题,就是很难在一大篇文字中找出来。
找 MAX_CLASSES_PER_STUDENT
很容易,但想找数字 7 就麻烦了,它可能是某些文件名或其他常量定义的一部分,出现在因不同意图而采用的各种表达式中。如果该常量是个长数字,又被人错改过,就会逃过搜索,从而造成错误。
同样,e 也不是个便于搜索的好变量名。它是英文中最常用的字母,在每个程序、每段代码中都有可能出现。由此而见,长名称胜于短名称,搜得到的名称胜于用自造编码代写就的名称。
窃以为单字母名称仅用于短方法中的本地变量。名称长短应与其作用域大小相对应。若变量或常量可能在代码中多处使用,则应赋其以便于搜索的名称。再比较
for (int j=0; j<34; j++) { s += (t[j]*4)/5; }
和
int realDaysPerIdealDay = 4; const int WORK_DAYS_PER_WEEK = 5; int sum = 0; for (int j=0; j < NUMBER_OF_TASKS; j++) { int realTaskDays = taskEstimate[j] * real DaysPerIdealDay; int realTaskweeks = (realdays / WORK_DAYS_PER_WEEK) ; sum += realTas kWeeks; }
注意,上面代码中的 sum 并非特别有用的名称,不过它至少搜得到。采用能表达意图的名称,貌似拉长了函数代码,但要想想看,WORK_DAYS_PER_WEEK
要比数字 5 好找得多,而列表中也只剩下了体现作者意图的名称。
2.7 避免使用编码
匈牙利语标记法(Hungarian Notation,HN)和成员前缀已经过时,是旧代码的标志物。
2.9 类名
类名和对象名应该是名词或名词短语,如 Customer
、WikiPage
、Account
和 AddressParser
。避免使用 Manager
、Processor
、Data
或 Info
这样的类名。类名不应当是动词。
2.10 方法名
方法名应当是动词或动词短语,如 postPayment
、deletePage
或 save
。属性访问器、修改器和断言应该根据其值命名,并依 Javabean 标准加上 get
、set
和 is
前缀。
string name = employee.getName(); customer.setName("mike") ; if (paycheck.isPosted())...
重载构造器时,使用描述了参数的静态工厂方法名。例如,
Complex fulcrumPoint = Complex.FromRealNumber (23.0);
通常好于
Complex fulcrumPoint = new Complex (23.0);
可以考虑将相应的构造器设置为 private
,强制使用这种命名手段。
2.16 添加有意义的语境
设想你有名为 firstName
、lastName
、street
、houseNumber
、city
、state
和 zipcode
的变量。当它们搁一块儿的时候, 很明确是构成了一个地址。不过,假使只是在某个方法中看见孤零零一个 state
变量呢?你会理所当然推断那是某个地址的一部分吗?
可以添加前缀 addrFirstName
、addrLastName
、addrState
等,以此提供语境。至少,读者会明白这些变量是某个更大结构的一部分。当然,更好的方案是创建名为 Address
的类。这样,即便是编译器也会知道这些变量隶属某个更大的概念了。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY