+ All Categories
Home > Technology > Designing Your Own Domain-Specific Language in Groovy by Guillaume Laforge at SpringOne/2GX 2009

Designing Your Own Domain-Specific Language in Groovy by Guillaume Laforge at SpringOne/2GX 2009

Date post: 08-May-2015
Category:
Upload: guillaume-laforge
View: 3,478 times
Download: 0 times
Share this document with a friend
Description:
Approach to designing Domain-Specific Languages in Groovy
82
Design Your Own Domain-Specific Language Guillaume Laforge - SpringSource
Transcript
Page 1: Designing Your Own Domain-Specific Language in Groovy by Guillaume Laforge at SpringOne/2GX 2009

Design Your Own Domain-Specific Language Guillaume Laforge - SpringSource

Page 2: Designing Your Own Domain-Specific Language in Groovy by Guillaume Laforge at SpringOne/2GX 2009

SpringOne 2GX 2009. All rights reserved. Do not distribute without permission.

• 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, SpringOne, JAX, Dynamic Language World, IJTC, and more...

Guillaume Laforge

2

Page 3: Designing Your Own Domain-Specific Language in Groovy by Guillaume Laforge at SpringOne/2GX 2009

SpringOne 2GX 2009. All rights reserved. Do not distribute without permission.

Introduction

Page 4: Designing Your Own Domain-Specific Language in Groovy by Guillaume Laforge at SpringOne/2GX 2009

SpringOne 2GX 2009. All rights reserved. Do not distribute without permission.

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...

4

Page 5: Designing Your Own Domain-Specific Language in Groovy by Guillaume Laforge at SpringOne/2GX 2009

The context

Page 6: Designing Your Own Domain-Specific Language in Groovy by Guillaume Laforge at SpringOne/2GX 2009

Subject Matter Experts,Business analysts...

Page 7: Designing Your Own Domain-Specific Language in Groovy by Guillaume Laforge at SpringOne/2GX 2009

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: Designing Your Own Domain-Specific Language in Groovy by Guillaume Laforge at SpringOne/2GX 2009

Lots of languages...

Page 9: Designing Your Own Domain-Specific Language in Groovy by Guillaume Laforge at SpringOne/2GX 2009

And in the end......nobody understands each other

Page 10: Designing Your Own Domain-Specific Language in Groovy by Guillaume Laforge at SpringOne/2GX 2009

SpringOne 2GX 2009. All rights reserved. Do not distribute without permission.

Expressing Requirements...

10

Page 11: Designing Your Own Domain-Specific Language in Groovy by Guillaume Laforge at SpringOne/2GX 2009

SpringOne 2GX 2009. All rights reserved. Do not distribute without permission.

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: Designing Your Own Domain-Specific Language in Groovy by Guillaume Laforge at SpringOne/2GX 2009

SpringOne 2GX 2009. All rights reserved. Do not distribute without permission.

Towards more readibility (1)

12

Page 13: Designing Your Own Domain-Specific Language in Groovy by Guillaume Laforge at SpringOne/2GX 2009

SpringOne 2GX 2009. All rights reserved. Do not distribute without permission.

Towards more readibility (1)

12

Page 14: Designing Your Own Domain-Specific Language in Groovy by Guillaume Laforge at SpringOne/2GX 2009

SpringOne 2GX 2009. All rights reserved. Do not distribute without permission.

Towards more readibility (1)

20%

12

Page 15: Designing Your Own Domain-Specific Language in Groovy by Guillaume Laforge at SpringOne/2GX 2009

SpringOne 2GX 2009. All rights reserved. Do not distribute without permission.

Towards more readibility (2)

13

Page 16: Designing Your Own Domain-Specific Language in Groovy by Guillaume Laforge at SpringOne/2GX 2009

SpringOne 2GX 2009. All rights reserved. Do not distribute without permission.

Towards more readibility (2)

13

Page 17: Designing Your Own Domain-Specific Language in Groovy by Guillaume Laforge at SpringOne/2GX 2009

SpringOne 2GX 2009. All rights reserved. Do not distribute without permission.

Towards more readibility (2)

80%

13

Page 18: Designing Your Own Domain-Specific Language in Groovy by Guillaume Laforge at SpringOne/2GX 2009

SpringOne 2GX 2009. All rights reserved. Do not distribute without permission.

A collection of DSLs

• In our everyday life, we’re surrounded by DSLs

–Technical dialects

–Notations

–Business languages

14

Page 19: Designing Your Own Domain-Specific Language in Groovy by Guillaume Laforge at SpringOne/2GX 2009

SpringOne 2GX 2009. All rights reserved. Do not distribute without permission.

Technical dialects

15

Page 20: Designing Your Own Domain-Specific Language in Groovy by Guillaume Laforge at SpringOne/2GX 2009

