<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/css" href="/stylesheets/rss.css"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
  <channel>
    <title>BlackBox : Groovy DSL steps</title>
    <link>http://www.warneronstine.com/blog/articles/2007/06/05/groovy-dsl-steps</link>
    <language>en-us</language>
    <ttl>40</ttl>
    <description>Where technology and art disappear</description>
    <item>
      <title>Groovy DSL steps</title>
      <description>&lt;p&gt;What are some of the basic steps that I&amp;#8217;ve followed as I create my DSLs (especially with respect to Groovy)? &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;What are your spoken and unspoken requirements?&lt;/li&gt;
&lt;li&gt;Who is the intended user? (this will help you decide some of the other questions later)&lt;/li&gt;
&lt;li&gt;Has this kind of problem been solved before?&lt;/li&gt;
&lt;li&gt;How did they solve it? (Language, Toolset, Techniques?)&lt;/li&gt;
&lt;li&gt;How closely does that solution match our requirements?&lt;/li&gt;
&lt;li&gt;What can we take away from that solution (if it doesn&amp;#8217;t match the requirements)?&lt;/li&gt;
&lt;li&gt;What kind of DSL do you want overall? (Internal or External)&lt;/li&gt;
&lt;li&gt;Prototype, prototype, prototype - even if it is an Internal DSL you will still want to start out with a working prototype that your intended audience can play with and give you feedback on. This should be an iterative process to refine the language.&lt;/li&gt;
&lt;li&gt;External DSL - how to implement?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I will cover the first 8 of these, and I will leave the External DSL for a later post (sorry ;-). For this I&amp;#8217;ll use the steps that I&amp;#8217;m currently going through on my own code to illustrate my own thought process.&lt;/p&gt;

&lt;h3&gt;Requirements&lt;/h3&gt;

&lt;p&gt;So, what are my requirements for my main two DSLs - &lt;code&gt;QueryBuilder&lt;/code&gt; and &lt;code&gt;ViewBuilder&lt;/code&gt; (this doesn&amp;#8217;t exist yet, but starting on the planning right now). For &lt;code&gt;QueryBuilder&lt;/code&gt; I wanted a clean syntax that makes it easy for developers to create constraints/restrictions on a database query. Ultimately the query could be executed by Hibernate, JPA, iBatis, whatever, so it should be ORM-agnostic. This actually isn&amp;#8217;t too hard as they all have this concept of a criteria on an object/table and restrictions for that query. And the same goes for &lt;code&gt;ViewBuilder&lt;/code&gt;, I want an HTML-like tree syntax that I can specify components in as well as attributes that will be applied to the view when it is built for me.&lt;/p&gt;

&lt;h3&gt;User&lt;/h3&gt;

&lt;p&gt;This one is easy, I am targeting Web application developers, initially I am targeting Tapestry Web application developers, but since the framework will be pluggable (probably around the 2.0 time) you can specify what specific pieces you want to use (Tapestry/JSF + Hibernate/JPA + Spring 1.x/2.x/Guice, etc.).&lt;/p&gt;

&lt;h3&gt;Has this problem been solved before?&lt;/h3&gt;

&lt;p&gt;In the case of the &lt;code&gt;QueryBuilder&lt;/code&gt;, yes. Grails currently has an implementation called &lt;a href="http://grails.codehaus.org/Hibernate+Criteria+Builder"&gt;&lt;code&gt;HibernateCriteriaBuilder&lt;/code&gt;&lt;/a&gt;. This has a nice syntax for specifying criteria and restrictions on that criteria. As for the &lt;code&gt;ViewBuilder&lt;/code&gt; I don&amp;#8217;t think this has been solved yet, but I will be looking. There is something similar in Groovy&amp;#8217;s core for creating arbitrary HTML, which is close but not exactly what I&amp;#8217;m looking for as I will need to generate more than just HTML from it.&lt;/p&gt;

&lt;h3&gt;How did they solve it?&lt;/h3&gt;

&lt;p&gt;Both of these were solved using Groovy&amp;#8217;s &lt;code&gt;BuilderSupport&lt;/code&gt; object which allows you to build up arbitrary &amp;#8220;nodes&amp;#8221; from a collection of method, property and closure calls. Very powerful and a little difficult to wrap your head around the first 10 times you look at it ;-) (alright, maybe it was just me, but that took a bit to fully understand what the hell it was doing).&lt;/p&gt;

&lt;h3&gt;How closely does that solution match our requirements?&lt;/h3&gt;

&lt;p&gt;First, for the &lt;code&gt;HibernateCriteriaBuilder&lt;/code&gt; it actually will build up a real, live Hibernate criteria and use it, which unfortunately is not what I want. I need to generate the Java code that will come out of it. And the &lt;a href="http://groovy.codehaus.org/Creating+XML+using+Groovy%27s+MarkupBuilder"&gt;&lt;code&gt;MarkupBuilder&lt;/code&gt;&lt;/a&gt; gets me part of the way there but not quite what I&amp;#8217;m looking for.&lt;/p&gt;

&lt;h3&gt;What can we take away from that solution?&lt;/h3&gt;

&lt;p&gt;I decided to take away the syntax from &lt;code&gt;HibernateCriteriaBuilder&lt;/code&gt; and looked at how they implemented it to see what I could do with that. And for the &lt;code&gt;ViewBuilder&lt;/code&gt; I am going to extend &lt;code&gt;BuilderSupport&lt;/code&gt; itself and use that to build up my nodes of whatever objects (so more than just plain HTML text, actually objects that represent things).&lt;/p&gt;

&lt;h3&gt;What kind of DSL do you want overall?&lt;/h3&gt;

&lt;p&gt;Definitely shooting for internal I think, but that doesn&amp;#8217;t preclude having some kind of external DSL for the class creation stuff (that was a giant pain to do in Groovy/Java - just not all of the information I actually needed). So, having some kind of custom language for defining models could definitely come in handy down the road, but I haven&amp;#8217;t decided anything yet. Plus, as I learn more Groovy and get feedback/suggestions I may stumble across something that simplifies my design greatly.&lt;/p&gt;

&lt;h3&gt;Prototype, prototype, prototype&lt;/h3&gt;

&lt;p&gt;This, aside from requirements and research is probably the most valuable step. Once you decide what you are going to do, how in the world do you do it? Especially if you&amp;#8217;re dealing with Meta-programming (which can be a hard concept to wrap your head around)?&lt;/p&gt;

&lt;p&gt;Here is where my experience will hopefully prove valuable to someone out there, here are the steps that I took when developing my &lt;code&gt;QueryBuilder&lt;/code&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Write the Unit tests first, start with the simplest test you can think of for how your language should work&lt;/li&gt;
&lt;li&gt;Run it - yeah I know its going to fail, but prove it to yourself ;-)&lt;/li&gt;
&lt;li&gt;Make it go green - whether you go ahead and create a simple class that has one method in it that does what you want do that&lt;/li&gt;
&lt;li&gt;Write another 2 tests - think about them, how are they going to change that class you just wrote, how much more complex is it going to make the logic you need to write to make sure you do what you expect.&lt;/li&gt;
&lt;li&gt;Fix the first test - is it time to extend &lt;code&gt;DelegatingMetaClass&lt;/code&gt; yet? Or maybe try something simpler like a &lt;code&gt;Category&lt;/code&gt;? Maybe the new &lt;code&gt;ExpandoMetaClass&lt;/code&gt; will work. Try a few of them out, but I don&amp;#8217;t recommend you dive right into extending &lt;code&gt;BuilderSupport&lt;/code&gt;, not yet, not unless you have already used it before and understand fully what it does. Throw in lots of &lt;code&gt;println "calling so and so with these arguments"&lt;/code&gt;. These help identify that what you are expecting is actually happening while you write your DSL.&lt;/li&gt;
&lt;li&gt;Did that work? Good, write it so the next test succeeds.&lt;/li&gt;
&lt;li&gt;Continue doing 4, 5, and 6 until you are happy and ready to show it to someone&lt;/li&gt;
&lt;li&gt;Let them play with it, get their feedback. Rinse, repeat, refactor. (Here is where I would suggest you revisit the &lt;code&gt;BuilderSupport&lt;/code&gt; idea, does it make sense? Remember not everything is an arbitrary nested tree, so not everything will benefit from using this structure.)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Well, I hope that this is helpful to someone ;-). I really have gotten the DSL bug and (mostly) enjoy writing them. If you run into a weird error, throw it out to the Groovy list, someone should be able to help you out.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Addendum&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I meant to add this in when I first started thinking about this post. When I started writing my &lt;code&gt;QueryBuilder&lt;/code&gt; I didn&amp;#8217;t start out with it generating anything but simple &lt;code&gt;select&lt;/code&gt; strings. This helped me visualize the proper nesting of things without getting too complex. Once that was working right I changed my unit tests to expect the actual Java code I wanted back and changed the logic of what the DSL output.&lt;/p&gt;</description>
      <pubDate>Tue, 05 Jun 2007 13:30:00 -0700</pubDate>
      <guid isPermaLink="false">urn:uuid:6a99802d-a3be-412f-863a-60d9f5741dae</guid>
      <author>Warner Onstine</author>
      <link>http://www.warneronstine.com/blog/articles/2007/06/05/groovy-dsl-steps</link>
      <category>programming</category>
      <category>groovy</category>
      <category>dsl</category>
      <category>java</category>
      <trackback:ping>http://www.warneronstine.com/blog/articles/trackback/296</trackback:ping>
    </item>
    <item>
      <title>"Groovy DSL steps" by Leo</title>
      <description>&lt;p&gt;Hey, Warner. I left made a response on &lt;a href="http://u.arizona.edu/~przybyls/2007/06/embedding-internal-dsl-using-kuali.html" rel="nofollow"&gt;my blog here.&lt;/a&gt;. It's always a great idea to outline a systematic approach like you have. A lot of people fail to do that, and they end up buying books that tell them how just to get that much out of it. Very good. I hope it helps a lot of people. &lt;/p&gt;</description>
      <pubDate>Mon, 11 Jun 2007 05:13:26 -0700</pubDate>
      <guid isPermaLink="false">urn:uuid:bda72dab-3241-4215-a4b7-9633b8879536</guid>
      <link>http://www.warneronstine.com/blog/articles/2007/06/05/groovy-dsl-steps#comment-11</link>
    </item>
    <item>
      <title>"Groovy DSL steps" by Warner Onstine</title>
      <description>&lt;p&gt;Guillaume, I definitely agree. I wanted to come up with some basics, but the user-level involvement definitely has to be there. It's hidden right now in the Prototype phase I talk about, but should be more fully discussed in a future post. I have several posts in my head right now so I'll jot this down as one to write up ;-)&lt;/p&gt;</description>
      <pubDate>Thu, 07 Jun 2007 12:43:10 -0700</pubDate>
      <guid isPermaLink="false">urn:uuid:2ad004d7-a936-429a-a168-d27f9ac11d38</guid>
      <link>http://www.warneronstine.com/blog/articles/2007/06/05/groovy-dsl-steps#comment-10</link>
    </item>
    <item>
      <title>"Groovy DSL steps" by Warner Onstine</title>
      <description>&lt;p&gt;This comment came from &lt;a href="http://glaforge.free.fr/weblog/" rel="nofollow"&gt;Guillaume Laforge&lt;/a&gt; (Groovy lead) on the Groovy users list:&lt;/p&gt;

