功能Java示例 第5部分–将I / O移到外部
这是称为“ 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)}}
我在本系列的每个部分中发展的示例是某种“提要处理程序”,用于处理文档。
处理效果如何?
- 一份或多份文件进来
- 如果文档“很重要”,则将其保存到Web服务API中,该API将为其创建并返回资源
- 如果成功,则将文档标记为已处理
- 如果失败,则将文档标记为失败
- 最终,文档将在数据库中更新
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移到外部相关推荐
- java 示例_功能Java示例 第5部分–将I / O移到外部
java 示例 这是称为" Functional Java by Example"的系列文章的第5部分. 在上一部分中,我们停止了对文档的变异,并返回了数据的副本. 现在,我们需要 ...
- java 函数式编程 示例_功能Java示例 第8部分–更多纯函数
java 函数式编程 示例 这是第8部分,该系列的最后一部分称为"示例功能Java". 我在本系列的每个部分中开发的示例是某种"提要处理程序",用于处理文档. ...
- 大数据 java 代码示例_功能Java示例 第7部分–将失败也视为数据
大数据 java 代码示例 这是称为" Functional Java by Example"的系列文章的第7部分. 我在本系列的每个部分中开发的示例是某种"提要处理程序 ...
- 对象作为参数示例java_功能Java示例 第6部分–用作参数
对象作为参数示例java 这是称为" Functional Java by Example"的系列文章的第6部分. 我在本系列的每个部分中开发的示例是某种"提要处理程序& ...
- java 示例_功能Java示例 第4部分–首选不变性
java 示例 这是称为" Functional Java by Example"的系列文章的第4部分. 在上一部分中,我们讨论了一些副作用,并且我想进一步详细说明如何通过将不可变 ...
- java 示例_功能Java示例 第3部分–不要使用异常来控制流程
java 示例 这是称为" Functional Java by Example"的系列文章的第3部分. 我在本系列的每个部分中开发的示例是某种"提要处理程序" ...
- java 示例_功能Java示例 第2部分–讲故事
java 示例 这是称为" Functional Java by Example"的系列文章的第2部分. 我在本系列的每个部分中开发的示例是某种"提要处理程序" ...
- java 函数式编程 示例_功能Java示例 第1部分–从命令式到声明式
java 函数式编程 示例 功能编程(FP)的目的是避免重新分配变量,避免可变的数据结构,避免状态并全程支持函数. 如果将功能性技术应用于日常Java代码,我们可以从FP中学到什么? 在这个名为&qu ...
- 功能Java示例 第8部分–更多纯函数
这是第8部分,该系列的最后一部分称为" Functional Java by Example". 我在本系列的每个部分中发展的示例是某种"提要处理程序",用于处 ...
最新文章
- 转://点评Oracle11g新特性之动态变量窥视
- oracle数据库exp命令导入导出dmp文件演示,oracle数据库备份还原功能
- 博士申请 | 加拿大麦吉尔大学丁俊老师招收机器学习全奖博士/硕士/实习生
- record not found or changed by another user 解决方法
- SAP Cloud for Customer和Hybris Commerce的session保护机制
- 从壹开始 [Admin] 之五 ║ 实现『按钮』级别权限配置
- android 贝塞尔曲线 波浪线,Android 贝塞尔曲线实现水纹波动效果
- SpringBoot之HelloWorld
- BeanUtils.copyProperties使用
- 对于 指针数组 数组指针 函数指针 函数指针数组 指向函数指针数组的指针 的简单理解
- uboot修改传递给内核的cmdline的方法
- 吃豆人 博弈_强化吃豆人
- python秒网课_利用python完成大学刷课(从0到完成的思路)
- 非线性动力学 nonlinear dynamics
- 一个能启动电脑的U盘
- auto.js脚本自动点击屏幕双11自动领金币
- Project 2016 中文版软件快捷键学习
- Echarts 实现动态地图
- 计算机视觉基础--边缘检测
- 数据湖有新解!Apache Hudi 与 Apache Flink 集成