SQL

Page 21: Designing Your Own Domain-Specific Language in Groovy by Guillaume Laforge at SpringOne/2GX 2009

SpringOne 2GX 2009. All rights reserved. Do not distribute without permission.

^[\w-\.]+@([\w-]){2,4}$

17

Page 22: Designing Your Own Domain-Specific Language in Groovy by Guillaume Laforge at SpringOne/2GX 2009

SpringOne 2GX 2009. All rights reserved. Do not distribute without permission.

Notations

18

Page 23: Designing Your Own Domain-Specific Language in Groovy by Guillaume Laforge at SpringOne/2GX 2009

1. e4 e52. Nf3 Nc63. Bb5 a6

Page 24: Designing Your Own Domain-Specific Language in Groovy by Guillaume Laforge at SpringOne/2GX 2009

L2 U F-1 B L2 F B -1 U L2

Page 25: Designing Your Own Domain-Specific Language in Groovy by Guillaume Laforge at SpringOne/2GX 2009

Visual!

Page 26: Designing Your Own Domain-Specific Language in Groovy by Guillaume Laforge at SpringOne/2GX 2009

SpringOne 2GX 2009. All rights reserved. Do not distribute without permission.

Business languages

22

Page 27: Designing Your Own Domain-Specific Language in Groovy by Guillaume Laforge at SpringOne/2GX 2009

SpringOne 2GX 2009. All rights reserved. Do not distribute without permission.

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...

23

Page 28: Designing Your Own Domain-Specific Language in Groovy by Guillaume Laforge at SpringOne/2GX 2009

SpringOne 2GX 2009. All rights reserved. Do not distribute without permission.

The techniques

Page 29: Designing Your Own Domain-Specific Language in Groovy by Guillaume Laforge at SpringOne/2GX 2009

SpringOne 2GX 2009. All rights reserved. Do not distribute without permission.

Three levels of techniques

25

Flexible & malleable syntax

• scripts• optional typing• native syntax constructs• parens / semi ommission• BigDecimal• operator overloading• closures

Meta-programming

• POGO• categories • builders• custom MetaClasses • ExpandoMetaClass

AST transformations

• AST traversal• local transformations• global transformations• hooks into Antlr

Page 30: Designing Your Own Domain-Specific Language in Groovy by Guillaume Laforge at SpringOne/2GX 2009

SpringOne 2GX 2009. All rights reserved. Do not distribute without permission.

Flexible & malleable

Page 31: Designing Your Own Domain-Specific Language in Groovy by Guillaume Laforge at SpringOne/2GX 2009

SpringOne 2GX 2009. All rights reserved. Do not distribute without permission.

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

27

Page 32: Designing Your Own Domain-Specific Language in Groovy by Guillaume Laforge at SpringOne/2GX 2009

SpringOne 2GX 2009. All rights reserved. Do not distribute without permission.

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”

28

Page 33: Designing Your Own Domain-Specific Language in Groovy by Guillaume Laforge at SpringOne/2GX 2009

SpringOne 2GX 2009. All rights reserved. Do not distribute without permission.

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!

29

Page 34: Designing Your Own Domain-Specific Language in Groovy by Guillaume Laforge at SpringOne/2GX 2009

SpringOne 2GX 2009. All rights reserved. Do not distribute without permission.

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

30

Page 35: Designing Your Own Domain-Specific Language in Groovy by Guillaume Laforge at SpringOne/2GX 2009

SpringOne 2GX 2009. All rights reserved. Do not distribute without permission.

Optional parens & semis

• Make statements and expressions look more like natural languages

–move(left);

–move left

31

Page 36: Designing Your Own Domain-Specific Language in Groovy by Guillaume Laforge at SpringOne/2GX 2009

SpringOne 2GX 2009. All rights reserved. Do not distribute without permission.

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)

32

Page 37: Designing Your Own Domain-Specific Language in Groovy by Guillaume Laforge at SpringOne/2GX 2009

SpringOne 2GX 2009. All rights reserved. Do not distribute without permission.

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)

33

Page 38: Designing Your Own Domain-Specific Language in Groovy by Guillaume Laforge at SpringOne/2GX 2009

SpringOne 2GX 2009. All rights reserved. Do not distribute without permission.

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)

34

Page 39: Designing Your Own Domain-Specific Language in Groovy by Guillaume Laforge at SpringOne/2GX 2009

SpringOne 2GX 2009. All rights reserved. Do not distribute without permission.

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.unaryPlus()

-a a.unaryMinus()

~a a.bitwiseNegate()

35

Page 40: Designing Your Own Domain-Specific Language in Groovy by Guillaume Laforge at SpringOne/2GX 2009

SpringOne 2GX 2009. All rights reserved. Do not distribute without permission.

Meta-programming

