查看原文
其他

名正则言顺:聊聊“起名”这件事

熊节 程序员练功房 2019-04-20

昨天练功房里讨论的话题是:编程的时候,关于“起名”这件事,有什么想法。


LW同学分享了自己的一个小经验:

比方说有三个函数,分别用来获取三种订单信息

第一种取名方式:getFooOrder,getBarOrder,getOtherOrder 这种取名方式感觉正规一点,也符合英语语法

但是我可能更倾向于第二种取名方式:getOrderFoo,getOrderBar,getOrderOther

这样取名的原因,一个是看起来名字都整齐一点,再一个就是IDE提供的函数名列表一般是按字母排序的,这样子可以一眼看到类中具体有几种订单之类的信息。


YQ同学提到自己的一个困惑:

比如说…前端里常见的响应一个 scroll 下滑的操作函数

就取名 handleScrollDown 

就感觉好长一个😂

或者类似 handleConfirmButtonClick


Kimmy同学适时放了个嘲讽:

ExtensibleMarkupLanguageHyperTextTransferProtocol(


然后大家都觉得这个名字长度其实还行,可以用“on+事件名”的形式,还能稍微再短点。


《实现模式》里面讲了一系列关于命名的建议。比如说,对于变量的命名,Kent Beck给出的建议是“按角色命名”:

我用变量名来描述它扮演的角色。其他关于这个变量的重要信息——生命周期、作用域和类型——通常从上下文中就可以找到。
Kent Beck,《实现模式》


再取变量中的一种——局部变量——来说,它常扮演的角色有几种:


  1. 解释(Explaining):面对复杂的运算时,把运算的中间结果赋值给一个局部变量,帮助阅读者分步理解整个运算。

  2. 复用(Reuse):如果一个表达式的值会不断变化(例如“当前的时间”),或者取得这个值的成本很高(例如需要调用网络接口),而你又需要多次使用同一个值,就应该将其保存在局部变量中,以便重复使用。

  3. 收集器(Collector):用来收集稍后需要的信息。如果要将收集器作为函数返回值,就将它命名为resultresults

  4. 计数(Count):可以看作一种特殊的收集器,专门用于记录“个数”。命名时可以考虑xxxCount这样的名字。

  5. 元素(Element):在迭代遍历一个集合时,需要用局部变量指代集合中的每一个元素。这种局部变量可以直接命名为each,或者在each后面加上集合的名字,即eachXxx的形式。


这里面的前两类角色需要根据逻辑概念来命名,后三类角色命名都是有套路的。如果发现一个局部变量不是这几类角色,很可能就需要想一想,是不是正确地在使用局部变量。


我在翻译《重构》第二版的时候跟林从羽聊到一个问题:同样是写程序,业余选手很可能是想到哪儿写到哪儿,要解决什么问题的时候临时想需要什么元素;而职业选手的脑子里则有一个可以穷尽的模式列表,什么情况下使用什么程序元素对他来说不是一个启发式的(heuristic)思考过程,而是模式匹配的过程。这个过程第一很快,第二不会写出稀奇古怪的、费解的程序结构。


可能职业程序员和业余程序员的区别就在于,业余选手需要heuristic的很多场合,对于职业选手来说是可以穷举的模式匹配


(类似的例子,比如“一段代码好不好”这个问题,业余选手要看着琢磨半天,职业选手则是在脑子里迅速把24个坏味道模式匹配了一遍,给出一个答案。)


又跑题了……说回“起名”这件事。我以前同事李光磊同学写过一段测试代码,被大家夸了好长时间 ,就像这样的……(感兴趣的同学可以去搜索InfoQ的文章《TDD实践之实用主义》)

这个玩法最大的好处是,生成的测试报告看着很清晰,单元测试的报告可以直接当文档来看,真正实现了“活文档”。


然后CF同学放了个大招,不光测试方法名可以中文,测试步骤也可以中文。BDD流派说测试用例(不仅仅测试报告)就是文档,这个文档看着怎么样?



于是我终于按捺不住喜悦的心情,找出了一个十六年前的超级大招……是C++之父Bjarne Stroustrup在一篇叫做《扩展C++2000的重载规则》的文章里写的……



高不高级?厉不厉害?


嗯,这篇文章是Stroustrup发表于2001年4月1日,然后我翻译的版本发表于《程序员》2002年4月刊😼




🏋🏻 程序员🏋🏻


 

    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存