阿里巴巴Java 约规手册:码出高效,码出质量

最近在和实验室的同学一起给学校教务处做一个教学工作量统计系统,在团队一起合作开发及测试的过程中,我认识到了自己在开发规范方面的不足,虽然以前就看过阿里巴巴Java 约规手册,但是我在平时自己做项目、学习的过程中并没有很注意,只遵守驼峰命名等较为基础的约规。在这次的开发过程中,因为开发当中的不规范而导致了很多问题,例如:

  • POJO 类及方法返回值的类型都定义的是 int 等基本类型,而不是 Integer 等引用类型,这样在数据库里的数据为空的情况下或者页面传来null 值的时候,系统就会报错;
  • 在工作量计算时,所需的常量也未使用枚举或类静态常量定义,从而导致程序里有许多魔数,这也会使维护变得困难;
  • 大家都是第一次实际自己设计并实现一个系统,在构想的时候难免不充分,在全局异常处理以及全局返回值定义方面没有统一,这将导致一旦系统出现异常无法做出足够正确的处理
  • 数据库的表结构和索引具有一定的缺陷,这可能会导致系统的架构缺陷和性能风险

所以我重新看了阿里巴巴Java 约规手册,在经过这次实战后,我对开发规范的重视程度提高了很多,对为什么要严格遵守约规有了更深入的认识,可能软件工程师与码农的区别不仅仅是技术、架构上差别,还有写出的代码的质量。