Page 41: Designing Your Own Domain-Specific Language in Groovy by Guillaume Laforge at SpringOne/2GX 2009

Groovy’s dynamic heart:

The MOP!MetaObject Protocol

Page 42: Designing Your Own Domain-Specific Language in Groovy by Guillaume Laforge at SpringOne/2GX 2009

SpringOne 2GX 2009. All rights reserved. Do not distribute without permission.

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

38

Page 43: Designing Your Own Domain-Specific Language in Groovy by Guillaume Laforge at SpringOne/2GX 2009

SpringOne 2GX 2009. All rights reserved. Do not distribute without permission.

GroovyObject

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

–get/setProperty(String name)–invokeMethod( String name, Object[] params)

–propertyMissing(String name)–methodMissing( String name, Object[] params)

–get/setMetaClass(MetaClass mc)

• A GO can have “pretended” methods and properties

39

Page 44: Designing Your Own Domain-Specific Language in Groovy by Guillaume Laforge at SpringOne/2GX 2009

SpringOne 2GX 2009. All rights reserved. Do not distribute without permission.

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

40

Page 45: Designing Your Own Domain-Specific Language in Groovy by Guillaume Laforge at SpringOne/2GX 2009

SpringOne 2GX 2009. All rights reserved. Do not distribute without permission.

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

41

Page 46: Designing Your Own Domain-Specific Language in Groovy by Guillaume Laforge at SpringOne/2GX 2009

The Builder pattern

Page 47: Designing Your Own Domain-Specific Language in Groovy by Guillaume Laforge at SpringOne/2GX 2009

SpringOne 2GX 2009. All rights reserved. Do not distribute without permission.

A builder for HR

• softskills { ideas { capture 2 formulate 3 } ...}knowhow { languages { java 4 groovy 5 } ...}

43

Page 48: Designing Your Own Domain-Specific Language in Groovy by Guillaume Laforge at SpringOne/2GX 2009

SpringOne 2GX 2009. All rights reserved. Do not distribute without permission.

A builder for HR

• softskills { ideas { capture 2 formulate 3 } ...}knowhow { languages { java 4 groovy 5 } ...}

43

Page 49: Designing Your Own Domain-Specific Language in Groovy by Guillaume Laforge at SpringOne/2GX 2009

SpringOne 2GX 2009. All rights reserved. Do not distribute without permission.

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...

44

Page 50: Designing Your Own Domain-Specific Language in Groovy by Guillaume Laforge at SpringOne/2GX 2009

SpringOne 2GX 2009. All rights reserved. Do not distribute without permission.

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

45

Page 51: Designing Your Own Domain-Specific Language in Groovy by Guillaume Laforge at SpringOne/2GX 2009

SpringOne 2GX 2009. All rights reserved. Do not distribute without permission.

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

46

Page 52: Designing Your Own Domain-Specific Language in Groovy by Guillaume Laforge at SpringOne/2GX 2009

SpringOne 2GX 2009. All rights reserved. Do not distribute without permission.

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

47

Page 53: Designing Your Own Domain-Specific Language in Groovy by Guillaume Laforge at SpringOne/2GX 2009

SpringOne 2GX 2009. All rights reserved. Do not distribute without permission.

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

48

Page 54: Designing Your Own Domain-Specific Language in Groovy by Guillaume Laforge at SpringOne/2GX 2009

SpringOne 2GX 2009. All rights reserved. Do not distribute without permission.

Compile-time metaprogramming

Page 55: Designing Your Own Domain-Specific Language in Groovy by Guillaume Laforge at SpringOne/2GX 2009

SpringOne 2GX 2009. All rights reserved. Do not distribute without permission.

• Groovy 1.6 introduced AST Transformations• Compile-time == No runtime performance penalty!

50

Transformation

Compile-time metaprogramming

Page 56: Designing Your Own Domain-Specific Language in Groovy by Guillaume Laforge at SpringOne/2GX 2009

SpringOne 2GX 2009. All rights reserved. Do not distribute without permission.

AST Transformations

• Two kinds of transformations

–Global transformations•applicable to all compilation units

–Local transformations•applicable to marked program elements•using specific marker annotations

51

Page 57: Designing Your Own Domain-Specific Language in Groovy by Guillaume Laforge at SpringOne/2GX 2009

SpringOne 2GX 2009. All rights reserved. Do not distribute without permission.

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

Page 58: Designing Your Own Domain-Specific Language in Groovy by Guillaume Laforge at SpringOne/2GX 2009

SpringOne 2GX 2009. All rights reserved. Do not distribute without permission.

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( ["fqn.MyTransformation"])public @interface WithLogging {...}

53

Page 59: Designing Your Own Domain-Specific Language in Groovy by Guillaume Laforge at SpringOne/2GX 2009

SpringOne 2GX 2009. All rights reserved. Do not distribute without permission.

