avatar

一次改造if-else的经历

项目经过不断的迭代,业务流程中的一个关键接口方法行数已经达到了大几百行快一千行了,其中充斥着大量if-else的分支判断语句,是时候重新梳理重构一把了!

讲一下代码的相关背景:这次要改造的是一个用于计算某款产品业务额度的接口。前端会通过一个交易码发起请求,请求在经过网关时被映射到该业务接口上,由这个接口负责处理相应的业务逻辑。由于该项业务入口区分了许许多多个不同的渠道,而且每个渠道对应有自己背后的计算模型和参数,因此随着时间的推移和产品的迭代,这个作为总入口的接口自然而然地被加上了许多的 if-else 语句用来区分不同的渠道从而计算得出不同的业务额度。

如此一来,这个接口对应的代码就变得相当冗长,方法行数达到大几百行,有时候要想找到对应的代码逻辑处做下修改也不容易,既不方便阅读也不方便维护。于是某天一个比较空闲的下午,就想着干脆把他重构一下好了。

像这种多种渠道多种计算规则的业务,一般我们会想到使用设计模式中的策略模式来重构它。这样做的确是可以。但是策略模式也有一个它自己的不足,就是随着往后渠道的增多,其对应的策略的实现类也会越来越多。这次我们就做个简单重构,也不大动干戈,力求做到不改动原有的代码逻辑的同时又把if-else语句干掉,使其代码结构更加清晰直观。

废话也说得够多了,下面就直接上我们的思路示例代码吧↓↓↓

java
1
2
3
4
5
6
7
8
9
10
11
private final Map<String, Function<BizParam, BizResult>> dispatcher = new HashMap<>(16);

@PostConstruct
void init() {
dispatcher.put(KEY_BIZ_A, Biz::doBizA);
dispatcher.put(KEY_BIZ_B, Biz::doBizB);
...
...
dispatcher.put(KEY_BIZ_G, Biz::doBizG);
dispatcher.put(KEY_DEFAULT, Biz::doDefault);
}

首先我们构造一个业务分发容器,并且在使用该容器的上下文初始化完成后初始化这个容器,为每一项渠道业务建立一个对应的 KEY , 将之前通过 if-else 来区分的分支代码的不同部分抽取出来成为独立的方法,可以考虑放到一个单独的业务类里边去,并与这个 KEY 一一对应上。完成上述重新封装后,接下来我们在原来的大几百行的方法里面就可以把那些讨厌的 if-else 统统干掉,现在只需要写上两行代码就可以了。

java
1
2
3
4
public BizResult doCreditCalculateBiz(BizParam in) {
String bizKey = getBizKey(in);
BizResult result = dispatcher.get(bizKey).apply(in);
}

首先我们通过入参用一个 getBizKey() 的方法来获取我们放入 dispathcer 这个业务分发容器中的 key, 在通过 key 拿到我们要执行的业务方法。 这里我们用的是Java 8中提供的
Function<T, R> 这个类,调用其 apply() 函数,它接受类定义上泛型的第一个参数作为入参,第二个泛型参数作为函数执行的返回结果。利用这个类的这个方法我们便可以根据不同的业务渠道入参,执行不同的业务方法,从而达到简化代码的目的。同时由于我们将所有的渠道和对应的业务方法都存到了容器中,也极大的方便了我们阅读代码,只要在容器处看一眼,便能很快找到对应的处理方法。后续如果增删也很方便,对于代码的维护性也有一定的提升。

上述就是这次改造的基本思路了。写在这里一方面是作为记录,另一方面也是提供一种实践方式。如果不想大改代码的话,采用这种方式去掉过多的 if-else 语句,或许也是个不错的选择呢!

文章作者: JanGin
文章链接: http://jangin.github.io/2020/08/05/refactor-code-with-Function-in-java8/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 JanGin's BLOG

评论