Java函数式编程(二)(二)

2014-11-24 01:25:17 · 作者: · 浏览: 1
现并发

一个大型应用快到了发布里程碑的时候,突然一个严重的性能问题浮出水面。团队迅速定位出性能瓶颈点是出在一个处理海量数据的庞大的模块里。团队中有人建议说如果能充分发掘多核的优势的话可以提高系统性能。

不过如果这个庞大的模块是用老的Java风格写的话,刚才这个建议带来的喜悦很快就破灭了。

团队很快意识到要这把这个庞然大物从串行执行改成并行需要费很大的精力,增加了额外的复杂度,还容易引起多线程相关的BUG。难道没有一种提高性能的更好方式吗?

有没有可能串行和并行的代码都是一样的,不管选择串行还是并行执行,就像按一下开关,表明一下想法就可以了?

听起来好像只有纳尼亚里面能这样,不过如果我们完全用函数式进行开发的话,这一切都将成为现实。内置的迭代器和函数式风格将扫清通往并行化的最后一道障碍。JDK的设计使得串行和并行执行的切换只需要一点不起眼的代码改动就可以实现,我们将会在145页《完成并行化的飞跃》中提到。

讲故事

在业务需求变成代码实现的过程中会丢失大量的东西。丢失的越多,出错的可能性和管理的成本就越高。

如果代码看起来就跟描述需求一样,将会很方便阅读,和需求人员讨论也变的更简单,也更容易满足他们的需求。

比如你听到产品经理在说,”拿到所有股票的价格,找出价格大于500块的,计算出能分红的资产总和”。使用Java提供的新设施,可以这么写:

tickers.map(StockUtil::getprice).filter(StockUtil::priceIsLessThan500).sum() 
这个转化过程几乎是无损的,因为基本上也没什么要转化的。这是函数式在发挥作用,在本书中还会看到更多这样的例子,尤其是第8章, 使用lambda表达式来构建程序,137页。
关注隔离

系统开发中,核心业务和它所需要的细粒度逻辑通常需要进行隔离。比如说,一个订单处理系统想要对不同的交易来源使用不同的计税策略。把计税和其余的处理逻辑进行隔离会使得代码重用性和扩展性更高。在面向对象编程中我们把这个称之为关注隔离,通常用策略模式来解决这个问题。解决方法一般就是创建一些接口和实现类。

我们可以用更少的代码来完成同样的效果。我们还可以快速尝试自己的产品思路,而不用上来就得搞出一堆代码,停滞不前。我们将在63页的,使用lambda表达式进行关注隔离中进一步探讨如果通过轻量级函数来创建这种模式以及进行关注隔离。

惰性求值

开发企业级应用时,我们可能会与WEB服务进行交互,调用数据库,处理XML等等。我们要执行的操作有很多,不过并不是所有时候都全部需要。避免某些操作或者至少延迟一些暂时不需要的操作是提高性能或者减少程序启动,响应时间的一个最简单的方式。

这只是个小事,但用纯OOP的方式来实现还需要费一番工夫。为了延迟一些重量级对象的初始化,我们要处理各种对象引用 ,检查空指针等等。不过,如果使用了新的Optinal类和它提供的一些函数式风格的API,这个过程将变得很简单,代码也更清晰明了,我们会在105页的延迟初始化中讨论这个。

提高可测性

代码的处理逻辑越少,容易被改错的地方当然也越少。一般来说函数式的代码比较容易修改,测试起来也较简单。

另外,就像第4章,使用lambda表达式进行设计和第5章资源的使用中那样,lambda表达式可以作为一种轻量级的mock对象,让异常测试变得更清晰易懂。lambda表达式还可以作为一个很好的测试辅助工具。很多常见的测试用例都可以接受并处理lambda表达式。这样写的测试用例能够抓住需要回归测试的功能的本质。同时,需要测试的各种实现都可以通过传入不同的lambda表达式来完成。

JDK自己的自动化测试用例也是lambda表达式的一个很好的应用范例——想了解更多的话可以看下OpenJDK仓库里的源代码。通过这些测试程序可以看到lambda表达式是如何将测试用例的关键行为进行参数化;比如,它们是这样构建测试程序的,“新建一个结果的容器”,然后“对一些参数化的后置条件进行检查”。

我们已经看到,函数式编程不仅能让我们写出高质量的代码,还能优雅的解决开发过程中的各种难题。这就是说,开发程序将变得更快更简单,出错也更少——只要你能遵守我们后面将要介绍到的几条准则。

未完待续,后续文章请继续关注deepinmind。

原创文章转载请注明出处:Java译站