SlideShare una empresa de Scribd logo
1 de 143
Designing your own
Domain-Specific Language
with Groovy




  Guillaume Laforge
  Groovy Project Manager
  SpringSource / VMware
Guillaume Laforge

• Groovy Project Manager
• JSR-241 Spec Lead
• Head of Groovy Development
  at SpringSource / VMWare
• Initiator of the Grails framework
• Creator of the Gaelyk toolkit
• Co-author of Groovy in Action

• Speaker: JavaOne, QCon, JavaZone, Sun TechDays,
  Devoxx, The Spring Experience, SpringOne, JAX, Dynamic
  Language World, IJTC, and more...


                                                      2
Guillaume Laforge

• Groovy Project Manager
• JSR-241 Spec Lead
• Head of Groovy Development
  at SpringSource / VMWare
• Initiator of the Grails framework
• Creator of the Gaelyk toolkit
• Co-author of Groovy in Action

• Speaker: JavaOne, QCon, JavaZone, Sun TechDays,
  Devoxx, The Spring Experience, SpringOne, JAX, Dynamic
  Language World, IJTC, and more...


                                                      2
Domain-Specific Languages
are everywhere!




     Technical dialects
          Notations
   Real-life Groovy DSLs
SQL
^[w-.]+@([w-]){2,4}$
1. e4 e5
2. Nf3 Nc6
 3. Bb5 a6
L2   U   F -1   B   L2   F   B -1   U   L2
Music sheets:
      Visual!
Dance
notation:
  Visual!
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 many more...




                                                             10
Setting the stage...
The Context
Subject Matter Expers,
 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 THAN 10?
KTHXBYE
IM OUTTA YR LOOP
Lots of Languages...
And in the end...
nobody understands
        each other
Expressing Requirements...




                             17
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



                                                          18
Towards more readibility




                           19
Towards more readibility




                           19
Towards more readibility




                           20%




                                 19
Towards more readibility




                           20
Towards more readibility




                           20
Towards more readibility




                           80%


                                 20
Three levels of techniques

   Flexible &
malleable syntax              Meta-             Hooking into
                          programming           the compiler
• scripts
• optional typing        • POGO               • AST traversal
• native syntax          • categories         • local & global
constructs               • builders           transformations
                         • custom MetaClass   • hooks into Antlr
• parens / semi          • ExpandoMetaClass
ommission
• command chains
• named arguments
• BigDecimal
• operator overloading
• closures

                                                                   21
Level #1:
A flexible and malleable syntax
Scripts vs classes

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




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



}
    }




                                                     23
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"




                                                     23
Optional typing

• No need to bother with types or even generics
  – unless you want to!
  – but strongly typed if you so desire




                                                  24
Optional typing

• No need to bother with types or even generics
   – unless you want to!
   – but strongly typed if you so desire

//
given
this
API
method
public
Rate<LoanType,
Duration,
BigDecimal>[]
lookupTable()
{
...
}




                                                                24
Optional typing

• No need to bother with types or even generics
   – unless you want to!
   – but strongly typed if you so desire

//
given
this
API
method
public
Rate<LoanType,
Duration,
BigDecimal>[]
lookupTable()
{
...
}



    //
verbose
Java
notation
    Rate<LoanType,
Duration,
BigDecimal>[]
=
lookupTable();




                                                                24
Optional typing

• No need to bother with types or even generics
   – unless you want to!
   – but strongly typed if you so desire

//
given
this
API
method
public
Rate<LoanType,
Duration,
BigDecimal>[]
lookupTable()
{
...
}



    //
verbose
Java
notation
    Rate<LoanType,
Duration,
BigDecimal>[]
=
lookupTable();



                                    //
leaner
Groovy
variant
                                    def
table
=
lookupTable()


                                                                24
Native syntax constructs




                           25
Native syntax constructs


//
Lists




                           25
Native syntax constructs


//
Lists
def
days
=
[Monday,
Tuesday,
Wednesday]




                                          25
Native syntax constructs


//
Lists
def
days
=
[Monday,
Tuesday,
Wednesday]

//
Maps




                                          25
Native syntax constructs


//
Lists
def
days
=
[Monday,
Tuesday,
Wednesday]

//
Maps
def
states
=
[CA:
'California',
TX:
'Texas']




                                           25
Native syntax constructs


//
Lists
def
days
=
[Monday,
Tuesday,
Wednesday]

//
Maps
def
states
=
[CA:
'California',
TX:
'Texas']

//
Ranges
(you
can
create
your
own)




                                           25
Native syntax constructs


//
Lists
def
days
=
[Monday,
Tuesday,
Wednesday]

//
Maps
def
states
=
[CA:
'California',
TX:
'Texas']

//
Ranges
(you
can
create
your
own)
def
bizDays
=
Monday..Friday




                                           25
Native syntax constructs


//
Lists
def
days
=
[Monday,
Tuesday,
Wednesday]

//
Maps
def
states
=
[CA:
'California',
TX:
'Texas']

//
Ranges
(you
can
create
your
own)
def
bizDays
=
Monday..Friday
def
allowedAge
=
18..65



                                           25
Optional parens & semis

• Make statements and expressions
  look more like natural languages




                                     26
Optional parens & semis

• Make statements and expressions
  look more like natural languages


          move(left);




                                     26
Optional parens & semis

• Make statements and expressions
  look more like natural languages


          move(left);



          move
left


                                     26
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

       //
Calls
a
method
signature
like:
       def
take(Map
m,
MedicineQuantity
mq)


                                                       27
Command chains expressions




                             28
Command chains expressions


• A grammar improvement allowing you to
  drop dots & parens when chaining method calls
  – an extended version of top-level statements like println




                                                               28
Command chains expressions


• A grammar improvement allowing you to
  drop dots & parens when chaining method calls
  – an extended version of top-level statements like println




                                                               28
Command chains expressions


• A grammar improvement allowing you to
  drop dots & parens when chaining method calls
  – an extended version of top-level statements like println


• Less dots, less parens allow you to
  – write more readable business rules
  – in almost plain English sentences
    • (or any language, of course)




                                                               28
Command chains expressions


• A grammar improvement allowing you to
  drop dots & parens when chaining method calls
  – an extended version of top-level statements like println


• Less dots, less parens allow you to
  – write more readable business rules
  – in almost plain English sentences
    • (or any language, of course)




                                                               28
Command chains expressions


• A grammar improvement allowing you to
  drop dots & parens when chaining method calls
  – an extended version of top-level statements like println


• Less dots, less parens allow you to
  – write more readable business rules
  – in almost plain English sentences
    • (or any language, of course)


• Let’s have a look at some examples


                                                               28
Command chains expressions




      
turn
left

then
right





                                29
Command chains expressions

      Alternation of
      method names




      
turn
left

then
right





                                29
Command chains expressions

      Alternation of
      method names




      
turn
left

then
right



                         and parameters
                       (even named ones)




                                           29
Command chains expressions




      
turn
left

then
right





                                29
Command chains expressions




       Equivalent to:


      




(



).



(




)
      
turn
left

then
right





                                29
LookM  a!
N op are ns,
no do ts!
Command chains expressions




 take
2.pills

of

chloroquinine

after

6.hours




                                              31
Command chains expressions




 



(






).


(












).





(






)
 take
2.pills

of

chloroquinine

after

6.hours




                                              31
Command chains expressions

      //
environment
initialization
      Integer.metaClass.getPills
{
‐>
delegate
}
      Integer.metaClass.getHours
{
‐>
delegate
}
      

      //
variable
injection
      def
chloroquinine
=
/*...*/
      





  {                                                 }
      //
implementing
the
DSL
logic
      def
take(n)
{
      



[of:
{
drug
‐>
      







[after:
{
time
‐>
/*...*/
}]
      



}]
      }

      //
‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐
      take
2.pills
of
chloroquinine
after
6.hours

                                                    32
Command chains expressions




 take
2
.pills
of

chloroquinine
after

6.hours




                                              33
Command chains expressions




 take
2
.pills
of

chloroquinine
after

6.hours


                ... some dots remain ...




                                              33
Command chains expressions




 take
2

pills
of

chloroquinine
after

6
hours




                                              34
Command chains expressions




 



(
).




(

).












(




).
(




)
 take
2

pills
of

chloroquinine
after

6
hours




                                              34
Command chains expressions


      //
variable
injection
      def
(of,
after,
hours)
=
/*...*/
      

      //
implementing
the
DSL
logic




  {                                                 }
      def
take(n)
{
      



[pills:
{
of
‐>
      







[chloroquinine:
{
after
‐>
      











['6':
{
time
‐>
}]
      







}]
      



}]
      }

      //
‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐
      take
2
pills
of
chloroquinine
after
6
hours


                                                    35
Command chains expressions




                             36
Command chains expressions

 //
methods
with
multiple
arguments
(commas)




                                               36
Command chains expressions

 //
methods
with
multiple
arguments
(commas)
 take
coffee

with
sugar,
milk

and
liquor




                                               36
Command chains expressions

 //
methods
with
multiple
arguments
(commas)
 take
coffee

with
sugar,
milk

and
liquor

 //
leverage
named‐args
as
punctuation




                                               36
Command chains expressions

 //
methods
with
multiple
arguments
(commas)
 take
coffee

with
sugar,
milk

and
liquor

 //
leverage
named‐args
as
punctuation
 check
that:
margarita

tastes
good




                                               36
Command chains expressions

 //
methods
with
multiple
arguments
(commas)
 take
coffee

with
sugar,
milk

and
liquor

 //
leverage
named‐args
as
punctuation
 check
that:
margarita

tastes
good

 //
closure
parameters
for
new
control
structures




                                                    36
Command chains expressions

 //
methods
with
multiple
arguments
(commas)
 take
coffee

with
sugar,
milk

and
liquor

 //
leverage
named‐args
as
punctuation
 check
that:
margarita

tastes
good

 //
closure
parameters
for
new
control
structures
 given
{}

