阿里巴巴Java开发手册学习与IDEA插件试用

初中级Java工程师必备良药。引用手册的愿景:码出高效,码出质量。感谢阿里的工程师们做出的总结。

重要条目

以下列举了一些个人认为比较重要的条目。

编程规约

命名风格

  • 6 【强制】抽象类命名使用Abstract或Base开头;异常类命名使用Exception结尾;测试类命名以它要测试的类的名称开始,以Test结尾。
  • 8 【强制】POJO类中布尔类型的变量,都不要加is,否则部分框架解析会引起序列化错误。
  • 9 【强制】包名统一使用小写,点分隔符之间有且仅有一个自然语义的英语单词。包名统一使用单数形式,但是类名如果有复数含义,类名可以使用复数形式。
  • 12 【推荐】如果模块、接口、类、方法使用了设计模式,在命名时体现出具体模式。
  • 16 【参考】各层命名规约:Service/DAO层方法命名规约,领域模型命名规约(这个比较重要)

常量定义

一共就5个,都挺重要的。

  • 1 【强制】不允许任何魔法值(即未经定义的常量)直接出现在代码中。
  • 3 【推荐】不要使用一个常量类维护所有常量,按常量功能进行归类,分开维护。
  • 4 【推荐】常量的复用层次有五层:跨应用共享常量、应用内共享常量、子工程内共享常量、包内共享常量、类内共享常量。

代码格式

  • 3 【强制】if/for/while/switch/do等保留字与括号之间都必须加空格。
  • 5 【强制】采用4个空格缩进,禁止使用tab字符。(非常重要)
  • 9 【强制】IDE的text file encoding设置为UTF-8; IDE中文件的换行符使用Unix格式,不要使用Windows格式。

OOP规约

这一部分整体都很重要。个人感觉命名风格、常量定义、代码格式这几个分类一般都会有所了解,在其他书籍也有涉及,但是OOP规约,平时写代码确实不容易注意到,作为Java初学者基本都犯过类似的错误。OOP规约中很多条目都体现了软件工程中强调的“高内聚,低耦合”的特点,严格遵循这些规定,可以降低与其他调用方的耦合关系,便于代码的维护。

集合处理

只要了解集合类的相关API,读过源码,这些条目都很容易理解。

  • 6 【强制】泛型通配符<? extends T>来接收返回的数据,此写法的泛型集合不能使用add方法,而<? super T>不能使用get方法,做为接口调用赋值时易出错。
  • 7 【强制】不要在foreach循环里进行元素的remove/add操作。remove元素请使用Iterator方式,如果并发操作,需要对Iterator对象加锁。
  • 10 【推荐】使用entrySet遍历Map类集合KV,而不是keySet方式进行遍历。(这个条目下面的说明没太看懂,使用keySet进行遍历时,遍历应该是1次,而查询是2次?不懂)

并发处理

这里面的条目如果死记硬背的话根本没用,还是要理解背后的原理。

  • 1 【强制】获取单例对象需要保证线程安全,其中的方法也要保证线程安全。
  • 4 【强制】线程池不允许使用 Executors 去创建,而是通过 去创建,而是通过 ThreadPoolExecutor 的方式,这样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。
  • 11 【推荐】避免Random实例被多线程使用,虽然共享该实例是线程安全的,但会因竞争同一seed导致的性能下降。
  • 15 【参考】ThreadLocal无法解决共享对象的更新问题,ThreadLocal对象建议使用static修饰。(弄清楚ThreadLocal的使用场景)

控制语句

  • 3 【推荐】表达异常的分支时,少用if-else方式,用return。(这个有意思,卫语句、策略模式、状态模式来实现if-else值得学习,在《重构》一书中有详细介绍)
  • 7 && 8 【参考】参数校验

注释规约

  • 6 【推荐】与其“半吊子”英文来注释,不如用中文注释把问题说清楚。(笑)
  • 7 【推荐】代码修改的同时,注释也要进行相应的修改,尤其是参数、返回值、异常、核心逻辑等的修改。(强烈建议改为强制!未修改的注释有强烈的误导性)
  • 10 【参考】好的命名、代码结构是自解释的,注释力求精简准确、表达到位。(嗯,少写注释,多写文档)

