在Data Geekery ,我们喜欢Java。 而且,由于我们真的很喜欢jOOQ的流畅的API和查询DSL ,我们对Java 8将为我们的生态系统带来什么感到非常兴奋。

Java 8星期五

每个星期五,我们都会向您展示一些不错的教程风格的Java 8新功能,这些功能利用了lambda表达式,扩展方法和其他好东西。 您可以在GitHub上找到源代码 。

大多数内部DSL已过时

这是目前市场上最先进的内部DSL之一的供应商的说法。 让我解释:

语言很难

学习新语言(或API)非常困难。 您必须了解所有的关键字,构造,语句和表达式类型等。这对于外部DSL,内部DSL和“常规” API都是正确的,它们本质上是内部DSL,但流畅度较低。

使用JUnit时,人们已经习惯使用hamcrest匹配器 。 它们有六种语言(Java,Python,Ruby,Objective-C,PHP,Erlang)可用,这一事实使它们成为一个不错的选择。 作为特定领域的语言,他们已经建立了易于阅读的习惯用法,例如

assertThat(theBiscuit, equalTo(myBiscuit));
assertThat(theBiscuit, is(equalTo(myBiscuit)));
assertThat(theBiscuit, is(myBiscuit));

阅读此代码时,您将立即“理解”所声明的内容,因为API的读法像prosa。 但是学习用此API编写代码更加困难。 您将必须了解:

  • 所有这些方法来自哪里
  • 存在哪些方法
  • 谁可能使用自定义匹配器扩展了障碍
  • 扩展DSL时的最佳做法是什么

例如,在上面的示例中,三个之间到底有什么区别? 我什么时候应该使用另一个? 是is()检查对象身份吗? equalTo()是否检查对象是否相等?

hamcrest教程继续着以下示例:

public void testSquareRootOfMinusOneIsNotANumber() {assertThat(Math.sqrt(-1), is(notANumber()));
}

您可以看到notANumber()显然是一个自定义匹配器,在实用程序中的某个地方实现了:

public class IsNotANumber
extends TypeSafeMatcher<Double> {@Overridepublic boolean matchesSafely(Double number) {return number.isNaN();}public void describeTo(Description description) {description.appendText("not a number");}@Factorypublic static <T> Matcher<Double> notANumber() {return new IsNotANumber();}
}

尽管这种DSL的创建非常容易,并且可能也很有趣,但是出于简单的原因,开始着手编写和增强自定义DSL是很危险的。 它们绝不比其通用的,功能相同的同类更好-但它们却更难维护。 考虑一下Java 8中的上述示例:

用功能代替DSL

假设我们有一个非常简单的测试API:

static <T> void assertThat(T actual, Predicate<T> expected
) {assertThat(actual, expected, "Test failed");
}static <T> void assertThat(T actual, Predicate<T> expected, String message
) {assertThat(() -> actual, expected, message);
}static <T> void assertThat(Supplier<T> actual, Predicate<T> expected
) {assertThat(actual, expected, "Test failed");
}static <T> void assertThat(Supplier<T> actual, Predicate<T> expected, String message
) {if (!expected.test(actual.get()))throw new AssertionError(message);
}

现在,将hamcrest匹配器表达式与其功能等效项进行比较:

// BEFORE
// ---------------------------------------------
assertThat(theBiscuit, equalTo(myBiscuit));
assertThat(theBiscuit, is(equalTo(myBiscuit)));
assertThat(theBiscuit, is(myBiscuit));assertThat(Math.sqrt(-1), is(notANumber()));// AFTER
// ---------------------------------------------
assertThat(theBiscuit, b -> b == myBiscuit);
assertThat(Math.sqrt(-1), n -> Double.isNaN(n));

有了lambda表达式和经过精心设计的assertThat() API,我可以肯定,您将不再寻找用匹配器表达断言的正确方法。

请注意,不幸的是,我们不能使用Double::isNaN方法引用,因为它与Predicate<Double>不兼容。 为此,我们必须在断言API中执行一些原始类型的魔术,例如

static void assertThat(double actual, DoublePredicate expected
) { ... }

然后可以这样使用:

assertThat(Math.sqrt(-1), Double::isNaN);

好但是…

