最近review代码,然后带着程序员重构了一段,发现语法方面居然花了不少时间,然后感觉这种情况还是挺典型的,于是记录一下,下次就不用从语法教起了。
首先是review的时候看到了这样一段代码(命名都被我改掉了,也只改了命名):
String list = "";
if ("1".equals(inputPara.getA())) {
if (0 == Optional.ofNullable(bo).map(account -> account.getA()).orElse(0)) {
list = "A,";
}
}
if ("1".equals(inputPara.getAb())) {
if (0 == Optional.ofNullable(bo).map(account -> account.getAb()).orElse(0)) {
list = list + "AB,";
}
}
if ("1".equals(inputPara.getAbc())) {
if (0 == Optional.ofNullable(bo).map(account -> account.getAbc()).orElse(0)) {
list = list + "ABC,";
}
}
if ("1".equals(inputPara.getAbca())) {
if (0 == Optional.ofNullable(bo).map(account -> account.getAbca()).orElse(0)) {
list = list + "ABCA,";
}
}
if ("1".equals(inputPara.getAbcab())) {
if (0 == Optional.ofNullable(bo).map(account -> account.getAbcab()).orElse(0)) {
list = list + "ABCAB,";
}
}
list = list.trim().substring(0, list.lastIndexOf(","));
看到这段代码的时候,就很不舒服,几个判断里面的逻辑是一模一样的,没想到还发现下面两段代码,整个人瞬间就不好了。。。
String list = "";
if ("0".equals(inputPara.getA())) {
if (1 == Optional.ofNullable(bo).map(b -> b.getA()).orElse(0)) {
list = "A,";
bo.setA(0);
}
}
if ("0".equals(inputPara.getAb())) {
if (1 == Optional.ofNullable(bo).map(b -> b.getAb()).orElse(0)) {
list = list + "AB,";
bo.setAb(0);
}
}
if ("0".equals(inputPara.getAbc())) {
if (1 == Optional.ofNullable(bo).map(b -> b.getAbc()).orElse(0)) {
list = list + "ABC,";
bo.setAbc(0);
}
}
if ("0".equals(inputPara.getAbca())) {
if (1 == Optional.ofNullable(bo).map(b -> b.getAbca()).orElse(0)) {
list = list + "ABCA,";
bo.setAbca(0);
}
}
if ("0".equals(inputPara.getAbcab())) {
if (1 == Optional.ofNullable(bo).map(b -> b.getAbcab()).orElse(0)) {
list = list + "ABCAB,";
bo.setAbcab(0);
}
}
list = list.trim().substring(0, list.lastIndexOf(","));
String[] slist = callback.split(",");
for (String str : slist) {
if ("A".equals(str)) {
bo.setA(1);
} else if ("AB".equals(str)) {
bo.setAb(1);
} else if ("ABC".equals(str)) {
bo.setAbc(1);
} else if ("ABCA".equals(str)) {
bo.setAbca(1);
} else if ("ABCAB".equals(str)) {
bo.setAbcab(1);
} else {
continue;
}
}
前两段代码看上去格式完全没有变化,判断逻辑排除掉“0”和“1”就没啥区别;然后就是常量字符串写了三次,其实用的是一个玩意;还有个小问题Optional用的多余明明只比结果就好,还要转成0再比。第三段代码还有个问题,就是循环内部的判断,判断“A”的时候只需要一次,但是判断“ABCAB”的时候需要5次,同时还有人为耦合5次判断的嫌疑。
先来前两段代码,首先业务逻辑第一段是遇到“0”判断状态是否是“0”,不是就把状态改为1,同时记录与状态相关属性对应的字符串,第二段是遇到“1”改“0”其它与第一段一样。第一件事,先不管逻辑,先把常量字符串弄出来,好多地方用不能一个地方写一个。
enum BizEnum {
a("A"),
ab("AB"),
abc("ABC"),
abca("ABCA"),
abcab("ABCAB");
private String value;
BizEnum(String value){
this.value = value;
}
public String getValue() {
return value;
}
}
然后就是内部的逻辑了,前两段代码的外层是判断参数是否符合逻辑的,先不管,先看每个判断的内部,符合了判断逻辑后的处理方式是完全相同的,先合一下,这里不一样的很明显只有字段反射就好了,而字段是与常量一一对应的:
if(Integer.valueOf(0).equals(BeanUtil.get(b, attribute))){
String grant = BizEnum.valueOf(attribute).getValue();
return grant;
}
return "";
if(Integer.valueOf(1).equals(BeanUtil.get(b, attribute))){
BeanUtil.set(b, attribute, 0);
String grant = BizEnum.valueOf(attribute).getValue();
return grant;
}
return "";
这里“1”、“0”其实按说可以接参数,再不济也应该是常量,不过一是实际逻辑就是这样的,把业务逻辑固化下来也没啥坏处,而且也没有别的需要传参的理由,至于常量...,反正代码不是我改的(甩锅),只要能过得去也就算了,也没必要管那么细。
判断里面处理完了,回头看外面的判断,其实都是一样一样的,合成一个就完了:
private String changeValueLogic(InputPara inputPara, BO bo, String change, ChangeBO changeBO){
StringBuilder stringBuilder = new StringBuilder();
for (BizEnum aEnum : BizEnum.values()){
String string = (String) BeanUtil.get(inputPara, aEnum.name());
if(change.equals(string)){
String grant = changeBO.updateBO(bo, aEnum.name());
if(StringUtils.isNotEmpty(grant)){
stringBuilder.append(grant);
stringBuilder.append(",");
}
}
}
if(stringBuilder.length() == 0){
return "";
}
String result = stringBuilder.deleteCharAt(stringBuilder.lastIndexOf(",")).toString();
return result;
}
参数有点多,不过还是过得去就算了,判断逻辑就是根据业务对象状态和对应枚举,取出结果判断,符合就改掉状态,并且记录下常量,这里会看到有一个ChangeBo,这是一个接口:
interface ChangeBO{
String updateBO(BO bo, String attribute);
}
用这个接口的原因是毕竟只有外面判断一样,内部的逻辑还是有区别的,所以就要将内部判断的逻辑传进来,看一下开头那两段代码的优化结果就知道了:
public void createBiz(InputPara inputPara, BO bo) {
ChangeBO changeBO = (b, attribute) -> {
if(Integer.valueOf(0).equals(BeanUtil.get(b, attribute))){
String grant = BizEnum.valueOf(attribute).getValue();
return grant;
}
return "";
};
String result = this.changeValueLogic(inputPara, bo, "1", changeBO);
System.out.println(result);
}
public void updateBiz(InputPara inputPara, BO bo) {
ChangeBO changeBO = (b, attribute) -> {
if(Integer.valueOf(1).equals(BeanUtil.get(b, attribute))){
BeanUtil.set(b, attribute, 0);
String grant = BizEnum.valueOf(attribute).getValue();
return grant;
}
return "";
};
String result = this.changeValueLogic(inputPara, bo, "0", changeBO);
System.out.println(result);
}
这样这两个方法内部的逻辑就内聚了,一个方法就只干一件事了,而且再有并列的状态增加进这个BO,只需要增加对应的枚举项,这里的代码都不需要动了。
接下来就是第三段代码,其实第三段代码非常契合状态模式,直接照着套就好了,我也不多说了:
private void update(String callback, BO bo) {
Map<String, Consumer<BO>> map = this.getBs();
String[] sList = callback.split(",");
for (String str : sList){
Consumer<BO> hkcgAccountConsumer = map.get(str);
if(null == hkcgAccountConsumer){
continue;
}
hkcgAccountConsumer.accept(bo);
}
}
private Map getBs(){
Map<String, Consumer<BO>> map = new HashMap<>();
map.put(BizEnum.a.getValue(), (b) -> b.setA(1));
map.put(BizEnum.ab.getValue(), (b) -> b.setAb(1));
map.put(BizEnum.abc.getValue(), (b) -> b.setAbc(1));
map.put(BizEnum.abca.getValue(), (b) -> b.setAbca(1));
map.put(BizEnum.abcab.getValue(), (b) -> b.setAbcab(1));
return map;
}
==========================================================
咱最近用的github:https://github.com/saaavsaaa
微信公众号: