2018-11-杂记

大概翻完了《代码整洁之道》,和《重构-改善既有代码的设计》一起买的。发现后面都是关于java开发的细枝末节,所以就只看完了前几章。好几本书的序言都说,如果熟悉C语言的话看java应该不难,然后BB一大堆面向对象开发,C语言有对象吗?扯淡。买这些书主要是觉得自己写的代码有点糟糕,而且也没啥好代码作为参照,不管怎么说,看完是有点进步吧,比如现在知道给变量起名的时候区分动名词,不写废话注释,不再写超级大的函数,一个函数不再接受五六个参数。😂

1、关于变量名

之前写代码的时候,变量名都随便起,我觉得emmm好像是这个单词然后拿来就用,不区分动词名词也不区分语态。所以最终写完的程序要么加注释要么只有我能看得懂,即使是我自己看,也要花很长时间在区分函数功能变量功能上面。而且由于懒,变量名字都像兔尾巴,能写字母不用单词,能一个单词解决的不用两个单词,代价是添加功能或者变更需求的时候看自己的代码就像在看屎。所以,起个有意义的不会混淆的一目了然的长的像火车一样的变量名是有必要的。

a . 有意义

用abc iIlL1 o0这样的当变量名就不说了,谁看谁知道,后面维护代码的接盘侠不给他天灵盖打烂算他头铁。除了循环里的计数器写成 i j k h 这样的单字母,其余时候都最好起一个有实际意义的名字,比如变量里存的是图片地址数组,imgUrlList很明显比 abc 更合适,有了合适的变量名后,与之相关的操作也顺带着一目了然起来,比如imgUrlList.push()很明显是要添加一个新图片地址。

b . 区分动名词

有一天中午提前去吃饭,同事的Leader给他发了一段他提交的代码,让他自己找哪里有问题。我们三个人盯着十行代码看了20分钟也没觉的哪有问题,Leader说你看你的变量名是动词还是名词。😅。。用于保存从表单获取用户输入的信息的变量写成了getUserInfoList,实际上写成userInfoList就可以了,get更像是一个动作,用来取函数名不错,但是变量在定义时通常我们期望他保存一个固定类型固定用处的值,因此函数名用动词短语更合理,变量名用名词更合理。

c . 区分时态语态

英语老师说过,动词是有时态的,不同的时态可以描述不同的时间发生的动作,同时还是有语态的,描述这个动作是被动的还是主动的。假设目前有这样一个需求:页面上有一堆图标可选,但只能选择一个,点击之后图标高亮,未被选中的图标变灰。其中一种实现思路是,每发生一次点击就记录下当前点击的图标,在下一次点击发生时把上一次点击的图标变灰,然后再把当前点击的图标设成高亮。那么就需要一个变量来保存上一次点击的图标的信息。

如果写成markIcon好像也无伤大雅,但是写成lastMarkIcon更能表现出这个变量保存的是上一次点击时的icon,进一步的,考虑到icon是被标记的,写成lastMarkedIcon更能表现出这个变量的作用,意义,内容。

d . 避免混淆

如果在一个处理接口数据的函数里,定义了tempList,tempObj,list,showList这几个变量,下一次接口变更的时候谁还能看的懂?只有再从头理一遍处理逻辑才能明白每个变量的意思。避免混淆的方法是增加语境和修饰词,虽然这样会让变量名长的像火车,但是你可以一眼看出sortedDataList和formatedTimeStemp是排序过的数据数组和格式化后的时间戳。

2、关于函数

a . 短

上上周吧。我写了一个有5个子标签4个表格和12个echarts折线图的页面,这些数据来源于三个接口。那么当ajax返回的时候就得通知这些表格和折线图绘制渲染。从接口获取的数据也没法直接在页面上用,还需要格式化,处理成数组和对象才能传给echarts。于是我的ajax回调函数写了将近200行,处理数据,生成echarts实例,通知渲染函数。最后基本无论什么改动变更都要去改这个函数,虽然我承认一气呵成写出来很爽,后面改起来更爽,毕竟我都快在函数里写注释说这块是干嘛的了。虽然最后好歹功能都正常提了预发,后面还是花时间重构了一下。

重构的第一件事,就是拆开这个大的不像话的函数,把数据处理和生成实例分离成单独的函数,ajax回调函数只负责通知处理和渲染函数。这么拆开以后,函数逻辑和处理过程都清晰了很多,更改某部分的功能只需要去修改对应的处理函数,重复代码也精简了很多。

函数应该只干一件事 – 要么通知别人做,要么自己做。如果有几段代码重复出现,就应该拎出来封装成工具函数,在合适的时机调用,返回恰当的处理结果。

b . 减少参数

也提一提我上上周写的那个怪物页面,我在js里写了接收五六个参数的函数。😂

无非是想耍耍小聪明,尽量让一个函数处理更多相似的事情。我用了一堆标识参数来标识哪个表格发起的调用,一堆布尔值来区分处理逻辑,还有一两个参数是真正需要传递的。我以为这算是函数的重载吧,实际上只是写了一大堆愚蠢的if else switch和三目运算符。函数应该简简单单的只做一件事,而不是帮我去区分含混不清的数据。真正应该区分的是传递给函数的数据,而不是在调用函数的时候传一堆区分标识符。

很多的时候,是我没考虑好数据结构和函数的关系。昨天在别人的博客上看到一句话,聪明的数据结构加愚蠢的代码比愚蠢的数据结构加聪明的代码好得多,深以为然。而且我觉得如果在构思的时候合理划分保存数据的方式方法,写出来的代码也不至于过于丑陋。

c . 函数式编程

刚开始的时候其实我也没把这个概念放在心上,但其实遵循这个思想真的能在开发的时候提供便捷减少错误。有那么几点可以在实践中做些考虑:

  • 没有副作用 函数尽量不要跟外部环境互动,比如修改全局变量。函数的所有功能就是返回一个运算得到的值。
  • 引用透明 同样的输入总会导致同样的输出,不会出现预期之外的结果

3、注释

别写没意义的注释,别写多余注释,别写啰啰嗦嗦的注释。

其实在做好前面两条的时候,注释会显得多余。清晰可读的变量名和简短可预期的函数比注释更有表现力,所以很多时候注释是对坏代码的补充而不是对代码意图的阐释。

4、小记

以上有些观念是在阿里内网上的一篇大佬分享里学到的,高级语言相对机器语言来说最显而易见的作用就是高级语言更接近自然语言,更像日常说话,写作,描述时的词法语法,所以为啥不把程序写的跟小说一样清晰明了呢。让人能够轻松读懂代码的关键在于起个好的变量名,写简短单一职责可预期的函数,此外合理安排代码放置的位置,让每一行代码承上启下,总是按着执行顺序放置。

0%