building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls...

112
NEAL FORD thoughtworker / meme wrangler ThoughtWorks 14 Wall St, Suite 2019, New York, NY 10005 [email protected] www.nealford.com www.thoughtworks.com memeagora.blogspot.com ThoughtWorks building dsl’s in static & dynamic languages

Upload: others

Post on 29-May-2020

15 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t

NEAL FORD thoughtworker / meme wrangler

ThoughtWorks14 Wall St, Suite 2019, New York, NY 10005 nford@thoughtworks.comwww.nealford.comwww.thoughtworks.commemeagora.blogspot.com

ThoughtWorks

building dsl’s in static & dynamic languages

Page 2: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t
Page 3: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t

groovyjava

external dslsbest practices

ruby

building dsls in:types of dslsmotivation

what i cover

Page 4: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t

why won’t everyone shut up already about ruby on rails?

why is there so much xml mixed in with my java code?

why do things like aspects exist?

is there an evolutionary step beyond object-oriented programming?

burning questions

Page 5: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t
Page 6: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t
Page 7: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t

Superclass

Subclass Subclass

Subclass

Superclass

Subclass Subclass

Subclass

2.days.from.today

objects, aspects, generics become the building blocks for dsls

Page 8: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t

declarative vs imperative code

Page 9: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t

“Route 66, swinging, easy on the chorus, extra solo at the coda, and bump at the end”

“Iced Decaf Triple Grande Vanilla Skim with whip latte.”

“Scattered, smothered, covered”

“OMFG D00d Bob is t3h UBER 1337 R0XX0RZ LOL”

why dsls?

waffle house hash brown language: scattered, smothered, covered, chunked, topped, diced, peppered, & capped

Page 10: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t

Every non-trivial human behavior has a domain specific language.

Page 11: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t

how non-developers talk about work

why developers tend to stay within domains

all businesses have their own dsl

including your job

Page 12: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t

a limited form of computer language designed for a specific class of problems

coined by martin fowler

domain specific language

general style of development which operates about the idea of building software around a set of domain specific languages

language oriented programming

nomenclature

Page 13: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t

terminology specific to a particular logical domain (related to ubiquitous language)

domain specific notation

a limited form of computer language designed for a specific class of problems

domain specific language

definitions

Page 14: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t

api: explicit context

Page 15: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t

dsl: implicit context

Venti half-caf, non-fat, extra hot, no foam, no whip latte

once context is established, repeating it over and over is just noise

Page 16: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t

“text without context is pretext.”

jesse jackson

Page 17: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t

aka “embedded”

sit atop a base language

why dynamic languages tend to make better bases

types: internal

Page 18: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t

let your imagination run wild!

build your own language

must be able to lex and parse your language

types: external

Page 19: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t

a word aboutpatterns

Page 20: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t

Internal

DSLs

Page 21: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t

treat lines of code as sentences

example: jmock expectation

fluent interface

Page 22: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t
Page 23: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t

car api

Page 24: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t

car fluent interface

as simple as writing set methods that return this

Page 25: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t

method chainingMake modifier methods return the host object so that multiple modifiers can be invoked in a single

expression.

Page 26: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t

writing a fluent interface around log4j properties file creation

example: logging

Page 27: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t

the target

Page 28: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t

dsl syntax

Page 29: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t

alternate syntax

Page 30: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t
Page 31: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t

expression builder

a layer that provides a fluent interface over a regular api

Page 32: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t

wrap existing api’s in fluent interfaces to improve readability

example: wrapping ibatis

wrapping api’s

Page 33: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t

ibatis xml configuration

Page 34: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t

sqlmap

Page 35: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t

ThoughtWorks

Page 36: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t
Page 37: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t

...but the other guys do the same thing

competition is brutal!

incentives to encourage repeat customers...

easy to define & change

flexible business rules

bakery life

Page 38: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t

establishing profiles

Page 39: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t

discounts

Page 40: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t

customer profile

fluentinterface

pojostuff

Page 41: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t

profile in action

Page 42: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t

discount

Page 43: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t

discount implementation

Page 44: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t

getDiscount()

Page 45: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t

rulelist

Page 46: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t

demo, part 1

Page 47: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t

demo, part 2

Page 48: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t

chained result

Page 49: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t

rulelist

Page 50: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t

result

Page 51: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t

when does the call “finish”?

make sure things happen at the right time?

the finishing problem

Page 52: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t

chained method calls

nested method calls

method invocation

Page 53: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t
Page 54: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t
Page 55: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t

