阿里巴巴开发规范--精选常用规范

一、编程规范
(一)命名规范
1、类名使用驼峰法,DO/BO/DTO/VO/AO/PO除外
正例:UserDO
补充
  • pojo
    • vo (与前端交互的所有对象,包括接参和返回)
    • query (查询的筛选条件,前端传参和后端内部传参通用)
    • entity (数据库表基础对象)
    • dto(后端内部传输用,例如多张表字段合并到一个对象)
  • DO(Data Object):此对象与数据库表结构一一对应,通过 DAO 层向上传输数据源对象。
  • DTO(Data Transfer Object):数据传输对象,Service 或 Manager 向外传输的对象。
  • BO(Business Object):业务对象,可以由 Service 层输出的封装业务逻辑的对象。
  • AO(ApplicationObject):应用对象,在Web层与Service层之间抽象的复用对象模型, 极为贴近展示层,复用度不高
  • Query:数据查询对象,各层接收上层的查询请求。注意超过 2 个参数的查询封装,禁止使用 Map 类来传输。
  • VO(View Object):显示层对象,通常是 Web 向模板渲染引擎层传输的对象, 可以优化掉,展示业务不复杂的可以直接用DTO
  • PO(Persistant Object)持久对象, PO比较好理解,简单说PO就是数据库中的记录 ,一个PO的数据结构对应着库中表的结构,表中的一条记录就是一个PO对象,或者叫Entity/DO
  • BO和DTO的区别: 这两个的区别主要是就是字段的删减
  • BO对内,为了进行业务计算需要辅助数据,或者是一个业务有多个对外的接口,BO可能会含有很多接口对外所不需要的数据,因此DTO需要在BO的基础上,只要自己需要的数据,然后对外提供, 在这个关系上,通常不会有数据内容的变化,内容变化要么在BO内部业务计算的时候完成,要么在解释VO的时候完成
