<?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 : Tag groovy</title>
    <link>http://www.warneronstine.com/blog/articles/tag/groovy</link>
    <language>en-us</language>
    <ttl>40</ttl>
    <description>Where technology and art disappear</description>
    <item>
      <title>Is Maven going away?</title>
      <description>&lt;p&gt;First, let me say, I like &lt;a href="http://maven.apache.org"&gt;Maven&lt;/a&gt; - a lot. I&amp;#8217;ve liked the idea, if not the execution, since 1.0 (yes, I know there is some serious bad blood for the implementation of 1.0, and yes I still liked it). But I&amp;#8217;ve recently run into some irritating problems with Maven that would again, I think, require a major reworking of what it does.&lt;/p&gt;

&lt;p&gt;Here is the main issue Maven is designed to handle one language only for its compilation - primarily Java. This is rapidly starting to fall apart now that the JVM has some serious contenders besides Java, namely &lt;a href="http://groovy.apache.org"&gt;Groovy&lt;/a&gt;, &lt;a href="http://jruby.codehaus.org/"&gt;JRuby&lt;/a&gt;, &lt;a href="http://www.jython.org/"&gt;Jython&lt;/a&gt;, and &lt;a href="http://www.scala-lang.org/"&gt;Scala&lt;/a&gt;. There are some hackish things for getting Maven to deal with these, however it still only has one &amp;#8220;true&amp;#8221; source directory for compilation. A case in point is a mixed Java/Groovy project - trying to get &lt;a href="http://www.jetbrains.com/idea/"&gt;IntelliJ&lt;/a&gt; to respect the fact that I want not one, but two main source directories is a pain in the ass as I have to either tell it not to sync everytime I launch or I have to refix the source directories each time I update the project. &lt;/p&gt;

&lt;p&gt;This is what triggered this post - what happens when I want to do some &lt;a href="http://labs.adobe.com/technologies/flex/"&gt;Flex&lt;/a&gt; programming with some Java, ActionScript and MXML, all of these are true source files (and in Maven specfic directories). I&amp;#8217;m sure some Mavenite is going to say that these should be separate projects, but in alot of cases they aren&amp;#8217;t and it doesn&amp;#8217;t make sense to actually separate them into sub-projects. And I&amp;#8217;m equally as sure that some Ant-ite is going to come along and tell me to use &lt;a href="http://ant.apache.org/"&gt;Ant&lt;/a&gt; - I won&amp;#8217;t. Ant is stuck in the past and I won&amp;#8217;t use it unless I absolutely have to. I like the &amp;#8220;imposed&amp;#8221; structure that Maven offers. I can walk up to any project and know where  to find stuff instead of blindly hunting around for hours trying to piece it together like some giant source-code jigsaw puzzle, blech.&lt;/p&gt;

&lt;p&gt;So, I&amp;#8217;m at cross-roads, what should I do? There is &lt;a href="http://ant.apache.org/ivy/"&gt;Ivy&lt;/a&gt; (for dependency management -which they got from Maven natch), but that requires Ant, blech. There&amp;#8217;s also &lt;a href="http://gant.codehaus.org/"&gt;Gant&lt;/a&gt;, ok, this is better, but still Ant. &lt;a href="http://groovy.codehaus.org/GMaven"&gt;GMaven&lt;/a&gt;, but I&amp;#8217;m right back where I started.&lt;/p&gt;

&lt;p&gt;Enter, &lt;a href="http://www.gradle.org/"&gt;Gradle&lt;/a&gt;, a new Groovy-based build system that offers alot of the benefits of Maven without locking you in and the flexibility of Ant. I&amp;#8217;m not 100% sold on it yet, but I&amp;#8217;m going to give it a shot for a relatively complex project that will have a fair amount of Java, Groovy and other fun resource files. It looks interesting in that all the build files are actually Groovy scripts that are a DSL (like Gant files). Here&amp;#8217;s a short example with some dependencies (taken directly from their examples in the download).&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;import org.gradle.api.tasks.util.FileSet

usePlugin('groovy')

group = 'org.gradle'
version = '1.0'

sourceCompatibility = 1.5
targetCompatibility = 1.5

dependencies {
   clientModule(['groovy'], ":groovy-all:1.6-beta-1") {
       dependency(":commons-cli:1.0")
   }
   compile project(':groovycDetector')
   testCompile ":junit:4.4"
}

compile {
   exclude('**/Exclude.java')
   groovyExclude('**/ExcludeGroovy.groovy')
   groovyJavaExclude('**/ExcludeGroovyJava.java')
}