when
{}

then
{}




                                                    36
Command chains expressions

 //
methods
with
multiple
arguments
(commas)
 take
coffee

with
sugar,
milk

and
liquor

 //
leverage
named‐args
as
punctuation
 check
that:
margarita

tastes
good

 //
closure
parameters
for
new
control
structures
 given
{}

when
{}

then
{}

 //
zero‐arg
methods
require
parens




                                                    36
Command chains expressions

 //
methods
with
multiple
arguments
(commas)
 take
coffee

with
sugar,
milk

and
liquor

 //
leverage
named‐args
as
punctuation
 check
that:
margarita

tastes
good

 //
closure
parameters
for
new
control
structures
 given
{}

when
{}

then
{}

 //
zero‐arg
methods
require
parens
 select
all

unique()
from
names




                                                    36
Command chains expressions

 //
methods
with
multiple
arguments
(commas)
 take
coffee

with
sugar,
milk

and
liquor

 //
leverage
named‐args
as
punctuation
 check
that:
margarita

tastes
good

 //
closure
parameters
for
new
control
structures
 given
{}

when
{}

then
{}

 //
zero‐arg
methods
require
parens
 select
all

unique()
from
names

 //
possible
with
an
odd
number
of
terms


                                                    36
Command chains expressions

 //
methods
with
multiple
arguments
(commas)
 take
coffee

with
sugar,
milk

and
liquor

 //
leverage
named‐args
as
punctuation
 check
that:
margarita

tastes
good

 //
closure
parameters
for
new
control
structures
 given
{}

when
{}

then
{}

 //
zero‐arg
methods
require
parens
 select
all

unique()
from
names

 //
possible
with
an
odd
number
of
terms
 take
3

cookies

                                                    36
Command chains expressions

 //
methods
with
multiple
arguments
(commas)
 take
coffee

with
sugar,
milk

and
liquor
 



(





).



(










).


(





)

 //
leverage
named‐args
as
punctuation
 check
that:
margarita

tastes
good

 //
closure
parameters
for
new
control
structures
 given
{}

when
{}

then
{}

 //
zero‐arg
methods
require
parens
 select
all

unique()
from
names

 //
possible
with
an
odd
number
of
terms
 take
3

cookies

                                                    36
Command chains expressions

 //
methods
with
multiple
arguments
(commas)
 take
coffee

with
sugar,
milk

and
liquor
 



(





).



(










).


(





)

 //
leverage
named‐args
as
punctuation
 check
that:
margarita

tastes
good
 




(














).





(



)

 //
closure
parameters
for
new
control
structures
 given
{}

when
{}

then
{}

 //
zero‐arg
methods
require
parens
 select
all

unique()
from
names

 //
possible
with
an
odd
number
of
terms
 take
3

cookies

                                                    36
Command chains expressions

 //
methods
with
multiple
arguments
(commas)
 take
coffee

with
sugar,
milk

and
liquor
 



(





).



(










).


(





)

 //
leverage
named‐args
as
punctuation
 check
that:
margarita

tastes
good
 




(














).





(



)

 //
closure
parameters
for
new
control
structures
 given
{}

when
{}

then
{}
 




(

).



(

).



(

)

 //
zero‐arg
methods
require
parens
 select
all

unique()
from
names

 //
possible
with
an
odd
number
of
terms
 take
3

cookies

                                                    36
Command chains expressions

 //
methods
with
multiple
arguments
(commas)
 take
coffee

with
sugar,
milk

and
liquor
 



(





).



(










).


(





)

 //
leverage
named‐args
as
punctuation
 check
that:
margarita

tastes
good
 




(














).





(



)

 //
closure
parameters
for
new
control
structures
 given
{}

when
{}

then
{}
 




(

).



(

).



(

)

 //
zero‐arg
methods
require
parens
 select
all

unique()
from
names
 





(


).







.



(




)

 //
possible
with
an
odd
number
of
terms
 take
3

cookies

                                                    36
Command chains expressions

 //
methods
with
multiple
arguments
(commas)
 take
coffee

with
sugar,
milk

and
liquor
 



(





).



(










).


(





)

 //
leverage
named‐args
as
punctuation
 check
that:
margarita

tastes
good
 




(














).





(



)

 //
closure
parameters
for
new
control
structures
 given
{}

when
{}

then
{}
 




(

).



(

).



(

)

 //
zero‐arg
methods
require
parens
 select
all

unique()
from
names
 





(


).







.



(




)

 //
possible
with
an
odd
number
of
terms
 take
3

cookies
 



(
).

                                                    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!




                                                         37
BigDecimal by default

• Main reason why financial institutions often decide
  to use Groovy for their business rules!
  – Although these days rounding issues are overrated!


      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;




                                                         37
BigDecimal by default

• Main reason why financial institutions often decide
  to use Groovy for their business rules!
  – Although these days rounding issues are overrated!


      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;



      (d
*
(b
‐
c)
+
e
*
(c
‐
a))
/
(a
‐
b)




                                                         37
Custom control structures w/ closures

• When closures are last, they can be put “out” of the
  parentheses surrounding parameter


       unless
(account.balance
>
100.euros,
{

       



account.debit
100.euros

       })




                                                         38
Custom control structures w/ closures

• When closures are last, they can be put “out” of the
  parentheses surrounding parameter


       unless
(account.balance
>
100.euros,
{

       



account.debit
100.euros

       })



       //
calling
the
following
method:
       def
unless(boolean
b,
Closure
c)



                                                         38
Custom control structures w/ closures

• When closures are last, they can be put “out” of the
  parentheses surrounding parameter


       unless
(account.balance
>
100.euros)
{
       



account.debit
100.euros
       }



       //
calling
the
following
method:
       def
unless(boolean
b,
Closure
c)



                                                         38
Operator overloading

a
+
b

//
a.plus(b)           • Currency amounts
a
‐
b

//
a.minus(b)
a
*
b

//
a.multiply(b)         – 15.euros + 10.dollars
a
/
b

//
a.divide(b)
a
%
b

//
a.modulo(b)         • Distance handling
a
**
b
//
a.power(b)            – 10.kilometers - 10.meters
a
|
b

//
a.or(b)
a
&
b

//
a.and(b)            • Workflow, concurrency
a
^
b

//
a.xor(b)
a[b]


//
a.getAt(b)            – taskA | taskB & taskC
a
<<
b
//
a.leftShift(b)
a
>>
b
//
a.rightShift(b)     • Credit an account
+a




//
a.unaryPlus()         – account << 10.dollars
‐a




//
a.unaryMinus()          account += 10.dollars
~a




//
a.bitwiseNegate()       account.credit 10.dollars

                                                          39
Level #2:
Dynamic metaprogramming
The MOP
(Meta-Object Protocol)
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

                                                           42
Hooks

• GroovyObject(Support)
  – invokeMethod(), get/setProperty(), get/setMetaClass()
  – methodMissing(), propertyMissing()


• Custom MetaClasses add
  – invokeConstructor(), invokeMissingMethod(),
    invokeStaticMethod()
  – get/setAttribute()
  – respondsTo(), hasProperty()

• Categories
  – thread-scope & lexical-scope addition of methods


                                                            43
Hooks: 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


                                                            44
Adding properties to numbers

• Three possible approaches

  – create a Category
    • a category is a kind of decorator for default MCs

  – create a custom MetaClass
    • a full-blown MC class to implement
      and to set on the POGO instance

  – use ExpandoMetaClass
    • friendlier DSL approach but with a catch




                                                          45
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

                                                     46
With an ExpandoMetaClass


   Number.metaClass.getMeters
=
{‐>

   



new
Distance(delegate,
Unit.METERS)

   }
   

   100.meters



• But the catch is it’s really a global change,
  so beware EMC enhancements collisions



                                                  47
The Builder
 pattern
A builder for HR

 softskills
{
 



ideas
{
 







capture
2
 







formulate
3

 



}
 



...
 }
 knowhow
{
 



languages
{
 







java
4
 







groovy
5
 



}
 



...
 }




                        49
A builder for HR

 softskills
{
 



ideas
{
 







capture
2
 







formulate
3

 



}
 



...
 }
 knowhow
{
 



languages
{
 







java
4
 







groovy
5
 



}
 



...
 }




                        49
A builder for HR

 









(
 softskills
{
 








(
 



ideas
{
 














(
)
 







capture
2
 
















(
)
 







formulate
3

 




)
 



}
 



...
 
)
 }
 






(
 knowhow
{
 












(
 



languages
{
 











(
)
 







java
4
 













(
)
 







groovy
5
 




)
 



}
 




 



...
 
)
 }




                        49
Level #3:
Hooking into the compiler
Compile-time metaprogramming

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




                         Transformation




                                                    51
Compile-time metaprogramming

• With metaprogramming, Groovy’s able to modify the
  behaviour of programs... at runtime

• Groovy 1.6 introduced AST Transformations
  – AST: Abstract Syntax Tree
  – Ability to change what’s being compiled at compile-time!
    • No runtime impact!
    • Lets you change the semantics of your programs!
    • Nice way of implementing patterns
      and removing boiler-plate technical code
    • Better interoperability with Java
       – Jave code can call the methods / fields / etc injected in Groovy classes




                                                                                    52
AST Transformations



• Two kinds of transformations


  – Global transformations
    • applicable to all compilation units


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




                                              53
AST Transformations


• Several (local) transformations available
  – @ToString
  – @Log
  – @Delegate
  – @Immutable
  – and many more




                                              54
@Immutable

• To properly implement immutable classes
  – No mutators (state musn’t change)
  – Private final fields
  – Defensive copying of mutable components
  – Proper equals() / hashCode() / toString() for
    comparisons, or for keys in maps, etc.

      @Immutable
class
Coordinates
{
      



Double
lat,
lng
      }

      def
c1
=
new
Coordinates(lat:
48.8,
lng:
2.5)
      def
c2
=
new
Coordinates(48.8,
2.5)
      assert
