Copyright 2009 SpringSource. Copying, publishing or distributing without express written permission is prohibited. Practical Domain-Specific Languages with Groovy All the techniques to create your own DSLs Guillaume Laforge Head of Groovy Development
85
Embed
Practical Groovy Domain-Specific Languages - SpringOne Europe 2009
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Copyright 2009 SpringSource. Copying, publishing or distributing without express written permission is prohibited.
Practical Domain-Specific Languages with Groovy
All the techniques to create your own DSLs
Guillaume Laforge
Head of Groovy Development
Copyright 2008 SpringSource. Copying, publishing or distributing without express written permission is prohibited.
• Groovy Project Manager
• JSR-241 Spec Lead
• Head of Groovy Developmentat SpringSource
• Initiator of the Grails framework
• Co-author of Groovy in Action
• Speaker: JavaOne, QCon, JavaZone, Sun TechDays, Devoxx, The Spring Experience, JAX, Dynamic Language World, IJTC, and more...
Guillaume Laforge
2
Copyright 2008 SpringSource. Copying, publishing or distributing without express written permission is prohibited.
A few words about Groovy
• Groovy is a dynamic language for the JVM
–with a Meta Object Protocol
–compiles directly to bytecode, seamless Java interop
• Open Source ASL 2 project hosted at Codehaus
• Relaxed grammar derived from Java 5
–+ borrowed good ideas from Ruby, Python, Smalltalk
• Fast... for a dynlang on the JVM
• Closures, properties, optional typing, BigDecimal by default, nice wrapper APIs, and more...
3
Copyright 2008 SpringSource. Copying, publishing or distributing without express written permission is prohibited.
• The context and the usual issues we face
• Some real-life examples of Domain-Specific Languages
• Groovy’s DSL capabilities
• Integrating a DSL in your application
• Considerations to remember when designing your own DSL
Agenda
4
The context
Subject Matter Experts,Business analysts...
HAI
CAN HAS STDIO?
I HAS A VAR
IM IN YR LOOP
UP VAR!!1
VISIBLE VAR
IZ VAR BIGGER THAN 10?
KTHXBYE
IM OUTTA YR LOOP
KTHXBYE
Developer producing LOLCODE
Lots of languages...
And in the end......nobody understands each other
Copyright 2008 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 10
Expressing requirements...
Copyright 2008 SpringSource. Copying, publishing or distributing without express written permission is prohibited.
DSL: a potential solution?
•Use a more expressive language than a general purpose one
•Share a common metaphore of understanding between developers and subject matter experts
•Have domain experts help with the design of the business logic of an application
•Avoid cluttering business code with too much boilerplate technical code
•Cleanly separate business logic from application code
•Let business rules have their own lifecycle
11
Copyright 2008 SpringSource. Copying, publishing or distributing without express written permission is prohibited.
Towards more readibility (1)
12
Copyright 2008 SpringSource. Copying, publishing or distributing without express written permission is prohibited.
Towards more readibility (1)
12
Copyright 2008 SpringSource. Copying, publishing or distributing without express written permission is prohibited.
Towards more readibility (1)
20%
12
Copyright 2008 SpringSource. Copying, publishing or distributing without express written permission is prohibited.
Towards more readibility (2)
13
Copyright 2008 SpringSource. Copying, publishing or distributing without express written permission is prohibited.
Towards more readibility (2)
13
Copyright 2008 SpringSource. Copying, publishing or distributing without express written permission is prohibited.
Towards more readibility (2)
80%
13
Copyright 2008 SpringSource. Copying, publishing or distributing without express written permission is prohibited.
• The context and the usual issues we face
• Some real-life examples of Domain-Specific Languages
• Groovy’s DSL capabilities
• Integrating a DSL in your application
• Considerations to remember when designing your own DSL
Agenda
14
Copyright 2008 SpringSource. Copying, publishing or distributing without express written permission is prohibited.
• In our everyday life, we’re surrounded by DSLs
–Technical dialects
–Notations
–Business languages
15
A collection of DSLs
Copyright 2008 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 16
Technical dialects
SQL
Copyright 2008 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 18
^[\w-\.]+@([\w-]){2,4}$
Copyright 2008 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 19
Notations
1. e4 e52. Nf3 Nc63. Bb5 a6
L2 U F-1 B L2 F B -1 U L2
Visual!
Copyright 2008 SpringSource. Copying, publishing or distributing without express written permission is prohibited. 23
Business languages
Copyright 2008 SpringSource. Copying, publishing or distributing without express written permission is prohibited.
Real-life Groovy examples
• Anti-malaria drug resistance simulation
• Human Resources employee skills representation
• Insurance policies risk calculation engine
• Loan acceptance rules engine for a financial platform
• Mathematica-like lingua for nuclear safety simulations
• Market data feeds evolution scenarios
• and more...
24
Copyright 2008 SpringSource. Copying, publishing or distributing without express written permission is prohibited.
• The context and the usual issues we face
• Some real-life examples of Domain-Specific Languages
• Groovy’s DSL capabilities
• Integrating a DSL in your application
• Considerations to remember when designing your own DSL
Agenda
25
Copyright 2008 SpringSource. Copying, publishing or distributing without express written permission is prohibited.
A flexible & malleable syntax
• No need to write full-blown classes, use scripts
• Optional typing (def)
–in scripts, you can even omit the def keyword
• Native syntax constructs
• Parentheses & semi-colons are optional
• Named arguments
• BigDecimal by default for decimal numbers
• Closures for custom control structures
• Operator overloading
26
Copyright 2008 SpringSource. Copying, publishing or distributing without express written permission is prohibited.
Scripts vs classes
• Hide all the boilerplate technical code
–an end-user doesn’t need to know about classes
–public class Rule { public static void main(String[] args) { System.out.println(“Hello”); }}
–println “Hello”
27
Copyright 2008 SpringSource. Copying, publishing or distributing without express written permission is prohibited.
Optional typing
• No need to bother with types or even generics
–unless you want to!
• Imagine an interest rate lookup table method returning some generified type:
Copyright 2008 SpringSource. Copying, publishing or distributing without express written permission is prohibited.
Builders
• Builders are...
–a mechanism for creating any tree-structered graph
–the realization of the GoF builder pattern at the syntax level in Groovy
–simply a clever use of chained method invocation, closures, parentheses omission, and use of the GroovyObject methods
• Existing builders
–XML, Object graph, Swing, Ant, JMX, and more...
43
Copyright 2008 SpringSource. Copying, publishing or distributing without express written permission is prohibited.
The clever trick
• GroovyObject#invokeMethod() is used to catch all non-existing method calls in the context of the builder
• The nesting of closures visually shows the level of nesting / depth in the tree
• builder.m1(attr1:1, attr2:2, { builder.m2(...,
{...}) } becomes equivalent to
builder.m1(attr1:1, attr2:2) { m2(...) {...} }
thanks to parens omission
44
Copyright 2008 SpringSource. Copying, publishing or distributing without express written permission is prohibited.
Adding properties to numbers
• Three possible approaches
–create a Category
•a category is a kind of decorator for default MCs
–create a custom MetaClass
•a full-blown MC class to implement and to set on the POGO instance
–use ExpandoMetaClass
•friendlier DSL approach but with a catch
45
Copyright 2008 SpringSource. Copying, publishing or distributing without express written permission is prohibited.
With a Category
• class DistanceCategory { static Distance getMeters(Integer self) { new Distance(self, Unit.METERS) }}
use(DistanceCategory) { 100.meters}
• Interesting scope: thread-bound & lexical
• But doesn’t work across the hierarchy of classes
–ie. subclasses won’t benefit from the new property
46
Copyright 2008 SpringSource. Copying, publishing or distributing without express written permission is prohibited.
With an ExpandoMetaClass
• Number.metaClass.getMeters = {-> new Distance(delegate, Unit.METERS) }
100.meters
• Works for the class hierarchy for POJOs, and a flag exists to make it work for POGOs too
• But the catch is it’s really a global change, so beware EMC enhancements collisions
47
Copyright 2008 SpringSource. Copying, publishing or distributing without express written permission is prohibited.
Compile-time metaprogramming
• Groovy 1.6 introduced AST Transformations
• Compile-time == No runtime performance penalty!
Transformation
48
Copyright 2008 SpringSource. Copying, publishing or distributing without express written permission is prohibited.
AST Transformations
• Two kinds of transformations
–Global transformations
•applicable to all compilation units
–Local transformations
•applicable to marked program elements
•using specific marker annotations
49
Copyright 2008 SpringSource. Copying, publishing or distributing without express written permission is prohibited.
Example #1: @Singleton
• Let’s revisit this evil (anti-)pattern! public class Evil { public static final Evil instance = new Evil (); private Evil () {} Evil getInstance() { return instance; } }
• In Groovy! @Singleton class Evil {}
• Also a “lazy” version! @Singleton(lazy = true) class Evil {}
50
Copyright 2008 SpringSource. Copying, publishing or distributing without express written permission is prohibited.
• You can delegate to fields of your classes
–class Employee { def doTheWork() { “done” }}class Manager { @Delegate Employee slave = new Employee()}def god = new Manager()assert god.doTheWork() == “done”
• Damn manager who will get all the praiser...
51
Example #2: @DelegateNot just for Managers
Copyright 2008 SpringSource. Copying, publishing or distributing without express written permission is prohibited.
Global transformations
• Implement ASTTransformation
• Annotate the transfo specifying a compilation phase
• @GroovyASTTransformation(phase=CompilePhase.CONVERSION)public class MyTransformation implements ASTTransformation { public void visit(ASTNode[] nodes, SourceUnit unit) { ... }}
• For discovery, create the file META-INF/services/org.codehaus.groovy.transform.ASTTransformation
• Add the fully qualified name of the class in that file
52
Copyright 2008 SpringSource. Copying, publishing or distributing without express written permission is prohibited.
Local transformations
• Same approach as Globale transformations
• But you don’t need the META-INF file
• Instead create an annotation to specify on which element the transformation should apply