Java代码分层规范

本次将参照阿里的代码分层规范与命名规范做一次整理

类命名:
1.web层类名:使用Controller结尾
2.tr类名:使用Facade结尾
3.Service类名:使用Manager/ManagerImpl结尾
4.网关类名:使用FrontImpl结尾
5.抽象类名:使用Abstract或Base开头
6.异常类名:使用Exception结尾
7.测试类名:使用Test结尾
8.枚举类名:使用Enum结尾

POJO命名:
1.查询对象:xxxQuery(分页查询对象,仅限dao查询数据库使用)
2.数据对象:xxxDO(与数据库表相映射的类,仅限dao,manager层使用)
3.数据跨应用传输对象:xxxDTO(亦可当做返回调用者的模型对象)
4.数据传输对象:  xxxBO (manager/service 层应用内产生的可信对象,包含数据的相信信息,可供其他方法调用)
5.展示对象:xxxVO (向前端展示,需要对数据进行脱敏)
6.数据接收对象: xxxMethodQuery(web层不要使用@requestBody接收参数,web层入参大于3个参数的情况下,强制使用xxxMethodQuery对象接收参数,使用bean validate机制对入参进行校验)

方法命名:
1.Dao层方法的命名规约find/query/count/insert/delete/update作前缀
2.Service层方法的命名规约find/query/count/create/remove/modify 作前缀
3.Controller层方法的命名规约detail/query/count/create/remove/modify 作前缀

接口类名和方法名映射规则:
1、类名上面映射要避免出现混淆业务比如机具回收 之前已经出现/api/task 映射,不应在出现/api/task/device,可以改为/api/recycle/devicer
2、方法名映射 入过类名映射为 /api/recycle/devicer 方法名不应该再出现devicer  或者devicer 查询或更新操作直接是create、query即可

参数命名:
1.成员变量、局部变量使用驼峰式命名,不允许使用“_”或特殊字符
2.常量、枚举使用“_”分割,且每个单词全大写
2.Boolean类型的变量不能以is开头,否则框架解析会引起序列化错误

注意:
POJO 转换:使用 BeanUtils 转换简单对象,使用 ModelMapper 转换复杂对象
*   建议使用 Lombok `@Data` / `@Getter` / `@Setter` 提高效率
*   VO 面向外部输出,不能带枚举,可以带复杂对象
*   BO 有 枚举,里面可以带 List,带复杂对象
*   DTO 没有枚举,可以带 List
*   DO 和数据库字段一一对应(在mservice与openmoitor中,该对象由dalgen生成,不允许修改)


分层职责:
1.Controller层只做参数的基本校验,业务逻辑下沉到service层,数据请求方式请遵循
2.Controller严禁直接调用DAO层
3.Controller层异常交由框架打印
4.web请求方式应遵循restful风格,
  获取数据:GET
  保存数据:POST
  修改数据:PUT
  删除数据:DELECT
5.Service尽量不要try{}catch(){},如果有必要使用try{}catch(){}的话,捕获的异常“消化掉”,严禁向    上层抛异常
6.Service层,简单的新增、编辑和删除接口不使用事务,查询不使用事务,使用编程式事务尽可       能的缩小事务的粒度,提高接口的性能
7.dao层尽量不要返回多表数据。有必要的场景,自定义一个ListDO模型,接收查询的数据

集合的注意事项:
1.数组转集合
       使用Arrays.asList()把数组转换为集合时,不能使用修改集合相关的方法,它的add/remove/clear会抛                UnsupportedOperationException异常
       此方法体现的是适配器模式,只是转换接口,后台的数据仍是数组
2.推荐使用entrySet遍历Map集合,而不keySet,因为keySet其实是遍历了2次,一次是转为Iterator对象,另一次是从    HashMap中取出key对应的value,entrySet只遍历了一次,如果是jdk8,使用Map.foreach方法
3.Set集合存储的对象,该对象必须重写hashCode和equals方法,因为Set集合存储的是不重复的对象,是依靠hashCode和equals方法来保证的
 

代码格式:

  • 1.左小括号和字符串之间不出现空格;同样,右小括号和字符串之间也不出现空格,如:方法 findUser(name)
  • 2.if/for/while/switch/do 等保留字与括号之间都必须加空格 ,如:if (){}
  • 3.任何二元、三元运算符的左右两边都需要加一个空格,如+,-,*,/,=,&&,||等的前后都加一个空格, 如:String name = "张三"
  • 4.tab缩进采用4个空格 idea中请勿勾选Use tab character,eclipse中,必须勾选insert spaces for tabs
  • 5.注释的双斜线与内容之间有且只有一个空格
  • 6.单行字符数限制不超过120个,超出需换行,换行时遵循如下规则(1)第二行相对第一行缩进4个空格,从第三行开始,不需要继续缩进(2)运算符与下文一起换行(3)方法调用的点符号与下文一起换行(4)方法调用时,多个参数,需要换行时,在逗号后进行(5)在括号前不要换行
  • 7.方法定义参数在定义和传入时,多个参数逗号后必须加空格
  • 8.获取单例对象需保证线程安全
  • 9.线程资源必须由线程池创建,线程不允许Executors创建,必须由ThreadPoolExecutor创建说明:Executors返回的线程池的弊端,FixedThreadPool、SingleThreadPool允许的请求队列长度为Integer.MAX_VALUE可能会堆积大量的请求,造成OOM;CachedThreadPool、ScheduledThreadPool允许创建的线程数量为Integer.MAX_VALUE,可能会创建大量的线程,造成OOM
  • 10.当自动生成的更新sql,注意是否有bigint类型,如果有,则更新的时候注意会默认0将原有的数据覆盖了,此时需要特别注意,已经出现好几次这样的情况了
     