c1
==
c2


                                                      55
Global transformations

• Implement ASTTransformation
• Annotate the transfo specifying a compilation phase

  @GroovyASTTransformation(phase
=
CompilePhase.CONVERSION)
  class
MyTransformation
implements
ASTTransformation
{
  



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

                                                              56
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(["com.foo.MyTransformation"])
  @interface
CoolTransform
{...}




                                                             57
Example: the Spock framework

• Changing the semantics of the original code
• But keeping a valid Groovy syntax
         @Speck
         class
HelloSpock
{
         



def
"can
you
figure
out
what
I'm
up
to?"()
{
         







expect:
         







name.size()
==
size

         







where:
         







name




|
size
         







"Kirk"


|

4
         







"Spock"

|

5
         







"Scotty"
|

6
         



}
         }


• Check out http://www.spockframework.org
                                                            58
Integration mechanisms
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




                                                                  60
Java 6’s javax.script.* API



• Groovy provides an implementation of the javax.script.* API

  ScriptEngineManager
mgr
=
new
ScriptEngineManager();
  ScriptEngine
engine
=
mgr.getEngineByName("Groovy");
  String
result
=
(String)engine.eval("2+3");




                                                           61
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/bizRules.groovy"
      customizer-ref="rulesCustomizerMetaClass" />


• More to come in the next version of Spring

                                                       62
Groovy’s own mechanisms


• GroovyShell, Eval, GroovyScriptEngine
  – for more complex scripts and DSLs

• GroovyClassLoader or CompilationUnit
  – the most powerful mechanisms




                                          63
GroovyShell

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


• A base script class can be specified
  – providing «global» methods and fields


      def
binding
=
new
Binding()
      binding.mass
=
22.3
      binding.velocity
=
10.6

      def
shell
=
new
GroovyShell(binding)
      shell.evaluate("mass
*
velocity
**
2
/
2")


                                                   64
Imports customizer

• Inject imports in your scripts
  – so that users don’t have to add imports manually


 def
configuration
=
new
CompilerConfiguration()
 

 def
custo
=
new
ImportCustomizer()
 custo.addStaticStar(Math.name)
 configuration.addCompilationCustomizers(custo)

 

 def
result
=
new
GroovyShell(configuration)
 



.evaluate("
cos
PI/3
")


                                                       65
Applying an AST transformation

• Apply local AST transformations transparently
      def
configuration
=
new
CompilerConfiguration()

      configuration.addCompilationCustomizers(
      



new
ASTTransformationCustomizer(Log))

      

      new
GroovyShell(configuration).evaluate("""
      



class
Car
{








      







Car()
{












      











log.info
'Car
constructed'








      







}




      



}





      



log.info
'Constructing
a
car'




      



def
c
=
new
Car()
      """)

                                                        66
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



                                                                     67
Domain-Specific Language Descriptors


• DSLs are nice, but what about support in my IDE?

• DSLD to the rescue
  – Domain-Specific Language Descriptors
  – for Eclipse STS (but GDLS concent available in IntelliJ IDEA too)

• Idea: a DSL for describing DSLs, in order to provide
  – code-completion
  – code navigation
  – documentation hovers



                                                                   68
Domain-Specific Language Descriptors




                                       69
Domain-Specific Language Descriptors




                                       69
Domain-Specific Language Descriptors




currentType(
subType(
Number
)
).accept
{




[m:
"meter",
yd:
"yard",
cm:
"centimeter",
mi:
"mile",
km:
"kilometer"].each
{








property
name:it.key,
type:"Distance",












doc:
"""A
<code>${it.value}</code>
from
<a
href="$url">$url</a>"""




}
}




                                                                                69
A few considerations




    Growing a language
         Security
        Testability
Start small, with key concepts
  Beware over-engineering!
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 1st time.




  Don’t design alone at your desk
Involve the end users from the start
Playing it safe in a sandbox
Example use case

• Biggest European travel services company

• Their customers
  – travel agencies, airlines, booking websites...

• Customers want to customize the user experience
  – use personalized forms and templates
  – configure and tweak the underlying reservation features

• The company runs customers’ Groovy code
  on their own platform and mutualised servers!
  – How to secure that?

                                                              78
Sandboxing approaches

• Groovy supports the usual
  Java Security Managers
  – avoid System.exit(0)

• Use metaprogramming tricks to prevent calling or
  instanciating certain classes
  – think overriding constructors to throw exceptions

• Groovy 1.8 to the rescue
  – compiler customizers
    • SecureASTCustomizer
    • ASTTransformCustomizer


                                                        79
Secure AST customizer

        Idea: Implement an «arithmetic shell»
          Being able control what a user script is
          allowed to do: only arithmetic expressions




                                                       80
Secure AST customizer

             Idea: Implement an «arithmetic shell»
               Being able control what a user script is
               allowed to do: only arithmetic expressions

• Let’s setup our environment
  – some imports
  – an import customizer to import java.lang.Math.*
  – prepare a secure AST customizer




                                                            80
Secure AST customizer

             Idea: Implement an «arithmetic shell»
               Being able control what a user script is
               allowed to do: only arithmetic expressions

• Let’s setup our environment
  – some imports
  – an import customizer to import java.lang.Math.*
  – prepare a secure AST customizer
import
org.codehaus.groovy.control.customizers.*
import
org.codehaus.groovy.control.*
import
static
org.codehaus.groovy.syntax.Types.*


def
imports
=
new
ImportCustomizer().addStaticStars('java.lang.Math')
def
secure
=
new
SecureASTCustomizer()

                                                                  80
Secure AST customizer

 ...
 secure.with
{
   //
disallow
closure
creation
   closuresAllowed
=
false

   //
disallow
method
definitions
   methodDefinitionAllowed
=
false

 

   //
empty
white
list
=>
forbid
imports
   importsWhitelist
=
[]

   staticImportsWhitelist
=
[]
   //
only
allow
the
java.lang.Math.*
static
import
   staticStarImportsWhitelist
=
['java.lang.Math'
 ...


                                                      81
Secure AST customizer
...
   //
language
tokens
allowed
   tokensWhitelist
=
[
      PLUS,
MINUS,
MULTIPLY,
DIVIDE,
MOD,
POWER,
PLUS_PLUS,

      MINUS_MINUS,
COMPARE_EQUAL,
COMPARE_NOT_EQUAL,

      COMPARE_LESS_THAN,
COMPARE_LESS_THAN_EQUAL,

      COMPARE_GREATER_THAN,
COMPARE_GREATER_THAN_EQUAL
   ]


   //
types
allowed
to
be
used
(including
primitive
types)
   constantTypesClassesWhiteList
=
[
      Integer,
Float,
Long,
Double,
BigDecimal,

      Integer.TYPE,
Long.TYPE,
Float.TYPE,
Double.TYPE
   ]


   //
classes
who
are
allowed
to
be
receivers
of
method
calls
   receiversClassesWhiteList
=
[

      Math,
Integer,
Float,
Double,
Long,
BigDecimal
]
}
...

                                                                82
Secure AST customizer

• Ready to evaluate our arithmetic expressions!
    ...
    def
config
=
new
CompilerConfiguration()
    config.addCompilationCustomizers(imports,
secure)

    def
shell
=
new
GroovyShell(config)
    

    shell.evaluate
'cos(PI/3)'


• But the following would have failed:

            shell.evaluate
'System.exit(0)'


                                                        83
Test, test, test!


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


• Ensure end-users get meaninful error messages




                                                  84
Summary
Summary


• Groovy DSLs in the wild manage millions,
  and even billions of Euros (one of my customers)
  – so I guess we can say Groovy can be trusted :-)

• Groovy 1.8 adds some nice capabilities
  for writing nicer plain-English-like business rules

• Tooling is improving greatly with DSL descriptors
  – offering nice IDE integration for authoring business rules




                                                                 86
Thank you!




                                 e
                            aforg pment
                    ume L Develo
             Guilla Groovy            om
             He ad of      e@ gmail.c
                    glaforg rge
              Email: @glafo
                      :
              Twitter




                                           87

Más contenido relacionado

La actualidad más candente

HDR Defence - Software Abstractions for Parallel Architectures
HDR Defence - Software Abstractions for Parallel ArchitecturesHDR Defence - Software Abstractions for Parallel Architectures
HDR Defence - Software Abstractions for Parallel ArchitecturesJoel Falcou
 
Lecture 1 Compiler design , computation
Lecture 1 Compiler design , computation Lecture 1 Compiler design , computation
Lecture 1 Compiler design , computation Rebaz Najeeb
 
System Programming Unit III
System Programming Unit IIISystem Programming Unit III
System Programming Unit IIIManoj Patil
 
New c sharp4_features_part_iv
New c sharp4_features_part_ivNew c sharp4_features_part_iv
New c sharp4_features_part_ivNico Ludwig
 

La actualidad más candente (6)

6 data types
6 data types6 data types
6 data types
 
HDR Defence - Software Abstractions for Parallel Architectures
HDR Defence - Software Abstractions for Parallel ArchitecturesHDR Defence - Software Abstractions for Parallel Architectures
HDR Defence - Software Abstractions for Parallel Architectures
 
SPC Unit 2
SPC Unit 2SPC Unit 2
SPC Unit 2
 
Lecture 1 Compiler design , computation
Lecture 1 Compiler design , computation Lecture 1 Compiler design , computation
Lecture 1 Compiler design , computation
 
System Programming Unit III
System Programming Unit IIISystem Programming Unit III
System Programming Unit III
 
New c sharp4_features_part_iv
New c sharp4_features_part_ivNew c sharp4_features_part_iv
New c sharp4_features_part_iv
 

Destacado

Google App Engine, Groovy and Gaelyk presentation at the Paris JUG
Google App Engine, Groovy and Gaelyk presentation at the Paris JUGGoogle App Engine, Groovy and Gaelyk presentation at the Paris JUG
Google App Engine, Groovy and Gaelyk presentation at the Paris JUGGuillaume Laforge
 
Groovy 1 7 Update, past, present, future - S2G Forum 2010
Groovy 1 7 Update, past, present, future - S2G Forum 2010Groovy 1 7 Update, past, present, future - S2G Forum 2010
Groovy 1 7 Update, past, present, future - S2G Forum 2010Guillaume Laforge
 
Groovy introduction - IJTC 2008
Groovy introduction - IJTC 2008Groovy introduction - IJTC 2008
Groovy introduction - IJTC 2008Guillaume Laforge
 
Groovy and Gaelyk - Lausanne JUG 2011 - Guillaume Laforge
Groovy and Gaelyk - Lausanne JUG 2011 - Guillaume LaforgeGroovy and Gaelyk - Lausanne JUG 2011 - Guillaume Laforge
Groovy and Gaelyk - Lausanne JUG 2011 - Guillaume LaforgeGuillaume Laforge
 
Gaelyk - Guillaume Laforge - GR8Conf Europe 2011
Gaelyk - Guillaume Laforge - GR8Conf Europe 2011Gaelyk - Guillaume Laforge - GR8Conf Europe 2011
Gaelyk - Guillaume Laforge - GR8Conf Europe 2011Guillaume Laforge
 
Groovy in the Enterprise - Case Studies - TSSJS Prague 2008 - Guillaume Laforge
Groovy in the Enterprise - Case Studies - TSSJS Prague 2008 - Guillaume LaforgeGroovy in the Enterprise - Case Studies - TSSJS Prague 2008 - Guillaume Laforge
Groovy in the Enterprise - Case Studies - TSSJS Prague 2008 - Guillaume LaforgeGuillaume Laforge
 

Destacado (6)

Google App Engine, Groovy and Gaelyk presentation at the Paris JUG
Google App Engine, Groovy and Gaelyk presentation at the Paris JUGGoogle App Engine, Groovy and Gaelyk presentation at the Paris JUG
Google App Engine, Groovy and Gaelyk presentation at the Paris JUG
 
Groovy 1 7 Update, past, present, future - S2G Forum 2010
Groovy 1 7 Update, past, present, future - S2G Forum 2010Groovy 1 7 Update, past, present, future - S2G Forum 2010
Groovy 1 7 Update, past, present, future - S2G Forum 2010
 
Groovy introduction - IJTC 2008
Groovy introduction - IJTC 2008Groovy introduction - IJTC 2008
Groovy introduction - IJTC 2008
 
Groovy and Gaelyk - Lausanne JUG 2011 - Guillaume Laforge
Groovy and Gaelyk - Lausanne JUG 2011 - Guillaume LaforgeGroovy and Gaelyk - Lausanne JUG 2011 - Guillaume Laforge
Groovy and Gaelyk - Lausanne JUG 2011 - Guillaume Laforge
 
Gaelyk - Guillaume Laforge - GR8Conf Europe 2011
Gaelyk - Guillaume Laforge - GR8Conf Europe 2011Gaelyk - Guillaume Laforge - GR8Conf Europe 2011
Gaelyk - Guillaume Laforge - GR8Conf Europe 2011
 
Groovy in the Enterprise - Case Studies - TSSJS Prague 2008 - Guillaume Laforge
Groovy in the Enterprise - Case Studies - TSSJS Prague 2008 - Guillaume LaforgeGroovy in the Enterprise - Case Studies - TSSJS Prague 2008 - Guillaume Laforge
Groovy in the Enterprise - Case Studies - TSSJS Prague 2008 - Guillaume Laforge
 

Similar a Groovy DSLs - S2GForum London 2011 - Guillaume Laforge

GR8Conf 2009: Practical Groovy DSL by Guillaume Laforge
GR8Conf 2009: Practical Groovy DSL by Guillaume LaforgeGR8Conf 2009: Practical Groovy DSL by Guillaume Laforge
GR8Conf 2009: Practical Groovy DSL by Guillaume LaforgeGR8Conf
 
Tools and practices to help you deal with legacy code
Tools and practices to help you deal with legacy codeTools and practices to help you deal with legacy code
Tools and practices to help you deal with legacy codeDennis Doomen
 
Game Programming 04 - Style & Design Principles
Game Programming 04 - Style & Design PrinciplesGame Programming 04 - Style & Design Principles
Game Programming 04 - Style & Design PrinciplesNick Pruehs
 
Reading Notes : the practice of programming
Reading Notes : the practice of programmingReading Notes : the practice of programming
Reading Notes : the practice of programmingJuggernaut Liu
 
Design Like a Pro: Scripting Best Practices
Design Like a Pro: Scripting Best PracticesDesign Like a Pro: Scripting Best Practices
Design Like a Pro: Scripting Best PracticesInductive Automation
 
Style & Design Principles 01 - Code Style & Structure
Style & Design Principles 01 - Code Style & StructureStyle & Design Principles 01 - Code Style & Structure
Style & Design Principles 01 - Code Style & StructureNick Pruehs
 
Software Engineering Thailand: Programming with Scala
Software Engineering Thailand: Programming with ScalaSoftware Engineering Thailand: Programming with Scala
Software Engineering Thailand: Programming with ScalaBrian Topping
 
(Costless) Software Abstractions for Parallel Architectures
(Costless) Software Abstractions for Parallel Architectures(Costless) Software Abstractions for Parallel Architectures
(Costless) Software Abstractions for Parallel ArchitecturesJoel Falcou
 
Design Like a Pro: Scripting Best Practices
Design Like a Pro: Scripting Best PracticesDesign Like a Pro: Scripting Best Practices
Design Like a Pro: Scripting Best PracticesInductive Automation
 
[Gophercon 2019] Analysing code quality with linters and static analysis
[Gophercon 2019] Analysing code quality with linters and static analysis[Gophercon 2019] Analysing code quality with linters and static analysis
[Gophercon 2019] Analysing code quality with linters and static analysisWeverton Timoteo
 
Simple Ruby DSL Techniques: Big Project Impact!
Simple Ruby DSL Techniques: Big Project Impact!Simple Ruby DSL Techniques: Big Project Impact!
Simple Ruby DSL Techniques: Big Project Impact!Aman King
 
Devel::NYTProf 2009-07 (OUTDATED, see 201008)
Devel::NYTProf 2009-07 (OUTDATED, see 201008)Devel::NYTProf 2009-07 (OUTDATED, see 201008)
Devel::NYTProf 2009-07 (OUTDATED, see 201008)Tim Bunce
 
Stefan Richter - Writing simple, readable and robust code: Examples in Java, ...
Stefan Richter - Writing simple, readable and robust code: Examples in Java, ...Stefan Richter - Writing simple, readable and robust code: Examples in Java, ...
Stefan Richter - Writing simple, readable and robust code: Examples in Java, ...AboutYouGmbH
 
Strong typing @ php leeds
Strong typing  @ php leedsStrong typing  @ php leeds
Strong typing @ php leedsDamien Seguy
 
APIs and SDKs: Breaking into and Succeeding in a Specialty Market
APIs and SDKs: Breaking into and Succeeding in a Specialty MarketAPIs and SDKs: Breaking into and Succeeding in a Specialty Market
APIs and SDKs: Breaking into and Succeeding in a Specialty MarketSTC-Philadelphia Metro Chapter
 

Similar a Groovy DSLs - S2GForum London 2011 - Guillaume Laforge (20)

GR8Conf 2009: Practical Groovy DSL by Guillaume Laforge
GR8Conf 2009: Practical Groovy DSL by Guillaume LaforgeGR8Conf 2009: Practical Groovy DSL by Guillaume Laforge
GR8Conf 2009: Practical Groovy DSL by Guillaume Laforge
 
Tools and practices to help you deal with legacy code
Tools and practices to help you deal with legacy codeTools and practices to help you deal with legacy code
Tools and practices to help you deal with legacy code
 
Game Programming 04 - Style & Design Principles
Game Programming 04 - Style & Design PrinciplesGame Programming 04 - Style & Design Principles
Game Programming 04 - Style & Design Principles
 
Clean Code V2
Clean Code V2Clean Code V2
Clean Code V2
 
08 subprograms
08 subprograms08 subprograms
08 subprograms
 
Reading Notes : the practice of programming
Reading Notes : the practice of programmingReading Notes : the practice of programming
Reading Notes : the practice of programming
 
Design Like a Pro: Scripting Best Practices
Design Like a Pro: Scripting Best PracticesDesign Like a Pro: Scripting Best Practices
Design Like a Pro: Scripting Best Practices
 
Style & Design Principles 01 - Code Style & Structure
Style & Design Principles 01 - Code Style & StructureStyle & Design Principles 01 - Code Style & Structure
Style & Design Principles 01 - Code Style & Structure
 
Software Engineering Thailand: Programming with Scala
Software Engineering Thailand: Programming with ScalaSoftware Engineering Thailand: Programming with Scala
Software Engineering Thailand: Programming with Scala
 
(Costless) Software Abstractions for Parallel Architectures
(Costless) Software Abstractions for Parallel Architectures(Costless) Software Abstractions for Parallel Architectures
(Costless) Software Abstractions for Parallel Architectures
 
Design Like a Pro: Scripting Best Practices
Design Like a Pro: Scripting Best PracticesDesign Like a Pro: Scripting Best Practices
Design Like a Pro: Scripting Best Practices
 
[Gophercon 2019] Analysing code quality with linters and static analysis
[Gophercon 2019] Analysing code quality with linters and static analysis[Gophercon 2019] Analysing code quality with linters and static analysis
[Gophercon 2019] Analysing code quality with linters and static analysis
 
Simple Ruby DSL Techniques: Big Project Impact!
Simple Ruby DSL Techniques: Big Project Impact!Simple Ruby DSL Techniques: Big Project Impact!
Simple Ruby DSL Techniques: Big Project Impact!
 
Devel::NYTProf 2009-07 (OUTDATED, see 201008)
Devel::NYTProf 2009-07 (OUTDATED, see 201008)Devel::NYTProf 2009-07 (OUTDATED, see 201008)
Devel::NYTProf 2009-07 (OUTDATED, see 201008)
 
Subprogram
SubprogramSubprogram
Subprogram
 
Mcs lec2
Mcs lec2Mcs lec2
Mcs lec2
 
Stefan Richter - Writing simple, readable and robust code: Examples in Java, ...
Stefan Richter - Writing simple, readable and robust code: Examples in Java, ...Stefan Richter - Writing simple, readable and robust code: Examples in Java, ...
Stefan Richter - Writing simple, readable and robust code: Examples in Java, ...
 
firststeps
firststepsfirststeps
firststeps
 
Strong typing @ php leeds
Strong typing  @ php leedsStrong typing  @ php leeds
Strong typing @ php leeds
 
APIs and SDKs: Breaking into and Succeeding in a Specialty Market
APIs and SDKs: Breaking into and Succeeding in a Specialty MarketAPIs and SDKs: Breaking into and Succeeding in a Specialty Market
APIs and SDKs: Breaking into and Succeeding in a Specialty Market
 

Más de Guillaume Laforge

Lift off with Groovy 2 at JavaOne 2013
Lift off with Groovy 2 at JavaOne 2013Lift off with Groovy 2 at JavaOne 2013
Lift off with Groovy 2 at JavaOne 2013Guillaume Laforge
 
Groovy workshop à Mix-IT 2013
Groovy workshop à Mix-IT 2013Groovy workshop à Mix-IT 2013
Groovy workshop à Mix-IT 2013Guillaume Laforge
 
Les nouveautés de Groovy 2 -- Mix-IT 2013
Les nouveautés de Groovy 2 -- Mix-IT 2013Les nouveautés de Groovy 2 -- Mix-IT 2013
Les nouveautés de Groovy 2 -- Mix-IT 2013Guillaume Laforge
 
Groovy 2.0 update at Devoxx 2012
Groovy 2.0 update at Devoxx 2012Groovy 2.0 update at Devoxx 2012
Groovy 2.0 update at Devoxx 2012Guillaume Laforge
 
Groovy Domain Specific Languages - SpringOne2GX 2012
Groovy Domain Specific Languages - SpringOne2GX 2012Groovy Domain Specific Languages - SpringOne2GX 2012
Groovy Domain Specific Languages - SpringOne2GX 2012Guillaume Laforge
 
Groovy update at SpringOne2GX 2012
Groovy update at SpringOne2GX 2012Groovy update at SpringOne2GX 2012
Groovy update at SpringOne2GX 2012Guillaume Laforge
 
Groovy 1.8 et 2.0 au BreizhC@mp 2012
Groovy 1.8 et 2.0 au BreizhC@mp 2012Groovy 1.8 et 2.0 au BreizhC@mp 2012
Groovy 1.8 et 2.0 au BreizhC@mp 2012Guillaume Laforge
 
Groovy 1.8 and 2.0 at GR8Conf Europe 2012
Groovy 1.8 and 2.0 at GR8Conf Europe 2012Groovy 1.8 and 2.0 at GR8Conf Europe 2012
Groovy 1.8 and 2.0 at GR8Conf Europe 2012Guillaume Laforge
 
Groovy 2.0 update - Cloud Foundry Open Tour Moscow - Guillaume Laforge
Groovy 2.0 update - Cloud Foundry Open Tour Moscow - Guillaume LaforgeGroovy 2.0 update - Cloud Foundry Open Tour Moscow - Guillaume Laforge
Groovy 2.0 update - Cloud Foundry Open Tour Moscow - Guillaume LaforgeGuillaume Laforge
 
Going to Mars with Groovy Domain-Specific Languages
Going to Mars with Groovy Domain-Specific LanguagesGoing to Mars with Groovy Domain-Specific Languages
Going to Mars with Groovy Domain-Specific LanguagesGuillaume Laforge
 
Groovy 2.0 - Devoxx France 2012
Groovy 2.0 - Devoxx France 2012Groovy 2.0 - Devoxx France 2012
Groovy 2.0 - Devoxx France 2012Guillaume Laforge
 
Groovy Update, new in 1.8 and beyond - Guillaume Laforge - Devoxx 2011
Groovy Update, new in 1.8 and beyond - Guillaume Laforge - Devoxx 2011Groovy Update, new in 1.8 and beyond - Guillaume Laforge - Devoxx 2011
Groovy Update, new in 1.8 and beyond - Guillaume Laforge - Devoxx 2011Guillaume Laforge
 
GPars et PrettyTime - Paris JUG 2011 - Guillaume Laforge
GPars et PrettyTime - Paris JUG 2011 - Guillaume LaforgeGPars et PrettyTime - Paris JUG 2011 - Guillaume Laforge
GPars et PrettyTime - Paris JUG 2011 - Guillaume LaforgeGuillaume Laforge
 
Groovy Update - Guillaume Laforge - Greach 2011
Groovy Update - Guillaume Laforge - Greach 2011Groovy Update - Guillaume Laforge - Greach 2011
Groovy Update - Guillaume Laforge - Greach 2011Guillaume Laforge
 
Gaelyk update - Guillaume Laforge - SpringOne2GX 2011
Gaelyk update - Guillaume Laforge - SpringOne2GX 2011Gaelyk update - Guillaume Laforge - SpringOne2GX 2011
Gaelyk update - Guillaume Laforge - SpringOne2GX 2011Guillaume Laforge
 
Groovy Update, what's new in Groovy 1.8 and beyond - Guillaume Laforge - Spri...
Groovy Update, what's new in Groovy 1.8 and beyond - Guillaume Laforge - Spri...Groovy Update, what's new in Groovy 1.8 and beyond - Guillaume Laforge - Spri...
Groovy Update, what's new in Groovy 1.8 and beyond - Guillaume Laforge - Spri...Guillaume Laforge
 

Más de Guillaume Laforge (20)

Lift off with Groovy 2 at JavaOne 2013
Lift off with Groovy 2 at JavaOne 2013Lift off with Groovy 2 at JavaOne 2013
Lift off with Groovy 2 at JavaOne 2013
 
Groovy workshop à Mix-IT 2013
Groovy workshop à Mix-IT 2013Groovy workshop à Mix-IT 2013
Groovy workshop à Mix-IT 2013
 
Les nouveautés de Groovy 2 -- Mix-IT 2013
Les nouveautés de Groovy 2 -- Mix-IT 2013Les nouveautés de Groovy 2 -- Mix-IT 2013
Les nouveautés de Groovy 2 -- Mix-IT 2013
 
Groovy 2 and beyond
Groovy 2 and beyondGroovy 2 and beyond
Groovy 2 and beyond
 
Groovy 2.0 update at Devoxx 2012
Groovy 2.0 update at Devoxx 2012Groovy 2.0 update at Devoxx 2012
Groovy 2.0 update at Devoxx 2012
 
Groovy 2.0 webinar
Groovy 2.0 webinarGroovy 2.0 webinar
Groovy 2.0 webinar
 
Groovy Domain Specific Languages - SpringOne2GX 2012
Groovy Domain Specific Languages - SpringOne2GX 2012Groovy Domain Specific Languages - SpringOne2GX 2012
Groovy Domain Specific Languages - SpringOne2GX 2012
 
Groovy update at SpringOne2GX 2012
Groovy update at SpringOne2GX 2012Groovy update at SpringOne2GX 2012
Groovy update at SpringOne2GX 2012
 
JavaOne 2012 Groovy update
JavaOne 2012 Groovy updateJavaOne 2012 Groovy update
JavaOne 2012 Groovy update
 
Groovy 1.8 et 2.0 au BreizhC@mp 2012
Groovy 1.8 et 2.0 au BreizhC@mp 2012Groovy 1.8 et 2.0 au BreizhC@mp 2012
Groovy 1.8 et 2.0 au BreizhC@mp 2012
 
Groovy 1.8 and 2.0 at GR8Conf Europe 2012
Groovy 1.8 and 2.0 at GR8Conf Europe 2012Groovy 1.8 and 2.0 at GR8Conf Europe 2012
Groovy 1.8 and 2.0 at GR8Conf Europe 2012
 
Groovy 2.0 update - Cloud Foundry Open Tour Moscow - Guillaume Laforge
Groovy 2.0 update - Cloud Foundry Open Tour Moscow - Guillaume LaforgeGroovy 2.0 update - Cloud Foundry Open Tour Moscow - Guillaume Laforge
Groovy 2.0 update - Cloud Foundry Open Tour Moscow - Guillaume Laforge
 
Going to Mars with Groovy Domain-Specific Languages
Going to Mars with Groovy Domain-Specific LanguagesGoing to Mars with Groovy Domain-Specific Languages
Going to Mars with Groovy Domain-Specific Languages
 
Groovy 2.0 - Devoxx France 2012
Groovy 2.0 - Devoxx France 2012Groovy 2.0 - Devoxx France 2012
Groovy 2.0 - Devoxx France 2012
 
Whats new in Groovy 2.0?
Whats new in Groovy 2.0?Whats new in Groovy 2.0?
Whats new in Groovy 2.0?
 
Groovy Update, new in 1.8 and beyond - Guillaume Laforge - Devoxx 2011
Groovy Update, new in 1.8 and beyond - Guillaume Laforge - Devoxx 2011Groovy Update, new in 1.8 and beyond - Guillaume Laforge - Devoxx 2011
Groovy Update, new in 1.8 and beyond - Guillaume Laforge - Devoxx 2011
 
GPars et PrettyTime - Paris JUG 2011 - Guillaume Laforge
GPars et PrettyTime - Paris JUG 2011 - Guillaume LaforgeGPars et PrettyTime - Paris JUG 2011 - Guillaume Laforge
GPars et PrettyTime - Paris JUG 2011 - Guillaume Laforge
 
Groovy Update - Guillaume Laforge - Greach 2011
Groovy Update - Guillaume Laforge - Greach 2011Groovy Update - Guillaume Laforge - Greach 2011
Groovy Update - Guillaume Laforge - Greach 2011
 
Gaelyk update - Guillaume Laforge - SpringOne2GX 2011
Gaelyk update - Guillaume Laforge - SpringOne2GX 2011Gaelyk update - Guillaume Laforge - SpringOne2GX 2011
Gaelyk update - Guillaume Laforge - SpringOne2GX 2011
 
Groovy Update, what's new in Groovy 1.8 and beyond - Guillaume Laforge - Spri...
Groovy Update, what's new in Groovy 1.8 and beyond - Guillaume Laforge - Spri...Groovy Update, what's new in Groovy 1.8 and beyond - Guillaume Laforge - Spri...
Groovy Update, what's new in Groovy 1.8 and beyond - Guillaume Laforge - Spri...
 

Último

"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr BaganFwdays
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationSlibray Presentation
 
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks..."LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...Fwdays
 
Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage Cost
Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage CostLeverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage Cost
Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage CostZilliz
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek SchlawackFwdays
 
CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):comworks
 
Advanced Computer Architecture – An Introduction
Advanced Computer Architecture – An IntroductionAdvanced Computer Architecture – An Introduction
Advanced Computer Architecture – An IntroductionDilum Bandara
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Mark Simos
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebUiPathCommunity
 
Powerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time ClashPowerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time Clashcharlottematthew16
 
Search Engine Optimization SEO PDF for 2024.pdf
Search Engine Optimization SEO PDF for 2024.pdfSearch Engine Optimization SEO PDF for 2024.pdf
Search Engine Optimization SEO PDF for 2024.pdfRankYa
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc
 
Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Scott Keck-Warren
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubKalema Edgar
 
H2O.ai CEO/Founder: Sri Ambati Keynote at Wells Fargo Day
H2O.ai CEO/Founder: Sri Ambati Keynote at Wells Fargo DayH2O.ai CEO/Founder: Sri Ambati Keynote at Wells Fargo Day
H2O.ai CEO/Founder: Sri Ambati Keynote at Wells Fargo DaySri Ambati
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .Alan Dix
 
Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Manik S Magar
 
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxLoriGlavin3
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupFlorian Wilhelm
 

Último (20)

"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck Presentation
 
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks..."LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
 
Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage Cost
Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage CostLeverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage Cost
Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage Cost
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
 
CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):
 
Advanced Computer Architecture – An Introduction
Advanced Computer Architecture – An IntroductionAdvanced Computer Architecture – An Introduction
Advanced Computer Architecture – An Introduction
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio Web
 
Powerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time ClashPowerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time Clash
 
Search Engine Optimization SEO PDF for 2024.pdf
Search Engine Optimization SEO PDF for 2024.pdfSearch Engine Optimization SEO PDF for 2024.pdf
Search Engine Optimization SEO PDF for 2024.pdf
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
 
Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding Club
 
H2O.ai CEO/Founder: Sri Ambati Keynote at Wells Fargo Day
H2O.ai CEO/Founder: Sri Ambati Keynote at Wells Fargo DayH2O.ai CEO/Founder: Sri Ambati Keynote at Wells Fargo Day
H2O.ai CEO/Founder: Sri Ambati Keynote at Wells Fargo Day
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .
 
Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!
 
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project Setup
 

Groovy DSLs - S2GForum London 2011 - Guillaume Laforge

  • 1. Designing your own Domain-Specific Language with Groovy Guillaume Laforge Groovy Project Manager SpringSource / VMware
  • 2. Guillaume Laforge • Groovy Project Manager • JSR-241 Spec Lead • Head of Groovy Development at SpringSource / VMWare • Initiator of the Grails framework • Creator of the Gaelyk toolkit • Co-author of Groovy in Action • Speaker: JavaOne, QCon, JavaZone, Sun TechDays, Devoxx, The Spring Experience, SpringOne, JAX, Dynamic Language World, IJTC, and more... 2
  • 3. Guillaume Laforge • Groovy Project Manager • JSR-241 Spec Lead • Head of Groovy Development at SpringSource / VMWare • Initiator of the Grails framework • Creator of the Gaelyk toolkit • Co-author of Groovy in Action • Speaker: JavaOne, QCon, JavaZone, Sun TechDays, Devoxx, The Spring Experience, SpringOne, JAX, Dynamic Language World, IJTC, and more... 2
  • 4. Domain-Specific Languages are everywhere! Technical dialects Notations Real-life Groovy DSLs
  • 5. SQL
  • 7. 1. e4 e5 2. Nf3 Nc6 3. Bb5 a6
  • 8. L2 U F -1 B L2 F B -1 U L2
  • 9. Music sheets: Visual!
  • 11. 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 many more... 10
  • 14. Subject Matter Expers, Business Analysts...
  • 15. 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
  • 17. And in the end... nobody understands each other
  • 19. 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 18
  • 26. Three levels of techniques Flexible & malleable syntax Meta- Hooking into programming the compiler • scripts • optional typing • POGO • AST traversal • native syntax • categories • local & global constructs • builders transformations • custom MetaClass • hooks into Antlr • parens / semi • ExpandoMetaClass ommission • command chains • named arguments • BigDecimal • operator overloading • closures 21
  • 27. Level #1: A flexible and malleable syntax
  • 28. Scripts vs classes • Hide all the boilerplate technical code – an end-user doesn’t need to know about classes 23
  • 29. 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"); 



} } 23
  • 30. 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" 23
  • 31. Optional typing • No need to bother with types or even generics – unless you want to! – but strongly typed if you so desire 24
  • 32. Optional typing • No need to bother with types or even generics – unless you want to! – but strongly typed if you so desire //
