函数式编程(FP)的目的是避免重新分配变量,避免可变的数据结构,避免状态并全程支持函数。 如果将功能性技术应用于日常Java代码,我们可以从FP中学到什么?

在这个名为“ Functional Java by Example”的系列文章中,我将分8步重构现有的一段代码,以查看是否可以用Java达到Functional Nirvana

我对Haskell或F#等“真正的”功能语言没有太多经验,但是我希望在每篇文章中以示例方式演示将这些实践中的一些应用于每天的Java代码意味着什么。

希望最后您获得了一些见识,并且知道可以选择一些有益于您自己的代码库的技术。

这些都是这些部分:

  • 第1部分–从命令式到声明式
  • 第2部分–命名事物
  • 第3部分–不要使用异常来控制流程
  • 第4部分–首选不变性
  • 第5部分–将I / O移到外部
  • 第6部分–用作参数
  • 第7部分–将失败也视为数据
  • 第8部分–更多纯函数

我将在每篇文章发表时更新链接。 如果您通过内容联合组织来阅读本文,请查看我博客上的原始文章。

每次代码也被推送到这个GitHub项目 。

免责声明:代码是用Apache的Groovy中 ,主要是为简洁,所以我不必键入的东西(你知道:打字),其中不要紧的例子。 中学,这门语言只是让我开心。

为什么要关心函数式编程(FP)?

如果您不是在时髦的实时流数据事件处理框架上执行Haskell,F#或Scala,则最好打包。 这些天,甚至JavaScript的人都在围绕您的方法旋转函数-这种语言已经存在了一段时间。

那里有很多文章和视频,使您相信,如果这些天跳到功能性潮流上,那您将被旧的OOP束缚束缚住,坦白地说,它们在几年之内就已经过时了。

好吧,我在这里告诉您这不是完全正确的,但是FP 确实有一些前提,例如可读性,可测试性和可维护性 ,我们也在我们的(企业)Java代码中力求实现的值正确吗?

在阅读本文时,多年以来,您可能已经对FP是前进还是后退或2017-2018年无进展发表了相同的直率观点,您只是愿意接受新想法

通过学习FP,您可以提高每种语言的技能。

确定自己是什么,你可以从中学到如何自己编程可以从中受益。

如果您能胜任这项任务,那么让我们从...开始

现有的一些代码

关于示例代码的一句话:为这样的博客提供人为的示例是非常棘手的:它应该足够容易吸引广泛的受众,应该足够简单,无需太多上下文就可以理解,但仍然足够有趣,可以产生理想的学习效果。

展望未来,本系列的每一期都将在前一期的基础上进行。 下面是我们将作为起点的代码。

因此,戴上眼镜,看看您是否熟悉下面的编码样式。

class FeedHandler {Webservice webserviceDocumentDb documentDbvoid handle(List<Doc> changes) {for (int i = 0; i < changes.size(); i++) {def doc = changes[i]if (doc.type == 'important') {try {def resource = webservice.create(doc)doc.apiId = resource.iddoc.status = 'processed'} catch (e) {doc.status = 'failed'doc.error = e.message}documentDb.update(doc)}}}
}
  • 这是某种FeedHandler
  • 它具有两个属性,一些Webservice类和DocumentDb类。
  • 有一个handle方法可以对Doc对象列表进行处理。 文件?

尝试弄清楚这里发生了什么

..

..

..

做完了吗

读这样的东西有时会使您感到自己像一个解析器。

扫描类名称( FeedHandler? )和一个方法( void handle )可以使您感到有些FeedHandler? ,从而使您感到FeedHandler?

但是,弄清楚handle方法中确切地“处理”了什么要困难得多。

  • 那里有一个for-loop -但是到底是在迭代什么? 多少次?
  • 调用此变量webservice ,返回称为resource
  • 如果webservice成功返回,则正在迭代的doc (文档?)将更新为状态。
  • 似乎webservice还可以抛出一个Exception ,它被捕获和文档与其他状态更新。
  • 最终,该文档被此documentDb实例“更新”。 看起来像一个数据库。
  • 等等,这仅适用于“重要”文档 -在执行上述所有操作之前,首先检查doc.type

也许,您听说过以下短语:

读取的代码多于编写的代码。

看看这块美丽:

