重新设计Hamcrest

我在Hamcrest库上做了几篇文章 ,我确实很喜欢使用它,但是我希望对其进行一些更改。 我了解他们做出的大多数设计决策,但我认为其中一些确实不值得。

介绍Litecrest

我对库所做的大多数更改都有助于减轻Hamcrest的负担,因为我觉得有些事情不必要地减轻了负担。 这就是为什么我称我的更改为Litecrest。 它不会是一个实际的库; 这只是大声思考。 我也希望您能从中学到一些有关设计库的知识。

没有说明

Description接口以及StringDescriptionBaseDescription类实际上并不值得。 他们提供了列表转换为字符串好看一些不错的方法,但toString()在所有这些方法应该是足够的。 如果不是这样,可以将一些protected final方法放在BaseMatcher ,以方便地为列表构建字符串。 当然,这并没有真正遵循SRP密切,所以你可以使用类似 Description ,以提供方便的方法。

说明,否则不是很有帮助。 它的存在性假设它专门用于提供从长远来看可能不是String的输出。 作为一个使用良好的库,将其从String更改为与输出无关的类型会破坏向后兼容,但是这种更改不太可能需要。 应用YAGNI , Description类就在马桶下面。

无输出参数

所述describeTo()describeMismatch 不宜服用在Description或附加物体的任何其它类型的字符串,尤其是作为out参数(某物,以避免尽可能经常)。 由于这些方法没有返回类型开头,因此绝对没有理由使用out参数。

仔细研究问题,您将发现根本没有理由使用参数。 我了解到,他们可能一直在试图迫使匹配器的创建者不使用String串联,但事实并非如此。 如果匹配器的描述只是一个简单的小字符串,则没有理由他们不应该仅仅返回该字符串。 就个人而言,我将删除Description参数,并为它们提供String或CharSequence的返回类型。 我考虑使用CharSequence因为那样会给使用StringBuilder带来更大的动力,但是简单地返回String也不是什么大问题,因为他们可以在其上调用toString() 。 不过,我也可能会使用CharSequence ,因为我将在断言逻辑中使用StringBuilder来将输出放在一起,并且StringBuilder也可以采用CharSequence ,因此唯一的toString()必须在完成输出时被调用。

类型安全

Matcher接口采用通用参数,该参数与matches()方法一起使用,但是所述方法采用Object而不是通用类型。 javadoc声称这是由于类型擦除引起的,但我不认为这是一个问题。 我没有做任何挖掘来尝试是否可以将其切换为通用类型,但是如果我发现您实际上可以使用通用类型,则可以。 这消除了对TypeSafeMatcher的需求,因为它也检查null,因此可以用更简单的NullCheckingMatcher代替,或者只是实现它,以便断言在捕获到NullPointerException将不匹配描述更改为“为null”。 通过执行所有这些操作,我们可能会消除所有其他双倍的基类,这些基类必须加倍以覆盖类型安全匹配器和不那么重要的匹配器。 (例如: CustomMatcherCustomTypeSafeMatcherDiagnosingMatcherTypeSafeDiagnosingMatcher ,以及我加倍的ChainableMatcher ,摆脱了两个DiagnosingMatcher的影响;它们的设计很差,两次调用matches()

更改一些名字

我真的不喜欢describeTo()这个名字。 应该是describeExpected()describeMatch() 。 我了解他们遵循JMock ConstraintsSelfDescribing命名约定,但是看到他们没有费心完成其余方法签名的复制,实际上并没有任何好处。

CustomMatcher S的关系被称为OneOffMatcher S或QuickMatcher秒。 Custom是一个令人误解的名称,听起来您需要对其进行扩展才能创建自己的匹配器。

文档中的更多示例

我不确定该库中有几个类,因为它们的文档没有显示它们的使用方式,因此我不确定它们的用处。 Condition就是其中之一。 从少量的文档看来,这似乎是相对有用的,但是由于它没有提供使用示例(并且它是一个具有内部接口和两个内部类的相对复杂的文件),我不知道如何使用它。 它还没有记录其公共方法,因此我不确定它们是否需要大量研究。

FeatureMatcher已得到很好的记录,但同样没有示例。

那些为图书馆编写文档的人在任何时候都牢记这一点。 如果不是很明显(通常,即使不是很明显),则应给出使用中的类的示例。

删除无关的类

其中一些已经被直接或间接地解决了。 删除Description及其所有子类。 删除SelfDescribing ,因为它仅在Description仍然存在时才真正有用。 删除所有TypeSafe版本的基本匹配器。 卸下Diagnosing匹配器。 我不确定是否应该删除Condition因为我没有太大用。 如果保留Condition ,那么最终在核心org.hamcrest包中有五个原始的十一个类,在api org.hamcrest包中有四个原始的两个接口。

现在,让我们深入研究org.hamcrest.internal包。 ArrayIterator没什么用,因为您只能使用已经可以与foreach循环一起使用的数组。 NullSafety似乎模仿Arrays.toList()功能,但用IsNull匹配器替换了null匹配器。 我看不到这有什么帮助,因此将其删除。 ReflectiveTypeFinder可能最终会有用。 我只看到它在TypeSafeMatcherFeatureMatcher ,尽管我不确定在FeatureMatcher使用了多少。 不过,我会保留。 最后两个处理的是SelfDescribing ,我们已将其删除,因此这两个处理也是一样。 这仅使ReflectiveTypeFinder脱离了以前的五个类。

我不打算讨论所有其他匹配器。 在大多数情况下,已添加它们的用处。 由于删除了这么多的基类,几乎所有的类都可能必须进行更改。

Lambdas!

如果将新的功能范例也应用于hamcrest,则可以扩展匹配器概念的实用性。 我没有想太多,但是对于一次性匹配器,您可以修改库以包括一个新的assertThat()方法,如下所示:

public static  void assertThat(T item, String description, Predicate matcher) {if(!matcher.test(item)) {StringBuilder output = new StringBuilder();output.append("Expected: ").append(description).append("\n      but: was").append(item.toString());throw new AssertionError(output.toString());}
}

这将使您可以编写类似于以下内容的断言:

assertThat("cats", "doesn't contain \"dogs\"", str -> !str.contains("dogs"));

实际上,我实际上已经在ez-testing迷你库中添加了LambdaAssert类,因此您可以将其与原始hamcrest库一起使用。

匹配器接口

实际上有一个Matcher接口是毫无意义的,因为hamcrest希望您扩展BaseMatcher而不是实现Matcher 。 如果您非常不想让任何人实现,那么为什么要创建一个接口? 尤其是因为BaseMatcher为我们做的唯一事情就是为describeMismatch()创建一个默认实现describeMismatch()并“实现”放置在此处的不赞成使用的方法,告诉您使用BaseMatcher而不是Matcher )。