given
this
API
method public
Rate<LoanType,
Duration,
BigDecimal>[]
lookupTable()
{
...
} 24
  • 33. Optional typing • No need to bother with types or even generics – unless you want to! – but strongly typed if you so desire //
given
this
API
method public
Rate<LoanType,
Duration,
BigDecimal>[]
lookupTable()
{
...
} //
verbose
Java
notation Rate<LoanType,
Duration,
BigDecimal>[]
=
lookupTable(); 24
  • 34. Optional typing • No need to bother with types or even generics – unless you want to! – but strongly typed if you so desire //
given
this
API
method public
Rate<LoanType,
Duration,
BigDecimal>[]
lookupTable()
{
...
} //
verbose
Java
notation Rate<LoanType,
Duration,
BigDecimal>[]
=
lookupTable(); //
leaner
Groovy
variant def
table
=
lookupTable() 24
  • 43. Optional parens & semis • Make statements and expressions look more like natural languages 26
  • 44. Optional parens & semis • Make statements and expressions look more like natural languages move(left); 26
  • 45. Optional parens & semis • Make statements and expressions look more like natural languages move(left); move
left 26
  • 46. 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 //
Calls
a
method
signature
like: def
take(Map
m,
MedicineQuantity
mq) 27
  • 48. Command chains expressions • A grammar improvement allowing you to drop dots & parens when chaining method calls – an extended version of top-level statements like println 28
  • 49. Command chains expressions • A grammar improvement allowing you to drop dots & parens when chaining method calls – an extended version of top-level statements like println 28
  • 50. Command chains expressions • A grammar improvement allowing you to drop dots & parens when chaining method calls – an extended version of top-level statements like println • Less dots, less parens allow you to – write more readable business rules – in almost plain English sentences • (or any language, of course) 28
  • 51. Command chains expressions • A grammar improvement allowing you to drop dots & parens when chaining method calls – an extended version of top-level statements like println • Less dots, less parens allow you to – write more readable business rules – in almost plain English sentences • (or any language, of course) 28
  • 52. Command chains expressions • A grammar improvement allowing you to drop dots & parens when chaining method calls – an extended version of top-level statements like println • Less dots, less parens allow you to – write more readable business rules – in almost plain English sentences • (or any language, of course) • Let’s have a look at some examples 28
  • 53. Command chains expressions 
