读《编程匠艺—编写卓越的代码》:命名
2014-12-29 本文已影响321人
思学
刘易斯.卡莱尔(Lewis Carroll):
“当我选用一个词语时,”矮胖的人以傲慢的语调说道,“它表达的就是我要它表达的意思——不多也不少。”
一、为什么我们应该恰当地命名
名字表明了事物的身份,暗示了行为,更易让人记住并识别。
恰当地命名意味着了解名称就可以了解对象。
二、我们对什么进行命名
编写代码时,最常命名对象:
- 变量
- 函数
- 类型(class, enum, struct和typedef等)
- C++命名空间和Java包
- 宏
- 源文件
另外还包括: 状态机的状态、消息传送协议的各个部分、数据库的元素、应用程序的可执行文件等。
三、好的名称具有那些特性
-
描述性的
尽量做到能望文生义。 -
技术上正确的
只使用字母、数字(不能作开头)、特定字符(下划线);不使用空白(空格、制表符、换行符等);C/C++中不使用str开头带一个小写字母或以下划线开头的全局标识符,以及带命名空间std的标识符; -
符合语言习惯
了解语言的习惯与约定,如标准库使用一种约定,而Windows Win 32 API使用另一种约定。 -
恰当
根据使用范围,权衡名称长度;注意格调,避免使用blah或wibble等不严肃与foo或bar等古怪的名字。
四、命名细节
-
命令变量
(a).与现实世界对象相对应的变量,通常使用名词,如GUI应用程序中变量可以用ok_button和main_window;甚至一些概念类的变量,也被赋予名词形式,如elapsed_time或exchange_rate;
(b). 如果不是名词,变量通常使用名词化的动词,例如count;对于逻辑变量的名称,通常使用一个条件语句形式的名称,例如is_positive, 这样容易判断其值是true还是false。
(c).为了说明变量是成员变量而不是局部变量或全局变量,常常使用:(1)以下画线作为前缀;(2)以下画线作后缀;(3)以m_作为前缀 三种匈牙利命名法,其中(1)有风险,受到反对;(1)(2)形式不自然。
(d).一些程序员使用类似_ptr的后缀来修饰指针类型;使用类似_ref的后缀修饰引用类型,这种命名有些多余。
(e).小范围内,可使用首字母缩略词作变量名。
(f).将类型名与变量名区分开来,变量以小写字母开头,类型以大写字母开头。 -
命名函数
(a). 函数是一种行为,名字在逻辑上更应该是动词。
(b).有意义的函数名应当避免使用be、do和perform等只带无用信息的词语。
(c).始终从使用者的角度为函数命名。如果用户只看到一个函数计算苹果的个数,就不要管函数内部是如何具体实现的,命名这个函数为countApples()吧。 -
命名类型
在C语言中typedef命名、定义结构体时,在Java、C++和其他面向对象语言中创建新类型时,需要定义一个好的类型名。
(a).描述具有状态的数据对象的类,使用名词命名,如Bird;
(b).仿函数类,使用动词命名;
(c).接口类,按接口功能命名;
(d).类型命名中,避免使用class、data、object、type等词。 -
命名名字空间
C++和C#语言中的命名空间和Java语言的包,主要用于对构造分组,还用于防止名称的冲突。
(a).遵照语言的命名约定,如Java语言定义了一种像互联网域名一样嵌套的包名称的层次结构;
(b).为命名空间选择名称时,选择反映其内容的逻辑关系的词语。如果内容是某个大型系统的一部分,选择描述这个部分的名称,如操作系统中的UI、filesystem或controls都是很好的名称;
(c).不要采用暗示命名对象是一个集合的名称——controls_group就是一个不好的名字。 -
命名宏
(a).遵循传统,宏的名称使用全大写字母,并且其他任何地方不再使用全大写方式;
(b).宏是简单的文本替换工具,应该赋予在其他地方不再出现的独特名字
(c).使用唯一的文件名或项目名作为宏名称前缀是非常有用的,而且 PROJECTNAME_MY_MACRO比MY_MACRO更安全。 -
命名文件
一些语言对文件名要求严格——Java语言的源文件明必须与其包含的公共类型名相对应;另一方方面,C/C++对文件名无任何限制,但实际上源文件名对编码难度是有实际影响的。
(a).为了使文件更易命名,每个文件应该只包含单个概念单元,将代码分到尽可能多的文件,同时还能减少文件间耦合和使项目结构更清晰。
(b).为窗口定义界面的C/C++文件应该命名为widget.h,而不是
widget_interface.h、widget_decls.h或其他类似的变体。按照惯例,使用匹配文件widget.c或widget.cpp来平衡widget.h吧。
(c).由于有些系统对大小写敏感有些却无法区分,为了避免出错和考虑代码移植性,采用不同文件名时应当不以大小写不同作为区分,如果可以的话,文件名都使用小写字母吧。
(d).项目采用混合语言编程,不要同时创建foo.c、foo.cpp、foo.java,这样很混乱。
(e).为了避免文件同名,向文件名中添加一些路径信息是一种有效手段。
五、命名的主要规则
要起一个好名字,做到如下几点:
- 保持前后一致
请选择一种命名约定,并坚持使用
使用一致的命名约定,会易于开发、拓展和维护
-
利用上下文
(a).明白命名对象所处范围,尽量把对象放在最小范围中,选择一个在该范围内对上下文有意义的名字;
(b).每个对象都有类型,但命名时不要再声明类型信息。 -
使用对你有利的名字
(a).通过使用公共的前缀,可按相似的名称对对象分组;
(b).通过函数名称中包含函数参数类型信息,暗示输入参数或输出参数。
六、总结
《诗篇》(psalms):
我将寄希望于你的名,这名本为美好
好的名称不仅仅是审美上的需要,还传达了关于代码结构信息,还是不可或缺的协助理解和维护的工具。
七、建议
不要创建如下特征的名称:
-
含义模糊
首字母缩略词和简写太随意,单个字母太神秘 -
啰嗦
不要创建the_number_of_apples_before_I_started_eating这样的变量名 -
不准确或使人误解
一个对象与列表无关,就不要起widget_list之类的名
不要拼写错误,如把ignoramus写成ignoramous -
有歧义
不要使用有多种解释的名称 -
太做作
有趣的小缩写、自作聪明的简写和对数字的解释性使用都应该避免。
对于经验少的人,internationalization的常见缩写i18n是不够清晰的。
八、内容相关
匈牙利命名法
由于它的创始人程序员Charles Simonyi是匈牙利人和变量名看起来像是匈牙利语书写,被称为匈牙利命名法。最初从Microsoft公司传出,后被发展成多种匈牙利命名法;现在是一种很受争议的命名法,因为它的基本原则是:变量名=属性+类型+对象描述,而在名称中添加类型是一种冗余。
大写字母约定
- 20世纪70年代早期在Smalktalk第一次使用的camelCase型,现在广泛使用于Java语言库(一般用于类成员名)和许多C++代码库;
- .NET、Windows API以及Java类名使用的ProperCase(PascalCase)型
- C++标准库和GNU Foundation中使用的using_underscores型。
文件后缀
选择后缀也是文件命名的一部分。Java的编译系统要求文件名以.java作为结尾;但C/C++对后缀无要求。但我们应当使用普遍的约定,如C++实现文件采用.C、.cc、.cpp、.cxx和.c++常见后缀;头文件使用.h或.hpp后缀。