俗话说,隔行如隔山,异步君的朋友曾天真地问我桌面上花花绿绿的“字母”是什么?当我告诉她,没有这些“字母”,就没有她每天看的微博热搜和小哥哥美照。
她:“???”
把代码理解为“字母”是外行闹笑话,那同行是不是就能理解彼此?其实不然,对程序员来说,最痛苦的事情不是修BUG,看其他人写的代码更痛苦。
特别是看没注释的代码,恨不得给同事一招乾坤大挪移,把他写代码时的脑子,移给自己。
“没注释的代码就像小孩没娘,说来话长”,在写代码时不规范命名,就好比设计师图一时爽,新建了一大堆未命名-1.psd,未命名-2.psd……辛苦制图大半天,交稿之时两瞪眼。
编程也是一样,代码注释做的好,可以大幅提升后期的编程效率,但一些小白程序员做的奇葩命名惹得大伙儿叫苦不迭——
实习生搞APP开发搞的满身大汗,问咋了?他说我明明写了main方法,为什么运行不了?一看代码,惊了!main写成了mian,更无语的是:苹果手机命名是apple_sj,Android手机是android_sj……也不算太差,我见过命名是pingguo sj,anzhuo sj……
前端有一段代码是20多个按钮,根据不同的状态,展示不同的按钮组合……然后每个按钮是一个变量表示其显示还是隐藏,然后就看到了show1,show2,show3……show22,你以为这是全部嘛?错,其中一个show17竟然叫做shoe17……我……
曾接触某个政府网站代码,一溜的变量从a1递增到a4,然后定义一个数组叫a5,第一个变量叫a6,第二个变量叫a7,数组长度叫a8,然后又定义其他的变量叫a9……其实,这样的变量名有可能是后期替换的,增加阅读难度。
每一个程序员都应该掌握一套命名的方法论,合理正确有条理的规划这些编程内容,异步君特地推荐——《代码精进之路》!
一、命名的力量
在程序员的工作中,大部分的时间都在阅读和理解代码,好的命名能够让代码的概念清晰,增加代码的表达力;词不达意的命名会破坏我们思考的连贯性,分散有限的注意力。
命名其重要性往往被低估。而所谓的工匠精神,往往就是体现在细节之处,就日本的“煮饭仙人”50年专注于做好1碗米饭。一个名字虽然并不影响程序的执行,但是却对代码的表达力和可读性有着重要的影响。
名为万物之始,万物始于无名,道生一,一生二,二生三,三生万物。
——《易经》
人名、企业名...命名有着巨大的力量。
在阿里巴巴初创的时期,马云想做一个国际化的电子商务网站,要起一个全球化的名字。有一天,他在旧金山的街上发现阿里巴巴这个名字蛮有意思的,正在思考时,一名服务员送咖啡过来。马云问他:“你知道阿里巴巴吗?”他说:“当然知道了,就是open seasame(芝麻开门)”。
然后马云在街上找了来自不同国家的数十个人,问他们知道阿里巴巴吗?他们大多能讲到芝麻开门。在英文单词里,“a”排名又在第一位。而且大多数人一听(看)到阿里巴巴这个名字,都会感到奇怪,这样足以给人留下深刻的印象。
在Java企业级应用开发的历史上,也有一段和命名有关的有趣历史。在2000年左右,EJB(Enterprise Java Bean)大行其道,这让Martin Fowler、Rebecca Parsons和Josh MacKenzie等人感到很困惑。
后来他们发现人们之所以不愿意在他们的系统中使用普通的Java对象,是因为其缺少一个酷炫的名字,因此他们在一次会议上给普通的Java对象起了个名字——POJO(Plain Old Java Object)。
当时的EJB在开发和部署上给开发者带来了沉重的负担,POJO概念的提出很快得到了开发者的拥护。Spring等一系列轻量级框架的诞生,很快终结了EJB的统治地位,因此在一定程度上,POJO这个名字加速了EJB的消亡。
二、命名其实很难
命名的过程是一个抽象和思考的过程。
在工作中,当我们不能给一个模块、一个对象、一个函数,甚至一个变量找到合适的名称的时候,往往说明我们对问题的理解还不够透彻,需要重新去挖掘问题的本质,对问题域进行重新分析和抽象,有时还要调整设计和重构代码。因此,好的命名是我们写出好代码的基础。
就像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. int elapsedTimeInDays;
观察上面的命名,我们只能从注释中知道变量d指的是什么。如果没有注释,阅读代码的人为了知道d的含义,就不得不去寻找它的实例以获取线索。如果我们能够按照下面这样的方式命名这个变量,阅读代码的人就能够很容易地知道这个变量的含义。
1. int elapsedTimeInDays;
类似的还有魔术数,数字86400应该用常量SECONDS_PER_DAY来表达;每页显示10行记录的,10应该用PAGE_SIZE来表达。
这样做还有一个好处,即代码的可搜索性,在代码中查找PAGE_SIZE很容易,但是想找到10就很麻烦了,它可能是某些注释或者常量定义的一部分,出现在不同作用的各种表达式中。
2.函数名
函数命名要具体,空泛的命名没有意义。
例如,processData()就不是一个好的命名,因为所有的方法都是对数据的处理,这样的命名并没有表明要做的事情,相比之下,validateUserCredentials()或者eliminateDuplicateRequests()就要好许多。
函数的命名要体现做什么,而不是怎么做。假如我们将雇员信息存储在一个栈中,现在要从栈中获取最近存储的一个雇员信息,那么getLatestEmployee()就比popRecord()要好。
因为栈数据结构是底层实现细节,命名应该提升抽象层次、体现业务语义。合理的命名可以使你省掉记住“出栈”的脑力步骤,你只需要简单地说“取最近雇员的信息”。
3.类名
类是面向对象中最重要的概念之一,是一组数据和操作的封装。对于一个应用系统,我们可以将类分为两大类:实体类和辅助类。
实体类承载了核心业务数据和核心业务逻辑,其命名要充分体现业务语义,并在团队内达成共识,如Customer、Bank和Employee等。
辅助类是辅佐实体类一起完成业务逻辑的,其命名要能够通过后缀来体现功能。例如,用来为Customer做控制路由的控制类CustomerController、提供Customer服务的服务类CustomerService、获取数据存储的仓储类CustomerRepository。
对于辅助类,尽量不要用Helper、Util之类的后缀,因为其含义太过笼统,容易破坏SRP(单一职责原则)。比如对于处理CSV,可以这样写:
1. CSVHelper.parse(String)
2. CSVHelper.create(int[])
但是我更建议将CSVHelper拆开:
1. CSVParser.parse(String)
2. CSVBuilder.create(int[])
4.包名
包(Package)代表了一组有关系的类的集合,起到分类组合和命名空间的作用。在JavaScript的早期阶段,因为缺乏明确的分包机制,导致程序(特别是大型程序)很容易陷入混乱。
包名应该能够反映一组类在更高抽象层次上的联系。例如,有一组类Apple、Pear、Orange,我们可以将它们放在一个包中,命名为fruit。
包的命名要适中,不可太抽象,不能太具体。
此处以上面提到的水果作为例子,如果包名过于具体,比如Apple,那么Pear和Orange放进该包中就不恰当了;如果报名太抽象,称为Object,而Object无所不包,这就失去了包用来限定范围的作用。
5.模块名
模块(Module)主要是指Maven中的Module,相对于包,模块的粒度更大,通常一个模块中包含了多个包。
在Maven中,模块名就是一个坐标: <groupId, artifactId>。一方面,其名称保证了模块在Maven仓库中的唯一性;另一方面,名称要反映模块在系统中的职责。
例如,在COLA架构中,模块代表着架构层次,因此,对任何应该遵循COLA规范的应用都有着xxx-controller、xxx-app、xxx-domain和xxx-Infrastructure这4个标准模块。
四、命名工具
当你不知道如何优雅地给变量命名时,可以使用命名工具,快速搜索大型项目中的变量命名,看其他大型项目源码是如何命名的,哪些变量名的使用频率高。特别是对于英语非母语的我们,命名工具会非常有用。
我们可以在IDE中安装一个搜索插件,便于搜索海量的互联网上的开源代码。举例说明,作者一般会安装一个叫作OnlineSearch的插件,插件里自带了像SearchCode这样的代码搜索工具,也可以自己配置像Codelf这样的代码搜索工具。
OnlineSearch插件
《代码精进之路 从码农到工匠》
_
张建飞 著
代码精进教程,程序员代码整洁之道;
追求卓越和工匠精神,提高程序员的自我修养;
阿里巴巴集团高级技术专家多年经验积淀之作,众多业内大咖联合推荐,写代码不仅是技术,更是一门技艺!
1. 全面讲解编程技艺与方法,帮助读者培养编程习惯;
2. 培养技术人员的思想素养,分享多年技术管理心得;
3. 深度揭秘阿里巴巴团队在复杂度治理方面的探索实践;
4. 重点介绍,开源框架COLA架构及其企业级应用——“工匠平台”
每一个程序员都应该掌握一套命名的方法论:了解如何给软件制品(Artifact,包括Module、Package、Class、Function和Variable)命名。
如何写注释,如何让代码自明地表达自己,以及如何保持命名风格的一致性,异步君保证,这样做,不仅能使你走上代码精进之路,更能助你走上职场进阶之路!
如何获得:关注异步图书微信公众号,在同名文章中点击在看 参与话题留言 转发本文至朋友圈,2月20日,异步君将抽取2名读者赠送《代码精进之路 从码农到工匠》。
今日互动话题:
“分享你遇到过什么样的奇葩命名”
Copyright © 2024 妖气游戏网 www.17u1u.com All Rights Reserved