build fluent interfaces with a mixture of chained and nested method invocations

mitigating the finishing problem

Page 56: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t

use method chaining

for stateless

object construction

Page 57: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t

use nested methods

to control completion

Page 58: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t

in the nested add() methodon dependent method calls

validation

building objects with chained methods can create “bad citizens”

good citizenship?

imposes order semantics

allows invalid state

Page 59: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t

testing

Page 60: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t

context & noise

Page 61: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t

providing context

.

.

.

.

Page 62: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t

what kind of rocket science?

Page 63: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t
Page 64: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t

dynamic typing

closures

open classes

looser syntax rules than java

dynamic building blocks

Page 65: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t

the goal

Page 66: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t

expando meta-class

Page 67: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t

expando property

Page 68: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t

open classes for recipes

Page 69: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t

recipe redux

Page 70: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t

of

why grams & not

lbs?

Page 71: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t

of redux

Page 72: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t

who returns what?

Integer

BigDecimal

Ingredient

Ingredient

Page 73: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t

type transmogrification

transform types as needed as part of a fluent interface call

Page 74: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t

ruby

Page 75: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t

Recipes

Page 76: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t

target syntax

Page 77: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t

open classesopen class

aliasmethod

Page 78: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t

killing noise characters

Page 79: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t

const_missing

Page 80: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t

building a simple language for recipes allows you to build other stuff underneath

for example, a nutrition profile

expression builder

Page 81: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t

recipe nutrition profile

Page 82: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t

nutrition profile

Page 83: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t

testing profile

Page 84: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t

context

Page 85: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t

add context

evaluates ruby code by switching self to the instance of the object calling instance_eval

Page 86: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t

context

Page 87: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t

switching contexts

Page 88: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t

dsl’s allow you to specify intent without coupling in implementation

declarative code reveals semantic intent

imperative code reveals implementation

declarative advantages

Page 89: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t
Page 90: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t
Page 91: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t
Page 92: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t
Page 93: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t
Page 94: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t
Page 95: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t

external dsl

Page 96: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t

create your own parser & lexer

lex/yacc

roll your own language

www.antlr.org

Page 97: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t

antlrworks

Page 98: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t

antlrworks

Page 99: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t

software factories (microsoft)

a tool that supports language oriented programming

intentional software (charles simonyi)

mps (jetbrains)

language workbenches

Page 100: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t

class Foo { private int id;. . .. . .

}

Editable Representation

Storage RepresentationExecutable

Representation

Parse

Compile

compilation since cs-101

Page 101: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t
Page 102: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t

first java ide to edit the abstract syntax directly

enables refactoring

“post- ide’s”

Page 103: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t

workbenchesclass Foo { private int id;. . .. . .

}

Executable

Representation

Workbench

Versioning Storage

Editable Representation

Storage Representation

TabTabTab

Document Window

Label Menu

Text Field

Text Field

Text Field

Text Field

Text Field

Text Field

Label Label•

Label Text Field

Projections

Page 104: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t

jetbrainsmps

Page 105: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t

best practices

Page 106: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t

the rake napkin

what is the ideal dsl syntax?

build towards it

envision the perfect result

Page 107: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t

test,

test,

test

Page 108: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t

...not creating more complicated languages

keep your dsl as cohesive as possible

create solutions by composing dsls...

jetbrain’s use of mps

narrow the problem domain

Page 109: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t

domainspecific languagesimproveabstractions

by eliminating

noise

Page 110: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t

a better way to solve some

problems...

...whose timeis coming

Page 111: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t

ThoughtWorks

NEAL FORD thoughtworker / meme wrangler

ThoughtWorks14 Wall St, Suite 2019, New York, NY 10005 nford@thoughtworks.comwww.nealford.comwww.thoughtworks.commemeagora.blogspot.com

This work is licensed under the Creative Commons Attribution-Noncommercial-Share Alike 2.5 License.

http://creativecommons.org/licenses/by-nc-sa/2.5/

questions?

please fill out the session evaluationsslides & samples available at nealford.com

Page 112: building dsl’s in static & dynamic languages...dynamic languages. groovy java external dsls best practices ruby building dsls in: types of dsls motivation what i cover. why won’t

resourceshttp://martinfowler.com/bliki/DomainSpecificLanguage.html

http://www.theserverside.com/news/thread.tss?thread_id=46674

http://martinfowler.com/articles/languageWorkbench.html

http://homepages.cwi.nl/~arie/papers/dslbib/

upcoming book on building internal dsl’s in rubyzak tamsen & dan manges