
知名程序员菲尔・卡尔顿(Phil Karlton)说过,计算机科学里只有两个难题:缓存失效与如何命名。其中很多著名的编程书籍,都有专门讨论关于命名的章节。命名不仅仅是对变量和常量的命名,还包含了函数、类、接口等代码中的元素命名。
命名应该体现“它是做什么或者是什么”,让阅读代码的人一看就懂。比如,著名编程书籍《Clean Code》中提出“变量、函数或类的名称,应该已经回答了所有重要问题,它是什么?它做什么?它为什么存在?”。比如“int m”到底是代表了月还是分钟?如果变量名是“int minutesSinceStart”阅读代码的人则可以瞬间明白这个变量是什么。无独有偶,另一部著名编程书籍《Code Complete》指出,命名应该聚焦于事物的核心职责。但是清晰的命名往往会让一个名字过长,因此程序员在命名时往往需要审时度势,在短期作用域中可以使用短命名。比如程序员常常在for循环中使用i或j作为变量名。
另外,也应该避免同义替换,比如函数名“getUser()”和“fetchUser()”都可以代表“获取用户”。为了避免歧义,应该统一使用“getUser()”。同时,也要避免误导性命名,比如“List<Customer> userList”,容器里是Customer,变量名却叫userList。
给函数命名时,应该使用动词+名词的结构,从而体现出这个函数是做什么的。比如,“userData()”会让阅读者不明白这个函数到底是获取用户的还是创建用户的,而好的命名应该是“getUserData()”,这样阅读者就会明白这个函数是用来获取用户的。
有时,我们会遇到把值写死的情况,比如当须要判断一个用户是否成年时,有些程序员会直接写成“if (user.getAge() > 18) { ... }”,这会让阅读者不明白18到底代表什么。正确的做法应该是为“18”这个值创建一个常量,并给予一个合适的名字,比如“final int ADULT_AGE_THRESHOLD = 18;”,这样阅读者就会明白程序员的意图。
命名的难点在于,没有一个客观的评价标准。甚至很多人认为它不是一个编程中的问题,因为计算机本身不管遇到多糟糕的命名,都会把代码转化为汇编语言并执行,因此命名问题归根到底都是人的问题。