看不懂别人的代码是什么感觉?就好像走进一片森林里迷了路,这时候你是不是想把写代码的人抓过来骂一顿?下面就总结几条最让人受不了的。
1、 标志位以及全局变量太多
标志位看似用起来很方便,是为了表达一种状态,然而一旦起了就要去维护,什么时候清零?什么时候置1?什么时候初始化?当所表达的这件事情不简单,比如跟另一件事情有牵扯,标志位就不好用了,会有很多地方需要把他清零或置1,一旦有个地方忘了程序就会出错。标志位一两个还好,多了别人看的头昏,能避免就避免,实在避免不了怎么办?等一下再写,过一会就发现其实不用也可以。
全局变量(这里指的是int型或char型等基本类型的变量)跟标志位同理,太多只会引起头昏,用之前应该明确这个变量的作用范围,如果作用范围只是在一个函数里面,那么就没必要起在外面,直接在本函数起一个“static”类型的就可以了,也许有时候起的时候并没有发现这个变量可以在函数里写成static,代码写完后多看看就发现了。同理作用在本文件的那就在本文件里定义成static。
比单个文件中全局变量更可怕的是一个变量跨越几个文件使用,一不注意看花眼,心累不心累?如果一个变量确实会在几个模块里被读和写怎么办?可以在一个模块定义成static,然后通过读和写的接口函数来实现读写就好了。
在我看来全局变量这种东西能不用就不用,一般涉及相同业务的变量一起组成一个结构体在结构体里面定义,单独起一个全局的结构体就够了,而不是这里一个那里一个单独的变量散落在文件的各个地方。
比如当某件事情发生时A模块会去写某个变量,让B模块来读,此时定一个标志位以及变量,当B模块发现标志位置1了就去读变量,这种做法就不太好。AB模块完全可以通过消息队列来通信,A模块只需要把变量值通过发特定消息带给B模块就好了,这样就实现了B模块在事件发生时得到了这个变量。
2、 逻辑不够简单
逻辑复杂一方面可能是产品的功能本来就设计的复杂;一方面可能是写程序的时候思路不清晰,实现方法不够简洁,代码一团糟自己把自己作死的。如果这两方面都占了,那差不多到了要吐血的边缘了。
如果功能逻辑复杂该怎么办?代码该怎么写就应该好好规划,先想清楚别急着写。
拿我们的产品举个例子,智能家庭网关子设备绑定入网流程就比较复杂,首先手机APP在局域网内搜索子设备,网关收到搜索消息,去开启zigbee子设备入网流程,入网成功后子设备开始登陆到服务器流程,这个过程中手机持续发搜索消息,网关持续回复搜索消息告知子设备基本信息以及连网处于哪一阶段(比如与网关连接中、登陆服务器中)直到子设备登陆服务器成功,获得了登陆ID号,手机向服务器申请绑定该子设备,整个流程结束。
体现到代码上,整个过程中涉及到三个线程,局域网线程、广域网线程、zigbee线程,zigbee线程需要同时与局域网、广域网线程通信,广域网线程可能需要与局域网线程通信,这关系简直太复杂了。你无法想象原来代码靠一堆的flag和变量就把这功能做完了,你需要捋好多遍才搞清楚,那些名字相似的变量们都是些什么作用。
具体怎么做暂且不谈反正让我做是不会做成这样的,可以利用操作系统的消息队列、回调函数、信号量等等让线程间通信变得简单些,操作系统就是为了让我们更简洁地编码啊!
3、 函数设计不合理
一个 函数功能不单一,这是很容易会犯的错误,有时候某个函数被设计成完成一种功能,但随着产品功能迭代升级,发现程序执行到这有了另外一种情况这个函数处理不了了,于是不得不在原来函数里面又补上一段。这样就造成了这个函数有好几个功能:正常情况时就是原来功能,新的情况时,又是另外一种功能。从函数名看是只有前面这种功能,里面却藏着另一种功能,反正看着有些不爽,如果有时间来改一下,也许可以设计成两个函数,正常情况执行函数A,新的情况执行函数B。
功能切分不合理,到底什么功能可以包装成一个函数?会被反复用到的功能,或实现起来代码比较多放在程序里太长,细节又可以屏蔽的功能。不要几句代码就能实现的功能还要写一个函数,也不要很多不相干的东西全凑在一个函数里,函数又臭又长让人失去了耐心,然后又在某个旮旯里藏着关键性逻辑。
嵌套调用太多层,假如A函数调用B函数,B函数里面又调用C函数,C函数里面…….晕不晕?
4、 可读性差
魔鬼数字,比如数组的第5个元素减7,为什么是5?为什么是7?让人摸不着头脑,可以把5和7定义成宏,从宏的名字体现出其意义;
没有注释,这不用多说了吧,关键函数、关键逻辑都应该加上适当注释让后来者好维护;
命名风格不统一,无论是变量、函数还是文件名,都应该能望名知义并保持一样的规则,比如一个模块提供给其他模块的接口函数命名都保持”模块名_功能”这样子,忽然来了个不按这种规则命名的函数,那就比较影响阅读,处女座会受不了的;另外英文的简写尽量用常见的(比如count一般缩写成cnt),而不是冷门的让别人看不懂。