for (int i = 0; i < changes.size(); i++) {

上面的代码以命令式的方式编写,这意味着操作状态和行为的具体语句被明确地写出。

  • 用零初始化一个int i
  • int i小于changes列表的大小时循环
  • 每次迭代以1递增int i

以这种命令式 (过程)编码方式(大多数主流语言,包括Java,C ++,C#等面向对象编程(OOP)语言,都被设计为主要支持),开发人员编写了计算机所需的确切语句。执行以完成特定任务。

一些非常命令性 (过程性)代码的信号:

  1. 专注于如何执行任务
  2. 状态更改和执行顺序很重要
  3. 许多循环和条件

该代码明确地集中在“如何”上,这使得“什么”难以确定。

专注于什么

就像本文的标题一样,我们的第一步是从命令式的编码和重构方式转变为更具声明性的样式-FP是一种形式。

这个循环最困扰我。

这是代码的新版本。

class FeedHandler {Webservice webserviceDocumentDb documentDbvoid handle(List<Doc> changes) {// for (int i = 0; i < changes.size(); i++) {//    def doc = changes[i]changes.findAll { doc -> doc.type == 'important' }.each { doc ->try {def resource = webservice.create(doc)doc.apiId = resource.iddoc.status = 'processed'} catch (e) {doc.status = 'failed'doc.error = e.message}documentDb.update(doc)}}
}

有什么变化?

  • if (doc.type == 'important')部分已替换为findAll { doc -&gt; doc.type == 'important' } if (doc.type == 'important') findAll { doc -&gt; doc.type == 'important' } findAll { doc -&gt; doc.type == 'important' }再次涉及文档集合本身- 意思是“查找所有重要的文档,并仅返回那些重要文档的新集合”
  • 强制性的for-loop (带有中间的i变量)已由文档集合本身上的声明性的each方法所代替- 意思是“为列表中的每个文档执行一段代码,我不在乎您如何执行” &#55357;&#56898;

不用担心eachfindAll :这些方法是Groovy所添加的,我将它们与Java在同一代码库中愉快地一起使用,添加到任何Collection中,例如Set,List,Map。 Vanilla Java 8具有等效的机制,例如forEach可以更声明性地迭代集合。

导致可读软件的原因是:

描述“什么”而不是“如何”

如果我以更具功能性的风格编写代码,就可以轻松地看到发生了什么,这可以节省我的时间 (因为是的,我90%的时间都在读取代码而不是编写代码),并且这样编写代码不容易出错 ,因为更少的行会减少隐藏错误的机会。

现在就这样

在第2部分中,我们将正确命名事物 ,为更多功能的编程铺平道路,例如在本系列的后续版本中,“ Either”或“ Try”。

翻译自: https://www.javacodegeeks.com/2017/11/functional-java-example-part-1-imperative-declarative.html

功能Java示例 第1部分–从命令式到声明式相关推荐

  1. java 函数式编程 示例_功能Java示例 第1部分–从命令式到声明式

    java 函数式编程 示例 功能编程(FP)的目的是避免重新分配变量,避免可变的数据结构,避免状态并全程支持函数. 如果将功能性技术应用于日常Java代码,我们可以从FP中学到什么? 在这个名为&qu ...

  2. java 函数式编程 示例_功能Java示例 第8部分–更多纯函数

    java 函数式编程 示例 这是第8部分,该系列的最后一部分称为"示例功能Java". 我在本系列的每个部分中开发的示例是某种"提要处理程序",用于处理文档. ...

  3. 大数据 java 代码示例_功能Java示例 第7部分–将失败也视为数据

    大数据 java 代码示例 这是称为" Functional Java by Example"的系列文章的第7部分. 我在本系列的每个部分中开发的示例是某种"提要处理程序 ...

  4. 对象作为参数示例java_功能Java示例 第6部分–用作参数

    对象作为参数示例java 这是称为" Functional Java by Example"的系列文章的第6部分. 我在本系列的每个部分中开发的示例是某种"提要处理程序& ...

  5. java 示例_功能Java示例 第5部分–将I / O移到外部

    java 示例 这是称为" Functional Java by Example"的系列文章的第5部分. 在上一部分中,我们停止了对文档的变异,并返回了数据的副本. 现在,我们需要 ...

  6. java 示例_功能Java示例 第4部分–首选不变性

    java 示例 这是称为" Functional Java by Example"的系列文章的第4部分. 在上一部分中,我们讨论了一些副作用,并且我想进一步详细说明如何通过将不可变 ...

  7. java 示例_功能Java示例 第3部分–不要使用异常来控制流程

    java 示例 这是称为" Functional Java by Example"的系列文章的第3部分. 我在本系列的每个部分中开发的示例是某种"提要处理程序" ...

  8. java 示例_功能Java示例 第2部分–讲故事

    java 示例 这是称为" Functional Java by Example"的系列文章的第2部分. 我在本系列的每个部分中开发的示例是某种"提要处理程序" ...

  9. 功能Java示例 第8部分–更多纯函数

    这是第8部分,该系列的最后一部分称为" Functional Java by Example". 我在本系列的每个部分中发展的示例是某种"提要处理程序",用于处 ...

最新文章

  1. 如何复制代码到剪贴板?JS/FLASH...
  2. codeforces 126B Password(哈希)
  3. Es-nested嵌入式属性
  4. vb.net2019- 调用 opencv
  5. 算法设计与分析(第四周)同时选最大和最小 优化解法
  6. 【Python自动化运维之路Day2】
  7. android p wifi一直在扫描_在Android上的每次WiFi扫描之间我应该使用什么时间间隔?...
  8. c/c++ 模板与STL小例子系列一 自建Array数组
  9. 献给新一代人工智能后浪——《后丹》
  10. asp.net mvc中的后台验证
  11. 有关Linux下的一些配置
  12. python一对一视频教学-使用Python的Tornado框架实现一个一对一聊天的程序
  13. 美国当地时间4月17日中国概念股收盘行情
  14. 由DispatcherServlet看spring mvc请求处理过程
  15. python 3d游戏脚本_3ds Max python脚本编写及部分API介绍
  16. catia锥齿轮画法_CATIA自动生成锥齿轮模型的宏程序应用方法
  17. java 使用POI 导出 Excel 画斜线
  18. 【Unity】基于顶点色的海边波浪效果(适用移动端)
  19. 交换机端口与MAC绑定
  20. java 微信隐藏右上角_不懂这11个隐藏技巧,别说你会用微信

热门文章

  1. 面试-线程池的成长之路
  2. tomcat与apache的面试题
  3. Spring Cloud是什么,和Dubbo对比呢?
  4. admiration音标是什么_英语admiration的意思解释|读音发音|相关词语_英语词典_词林在线词典...
  5. controller属于哪一层_别急着换5G,4G手机同样值得考虑!哪几款安卓手机称得上4G机皇?...
  6. like左匹配索引失效_Mysql索引失效的情况
  7. (转) SpringBoot接入两套kafka集群
  8. 控制语句(if-else+循环+switch)汇编规则
  9. ssrs 基于表达式显示_基于表达式的访问控制
  10. jpa root.join_JPA 2.1和Java EE 7中的JPQL增强功能(第1部分– JOIN ON)