Java如何构造DSL方法重构
作者:??你呀不牛?? 发布时间:2021-10-10 02:04:09
DSL
Domain-specific language: 一种专注于某一领域,仅针对部分表达方式的计算机编程语言。
特点
方法链 Method Chaining
功能序列 Functional Sequence
嵌套函数 Nested Functions 嵌套函数
Lambda表达式/闭包 Lambda Expressions/Closures
概念有点抽象,先看代码吧
假设你想发一些邮件,你需要一个类能够方便的设置收信人、发信人、标题、内容。
一个传统的java api(具体业务代码都省略了):
public class Mailer {
public void from(String fromAddress) {
}
public void to(String toAddress) {
}
public void subject(String theSubject) {
}
public void message(String body) {
}
public void send() {
}
}
测试要这样写:
public static void main(String[] args) {
Mailer mailer = new Mailer();
mailer.from("build@example.com");
mailer.to("example@example.com");
mailer.subject("build notification");
mailer.message("some details about build status");
mailer.send();
}
我们可以做些重构,使这个api更流畅,更像DSL。
package dsl.example;
public class Mailer {
public Mailer from(String fromAddress) {
return this;
}
public Mailer to(String toAddress) {
return this;
}
public Mailer subject(String theSubject) {
return this;
}
public Mailer message(String body) {
return this;
}
public void send() {
}
}
这样看起来好多了,但是如果能消除new就更好了。因为用户的兴趣在于发送邮件,而不是在创建对象。
public static void main(String[] args) {
new Mailer()
.from("build@example.com")
.to("example@example.com")
.subject("build notification")
.message("some details about build status")
.send();
}
测试:
public static void main(String[] args) {
Mailer.mail()
.from("build@example.com")
.to("example@example.com")
.subject("build notification")
.message("some details about build status")
.send();
}
可以做一下静态导入
public static void main(String[] args) {
import static dsl.example.Mailer.mail;mail()
.from("build@example.com")
.to("example@example.com")
.subject("build notification")
.message("some details about build status")
.send();
}
这样,一个DSL的语句就完成了。一般来说,使用Java编写的DSL不会造就一门业务用户可以上手的语言,而会是一种业务用户也会觉得易读的语言,同时,从程序员的角度,它也会是一种阅读和编写都很直接的语言。
小结
创建DSL最好的方法是,首先将所需的API原型化,然后在基础语言的约束下将它实现。DSL的实现将会牵涉到连续不断的测试来肯定我们的开发确实瞄准了正确的方向。该“原型-测试”方法正是测试驱动开发模式(TDD-Test-Driven Development)所提倡的。
其实JDK8提供的很多api已经有很多内部DSL的语义,比如Stream流的find、count等操作都是一种DSL的语义表达,本文只是简单的说明了如何构造DSL,有机会计划找一个实际的业务代码用DSL的方式重构,敬请期待。
来源:https://juejin.cn/post/7034906507510562824


猜你喜欢
- 1 初识Mybatis-Plus MyBatis-Plus简称 MP,是一个 MyBatis的增强工具,在MyBatis的基础上只做增强不
- 因为一直用spring整合了mybatis,所以很少用到mybatis的session缓存。 习惯是本地缓存自己用map写或者引入第三方的本
- JPanel是面板组件,非顶层容器,一个界面只有可以有一个JFrame窗体组件,但可以有多个Jpanel面板,而JPanel上也可以使用Fl
- 前后端分离开发中,一般都会遇到请求跨域问题。而且一般也会遇到登陆失效问题。今天就以springboot和vue为例来看如何解决上述问题增加过
- jmap是java自带的工具1. 查看整个JVM内存状态jmap -heap [pid]2. 查看JVM堆中对象详细占用情况jmap -hi
- 数据导出到Excel几乎是所有客户都会提出的一个需求。下面我就分享一下我的代码。首先需要引入的jar包:然后就是正式代码了。package
- 前言之前用springboot的时候,只知道捕获异常使用try{}catch,一个接口一个try{}catch,这也是大多数开发人员异常处理
- 今天在APP中增加一个添加项目的功能,项目的主键为整数,要让它自增长。既然要自增长,那么在代码里面就不用给id字段赋值。但是调试的时候发现不
- 查询文档 & 基本操作为了方便学习, 本节中所有示例沿用上节的索引按照ID单个GET class_1/_doc/1查询结果:{ &n
- 完整代码:https://github.com/iyuanyb/Downloader多线程下载及断点续传的实现是使用 HTTP/1.1 引入
- 我就废话不多说了,大家还是直接看代码吧~ public List<FreightM> sortList(List&l
- 单线程是安全的,因为线程只有一个,不存在多个线程抢夺同一个资源代码例子:public class SingleThread {int num
- 同时使用and和or的查询UserServiceImpl 类,service实现类import org.springframework.be
- 这篇文章主要介绍了Mybatis模糊查询及自动映射实现详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要
- jackson提供对LocalDate的支持SpringBoot默认使用jackson来进行json格式转换,我们在配置文件中加入如下配置可
- 条形码,是由宽度不等的多个黑条和空白所组成,用以表达一组信息的图形标识符。通过给文档添加条形码,可以直观,快捷地访问和分享一些重要的信息。本
- 关联篇:深入Android的消息机制源码详解-Handler,MessageQueue与Looper关系关联篇:Handler内存泄漏及其
- 本文实例为大家分享了Android实现登录注册功能的具体代码,供大家参考,具体内容如下运行环境 Android Studio总体效果图一、
- Vitamio是一个功能强大而稳定的播放器库,它支持多种视频格式和编解码方式,并且具有快速、流畅的播放效果,因此在一些对播放质量要求比较高的
- UI编程通常都会伴随事件处理,Android也不例外,它提供了两种方式的事件处理:基于回调的事件处理和基于 * 的事件处理。对于基于 * 的