功能Java示例 第2部分–讲故事

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

我在本系列的每个部分中发展的示例是某种“提要处理程序”,用于处理文档。 在上一部分中,我从一些原始代码开始,并应用了一些重构来描述“什么”而不是“如何”。

为了帮助代码向前发展,我们需要先讲一个故事 。 那就是这部分的地方。

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

这些都是这些部分:

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

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

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

作为参考,我们现在以以下代码为起点:

class FeedHandler {Webservice webserviceDocumentDb documentDbvoid handle(List<Doc> changes) {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)}}
}

大声读出

当我最初开始使用Spock作为测试框架时,由于它是多年前Grails默认提供的,因此它的众多功能和易用性给我留下了深刻的印象(至今仍是)。

你知道什么是假人,存根和间谍吧? Mockito拥有它们,Powermock拥有它们以及基本上所有其他严肃的(单元)测试框架。 Mock的概念并不难掌握(您可以在此处阅读全部内容),但是Spock具有一种特殊的方式来描述其(与预期的)模拟交互。

关于“基于交互的测试”的一章非常出色,它解释了如何使用代码示例来记录这些交互。

“模拟”子章开头为:

模拟是描述(强制)规范下的对象与其协作者之间的交互的行为。 这是一个例子:

def "should send messages to all subscribers"() {when:publisher.send("hello")then:1 * subscriber.receive("hello")1 * subscriber2.receive("hello")
}

如果您不熟悉Spock,Groovy或仅具有上述写作风格,请不要担心!

以上Spock文档的作者也认识到,并不是每个人都会立即理解这里发生的事情。

他们会提供一些建议,并继续提供文档:

大声朗读 :“当发布者发送“ hello”消息时,两个订户都应该只收到一次该消息。”

我的重点是“大声朗读”,因为我认为这很重要。 这里不讨论Spock的更多详细信息,而是我自己在日常编码中要牢记的建议本身。

  • 当我编写一段代码时,我可以大声读出吗?
  • 当其他人读取我的代码时,他/她可以大声读出吗?

这里的“大声” 与音量无关,而是可以用一种简洁易懂的方式描述“这里正在发生什么”。 这使得对代码的推理变得容易。

高级与低级

请考虑以下情形:

在不知名的城市中开车游览了几个小时以找到剧院后,汽车导航系统出现故障后,您最终决定停下来询问方向。

您在行人附近停下。

您:

先生,您碰巧知道如何从这里到达剧院

行人:

  1. 当然,这很容易。 开始了:

  2. 检查窗户以确保您具有良好的可见性。 检查后视镜以确保它们正确对齐,从而为您提供正确的道路视野。

  3. 调整座椅,使双脚舒适地到达两个踏板。

  4. 关闭窗口。

  5. 重置转向灯。

  6. 开始驾驶前,请松开驻车制动器。

  7. 啊,我看你有自动档。 请将变速杆置于“驱动器”中。

  8. 慢慢踩刹车,并监控仪表盘仪表。

  9. 继续前进,提高速度,监控车速表,将RPM保持在2000附近

  10. 大约120码后,在开始转向左车道之前,请先与您的方向灯指示至少两秒钟。

  11. 缓慢将汽车移至另一车道。 稍微将您的手放在方向盘上,以改变车道。 车轮只需要很小的移动即可; 因为大多数现代汽车都装有动力转向系统。 更改车道大约需要一到三秒钟。 减少一点,您做得太快了; 再也没有,你做得太慢了。

  12. 再走X步…

  13. 祝好运!

或者,考虑对话将像这样的替代宇宙:

您:

先生,您是否会知道如何从这里到达剧院?

行人:

  1. 当然,这很容易。 开始了:

  2. 左转,过桥。 在你的右边。

  3. 祝好运!

最后一种情况是轻而易举:明确说明要做什么和去哪里!

但是,第一种情况是细节缠身 -有关驾驶汽车本身的低级细节 -即使我们不希望在现实生活中得到这样的指导,我们仍然会编写这样的软件。

告诉我一些正确的内容。 如果我需要具体信息,我会要求它。

(顺便说一句wikihow.com:如何驾驶汽车,请捐赠上述说明中的一些。如果您确实需要学习驾驶,它有很多资源!)

在正确的级别上讲内容,不仅意味着使用正确命名的类和方法,而且还意味着在它们中使用正确的种类

