阿里编码规范摘要

唐宋元明清:
POJO是DO/DTO/BO/VO的统称,禁止命名成xxxPOJO。

唐宋元明清:
不要使用一个常量类维护所有常量,要按常量功能进行归类,分开维护

唐宋元明清:
) 【强制】所有的POJO类属性必须使用包装数据类型。
2) 【强制】RPC方法的返回值和参数必须使用包装数据类型。
3) 【推荐】所有的局部变量使用基本数据类型。

唐宋元明清:
定义DO/DTO/VO等POJO类时,不要设定任何属性默认值。

唐宋元明清:
构造方法里面禁止加入任何业务逻辑,如果有初始化逻辑,请放在init方法中。

唐宋元明清:
POJO类必须写toString方法。使用IDE中的工具:source> generate toString时,如果继承了另一个POJO类,注意在前面加一下super.toString。

唐宋元明清:
说明:在方法执行抛出异常时,可以直接调用POJO的toString()方法打印其属性值,便于排查问题。

唐宋元明清:
浅拷贝 只拷贝指针,深拷贝就是拷贝他的值,重新生成的对像。就像是浅拷贝就是你的影子,深拷贝是你的克隆人,你没了影子也就没了,但是克隆人还活着。

唐宋元明清:
【推荐】类成员与方法访问控制从严:
1) 如果不允许外部直接通过new来创建对象,那么构造方法必须是private。
2) 工具类不允许有public或default构造方法。
3) 类非static成员变量并且与子类共享,必须是protected。
4) 类非static成员变量并且仅在本类使用,必须是private。
5) 类static成员变量如果仅在本类使用,必须是private。
6) 若是static成员变量,考虑是否为final。
7) 类成员方法只供类内部调用,必须是private。
8) 类成员方法只对继承类公开,那么限制为protected。
说明:任何类、方法、参数、变量,严控访问范围。过于宽泛的访问范围,不利于模块解耦。
思考:如果是一个private的方法,想删除就删除,可是一个public的service成员方法或成员变量,删除一下,不得手心冒点汗吗?变量像自己的小孩,尽量在自己的视线内,变量作用域太大,无限制的到处跑,那么你会担心的。

唐宋元明清:
【强制】关于hashCode和equals的处理,遵循如下规则:
1) 只要重写equals,就必须重写hashCode。
2) 因为Set存储的是不重复的对象,依据hashCode和equals进行判断,所以Set存储的对象必须重写这两个方法。
3) 如果自定义对象作为Map的键,那么必须重写hashCode和equals。
说明:String重写了hashCode和equals方法,所以我们可以非常愉快地使用String对象作为key来使用。

唐宋元明清:
【强制】泛型通配符<? extends T>来接收返回的数据,此写法的泛型集合不能使用add方法,而<? super T>不能使用get方法,作为接口调用赋值时易出错。
说明:扩展说一下PECS(Producer Extends Consumer Super)
原则:
第一、频繁往外读取内容的,适合用<? extends T>。
第二、经常往里插入的,适合用<? super T>。

唐宋元明清:
【强制】不要在foreach循环里进行元素的remove/add操作。remove元素请使用Iterator方式,如果并发操作,需要对Iterator对象加锁。
正例:
List list = new ArrayList<>();
list.add(“1”);
list.add(“2”);
Iterator iterator = list.iterator();
while (iterator.hasNext()) {
String item = iterator.next();
if (删除元素的条件) {
iterator.remove();
}
}
反例:
for (String item : list) {
if (“1”.equals(item)) {
list.remove(item);
}
}
说明:以上代码的执行结果肯定会出乎大家的意料,那么试一下把“1”换成“2”,会是同样的结果吗?

唐宋元明清:
】使用entrySet遍历Map类集合KV,而不是keySet方式进行遍历。
说明:keySet其实是遍历了2次,一次是转为Iterator对象,另一次是从hashMap中取出key所对应的value。而entrySet只是遍历了一次就把key和value都放到了entry中,效率更高。如果是JDK8,使用Map.foreach方法。
正例:values()返回的是V值集合,是一个list集合对象;keySet()返回的是K值集合,是一个Set集合对象;entrySet()返回的是K-V值组合集合。

