一文搞定代码中的命名

·  阅读 15

导语

Phil Karlton 曾经说过:计算机科学领域只有两件难事:缓存失效和命名。而命名又是写出整洁代码基础中的基础,本文的副标题其实是《关于命名的读书笔记》,自己在学习过程中的整理出来一点心得笔记,共勉!


为什么要做好命名?

任何一个傻瓜都能写出计算机可以理解的代码。唯有写出人类容易理解的代码,才是优秀的程序员。—— Martin Fowler

整洁的代码如同优美的散文。—— Grady Booch

程序写出来是给人看的,附带能在机器上运行。–《计算机程序的结构与解释》

读悬疑侦探类小说,透过神秘的文字推测故事情节是个挺不错的体验。但是如果是在阅读代码,这种体验会让你泪奔。


做好命名很难

起名字这件事看似不难,但是要经过深思熟虑,取出名副其实、表达性好的名字并不是一件很容易的事。

命名为什么难呢?因为命名的过程本身就是一个抽象和思考的过程,在工作中,当我们不能给一个模块、一个对象、一个函数,甚至一个变量找到合适的名称的时候,往往说明我们对问题的理解还不够透彻,需要重新去挖掘问题的本质,对问题域进行重新分析和抽象,有时还要调整设计和重构代码。因此,好的命名是我们写出好代码的基础。

就像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.)“

此外,Martin Fowler也表示过,他最喜欢的一句谚语,就是我们的导语中提到的那句话:“在计算机科学中有两件难事:缓存失效和命名。(There are only two hard things in Computer Science:cache invalidation and naming things.)”


变量命名

1)好的命名的注意事项

1.1)命名要名副其实

这是为变量命名时最重要的考虑选项。名字要完全、准确的描述出该变量代表的事物。

最简单的方法是用文字描述变量所表达的含义,对变量的描述就是最好的变量名。这种名字很容易阅读,因为它不包含容易晦涩的缩写,同时也没有歧义。因为他对代表的事物做了完整描述,因此不容易混淆。

如描述运动场中座椅数数量,number_of_sets_in_the_stadium

备注: 本文命名都以python的命名方式书写,其他语言的根据语言命名格式转换即可。

如果有一种变量你没法描述,那么说明你可能要重新思考业务,思考逻辑。

1.2)以问题为导向

好记的名字往往反映的通常都是问题,而不是解决方案。好的名字通常表达 what ,而不是 how ,如果名字反映了计算的某些方面而不是问题本身,那么它反映的就是 how 而不是 what

举例子说明一个员工的数据记录,input_rec 或者 employee_datainput_rec 反映的就是输入记录这些计算机学术用语。employee_data 则直指问题。那么 employee_data 就是个好名字。

1.3)最佳的命名长度

变量名的最佳长度似乎应该介于 nnumber_of_sets_in_the_stadium 之间。太短的名字无法传达足够的信息。太长的名字很难写,同时还会使程序视觉结构变得模糊不清。

国外的大佬 Gorla、Benander 研究发现,当变量名平均在 10 到 16 个字符的时候,调试程序所花费的时间最小,平均名字长度在 8 到 20 个字符的时候也很适合调试。这项原则并不是要求你一定要把变量控制在 8 到 16 的长度。它强调的是如果你查看自己写的代码时发现很多更短的名字,你需要好好斟酌,确保这些名字是否足够清晰表达其含义。

太长: number_of_sets_in_the_stadium

太短: n,nsisd

正好: num_sets_in_stadium
复制代码
1.4)变量名中的限定词

很多程序都有表示计算结果的变量:总额、平均值、最大值等等,如果要用类似total、sum、average、max、min、record、string、pointer这样的限定词来修饰某个事物,请把限定词放到名字的最后。

因为变量名中最重要的,即为这一变量赋予主要含义的部分应当位于最前面,这样这一部分就可以显得最为突出,又可以首先被阅读到。另外将限定词统一放在后面可以提高可读性,简化维护工作。

2)为特定类型的数据命名

2.1)为循环下标命名

循环我们基本上天天用,小到写个 shell 脚本,大到登月工程,在软件工程中很常见。

既然经常那么 i、j、k 这些想来你也不陌生。如果一个变量要在循环之外用,那么就应该为它取一个比i、j 或者 k 更有意义的名字。

如果循环不是简单几行,阅读代码的人很容易就忘记本来的含义。