manifest.mainAttributes(myprop: 'myvalue')
metaInf &amp;lt;&amp;lt; new FileSet(new File(srcRoot, 'metaInfFiles'))

test.options.systemProperties['org.gradle.integtest.buildDir'] = buildDir.absolutePath
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I will try and keep everyone up to date as I continue to investigate this new build system. They also state that they are going to be supporting polyglot programming in the near future which I&amp;#8217;m looking forward to.&lt;/p&gt;</description>
      <pubDate>Sun, 06 Jul 2008 07:49:33 -0700</pubDate>
      <guid isPermaLink="false">urn:uuid:f693853e-5003-4e42-bab5-7bf1838bfc9f</guid>
      <author>Warner Onstine</author>
      <link>http://www.warneronstine.com/blog/articles/2008/07/06/is-maven-going-away</link>
      <category>programming</category>
      <category>maven</category>
      <category>java</category>
      <category>groovy</category>
      <category>scala</category>
      <category>polyglot</category>
      <trackback:ping>http://www.warneronstine.com/blog/articles/trackback/321</trackback:ping>
    </item>
    <item>
      <title>Groovy DSL roundup</title>
      <description>&lt;p&gt;This is my first attempt at categorizing some of the DSLs I&amp;#8217;ve run across into some kind of logical grouping. First I&amp;#8217;ll list out some Groovy DSL examples (sound off in the comments for those I&amp;#8217;m not aware of, the more the better). I&amp;#8217;ll go through the DSLs first and then look at the possible categories after the break. And the first two are mine that I created&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.warneronstine.com/blog/articles/2007/04/27/my-groovy-hom-take-2"&gt;Groovy Higher Order Messaging (HOM)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Math DSL &lt;a href="http://www.warneronstine.com/blog/articles/2007/11/23/math-dsl-beginning"&gt;Part 1&lt;/a&gt; and &lt;a href="http://www.warneronstine.com/blog/articles/2007/11/26/math-dsl-part-deux-elementary-row-operations-eros"&gt;Part 2&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://groovy.codehaus.org/GroovyLab"&gt;GroovyLab&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://json-lib.sourceforge.net/groovy.html"&gt;Json-lib with Groovy&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://grails.org/doc/1.0.x/guide/14.%20Grails%20and%20Spring.html#14.3%20Runtime%20Spring%20with%20the%20Beans%20DSL"&gt;Grails&amp;#8217; Spring Bean DSL&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://grails.org/doc/1.0.x/guide/5.%20Object%20Relational%20Mapping%20%28GORM%29.html#5.4.1%20Dynamic%20Finders"&gt;Grails&amp;#8217; Dynamic Finders&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://grails.org/doc/1.0.x/guide/5.%20Object%20Relational%20Mapping%20%28GORM%29.html#5.4.2%20Criteria"&gt;Grails&amp;#8217; Criteria DSL&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://grails.org/Validation+Reference"&gt;Grails&amp;#8217; Domain Class Validation DSL&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jparsec.codehaus.org/Groovy+Parser"&gt;JParsec&amp;#8217;s Groovy interface&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://glaforge.free.fr/weblog/index.php?itemid=233"&gt;Guillaume&amp;#8217;s Unit Manipulation DSL&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://docs.codehaus.org/display/GROOVY/Using+Ant+from+Groovy"&gt;AntBuilder&lt;/a&gt; (as well as XMLBuilder, SwingBuilder, etc. - builders, essentially)&lt;/li&gt;
&lt;li&gt;&lt;a href="http://kenbarclay.blogspot.com/"&gt;Ken Barclay&amp;#8217;s GParsec&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Human readable date manipulation such as in &lt;a href="http://glaforge.free.fr/weblog/index.php?itemid=187"&gt;Guillaume&amp;#8217;s example&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://tiago.org/ps/2008/02/25/dsl-tactics-in-groovy-1many/"&gt;Tiago Ant&amp;atilde;o&amp;#8217;s Malaria Drug DSL&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://codeforfun.wordpress.com/2007/04/09/gspec-for-java-bdd/"&gt;GSpec Behavior Driven Development&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I know there are more out there but this is a good starting point for sure.&lt;/p&gt;

&lt;p&gt;Now, on to the actual categories of DSL &amp;#8220;types&amp;#8221;&lt;/p&gt;