让我们再次看一下我们的代码:

class FeedHandler {Webservice webserviceDocumentDb documentDbvoid handle(List<Doc> changes) {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)}}
}

故事

我们如何在代码中结合“大声读出”和“高级还是低级”?

我们的单handle方法当前显示为什么样?

  1. 查找type -property等于字符串"important"所有文档。

  2. 呼叫createwebservice与文档,返回的资源。

  3. 如果我们有资源,请将资源的id分配给文档的apiId属性。

  4. 将文档的status属性设置为字符串"processed"

  5. 如果发生异常,请将文档的status属性设置为字符串"failed" 将文档的status属性设置为来自异常的message

  6. 最后,使用documentDb在documentDb上调用update

基本上,这只是重复代码语句!

什么故事,我想告诉取而代之的,是以下情况:

  1. 通过Web服务“创建资源”来处理“重要”文档。

  2. 每次成功时,将两者关联在一起并“将文档标记为已处理”,否则将其标记为“失败”。

读得很好,你不觉得吗?

实际上,我们可以通过在IDE中使用几种“提取方法”重构并为提取的方法选择一些好的名称来实现这一目标。

在上面的故事中,双引号短语是我想在高层看到的重要部分。

“重要”

我为什么要关心文档使用什么属性来确定其重要性? 现在是字符串"important" ,表示“嘿,我很重要!” 但是如果条件变得更加复杂怎么办?

doc.type == 'important'提取到其自身的方法isImportant

changes.findAll { doc -> isImportant(doc) }// ...private boolean isImportant(doc) {doc.type == 'important'}

“创造资源”

我为什么在这里关心如何在Web服务中调用什么方法? 我只想创建一个资源。