唐宋元明清:
【强制】线程资源必须通过线程池提供,不允许在应用中自行显式创建线程。
说明:使用线程池的好处是减少在创建和销毁线程上所消耗的时间以及系统资源的开销,解决资源不足的问题。如果不使用线程池,有可能造成系统创建大量同类线程而导致消耗完内存或者“过度切换”的问题。

唐宋元明清:
强制】线程池不允许使用Executors去创建,,而是通过 ThreadPoolExecutor的方式,这样的处理方式让写同学更加明确线程池运行规则,避资源耗尽风险。
说明: Executors返回的线程池对象的弊端 如下 :
1)FixedThreadPool和SingleThreadPool: 允许的请求队列长度为 Integer.MAX_VALUE,可 能会堆积大量的请求,从而导致 OOM。
2)CachedThreadPool 和 ScheduledThreadPool: 允许的创建线程数量为 Integer.MAX_VALUE,可能会创建大量的线程,从而导致 OOM。

唐宋元明清:
【强制】后台输送给页面的变量必须加 ! v a r — — 中 间 的 感 叹 号 。 说 明 : 如 果 v a r 等 于 n u l l 或 者 不 存 在 , 那 么 !{var}——中间的感叹号。 说明:如果var等于null或者不存在,那么 !varvarnull{var}会直接显示在页面上。

唐宋元明清:
强制】获取当前毫秒数System.currentTimeMillis(); 而不是new Date().getTime(); 说明:如果想获取更加精确的纳秒级时间值,使用System.nanoTime()的方式。在JDK8中,针对统计时间等场景,推荐使用Instant类。

唐宋元明清:
推荐】不要在视图模板中加入任何复杂的逻辑。
说明:根据MVC理论,视图的职责是展示,不要抢模型和控制器的活。

唐宋元明清:
【推荐】任何数据结构的构造或初始化,都应指定大小,避免数据结构无限增长吃光内存。

唐宋元明清:
强制】日志文件至少保存15天,因为有些异常具备以“周”为频次发生的特点

唐宋元明清:
【强制】小数类型为decimal,禁止使用float和double。

唐宋元明清:
说明:float和double在存储的时候,存在精度损失的问题,很可能在值的比较时,得到不正确的结果。如果存储的数据范围超过decimal的范围,建议将数据拆成整数和小数分开存储。

唐宋元明清:
【强制】如果存储的字符串长度几乎相等,使用char定长字符串类型。
【强制】varchar是可变长字符串,不预先分配存储空间,长度不要超过5000,如果存储长度大于此值,定义字段类型为text,独立出来一张表,用主键来对应,避免影响其它字段索引效率。
【强制】表必备三字段:id, gmt_create, gmt_modified。
说明: 其中 id必为 主键,类型必为 主键,类型bigint unsigned、单表时自增步长为 、单表时自增步长为 1。gmt_create, gmt_modified的类型均为 的类型均为 datetime类型,前者现在时表示主动创建,后者过去分词表示被动更新。

唐宋元明清:
【推荐】表的命名最好是加上“业务名称_表的作用”。
正例:alipay_task / force_project / trade_config
【推荐】库名与应用名称尽量一致。

唐宋元明清:
字段命名全部使用小写字母,多个单词使用下划线分割,不允许出现大写字母。
正例:user_name
【推荐】主键字段建议使用bigint unsingned类型,自增。
正例:user_id bigint unsingned comment ‘用户标识’

唐宋元明清:
使用ISNULL()来判断是否为NULL值。
说明:NULL与任何值的直接比较都为NULL。
1) NULL<>NULL的返回结果是NULL,而不是false。
2) NULL=NULL的返回结果是NULL,而不是true。
3) NULL<>1的返回结果是NULL,而不是true。

唐宋元明清:
在代码中写分页查询逻辑时,若count为0应直接返回,避免执行后面的分页语句

