dsl's with groovy

32
DSL’s With Groovy Paul Bowler Senior Consultant, OpenCredo

Upload: paulbowler

Post on 07-Nov-2014

860 views

Category:

Technology


1 download

DESCRIPTION

DSL's with Groovy presentation (OpenCredo 2011)

TRANSCRIPT

Page 1: DSL's with Groovy

DSL’s With GroovyPaul Bowler

Senior Consultant, OpenCredo

Page 2: DSL's with Groovy

“Domain-Specific”Languages?

Page 3: DSL's with Groovy

Domain?

–nouna field of action, thought,

influence, etc.

Page 4: DSL's with Groovy

Domains, domains, domains...!

Page 5: DSL's with Groovy

Domain Language?

• Narrow, specialised focus

• Contains syntax and grammar to interact with the domain

• Few, if any, control structures (not ‘Turing Complete’)

• Communicates instructions and configuration

Page 6: DSL's with Groovy

So, like these?

Page 7: DSL's with Groovy

...or these?

Page 8: DSL's with Groovy

yes, ... and no!

Page 9: DSL's with Groovy

What then?

“...most DSL’s are merely a thin facade over a library or framework.”

Martin Fowler, ThoughtWorks

OS

PlatformFramework

DSL

Page 10: DSL's with Groovy

What’s wrong with code?

DeveloperDomain Expert

Cognitive Gap

Page 11: DSL's with Groovy

How do DSL’s help?

• Expressive - Well-designed abstractions

• Simple - Reduce cognitive overhead

• Focussed - Deliver clarity of intent

• Inclusive - Empower the domain expert

Page 12: DSL's with Groovy

What’s wrong with code?

DeveloperDomain Expert

Cognitive Gap

Page 13: DSL's with Groovy

Close the Cognitive Gap

DeveloperDomain Expert

Page 14: DSL's with Groovy

How?

• External DSL - Separate from the ‘main’ languagee.g. SQL, XML, JSON

• Internal DSL - Valid code in the ‘main’ language

• Language Workbench - Specialised ‘IDE’ as editing environment with ‘human-centric’ graphical representation

Page 15: DSL's with Groovy

Why Groovy?

Less noise More sugar

Page 16: DSL's with Groovy

How?

• Builders

• Categories

• Meta-Object Protocol (MOP)

• Abstract Syntax Tree (AST) Transformations

Page 17: DSL's with Groovy

Builders

• Great for hierarchical structures, such as trees, collections of collections, etc.

• Built in support for XML, HTML, Swing, etc

• Roll your own by extending ‘BuilderSupport’ class

Page 18: DSL's with Groovy

Using buildersdef writer = new StringWriter()def xml = new MarkupBuilder(writer)

xml.team(nickname:'DreamTeam') { member(name:'John Smith', age:'32') { nationality('British') job(type:'full-time', 'Java Developer') } member(name:'Sue Perb', age:'25') { nationality('Australian') job(type:'full-time', 'Tester') } member(name:'Fred Bloggs', age:'30') { nationality('Irish') job(type:'contract', 'Build Guru') }}

Page 19: DSL's with Groovy

Builder Methodsclass MyBuilder extends BuilderSupport {

public void setParent(Object parent, Object child) { }

public createNode(Object name) { } public createNode(Object name, Object value) { } public createNode(Object name, Map attributes) { } public createNode(Object name, Map attributes, Object value) { }}

Page 20: DSL's with Groovy

Categories• Allow syntax extensions, e.g:

def nextWeek = today + 7.days

• Any public static method is a candidate to be a category method

• The type of the first parameter is the target type that may have the new methods ‘injected’

• No need to extend a particular class or implement an interface

• Gotcha! Methods added to classes for limited time using ThreadLocal. Also requires wrapping with use() method.

Page 21: DSL's with Groovy

Category Exampleimport org.apache.commons.lang.StringUtils

class StringCategory { static capitalize( String self ){ StringUtils.capitalize(self) }

static normalize( String self ){ self.split("_").collect { word -> word.toLowerCase().capitalize() }.join("") }}

use( StringCategory ) { assert "Groovy" == "groovy".capitalize() assert "CamelCase" == "CAMEL_CASE".normalize()} 

Page 22: DSL's with Groovy

MOP

• Every object inherits from groovy.lang.GroovyObject which contains MetaClass

• ExpandoMetaClass extensions and hooks:invokeMethod(),getProperty(), methodMissing()and propertyMissing()

• Used extensively in Grails - Dynamic Finders (e.g. book.findAllByAuthor)

Page 23: DSL's with Groovy

• Less code and cleaner implementation than categories

• Uses closures and delegates

• Can add or update/overload existing methods

• No need for Use()

• Can overload static methods

• Has longer lifespan than categories

• Inheritance not enabled by default for performance reasons

MOP vs Categories

Page 24: DSL's with Groovy

MOP Example

import org.apache.commons.lang.StringUtils

String.metaClass.capitalize = { StringUtils.capitalize(delegate)}

String.metaClass.normalize = { delegate.split("_").collect { word -> word.toLowerCase().capitalize() }.join("")}

assert "Groovy" == "groovy".capitalize()assert "CamelCase" == "CAMEL_CASE".normalize()

Page 25: DSL's with Groovy

Abstract Syntax Tree

• Compile-time Meta Programming allowing developers to hook into the compilation process

• No runtime performance penalty

• Global transformations using service locator file

• Local transformations using annotations

• Built using... builders!

• Transformations must be performed in one of the nine defined compiler phases

Page 26: DSL's with Groovy

Compilation Phases1. Initialization: source files are opened and environment

configured2. Parsing: the grammar is used to to produce tree of tokens

representing the source code3. Conversion: An abstract syntax tree (AST) is created from

token trees.4. Semantic Analysis: Performs consistency and validity checks that

the grammar can't check for, and resolves classes.5. Canonicalization: Complete building the AST6. Instruction Selection: instruction set is chosen, for example java5

or pre java57. Class Generation: creates the binary output in memory8. Output: write the binary output to the file system9. Finalisation: Perform any last cleanup

Page 28: DSL's with Groovy

It all looks so complicated!

Page 29: DSL's with Groovy

Case Study - Grint‘Groovier Integration!’

Page 30: DSL's with Groovy

Grint

• Groovy DSL for Integration Patterns

• Deployable as a Grails plugin

• Baked for our DSL course

• Already in production...

Page 31: DSL's with Groovy

A Groovier Approach to Integration

• Events cause messages

• EDA 

• See Event-driven IO to get an idea

• Node.js

• Akka

• Even Spring Integration...

Page 32: DSL's with Groovy

Thank you