将与Web服务的所有事务都提取到它自己的方法(称为createResource

def resource = createResource(doc)// ...private Resource createResource(doc) {webservice.create(doc)}

“更新为已处理”

提取将资源/文档/将状态设置为其自己的方法(称为updateToProcessed

updateToProcessed(doc, resource)// ...private void updateToProcessed(doc, resource) {doc.apiId = resource.iddoc.status = 'processed'}

“更新失败”

不在乎细节。 提取到updateToFailed

updateToFailed(doc, e)// ...private void updateToFailed(doc, e) {doc.status = 'failed'doc.error = e.message}

看来我们最后只剩下了documentDb.update(doc)

这是在数据库中存储已处理/失败文档的一部分,我已经在最高级别上进行了描述。

我将其放在每个刚刚创建的updateTo*方法中-较低的级别。

private void updateToProcessed(doc, resource) {doc.apiId = resource.iddoc.status = 'processed'documentDb.update(doc)}private void updateToFailed(doc, e) {doc.status = 'failed'doc.error = e.messagedocumentDb.update(doc)}

那么,提取出细节之后,有什么变化?

void handle(List<Doc> changes) {changes.findAll { doc -> isImportant(doc) }.each { doc ->try {def resource = createResource(doc)updateToProcessed(doc, resource)} catch (e) {updateToFailed(doc, e)}}}

任何人(例如,同事,您未来的自我)都会“一口气”地读一读,将会了解30,000英尺的行程。

如果您需要任何这些步骤的详细信息,只需深入了解该方法即可。

能够写声明式的东西(本系列的前一部分)并在正确的水平上讲故事(本部分)还将有助于在第3部分及以后的部分中更轻松地进行将来的更改。

现在就这样

作为参考,这是重构代码的完整版本。

class FeedHandler {Webservice webserviceDocumentDb documentDbvoid handle(List<Doc> changes) {changes.findAll { doc -> isImportant(doc) }.each { doc ->try {def resource = createResource(doc)updateToProcessed(doc, resource)} catch (e) {updateToFailed(doc, e)}}}private Resource createResource(doc) {webservice.create(doc)}private boolean isImportant(doc) {doc.type == 'important'}private void updateToProcessed(doc, resource) {doc.apiId = resource.iddoc.status = 'processed'documentDb.update(doc)}private void updateToFailed(doc, e) {doc.status = 'failed'doc.error = e.messagedocumentDb.update(doc)}}

翻译自: https://www.javacodegeeks.com/2017/11/functional-java-example-part-2-tell-story.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/348322.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

OpenHub框架–下一个有趣的功能

这是有关OpenHub框架的系列文章中的第三篇&#xff0c;第一篇介绍OpenHub框架 &#xff0c;第二篇介绍异步消息传递模型 。 该系列的最后一篇文章将更详细地介绍其他一些有趣的功能&#xff0c;并说明为什么OpenHub可以成为您的集成项目的理想选择的原因。 节流 节流是一种功…

ubuntu生成密钥和证书_基于浏览器的密钥生成以及与浏览器的密钥/证书存储的交互...

ubuntu生成密钥和证书想象以下情况&#xff1a; 您需要从访问您的网站的用户那里获取一个密钥&#xff08;在非对称情况下为用户的公共密钥 &#xff09;&#xff0c;并希望浏览器记住私有部分&#xff0c;而不会因冗长的导入过程而困扰用户。 老实说&#xff0c;实际上&#…

android数据流分类,【Android工程之类】1 MVVM架构 - MVVM与单向数据流

前言这个系列将讲述使用MVVM架构、LiveData、Room、Kodein、Retrofit、EventBus来建立一个统一的、优雅的、可维护的TODO程序&#xff0c;本系列分为多个章节&#xff0c;从0开始一步一步引入这些优秀的库。下图展示的是Jetpack组件库包含的内容&#xff0c;这套的架构方案的核…

java ssl证书_Java安全教程–创建SSL连接和证书的分步指南

java ssl证书在有关应用JEE安全性的系列文章中&#xff0c;我们为您提供了另一个有关如何在Java EE应用程序中创建SSL连接和创建证书的详细教程。 如我们之前的文章中所述&#xff0c; 安全套接字层&#xff08;SSL&#xff09;/传输层安全性&#xff08;TLS&#xff09;将启用…

通过Okta的单点登录保护Spring Boot Web App的安全

“我喜欢编写身份验证和授权代码。” 〜从来没有Java开发人员。 厌倦了一次又一次地建立相同的登录屏幕&#xff1f; 尝试使用Okta API进行托管身份验证&#xff0c;授权和多因素身份验证。 您可以使用SpringBoot和Okta在不到20分钟的时间内启动具有完整用户身份和授权管理的企…

java ee cdi_Java EE CDI程序化依赖关系消歧示例–注入点检查

java ee cdi在本教程中&#xff0c;我们将看到在注入Java EE CDI bean时如何避免程序依赖消除歧义。 我们已经在Jave EE依赖关系消除歧义示例中展示了如何避免CDI Bean中的依赖关系歧义消除。 在这里&#xff0c;我们将向您展示如何以动态方式避免依赖消除歧义。 我们将通过检查…

atom自动补全html代码,Atom - Emmet插件的使用详解(HTML/CSS代码自动补全)

一、Emmet的安装与介绍Emmet (前身为 Zen Coding) 是一个能大幅度提高前端开发效率的工具&#xff0c;能够实现 HTML、CSS 的快速编写。官网地址&#xff1a;http://emmet.io/官方文档&#xff1a;http://docs.emmet.io/cheat-sheet/Atom的emmet介绍页面&#xff1a;https://at…

html怎么做出相框的效果,PS滤镜制作漂亮的实木相框效果

一、新建一个600 * 800像素的文件&#xff0c;然后新建一个图层&#xff0c;前景颜色设置为红色&#xff0c;背景设置为深红色&#xff0c;执行&#xff1a;滤镜 > 渲染 > 纤维&#xff0c;参数设置如下图。二、执行&#xff1a;图像 > 旋转画布 > 逆时针90度&…

查询阜阳2021高考成绩,2021年阜阳高考成绩排名及成绩公布时间什么时候出来

阜阳高考结束后&#xff0c;每年都有很多家长和考试不知道阜阳高考成绩排名如何查询、阜阳高考成绩什么时候公布以及查询方式&#xff0c;本文小编整理了阜阳高考成绩查询排名的相关知识。一、阜阳高考成绩公布时间及查询方式根据往年阜阳高考成绩公布时间预测&#xff0c;2021…

2021高考厦门一中成绩查询,2021年厦门中考成绩和分数线什么时候公布(附查询入口)...

每年中考结束后很多考生和家长都很关心成绩什么时候公布&#xff0c;中考分数线什么时候公布&#xff1f;然而你离彻底解放就只差一步——查分数&#xff01;查分数&#xff0c;比上考场考试还要紧张啊&#xff01;考分不知道&#xff0c;玩耍似心跳。那么2019年厦门中考成绩什…

Java开发人员应该知道的前20个库和API

优秀且经验丰富的Java开发人员的特征之一是对API的广泛了解&#xff0c;包括JDK和第三方库。 我花了很多时间来学习API&#xff0c;尤其是在阅读了Effective Java 3rd Edition之后 &#xff0c;Joshua Bloch建议在Java 3rd Edition中使用现有的API进行开发&#xff0c;而不是为…

打磨锤子计算机专业,钳工磨锤子实训心得体会

钳工磨锤子实训心得体会实训是职业技能实际训练的简称,是指在学校控制状态下,按照人才培养规律与目标,对学生进行职业技术应用能力训练的教学过程。钳工磨锤子实训心得体会&#xff0c;我们来看看。钳工磨锤子实训心得体会1前言&#xff1a;通过这次的钳工实习报告&#xff0c;…

html编辑器设置为publisher,将PDF转换为Publisher的简单方法

二、 如何把PDF文件转换为Publisher支持的图片格式一些专业的软件或者在线网站都可以帮助我们把PDF文件转换为Publisher支持的图片格式。下面将提供几种支持PDF文件转换为图片格式的方法。(1) 使用都叫兽™PDF转换器进行格式转换热点推荐 - ADs都叫兽™PDF转换器 - 多功能的PDF…

Oracle应用容器云上的WildFly Swarm

在此博客文章中&#xff0c;我将描述如何将打包在WildFly Swarmber -jar中的CloudEE Duke应用程序部署到Oracle Application Container Cloud 。 在Oracle Application Container Cloud中进行部署所需的部署工件是一个ZIP归档文件&#xff0c;其中包含应用程序ber-jar和清单文…

适合学计算机用的机械键盘,一款好用的机械键盘应该怎么选?看完这篇就明白了...

一款好用的机械键盘应该怎么选&#xff1f;看完这篇就明白了2019-07-30 15:53:134点赞14收藏3评论今天给大家带来好物推荐第1期——机械键盘。作为在办公室办公的从业者们&#xff0c;平时工作中与电脑的接触时间最多。而人与电脑的交互主要靠键盘和鼠标&#xff0c;其中使用最…

六年级计算机课学什么时候,六年级信息技术《进一步了解计算机》教学设计

六年级信息技术《进一步了解计算机》教学设计教学目标知识与技能&#xff1a;1.了解计算机的五大部件2.了解各种典型的、常见的输入设备、输出设备、存储器等。过程与方法&#xff1a;通过学生利用教师提供的主题资源网站自主学习&#xff0c;了解计算机五大部件。情感、态度与…

asciidoc文件阅读_可搜索的文件? 是的你可以。 选择AsciiDoc的另一个原因

asciidoc文件阅读Elasticsearch是一个基于Apache Lucene的灵活&#xff0c;功能强大的开源&#xff0c;分布式实时云搜索和分析引擎&#xff0c;可提供全文搜索功能。 它是面向文档且无架构的。 Asciidoctor是一个纯Ruby处理器&#xff0c;用于将AsciiDoc源文件和字符串转换为…

专转本计算机专业录取分数线,2018江苏专转本各专业分数线一览!

原标题&#xff1a;2018江苏专转本各专业分数线一览&#xff01;2018江苏专转本分数线梳理018江苏专转本考试已过去四个月&#xff0c;分数线已经公布了三个多月。按照分数线进行梳理大致情况如下&#xff1a;300分以上院校专业常州大学的财务管理 320分独占鳌头。300分以上分数…

综合知识计算机类编制,天津事业编综合知识是什么

天津事业编综合知识有三类&#xff0c;分别是文字综合类、财会类、计算机类&#xff0c;考试时根据岗位考试要求进行一类综合知识的考核&#xff0c;均为主客观性试题&#xff0c;考试时限为150分钟&#xff0c;满分为100分。综合知识(文字综合类)简介(一)测试内容综合知识(文字…

哥大计算机科学学费,哥大计算机科学专业成功案例解析!!!

学生背景&#xff1a;学生&#xff1a;刘同学本科背景&#xff1a;北京大学 生物工程专业GPA: 3.5/4.0雅思7.5 GRE320录取院校&#xff1a;哥伦比亚大学—MS in Computer Science计算机科学硕士规划分析&#xff1a;1、背景分析L同学本科读的是生物工程专业&#xff0c;因为同学…