turn
left

then
right
 29
  • 54. Command chains expressions Alternation of method names 
turn
left

then
right
 29
  • 55. Command chains expressions Alternation of method names 
turn
left

then
right
 and parameters (even named ones) 29
  • 56. Command chains expressions 
turn
left

then
right
 29
  • 57. Command chains expressions Equivalent to: 




(



).



(




) 
turn
left

then
right
 29
  • 58. LookM a! N op are ns, no do ts!
  • 59. Command chains expressions take
2.pills

of

chloroquinine

after

6.hours 31
  • 60. Command chains expressions 



(






).


(












).





(






) take
2.pills

of

chloroquinine

after

6.hours 31
  • 61. Command chains expressions //
environment
initialization Integer.metaClass.getPills
{
‐>
delegate
} Integer.metaClass.getHours
{
‐>
delegate
} 
 //
variable
injection def
chloroquinine
=
/*...*/ 
 { } //
implementing
the
DSL
logic def
take(n)
{ 



[of:
{
drug
‐> 







[after:
{
time
‐>
/*...*/
}] 



}] } //
‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ take
2.pills
of
chloroquinine
after
6.hours 32
  • 62. Command chains expressions take
2
.pills
of

chloroquinine
after

6.hours 33
  • 63. Command chains expressions take