以下是约规手册的部分内容概述:

  • 代码中的命名均不能以下划线或美元符号开始,也不能以其结束
  • 代码中的命名严禁中英文混合,更不允许使用中文,应使用正确的英文拼写和语法‘’
  • 类名要使用 UpperCamelCase 风格,除了DO / BO / DTO / VO / AO / PO 等领域模型
  • 方法名、参数名、成员变量、局部变量都统一使用 lowerCamelCase 风格,必须遵从
    驼峰形式
  • 常量命名全部大写,单词间用下划线隔开,力求语义表达完整清楚
  • 抽象类命名使用 Abstract 或 Base 开头;异常类命名使用 Exception 结尾;测试类
    命名以它要测试的类名开始,以 Test 结尾
  • 类型与中括号紧挨相连来定义数组。例如:String[] args 而不是 String args[]
  • POJO 类中布尔类型的变量,都不要加 is 前缀,否则部分框架解析会引起序列化错误
  • 包名统一使用小写,点分隔符之间仅有一个自然语义的英文单词
  • 杜绝绝大部分缩写(个人认为杜绝所有缩写)
  • 命名变量、常量等要做到看文知义
  • 如果模块、接口、类、方法使用了设计模式,在命名时体现出具体模式
  • 接口类中的方法和属性不要加任何修饰符号尽量不要在接口里定义变量,如果一定要定义变量,肯定是与接口方法相关,并且是整个应用的基础常量
  • 枚举类名建议带上 Enum 后缀,枚举成员名称需要全大写,单词间用下划线隔开
  • Service/DAO 层方法命名规约:获取单个对象的方法用 get 作前缀、获取多个对象的方法用 list 作前缀、获取统计值的方法用 count 作前缀、插入的方法用 save/insert 作前缀、删除的方法用 remove/delete 作前缀、修改的方法用 update 作前缀
  • 领域模型命名规约:数据对象:xxxDO,xxx 即为数据表名;数据传输对象:xxxDTO,xxx 为业务领域相关的名称;展示对象:xxxVO,xxx 一般为网页名称;POJO 是 DO/DTO/BO/VO 的统称,禁止命名成 xxxPOJO
  • 不允许任何魔数出现在代码中(深有体会)
  • long 或 Long 赋初始值时,使用大写的 L,以免与1混淆
  • 不要使用一个常量类维护所有常量,按常量功能进行归类,分开维护
  • 注意常量的复用层次,根据不同的复用层次来决定常量放置的位置
  • 如果变量值仅在一个固定范围内变化用 enum 类型来定义(例如一年有几个季节)
  • if/for/while/switch/do 等保留字与括号之间都必须加空格
  • 任何二目、三目运算符的左右两边都需要加一个空格
  • 采用 4 个空格缩进,禁止使用 tab 字符
  • 注释的双斜线与注释内容之间有且仅有一个空格
  • IDE 的 text file encoding 设置为 UTF-8; IDE 中文件的换行符使用 Unix 格式,
    不要使用 Windows 格式
  • 避免通过一个类的对象引用访问此类的静态变量或静态方法,无谓增加编译器解析成
    本,直接用类名来访问即可
  • 所有的覆写方法,必须加@Override 注解
  • 避免使用可变参数编程
  • 不能使用过时的类或方法
  • Object 的 equals 方法容易抛空指针异常,应使用常量或确定有值的对象来调用
    equals(例如:“hello”.equals(object) 而不是 object.equals(“hello”))
  • 所有的相同类型的包装类对象之间值的比较,全部使用 equals 方法比较
  • 所有的 POJO 类属性必须使用包装数据类型
  • RPC 方法的返回值和参数必须使用包装数据类型
  • 所有的局部变量使用基本数据类型
  • 定义 DO/DTO/VO 等 POJO 类时,不要设定任何属性默认值
  • 在进行序列化和反序列化时不要轻易修改serialVersionUID 的值
  • POJO 类必须写 toString 方法。使用 IDE 中的工具:source> generate toString
    时,如果继承了另一个 POJO 类,注意在前面加一下 super.toString
  • 使用索引访问用 String 的 split 方法得到的数组时,需做最后一个分隔符后有无
    内容的检查,否则会有抛 IndexOutOfBoundsException 的风险
  • setter 方法中,参数名称与类成员变量名称一致,this.成员名 = 参数名。在
    getter/setter 方法中,不要增加业务逻辑,增加排查问题的难度
  • 循环体内,字符串的连接方式,使用 StringBuilder 的 append 方法进行扩展(有利于提高效率)
  • 慎用 Object 的 clone 方法来拷贝对象
  • 类成员与方法访问控制从严
  • 要注意对 ArrayList 的 subList 的操作,以及 subList 不可强转成 ArrayList
  • 不要在 foreach 循环里进行元素的 remove/add 操作。remove 元素请使用 Iterator
    方式,如果并发操作,需要对 Iterator 对象加锁
  • 使用 entrySet 遍历 Map 类集合 KV,而不是 keySet 方式进行遍历
  • 获取单例对象需要保证线程安全,其中的方法也要保证线程安全
  • 创建线程或线程池时请指定有意义的线程名称,方便出错时回溯
  • 线程资源必须通过线程池提供,不允许在应用中自行显式创建线程
  • 高并发时,同步调用应该去考量锁的性能损耗。能用无锁数据结构,就不要用锁;能
    锁区块,就不要锁整个方法体;能用对象锁,就不要用类锁
  • ThreadLocal 无法解决共享对象的更新问题,ThreadLocal 对象建议使用 static
    修饰
  • 在 if/else/for/while/do 语句中必须使用大括号
  • 在一个 switch 块内,每个 case 要么通过 break/return 等来终止,要么注释说明程
    序将继续执行到哪一个 case 为止;在一个 switch 块内,都必须包含一个 default 语句并且放在最后,即使空代码
  • 在高并发场景中,避免使用”等于”判断作为中断或退出的条件(因为等值判断可能被击穿)
  • 避免采用取反逻辑运算符
  • 要注意参数校验的场景(内部校验和外部校验)
  • 类、类属性、类方法的注释必须使用 Javadoc 规范,使用/*内容/格式,不得使用// xxx 方式
  • 所有的抽象方法(包括接口中的方法)必须要用 Javadoc 注释、除了返回值、参数、
    异常说明外,还必须指出该方法做什么事情,实现什么功能
  • 所有的类都必须添加创建者和创建日期
  • 所有的枚举类型字段必须要有注释,说明每个数据项的用途
  • 代码修改的同时,注释也要进行相应的修改,尤其是参数、返回值、异常、核心逻辑
    等的修改
  • 待办事宜(TODO):( 标记人,标记时间,[预计处理时间])
  • 错误,不能工作(FIXME):(标记人,标记时间,[预计处理时间])
  • Java 类库中定义的可以通过预检查方式规避的 RuntimeException 异常不应该通过
    catch 的方式来处理,比如:NullPointerException,IndexOutOfBoundsException 等
  • 异常不要用来做流程控制,条件控制
  • catch 时请分清稳定代码和非稳定代码,稳定代码指的是无论如何不会出错的代码。
    对于非稳定代码的 catch 尽可能进行区分异常类型,再做对应的异常处理
  • 异常捕获后必须要进行处理
  • 有 try 块放到了事务代码中,catch 异常后,如果需要回滚事务,一定要注意手动回
    滚事务
  • finally 块必须对资源对象、流对象进行关闭
  • 捕获异常与抛异常,必须是完全匹配
  • 防止 NullPointerException 是程序员的基本修养,要注意 NullPointerException 发生的场景
  • 避免出现重复的代码(Don’t Repeat Yourself),即 DRY 原则
  • 应用中不可直接使用日志系统(Log4j、Logback)中的 API,而应依赖使用日志框架
    SLF4J 中的 API,使用门面模式的日志框架,有利于维护和各个类的日志处理方式统一
  • 日志文件推荐至少保存 15 天,因为有些异常具备以“周”为频次发生的特点
  • 注意日志文件的命名方式
  • 对 trace/debug/info 级别的日志输出,必须使用条件输出形式或者使用占位符的方
    式,以免造成资源的浪费
  • 后台输送给页面的变量必须加$!{var}——中间的感叹号
  • 注意 Math.random() 这个方法返回是 double 类型,注意取值的范围 0≤x<1(能够
    取到零值,注意除零异常),如果想获取整数类型的随机数,不要将 x 放大 10 的若干倍然后取整,直接使用 Random 对象的 nextInt 或者 nextLong 方法
  • 获取当前毫秒数 System.currentTimeMillis(); 而不是 new Date().getTime()
  • 不要在视图模板中加入任何复杂的逻辑
  • 任何数据结构的构造或初始化,都应指定大小,避免数据结构无限增长吃光内存
  • 隶属于用户个人的页面或者功能必须进行权限控制校验
  • 用户敏感数据禁止直接展示,必须对展示数据进行脱敏
  • 严禁SQL 注入
  • 用户请求传入的任何参数必须做有效性验证
  • 表单、AJAX 提交必须执行 CSRF 安全过滤
  • 表达是与否概念的字段,必须使用 is_xxx 的方式命名,数据类型是 unsigned tinyint
    ( 1 表示是,0 表示否)
  • 表名、字段名必须使用小写字母或数字,禁止出现数字开头,禁止两个下划线中间只
    出现数字。数据库字段名的修改代价很大,因为无法进行预发布,所以字段名称需要慎重考虑
  • 表名不使用复数名词
  • 禁用MYSQL官方保留字
  • 小数类型为 decimal,禁止使用 float 和 double
  • 表必备三字段:id, gmt_create, gmt_modified
  • 单表行数超过 500 万行或者单表容量超过 2GB,才推荐进行分库分表
  • 业务上具有唯一特性的字段,即使是多个字段的组合,也必须建成唯一索引
  • 超过三个表禁止 join。需要 join 的字段,数据类型必须绝对一致;多表关联查询时,
    保证被关联的字段需要有索引
  • 页面搜索严禁左模糊或者全模糊,如果需要请走搜索引擎来解决
  • 利用延迟关联或者子查询优化超多分页场景
  • 不要使用 count(列名)或 count(常量)来替代 count(*)
  • 当某一列的值全是 NULL 时,count(col)的返回结果为 0,但 sum(col)的返回结果为
    NULL,因此使用 sum()时需注意 NPE 问题
  • NULL 与任何值的直接比较都为 NULL
  • 在代码中写分页查询逻辑时,若 count 为 0 应直接返回,避免执行后面的分页语句
  • 不得使用外键与级联,一切外键概念必须在应用层解决
  • 数据订正(特别是删除、修改记录操作)时,要先 select,避免出现误删除,确认
    无误才能执行更新语句
  • 在表查询中,一律不要使用 * 作为查询的字段列表,需要哪些字段必须明确写明
  • 不允许直接拿 HashMap 与 Hashtable 作为查询结果集的输出
  • 更新数据表记录时,必须同时更新记录对应的 gmt_modified 字段值为当前时间
  • @Transactional 事务不要滥用。事务会影响数据库的 QPS,另外使用事务的地方需
    要考虑各方面的回滚方案,包括缓存回滚、搜索引擎回滚、消息补偿、统计修正等
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值