唐宋元明清:
强制】不得使用外键与级联,一切外键概念必须在应用层解决。
说明:以学生和成绩的关系为例,学生表中的student_id是主键,那么成绩表中的student_id则为外键。如果更新学生表中的student_id,同时触发成绩表中的student_id更新,即为级联更新。外键与级联更新适用于单机低并发,不适合分布式、高并发集群;级联更新是强阻塞,存在数据库更新风暴的风险;外键影响数据库的插入速度。

唐宋元明清:
【强制】禁止使用存储过程,存储过程难以调试和扩展,更没有移植性。

唐宋元明清:
强制】在表查询中,一律不要使用 * 作为查询的字段列表,需要哪些字段必须明确写明。
说明:
1)增加查询分析器解析成本。
2)增减字段容易与resultMap配置不一致。
3)无用字段增加网络消耗,尤其是text类型的字段。

唐宋元明清:
强制】POJO类的布尔属性不能加is,而数据库字段必须加is_,要求在resultMap中进行字段与属性之间的映射。
说明:参见定义POJO类以及数据库字段定义规定,在中增加映射,是必须的。在MyBatis Generator生成的代码中,需要进行对应的修改。

唐宋元明清:
强制】sql.xml配置参数使用:#{},#param# 不要使用${} 此种方式容易出现SQL注入

唐宋元明清:
【推荐】不要写一个大而全的数据更新接口。传入为POJO类,不管是不是自己的目标更新字段,都进行update table set c1=value1,c2=value2,c3=value3; 这是不对的。执行SQL时,不要更新无改动的字段,一是易出错;二是效率低;三是增加binlog存储

唐宋元明清:
参考】@Transactional事务不要滥用。事务会影响数据库的QPS,另外使用事务的地方需要考虑各方面的回滚方案,包括缓存回滚、搜索引擎回滚、消息补偿、统计修正等。

唐宋元明清:
一方库: 本工程内部子项目模块依赖的库(jar包)。
10. 二方库: 公司内部发布到中央仓库,可供公司内部其它应用依赖的库(jar包)。
11. 三方库: 公司之外的开源库(jar包)。

唐宋元明清:
7. 【推荐】利用延迟关联或者子查询优化超多分页场景。
说明:MySQL 并不是跳过 offset 行,而是取 offset+N 行,然后返回放弃前 offset 行,返回 N 行,那当 offset 特别大的时候,效率就非常的低下,要么控制返回的总页数,要么对超过 特定阈值的页数进行 SQL 改写。
正例:先快速定位需要获取的 id 段,然后再关联:
SELECT a.* FROM 表 1 a, (select id from 表 1 where 条件 LIMIT 100000,20 ) b where a.id=b.id(这样写主要是避免mysql取出前offset里过多的不需要的数据,其实只要取出id,最后在根据id来查询出需要的所有数据。哈哈,感谢阿里开发文档,最近有个功能就是由于这个问题导致sql查询在200ms以上,感觉找到了更好的优化方案,之前做过排序按书签方式 ,记录上次查询最新/大的id值,在往后取出一定数量的值,后来发现using filesort排序会导致更慢,但是如果不按时间排序,又不能按书签这种方式取出数据。)

唐宋元明清:
禁止使用float、double类型,建议使用decimal或者int替代

唐宋元明清:
添加默认字符集和排序DEFAULT CHARSET=utf8 COLLATE=utf8_bin
示例:
CREATE TABLE tablename (
table_id bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT ‘id’,
name varchar(64) NOT NULL COMMENT ‘英文 产生方式:手工维护 组成字符:英文、数字、“_” 数据长度:64’,PRIMARY KEY (table_id)
) ENGINE=InnoDB AUTO_INCREMENT=1001 DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT=‘表描述’;

唐宋元明清:
避免使用存储过程,触发器
避免使用存储过程、触发器、函数等,容易将业务逻辑和DB耦合在一起,并且MySQL的存储过程、触发器、函数中存在一定的bug。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值