2
.pills
of

chloroquinine
after

6.hours ... some dots remain ... 33
  • 64. Command chains expressions take
2

pills
of

chloroquinine
after

6
hours 34
  • 65. Command chains expressions 



(
).




(

).












(




).
(




) take
2

pills
of

chloroquinine
after

6
hours 34
  • 66. Command chains expressions //
variable
injection def
(of,
after,
hours)
=
/*...*/ 
 //
implementing
the
DSL
logic { } def
take(n)
{ 



[pills:
{
of
‐> 







[chloroquinine:
{
after
‐> 











['6':
{
time
‐>
}] 







}] 



}] } //
‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ take
2
pills
of
chloroquinine
after
6
hours 35
  • 68. Command chains expressions //
methods
with
multiple
arguments
(commas) 36
  • 69. Command chains expressions //
methods
with
multiple
arguments
(commas) take
coffee

with
sugar,
milk

and
liquor 36
  • 70. Command chains expressions //
methods
with
multiple
arguments
(commas) take
coffee

with
sugar,
milk

and
liquor //
leverage
named‐args
as
punctuation 36
  • 71. Command chains expressions //
methods
with
multiple
arguments
(commas) take
coffee

with
sugar,
milk

and
liquor //
leverage
named‐args
as
punctuation check
that:
margarita

