一段业务代码的重构过程

    最近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

微信公众号:

           

转载于:https://my.oschina.net/saaavsaaa/blog/1036682

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值