……您可能会听到自己在说,“但是我们可以将匹配器与lambda和流结合起来”。 是的,我们当然可以。 我现在已经在jOOQ集成测试中做到了。 我想跳过所有不在系统属性中提供的方言列表中的SQL方言的集成测试:

String dialectString = System.getProperty("org.jooq.test-dialects");// The string must not be "empty"
assumeThat(dialectString, not(isOneOf("", null)));// And we check if the current dialect() is
// contained in a comma or semi-colon separated
// list of allowed dialects, trimmed and lowercased
assumeThat(dialect().name().toLowerCase(),// Another matcher hereisOneOf(stream(dialectString.split("[,;]")).map(String::trim).map(String::toLowerCase).toArray(String[]::new))
);

……那也很整洁,对吗?

但是为什么我不干脆写:

// Using Apache Commons, here
assumeThat(dialectString, StringUtils::isNotEmpty);
assumeThat(dialect().name().toLowerCase(),d -> stream(dialectString.split("[,;]")).map(String::trim).map(String::toLowerCase()).anyMatch(d::equals)
);

无需Hamcrest,只需普通的旧lambda和溪流!

现在,当然,可读性只是一个问题。 但是上面的示例清楚地表明,不再需要 Hamcrest匹配器和Hamcrest DSL。 鉴于在接下来的2-3年内,所有Java开发人员中的大多数将非常习惯于每天使用Streams API,而不是非常习惯于使用Hamcrest API,因此,我敦促JUnit维护人员不要使用使用Hamcrest以支持Java 8 API。

哈姆克雷斯特现在被认为是坏人吗?

好吧,它过去已经达到了目的,人们对此已经有所适应。 但是,正如我们在上一篇有关Java 8和JUnit Exception匹配的文章中已经指出的那样,是的,我们确实相信Java的人们在过去的十年中一直在树错误的树。

缺少lambda表达式已导致各种完全膨胀的库 ,现在也有些无用的库 。 许多内部DSL或注释魔术师也受到影响。 不是因为他们不再解决以前遇到的问题,而是因为它们还没有支持Java-8。 Hamcrest的Matcher类型不是功能接口,尽管将其转换为一个接口很容易。 实际上,Hamcrest的CustomMatcher逻辑应该被拉到Matcher接口中,成为默认方法。

使用诸如AssertJ之类的替代方案,事情不会变得更好。该替代方案创建了一个替代DSL,现在它已通过lambda和Streams API变得过时了(就呼叫站点代码冗长而言)。

如果您坚持使用DSL进行测试,那么无论如何Spock可能都是一个更好的选择。

其他例子

Hamcrest只是这种DSL的一个示例。 本文展示了如何通过使用标准的JDK 8构造和几个实用程序方法几乎完全将其从堆栈中删除,无论如何,您可能很快就会在JUnit中使用它们。

Java 8将为上个十年的DSL辩论带来很多新的吸引力,因为Streams API还将大大改善我们看待转换或构建数据的方式。 但是,当前许多DSL尚未为Java 8做好准备,并且尚未以功能性方式进行设计。 对于难以学习的事物和概念,它们有太多的关键字,可以使用函数更好地建模。

该规则的一个例外是jOOQ或jRTF之类的DSL,它们以1:1的方式对实际存在的外部DSL进行建模,继承了所有现有的关键字和语法元素,从而使它们从一开始就很容易学习。

你拿什么

您对上述假设有何看法? 最喜欢的内部DSL是什么,由于Java 8已过时,它可能在未来五年内消失或完全转换?

翻译自: https://www.javacodegeeks.com/2014/06/java-8-friday-most-internal-dsls-are-outdated.html