tastes
good 36
  • 72. Command chains expressions //
methods
with
multiple
arguments
(commas) take
coffee

with
sugar,
milk

and
liquor //
leverage
named‐args
as
punctuation check
that:
margarita

tastes
good //
closure
parameters
for
new
control
structures 36
  • 73. Command chains expressions //
methods
with
multiple
arguments
(commas) take
coffee

with
sugar,
milk

and
liquor //
leverage
named‐args
as
punctuation check
that:
margarita

tastes
good //
closure
parameters
for
new
control
structures given
{}

when
{}

then
{} 36
  • 74. Command chains expressions //
methods
with
multiple
arguments
(commas) take
coffee

with
sugar,
milk

and
liquor //
leverage
named‐args
as
punctuation check
that:
margarita

tastes
good //
closure
parameters
for
new
control
structures given
{}

when
{}

then
{} //
zero‐arg
methods
require
parens 36
  • 75. Command chains expressions //
methods
with
multiple
arguments
(commas) take
coffee

with
sugar,
milk

and
liquor //
leverage
named‐args
as
punctuation check
that:
margarita

tastes
good //
closure
parameters
for
new
control
structures given
{}

when
{}

then
{} //
zero‐arg
methods
require
parens select
all

unique()
from
names 36
  • 76. Command chains expressions //
methods
with
multiple
arguments
(commas) take
coffee

with
sugar,
milk

and
liquor //
leverage
named‐args
as
punctuation check
that:
margarita

tastes
good //
closure
parameters
for
new
control
structures given
{}

when
{}

then
{} //
zero‐arg
methods
require
parens select
all

unique()
from
names //
possible
with
an
odd
number
of
terms 36
  • 77. Command chains expressions //
methods
with
multiple
arguments
(commas) take
coffee

with
sugar,
milk

and
liquor //
leverage
named‐args
as
punctuation check
that:
margarita

tastes
good //
closure
parameters
for
new
control
structures given
{}

when
{}

then
{} //
zero‐arg
methods
require
parens select
all

unique()
from
names //
possible
with
an
odd
number
of
terms take
3

cookies 36
  • 78. Command chains expressions //
methods
with
multiple
arguments
(commas) take
coffee

with
sugar,
milk

and
liquor 



(





).



(










).


(





) //
leverage
named‐args
as
punctuation check
that:
margarita

tastes
good //
closure
parameters
for
new
control
structures given
{}

when
{}

then
{} //
zero‐arg
methods
require
parens select
all

unique()
from
names //
possible
with
an
odd
number
of
terms take
3

cookies 36
  • 79. Command chains expressions //
methods
with
multiple
arguments
(commas) take
coffee

with
sugar,
milk

and
liquor 



(





).



(










).


(





) //
leverage
named‐args
as
punctuation check
that:
margarita

tastes
good 




(














).





(



) //
closure
parameters
for
new
control
structures given
{}

when
{}

then
{} //
zero‐arg
methods
require
parens select
all

unique()
from
names //
possible
with
an
odd
number
of
terms take
3

cookies 36
  • 80. Command chains expressions //
methods
with
multiple
arguments
(commas) take
coffee

with
sugar,
milk

and
liquor 



(





).



(










).


(





) //
leverage
named‐args
as
punctuation check
that:
margarita

tastes
good 




(














).





(



) //
closure
parameters
for
new
control
structures given
{}

when
{}

then
{} 




(

).



(

).



(

) //
zero‐arg
methods
require
parens select
all

unique()
from
names //
possible
with
an
odd
number
of
terms take
3

cookies 36
  • 81. Command chains expressions //
methods
with
multiple
arguments
(commas) take
coffee

with
sugar,
milk

and
liquor 



(





).



(










).


(





) //
leverage
named‐args
as
punctuation check
that:
margarita

tastes
good 




(














).





(



) //
closure
parameters
for
new
control
structures given
{}

when
{}

then
{} 




(

).



(

).



(

) //
zero‐arg
methods
require
parens select
all

unique()
from
names 





(


).







.



(




) //
possible
with
an
odd
number
of
terms take
3

cookies 36
  • 82. Command chains expressions //
methods
with
multiple
arguments
(commas) take
coffee

with
sugar,
milk

and
liquor 



(





).



(










).


(





) //
leverage
named‐args
as
punctuation check
that:
margarita

tastes
good 




(














).





(



) //
closure
parameters
for
new
control
structures given
{}

when
{}

then
{} 




(

).



(

).



(

) //
zero‐arg
methods
require
parens select
all

unique()
from
names 





(


).







.



(




) //
possible
with
an
odd
number
of
terms take
3

cookies 



(
). 36
  • 83. BigDecimal by default • Main reason why financial institutions often decide to use Groovy for their business rules! – Although these days rounding issues are overrated! 37
  • 84. BigDecimal by default • Main reason why financial institutions often decide to use Groovy for their business rules! – Although these days rounding issues are overrated! 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; 37
  • 85. BigDecimal by default • Main reason why financial institutions often decide to use Groovy for their business rules! – Although these days rounding issues are overrated! 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; (d
*
(b
‐
c)
+
e
*
(c
‐
a))
/
(a
‐
b) 37
  • 86. Custom control structures w/ closures • When closures are last, they can be put “out” of the parentheses surrounding parameter unless
(account.balance
>
100.euros,
{
 



account.debit
100.euros
 }) 38
  • 87. Custom control structures w/ closures • When closures are last, they can be put “out” of the parentheses surrounding parameter unless
(account.balance
>
100.euros,
{
 



account.debit
100.euros
 }) //
calling
the
following
method: def
unless(boolean
b,
Closure
c) 38
  • 88. Custom control structures w/ closures • When closures are last, they can be put “out” of the parentheses surrounding parameter unless
(account.balance
>
100.euros)
{ 



account.debit
100.euros } //
calling
the
following
method: def
unless(boolean
b,
Closure
c) 38
  • 89. Operator overloading a
+
b

//
a.plus(b) • Currency amounts a
‐
b

//
a.minus(b) a
*
b

//
a.multiply(b) – 15.euros + 10.dollars a
/
b

//
a.divide(b) a
%
b

//
a.modulo(b) • Distance handling a
**
b
//
a.power(b) – 10.kilometers - 10.meters a
|
b

//
a.or(b) a
&
b

//
a.and(b) • Workflow, concurrency a
^
b

//
a.xor(b) a[b]


//
a.getAt(b) – taskA | taskB & taskC a
<<
b
//
a.leftShift(b) a
>>
b
//
a.rightShift(b) • Credit an account +a




//
a.unaryPlus() – account << 10.dollars ‐a




//
a.unaryMinus() account += 10.dollars ~a




//
a.bitwiseNegate() account.credit 10.dollars 39
  • 92. 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 42
  • 93. Hooks • GroovyObject(Support) – invokeMethod(), get/setProperty(), get/setMetaClass() – methodMissing(), propertyMissing() • Custom MetaClasses add – invokeConstructor(), invokeMissingMethod(), invokeStaticMethod() – get/setAttribute() – respondsTo(), hasProperty() • Categories – thread-scope & lexical-scope addition of methods 43
  • 94. Hooks: 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 44
  • 95. Adding properties to numbers • Three possible approaches – create a Category • a category is a kind of decorator for default MCs – create a custom MetaClass • a full-blown MC class to implement and to set on the POGO instance – use ExpandoMetaClass • friendlier DSL approach but with a catch 45
  • 96. 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 46
  • 97. With an ExpandoMetaClass Number.metaClass.getMeters
=
{‐>
 



new
Distance(delegate,
Unit.METERS)
 } 
 100.meters • But the catch is it’s really a global change, so beware EMC enhancements collisions 47
  • 99. A builder for HR softskills
{ 



ideas
{ 







capture
2 







formulate
3
 



} 



... } knowhow
{ 



languages
{ 







java
4 







groovy
5 



} 



... }

 49
  • 100. A builder for HR softskills
{ 



ideas
{ 







capture
2 







formulate
3
 



} 



... } knowhow
{ 



languages
{ 







java
4 







groovy
5 



} 



... }

 49
  • 101. A builder for HR 









( softskills
{ 








( 



ideas
{ 














(
) 







capture
2 
















(
) 







formulate
3
 




) 



} 



... 
) } 






( knowhow
{ 












( 



languages
{ 











(
) 







java
4 













(
) 







groovy
5 




) 



} 



 



... 
) }

 49
  • 102. Level #3: Hooking into the compiler
  • 103. Compile-time metaprogramming • Groovy 1.6 introduced AST Transformations • Compile-time == No runtime performance penalty! Transformation 51
  • 104. Compile-time metaprogramming • With metaprogramming, Groovy’s able to modify the behaviour of programs... at runtime • Groovy 1.6 introduced AST Transformations – AST: Abstract Syntax Tree – Ability to change what’s being compiled at compile-time! • No runtime impact! • Lets you change the semantics of your programs! • Nice way of implementing patterns and removing boiler-plate technical code • Better interoperability with Java – Jave code can call the methods / fields / etc injected in Groovy classes 52
  • 105. AST Transformations • Two kinds of transformations – Global transformations • applicable to all compilation units – Local transformations • applicable to marked program elements • using specific marker annotations 53
  • 106. AST Transformations • Several (local) transformations available – @ToString – @Log – @Delegate – @Immutable – and many more 54
  • 107. @Immutable • To properly implement immutable classes – No mutators (state musn’t change) – Private final fields – Defensive copying of mutable components – Proper equals() / hashCode() / toString() for comparisons, or for keys in maps, etc. @Immutable
