There are only two hard things in computer science: cache invalidation and naming things.
计算机科学中只有两件难事:缓存失效和命名。
——(Phil Karlton)菲尔·卡尔顿
菲尔·卡尔顿 (Phil Karlton) 是一个著名的计算机科学家,他曾在 Netscape 平台工作。
最近在读张建飞老师的《程序员的底层思维》(值得一读,推荐),重点强调了程序员的抽象思维,让我想起了 Phil Karlton 的这句话。今天就来聊聊命名。
命名重要且难
正如Stack Overflow的创始人Joel Spolsky所说:
“Creating good names is hard,but it should be hard,because a great name captures essential meaning in just one or two words.”(起一个好名字应该很难,因为,一个好名字需要把要义浓缩在一到两个词中。)
命名为什么难呢?因为命名的过程本身就是一个抽象和思考的过程,在工作中,当我们不能给一个模块、一个对象、一个函数,甚至一个变量找到合适的名称的时候,往往说明我们对问题的理解还不够透彻,需要重新去挖掘问题的本质,对问题域进行重新分析和抽象,有时还要调整设计和重构代码。因此,好的命名是我们写出好代码的基础。
因此,要想真正做好命名,除了要掌握一些命名技法,还需要更深层次的修炼——提升抽象思维能力。
以下总结命名错误的几个层次、原因及规避方法。
拼音命名
许多新手喜欢用拼音来命名,比如shujuku
、nihaoshijie
、ccgc
,我不说中文(数据库、你好世界、存储过程),你肯定是看不懂的。这种方式弊端很多,比如:
- 拼音是有语调的,同音词太多,没办法做到唯一性,也就无法保证命名的准确性;
- 中文词语很简洁,但拼音往往很长,不分词根本没法读,如果加下划线分词,那就更长了;
- 中文不区分动词和名词,容易造成功能性的命名,如submit和submission,中文都是tijiao;
- 中文拼音不好区别单数和复数;
- 中文也不好区分主动和被动,比如
选择元素
和选中的元素
,正常英语是SelectItems
和SelectedItems
,而拼音可能会写能一样的xuanzhe_yuansu
或xuanzhe_de_yuansu
,同样,没办法表示单复数形式;
Donald Knuth 曾经说过:“Programs are meant to be ready by humans and only icidentally for computers to execute.” 代码是用来让人读的,只是顺便让机器执行而已。(原话或许是 Hal Abelson 说的)
种种原因,拼音命名是无法保证代码是可读的,也就是说,你写的代码,别人看不懂,你自己过一段时间也看不懂。所以,千万不要用拼音命名。更不要拼音和英文混用,这样更让人头大。
杀死一个程序员不用枪,只要让他维护一个拼音命名的代码库就行了。
拼写错误
拼写错误是最低级的错误。我刚参加工作时,偶尔会犯这种错误,比如:database
会写成 datebase
。当然,现在这种错误很容易被 IDE 或者编译器检查出来,所以,只要你不是故意的,这种错误很难出现在正式发布的代码中。
anyway,编程就是要细心一点,如果你经常犯这种错误,那就要考虑找人结对编程,或者转行。
词不达意
虽然英语是世界通用语言,但是,毕竟不是我们的母语,有时候,我们会用错词,比如:completed
和 finished
都有完成的意思,且都有动词词性。但在语义侧重稍有差别。
-
complete
: 在表示动词“完成”之义时,侧重于表达完成得比较圆满。另外,complete还有形容词词性,表示“完成的,完整的”。 -
finish
: 在表示“完成之义时,侧重于表示”结束了,做完了”,并没有什么好坏之分。
举个例子你就明白~
-
如果你嫁对了人, then you are complete。
-
如果你嫁错了人, then you are finished。
-
如果你嫁错了人还生了个倒霉孩子, then you are completely finished。
英文还有一个缺陷,就是词汇量太大。专有名词太多,同一种类型不同的命名。如汽车、火车、出租车、公交车、卡车、救护车、消防车分别叫做 Car,train,taxi,bus,truck,ambulance。
词汇量大,自然会造成记忆负担。解决办法就是多看英文资料,多学多写。
代码风格不统一
代码风格不统一,也是一种命名错误。比如,有的人喜欢用驼峰命名法,有的人喜欢用下划线命名法,有的人喜欢用帕斯卡命名法。当然这不是什么大问题,只要团队内部统一就行了。也有很多工具可以帮助我们做到风格统一,比如:EditorConfig。
有时候风格不统一来自编程范式的不同,比如:面向对象编程和函数式编程。面向对象编程中,我们喜欢用名词来命名,比如:Student
、Teacher
、Class
,而函数式编程中,我们喜欢用动词来命名,比如:add
、remove
、update
。这种情况下,建议团队内部统一编程范式,这样,代码风格也就统一了。
命名过长
命名过长也是一种错误。限定词越多,意思不是越明确吗?其实不然,命名过长,反而会让人看不懂。
比如,有的人喜欢把变量命名成:theNumberOfStudentsInClass
,这样的命名太长。事实上叫studentsCount
就可以了。
解决办法是要找到核心词。比如,studentsCount
,核心词是count
,theNumberOfStudentsInClass
,核心词是students
。核心词越多,越难理解。
依赖注释
有些人函数命名很随意,然后用注释来解释函数的作用。这种做法就好像正经工作时间不好好努力,下班后加班加点的干,是极不可取的。因为,代码应该是自解释的,添加注释往往还会增加额外负担。如果你的代码需要注释,那么,你的代码就不够清晰,需要重构。
大部分注释都是无用的,当然,有些业务逻辑复杂的地方,还是需要注释的,但是,注释应该是最后的手段,而不是第一选择。
随意命名
现实情况是,很多工程师常常忽略了命名的重要性,只要能实现业务功能,名字从来就不是重点。实际上,这既是对系统的不负责任,也是对自己的不负责任,更是对后期维护系统的人不负责任。写程序和写文章有极强的相似性,本质上都是用语言阐述一件事情。试想,如果文章中用的都是一些词不达意的句子,这样的文章谁能看得懂,谁又愿意去看呢?
每一次的变量命名、方法命名、类命名都是难得的训练抽象思维的机会。不要浪费这个机会,要认真对待每一个命名,要尽可能的做到准确、简洁、易读。
总结
命名是一门学问。总体三个经验:
- 学好英语
- 多做练习
- 多看优秀代码
现在人工智能工具可以帮写代码,能够大块大块的生成各种业务逻辑的代码。而代码都是基于变量名生成的,所以,写好变量名,就能生成高质量的代码。
所以,命名是程序员的基本功。即便是 AI 时代,抽象思维能力都是程序员的核心竞争力之一。