Thursday, March 13, 2008

I might be getting this DSL stuff

I know I am a little slow. I usually have to hear and see something three times before I start to grasp it. I know it was that way with Aspects and it has definitely been that way with DSLs. At every conference I have gone to for the last 2 years I have made sure to attend DSL talks. I have probably seen Neal Ford speak on the topic at least five times alone. By this point, I have definitely understood the concepts. Hearing Neal Ford's Starbuck's language example gave me that aha moment. But I have not been able to take it to the next step. I have not been able to put it into practice. That may be because I have been writing code so long I don't see problem with curly braces and long lists of method chaining and ugly parameters. But tonight, I think I got it. I think I saw the value in a whole new way.

I took this simple example written in Groovy that only a programmer could love.

println this.class.getResourceAsStream('readme.txt').getText()

This example only reads a file found in the classpath and then prints it to standard out. It might look pretty standard to developers but to anybody else it looks like a cryptic foreign language. This example is even in Groovy which simplifies the code a lot compared to a Java equivalent. (I actually started writing a Java equivalent for this post but it was too painful after writing the Groovy solution so I stopped.)

So after looking at this example, I set out to write the same functionality in a human readable format. In all the DSL sessions I have attended, they always say start of with the end in mind and make it look like a sentence.

So, I came up with "write readme.txt contents". In code it looks like the following example:

write 'readme.txt'.contents()

Not to bad for my first DSL. I think the intent is pretty clear. Next is how I implemented it.

String.metaClass.contents = {
this.class.getResourceAsStream(delegate).getText()
}

def write = { file ->
println file
}

write 'readme.txt'.contents()


You can see I used a little bit of Groovy's MOP (Meta-Object Programming) to add a contents method to the String class that does the resource loading base on the delegate which is the object on which the message was passed which in this case is the 'readme.txt' String. Next I defined a write closure that does a println on the parameter passed. Note using Groovy's optional parentheses makes it flow much more like a natural sentence.

Now that I have reached this milestone, I am afraid all standard code is going to repulse me. I know I am stuggling to write Java code after having used Groovy.

4 comments:

rhyolight said...

That is a great simple example of a DSL in Groovy. Very simple, concise, and makes perfect sense. Great job!

Dmitriy Kopylenko said...

Since Groovy has the optional method parentheses, the example could even look like this: writeContentsOf 'readMe.txt'

J Salvador said...

not running on groovy 1.51

J Salvador said...

not running on groovy 1.51