阿里官方代码规范
1.1.1 代码中的命名均不能以下划线或美元符号开始,也不能以下划线或美元符号结束
1.1.2 代码中的命名严禁使用拼音与英文混合的方式,更不允许直接使用中文的方式
1.1.3 / 1.1.4 类名使用UpperCamelCase风格,必须遵从驼峰形式(某些情况诸如领域模型相关的命名除外);方法名、参数名、成员变量、局部变量都统一使用lowerCamelCase风格,必须遵从驼峰形式
1.1.5 常量命名全部大写,单词间用下划线隔开
1.1.9 包名统一使用小写,点分隔符之间有且仅有一个自然语义的英语单词
1.1.6 抽象类命名使用Abstract或Base开头;异常类命名使用Exception结尾;测试类命名以它要测试的类的名称开始,以Test结尾
1.1.13 对于Service和DAO类,基于SOA的理念,暴露出来的服务一定是接口,内部的实现类用Impl的后缀与接口区别
1.1.13 如果是形容能力的接口名称,取对应的形容词做接口名 1.1.14 枚举类名建议带上Enum后缀,枚举成员名称需要全大写,单词间用下划线隔开
1.1.11 如果使用到了设计模式,建议在类名中体现出具体模式
1.1.9 包名统一使用单数形式;类名如果有复数含义,类名可以使用复数形式
1.2.1 不允许出现任何魔法值(即未经定义的常量)直接出现在代码中
1.2.3 不要使用一个常量类维护所有常量,应该按常量功能进行归类,分开维护
1.2.4 常量的复用层次有五层:跨应用共享常量、应用内共享常量、子工程内共享常量、包内共享常量、类内共享常量
1.2.5 如果变量值仅在一个范围内变化用Enum类。如果还带有名称之外的延伸属性,必须使用Enum类
1.1.12 尽量不要在接口里定义变量,如果一定要定义变量,肯定是与接口方法相关,并且是整个应用的基础常量
1.2.2 long或者Long初始赋值时,必须使用大写的L,不能是小写的l,小写容易跟数字1混淆,造成误解
1.1.12 接口类中的方法和属性不要加任何修饰符号(public 也不要加),保持代码的简洁性,并加上有效的Javadoc注释
1.4.2 所有的覆写方法,必须加@Override注解
1.4.3 可变参数必须放置在参数列表的最后。(提倡同学们尽量不用可变参数编程)
1.4.4 对外暴露的接口签名,原则上不允许修改方法签名,避免对接口调用方产生影响。接口过时必须加@Deprecated注解,并清晰地说明采用的新接口或者新服务是什么
1.4.5 不能使用过时的类或方法 1.4.10 序列化类新增属性时,请不要修改serialVersionUID字段,避免反序列失败
1.4.17 循环体内,字符串的联接方式,使用StringBuilder的append
1.4.18 final可提高程序响应效率
1.4.19 慎用Object的clone方法来拷贝对象
1.4.7 所有的相同类型的包装类对象之间值的比较,全部使用equals方法比较
1.4.8 所有的POJO类属性必须使用包装数据类型
1.4.8 RPC方法的返回值和参数必须使用包装数据类型
1.4.8 所有的局部变量【推荐】使用基本数据类型 通常我们都会用is_disabled字段在数据库中表示某一个表的记录是否被逻辑删除,而这个字段,在Java代码中被映射成什么类型呢? Boolean?如果被映射成包装类型,那么数据库里面的这个字段就可以为null,有些读者会说,这并没有什么问题啊。可是,数据库is_disabled字段如果为null,代表什么逻辑含义呢? 这条记录究竟是有效还是无效? 如果这个字段不能为null,那么将其映射成基本类型是一个皆大欢喜的事情:既保证了数据库数据的完整性,我们在初始化的时候还可以忽略这个字段,因为boolean天生的默认值就是false 方法命名
1.1.15 Service/DAO层方法命名规约 - 获取单个对象的方法用get做前缀 - 获取多个对象的方法用list做前缀 - 获取统计值的方法用count做前缀 - 插入的方法用save(推荐)或insert做前缀 - 删除的方法用remove(推荐)或delete做前缀 - 修改的方法用update做前缀 方法和属性
1.4.9 定义DO/DTO/VO等POJO类时,不要设定任何属性默认值
1.4.11 构造方法里面禁止加入任何业务逻辑,如果有初始化逻辑,请放在init方法中
1.4.14 当一个类有多个构造方法,或者多个同名方法,这些方法应该按顺序放置在一起,便于阅读
1.4.15 类内方法定义顺序依次是:公有方法或保护方法 > 私有方法 > getter/setter方法
1.4.16 setter方法中,参数名称与类成员变量名称一致,this.成员名=参数名。在getter/setter方法中,尽量不要增加业务逻辑
1.4.20 类成员与方法访问控制从严 格式规约
1.3.5 缩进采用4个空格,禁止使用tab字符
1.3 6. 单行字符数限不超过 120 个
1.3.8 IDE的text file encoding设置为UTF-8; IDE中文件的换行符使用Unix格式,不要使用windows格式
1.3.10 方法体内的执行语句组、变量的定义语句组、不同的业务逻辑之间或者不同的语义之间插入一个空行 并发处理
1.6.1 获取单例对象需要保证线程安全,其中的方法也要保证线程安全
1.6.2 创建线程或线程池时请指定有意义的线程名称,方便出错时回溯
1.6.3 线程资源必须通过线程池提供,不允许在应用中自行显式创建线程
1.6.4 线程池不允许使用Executors去创建,而是通过ThreadPoolExecutor去创建
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修饰。这个变量是针对一个线程内所有操作共有的,所以设置为静态变量, 所有此类实例共享此静态变量 注释规约
1.8.5 所有的枚举类型字段必须要有注释,说明每个数据项的用途
1.8.6 与其"半吊子"英文来注释,不如用中文注释把问题说清楚。专有名词与关键字保持英文原文即可
1.8.8 注释掉的代码尽量要配合说明,而不是简单的注释掉
1.8.10 好的命名、代码结构是自解释的,注释力求精简准确、表达到位 数据库规约
3.1.1 是与否概念的字段,必须使用is_xxx的方式命名,数据类型是unsigned tinyint( 1表示是,0表示否)
3.1 2 表名、字段名必须使用小写字母或数字;禁止出现数字开头,禁止两个下划线中间只出现数字
3.1.3 表名不使用复数名词
3.1.4 禁用保留字
3.1.5 唯一索引名为uk_字段名;普通索引名则为idx_字段名
3.1.10 表的命名最好是加上业务名称_表的作用
3.1.11 库名与应用名称尽量一致
3.1.6 小数类型为decimal,禁止使用float和double
3.1.7 如果存储的字符串长度几乎相等,使用char定长字符串类型
3.1.8 varchar是可变长字符串,不预先分配存储空间,长度不要超过5000 明确日期和时间,日期使用date类型并使用xxDate进行Java字段命名,时间使用date_time类型并使用xxTime进行Java字段命名,以示区分
3.1.9 表必备三字段:id, gmt_create, gmt_modified
3.1.8 如果存储长度大于此值,定义字段类型为text,独立出来一张表,用主键来对应,避免影响其它字段索引效率
3.1.12 如果修改字段含义或对字段表示的状态追加时,需要及时更新字段注释
3.1.13 字段允许适当冗余,以提高性能,但是必须考虑数据同步的情况
3.1.14 单表行数超过500万行或者单表容量超过2GB,才推荐进行分库分表
3.1.15 合适的字符存储长度,不但节约数据库表空间、节约索引存储,更重要的是提升检索速度
3.2.1 业务上具有唯一特性的字段,即使是组合字段,也必须建成唯一索引
3.2.2 超过三个表禁止join
3.2.3 在varchar字段上建立索引时,必须指定索引长度
3.2.4 页面搜索严禁左模糊或者全模糊
3.2.5 如果有order by的场景,请注意利用索引的有序性
3.2.7 利用延迟关联或者子查询优化超多分页场景
3.2.9 建组合索引的时候,区分度最高的在最左边 禁止超过2个表的join语句出现在程序中 另外有关严禁使用全模糊查找,建组合索引时,区分度最高的往左放这些原则,在一定程度上会改变我们编写程序的习惯,所以应该时刻注意。
3.3.1 不要使用count(列名)或count(常量)来替代count(*)
3.3.5 在代码中写分页查询逻辑时,若count为0应直接返回,避免执行后面的分页语句
3.3.6 不得使用外键与级联,一切外键概念必须在应用层解决
3.3.7 禁止使用存储过程,存储过程难以调试和扩展,更没有移植性 3.3.9 in操作能避免则避免,若实在避免不了,需要仔细评估in后边的集合元素数量,控制在1000个之内 3.4.1 在表查询中,一律不要使用 * 作为查询的字段列表,需要哪些字段必须明确写明
1.7.3 推荐尽量少用else, if-else的方式可以改写成:
if(condition){
…
return obj;
}
// 接着写else的业务逻辑代码;
1.7.3 如果非得使用if()…else if()…else…方式表达逻辑,【强制】请勿超过3层,超过请使用状态设计模式
1.7.5 循环体中的语句要考量性能,以下操作尽量移至循环体外处理,如定义对象、变量、获取数据库连接,进行不必要的try-catch操作 这一条值得说一下,因为有些代码会走得比较深,写着写着就忘了它处于循环体的内部了。所以保持一个谨慎的心态比较重要。
1.7.7 方法中需要进行参数校验的场景:
1) 调用频次低的方法。
2) 执行时间开销很大的方法,参数校验时间几乎可以忽略不计,但如果因为参数错误导致中间执行回退,或者错误,那得不偿失。
3) 需要极高稳定性和可用性的方法。
4) 对外提供的开放接口,不管是RPC/API/HTTP接口。
5) 敏感权限入口。
1.7.8 方法中不需要参数校验的场景:
1) 极有可能被循环调用的方法,不建议对参数进行校验。但在方法说明里必须注明外部参数检查
2) 底层的方法调用频度都比较高,一般不校验。毕竟是像纯净水过滤的最后一道,参数错误不太可能到底层才会暴露问题。一般DAO层与Service层都在同一个应用中, 部署在同一台服务器中,所以DAO的参数校验,可以省略
3) 被声明成private只会被自己代码所调用的方法,如果能够确定调用方法的代码传入参数已经做过检查或者肯定不会有问题,此时可以不校验参数 在业务逻辑中尽可能不要使用setter方法,而是使用构造函数或者封装成一个有逻辑意义的方法,提高代码的可读性
在业务逻辑中尽可能不要使用setter方法,而是使用构造函数或者封装成一个有逻辑意义的方法,提高代码的可读性
在上面的代码中,左侧代码中的setter方法调用,会被封装到ShuttleOrder对象中的cancel方法中去。在实际的service代码中,只会出现下半部分的一行代码。
这样做的好处在于:cancel这个方法被封装后,shuttleOrder.cancel()的调用从可读性上要明显优于使用2句setter方法,同时也为将来的逻辑扩展预留了位置。这也是面向对象的一种实践