Take a look at the following code, an example of a specification written using spek
In this code, given, on and it are all functions.
Kotlin allows top-level functions to be defined (without the need for them to belong to a class). As such, we could merely declare these functions in a single file as below:
At first sight it might not seem like a bad approach, but it is. The problem is that you cannot prevent someone from calling the code like so:
or any other weird combination for that matter.
This means that we would now have to put in additional runtime checks to verify that things are called in the correct manner; context has been set up before the action, the action has been executed before the assertions and so on and so forth. Pain.
Extension Function Literals
We’ve already seen that Kotin has extension functions, similar to C#. We’ve also seen that we can define extension functions as function literals:
Combining this with high-order functions, that is a function that takes a function as a parameter, we can do:
given is still a top-level function. However, the diference is that on and it are no longer top-level. Instead, we’re creating three different classes: Given, On and It.
Let’s take a look at the Given class. This class has a method that takes two parameters: a string, which is the description and a second parameter which is the extension function literal we’ve been talking about:
The parameter is an extension function on the On class, which takes no parameters and returns no value (Unit in Kotlin - void).
We repeat the same pattern with the On and It classes. By doing this, we now enforce a certain flow at compile time and prohibit out of order usage.
You can see also in the code, that the It class contains a series of assertion methods, exactly where they belong.
We can see that with some simple extension function literals, we can easily impose a series of restrictions on our DSL’s. Of course, in this case, the example is quite straightforward but the same thing can be applied to designing other DSL’s such as HTML builders et al.
[Thanks to @orangy for highlighting the issue and refactoring of Spek to this]