2、抽象类命名使用Abstract或Base
3、枚举成员名称需要全大写
4、各层命名规约
Service/DAO层方法命名规约
1)获取单个对象的方法用get作前缀
2)获取多个对象的方法用list作前缀
3)获取统计值的方法用count作前缀
4)插入的方法用save/insert作前缀
5)删除的方法用remove/delete作前缀
6)修改的方法用uodate作前缀
领域模型命名规约
1)数据对象:xxxDO,xxx即为数据表名
2)数据传输对象:xxxDTO,xxx为业务领域相关的名称
3)展示对象:xxxVO,xxx一般为网页名称
4)POJO是DO/DTO/BO/VO的统称,禁止命名为xxxPOJO
(二)常量定义
1、long或者Long初始赋值时,使用大写的L,不能是小写的l,小写容易跟数字1混淆,造成误解。
2、不要使用一个常量类维护所有常量,按常量功能进行归类,比如缓存相关常量放在类CacheConsts下,系统配置相关常量放在类ConfigConsts下
(三)代码格式
if/for/while/switch/do等保留字与括号之间都必须加空格
(四)OOP规约
1、Object的equals方法容易抛出空指针异常,应使用常量或确定有值的对象来调用equals
正例:“test”.equals(object)
2、关于基本数据类型与包装数据类型的使用标准如下:
所有的POJO类属性必须使用 包装数据类型
RPC方法的返回值和参数必须使用 包装数据类型
所有的局部变量使用 基本数据类型
3、构造方法里面禁止加入任何业务逻辑,如果有初始化逻辑,请放在init方法中
4、使用索引访问用String的split方法得到的数组时,需做最后一个分隔符后有无内容的检查,否则会有角标越界异常
5、类内方法定义的顺序依次是:公有方法或保护方法>私有方法>getter/setter方法
6、循环体内,字符串的连接方式,使用StringBuilder的append方法进行扩展
7、final可以声明类、成员变量、方法、以及本地变量,下列情况使用final关键字
1)不允许被继承的类,如:String类
2)不允许修改引用的域对象,如POJO类的域变量
3)不允许被重写的方法,如:POJO类的setter方法
4)不允许运行过程中重新赋值的局部变量
5)避免上下文重复使用一个变量,使用final描述可以强制重新定义一个变量,方便更好地进行重构
8、慎用Object的clone方法来拷贝对象,对象的clone方法默认是浅拷贝,若想实现深拷贝需要重写clone方法实现属性对象的拷贝
9、类成员与方法访问控制从严
1)如果不允许外部直接通过new来创建对象,那么构造方法必须是private
2)工具类不允许有public或者default构造方法
3)类非static成员变量并且与子类共享,必须是protected
4)类非static成员变量并且仅在本类使用,必须是private
5)类static成员变量如果仅在本类使用,必须是private
6)若是static成员变量,必须考虑是否为final
7)类成员方法只供类内部调用,必须是private
8)类成员方法只对继承类公开,那么限制为protected
(五)集合处理
1、关于hashcode和equals的处理,遵循如下规则:
1)只要重写equals,就必须重写hashCode
2)因为Set存储的是不重复的对象,依据hashCode和equals进行判断,所以Set存储的对象必须重写这两个方法
3)如果自定义对象作为Map的键,那么必须重写hashCode和equals,String重写了hashCode和equals方法,所以可以使用String对象作为key
2、不要在foreach循环里进行元素的remove/add操作,remove元素请使用Iterator方式,如果并发操作,需要对Iterator对象加锁
3、Map类集合K/V能不能存储null值的情况
集合类                             key                  Value               Super             说明
Hashtable                      不允许为null    不允许为null    Dictionary      线程安全
ConcurrentHashMap     不允许为null    不允许为null    AbstractMap  锁分段技术(JDK8:CAS)
TreeMap                       不允许为null      允许为null    AbstractMap  线程不安全
HashMap                      允许为null        允许为null    AbstractMap  线程不安全
(六)并发处理
1、线程资源必须通过线程池提供,不允许在应用中自行显式创建线程,线程不允许使用Executors去创建,而是通过ThraedPoolExecutor的方式,这样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。
2、SimpleDateFormat是线程不安全的类,一般不要定义为static变量,如果定义为static,必须加锁,或者使用DateUtils工具类;
如果是JDK8的应用,可以使用Instant代替Date,LocalDateTime代替Calendar,DateTimeFormatter代替SimpleDateFormatter代替SimpleDateFormat
3、高并发时,同步调用应该去考量锁的性能损耗。能用无锁数据结构,就不要用锁;能锁区块,就不要锁整个方法体;能用对象锁,就不要用类锁,避免在锁代码块中调用RPC方法。
4、 并发修改同一记录时,避免更新丢失,需要加锁。要么在应用层加锁,要么在缓存加锁,要么在数据库使用乐观锁,使用version作为更新依据,如果每次访问冲突概率小于20%,推荐使用乐观锁,否则使用悲观锁。乐观锁的重试次数不得小于3次。
5、多线程并行处理定时任务时,Timer运行多个TimeTask时,只要其中之一没有捕获抛出的异常,其他任务便会自动终止运行,使用SchedExecutorService则没有这个问题。
6、使用CountDownLatch进行异步转同步操作,每个线程退出前必须调用countDown方法,线程执行代码注意catch异常,确保 countDown方法被执行到,避免主线程无法执行至await方法,直到超时才返回结果。子线程抛出异常堆栈,不能在主线程try-catch到。
(七)控制语句
1、在一个switch块内,每个case要么通过break/return等来终止,要么注释说明程序将继续执行到哪一个case为止,在switch块内,都必须包含一个default语句并且放在最后,即使空代码
2、在高并发场景中,避免使用“等于”判断作为判断或退出的条件,容易产生等值判断被“击穿”的情况,使用大于或小于的区间判断条件来代替。
3、循环体中的语句要考量性能,以下操作尽量移至循环体外处理,如定义对象、变量、获取数据库连接,进行不必要的try-catch操作。
二、异常日志
(一)异常处理
1、不要在finally块中使用return
(二)日志规约
1、对trace/debug/info级别的日志输出,必须使用条件输出形式或者使用占位符的方式。
比如:logger.debug("Processing trade witn id:{} and symbol:{}",id,symbol)
2、避免重复打印日志,浪费磁盘空间,务必在log4j.xml或logback.xml中设置additivity=false
三、安全规约
1、隶属于用户个人的页面或者功能必须进行权限控制校验,防止没有做水平权限校验就可随意访问、修改、删除别人的数据,比如查看他人的私信内容,修改他人的订单。
2、用户敏感数据禁止直接展示,必须对展示数据进行脱敏
3、用户输入的SQL参数严格使用参数绑定或者METADATA字段值限定,防止SQL注入,禁止字符串拼接SQL访问数据库
4、用户请求传入的任何参数必须做有效性验证,忽略参数校验可能导致:pagesize过大导致内存溢出,恶意order by导致数据库慢查询,任意重定向,SQL注入,反序列化注入、正则输入源串拒绝服务ReDos
四、MySQL数据库
(一)建表规约
1、表达是与否概念的字段,必须使用is_xxx的方式命名,数据类型是unsigneed tinyint(1表示是,0表示否)
2、表名、字段名必须使用小写字母或数字,禁止出现数字开头,禁止两个下划线中间只出现数字。
3、小数类型为decimal,禁止使用float和double,如果存储的数据范围超过decimal的范围,建议将数据拆成整数和小数分开存储
4、varchar是可变长字符串,不预先分配存储空间,长度不要超过5000,如果存储长度大于此值,定义字段类型为text,独立出来一张表,用主键来对应,避免影响其他字段索引效率
5、表必备三字段:id主键id、gmt_create创建时间、gmt_modified修改时间
6、单表行数超过500万行,或者单表容量超过2GB,才推荐进行分库分表
(二)索引规约
1、业务上具有唯一特性的字段,必须建成唯一索引
2、超过三个表禁止join,需要join的字段,数据类型必须绝对一致,保证被关联的字段需要有索引
3、在varchar字段上建立索引时,必须指定索引长度,没必要对全字段建立索引,根据实际文本区分度决定索引长度即可,一般对字符串类型数据,长度为20的索引,区分度会高达90%以上,可以使用count(distinct left(列名,索引长度))/count("")的区分度来确定
4、页面搜索严禁左模糊或者全模糊,如果需要请走搜索引擎来解决。索引文件具有B-Tree的最左前缀匹配特性,如果左边的值未确定,那么无法使用此索引
5、如果有order by的场景,请注意利用索引的有序性。order by最后的字段是组合索引的一部分,并且放在索引组合顺序的最后,避免出现file_sort的情况,影响查询性能。
正例:where a=? and b=? order by c;索引a_b_c
反例:索引中有范围查找,那么索引有序性无法利用,如where a>10 order by b;索引a_b无法排序
6、SQL性能优化的目标:至少要达到range级别,要求是ref级别,如果可以是consts最好;consts单表在中最多只有一个匹配行,ref指的是使用普通的索引,range对索引进行范围检索,type=index,索引物理文件全扫描,速度非常慢
(三)SQL语句
1、数据订正时,特别是删除、修改记录操作,要先select,避免出现误删除,确认无误才能执行更新语句
2、in操作能避免就避免,避免不了,控制在1000个之内
3、sql.xml配置参数使用#{},#param#,不要使用${},此种方式容易出现SQL注入。
  • 1
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值