&lt;p&gt;I have been paying attention to Martin Fowler&amp;#8217;s new &lt;a href="http://www.martinfowler.com/dslwip/"&gt;DSL book&lt;/a&gt; in which he specifies several types of Internal DSLs. I&amp;#8217;m not 100% on board with all of these yet, but here they are (of course these may change as this is a work in progress, so if he changes them it isn&amp;#8217;t my fault :P):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.martinfowler.com/dslwip/ExpressionBuilder.html"&gt;Expression Builder&lt;/a&gt;: A layer that provides a fluent interface over a regular API&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.martinfowler.com/dslwip/FunctionSequence.html"&gt;Function Sequence&lt;/a&gt;: A combination of function calls as a sequence of statements.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.martinfowler.com/dslwip/NestedFunction.html"&gt;Nested Function&lt;/a&gt;: Compose functions by nesting function calls as arguments of of other calls.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.martinfowler.com/dslwip/MethodChaining.html"&gt;Method Chaining&lt;/a&gt;: Make modifier methods return the host object so that multiple modifiers can be invoked in a single expression.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.martinfowler.com/dslwip/ObjectScoping.html"&gt;Object Scoping&lt;/a&gt;: Put DSL code in a subclass of a class that provdes the DSL vocabulary.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.martinfowler.com/dslwip/Closure.html"&gt;Closure&lt;/a&gt;:
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.martinfowler.com/dslwip/NestedClosure.html"&gt;Nested Closure&lt;/a&gt;: Express statement sub-elements of a function call by putting them into a closure in an argument.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.martinfowler.com/dslwip/LiteralCollection.html"&gt;Literal Collection Expression&lt;/a&gt;: Form language expressions using literal collection syntax&lt;/li&gt;
&lt;li&gt;Dynamic Reception: Handle messages without defining them in the code&lt;/li&gt;
&lt;li&gt;Annotation: Data about program elements, such as classes and methods, which can be processed during compilation or execution.&lt;/li&gt;
&lt;li&gt;Macro: Define DSL expressions as macro definitions&lt;/li&gt;
&lt;li&gt;Parse Tree Manipulation: Capture the parse tree of a code fragment to manipulate it with DSL processing code.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ok, so these are the basic categories as Martin has defined them. How do these map up to the tools and techniques we have in Groovy? &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Method/Property Missing - a special method that is called when a method can not be found allowing a developer to intercept the call
&lt;ul&gt;
&lt;li&gt;Maps to Dynamic Reception fairly well&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Categories - allows new methods to be added to any class at runtime
&lt;ul&gt;
&lt;li&gt;Could fit into Object Scoping or maybe a new one, Duck Typing? - not sure&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;ExpandoMetaClass - a dynamically expandable bean
&lt;ul&gt;
&lt;li&gt;Again Dynamic Reception&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Closures/Nested Closures
&lt;ul&gt;
&lt;li&gt;Closures/Nested Closures&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Relaxed rules on the use of parentheses
&lt;ul&gt;
&lt;li&gt;Hmm, not sure where this would fit&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Built-in list and map syntax
&lt;ul&gt;
&lt;li&gt;I believe this is Literal Collection Expression&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Ability to dynamically add methods to an interface and have concrete classes also have the methods
&lt;ul&gt;
&lt;li&gt;Again, this sounds like Dynamic Reception&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Operator overloading
&lt;ul&gt;
&lt;li&gt;Hmm, again I&amp;#8217;m not sure where this fits&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Annotations
&lt;ul&gt;
&lt;li&gt;Annotation&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;First up we have our builders (AntBuilder, XMLBuilder, Criteria Builder, etc.) these essentially mimic some other existing structure (an Ant build file, XML file, or SQL syntax). What patterns do these use? Just off the top of my head I think I see:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Expression Builder&lt;/li&gt;
&lt;li&gt;Nested Closures&lt;/li&gt;
&lt;li&gt;Dynamic Reception&lt;/li&gt;
&lt;li&gt;Literal Collection Expression&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;JSON-lib&amp;#8217;s Groovy interface has the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Literal Collection Expression&lt;/li&gt;
&lt;li&gt;Dynamic Reception&lt;/li&gt;
&lt;li&gt;Operator Overloading (&lt;code&gt;as&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;My Groovy Higher Order Messaging DSL has:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Dynamic Reception&lt;/li&gt;
&lt;li&gt;Nested Closures&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;My Groovy Math DSL has:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Dynamic Reception&lt;/li&gt;
&lt;li&gt;Nested Closures (or possibly what would be considered Function Sequence in some cases, even though they aren&amp;#8217;t functions but it might fit)&lt;/li&gt;
&lt;li&gt;Operator Overloading&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;GroovyLab has:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Expression Builder&lt;/li&gt;
&lt;li&gt;Probably has more just don&amp;#8217;t have time to dig into the code - I&amp;#8217;m just looking at the quick examples)&lt;/li&gt;
&lt;li&gt;Operator Overloading&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Guillaume&amp;#8217;s Unit Manipulation DSL has:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Expression Builder&lt;/li&gt;
&lt;li&gt;Dynamic Reception&lt;/li&gt;
&lt;li&gt;Closure/Nested Closure&lt;/li&gt;
&lt;li&gt;Operator Overloading&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ken Barclay&amp;#8217;s GParsec has:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Dynamic Reception&lt;/li&gt;
&lt;li&gt;Parse Tree Manipulation? (not sure if this qualifies for this or not)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;GroovyRestlet DSL has:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Literal Collection Expression&lt;/li&gt;
&lt;li&gt;Closure/Nested Closure&lt;/li&gt;
&lt;li&gt;Function Sequence&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;GSpec has:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Closure/Nested Closure&lt;/li&gt;
&lt;li&gt;Function Sequence&lt;/li&gt;
&lt;li&gt;Dynamic Reception&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Grails&amp;#8217; Domain Class Validation DSL has:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Literal Colleciton Expression&lt;/li&gt;
&lt;li&gt;Closure&lt;/li&gt;
&lt;li&gt;Macros?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Tiago Ant&amp;atilde;o&amp;#8217;s Malaria Drug DSL has:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Object Scoping&lt;/li&gt;
&lt;li&gt;Dynamic Reception&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Human readable date modification has:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Object Scoping&lt;/li&gt;
&lt;li&gt;Operator Overloading&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now, one of the big things that I think Fowler is missing here (and one that you can see several DSLs take advantage of) is Operator Overloading/Overriding. This, I think, is a key technique in DSLs and one that can make a DSL go from good to great. It&amp;#8217;s all about letting the user think in the context they are in - be it math matrices, sql queries, file and string manipulation (overriding the &lt;code&gt;&amp;lt;&amp;lt;&lt;/code&gt; or &lt;code&gt;&amp;gt;&amp;gt;&lt;/code&gt; operators). It&amp;#8217;s all about the user&amp;#8217;s context and making it easy for them to &amp;#8220;think&amp;#8221; in their domain and not have to worry about the language implementation (I use it quite heavily in my Math DSL to implement matrix operators for example).&lt;/p&gt;

&lt;p&gt;I know I didn&amp;#8217;t hit on all the DSLs I mentioned, but will try and come up with a wiki or something that people can contribute back to. In the mean time sound off in the comments if you have a DSL that I didn&amp;#8217;t mention, or you feel my categorization is wrong (and why). I&amp;#8217;m also curious if there are examples of some of the ones I didn&amp;#8217;t touch on such as Annotations. This is an initial stab at this and as I said earlier I&amp;#8217;m not 100% on board with how Fowler has organized things but I think it&amp;#8217;s a good start.&lt;/p&gt;</description>
      <pubDate>Thu, 24 Apr 2008 09:50:00 -0700</pubDate>
      <guid isPermaLink="false">urn:uuid:245a00d3-2be2-46fb-a01b-9da2db8bc944</guid>
      <author>Warner Onstine</author>
      <link>http://www.warneronstine.com/blog/articles/2008/04/24/groovy-dsl-roundup</link>
      <category>programming</category>
      <category>groovy</category>
      <category>dsl</category>
      <trackback:ping>http://www.warneronstine.com/blog/articles/trackback/318</trackback:ping>
    </item>
    <item>
      <title>Thinking about picking the Groovy DSL book up again</title>
      <description>&lt;p&gt;But before I do I thought I&amp;#8217;d ask everyone out there (who are interested in such a book), what would you like to see in it?&lt;/p&gt;

&lt;p&gt;One possibility I&amp;#8217;ve been tossing around is to turn it into a techniques or cookbook-style book. I&amp;#8217;ve been reading through &lt;a href="http://www.amazon.com/gp/product/0596008031?ie=UTF8&amp;amp;tag=warneronstinecom&amp;amp;linkCode=as2&amp;amp;camp=1789&amp;amp;creative=9325&amp;amp;creativeASIN=0596008031"&gt;&amp;#8220;Designing Interfaces&amp;#8221;&lt;/a&gt; by Jennifer Tidwell. In this book she organizes the interface solutions into different sections and goes through each one with an example and what it solves and when to use it. I really like this idea (but others might not). Originally my book was a &amp;#8220;How do I get started designing DSLs?&amp;#8221; and &amp;#8220;What in the world are they and why should I care?&amp;#8221;.&lt;/p&gt;

&lt;p&gt;Another thing I&amp;#8217;ve been thinking about is ditching the Java part and making it Groovy only. This appeals to me because I feel that Groovy is much cleaner to implement an Internal DSL than Java is. Can you do DSLs in Java? Of course you can, but I&amp;#8217;m not sure that I can give it the best treatment because it isn&amp;#8217;t what I&amp;#8217;m passionate about.&lt;/p&gt;

&lt;p&gt;So, sound off in the comments, let me know what topics you&amp;#8217;d like to see covered, what challenges have you faced in writing a DSL (or API/Framework) that you would have liked someone to trailblaze for you to show the dead-ends first?&lt;/p&gt;</description>
      <pubDate>Wed, 26 Mar 2008 10:30:00 -0700</pubDate>
      <guid isPermaLink="false">urn:uuid:9d272a61-3965-49b2-98a1-2001a11f0102</guid>
      <author>Warner Onstine</author>
      <link>http://www.warneronstine.com/blog/articles/2008/03/26/thinking-about-picking-the-dsl-book-up-again</link>
      <category>programming</category>
      <category>writing</category>
      <category>groovy</category>
      <category>dsl</category>
      <trackback:ping>http://www.warneronstine.com/blog/articles/trackback/311</trackback:ping>
    </item>
    <item>
      <title>Groovy Roadmap</title>
      <description>&lt;p&gt;So Guillaume posted the &lt;a href="http://www.nabble.com/Tentative-Roadmap-to14368039.html#a14368039"&gt;current road map&lt;/a&gt; to the list a couple of days ago and I &lt;a href="http://www.nabble.com/Tentative-Roadmap-to14368039.html#a14383653"&gt;put in my .02&lt;/a&gt; for fixing the (in my eyes) broken operator overloading. And the bug I really wanted is now marked to be fixed in 1.6!&lt;/p&gt;

&lt;p&gt;I honestly can&amp;#8217;t say how happy I am at this and will definitely test this functionality out with my &lt;a href="http://warneronstine.com/groovymath"&gt;Math DSL&lt;/a&gt; that I am working on.&lt;/p&gt;</description>
      <pubDate>Thu, 20 Dec 2007 16:36:36 -0700</pubDate>
      <guid isPermaLink="false">urn:uuid:14955af8-084c-47c1-88c2-32ad4a9aae0f</guid>
      <author>Warner Onstine</author>
      <link>http://www.warneronstine.com/blog/articles/2007/12/20/groovy-roadmap</link>
      <category>programming</category>
      <category>groovy</category>
      <category>news</category>
      <trackback:ping>http://www.warneronstine.com/blog/articles/trackback/308</trackback:ping>
    </item>
    <item>
      <title>Overriding the 'as' operator</title>
      <description>&lt;p&gt;A friend of mine sent me a link to Charles Nutter&amp;#8217;s blog on &lt;a href="http://headius.blogspot.com/2007/12/groovy-in-ruby-implement-interface-with.html"&gt;implementing interfaces using the &lt;code&gt;as&lt;/code&gt; operator&lt;/a&gt;. While I was explaining how it worked to him I remembered that like many operators you can also override this one using &lt;code&gt;asType()&lt;/code&gt;. This got us to thinking when would you use this functionality?&lt;/p&gt;

&lt;p&gt;I have one project I&amp;#8217;m working on right now (not ready to talk yet about as I want more code in place before I unveil it, :-P) but this might be useful. Say that you wanted to duck-type your object for specific class instances. Overriding &lt;code&gt;as&lt;/code&gt; may be one place to do it. &lt;/p&gt;

&lt;p&gt;When would this make sense? Personally I think something like this makes the most sense in a library that provides some kind of functionality to a bunch of classes (rather than a one-off case). But I&amp;#8217;m curious to see how others have used this functionality, would help to shed some light on other uses I hadn&amp;#8217;t thought of. &lt;/p&gt;</description>
      <pubDate>Thu, 06 Dec 2007 09:40:25 -0700</pubDate>
      <guid isPermaLink="false">urn:uuid:4e93957b-7b7c-4893-b1e7-a9f5c6d13d98</guid>
      <author>Warner Onstine</author>
      <link>http://www.warneronstine.com/blog/articles/2007/12/06/overriding-the-as-operator</link>
      <category>programming</category>
      <category>dsl</category>
      <category>groovy</category>
      <trackback:ping>http://www.warneronstine.com/blog/articles/trackback/307</trackback:ping>
    </item>
    <item>
      <title>Math DSL Part Deux - Elementary Row Operations (EROs)</title>
      <description>&lt;p&gt;After sending out my query to the groovy user list I got back some ideas (no offense to Yann, just something I need to tackle on my own, so I didn&amp;#8217;t look at your solution). What I ended up doing was two-fold:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create a new MetaClass using ExpandoMetaClass &lt;/li&gt;
&lt;li&gt;Define a new class that understood what row and matrix it was going to operate on (so it can have its own operator overloading)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Yes it was a little bit of extra work, but worth it. I also implemented my &lt;code&gt;or&lt;/code&gt; operator overloading so that I can specify augmented matrices in three formats:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;A|I&lt;/code&gt; for the identity matrix (only works on square matrices)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;A|0&lt;/code&gt; for the zero column, used for solving the set of linear equations&lt;/li&gt;
&lt;li&gt;&lt;code&gt;A|b&lt;/code&gt; for a vector column, also used for solving the set of linear equations&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As always it helps to learn from others&amp;#8217; mistakes (and oddities) so I&amp;#8217;ll share mine along the road:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;When dealing with EMC (ExpandoMetaClass) watch out for the use of the &lt;code&gt;this&lt;/code&gt; keyword&lt;/li&gt;
&lt;li&gt;Closure delegates don&amp;#8217;t always act the way you would hope when extending &lt;code&gt;GroovyObjectSupport&lt;/code&gt; (at least I couldn&amp;#8217;t get it to work right which is one reason why I switched to EMC)&lt;/li&gt;
&lt;li&gt;Overriding the &lt;code&gt;or&lt;/code&gt; operator works fine until you get to an object that has overridden the &lt;code&gt;equals&lt;/code&gt; operator. In this case Groovy kept trying to find out if my &lt;code&gt;Matrix&lt;/code&gt; was equal to my &lt;code&gt;MatrixColumn&lt;/code&gt;. Once I figured this out I just returned false if the &lt;code&gt;MatrixColumn&lt;/code&gt; was being compared against a &lt;code&gt;Matrix&lt;/code&gt; then it worked as expected.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The next part I want to add is the ability to track the EROs through Elementary Matrices. These are matrices that start out as 1s along the diagonal and they get the same EROs applied to them (this will be useful further down the line for other operations).&lt;/p&gt;</description>
      <pubDate>Mon, 26 Nov 2007 11:59:24 -0700</pubDate>
      <guid isPermaLink="false">urn:uuid:57fad73d-f7fd-481b-8474-f518f4e92dd9</guid>
      <author>Warner Onstine</author>
      <link>http://www.warneronstine.com/blog/articles/2007/11/26/math-dsl-part-deux-elementary-row-operations-eros</link>
      <category>programming</category>
      <category>linear_algebra</category>
      <category>math</category>
      <category>matrix</category>
      <category>groovy</category>
      <category>dsl</category>
      <trackback:ping>http://www.warneronstine.com/blog/articles/trackback/306</trackback:ping>
    </item>
    <item>
      <title>Math DSL beginning</title>
      <description>&lt;p&gt;I decided to start working on this taking one of the examples I worked out for the book for math Sets (partially incomplete due to Groovy&amp;#8217;s inability to directly override &lt;code&gt;lessThan&lt;/code&gt;, &lt;code&gt;lessThanEquals&lt;/code&gt;, &lt;code&gt;greaterThan&lt;/code&gt;, &lt;code&gt;greaterThanEquals&lt;/code&gt;) and to put into code some of the techniques I was learning in my Linear Algebra class. &lt;/p&gt;

&lt;p&gt;So far I&amp;#8217;ve implemented the following into my matrix math DSL:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Matrix/Row equality - allows you to test if two matrices or rows are equal (i.e. - contain the same ordered set of numbers)&lt;/li&gt;
&lt;li&gt;Matrix addition/subtraction - You can add two matrices together if they are the same dimensions (2x2, 2x3, whatever, as long as the match in row and columns)&lt;/li&gt;
&lt;li&gt;Matrix/Row scalar multiplication - You can multiply a scalar value against a row or matrix&lt;/li&gt;
&lt;li&gt;Matrix multiplication - You can multiply two matrices together if the first matrix A&amp;#8217;s (say 2x3) columns match B&amp;#8217;s  rows of the matrix you are multiplying against (say 3x2) which will produce a 2x2 matrix. If you did BxA then you would end up with a new matrix of 3x3&lt;/li&gt;
&lt;li&gt;Matrix powers - If the matrix is square (say 3x3) you can multiply it by itself to get the power of the matrix&lt;/li&gt;
&lt;li&gt;Left-shift operation - be able to dynamically create a Row or Matrix by adding new elements to the end&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I still have a lot of work which is laid out on my Trac site for &lt;a href="http://warneronstine.com/groovymath/roadmap"&gt;GroovyMath&lt;/a&gt; which leads me to my next conundrum. &lt;/p&gt;

&lt;p&gt;When dealing with matrices you need to do a lot of Reduced Echelon Form (REF) or Row Reduced Echelon Form (RREF) this consists of taking one of two Elementary Row Operations (EROs) and applying it to a row to get a matrix in the form of a diagonal (all 1s down the upper-left to lower-right diagonal with 0s everywhere else) or getting it into an upper-diagonal form (0s below the diagonal and integers everywhere else). The two EROs that you can consist of a) row interchange, where you can exchange one row with another; and b) row addition, where you can add one row to another multiplying that row by a scalar. What I would like to be able to do is something like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;def A = new Matrix(//rows go in here)
A.r1 + A.r2*2 //which will add 2 times the second row and add it to the first and replace it
A.r1 % A.r2 //which will exchange rows 1 and 2 with each other
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Another thought I had was to do this in some kind of &amp;#8220;rowOperations&amp;#8221; closure:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;def A = new Matrix(//rows go in here)
A.rowOperations {
    r1 + r2*2
    r1 % r2
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Which definitely reads better than the first (and of course that&amp;#8217;s all part of a DSL how well does it translate the native tongue into code). But the issue that I have with either of these approaches (maybe, still ironing out the second in my head) is that the properties r1 and r2 don&amp;#8217;t exist. These property accessors will need to be intercepted. Ok, not a big deal. But if I choose to implement this in MatrixRow (i.e. - actually return the row itself) it doesn&amp;#8217;t allow me to modify the originating matrix (A in this case) only change the row. For the addition problem I think I can get around it as it is executing in a closure, but the row interchange is an issue. The individual rows don&amp;#8217;t know they&amp;#8217;re a part of a matrix and I&amp;#8217;m not sure that knowing it allows them to do anything.&lt;/p&gt;

&lt;p&gt;Anyways, just wrestling with this concept right now as it is key to moving on to the more advanced functionality in my matrix math. Any suggestions are more than welcome. One new feature that I really like will be overriding the &lt;code&gt;or&lt;/code&gt; operator to provide Augmented Matrices (another key part). Normally you define an augmented matrix in one of three ways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;A|0&lt;/code&gt; - add a column of all zeros&lt;/li&gt;
&lt;li&gt;&lt;code&gt;A|b&lt;/code&gt; - add a vector as the augmented matrix&lt;/li&gt;
&lt;li&gt;&lt;code&gt;A|I&lt;/code&gt; - add an Identity matrix&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The first two are used to solve the set of linear equations and a bunch of other things. The second is used to find the inverse of the matrix as you transform through EROs the matrix &lt;code&gt;A&lt;/code&gt; so that it equals &lt;code&gt;I&lt;/code&gt; (the identity matrix) and then the side that &amp;#8220;I&amp;#8221; was on now equals the inverse of &lt;code&gt;A&lt;/code&gt;. I would say stop me if I&amp;#8217;m boring you but it&amp;#8217;s probably too late for that. I just wanted to point out how cool it was I can override the &lt;code&gt;or&lt;/code&gt; operator to do something completely different that makes perfect sense in my given domain.&lt;/p&gt;</description>
      <pubDate>Fri, 23 Nov 2007 18:11:12 -0700</pubDate>
      <guid isPermaLink="false">urn:uuid:a393a739-cbd5-423b-8877-07cd92ff46fc</guid>
      <author>Warner Onstine</author>
      <link>http://www.warneronstine.com/blog/articles/2007/11/23/math-dsl-beginning</link>
      <category>programming</category>
      <category>linear_algebra</category>
      <category>math</category>
      <category>matrix</category>
      <category>groovy</category>
      <category>dsl</category>
      <trackback:ping>http://www.warneronstine.com/blog/articles/trackback/305</trackback:ping>
    </item>
    <item>
      <title>DSL book on hold...unfortunately</title>
      <description>&lt;p&gt;Well we got the first round of reviews back from the technical reviewers and there&amp;#8217;s a lot of work to be done. So much so that we&amp;#8217;ve decided to put the book on hold while we regroup and figure out if/how we are going to address the issues that the reviewers found with the book. In a lot of cases it is going to require a complete rewrite of the example (and hence the chapter itself). Personally I feel the core is there, but maybe the examples weren&amp;#8217;t as fleshed out as they could have been.&lt;/p&gt;

&lt;p&gt;Now of course I&amp;#8217;m a little embarrassed that I announced the book before it was done, but that&amp;#8217;s what happens sometimes. Not sure at this point whether or not the book will continue, taking some time to regroup/rethink things and see if it is something that I want to push forward with.&lt;/p&gt;

&lt;p&gt;I will keep everyone up to date here on the progress of things once I&amp;#8217;ve decided what to do. In the meantime I am going to get back to some of my back-burner projects (a few of which have some DSLs in them ;-).&lt;/p&gt;</description>
      <pubDate>Tue, 30 Oct 2007 10:20:44 -0700</pubDate>
      <guid isPermaLink="false">urn:uuid:d4ecd040-55d5-4524-9606-af4c0b8c2588</guid>
      <author>Warner Onstine</author>
      <link>http://www.warneronstine.com/blog/articles/2007/10/30/dsl-book-on-hold-unfortunately</link>
      <category>programming</category>
      <category>writing</category>
      <category>groovy</category>
      <category>java</category>
      <category>dsl</category>
      <category>writings</category>
      <trackback:ping>http://www.warneronstine.com/blog/articles/trackback/304</trackback:ping>
    </item>
    <item>
      <title>DSL book in progress</title>
      <description>&lt;p&gt;Now that things feel a little bit more final to me I thought I would take this opportunity to announce the book that&amp;#8217;s been keeping me from blogging. The tentative title is Creating DSLs using Java and Groovy and it will be published by &lt;a href="http://www.pragprog.com/"&gt;Pragmatic Programmers&lt;/a&gt;. I started working on this idea after last years &lt;a href="http://nofluffjuststuff.com"&gt;No Fluff Just Stuff&lt;/a&gt; where I saw &lt;a href="http://www.nealford.com/"&gt;Neal Ford&lt;/a&gt; speak on DSLs and I talked to him briefly about a project I was working on. His talk inspired me to push forward with using DSLs for code generation specifically using Groovy.&lt;/p&gt;

&lt;p&gt;The book will cover both Java and Groovy techniques for writing DSLs, as well as have some general guidelines for writing DSLs. We also have a chapter on &lt;a href="http://antlr.org"&gt;ANTLR&lt;/a&gt; and &lt;a href="https://javacc.dev.java.net/"&gt;JavaCC&lt;/a&gt; for writing external DSLs using Java. I tried to cover as much as I could of Groovy meta-programming and some of the additional capabilities of Groovy that make it a good language to write an internal DSL on top of, but there&amp;#8217;s only so much space ;-).&lt;/p&gt;

&lt;p&gt;We just sent off the book for peer review, which means its about half-way finished, maybe a little more. We are currently shooting for a release date sometime early next year, which looks very doable at this point, but I expect a ton of edits to come back from this first review. &lt;/p&gt;

&lt;p&gt;On a final note I just want to say what a pleasure it has been working with the PragProg crew. I love, love, love their &lt;a href="http://www.pragprog.com/write-for-us"&gt;book build system&lt;/a&gt; and my editor Susannah rocks. I have had a blast working with them so far on this book and am looking forward to finishing this up and getting it published.&lt;/p&gt;</description>
      <pubDate>Wed, 10 Oct 2007 09:44:00 -0700</pubDate>
      <guid isPermaLink="false">urn:uuid:0fafb693-2a37-4d0f-9238-18cdea59d12e</guid>
      <author>Warner Onstine</author>
      <link>http://www.warneronstine.com/blog/articles/2007/10/10/dsl-book-in-progress</link>
      <category>programming</category>
      <category>writing</category>
      <category>groovy</category>
      <category>java</category>
      <category>dsl</category>
      <category>writings</category>
      <trackback:ping>http://www.warneronstine.com/blog/articles/trackback/303</trackback:ping>
    </item>
    <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>
  </channel>
</rss>