Example: the Spock framework

• Changing the semantics of the original code• But 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•

54

Page 60: Designing Your Own Domain-Specific Language in Groovy by Guillaume Laforge at SpringOne/2GX 2009

SpringOne 2GX 2009. All rights reserved. Do not distribute without permission.

Integrating DSLs

Page 61: Designing Your Own Domain-Specific Language in Groovy by Guillaume Laforge at SpringOne/2GX 2009

SpringOne 2GX 2009. All rights reserved. Do not distribute without permission.

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

56

Page 62: Designing Your Own Domain-Specific Language in Groovy by Guillaume Laforge at SpringOne/2GX 2009

SpringOne 2GX 2009. All rights reserved. Do not distribute without permission.

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”);

57

Page 63: Designing Your Own Domain-Specific Language in Groovy by Guillaume Laforge at SpringOne/2GX 2009

SpringOne 2GX 2009. All rights reserved. Do not distribute without permission.

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="events" script-source="classpath:dsl/eventsChart.groovy" customizer-ref="eventsMetaClass" />

58

Page 64: Designing Your Own Domain-Specific Language in Groovy by Guillaume Laforge at SpringOne/2GX 2009

SpringOne 2GX 2009. All rights reserved. Do not distribute without permission.

Groovy’s own mechanisms

• Eval–for evaluating simple expressions

• GroovyShell–for more complex scripts and DSLs

• GroovyClassLoader–the most powerful mechanism

59

Page 65: Designing Your Own Domain-Specific Language in Groovy by Guillaume Laforge at SpringOne/2GX 2009

SpringOne 2GX 2009. All rights reserved. Do not distribute without permission.

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’)

60

Page 66: Designing Your Own Domain-Specific Language in Groovy by Guillaume Laforge at SpringOne/2GX 2009

SpringOne 2GX 2009. All rights reserved. Do not distribute without permission.

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”)

61

Page 67: Designing Your Own Domain-Specific Language in Groovy by Guillaume Laforge at SpringOne/2GX 2009

SpringOne 2GX 2009. All rights reserved. Do not distribute without permission.

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);

62

Page 68: Designing Your Own Domain-Specific Language in Groovy by Guillaume Laforge at SpringOne/2GX 2009

SpringOne 2GX 2009. All rights reserved. Do not distribute without permission.

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

63

Page 69: Designing Your Own Domain-Specific Language in Groovy by Guillaume Laforge at SpringOne/2GX 2009

SpringOne 2GX 2009. All rights reserved. Do not distribute without permission.

A few considerations

Page 70: Designing Your Own Domain-Specific Language in Groovy by Guillaume Laforge at SpringOne/2GX 2009

Start small, with key concepts

Beware overengineering!

Page 71: Designing Your Own Domain-Specific Language in Groovy by Guillaume Laforge at SpringOne/2GX 2009

Grow your language progressively

Page 72: Designing Your Own Domain-Specific Language in Groovy by Guillaume Laforge at SpringOne/2GX 2009

Get your hands dirty

Play with the end-users

Page 73: Designing Your Own Domain-Specific Language in Groovy by Guillaume Laforge at SpringOne/2GX 2009

Let your DSL fly, it’s not yours, it’s theirs!

Page 74: Designing Your Own Domain-Specific Language in Groovy by Guillaume Laforge at SpringOne/2GX 2009

Tight feedback loop

Iterative process

Page 75: Designing Your Own Domain-Specific Language in Groovy by Guillaume Laforge at SpringOne/2GX 2009

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 76: Designing Your Own Domain-Specific Language in Groovy by Guillaume Laforge at SpringOne/2GX 2009

Playing it safein a sandbox

Page 77: Designing Your Own Domain-Specific Language in Groovy by Guillaume Laforge at SpringOne/2GX 2009

SpringOne 2GX 2009. All rights reserved. Do not distribute without permission.

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

72

Page 78: Designing Your Own Domain-Specific Language in Groovy by Guillaume Laforge at SpringOne/2GX 2009

SpringOne 2GX 2009. All rights reserved. Do not distribute without permission.

Test, test, test!

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

• Ensure end-users get meaninful error messages

73

Page 79: Designing Your Own Domain-Specific Language in Groovy by Guillaume Laforge at SpringOne/2GX 2009

SpringOne 2GX 2009. All rights reserved. Do not distribute without permission.

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

74

Page 81: Designing Your Own Domain-Specific Language in Groovy by Guillaume Laforge at SpringOne/2GX 2009

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

?

Page 82: Designing Your Own Domain-Specific Language in Groovy by Guillaume Laforge at SpringOne/2GX 2009

SpringOne 2GX 2009. All rights reserved. Do not distribute without permission.

• 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/

• 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/

77

Pictures Used in this Presentation


Recommended