In the previous post The Navigation: Using the annotations for named parameters we have declared some methods accepting named parameters…
Groovy DSL Builders #10: The Conclusion
In the previous post The Navigation: Using the annotations for named parameters we have declared some methods accepting named parameters in our DSL. This final part provides a checklist for anyone who is going to write Groovy builder from a scratch as well as for developers who want to revisit existing ones.

YUML.me Diagram’s Diagram
Let’s summarise what you should learn from this series into two checklists depending if you are creating new builder DSL or revisiting existing one:
Checklist for creating new builder DSL
- As long as there is just a tiny option that Java developers would benefit from your builder DSL try to write your code in Java with Groovy-specific code inside extension classes. The extension classes can still be written in Java.
- Separate data and definition classes — at least use different interfaces for each situation.
- Use
Consumerinstead ofClosureand then in the Groovy extension class declare shadow method acceptingClosure. Alternatively, you can useFunctionto emphasise the expected content of the lambda code. UseConsumerWithDelegateandFunctionWithDelegatefrom Groovy Closure Support project to properly handle closures’ owner. - Any
Closureparameter should be annotated withDelegatesToandClosureParams. Do not forget to setstrategyofDelegatesToannotation toDELEGATE_FIRST. - Consider what is the best return type of the
Closureparameters. Try to declare a common interface for the result of every possible statement expected inside the closure’s body. - Provide an extension point for your DSL
- Use named arguments only when there is no other option. Always annotate named arguments map with
NamedParams. Methods with named arguments should only be defined in Groovy extension classes.
Checklist for existing Groovy builder DSL
- Consider providing pure Java variant of your DSL
- Separate data and definition classes — at least use different interfaces for each situation.
- Ensure every
Closureparameter is annotated withDelegatesToandClosureParams. Do not forget to setstrategyofDelegatesToannotation toDELEGATE_FIRST. - Ensure top-level owner is propagated into any nested closures. You can use
GroovyClosure.cloneWithTopLevelOwnermethod from Groovy Closure Support project if you decide not to migrate toConsumerorFunction. - Consider what is the best return type of the
Closureparameters. Try to declare a common interface for the result of every possible statement expected inside the closure’s body. - Provide an extension point for your DSL
- Use named arguments only when there is no other option. Always annotate named arguments map with
NamedParams.
One general advice for both situations which didn’t fit elsewhere:
_Try to avoid method names which have a special meaning in Groovy. The most toxic in the terms of builder DSL is using the method_ `_get_` _which is basically a shortcut to_ `_propertyMissing_` _fallback. Especially if you haven't resolved the problem with_ `_owner_` _this may result into cryptic exceptions._
The whole YUML DSL code is available on GitHub:
git clone https://github.com/musketyr/yuml-dsl-builder.git
Contents
- The Concept: The core concept of builders
- The Essence: The closures’ basics
- The Aid: Using the annotations for static compilation
- The Disguise: Hiding the implementation of the builder API
- The Desiccation: Keeping the code DRY
- The Expectations: The importance of handling closures’ owner properly
- The Extension: Designing your builder DSL for extendability
- The Resignation: Rewriting the Groovy DSL builder into Java
- The Navigation: Using the annotations for named parameters
10. [The Conclusion: _The checklist for Groovy DSL builders’ authors_](https://medium.com/p/9d2b961dbc55)