转载

解读阿里官方代码规范(三)

今天是2017年2月16日

这是demo2do的第 3 篇文章

本文同时隶属于 【代码洁癖】 系列

本文是阿里官方代码规范解读系列的第三篇,本系列总计五篇。

  • 格式规约

格式规约是代码规范中争议最大的,由于条目众多,在这里就不逐一解读,挑选几条大致说一下。

1. 3.5 缩进采用4个空格,禁止使用tab字符

1 . 3 6. 单行字符数限不超过 120 个

1. 3. 8 IDE的text file encoding设置为UTF-8; IDE中文件的换行符使用Unix格式,不要使用windows格式

1. 3. 10 方法体内的执行语句组、变量的定义语句组、不同的业务逻辑之间或者不同的语义之间插入一个空行

绝大多数情况下,空格党和Tab党的较量是空格党完胜。笔者也不记得是多少年前被一位前辈教育说禁止使用Tab,就保持了良好的习惯至今。对于缩进,个人比较赞同4个空格,但HTML等页面上使用4个空格的话,一些复杂页面的缩进就会比较恐怖,此时可以降级为2个空格。

对于单行字符数的限制不超过120个这条规则, 笔者完全不能认同 。这里面牵涉到的情况比较多,不能一棒子打死了。有些逻辑有大量的分支和循环的嵌套,如果遵循4个空格的缩进原则,碰到方法名称还比较长的状况,就要折行,这给代码阅读带来极大的困扰;另外有一种情况,就是需要额外进行比较长的注释编写,不能写在一行里的感觉真是比较糟糕,因为还得考虑断句才不影响阅读。另外,笔者有一个习惯是在条件语句边上加一句注释,这样就有很大概率会超出120字:

解读阿里官方代码规范(三)

有人会问,条件语句边上加注释是什么鬼?从上面的代码上可以看到,条件语句上面的一行注释实际上在解释整个代码片段,而条件语句边上的注释说明的是条件语句本身!当然如果读者有更好的写注释的位置,请及时给笔者留言。

文件的UTF-8和Unix格式没什么好说的,IDE支持的也很好。但这一点对初级程序员尤为重要,我已经不知道多少次就这个问题惩罚过实习生了。

有关语句组空行,是笔者极力推荐的一个做法。这不仅仅是为了空行而空行,这里的空行本身就是一种编程思路的整理。而笔者还有一个习惯就是对比较复杂的逻辑,都在语句组的前面加上注释,注释也用编号编排,这样回头debug时也会极大提升效率。

  • 集合类型

阿里规范中的集合类型这个章节,感觉写得比较鸡肋。绝大多数的规范似乎都是针对初级程序员的。笔者看了半天也没总结出一条值得额外解读的,所以权当复习一遍基础知识就好。

  • 并发处理

1 .6.1 获取单例对象需要保证线程安全,其中的方法也要保证线程安全

1 .6.2 创建线程或线程池时请指定有意义的线程名称,方便出错时回溯

1.6.3 线程资源必须通过线程池提供,不允许在应用中自行显式创建线程

1 . 6.4 线程池不允许使用Executors去创建,而是通过 ThreadPoolExecutor 去创建

上面这4条规则主要是针对线程的创建和使用。由于Spring的存在,其实上述情况不太可能发生。

1 .6.5 高并发时,同步调用应该去考量锁的性能损耗。能用无锁数据结构,就不要用锁;能锁区块,就不要锁整个方法体;能用对象锁,就不要用类锁

1 .6.7 对多个资源、数据库表、对象同时加锁时,需要保持一致的加锁顺序,否则可能会造成死锁

1.6.8 并发修改同一记录时,避免更新丢失,要么在应用层加锁,要么在缓存加锁,要么在数据库层使用乐观锁,使用version作为更新依据

上面这3条规则主要是针对锁。不过这几条规则看上去更像是3道面试题的答案。这3道面试题分别是:

  • 使用锁同步,有什么需要注意的地方?

  • 什么是死锁?举例说明什么情况会发生死锁?

  • 什么是乐观锁?什么是悲观锁?分别用在什么场景?

相信能解答上述面试题的同学,应该对上面的原则了然于心。

1 .6.9 多线程并行处理定时任务时,Timer运行多个TimeTask时,只要其中之一没有捕获抛出的异常,其它任务便会自动终止运行,使用ScheduledExecutorService则没有这个问题

1 .6.10 使用CountDownLatch进行异步转同步操作,每个线程退出前必须调用countDown方法,线程执行代码注意catch异常,确保countDown方法可以执行,避免主线程无法执行至countDown方法,直到超时才返回结果回溯

1.6.13 volatile解决多线程内存不可见问题。对于一写多读,是可以解决变量同步问题,但是如果多写,同样无法解决线程安全问题

1 . 6.14 HashMap在容量不够进行resize时由于高并发可能出现死链

1 . 6.15 ThreadLocal无法解决共享对象的更新问题,ThreadLocal对象建议使用static修饰。这个变量是针对一个线程内所有操作共有的,所以设置为静态变量,所有此类实例共享此静态变量

上面这些规则基本上属于知识贴范畴,可以一带而过,有些可能不太会实际碰到。像定时任务,可能使用Spring的封装更多一些,而Spring默认就是使用ScheduledExecutorService的。

而CountDownLatch的异常捕获,也是一个老生常谈的问题了,属于多线程编程的基本功。

最后的三条对于写应用的同学接触不多,但写底层的同学应该会很熟悉。

  • 注释规约

注释规约的内容比较多,这里也仅挑选一些具有代表性的进行解读

1 .8.5 所有的枚举类型字段必须要有注释,说明每个数据项的用途

1 .8.6 与其“半吊子”英文来注释,不如用中文注释把问题说清楚。专有名词与关键字保持英文原文即可

1.8.8 注释掉的代码尽量要配合说明,而不是简单的注释掉

1 .8.10 好的命名、代码结构是自解释的,注释力求精简准确、表达到位

枚举类加注释是非常必要的,因为枚举通常是都是常量的扩展,而常量是需要说明的。

鉴于很多程序员的英语水平,笔者建议英语不够好的程序员直接使用中文写注释。

对于注释掉的代码,笔者的意见是在绝大多数情况下应该直接删除,除非在很短的时间内还有恢复的余地。

有关什么是好的命名和代码结构,什么样的命名能够使得代码做到自解释,笔者将另外撰文进行说明。

(本系列未完待续)

如果你喜欢陆老师的文章,请长按二维码关注demo2do公众号

解读阿里官方代码规范(三)

如果你认为本文对你有帮助,请打赏

解读阿里官方代码规范(三)

原文  http://mp.weixin.qq.com/s?__biz=MzI0Mjc3NTEzMQ==&mid=2247483665&idx=1&sn=eacdc874bc9dc8a14dcded0ec3a56201&chksm=e9766425de01ed33fc576f11c4b8e9349ab91c468ebe1bee4a5baa3dbe84db0c520508d14670
正文到此结束
Loading...