其它

  • 7 【推荐】任何数据结构的构造或初始化,都应指定大小,避免数据结构无限增长吃光内存。
  • 8 【推荐】及时清理不再使用的代码段或配置信息。

异常日志

很重要很重要的一部分。有经验的程序员能优雅地处理异常。异常日志打的好不好,直接关系到排查错误的难易程度。

异常处理

  • 3 【强制】对大段代码进行try-catch,这是不负责任的表现。(补充一句,catch Exception或者RuntimeException也是不负责任的)
  • 4 【强制】捕获异常是为了处理它,不要捕获了却什么都不处理而抛弃之,如果不想处理它,请将该异常抛给它的调用者。最外层的业务使用者,必须处理异常,将其转化为用户可以理解的内容。
  • 10 【推荐】防止NPE,是程序员的基本修养,注意NPE产生的场景
  • 12 【参考】在代码中使用“抛异常”还是“返回错误码”,对于公司外的http/api开放接口必须使用“错误码”;而应用内部推荐异常抛出;跨应用间RPC调用优先考虑使用Result方式,封装isSuccess()方法、“错误码”、“错误简短信息”。

日志规约

  • 1 【强制】应用中不可直接使用日志系统(Log4j、Logback)中的API,而应依赖使用日志框架SLF4J中的API。
  • 2 【强制】日志文件推荐至少保存15天,因为有些异常具备以“周”为频次发生的特点。
  • 4 【强制】对trace/debug/info级别的日志输出,必须使用条件输出形式或者使用占位符的方式。
  • 8 【参考】可以使用warn日志级别来记录用户输入参数错误的情况,避免用户投诉时,无所适从。注意日志输出的级别,error级别只记录系统逻辑出错、异常等重要的错误信息。如非必要,请不要在此场景打出error级别。

单元测试

  • 8 【推荐】单元测试的基本目标:语句覆盖率达到70%;核心模块的语句覆盖率和分支覆盖率都要达到100%
  • 9 【推荐】编写单元测试代码遵守BCDE原则,以保证被测试模块的交付质量。
  • 10 【推荐】对于数据库相关的查询,更新,删除等操作,不能假设数据库里的数据是存在的,或者直接操作数据库把数据插入进去,请使用程序插入或者导入数据的方式来准备数据。
  • 11 【推荐】和数据库相关的单元测试,可以设定自动回滚机制,不给数据库造成脏数据。

安全规约

安全问题是大问题!!!每一条都很重要!

MySQL数据库

说实话,数据库基础比较差,感觉四个规约中的条目都很重要。ORM部分是基于MyBatis的,可以参考。

工程结构

应用分层

如果手册中的架构图是代码架构的话,应该是事务脚本设计而非领域驱动设计。(附录2中的专有名词说明也证实这一点,Business Object(BO)属于POJO,而POJO规定只含有getter和setter)对一般项目来说,使用这一代码架构进行分层设计应该都是OK的。

IDEA插件试用

IDEA MAC 2016.3装上就能用,自己体验下就好,cmd + alt + shift + J 一键搞定PMD。另外p3c项目有很多的issue,后面有时间有兴趣的话考虑提提PR。

想法

  • 手册中的很多条目不是用来死记硬背的,而是帮助你理解Java中的一些比较关键的设计原理(如集合类,序列化,并发等),把规约背后的原理弄懂才算是真正学会了。
  • 对于没有实际生产经验的学生来说,手册中与“生产”和“合作”有关的部分可能平时自己写代码真的不会想到,学习这一部分内容可以在正式工作之前养成良好的编码习惯。
  • 学习这本手册只是一个开始,作为一个有追求的程序设计师,应该维护一本属于自己的“开发手册-终极版”,沉淀自己的技术,提升自己的软件修为。

参考资料