fruits = ['banana','apple''mango']
for fruit in fruits:
   print(f"当前水果:{fruit}")
复制代码

为循环下标变量命名可以避免下标串话,就是想写j的时候写了i,笔者本人之前写循环的时候就串话了,导致那个bug上了调试才定位找出来。

当然i、j、k这三个循环下标从c语言开始就伴随着我们,深入人心,所以想要用的时候尽量避免用于非下标情况,给人造成误解(想个更具有描述性的名字这事不就解决了)。

2.2)为状态变量命名

状态变量主要为了描述你的程序的状态。

建议把标记也看作状态变量的一种,起一个比 flag 、status 更好的名字,标记的名字不应该包含 flag ,因为你看不出该标记是做什么的。为了清楚起见我们还应该用枚举类型、具名常量或者用作居民常量的全局变量来进行赋值。

2.3)为临时变量命名

临时变量用于存储计算的中间结果。

我们经常把它们写成temp、x或者其他一些模糊且缺乏描述性的名字(有没有躺枪…)。

临时变量是一个信号,表明你还没有完全把问题理解清楚。而且,因为我们将这些变量“正式”的赋予了一种“临时”状态,我们就会往往更加随意的对待它,当你忽略它,那么就有出错的可能了。

临时性的保留一些值常常是有必要的,但是确实不管从哪个角度看,你程序中的大多数变量都是临时的,把其中个别的称为临时性,说明你还没有弄清楚它们的实际用途。

2.4)为布尔变量命名
  • 推荐一些经典的布尔变量名

    • done: 用来表示某件事已经完成。完成前 False ,完成后为 True 。 error: 用来表示有错误发生。错误发生前 False ,发生时设置为 True 。 found: 用来表示某个值已经找到。没找到前 False ,找到后为 True 。 success 或者 ok: 用来表示某项操作是否成功。操作失败 False ,操作成功为 True 。
  • 给布尔变量赋予隐含“真假”含义的名字

    • donefound就是不错的布尔变量名,因为其状态要么是 True ,要么是 False ,但是像 status 确实很糟糕的布尔变量值,因为它没有明确的TrueFalsestatusTrue表示啥?
    • 还有程序员喜欢在他们写的布尔变量名前加上is(有没有躺枪-_-|)。加上了is后,变量名就变成了is_error?is_complete?优点之一就是不会用于不隐含“真假含义”的名字了,如is_status,缺点就是降低可读性,比如if(is_found)可读性略差于if(found)
  • 使用肯定的布尔变量名

    • 比如not_found,not_done这样看起来就比较难读了,来个语句你感受一下。 if not not_found 玩门萨测试呢?这样的名字就应该替换为 found 之类的。
2.5)为具名常量命名

因为具名常量很像变量,所以放在这里说一下。在为具名变量命名的时候,应该依据常量代表的含义命名,而不是该常量所代表的数值。

3)应该避免的名字

避免使用令人误解的名字或者缩写

要确保名字的含义是正确的,大家知道 ATM 机是取钱的,但是网络中有 Asynchronous Transfer Mode(ATM)异步传输模式,这种容易引起误解的尽量避免。

3.1)避免使用具有相似含义的名字

如果两个变量的名字交换而不影响你对程序的理解,那么你就需要为这两个变量重新改名字了,因为如果用在同一段代码里面很容易混淆,出现一下子不好发现的错误。

避免使用具有不同含义但却有相似名字的变量

如果含义不同却名字相似的也要避免,比如client_recsclient_reps。这样的名字只差一个字母,再加上编辑器补全时候很容易忽视,导致出现错误。

3.2)避免使用发音相近的名字

使用发音相近的词作为变量,主要有两个不合适点:

  • 第一个就是跟人讨论时候,容易误解。
  • 第二做语音类测试时候。
3.3)避免在名字中使用数字

如果名字中的数字真的很重要,建议使用数组代替一组单个的变量。如果数组不合适,那么数字就更不合适了。要避免 file1file2total1total2 这种变量,过一段时间谁也不知道它们是啥,你总可以想出不加数字就能区分变量的名字吧。特殊情况要特殊对待,比如深圳去上海的 G205 国道,美国的51 区,建议再创建一个含有数字名字之前,请确定没有更好的选项。

3.4)避免在名字中拼错单词

本来别人看你代码就要花点脑细胞,结果你拼错了。 content 和 context highlite 和 hilite 大哥们,饶了看你代码的人吧。

3.5)避免仅靠大小写来区分变量名

