今天根据具体实例谈一个代码风格的问题。
在一个群里,朋友 A 发来一段代码:
public void convertData(Long companyId) {
try {
convertOperator(companyId);
convertDict(companyId);
converSupplier(companyId);
converCustomer(companyId);
convertEnum(companyId);
convertMenu(companyId, LanguageEnum.defaultValue());
} catch (Exception e) {
log.error("数据label转换异常", e);
} finally {
clearTheadLocal();
}
}
他问,如果一个方法报错,不影响后面的方法执行,有什么好办法吗。
朋友 B 看到后说,每个方法里面单独 try catch
呢。
我看到后回了一句 你们函数式思维有待加强。
朋友 A 回复朋友 B 说,我的解决方案和你一样,但是我不想写这么挫的代码,就过来问问你们。
接着我发了一段下面的代码到群里:
List<Consumer<Long>> consumers = Arrays.asList(
this::convertOperator,
this::convertDict,
// 自己补后面的,
id -> this.convertMenu(id, LanguageEnum.defaultValue())
);
boolean result = consumers.stream().reduce(true, (a, b) -> {
try {
b.accept(companyId);
return a;
} catch (Exception e) {
return false;
}
}, Boolean::logicalAnd);
if (!result) {
log.error("数据label转换异常", e);
}
clearTheadLocal();
如果你能看明白并且习惯于这种编码风格就不用往下读了。下面我会再唠叨几句。
1关于函数式风格
我们写代码的目的通常是为了处理数据,而编码的风格一般是针对数据,写一些处理数据的函数,然后将数据作为参数依次调用这些函数。
这种编码风格的重心是 面向数据,函数只是处理数据的工具。
而我上面说的 函数式编程,它的重心是 面向函数,数据只是函数运行时依赖的参数。
这种重心的转变会造成完全迥异的编码风格。
函数式编程的一个特点,是把一个需求分成若干小的函数块。函数执行完,需求也就完成了。
切记,它的重点是整个过程是面向函数的。
结合上面朋友问的问题来说,对于数据 companyId
,它要执行很多的 convertXX()
函数。单个函数的失败不会影响后续函数的执行,当所有函数执行结束后,如果有失败的,则打印一条日志,最终做一些清理工作。
以上,我们可以做如下封装:
-
一组 convertXX()
函数。每个函数都可能抛异常,为了不影响后续函数的执行,我们将函数的成功执行返回true
,失败返回false
。 -
将这组函数的最终执行结果进行 逻辑与
操作,判断是否全部成功,如果不是,则打印日志。 -
做一些清理工作。
最终的实现:
我们可以把这组 convertXX()
函数打包成一个 Stream
流,依次执行它们并将执行结果通过 reduce()
操作转换成最终的值,最后再做日志和清理工作。
根据以上分析,我们甚至能给出更加函数式的代码(相对于上面发到群里的而言。同时为了方便解释,做了特殊的格式化):
public boolean convertData(Long companyId) {
return Stream.<Consumer<Long>>of( // 一组函数
this::convertOperator,
this::convertDict,
// 自己补后面的,
// 把多参数的函数转换成单参数的
id -> this.convertMenu(id, LanguageEnum.defaultValue())
).collect(collectingAndThen(
reducing(
true,
(c) -> { // 依次执行单个函数,成功返回 true;失败 false
try {
c.accept(companyId);
return true;
} catch (Exception e) {
// todo log e
return false;
}
},
Boolean::logicalAnd // 汇总所有函数的执行结果
),
r -> { // 所有函数执行完成后,执行日志和清理
if (!r) {
log.error("数据label转换异常");
}
clearTheadLocal();
return r;
}));
}
其实,类似的编码风格我在之前的文章中也有提到:编码技巧:pipe 思想。
怎么样,有收获吗?
原文始发于微信公众号(背井):重构你的代码风格 —— 从帮一个朋友改进代码说起
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/246646.html