如果您真的不希望人们使用该界面,请摆脱它。 就个人而言,由于无论如何我还是经常重写describeMismatch() ,所以我认为只需要实现接口就完全可以,而不必让JVM加载实际上为我提供任何东西的基类。

另外,由于我们现在有了Java 8,因此该接口可以仅使用默认方法来实现默认实现。 但是,我可以理解要避免这种情况,因为较旧的Java版本将无法利用这一点。

所以,要么只是BaseMatcher或没事的Matcher正在实施。

奥托罗

我还想更改其他一些小事情,例如,迫使人们重写describeMismatch()而不是提供默认值,但是我甚至不确定那个,因为默认值通常足够有效。 无论如何,即使您有一个受欢迎的图书馆,也并不意味着它是完美的。 始终注意进行重构。

不幸的是,所有这些更改都不是向后兼容的,但有时是值得的。

翻译自: https://www.javacodegeeks.com/2015/01/redesigning-hamcrest.html

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

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

相关文章

CSS 垂直居中

1、使用绝对定位垂直居中 绝对对位原理:元素在过度受限情况下,将margin设置为auto,浏览器会重算margin的值,过度受限指的是同时设置top/bottom与height或者left/right与width。 .absolute_center{/*display:none;*/position:absol…

Java EE拦截器

历史 我认为重要的是要看一下Java EE中的Interceptor的发展,因为它是从EJB特定的项目开始的,后来又演变成一个单独的规范,现在可供其他Java EE规范扩展,这一事实很简单。 版本1.0 拦截器最初是在EJB 3.0 ( Java EE 5的…

New Begin

已经研究生三年级了, 最近也找好了工作,应该要开始自己的程序人生了。 虽然说写程序也写了很一段时间了, 决定现在开始在cnblogs这个,记录下自己的学习轨迹。开始维护自己的blogs。转载于:https://www.cnblogs.com/binzeehale/ar…

[ExtJs6] 环境搭建及创建项目

1. 环境搭建 sencha cmd 和 extjs6 sdk.sencha cmd: https://www.sencha.com/products/extjs/cmd-download/extjs6: https://www.sencha.com/sencha cmd 安装过程将其加入系统的环境变量path中。export PATH${PATH}:/Users/shuanggai/bin/Sencha/Cmd/6.2.2.36把改语句添加到 ~/…

通过Spring Integration和RabbitMQ获得高可用性的AMQP支持的消息通道

Spring Integration消息通道默认情况下将消息存储在内存中。 这是因为内存速度快,易于实现,并且不会增加网络成本。 但是,在某些情况下,这可能会引起问题,因为如果应用程序崩溃或服务器意外关闭,所有消息都…

有机会多熟悉下开源框架

Struts2,Spring,Hibernate等开源框架的使用转载于:https://www.cnblogs.com/yqskj/archive/2012/11/05/2756085.html

vue之node.js的简单介绍

一、什么是node.js? 它是可以运行JavaScript的服务平台,可以吧它当做一门后端程序,只是它的开发语言是JavaScript 二、安装 1、node.js的特性: - 非阻塞IO模型- 时间驱动 2、运用的场景: - 高并发低业务- 实时场景- 聊…

Java 8 StringJoiner

在Java 8发行版中,最受关注的是Lamda,新的Date API和Nashorn Javascript引擎。 在这些阴影下,有较小但有趣的变化。 其中之一是StringJoiner的引入。 StringJoiner是用于分隔字符或字符串列表的实用程序。 您可能会认出以下代码: …

设置TextView为下划线的样式

1 tvUserTel.setText(Html.fromHtml("<u>"usertel"</u>")); 2 tvUserTel.setTextColor(Color.BLUE);//设置为蓝色 转载于:https://www.cnblogs.com/Tristan2012/archive/2012/11/06/2757239.html

jQuery之jQuery扩展和事件

一、jQuery事件 常用事件 blur([[data],fn]) 失去焦点 focus([[data],fn]) 获取焦点&#xff08; 搜索框例子&#xff09; change([[data],fn]) 当select下拉框中的元素发生改变的时候触发change事件(select例子) click([[data],fn]) 点击 dblclick([[data],fn])…

JavaFX列表示例

这是使用JavaFX构建的示例列表应用程序。 该应用程序是待办事项列表。 此应用程序具有添加&#xff0c;更新和删除列表中项目的功能。 列表数据存储在HSQLDB关系数据库中。 该应用程序使用JDBC&#xff08;Java数据库连接&#xff09;API访问数据库。 该应用程序打包为可执行JA…

flex弹性布局操练2

上一个是练习的1个内元素的&#xff0c;这次练习两个元素的。 ul.box1 {list-style:none;background-color:black;display:flex;justify-content:space-between;/*水平轴的位置,默认是flex-start就是第一种情况*/align-items:center;/*垂直轴的位置*/width:100px;height:100px;…

CDI 2.0更新

CDI 2.0是Java EE平台的上下文和依赖项注入的下一个版本&#xff0c;并且是Java EE 8中包含的候选对象。 自2014年9月以来&#xff0c;它一直在开发中&#xff0c;并且发展Swift&#xff01; CDI 2.0的主要目标 与Java SE 8对齐&#xff08;当然&#xff01;&#xff09; 支持…

一段js实现复制文本内容到剪切板

<script type"text/javascript"> function copyUrl2(){var Url2document.getElementById("biao1").innerText;var oInput document.createElement(input);oInput.value Url2;document.body.appendChild(oInput);oInput.select(); // 选择对象docum…

【Android】自带Theme

?android:theme"android:style/Theme.Dialog" 将一个Activity显示为对话框模式?android:theme"android:style/Theme.NoTitleBar" 不显示应用程序标题栏?android:theme"android:style/Theme.NoTitleBar.Fullscreen" 不显示应用程序标题栏&…

使用Maven Failsafe和JUnit @Category将集成测试与单元测试分开

为什么单元测试应与集成测试分开运行 单元测试级别的TDD相当简单&#xff0c;因为单元测试中的类要么没有复杂的依赖关系&#xff0c;要么使用模拟框架&#xff08;例如Mockito&#xff09;来模拟依赖关系。 但是&#xff0c;当我们进入集成测试时&#xff0c;TDDSwift变得困难…

SVN功能小结 .

基本操作1同步在MyEclipse J2EE透视图下,右击你要同步的工程->小组->与资源库同步->这时会进入同步透视图,会显示出本机与SVN上内容有不同的文件,双击文件名,会显示出两个文件中哪里不同;2提交在同步透视图下有”灰色向右的箭头,表示你本机修改过”,右击该文件,可以选…

Selenium1 Selenium2 WebDriver

内容摘要&#xff1a; Selenium 1 原理WebDriver WebDriver 组件WebDriver 协议 Remote End 处理流程Commands & Endpoints & 请求路由错误消息 WebDriver 配置 Selenium 2 1、Selenium 1 原理 (1).测试用例&#xff08;Testcase&#xff09;通过Client Lib的接口向Se…

Fork / Join框架vs并行流vs.ExecutorService:最终的Fork / Join基准

Fork / Join框架在不同配置下如何工作&#xff1f; 就像即将上映的《星球大战》一样&#xff0c;围绕Java 8并行性的批评也充满了兴奋。 并行流的语法糖带来了一些炒作&#xff0c;就像我们在预告片中看到的新型光剑一样。 现在&#xff0c;有了许多使用Java进行并行处理的方法…

CSRF攻击与防御

CSRF是什么 CSRF在百度百科中是这么说的&#xff1a;“CSRF&#xff08;Cross-site request forgery跨站请求伪造&#xff0c;也被称为“one click attack”或者session riding&#xff0c;通常缩写为CSRF或者XSRF&#xff0c;是一种对网站的恶意利用。尽管听起来像跨站脚本&a…