&lt;blockquote&gt;
    &lt;p&gt;This is a nice wrap-up of the steps to follow.
    The thing I feel is missing a little is the "invention" of the DSL in
    itself with the end-user.
    I think we have to stress that part more.
    You have to know what's possible to do with Groovy in terms of DSL, you have to speak at length with your users, and incrementally design on paper (or on screen) what the DSL will look like.
    I think this step should be emphasized a bit more in the approach.&lt;/p&gt;
&lt;/blockquote&gt;</description>
      <pubDate>Thu, 07 Jun 2007 12:40:06 -0700</pubDate>
      <guid isPermaLink="false">urn:uuid:efb57515-8a70-43f5-8194-c7fd4d3eda91</guid>
      <link>http://www.warneronstine.com/blog/articles/2007/06/05/groovy-dsl-steps#comment-9</link>
    </item>
    <item>
      <title>"Groovy DSL steps" by Graeme Rocher</title>
      <description>&lt;p&gt;nteresting, though I find that in the beginning it seems like a good
idea to extend BuilderSupport, but later you realise it is too
limiting and overriding invokeMethod is far more flexible as far as
the syntax options you have available to you&lt;/p&gt;

&lt;p&gt;It of course depends on the DSL you are writing&lt;/p&gt;

&lt;p&gt;Cheers
Graeme&lt;/p&gt;</description>
      <pubDate>Wed, 06 Jun 2007 07:19:43 -0700</pubDate>
      <guid isPermaLink="false">urn:uuid:1c023565-f0ac-4cbc-abfa-ac2861e63ae3</guid>
      <link>http://www.warneronstine.com/blog/articles/2007/06/05/groovy-dsl-steps#comment-8</link>
    </item>
  </channel>
</rss>
