Jakub is a Java EE developer since 2005 and occasionally a project manager, working currently with Iterate AS. He's highly interested in developer productivity (and tools like Maven and AOP/AspectJ), web frameworks, Java portals, testing and performance and works a lot with IBM technologies. A native to Czech Republic, he lives now in Oslo, Norway. Jakub is a DZone MVB and is not an employee of DZone and has posted 155 posts at DZone. You can read more from them at their website. View Full User Profile

Tips And Resources For Creating DSLs in Groovy

11.16.2011
| 5643 views |
  • submit to reddit

Paul King had a very good presentation (last year’s slides) at JavaZone about why to use Domain-Specific Languages and how to create internal DSLs in Groovy. I’d like to list here few tips that he has mentioned but before we get to that, why would you want to create a DSL? Martin Fowler answers that in his Domain-Specific Languages book (2010). Some of the reasons are to have a higher-level, more focused and conscise representation that also domain experts can read and perhaps even write. You  have certainly already used a DSL such as regular expressions, CSS, SQL, Spock‘s BDD tests, build instructions in Gradle – these are rather technical but sometimes DSLs are also created to be used by business users, f.ex. for anti-malaria drug resistance simulation. (Want more DSLs in Groovy?).

Paul mentions one important thing – you can always make your DSL better, i.e. more fail-proof (case insensitive, support plural endings, …) and secure and more like a natural language but it all comes at a cost and you must evaluate when the cost overweights the benefit (beware the 80:20 rule).

Some of the Groovy DSL implementation tips:

  • Add methods to any object/class via metaprogramming: <class|instance>.metaclass.<method name or getProperty> = {MyType param -> … } – you can use ‘delegate’ to refer to the instance
    • notice that getProperty is called for anything that isn’t a method as in map['key'] == map.key – useful to implement e.g. 1.kg
    • Call ExpandoMetaClass.enableGlobally() to propagate methods added to Number also to Integer etc.
  • Use a GroovyShell and a custom Binding subclass overriding getVariable(String symbol) so as to return/create an object for unknown “variables” (ex.: “newOrder” -> new Order(), creation of vars for symbols like “h”, “km” etc. => 24.km/h)
  • Operator overloading: methods of specific names are invoked for operators (/ -> div, * -> multiply etc.)
  • Use a closure setting its delegate and configuring it the cosure’s resolve strategy to delegate unknown methods further to the delegate
  • Create a custom Closure subclass and use that for a closure instead of the default one
  • Use Groovy’s Categories (st. like a temporary mixin, activated via the use(category) { .. } form) to add localy methods to classes
  • Use Groovy Builders for tree-like DSLs (builder <-> method calls that take a Closure as argument)
  • Use map attributes to get st. resembling named atributes
  • Use GroovyShell with a custom classloader and compilation phase something to prevent calls of other static and instance methods than allowed

Resources

PS: The latest release of Groovy in Action should also contain a chapter on DSLs.

 

From http://theholyjava.wordpress.com/2011/11/13/tips-and-resources-for-creating-dlss-in-groovy/

Published at DZone with permission of Jakub Holý, author and DZone MVB.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Tags: