Practical Domain-Specific
Languages in Groovy
Guillaume Laforge
Groovy Project Manager
SpringSource
Guillaume Laforge

Groovy Project Manager
JSR-241 Spec Lead
Head of Groovy Development
at SpringSource
Initiator of the Gr...
A few words about Groovy

 Groovy is a dynamic language for the JVM
  • with a Meta Object Protocol
  • compiles directly ...
end a
The context and                                  Ag
the usual issues we face
Some real-life examples of Domain-
Spec...
The context
Subject Matter Experts,
  Business analysts...
Developer producing LOLCODE




HAI
CAN HAS STDIO?
I HAS A VAR
IM IN YR LOOP
   UP VAR!!1
   VISIBLE VAR
   IZ VAR BIGGER ...
Lots of languages...
And in the end...
...nobody understands each other
Expressing requirements...
DSL: a potential solution?

  Use a more expressive language than a general
 purpose one

  Share a common metaphore of un...
Towards more readibility (1)




                               2009 CommunityOne Conference: EAST | developers.sun.com/ev...
Towards more readibility (1)




                               2009 CommunityOne Conference: EAST | developers.sun.com/ev...
Towards more readibility (1)




                                                                                         ...
Towards more readibility (2)




                               2009 CommunityOne Conference: EAST | developers.sun.com/ev...
Towards more readibility (2)




                               2009 CommunityOne Conference: EAST | developers.sun.com/ev...
Towards more readibility (2)




                                                                               80%

     ...
end a
The context and                                  Ag
the usual issues we face
Some real-life examples of Domain-
Spec...
A collection of DSLs


 In our everyday life, we’re surrounded by DSLs

  • Technical dialects
  • Notations
  • Business ...
Technical dialects




                     2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone   ...
SQL
^[w-.]+@([w-]){2,4}$




                2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone   18
Notations




            2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone   19
1. e4 e5
2. Nf3 Nc6
3. Bb5 a6
L2 U F-1 B L2 F B -1 U L2
Visual!
Business languages




                     2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone   ...
Real-life Groovy examples

 Anti-malaria drug resistance simulation
 Human Resources employee skills representation
 Insur...
end a
The context and                                  Ag
the usual issues we face
Some real-life examples of Domain-
Spec...
A flexible & malleable syntax

 No need to write full-blown classes, use scripts
 Optional typing (def)
  • in scripts, yo...
Scripts vs classes

 Hide all the boilerplate technical code
  • an end-user doesn’t need to know about classes

  • publi...
Optional typing

 No need to bother with types or even generics
  • unless you want to!

 Imagine an interest rate lookup ...
Native syntax constructs

 Lists
  • [Monday, Tuesday, Wednesday]
 Maps
  • [CA: ‘California’, TX: ‘Texas’]
 Ranges
  • de...
Optional parens & semis

 Make statements and expressions
 look more like natural languages



  • move(left);



  • move...
Named arguments

In Groovy you can mix named and unnamed arguments for
method parameters
 • named params are actually put ...
BigDecimal by default

 Main reason why financial institutions often decide to use
 Groovy for their business rules!
  • A...
Custom control structures,
thanks to closures
 When closures are last, they can be put “out” of the
 parentheses surroundi...
Operator overloading
a + b    a.plus(b)           Currency amounts
a - b    a.minus(b)
                             • 15.e...
Groovy’s dynamic heart:

The MOP!
MetaObject Protocol
Groovy’s MOP

All the accesses to methods, properties, constructors,
operators, etc. can be intercepted thanks to the MOP
...
GroovyObject