注释规约:
类,类中的方法必须加注释,使用javadoc规范,类注释需要记录创建人、创建时间;IDEA中可以使用Alt+Insert选择生成类注释或方法注释

日志规约:
1.禁止使用System及Throwable.printStackTrace的方式输出日志信息,必须用Logger替代。
2.对于日志的打印,任何情况下都不允许因日志错误导致业务失败。
3.日志的打印要根据具体场景,打印到指定位置,格式如下
private static final Logger logger = LoggerFactory.getLogger(LoggerNamesConstants.DYNAMIC_DEVICEMTN_DEGEST);
4.错误日志必须打印最大级别的错误信息
LoggerUtil.error(e, logger, "devicemtn DevicemtnTaskProcessFrontImpl editProcessSchema error. errorMessage: {0}", e.getMessage());
5.所有错误日志必须输出到common-error.log中。目前线上所有的错误日志会自动生成报告,限期安排人员分析与解决。

异常规约:

【强制】Java 类库中定义的可以通过预检查方式规避的RuntimeException异常不应该通过catch 的方式来处理,比如:NullPointerException,IndexOutOfBoundsException等等。
说明:无法通过预检查的异常除外,比如,在解析字符串形式的数字时,不得不通过catch NumberFormatException来实现。
正例:if (obj != null) {...}
反例:try { obj.method() } catch (NullPointerException e) {…}

【强制】异常不要用来做流程控制,条件控制。
说明:异常设计的初衷是解决程序运行中的各种意外情况,且异常的处理效率比条件判断方式要低很多。

【强制】catch时请分清稳定代码和非稳定代码,稳定代码指的是无论如何不会出错的代码。对于非稳定代码的catch尽可能进行区分异常类型,再做对应的异常处理。
说明:对大段代码进行try-catch,使程序无法根据不同的异常做出正确的应激反应,也不利于定位问题,这是一种不负责任的表现。
正例:用户注册的场景中,如果用户输入非法字符,或用户名称已存在,或输入密码过于简单,在程序上作出分门别类的判断,并提示给用户。

【强制】捕获异常是为了处理它,不要捕获了却什么都不处理而抛弃之,如果不想处理它,请将该异常抛给它的调用者。最外层的业务使用者,必须处理异常,将其转化为用户可以理解的内容。
反例:会员角标问题排查

【强制】事务场景中,抛出异常被catch后,如果需要回滚,一定要手动回滚事务。

【强制】finally块必须对资源对象、流对象进行关闭,有异常也要做try-catch。
说明:如果JDK7,可以使用try-with-resources方式。

【强制】不要在finally块中使用return。
说明:finally块中的return返回后方法结束执行,不会再执行try块中的return语句。

【强制】捕获异常与抛异常,必须是完全匹配,或者捕获异常是抛异常的父类。
说明:如果预期对方抛的是绣球,实际接到的是铅球,就会产生意外情况。

【推荐】方法的返回值可以为null,不强制返回空集合,或者空对象等,必须添加注释充分说明什么情况下会返回null值。
说明:本规约明确防止NPE是调用者的责任。即使被调用方法返回空集合或者空对象,对调用者来说,也并非高枕无忧,必须考虑到远程调用失败,运行时异常等场景返回null的情况。

【推荐】防止NPE,是程序员的基本修养,注意NPE产生的场景:
 1) 返回类型为基本数据类型,return包装数据类型的对象时,自动拆箱有可能产生NPE。
  反例:public int f(){ return Integer对象},如果为null,自动解箱抛NPE。
 2) 数据库的查询结果可能为null。
 3) 集合里的元素即使isNotEmpty,取出的数据元素也可能为null。
 4) 远程调用返回对象时,一律要求空指针判断,防止NPE。
 5) 对于session中获取的数据,建议进行NPE检查,避免空指针。
 6) 级联调用obj.getA().getB().getC();易产生NPE。
  反例:“一拍档客户”的返回值从空对象变成了null,导致线上故障,NPE无小事。

【推荐】对于公司外的http/api开放接口必须使用“错误码”;跨应用间HSF调用优先考虑使用Result方式,封装isSuccess()方法、“错误码”、“错误简短信息”;而应用内部推荐异常抛出。
说明:关于HSF方法返回方式使用Result方式的理由:
 1)中间件平台基本上使用ResultDTO来封装,由于中间件的普及,本身就有标准的引导含义。
 2)使用抛异常返回方式,调用方如果没有捕获到就会产生运行时错误。
 3)如果不加栈信息,只是new自定义异常,加入自己的理解的error message,对于调用端解决问题的帮助不会太多。如果加了栈信息,在频繁调用出错的情况下,数据序列化和传输的性能损耗也是问题。

【推荐】定义时区分unchecked / checked 异常,避免直接使用RuntimeException抛出,更不允许抛出Exception或者Throwable,应使用有业务含义的自定义异常。推荐业界或者集团已定义过的自定义异常,如:DAOException / ServiceException等。

【参考】避免出现重复的代码(Don’t Repeat Yourself),即DRY原则。
说明:随意复制和粘贴代码,必然会导致代码的重复,在以后需要修改时,需要修改所有的副本,容易遗漏。必要时抽取共性方法,或者抽象公共类,甚至是共用模块。
正例:一个类中有多个public方法,都需要进行数行相同的参数校验操作,这个时候请抽取:

private boolean checkParam(DTO dto) {
    ...
}

 

  • 8
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值