class
Coordinates
{ 



Double
lat,
lng } def
c1
=
new
Coordinates(lat:
48.8,
lng:
2.5) def
c2
=
new
Coordinates(48.8,
2.5) assert
c1
==
c2 55
  • 108. Global transformations • Implement ASTTransformation • Annotate the transfo specifying a compilation phase @GroovyASTTransformation(phase
=
CompilePhase.CONVERSION) class
MyTransformation
implements
ASTTransformation
{ 



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 56
  • 109. 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(["com.foo.MyTransformation"]) @interface
CoolTransform
{...} 57
  • 110. Example: the Spock framework • Changing the semantics of the original code • But keeping a valid Groovy syntax @Speck class
HelloSpock
{ 



def
"can
you
figure
out
what
I'm
up
to?"()
{ 







expect: 







name.size()
==
size 







where: 







name




|
size 







"Kirk"


|

4 







"Spock"

|

5 







"Scotty"
|

6 



} } • Check out http://www.spockframework.org 58
  • 112. 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 60
  • 113. Java 6’s javax.script.* API • Groovy provides an implementation of the javax.script.* API ScriptEngineManager
mgr
=
new
ScriptEngineManager(); ScriptEngine
engine
=
mgr.getEngineByName("Groovy"); String
result
=
(String)engine.eval("2+3"); 61
  • 114. 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/bizRules.groovy" customizer-ref="rulesCustomizerMetaClass" /> • More to come in the next version of Spring 62
  • 115. Groovy’s own mechanisms • GroovyShell, Eval, GroovyScriptEngine – for more complex scripts and DSLs • GroovyClassLoader or CompilationUnit – the most powerful mechanisms 63
  • 116. GroovyShell • A Binding provides a context of execution – can implement lazy evaluation if needed • A base script class can be specified – providing «global» methods and fields def
binding
=
new
Binding() binding.mass
=
22.3 binding.velocity
=
10.6 def
shell
=
new
GroovyShell(binding) shell.evaluate("mass
*
velocity
**
2
/
2") 64
  • 117. Imports customizer • Inject imports in your scripts – so that users don’t have to add imports manually def
configuration
=
new
CompilerConfiguration() 
 def
custo
=
new
ImportCustomizer() custo.addStaticStar(Math.name) configuration.addCompilationCustomizers(custo)
 
 def
result
=
new
GroovyShell(configuration) 



.evaluate("
cos
PI/3
") 65
  • 118. Applying an AST transformation • Apply local AST transformations transparently def
configuration
=
new
CompilerConfiguration() configuration.addCompilationCustomizers( 



new
ASTTransformationCustomizer(Log))
 
 new
GroovyShell(configuration).evaluate(""" 



class
Car
{







 







Car()
{











 











log.info
'Car
constructed'







 







}



 



}




 



log.info
'Constructing
a
car'



 



def
c
=
new
Car() """) 66
  • 119. 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 67
  • 120. Domain-Specific Language Descriptors • DSLs are nice, but what about support in my IDE? • DSLD to the rescue – Domain-Specific Language Descriptors – for Eclipse STS (but GDLS concent available in IntelliJ IDEA too) • Idea: a DSL for describing DSLs, in order to provide – code-completion – code navigation – documentation hovers 68
  • 124. A few considerations Growing a language Security Testability
  • 125. Start small, with key concepts Beware over-engineering!
  • 126. Grow your language progressively
  • 127. Get your hands dirty Play with the end-users
  • 128. Let your DSL fly, it’s not yours, it’s theirs!
  • 129. Tight feedback loop Iterative process
  • 130. Stay humble, You can’t get it right the 1st time. Don’t design alone at your desk Involve the end users from the start
  • 131. Playing it safe in a sandbox
  • 132. Example use case • Biggest European travel services company • Their customers – travel agencies, airlines, booking websites... • Customers want to customize the user experience – use personalized forms and templates – configure and tweak the underlying reservation features • The company runs customers’ Groovy code on their own platform and mutualised servers! – How to secure that? 78
  • 133. Sandboxing approaches • Groovy supports the usual Java Security Managers – avoid System.exit(0) • Use metaprogramming tricks to prevent calling or instanciating certain classes – think overriding constructors to throw exceptions • Groovy 1.8 to the rescue – compiler customizers • SecureASTCustomizer • ASTTransformCustomizer 79
  • 134. Secure AST customizer Idea: Implement an «arithmetic shell» Being able control what a user script is allowed to do: only arithmetic expressions 80
  • 135. Secure AST customizer Idea: Implement an «arithmetic shell» Being able control what a user script is allowed to do: only arithmetic expressions • Let’s setup our environment – some imports – an import customizer to import java.lang.Math.* – prepare a secure AST customizer 80
  • 136. Secure AST customizer Idea: Implement an «arithmetic shell» Being able control what a user script is allowed to do: only arithmetic expressions • Let’s setup our environment – some imports – an import customizer to import java.lang.Math.* – prepare a secure AST customizer import
org.codehaus.groovy.control.customizers.* import
org.codehaus.groovy.control.* import
static
org.codehaus.groovy.syntax.Types.* 
 def
imports
=
new
ImportCustomizer().addStaticStars('java.lang.Math') def
secure
=
new
SecureASTCustomizer() 80
  • 137. Secure AST customizer ... secure.with
{ //
disallow
closure
creation closuresAllowed
=
false
 //
disallow
method
definitions methodDefinitionAllowed
=
false
 
 //
empty
white
list
=>
forbid
imports importsWhitelist
=
[]
 staticImportsWhitelist
=
[] //
only
allow
the
java.lang.Math.*
static
import staticStarImportsWhitelist
=
['java.lang.Math' ... 81
  • 138. Secure AST customizer ... //
language
tokens
allowed tokensWhitelist
=
[ PLUS,
MINUS,
MULTIPLY,
DIVIDE,
MOD,
POWER,
PLUS_PLUS,
 MINUS_MINUS,
COMPARE_EQUAL,
COMPARE_NOT_EQUAL,
 COMPARE_LESS_THAN,
COMPARE_LESS_THAN_EQUAL,
 COMPARE_GREATER_THAN,
COMPARE_GREATER_THAN_EQUAL ] 
 //
types
allowed
to
be
used
(including
primitive
types) constantTypesClassesWhiteList
=
[ Integer,
Float,
Long,
Double,
BigDecimal,
 Integer.TYPE,
Long.TYPE,
Float.TYPE,
Double.TYPE ] 
 //
classes
who
are
allowed
to
be
receivers
of
method
calls receiversClassesWhiteList
=
[
 Math,
Integer,
Float,
Double,
Long,
BigDecimal
] } ... 82
  • 139. Secure AST customizer • Ready to evaluate our arithmetic expressions! ... def
config
=
new
CompilerConfiguration() config.addCompilationCustomizers(imports,
secure) def
shell
=
new
GroovyShell(config) 
 shell.evaluate
'cos(PI/3)' • But the following would have failed: shell.evaluate
'System.exit(0)' 83
  • 140. Test, test, test! • Don’t just test for nominal cases – Explicitely test for errors! • Ensure end-users get meaninful error messages 84
  • 142. Summary • Groovy DSLs in the wild manage millions, and even billions of Euros (one of my customers) – so I guess we can say Groovy can be trusted :-) • Groovy 1.8 adds some nice capabilities for writing nicer plain-English-like business rules • Tooling is improving greatly with DSL descriptors – offering nice IDE integration for authoring business rules 86
  • 143. Thank you! e aforg pment ume L Develo Guilla Groovy om He ad of e@ gmail.c glaforg rge Email: @glafo : Twitter 87

Notas del editor

  1. \n
  2. \n
  3. \n
  4. \n
  5. \n
  6. \n
  7. \n
  8. \n
  9. \n
  10. \n
  11. \n
  12. \n
  13. \n
  14. \n
  15. \n
  16. \n
  17. \n
  18. \n
  19. \n
  20. \n
  21. \n
  22. \n
  23. \n
  24. \n
  25. \n
  26. \n
  27. \n
  28. \n
  29. \n
  30. \n
  31. \n
  32. \n
  33. \n
  34. \n
  35. \n
  36. \n
  37. \n
  38. \n
  39. \n
  40. \n
  41. \n
  42. \n
  43. \n
  44. \n
  45. \n
  46. \n
  47. \n
  48. \n
  49. \n
  50. \n
  51. \n
  52. \n
  53. \n
  54. \n
  55. \n
  56. \n
  57. \n
  58. \n
  59. \n
  60. \n
  61. \n
  62. \n
  63. \n
  64. \n
  65. \n
  66. \n
  67. \n
  68. \n
  69. \n
  70. \n
  71. \n
  72. \n
  73. \n
  74. \n
  75. \n
  76. \n
  77. \n
  78. \n
  79. \n
  80. \n
  81. \n
  82. \n
  83. \n
  84. \n
  85. \n
  86. \n
  87. \n
  88. \n
  89. \n
  90. \n
  91. \n
  92. \n
  93. \n
  94. \n
  95. \n
  96. \n
  97. \n
  98. \n
  99. \n
  100. \n
  101. \n
  102. \n
  103. \n
  104. \n
  105. \n
  106. \n
  107. \n
  108. \n
  109. \n
  110. \n
  111. \n
  112. \n
  113. \n
  114. \n
  115. \n
  116. \n
  117. \n
  118. \n
  119. \n
  120. \n
  121. \n
  122. \n
  123. \n
  124. \n
  125. \n
  126. \n
  127. \n
  128. \n
  129. \n
  130. \n
  131. \n
  132. \n
  133. \n
  134. \n
  135. \n
  136. \n
  137. \n
  138. \n
  139. \n
  140. \n
  141. \n
  142. \n
  143. \n
  144. \n
  145. \n