All instances of classes created in Groovy implement the
GroovyObject interface:

 • getProperty(String name...
MetaClass

 The core of Groovy’s MOP system
 • invokeConstructor()
 • invokeMethod() and
   invokeStaticMethod()
 • invoke...
ExpandoMetaClass

 A DSL for MetaClasses!

MoneyAmount.metaClass.constructor = { ... }
Number.metaClass.getDollars = { ......
The Builder pattern
A builder for HR

 softskills {
     ideas {
         capture 2
         formulate 3
     }
     ...
 }
 knowhow {
     la...
A builder for HR

 softskills {
     ideas {
         capture 2
         formulate 3
     }
     ...
 }
 knowhow {
     la...
Builders

Builders are...
 • a mechanism for creating any tree-structered graph
 • the realization of the GoF builder patt...
The clever trick

 GroovyObject#invokeMethod() is used to catch all non-
 existing method calls in the context of the buil...
Adding properties to numbers

 Three possible approaches

  • create a Category
    •   a category is a kind of decorator ...
With a Category

class DistanceCategory {
    static Distance getMeters(Integer self) {
        new Distance(self, Unit.ME...
With an ExpandoMetaClass

Number.metaClass.getMeters = {->
    new Distance(delegate, Unit.METERS)
}
100.meters

Works for...
Compile-time
metaprogramming
Groovy 1.6 introduced AST Transformations
Compile-time == No runtime performance penalty!



...
AST Transformations

 Two kinds of transformations
  • Global transformations
   •   applicable to all compilation units

...
Global transformations

 Implement ASTTransformation

 Annotate the transfo specifying a compilation phase
 @GroovyASTTran...
Local transformations

 Same approach as Globale transformations
 But you don’t need the META-INF file
 Instead create an ...
Example: the Spock framework

 Changing the semantics of the original code
 But keeping a valid Groovy syntax
@Speck
class...
end a
The context and                                  Ag
the usual issues we face
Some real-life examples of Domain-
Spec...
Various integration mechanisms

 Java 6’s javax.script.* APIs (aka JSR-223)
 Spring’s language namespace
 Groovy’s own mec...
Java 6’s javax.script.* API

 Groovy 1.6 provides its own implementation of the
 javax.script.* API

 ScriptEngineManager ...
Spring’s lang namespace

POGOs (Plain Old Groovy Objects) can be pre-compiled as
any POJO and used interchangeably with PO...
Groovy’s own mechanisms

 Eval
  • for evaluating simple expressions

 GroovyShell
  • for more complex scripts and DSLs

...
Eval

 Simple mechanism to evaluate math-like formulas

Eval.me (              ‘3*4’)
Eval.x (1,             ‘3*x + 4’)
Ev...
GroovyShell

 A Binding provides a context of execution
  • can implement lazy evaluation if needed

 A base script class ...
GroovyClassLoader

 Most powerful mechanism
  • could also visit or change the AST
  • scripts & classes can be loaded fro...
Externalize business rules

 Although Groovy DSLs can be embedded in normal Groovy
 classes, you should externalize them

...
end a
The context and                                  Ag
the usual issues we face
Some real-life examples of Domain-
Spec...
Start small, with key concepts
Beware overengineering!
Grow your language progressively
Get your hands dirty
Play with the end-users
Let your DSL fly,
it’s not yours,
it’s theirs!
Tight feedback loop
Iterative process
Stay humble.
You can’t get it right the first time.
Don’t design alone at your desk
Involve the end users from the start
Playing it safe
in a sandbox
Various levels
of sandboxing


 Groovy supports the usual Java Security Managers

 Use metaprogramming tricks to prevent c...
Test, test, test!

 Don’t just test for nominal cases
  • Explicitely test for errors!

 Ensure end-users get meaninful er...
end a
                                  Ag
Summary

Questions & Answers




                      2009 CommunityOne Confer...
Summary

Groovy’s a great fit for Domain-Specific Languages
 • Malleable & flexible syntax
 • Full object-orientation

Met...
?
I kan haz my cheezburgr naw?
 Or do ya reely haz keshtionz?
Appendix




           2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone   74
http://www.flickr.com/photos/wheatfields/420088151/sizes/l/
http://www.flickr.com/photos/therefromhere/518053737/sizes/l/
...
http://www.flickr.com/photos/forezt/192554677/sizes/o/
http://keremkosaner.files.wordpress.com/2008/04/softwaredevelopment...
Upcoming SlideShare
Loading in …5
×

Practical Groovy Domain-Specific Languages

1,694
-1

Published on

Published in: Technology
0 Comments
5 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
1,694
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
73
Comments
0
Likes
5
Embeds 0
No embeds

No notes for slide

Practical Groovy Domain-Specific Languages

  1. 1. Practical Domain-Specific Languages in Groovy Guillaume Laforge Groovy Project Manager SpringSource
  2. 2. Guillaume Laforge Groovy Project Manager JSR-241 Spec Lead Head of Groovy Development at 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... 2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone 2
  3. 3. 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... 2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone 3
  4. 4. end a The context and Ag 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 2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone 4
  5. 5. The context
  6. 6. Subject Matter Experts, Business analysts...
  7. 7. Developer producing LOLCODE 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
  8. 8. Lots of languages...
  9. 9. And in the end... ...nobody understands each other
  10. 10. Expressing requirements...
  11. 11. 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 2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone 11
  12. 12. Towards more readibility (1) 2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone 12
  13. 13. Towards more readibility (1) 2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone 12
  14. 14. Towards more readibility (1) 20% 2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone 12
  15. 15. Towards more readibility (2) 2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone 13
  16. 16. Towards more readibility (2) 2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone 13
  17. 17. Towards more readibility (2) 80% 2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone 13
  18. 18. end a The context and Ag 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 2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone 14
  19. 19. A collection of DSLs In our everyday life, we’re surrounded by DSLs • Technical dialects • Notations • Business languages 2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone 15
  20. 20. Technical dialects 2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone 16
  21. 21. SQL
  22. 22. ^[w-.]+@([w-]){2,4}$ 2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone 18
  23. 23. Notations 2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone 19
  24. 24. 1. e4 e5 2. Nf3 Nc6 3. Bb5 a6
  25. 25. L2 U F-1 B L2 F B -1 U L2
  26. 26. Visual!
  27. 27. Business languages 2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone 23
  28. 28. 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... 2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone 24
  29. 29. end a The context and Ag 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 2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone 25
  30. 30. 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 2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone 26
  31. 31. 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” 2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone 27
  32. 32. 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! 2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone 28
  33. 33. 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 2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone 29
  34. 34. Optional parens & semis Make statements and expressions look more like natural languages • move(left); • move left 2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone 30
  35. 35. 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) 2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone 31
  36. 36. 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) 2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone 32
  37. 37. 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) 2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone 33
  38. 38. Operator overloading a + b a.plus(b) Currency amounts a - b a.minus(b) • 15.euros + 10.dollars a * b a.multiply(b) a / b a.divide(b) Distance handling a % b a.modulo(b) • 10.kilometers - 10.meters a ** b a.power(b) a | b a.or(b) Workflow, concurrency a & b a.and(b) • taskA | taskB & taskC a ^ b a.xor(b) a[b] a.getAt(b) Credit an account a << b a.leftShift(b) •account << 10.dollars account += 10.dollars a >> b a.rightShift(b) account.credit 10.dollars +a a.positive() -a a.negative() ~a a.bitwiseNegate() 2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone 34
  39. 39. Groovy’s dynamic heart: The MOP! MetaObject Protocol
  40. 40. 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 2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone 36
  41. 41. 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 2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone 37
  42. 42. 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 2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone 38
  43. 43. 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 2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone 39
  44. 44. The Builder pattern
  45. 45. A builder for HR softskills { ideas { capture 2 formulate 3 } ... } knowhow { languages { java 4 groovy 5 } ... } 2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone 41
  46. 46. A builder for HR softskills { ideas { capture 2 formulate 3 } ... } knowhow { languages { java 4 groovy 5 } ... } 2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone 41
  47. 47. 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... 2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone 42
  48. 48. 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 2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone 43
  49. 49. 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 2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone 44
  50. 50. With a Category class DistanceCategory { static Distance getMeters(Integer self) { new Distance(self, Unit.METERS) } } use(DistanceCategory) { 100.meters } Interesting scope: thread-bound & lexical Have to surround with “use” • but there are ways to hide it 2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone 45
  51. 51. 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 2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone 46
  52. 52. Compile-time metaprogramming Groovy 1.6 introduced AST Transformations Compile-time == No runtime performance penalty! Transformation 2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone 47
  53. 53. AST Transformations Two kinds of transformations • Global transformations • applicable to all compilation units • Local transformations • applicable to marked program elements • using specific marker annotations 2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone 48
  54. 54. 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 2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone 49
  55. 55. 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 @Retention(RetentionPolicy.SOURCE) @Target([ElementType.METHOD]) @GroovyASTTransformationClass( [quot;fqn.MyTransformationquot;]) public @interface WithLogging {...} 2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone 50
  56. 56. Example: the Spock framework Changing the semantics of the original code But keeping a valid Groovy syntax @Speck class HelloSpock { def quot;can you figure out what I'm up to?quot;() { expect: name.size() == size where: name << [quot;Kirkquot;, quot;Spockquot;, quot;Scottyquot;] size << [4, 5, 6] } } Check out http://www.spockframework.org 2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone 51
  57. 57. end a The context and Ag 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 2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone 52
  58. 58. Various integration mechanisms Java 6’s javax.script.* APIs (aka JSR-223) Spring’s language namespace Groovy’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 2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone 53
  59. 59. 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”); 2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone 54
  60. 60. Spring’s lang namespace POGOs (Plain Old Groovy Objects) can be pre-compiled as any POJO and used interchangeably with POJOs in a Spring application But Groovy scripts & classes can be loaded at runtime through the <lang:groovy/> namespace and tag Reloadable on change Customizable through a custom MetaClass <lang:groovy id=quot;eventsquot; script-source=quot;classpath:dsl/ eventsChart.groovyquot; customizer-ref=quot;eventsMetaClassquot; /> 2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone 55
  61. 61. Groovy’s own mechanisms Eval • for evaluating simple expressions GroovyShell • for more complex scripts and DSLs GroovyClassLoader • the most powerful mechanism 2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone 56
  62. 62. 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’) 2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone 57
  63. 63. 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.3 binding.velocity = 10.6 def shell = new GroovyShell(binding) shell.evaluate(“mass * velocity ** 2 / 2”) 2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone 58
  64. 64. 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); 2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone 59
  65. 65. 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 2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone 60
  66. 66. end a The context and Ag 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 2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone 61
  67. 67. Start small, with key concepts Beware overengineering!
  68. 68. Grow your language progressively
  69. 69. Get your hands dirty Play with the end-users
  70. 70. Let your DSL fly, it’s not yours, it’s theirs!
  71. 71. Tight feedback loop Iterative process
  72. 72. Stay humble. You can’t get it right the first time. Don’t design alone at your desk Involve the end users from the start
  73. 73. Playing it safe in a sandbox
  74. 74. 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 2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone 69
  75. 75. Test, test, test! Don’t just test for nominal cases • Explicitely test for errors! Ensure end-users get meaninful error messages 2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone 70
  76. 76. end a Ag Summary Questions & Answers 2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone 71
  77. 77. 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 2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone 72
  78. 78. ? I kan haz my cheezburgr naw? Or do ya reely haz keshtionz?
  79. 79. Appendix 2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone 74
  80. 80. 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/ 2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone 75
  81. 81. 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/ 2009 CommunityOne Conference: EAST | developers.sun.com/events/communityone 76
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×