编码规范经验谈

     
接手Chat 3.0的项目接近两个Q,在阅读了这些代码的基础上开了一些新功能。对我们项目组的核心工程的代码有些批判的想法,现在拿来跟大家分享一下。它山之石可以攻玉,相信对大家有一定的借鉴意义。
计算机巨匠 Donald Kunth(《计算机程序设计的艺术》系列作者)有一句名言:程序是写给人看的,只是偶尔让机器执行一下。言辞颇为偏激,但是至少强调了一点,代码的可读性是十分重要的。一个大型的项目,一般会有10-20次的产品迭代,就我们IM这个可以做到死的项目而言,恐怕远远不止这么点次数。迭代也就意味着,要阅读其他同事的代码(包括离职同事)。我们在现有的系统上开发一个新的功能时,通常会花40%—60%的精力去阅读相关的代码。经常听到同事抱怨,“这代码怎么写的这样?",”被以前的代码坑了“。现有代码的质量,严重的影响了开发新功能的时间成本和质量。
下面是我总结的我们项目组编码实践上的一些常见的问题。
 
1.变量名不规范,不知所云。变量命名的首要规则就是”见名识义“,最好的注释就是代码本身。命名恰当,还需要注释吗?
TCP协议里有这么个协议:send_web_msg_autoreply ,初看是发给web端的自动回复,实际上是给所有的客户端的自动回复。SDK里有这个一个缓存的key名:EVALUATE_KEY,初看是跟评价相关的key,其实保存的是会话的sid。这样的命名是极具误导性,令人费解,更容易导致bug。
 
2.字面值问题。字面值,也称之为”魔数“(magic number)。记得上《数据结构》课程时,老师检查了我们的代码后,跟我们说,所有字面值统统拿出来放到代码的最前面定义成常量。当时不明白老师的意思,但随着经验的积累,终于明白了老师的意思。字面值定义成常量,至少有两个好处。(1),增加可读性,(2),避免”霰弹“式修改。第一个不必多说。假设一个字面值在代码里出现10次,有一天随着需求的变更,需要修改,那么也就要修改10个地方。你能保证这10个地方都改到吗?如果没有改完,那么bug也就产生了。
分流逻辑里有这么三行代码:
map.put("shunt_result",Boolean.TRUE.toString());
map.put("shunt_type",Integer.toString(destParam));
map.put("shunt_param", venderId.toString());
shunt_result等三个字面值光在shunt函数里,就出现了5次之多,所在类里竟然有7次!一旦需要改字面值,改的完吗?
 
3.过度膨胀的类。设计模式六大原则里有个单一职责原则,强调一个类只负责一件事,属于猫的类就不要去添加属于耗子的功能代码。但是前台的类,ChatCore**ServiceImpl 已经超过了4K行,ChatCoreSellerServiceImpl 超过了5K行,超过1000行的类不胜枚举。这些类的职责早已不在单一。当一个类完全靠搜索去查代码的功能时,我们已经无法去掌控它了。
 
4.重复的代码。《重构》一书提到过代码的bad smell(坏味道),其中之一就是duplicated code。重复的代码意味着,如果需求变化,那么需要多处修改。而更坏的消息便是,在一个有5千行代码的类里多处修改。
sdk里有这样一段过滤功能的代码:
// 内容过滤(敏感词、协议保留字符、不安全的字符)
String afterFilt = null;
RichText text = protocolService.parseRichText(msg.getMsgtext());
afterFilt = filterService.filtXss(text.getD());
afterFilt = filterService.filtSensitiveWord(afterFilt, SensitiveWord.WAITER);
msg.setRichText(text);
出现了多次。如果把这段代码抽成一个公共调用的方法,不仅可以避免多处修改,同时,我们的类会更加的简短。
 
5.过长的形参列表。方法的形参列表过长,不仅难以阅读,调用起来也觉得麻烦。更恰当的practice是,把这些形参放到一个class中去,然后把这个类作为形参。如果需要再增加一个参数,就不用改形参列表,直接改类即可。
前台有很多代码都有七八个参数。不列举了。
 
6.过长的的方法。同类一样,方法也要职责单一,不宜过长。相信大家都有这样的认识:方法越长,越难以理解。看过我们组架构师的代码就会发现一个显著的特点,方法短小精悍(譬如cell工程)。一个短小的方法,搭配一个好的方法名,带来的可读性和共享性是十分强大的。
一个askFromMobile方法,是100行。

7.日志被吃掉。这个虽然无关代码风格,但是对线上排查问题极为重要。多次排查线上问题时,发现日志没有输出完整,甚至根本没有输出。看下面一个例子,碰到这样的代码,查问题时真要吐血。
public OrderListResultInfo getOrderList(OrderQueryInfo orderQueryInfo) {
		OrderListResultInfo resultInfo = null;
		try {
			resultInfo = orderCenterExportSaf.getOrderList(orderQueryInfo);
		} catch (Exception e) {
			
		} 
		return resultInfo;
	}

 
这7个问题是我目前总结的比较常见的问题。贴出来的代码并不针对任何人,只是希望大家以后能避免这样的现象,大家一起写出更高质量的代码。
在一个大型项目里开发功能添加代码,没有一行代码可以作为一个人的“私有代码”、“私有财产”,你的代码即使不被别人用到,也会被别人阅读。代码的可读性在大型工程里的重要意义不言而喻,没有一个人可以再大型项目里为所欲为的写代码。“私有代码”是对其他协同的同事的不尊重!
有一个心理学理论叫破窗理论(详见《程序员的修炼》),一个房子如果窗户破了,没有人去修补,隔不久,其它的窗户也会莫名其妙地被人打破 。同样,如果一个大型工程,你写了一段烂代码,那么不久,就会有更多的烂代码出现。因为大家都学会了破罐子破摔。
最后,以《代码大全》一书的某个章节的标题作为本文的结尾:Write programs for persons first, for computers second.
PS,阿里巴巴推出了Java开发编码规范,十分实用,传送门  https://github.com/alibaba/p3c


猜你喜欢

转载自blog.csdn.net/bruce128/article/details/50578026