Java 8 Friday:大多数内部DSL已过时相关推荐

  1. martin fowler_用Java和Java 8创建内部DSL,采用Martin Fowler的方法

    martin fowler 目前,我正在阅读Martin Fowler撰写的有关DSL- 特定领域语言的精彩书籍. 围绕DSL的嗡嗡声,围绕轻松支持DSL创建的语言,以及DSL的使用,使我好奇地了解和 ...

  2. 用Java和Java 8创建内部DSL,采用Martin Fowler的方法

    目前,我正在阅读Martin Fowler撰写的有关DSL- 特定于域的语言的精彩书籍. 围绕DSL的嗡嗡声,围绕轻松支持DSL创建的语言,以及DSL的使用使我好奇地了解和了解DSL的这一概念. 到目 ...

  3. IE错误 Java TM 已被阻止,因为它已过时并且需要更新 的解决方法

    自今年9月 10日,大量用户反馈,登陆到Oracle E-Business Suite后再点Form,IE 弹出"Java(TM)已被阻止,因为它已过时并且需要更新. "的错误,这 ...

  4. IDEA中提示:Warning:java: 源值1.5已过时, 将在未来所有发行版中删除

    问题描述: 运行Java Web项目时,IDEA中提示:Warning:java: 源值1.5已过时, 将在未来所有发行版中删除 解决方法: 1. 打开[File]-[Project Structur ...

  5. java 8 dsl_Java 8的内部DSL

    DSL定义:Domain-specific language (名词,简称DSL): 是一种专注特定领域的有限表达法. Martin Fowler 认为DSL区别于通常语义上的领域模型,通过一些内部的 ...

  6. 前端 DSL 实践指南(上)—— 内部 DSL

    编者按:本文转载自云音乐前端技术团队,作者网易云音乐前端工程师郑海波 前言 近几年,前端社区中 DSL 这个词开始频繁出镜,这和环境的变化有很大关系: React.Vue.Angular 等现代框架的 ...

  7. IntelliJ IDEA 源值1.5已过时,将在未来所有版本中删除

    转载自  IntelliJ IDEA 源值1.5已过时,将在未来所有版本中删除 原因: IDEA默认把项目的源代码版本设置为jdk1.5,目标代码设置为jdk1.5 解决方案: 1修改Maven的Se ...

  8. swing程序 过时拉嘛_密码已过时-如何保护您的应用程序和保护用户

    swing程序 过时拉嘛 重点 (Top highlight) I've said this part before, so if you read the previous article, ski ...

  9. Android应用发布页(已过时,更新请到http://hi.baidu.com/new/weimingtom_点击待宵草标签)...

    已过时,更新请到http://weimingtom.blog.163.com点击待宵草标签 或者去机锋市场和应用汇下载(机锋上的是最新版). 1. 日语简易词典(jkanji) * 稳定版本: v2. ...

最新文章

  1. Git版本库创建(包含文件权限设置 Linux环境下)
  2. python多线程和多进程的区别_python中多线程与多进程的区别
  3. 怎样在Github参与一个开源项目
  4. 每天都在支付,你真的了解信息流和资金流?
  5. mysql删除完全重复数据库_MySQL中删除完全重复数据的准确SQL语句
  6. 计算机主机有自带的声音吗,台式电脑主机前面的插孔没声音怎么回事?如何解决?...
  7. android系统级浮层,android 新手引导浮层的实现
  8. python-lambda(匿名函数)原理与应用
  9. novipnoad电影网站分析
  10. java 分卷压缩_Java:分卷压缩和解压缩请选择Zip4j
  11. 在docker中运行自己的eureka服务端
  12. 【机器学习|数学基础】Mathematics for Machine Learning系列之矩阵理论(18):方阵的幂级数
  13. 区块链大戏上演!陈伟星VS朱啸虎公开互怼数个回合 | 区块链日报
  14. 紫薇星上的Java——映射转换
  15. Android Handle用法
  16. 顽石互动创始人吴刚:走高品质的发展道路
  17. wsappx导致系统崩溃
  18. 8.五言律诗和绝句的句型及平仄格式
  19. SAP案例教程STO公司间采购前台操作
  20. android手机如何到导出电话号码,手机通讯录怎么导入到新手机?这招太给力了!...

热门文章

  1. Opencv FFmpeg Ubuntu下编译问题
  2. win10控制视频声音大小
  3. 19年8月 字母哥 第五章 静态资源与模板引擎的整合 用热点公司网不行
  4. String path = request.getContextPath()和String basePath = request.getScheme()
  5. session实现购物车
  6. Dijkstra 算法——计算有权最短路径(边有权值)
  7. java反射机制+继承设计技巧
  8. 会话技术Session
  9. log4j2自动删除_登录样式:log4j 2,上下文,自动清除…全部不附带任何字符串!...
  10. tcga癌症亚型获取_亚型多态性应用于元组的危险