这是称为“ Functional Java by Example”的系列文章的第5部分。

在上一部分中,我们停止了对文档的变异,并返回了数据的副本。 现在,我们需要移走一些I / O。

如果您是第一次来,最好是从头开始阅读。 它有助于了解我们从何处开始以及如何在整个系列中继续前进。

这些都是这些部分:

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

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

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

将I / O移到外面

还记得我们以前留下的东西吗?

class FeedHandler {Webservice webserviceDocumentDb documentDbvoid handle(List<Doc> changes) {changes.findAll { doc -> isImportant(doc) }.each { doc ->createResource(doc).thenAccept { resource ->documentDb.update(setToProcessed(doc, resource))}.exceptionally { e ->documentDb.update(setToFailed(doc, e))}}}private CompletableFuture<Resource> createResource(doc) {webservice.create(doc)}private boolean isImportant(doc) {doc.type == 'important'}private Doc setToProcessed(doc, resource) {doc.copyWith(status: 'processed',apiId: resource.id)}private Doc setToFailed(doc, e) {doc.copyWith(status: 'failed',error: e.message)}}

我在本系列的每个部分中发展的示例是某种“提要处理程序”,用于处理文档。

处理效果如何?

  1. 一份或多份文件进来
  2. 如果文档“很重要”,则将其保存到Web服务API中,该API将为其创建并返回资源
  3. 如果成功,则将文档标记为已处理
  4. 如果失败,则将文档标记为失败
  5. 最终,文档将在数据库中更新

Web服务可以是REST服务(因为我们在谈论资源 ),数据库可以是CouchDB或MongoDB的文档存储(因为我们在谈论文档 ),但这并不重要。

重要的是通常在任何系统中都涉及一些I / O(输入/输出)。 从文件系统读取信息,将信息存储到数据库中,在Web服务之间通过网络进行通信。

正如我们在上一期文章中所见,我们希望我们的功能尽可能纯净 ,没有任何副作用。 不幸的是,真正的系统必须与外界交互才能有意义。

我们还如何获取输入到系统中的信息,或向用户输出什么呢? I / O的一些示例是:

  • 文件系统访问
  • 网络插座
  • HTTP请求
  • JDBC操作
  • 启动线程
  • 系统时钟访问

我们已经通过setToProcessed / setToFailed方法摆脱了对数据库的访问,方法是将其上移到调用链上一步,但是它仍在FeedHandler

我们能做的最好的就是将I / O移到系统外部。

我们可以做的最明显的改变是完全摆脱数据库,而只是从handle()返回新的更新文档。

摆脱数据库

更改

.thenAccept { resource ->documentDb.update(setToProcessed(doc, resource))
}
.exceptionally { e ->documentDb.update(setToFailed(doc, e))
}

.thenApply { resource ->setToProcessed(doc, resource)
}
.exceptionally { e ->setToFailed(doc, e)
}

摆脱documentDb

我们只是在通话链的更远处返回所有修改过的文档。 这就是为什么我们还必须……

…摆脱虚无

从更改返回类型

void handle(...)

List<Doc> handle(...)

因此处理过的文档会一直返回到外部。

并不是说我们不再与任何数据库进行任何交互,而是不再需要我们的FeedHandler组件! 通过将任何I / O移至系统的外围,中间的所有内容都可以尽可能地纯净。

还记得Haskell,这是一种“纯”功能语言吗? 从“ 学到了伟大的Haskell” :

事实证明,Haskell实际上拥有一个非常聪明的系统来处理具有副作用的功能,这些功能将我们程序的纯净部分和不纯净的部分整齐地分开了,这就像在与之交谈一样,可以完成所有肮脏的工作。键盘和屏幕。 将这两个部分分开,我们仍然可以推理我们的纯程序,并利用纯净提供的所有功能,例如惰性,健壮性和模块化,同时与外界进行有效的通信。

当它在90年代被发明时,它引入了IO monad来处理I / O。 任何函数,例如从外部读取,都必须使用返回类型IO ,该类型实际上是由编译器检查的。

这有一些好处,例如Haskell编译器在重新排序所有非IO代码以进行优化方面具有一定的自由度。 从纯函数和I / O :

因为纯函数代码就像代数,所以编译器可以将所有非IO函数视为数学方程式。 这有点类似于关系数据库如何优化查询。

在Java中,我们没有针对这些事情的特定编译器支持,但是有一些事情我们可以照顾好自己。

记住: void是一个沉Kong。 任何返回void方法要么没有意义,要么具有副作用,例如写入显示,网络,文件或数据库,即与外部系统的交互。 代替执行I / O作为副作用,而是向调用方返回一个值,以描述与外部系统的交互。

现在就这样!

翻译自: https://www.javacodegeeks.com/2018/11/functional-java-example-move-outside.html

功能Java示例 第5部分–将I / O移到外部相关推荐

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

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

  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示例 第4部分–首选不变性

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

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

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

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

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

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

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

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

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

最新文章

  1. 转://点评Oracle11g新特性之动态变量窥视
  2. oracle数据库exp命令导入导出dmp文件演示,oracle数据库备份还原功能
  3. 博士申请 | 加拿大麦吉尔大学丁俊老师招收机器学习全奖博士/硕士/实习生
  4. record not found or changed by another user 解决方法
  5. SAP Cloud for Customer和Hybris Commerce的session保护机制
  6. 从壹开始 [Admin] 之五 ║ 实现『按钮』级别权限配置
  7. android 贝塞尔曲线 波浪线,Android 贝塞尔曲线实现水纹波动效果
  8. SpringBoot之HelloWorld
  9. BeanUtils.copyProperties使用
  10. 对于 指针数组 数组指针 函数指针 函数指针数组 指向函数指针数组的指针 的简单理解
  11. uboot修改传递给内核的cmdline的方法
  12. 吃豆人 博弈_强化吃豆人
  13. python秒网课_利用python完成大学刷课(从0到完成的思路)
  14. 非线性动力学 nonlinear dynamics
  15. 一个能启动电脑的U盘
  16. auto.js脚本自动点击屏幕双11自动领金币
  17. Project 2016 中文版软件快捷键学习
  18. Echarts 实现动态地图
  19. 计算机视觉基础--边缘检测
  20. 数据湖有新解!Apache Hudi 与 Apache Flink 集成

热门文章

  1. 【结论】取石子游戏(jzoj 1211)
  2. P2468 [SDOI2010]粟粟的书架 动态规划,主席树,二分答案
  3. Sentinel(二)之Quick Start
  4. json-lib的字符串自动转换坑
  5. Java的并发编程中的多线程问题到底是怎么回事儿?
  6. JAVA面试常考系列六
  7. Hadoop入门(一)概念与单机安装
  8. 我们在进行着一场拔河比赛……
  9. 干货!sqlserver数据库所有知识点总结整理,含代码(挺全的)
  10. javaWeb服务详解【客户端调用】(含源代码,测试通过,注释) ——applicationContext.xml