This is the 25th day of my participation in the November Gwen Challenge. Check out the event details: The last Gwen Challenge 2021
DSL
Domain-specific language: A computer programming language that focuses on a specific Domain and is specific to only a subset of expressions.
It has several features:
- Method Chaining
- Functional Sequence
- Nested Functions are Nested Functions
- Lambda Expressions/Closures Lambda Expressions/Closures
It’s kind of abstract, so let’s look at the code
Suppose you want to send some emails, and you need a class that can easily set the recipient, sender, subject, and content.
A traditional Java API (the business code is omitted) :
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(a) {}}Copy the code
The test should be written like this:
public static void main(String[] args) {
Mailer mailer = new Mailer();
mailer.from("[email protected]");
mailer.to("[email protected]");
mailer.subject("build notification");
mailer.message("some details about build status");
mailer.send();
}
Copy the code
We can do some refactoring to make the API smoother and more dSL-like.
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(a) {}}Copy the code
Testing:
Copy the code
That looks better, but it would be nice to eliminate new. The user’s interest is in sending mail, not in creating objects.
public static void main(String[] args) {
new Mailer()
.from("[email protected]")
.to("[email protected]")
.subject("build notification")
.message("some details about build status")
.send();
}
Copy the code
Testing:
public static void main(String[] args) {
Mailer.mail()
.from("[email protected]")
.to("[email protected]")
.subject("build notification")
.message("some details about build status")
.send();
}
Copy the code
You can do a static import
public static void main(String[] args) {
import staticdsl.example.Mailer.mail; mail() .from("[email protected]")
.to("[email protected]")
.subject("build notification")
.message("some details about build status")
.send();
}
Copy the code
This completes a DSL statement. In general, a DSL written in Java will not result in a language that business users can use, but a language that business users will find readable and, from a programmer’s point of view, straightforward to read and write.
summary
The best way to create a DSL is to first prototype the required API and then implement it within the constraints of the underlying language. The implementation of the DSL will involve continuous testing to make sure that we are really aiming in the right direction. This “prototype-test” approach is exactly what the TDD-test-driven Development pattern (TDD) advocates.
In fact, JDK8 provides a lot of APIS have a lot of internal DSL semantics, such as Stream find, count and other operations are a kind of DSL semantic expression, this article is only a simple explanation of how to construct DSL, if you have the opportunity to plan to find a real business code with DSL way reconstruction, please look forward to.