所以语言区分大小写,但还是避免仅靠大小写区分变量,大写名字和小写名字字面意思一样,还是不要做不同的变量了吧。

3.6)避免使用标准类型,变量和函数的名字

不要用语言的关键字。很多语言现在不能写关键字,但是大小写不区分,比如python代码:

>>> if = 1
  File "", line 1
    if = 1
       ^
SyntaxError: invalid syntax
>>> If = 1
>>>
复制代码

本文提供了这么多变量名的方法就不要用关键字这种了。

3.7)避免使用与变量含义完全无关的名字

image.png

就问你怕不怕?还有的喜欢给变量起一些对自己特殊意义的名字作为变量名,除非程序真的跟你特殊意义有关。这些能避免避免吧。

3.8)避免在名字中包含容易混淆的字符

把下列不属于该组的名字圈出来:

eye_Chart1 ttl5 TTLCONFUSION

eye_ChartI ttlS TTLCONFUSION

eye_Chart1 tt1S TTLC0NFUSION

还是不要搞这些找不同游戏才能出现的变量哈。


函数命名

1. 描述函数所做的所有事情

函数的命名应该是动词或者动词短语,如delete_pagesave等。

函数的名字应该描述其所有的输出结果以及副作用,比如你的函数是计算报表总额并打开一个输出文件,那么把它命名为 computer_report_totals() 不能算完整。完整的应该是 computer_report_totals_and_open_output_file()

如果写一些带有副作用的子程序,那么就会起出上面那种长出天际的名字,解决这个问题的办法不是使用描述性较弱的 computer_report_totals() 命名方式,而是换一种编写方式,直接了当地写成解决问题,不产生副作用。

2. 给函数命名时要对返回值有所描述

函数有返回值,因此,函数的命名要应该针对其返回值进行。比如说 xxx_is_ready 这样的,一看就让人知道是返回的布尔值。

3. 准确使用对仗词

命名时遵守对仗词的命名规则有助于保持一致性,从而提高可读性。像 first/last,这样的对仗词就很容易理解,而像 file_open()l_close() 就很让人迷惑了,下面列出一些常见的对仗词组。

add/remove
increment/decrement
open/close
begin/end
insert/delete
show/hide
create/destroy
lock/unlock
source/target
first/last
min/max
start/stop
get/put
next/previous
up/down
get/set
old/new
复制代码
4. 函数名字长度

研究表明,变量名的最佳长度是9到15个字符,在面向对象的语言中,函数是跟在对象的名字之后,这实际上是为其提供了一部分的名字。重点的尽可能的含义清晰,长短要视名字是否清晰而定。

5. 为常用操作确立命名规则

在某些系统里,区分不同类别非常重要,而命名规则往往能是指示这种区别的最简单也是最可靠的办法。忽视了为返回对象标识的类函数建立一个命名规则,看看下面的名字

  • employee.id.get()
  • dependent.get_id()
  • candidate.get_id()
6. 类命名

类的命名应该是名词或者名词短语,如 Customer 或者 AddressParser


命名工具推荐

Codelf 由前网易前端工程师知名移动前端调试工具 MIHTool 的作者基于searchcode 和有道词典开发完成。目前开源在 Github上。

Codelf:unbug.github.io/codelf/

Codelf 的 github repo:github.com/unbug/codel…

文学系的可以搜搜热词:盘它

image.png

我太南了

image.png


总结

白居易每作一首诗,都要给不识字的老太太念念,老太太能听懂的,就要,听不大懂的,就改。我们的代码命名是我们写成好代码的基础,也应该奔着这个目标走。大家看文章过程中觉得有不妥的或者不合适的地方,欢迎讨论交流哈。


参考书籍

《代码大全2》:book.douban.com/subject/147…

《代码整洁之道》:book.douban.com/subject/419…

《重构》:book.douban.com/subject/304…

转自:于颜川KM分享

更多后台和前端开发规范

蓝鲸文档中心开发指南:bk.tencent.com/docs/docume…

Python代码规范小结:bk.tencent.com/s-mart/comm…


蓝鲸智云

本文由腾讯蓝鲸智云编辑发布,腾讯蓝鲸智云(简称蓝鲸)软件体系是一套基于PaaS的技术解决方案,致力于打造行业领先的一站式自动化运维平台。目前已经推出社区版、企业版,欢迎体验。

分类:
前端
标签:
收藏成功!
已添加到「」, 点击更改