Practical Groovy Domain-Specific Languages
-
Upload
guillaume-laforge -
Category
Technology
-
view
2.723 -
download
2
description
Transcript of Practical Groovy Domain-Specific Languages
![Page 1: Practical Groovy Domain-Specific Languages](https://reader036.fdocuments.net/reader036/viewer/2022081413/54579a22b1af9fc0638b52c1/html5/thumbnails/1.jpg)
Practical Domain-Specific Languages in Groovy
Guillaume LaforgeGroovy Project ManagerSpringSource
![Page 2: Practical Groovy Domain-Specific Languages](https://reader036.fdocuments.net/reader036/viewer/2022081413/54579a22b1af9fc0638b52c1/html5/thumbnails/2.jpg)
2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone
Groovy Project Manager
JSR-241 Spec LeadHead of Groovy Developmentat SpringSource
Initiator of the Grails frameworkCo-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
![Page 3: Practical Groovy Domain-Specific Languages](https://reader036.fdocuments.net/reader036/viewer/2022081413/54579a22b1af9fc0638b52c1/html5/thumbnails/3.jpg)
2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone
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
![Page 4: Practical Groovy Domain-Specific Languages](https://reader036.fdocuments.net/reader036/viewer/2022081413/54579a22b1af9fc0638b52c1/html5/thumbnails/4.jpg)
2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone
The context and the usual issues we faceSome real-life examples of Domain-Specific LanguagesGroovy’s DSL capabilitiesIntegrating a DSL in your applicationConsiderations to remember when designing your own DSL
Agenda
4
![Page 5: Practical Groovy Domain-Specific Languages](https://reader036.fdocuments.net/reader036/viewer/2022081413/54579a22b1af9fc0638b52c1/html5/thumbnails/5.jpg)
The context
![Page 6: Practical Groovy Domain-Specific Languages](https://reader036.fdocuments.net/reader036/viewer/2022081413/54579a22b1af9fc0638b52c1/html5/thumbnails/6.jpg)
Subject Matter Experts,Business analysts...
![Page 7: Practical Groovy Domain-Specific Languages](https://reader036.fdocuments.net/reader036/viewer/2022081413/54579a22b1af9fc0638b52c1/html5/thumbnails/7.jpg)
HAICAN HAS STDIO?I HAS A VARIM IN YR LOOP UP VAR!!1 VISIBLE VAR IZ VAR BIGGER THAN 10? KTHXBYEIM OUTTA YR LOOPKTHXBYE
Developer producing LOLCODE
![Page 8: Practical Groovy Domain-Specific Languages](https://reader036.fdocuments.net/reader036/viewer/2022081413/54579a22b1af9fc0638b52c1/html5/thumbnails/8.jpg)
Lots of languages...
![Page 9: Practical Groovy Domain-Specific Languages](https://reader036.fdocuments.net/reader036/viewer/2022081413/54579a22b1af9fc0638b52c1/html5/thumbnails/9.jpg)
And in the end......nobody understands each other
![Page 10: Practical Groovy Domain-Specific Languages](https://reader036.fdocuments.net/reader036/viewer/2022081413/54579a22b1af9fc0638b52c1/html5/thumbnails/10.jpg)
Expressing requirements...
![Page 11: Practical Groovy Domain-Specific Languages](https://reader036.fdocuments.net/reader036/viewer/2022081413/54579a22b1af9fc0638b52c1/html5/thumbnails/11.jpg)
2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone
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
![Page 12: Practical Groovy Domain-Specific Languages](https://reader036.fdocuments.net/reader036/viewer/2022081413/54579a22b1af9fc0638b52c1/html5/thumbnails/12.jpg)
2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone
Towards more readibility (1)
12
![Page 13: Practical Groovy Domain-Specific Languages](https://reader036.fdocuments.net/reader036/viewer/2022081413/54579a22b1af9fc0638b52c1/html5/thumbnails/13.jpg)
2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone
Towards more readibility (1)
12
![Page 14: Practical Groovy Domain-Specific Languages](https://reader036.fdocuments.net/reader036/viewer/2022081413/54579a22b1af9fc0638b52c1/html5/thumbnails/14.jpg)
2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone
Towards more readibility (1)
20%
12
![Page 15: Practical Groovy Domain-Specific Languages](https://reader036.fdocuments.net/reader036/viewer/2022081413/54579a22b1af9fc0638b52c1/html5/thumbnails/15.jpg)
2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone
Towards more readibility (2)
13
![Page 16: Practical Groovy Domain-Specific Languages](https://reader036.fdocuments.net/reader036/viewer/2022081413/54579a22b1af9fc0638b52c1/html5/thumbnails/16.jpg)
2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone
Towards more readibility (2)
13
![Page 17: Practical Groovy Domain-Specific Languages](https://reader036.fdocuments.net/reader036/viewer/2022081413/54579a22b1af9fc0638b52c1/html5/thumbnails/17.jpg)
2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone
Towards more readibility (2)
80%
13
![Page 18: Practical Groovy Domain-Specific Languages](https://reader036.fdocuments.net/reader036/viewer/2022081413/54579a22b1af9fc0638b52c1/html5/thumbnails/18.jpg)
2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone
The context and the usual issues we faceSome real-life examples of Domain-Specific LanguagesGroovy’s DSL capabilitiesIntegrating a DSL in your applicationConsiderations to remember when designing your own DSL
Agenda
14
![Page 19: Practical Groovy Domain-Specific Languages](https://reader036.fdocuments.net/reader036/viewer/2022081413/54579a22b1af9fc0638b52c1/html5/thumbnails/19.jpg)
2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone
A collection of DSLs
In our everyday life, we’re surrounded by DSLs
• Technical dialects
• Notations
• Business languages
15
![Page 20: Practical Groovy Domain-Specific Languages](https://reader036.fdocuments.net/reader036/viewer/2022081413/54579a22b1af9fc0638b52c1/html5/thumbnails/20.jpg)
2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone
Technical dialects
16
![Page 21: Practical Groovy Domain-Specific Languages](https://reader036.fdocuments.net/reader036/viewer/2022081413/54579a22b1af9fc0638b52c1/html5/thumbnails/21.jpg)
SQL
![Page 22: Practical Groovy Domain-Specific Languages](https://reader036.fdocuments.net/reader036/viewer/2022081413/54579a22b1af9fc0638b52c1/html5/thumbnails/22.jpg)
2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone
^[\w-\.]+@([\w-]){2,4}$
18
![Page 23: Practical Groovy Domain-Specific Languages](https://reader036.fdocuments.net/reader036/viewer/2022081413/54579a22b1af9fc0638b52c1/html5/thumbnails/23.jpg)
2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone
Notations
19
![Page 24: Practical Groovy Domain-Specific Languages](https://reader036.fdocuments.net/reader036/viewer/2022081413/54579a22b1af9fc0638b52c1/html5/thumbnails/24.jpg)
1. e4 e52. Nf3 Nc63. Bb5 a6
![Page 25: Practical Groovy Domain-Specific Languages](https://reader036.fdocuments.net/reader036/viewer/2022081413/54579a22b1af9fc0638b52c1/html5/thumbnails/25.jpg)
L2 U F-1 B L2 F B -1 U L2
![Page 26: Practical Groovy Domain-Specific Languages](https://reader036.fdocuments.net/reader036/viewer/2022081413/54579a22b1af9fc0638b52c1/html5/thumbnails/26.jpg)
Visual!
![Page 27: Practical Groovy Domain-Specific Languages](https://reader036.fdocuments.net/reader036/viewer/2022081413/54579a22b1af9fc0638b52c1/html5/thumbnails/27.jpg)
2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone
Business languages
23
![Page 28: Practical Groovy Domain-Specific Languages](https://reader036.fdocuments.net/reader036/viewer/2022081413/54579a22b1af9fc0638b52c1/html5/thumbnails/28.jpg)
2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone
Real-life Groovy examples
Anti-malaria drug resistance simulationHuman Resources employee skills representationInsurance policies risk calculation engineLoan acceptance rules engine for a financial platformMathematica-like lingua for nuclear safety simulationsMarket data feeds evolution scenarios
and more...
24
![Page 29: Practical Groovy Domain-Specific Languages](https://reader036.fdocuments.net/reader036/viewer/2022081413/54579a22b1af9fc0638b52c1/html5/thumbnails/29.jpg)
2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone
The context and the usual issues we faceSome real-life examples of Domain-Specific LanguagesGroovy’s DSL capabilitiesIntegrating a DSL in your applicationConsiderations to remember when designing your own DSL
Agenda
25
![Page 30: Practical Groovy Domain-Specific Languages](https://reader036.fdocuments.net/reader036/viewer/2022081413/54579a22b1af9fc0638b52c1/html5/thumbnails/30.jpg)
2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone
A flexible & malleable syntax
No need to write full-blown classes, use scriptsOptional typing (def)• in scripts, you can even omit the def keyword
Native syntax constructsParentheses & semi-colons are optionalNamed argumentsBigDecimal by default for decimal numbersClosures for custom control structuresOperator overloading
26
![Page 31: Practical Groovy Domain-Specific Languages](https://reader036.fdocuments.net/reader036/viewer/2022081413/54579a22b1af9fc0638b52c1/html5/thumbnails/31.jpg)
2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone
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
![Page 32: Practical Groovy Domain-Specific Languages](https://reader036.fdocuments.net/reader036/viewer/2022081413/54579a22b1af9fc0638b52c1/html5/thumbnails/32.jpg)
2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone
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:
•Rate<LoanType, Duration, BigDecimal>[] lookupTable() { ... }def table = lookupTable()
No need to repeat the horrible generics type info!
28
![Page 33: Practical Groovy Domain-Specific Languages](https://reader036.fdocuments.net/reader036/viewer/2022081413/54579a22b1af9fc0638b52c1/html5/thumbnails/33.jpg)
2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone
Native syntax constructs
Lists• [Monday, Tuesday, Wednesday]
Maps• [CA: ‘California’, TX: ‘Texas’]
Ranges• def bizDays = Monday..Friday• def allowedAge = 18..65• You can create your own custom ranges
29
![Page 34: Practical Groovy Domain-Specific Languages](https://reader036.fdocuments.net/reader036/viewer/2022081413/54579a22b1af9fc0638b52c1/html5/thumbnails/34.jpg)
2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone
Optional parens & semis
Make statements and expressions look more like natural languages
• move(left);
• move left
30
![Page 35: Practical Groovy Domain-Specific Languages](https://reader036.fdocuments.net/reader036/viewer/2022081413/54579a22b1af9fc0638b52c1/html5/thumbnails/35.jpg)
2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone
Named arguments
In Groovy you can mix named and unnamed arguments for method parameters
• named params are actually put in a map parameter• plus optional parens & semis
take 1.pill, of: Chloroquinine, after: 6.hours
Corresponds to a method signature like:
•def take(Map m, MedicineQuantity mq)
31
![Page 36: Practical Groovy Domain-Specific Languages](https://reader036.fdocuments.net/reader036/viewer/2022081413/54579a22b1af9fc0638b52c1/html5/thumbnails/36.jpg)
2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone
BigDecimal by default
Main reason why financial institutions often decide to use Groovy for their business rules!
• Although these days rounding issues are overrated!
Java vs Groovy for a simple interpolation equation
BigDecimal uMinusv = c.subtract(a); BigDecimal vMinusl = b.subtract(c); BigDecimal uMinusl = a.subtract(b); return e.multiply(uMinusv) .add(d.multiply(vMinusl)) .divide(uMinusl, 10, BigDecimal.ROUND_HALF_UP);
(d * (b - c) + e * (c - a)) / (a - b)
32
![Page 37: Practical Groovy Domain-Specific Languages](https://reader036.fdocuments.net/reader036/viewer/2022081413/54579a22b1af9fc0638b52c1/html5/thumbnails/37.jpg)
2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone
Custom control structures,thanks to closures
When closures are last, they can be put “out” of the parentheses surrounding parameters
unless (account.balance > 100.euros, { account.debit 100.euros })
unless (account.balance > 100.euros) { account.debit 100.euros}
Signature def unless(boolean b, Closure c)
33
![Page 38: Practical Groovy Domain-Specific Languages](https://reader036.fdocuments.net/reader036/viewer/2022081413/54579a22b1af9fc0638b52c1/html5/thumbnails/38.jpg)
2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone
Operator overloading
Currency amounts•15.euros + 10.dollars
Distance handling•10.kilometers - 10.meters
Workflow, concurrency•taskA | taskB & taskC
Credit an account•account << 10.dollarsaccount += 10.dollarsaccount.credit 10.dollars
a + b a.plus(b)
a - b a.minus(b)
a * b a.multiply(b)
a / b a.divide(b)
a % b a.modulo(b)
a ** b a.power(b)
a | b a.or(b)
a & b a.and(b)
a ^ b a.xor(b)
a[b] a.getAt(b)
a << b a.leftShift(b)
a >> b a.rightShift(b)
+a a.positive()
-a a.negative()
~a a.bitwiseNegate()34
![Page 39: Practical Groovy Domain-Specific Languages](https://reader036.fdocuments.net/reader036/viewer/2022081413/54579a22b1af9fc0638b52c1/html5/thumbnails/39.jpg)
Groovy’s dynamic heart:
The MOP!MetaObject Protocol
![Page 40: Practical Groovy Domain-Specific Languages](https://reader036.fdocuments.net/reader036/viewer/2022081413/54579a22b1af9fc0638b52c1/html5/thumbnails/40.jpg)
2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone
Groovy’s MOP
All the accesses to methods, properties, constructors, operators, etc. can be intercepted thanks to the MOP
While Java’s behavior is hard-wired at compile-time in the class
Groovy’s runtime behavior is adaptable at runtime through the metaclass.
Different hooks for changing the runtime behavior• GroovyObject, custom MetaClass implementation, categories,
ExpandoMetaClass
36
![Page 41: Practical Groovy Domain-Specific Languages](https://reader036.fdocuments.net/reader036/viewer/2022081413/54579a22b1af9fc0638b52c1/html5/thumbnails/41.jpg)
2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone
GroovyObject
All instances of classes created in Groovy implement the GroovyObject interface:
•getProperty(String name)•setProperty(String name, Object value)
•invokeMethod(String name, Object[] params)
•getMetaClass()•setMetaClass(MetaClass mc)
A GO can have “pretended” methods and properties
37
![Page 42: Practical Groovy Domain-Specific Languages](https://reader036.fdocuments.net/reader036/viewer/2022081413/54579a22b1af9fc0638b52c1/html5/thumbnails/42.jpg)
2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone
MetaClass
The core of Groovy’s MOP system
•invokeConstructor()•invokeMethod() and invokeStaticMethod()
•invokeMissingMethod()•getProperty() and setProperty()
•getAttribute() and setAttribute()•respondsTo() and hasProperty()
MetaClasses can change the behavior of existing third-party classes — even from the JDK
38
![Page 43: Practical Groovy Domain-Specific Languages](https://reader036.fdocuments.net/reader036/viewer/2022081413/54579a22b1af9fc0638b52c1/html5/thumbnails/43.jpg)
2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone
ExpandoMetaClass
A DSL for MetaClasses!
MoneyAmount.metaClass.constructor = { ... }Number.metaClass.getDollars = { ... }Distance.metaClass.toMeters = { ... }Distance.metaClass.static.create = { ... }
To avoid repetition of Type.metaClass, you can pass a closure to metaClass { ... }
The delegate variable in closure represents the current instance, and it the default parameter
39
![Page 44: Practical Groovy Domain-Specific Languages](https://reader036.fdocuments.net/reader036/viewer/2022081413/54579a22b1af9fc0638b52c1/html5/thumbnails/44.jpg)
The Builder pattern
![Page 45: Practical Groovy Domain-Specific Languages](https://reader036.fdocuments.net/reader036/viewer/2022081413/54579a22b1af9fc0638b52c1/html5/thumbnails/45.jpg)
2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone
A builder for HR
softskills { ideas { capture 2 formulate 3 } ...}knowhow { languages { java 4 groovy 5 } ...}
41
![Page 46: Practical Groovy Domain-Specific Languages](https://reader036.fdocuments.net/reader036/viewer/2022081413/54579a22b1af9fc0638b52c1/html5/thumbnails/46.jpg)
2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone
A builder for HR
softskills { ideas { capture 2 formulate 3 } ...}knowhow { languages { java 4 groovy 5 } ...}
41
![Page 47: Practical Groovy Domain-Specific Languages](https://reader036.fdocuments.net/reader036/viewer/2022081413/54579a22b1af9fc0638b52c1/html5/thumbnails/47.jpg)
2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone
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...
42
![Page 48: Practical Groovy Domain-Specific Languages](https://reader036.fdocuments.net/reader036/viewer/2022081413/54579a22b1af9fc0638b52c1/html5/thumbnails/48.jpg)
2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone
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
43
![Page 49: Practical Groovy Domain-Specific Languages](https://reader036.fdocuments.net/reader036/viewer/2022081413/54579a22b1af9fc0638b52c1/html5/thumbnails/49.jpg)
2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone
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
44
![Page 50: Practical Groovy Domain-Specific Languages](https://reader036.fdocuments.net/reader036/viewer/2022081413/54579a22b1af9fc0638b52c1/html5/thumbnails/50.jpg)
2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone
With a Category
class DistanceCategory { static Distance getMeters(Integer self) { new Distance(self, Unit.METERS) }}
use(DistanceCategory) { 100.meters}
Interesting scope: thread-bound & lexicalHave to surround with “use”• but there are ways to hide it
45
![Page 51: Practical Groovy Domain-Specific Languages](https://reader036.fdocuments.net/reader036/viewer/2022081413/54579a22b1af9fc0638b52c1/html5/thumbnails/51.jpg)
2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone
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
46
![Page 52: Practical Groovy Domain-Specific Languages](https://reader036.fdocuments.net/reader036/viewer/2022081413/54579a22b1af9fc0638b52c1/html5/thumbnails/52.jpg)
2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone
Compile-time metaprogramming
Groovy 1.6 introduced AST Transformations
Compile-time == No runtime performance penalty!
Transformation47
![Page 53: Practical Groovy Domain-Specific Languages](https://reader036.fdocuments.net/reader036/viewer/2022081413/54579a22b1af9fc0638b52c1/html5/thumbnails/53.jpg)
2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone
AST Transformations
Two kinds of transformations
• Global transformations• applicable to all compilation units
• Local transformations• applicable to marked program elements• using specific marker annotations
48
![Page 54: Practical Groovy Domain-Specific Languages](https://reader036.fdocuments.net/reader036/viewer/2022081413/54579a22b1af9fc0638b52c1/html5/thumbnails/54.jpg)
2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone
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
49
![Page 55: Practical Groovy Domain-Specific Languages](https://reader036.fdocuments.net/reader036/viewer/2022081413/54579a22b1af9fc0638b52c1/html5/thumbnails/55.jpg)
2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone
Local transformations
Same approach as Globale transformationsBut you don’t need the META-INF fileInstead create an annotation to specify on which element the transformation should apply
@Retention(RetentionPolicy.SOURCE)@Target([ElementType.METHOD])@GroovyASTTransformationClass( ["fqn.MyTransformation"])public @interface WithLogging {...}
50
![Page 56: Practical Groovy Domain-Specific Languages](https://reader036.fdocuments.net/reader036/viewer/2022081413/54579a22b1af9fc0638b52c1/html5/thumbnails/56.jpg)
2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone
Example: the Spock framework
Changing the semantics of the original codeBut keeping a valid Groovy syntax
@Speckclass HelloSpock { def "can you figure out what I'm up to?"() { expect: name.size() == size
where: name << ["Kirk", "Spock", "Scotty"] size << [4, 5, 6] }}
Check out http://www.spockframework.org
51
![Page 57: Practical Groovy Domain-Specific Languages](https://reader036.fdocuments.net/reader036/viewer/2022081413/54579a22b1af9fc0638b52c1/html5/thumbnails/57.jpg)
2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone
The context and the usual issues we faceSome real-life examples of Domain-Specific LanguagesGroovy’s DSL capabilitiesIntegrating a DSL in your applicationConsiderations to remember when designing your own DSL
Agenda
52
![Page 58: Practical Groovy Domain-Specific Languages](https://reader036.fdocuments.net/reader036/viewer/2022081413/54579a22b1af9fc0638b52c1/html5/thumbnails/58.jpg)
2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone
Various integration mechanisms
Java 6’s javax.script.* APIs (aka JSR-223)Spring’s language namespaceGroovy’s own mechanisms
But a key idea is to externalize those DSL programs• DSL programs can have their own lifecycle
• no need to redeploy an application because of a rule change• business people won’t see the technical code
53
![Page 59: Practical Groovy Domain-Specific Languages](https://reader036.fdocuments.net/reader036/viewer/2022081413/54579a22b1af9fc0638b52c1/html5/thumbnails/59.jpg)
2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone
Java 6’s javax.script.* API
Groovy 1.6 provides its own implementation of the javax.script.* API
ScriptEngineManager mgr = new ScriptEngineManager();ScriptEngine engine = mgr.getEngineByName(“Groovy”);
String result = (String)engine.eval(“2+3”);
54
![Page 60: Practical Groovy Domain-Specific Languages](https://reader036.fdocuments.net/reader036/viewer/2022081413/54579a22b1af9fc0638b52c1/html5/thumbnails/60.jpg)
2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone
Spring’s lang namespace
POGOs (Plain Old Groovy Objects) can be pre-compiled as any POJO and used interchangeably with POJOs in a Spring applicationBut Groovy scripts & classes can be loaded at runtime through the <lang:groovy/> namespace and tagReloadable on changeCustomizable through a custom MetaClass
<lang:groovy id="events" script-source="classpath:dsl/eventsChart.groovy" customizer-ref="eventsMetaClass" />
55
![Page 61: Practical Groovy Domain-Specific Languages](https://reader036.fdocuments.net/reader036/viewer/2022081413/54579a22b1af9fc0638b52c1/html5/thumbnails/61.jpg)
2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone
Groovy’s own mechanisms
Eval• for evaluating simple expressions
GroovyShell• for more complex scripts and DSLs
GroovyClassLoader• the most powerful mechanism
56
![Page 62: Practical Groovy Domain-Specific Languages](https://reader036.fdocuments.net/reader036/viewer/2022081413/54579a22b1af9fc0638b52c1/html5/thumbnails/62.jpg)
2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone
Eval
Simple mechanism to evaluate math-like formulas
Eval.me ( ‘3*4’)Eval.x (1, ‘3*x + 4’)Eval.xy (1, 2, ‘x + y’)Eval.xyz(1, 2, 3, ‘x * y - z’)
57
![Page 63: Practical Groovy Domain-Specific Languages](https://reader036.fdocuments.net/reader036/viewer/2022081413/54579a22b1af9fc0638b52c1/html5/thumbnails/63.jpg)
2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone
GroovyShell
A Binding provides a context of execution• can implement lazy evaluation if needed
A base script class can be specified
def binding = new Binding()binding.mass = 22.3binding.velocity = 10.6def shell = new GroovyShell(binding)shell.evaluate(“mass * velocity ** 2 / 2”)
58
![Page 64: Practical Groovy Domain-Specific Languages](https://reader036.fdocuments.net/reader036/viewer/2022081413/54579a22b1af9fc0638b52c1/html5/thumbnails/64.jpg)
2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone
GroovyClassLoader
Most powerful mechanism• could also visit or change the AST• scripts & classes can be loaded from elsewhere
• more control on compilation
GroovyClassLoader gcl = new GroovyClassLoader();Class clazz = gcl.parseClass( new File(“f.groovy”));GroovyObject instance = (GroovyObject)clazz.newInstance();instance.setMetaClass(customMC);
59
![Page 65: Practical Groovy Domain-Specific Languages](https://reader036.fdocuments.net/reader036/viewer/2022081413/54579a22b1af9fc0638b52c1/html5/thumbnails/65.jpg)
2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone
Externalize business rules
Although Groovy DSLs can be embedded in normal Groovy classes, you should externalize them
Store them elsewhere• in a database, an XML file, etc.
Benefits• Business rules are not entangled
in technical application code• Business rules can have their own lifecycle, without requiring
application redeployments
60
![Page 66: Practical Groovy Domain-Specific Languages](https://reader036.fdocuments.net/reader036/viewer/2022081413/54579a22b1af9fc0638b52c1/html5/thumbnails/66.jpg)
2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone
The context and the usual issues we faceSome real-life examples of Domain-Specific LanguagesGroovy’s DSL capabilitiesIntegrating a DSL in your applicationConsiderations to remember when designing your own DSL
Agenda
61
![Page 67: Practical Groovy Domain-Specific Languages](https://reader036.fdocuments.net/reader036/viewer/2022081413/54579a22b1af9fc0638b52c1/html5/thumbnails/67.jpg)
Start small, with key concepts
Beware overengineering!
![Page 68: Practical Groovy Domain-Specific Languages](https://reader036.fdocuments.net/reader036/viewer/2022081413/54579a22b1af9fc0638b52c1/html5/thumbnails/68.jpg)
Grow your language progressively
![Page 69: Practical Groovy Domain-Specific Languages](https://reader036.fdocuments.net/reader036/viewer/2022081413/54579a22b1af9fc0638b52c1/html5/thumbnails/69.jpg)
Get your hands dirty
Play with the end-users
![Page 70: Practical Groovy Domain-Specific Languages](https://reader036.fdocuments.net/reader036/viewer/2022081413/54579a22b1af9fc0638b52c1/html5/thumbnails/70.jpg)
Let your DSL fly, it’s not yours, it’s theirs!
![Page 71: Practical Groovy Domain-Specific Languages](https://reader036.fdocuments.net/reader036/viewer/2022081413/54579a22b1af9fc0638b52c1/html5/thumbnails/71.jpg)
Tight feedback loop
Iterative process
![Page 72: Practical Groovy Domain-Specific Languages](https://reader036.fdocuments.net/reader036/viewer/2022081413/54579a22b1af9fc0638b52c1/html5/thumbnails/72.jpg)
Stay humble.
You can’t get it right the first time.
Don’t design alone at your deskInvolve the end users from the start
![Page 73: Practical Groovy Domain-Specific Languages](https://reader036.fdocuments.net/reader036/viewer/2022081413/54579a22b1af9fc0638b52c1/html5/thumbnails/73.jpg)
Playing it safein a sandbox
![Page 74: Practical Groovy Domain-Specific Languages](https://reader036.fdocuments.net/reader036/viewer/2022081413/54579a22b1af9fc0638b52c1/html5/thumbnails/74.jpg)
2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone
Various levels of sandboxing
Groovy supports the usual Java Security Managers
Use metaprogramming tricks to prevent calling / instanciating certain classes
Create a special GroovyClassLoader AST code visitor to filter only the nodes of the AST you want to keep
• ArithmeticShell in Groovy’s samples
69
![Page 75: Practical Groovy Domain-Specific Languages](https://reader036.fdocuments.net/reader036/viewer/2022081413/54579a22b1af9fc0638b52c1/html5/thumbnails/75.jpg)
2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone
Test, test, test!
Don’t just test for nominal cases• Explicitely test for errors!
Ensure end-users get meaninful error messages
70
![Page 76: Practical Groovy Domain-Specific Languages](https://reader036.fdocuments.net/reader036/viewer/2022081413/54579a22b1af9fc0638b52c1/html5/thumbnails/76.jpg)
2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone
Summary
Questions & Answers
Agenda
71
![Page 77: Practical Groovy Domain-Specific Languages](https://reader036.fdocuments.net/reader036/viewer/2022081413/54579a22b1af9fc0638b52c1/html5/thumbnails/77.jpg)
2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone
Summary
Groovy’s a great fit for Domain-Specific Languages• Malleable & flexible syntax• Full object-orientation
Metaprogramming capabilities• Runtime metaprogramming• Compile-time metaprogramming
Groovy’s very often used for mission-critical DSLs
72
![Page 78: Practical Groovy Domain-Specific Languages](https://reader036.fdocuments.net/reader036/viewer/2022081413/54579a22b1af9fc0638b52c1/html5/thumbnails/78.jpg)
I kan haz my cheezburgr naw?Or do ya reely haz keshtionz?
?
![Page 79: Practical Groovy Domain-Specific Languages](https://reader036.fdocuments.net/reader036/viewer/2022081413/54579a22b1af9fc0638b52c1/html5/thumbnails/79.jpg)
2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone
Appendix
74
![Page 80: Practical Groovy Domain-Specific Languages](https://reader036.fdocuments.net/reader036/viewer/2022081413/54579a22b1af9fc0638b52c1/html5/thumbnails/80.jpg)
2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone
http://www.flickr.com/photos/wheatfields/420088151/sizes/l/
http://www.flickr.com/photos/therefromhere/518053737/sizes/l/
http://www.flickr.com/photos/romainguy/230416692/sizes/l/
http://www.flickr.com/photos/addictive_picasso/2874279971/sizes/l/
http://www.flickr.com/photos/huangjiahui/3127634297/sizes/l/
http://www.flickr.com/photos/25831000@N08/3064515804/sizes/o/
http://www.flickr.com/photos/lanier67/3147696168/sizes/l/
http://www.flickr.com/photos/ktb/4916063/sizes/o/
http://www.flickr.com/photos/nathonline/918128338/sizes/l/
http://www.flickr.com/photos/kevinsteele/39300193/sizes/l/
http://commons.wikimedia.org/wiki/File:Brueghel-tower-of-babel.jpg
http://commons.wikimedia.org/wiki/File:Platypus.jpg
http://www.flickr.com/photos/joaomoura/2317171808/sizes/l/
http://www.flickr.com/photos/wiccked/132687067/
http://www.flickr.com/photos/timsamoff/252370986/sizes/l/
http://www.flickr.com/photos/29738009@N08/2975466425/sizes/l/
http://www.flickr.com/photos/howie_berlin/180121635/sizes/o/
http://www.flickr.com/photos/yogi/1281980605/sizes/l/
http://www.flickr.com/photos/dorseygraphics/1336468896/sizes/l/
http://www.flickr.com/photos/xcbiker/386876546/sizes/l/
http://www.flickr.com/photos/pietel/152403711/sizes/o/
75
![Page 81: Practical Groovy Domain-Specific Languages](https://reader036.fdocuments.net/reader036/viewer/2022081413/54579a22b1af9fc0638b52c1/html5/thumbnails/81.jpg)
2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone
http://www.flickr.com/photos/forezt/192554677/sizes/o/
http://keremkosaner.files.wordpress.com/2008/04/softwaredevelopment.gif
http://www.jouy.inra.fr
http://www.flickr.com/photos/ejpphoto/408101818/sizes/o/
http://www.flickr.com/photos/solaro/2127576608/sizes/l/
http://www.flickr.com/photos/biggreymare/2846899405/sizes/l/
76