最近开始重构,发现重构真的是即恶心又爽的一件事。不断的发现问题,解决问题。
个人觉得后端重构要注意以下的几个点:
最重要的一点:新启一套接口和方法去重构,同时保证两套系统的可用性。
(1)类似我们原有代码,对于定义定向id,有的叫targetingId,有的叫mid。可理解性差。不同get接口应该传的是一个同一个值,却命名不一致。
(2)还有的用户id,都是advertiserId,有的是Long类型,有的是String类型,后端service统一接收的是Long,在controller层又通过这种无效代码转换成Long。
Long aid =Long.parseLong(advertiserId);
首先我们的广告系统业务逻辑及其复杂。重构除了把代码优化外,文档化也是很重要的。
很多系统没有有关特殊逻辑的梳理,导致后面排查外网问题,需求评审时候要重新梳理一遍逻辑。
还有可能修改一个点不小心影响到其他点,然后导致踩坑。
本次使用了swagger文档工具。还是蛮好玩的。
作为复杂逻辑的应用层系统,会调用多方的接口。
在service层级,要尽量保证一个方法只实现一个功能,不要把一堆功能组装在一起,一个方法调用了5,6个其他服务方的接口,很难定位问题。
单元测试补齐也是很重要的一点。
基于serviceImpl层级,要保证每一个方法的单元测试补齐。
一方面实现在开发过程中实现“测试驱动开发”,先写单元测试,再开发代码。
提交代码到SVN和Git之前,先跑单元测试,单测跑成功之后才可以提交代码。
扫描发现有三个层级的问题:
(1)Blocker(崩溃):
1》在使用正则表达式时,利用好其他、预编译功能,可以有效加快正则匹配速度:
原始代码类似如下:
public static String replaceBlank(String str) {
String dest = "";
if (str!=null) {
Pattern p = Pattern.compile("|\t");
Matcher m = p.matcher(str);
dest = m.replaceAll("");
}
return dest;
}
修改成:
private final static Pattern pattern = Pattern.compile("\t");
public static String replaceBlank(String str) {
String dest = "";
if (str!=null) {
dest = pattern.matcher(str).replaceAll("");
}
return dest;
}
2》if...else...没有加大括号,没必要举具体的demo,标准的格式应该是这样的。
if (条件) {
//do something
}
else {
//do something
}
3》 所有包装类对象之间值的比较,全部使用equals方法比较:
之前代码中有的uid这种使用了Long,然后使用了==去比较,这样是不合理的,将==改成了equals。
4》所有的覆写方法,必须加@Override注解:
这个比较好理解,类似于有的aaaServiceImpl类实现了aaaService接口,但是在Impl中实现接口的部分方法没有加@Override注解,补充一下就ok了。
5》避免通过一个类的对象饮用访问此类的静态变量或静态方法,无谓增加编译器解析成本,直接使用类名来访问即可。
静态方法可以直接使用类名访问。具体可以见我的博客:《Static和final关键字解析》
(2)Critical(严重):
1》常量命名应该全部大写,单词间用下划线隔开,力求语义表达完整清楚,不要嫌名字长。
类似于USER_NAME一定要大写。
private static final String USER_NAME = "userName";
2》不能使用过时的类或方法。
类似于我们的一个方法reject已经不用了,改用withError。修改掉就不会有这种错误了。
3》Object的equals方法容易抛空指针异常,应使用常量或确定有值的对象来调用equals。
正确用法应该是
“aaa”.equals(userName)
而不是:
(userName).equals("aaa");
(3)Major(重要)
1》中括号是数组类型的一部分,数组定义如下:String[] args
我们代码里定义了一个数组:Field ff[]=XXXX;
应该变为 Field[] ff = XXX;
2》及时清理不再使用的代码段或配置信息。
说明:对于垃圾代码或过时配置,坚决清理干净,避免程序过度臃肿,代码冗余。
一般系统在经过测试,后续增加业务需求,很多人接手之后,会出现很多垃圾代码,有些代码被注释掉了,想着以后在用。
把这部分代码趁着重构,整体删除掉。
3》不允许任何魔法值(即未经定义的常量)直接出现在代码中。
有些判断里面可能直接判断if(("test").equals(a)){}
应该做法是
private static final String AAA = "test";
if(AAA.equals("a")){}
4》集合初始化时,指定集合初始值大小。
说明:HashMap使用如下构造方法进行初始化,如果暂时无法确定集合大小,那么指定默认值(16)即可。
5》所有的类都必须添加创建者信息.
6》事务场景中,抛出异常被catch后,如果需要回滚,一定要手动回滚事务。
7》类、类属性、类方法的注释必须使用javadoc规范,使用/**内容*/格式,不得使用//xxx方式和/*xxx*/方式。 说明:在IDE编辑窗口中,javadoc方式会提示相关注释,生成javadoc可以正确输出相应注释;在IDE中,工程调用方法时,不进入方法即可悬浮提示方法、参数、返回值的意义,提高阅读效率。
8》所有的抽象方法(包括接口中的方法)必须要用javadoc注释、除了返回值、参数、异常说明外,还必须指出该方法做什么事情,实现什么功能。