Ce diaporama a bien été signalé.
Nous utilisons votre profil LinkedIn et vos données d’activité pour vous proposer des publicités personnalisées et pertinentes. Vous pouvez changer vos préférences de publicités à tout moment.
SDTÊDQOHG 25* Unless otherwise indicated,  these slides are © 2015 Gradle,  Inc.  and licensed under a Creative Commons At...
Who aml

speaker {
name 'Cédric Champeau'
company 'Gradle Inc'
oss 'Apache Groovy committer', 
successes (['Static type ch...
Domain Specific Languages

o Focused

o Readable

o Practical

o (usually) embeddable

o Examples:  SQL,  HTML,  XSLT,  An...
Disclaimer

This is an opiniated talk about how a DSL designed with Apache
Groovy should look like. 

 

l sprlngone   Unl...
Apache Groovy for DSLs

o Concise,  clean syntax
o Supports scrlpting
o Supports metaprogramming

o Embeddable
o Mature to...
Some old Groovy DSLs

 

/4 - -
Kspnngone  Unl otherwise ll"l(ll. (`dl<-'[l,  these slides are "i 2015 (šradle,  Jnr,  and...
Groovy SQL

sql. execute "insert into PROJECT (id,  name,  url) values ($i| ap. id,  $nap. name,  snap

< >

 

/ < . 
Ksp...
i-i?  gia-racial: 
esi-gelit , Itali-fl

 

SDTÊDQOHG 25* Unless otherwise indicated,  these slides are © 2015 Gradle,  In...
Spring Boot

@EnableAutoConfiguration

ęcomponentscan ( "foo .  ba r" )

class Application {
static void main(String[] arg...
iinlsiliëilall h! ) 4* l
"ii-. ITLIi-v"

zini-slktíiiall 'ml : l
, trant-uu "namm"

 

SDTÊDQOHG 25* Unless otherwise indi...
Some thoughts

o removing semicolons is not designing a DSL
o removing parenthesís is not designing a DSL
o user experienc...
Modern Apache Groovy DSLs

Złlllb-Ijųiijła,  Iii-i,  .milllt-iaųsaiiiųuųiàtaųultųæizlntw HllųullilgbiåïlUli)lllll): učllul...
Spock

Setup: 
def map =  new HashMap()

when: 
map. put(null,  "elem")

then: 
notThrown(NullPointerException)

 

/ “ . ...
inni-geï:  rlęlnàioniññlniøil líl l
liauàiiilłaiiiia s:  ',  ,_ -' m ? ILÃVIS
. l -Jielaiilsïisvfijíi

 

SDTÊDQOHG 25* Un...
Gradle new model

model {
components {
shared(CustomLibrary) {
javaversions 6, 7
}

main(JvmLib ra rySpec) {
targetPlatfor...
Nail-midt '{

praniojłęur "ilçlClc- 'lt-irfloilr"

i

šlåililr"`wllhllllïlnl 'l
øręni-: ł-. ur "tláúkc- -Jï niinl-it(ęiii....
Jenkins Job DSL

job {
using 'TMPL-test'
name 'PROJ - integ- tests'

scm {

git(gitUrl)
}
triggers {

cron('15 1.13 * * *'...
l op,  ,ųmrlteÉninei

iiinioítaliíriygisu - 'l
Ljuiíųėïi:  gr , øialramla

: Il l
, oi-, usionwuamclii l _ei r
Li , Itulłï...
SDTÊDQOHG 25* Unless otherwise indicated,  these slides are © 2015 Gradle,  Inc.  and licensed under a Creative Commons At...
Thetoob

o Closures with support annotations (@DelegatesTo,  .. .)
o Compilation customizers

o AST transformations

o Typ...
Closures

o Still at the core of most DSLs
o delegate is very important: 

['Paris',  Washington'.  'Berlin']. collect { i...
Setting the delegate

class HelperExtension {
public static <T, U> List<U> myCollect(List<T> items,  Closure<U> action) {
...
Convert it to an extension module
o META-INF

I services
o org. codehaus. groovy.  runt-ime.  ExtensionModule

moduleName=...
Convert it to an extension module

o Consume it as if it was a regular Groovy method

['Paris',  'washington',  'Berlin']....
Declare the delegate type

o Best IDE support
o Only way to have static type checking

public static <T, U> List<U> myColl...
Removing Ceremony

o Is your DSL self-contained? 

o If so
I Try to remove explicit imports
I Avoid usage of the new keywo...
iniuiøílkaliiàw
a. h'l'u_lf'l"

: gi max-twin)
maai-tuie

 

SDTÊDQOHG 25* Unless otherwise indicated,  these slides are ©...
SAM What? 

This is cool: 

handle {
println message
}

SAM type coercion works for both interfaces and abstract classes. ...
ihm:  'itųibàtar-uųr : i

t

 

SDTÊDQOHG 25* Unless otherwise indicated,  these slides are © 2015 Gradle,  Inc.  and lice...
Compilation customizers

def importcustomizer =  new ImportCustomizer()
importcustomizer. addstaticstars 'com. acme. webSe...
Compilation customizers

o Impo rtCustomi ze r:  automatically add imports to your scripts

o ASTT ransfo rmati onCustomi ...
Avoiding imperative style

class webserver {

static void serve(@DelegatesTo(ServerSpec) Closure cl) {

def spec =  new Se...
Avoiding imperative style

class ServerSpec {

int port

void port(int port) { this. port =  port }

void get(String path,...
Avoiding imperative style

o Use the ServerSpec style above
o The closure should configure the model
o Executlon can be de...
?mini i{
oïlasimioítaniríiiai:  il

1.3. .  
_mi naai "f-nir" 'tïlfoiarųlrjii 'iimjif

     
    

icW/ “šnçiexczifxiirrit...
,llalgialniøitęlniųmpięløtåitli. kitaar _ouųïęiøiiizbiizrüiųi

, Ir-_igięiuioitęniųvnpiaidå _hit-ar `l.1'o| n=. ii1i-G'ií:...
immutable builders
o A dependency spec is by default immutable

public interface Dependencyspec {

@Nullable
St ring getP ...
lmmutable builders

o The builder specializes the spec interface

public interface DependencySpecBuilder extends Dependenc...
immutable builders

o Concrete implementation provides the builder

public class Defaultnependencyspec implements Dependen...
immutable builders

o And the container stores a list of builders

public class DefaultDependencyspeccontainer implements ...
SDTÊDQOHG 25* Unless otherwise indicated,  these slides are © 2015 Gradle,  Inc.  and licensed under a Creative Commons At...
Goals

o Provide early feedback to the user
o Type safety
o Help the compiler understand your DSL

 

/ ' .  y
Kspnngone  ...
Type checking extensions API

o Event-based API
o React to events such as undefined Variable or method not found
o Develop...
MarkupTemplateEngine example

o Given the following template

pages. each { page -> _
p("Page title:  $page. title")
} Dtp...
Solution

o Declare the model types

modelTypes =  {
List<Page> pages
}

pages. each { page ->
p("Page title:  $page. titl...
MarkupTemplateEngine extension

o Recognizes unresolved method calls
I converts them into direct methodMissing calls
o Rec...
SDTÊDQOHG 25* Unless otherwise indicated,  these slides are © 2015 Gradle,  Inc.  and licensed under a Creative Commons At...
"i" . l -aęulivłiríililjnxøïłavz- { : Iiizr l

 

SDTÊDQOHG 25* Unless otherwise indicated,  these slides are © 2015 Gradl...
(Optional) @ClosureParams

public static <T> Co11ection<T> eachwithIndex(
Col1ection<T> self, 
Qclosu rePa rams (va1ue= F ...
What we learnt

o Leverage the lean syntax of Groovy
o Scoping improves readabilíty
o Use the delegate

o Use @DelegatesTo...
Questions

 

/ < . 
Ksprlngone á:  Unl 's nthenvise indicdied,  these slides are W* 201 S (šrddle,  lnc,  and licensed un...
We're hiring! 
httpJ/ gradIeorg/ gradIe-jobs/ 

    
 

I

Gradle

Bujld Happiness. 

 

/ ' .  y
Ksprlngone  Unless other...
Thank you! 

o slides and code:  httpsJ/ github. comlmelixls2gx-groovy-dsls

o Groovy documentation :  httpJ/ groovy-
Iang...
Prochain SlideShare
Chargement dans…5
×

Groovy DSLs in 2016

1 081 vues

Publié le

Recorded at SpringOne2GX
Speaker: Cédric Champeau
Groovy Advanced Track

Groovy has been a language of great interest to build internal domain specific languages (DSLs) for years now. But what will an "idiomatic Groovy DSL" in 2016? If you were to write a DSL today, what would you use? Runtime metaprogramming? Builders? Static compilation? Type checking extensions?

In this talk, we will illustrate what we think is a modern DSL written in Groovy, syntactically speaking, but also implementation wise. How you can improve the syntax of your DSL, its performance, or user experience.

Publié dans : Technologie
  • Soyez le premier à commenter

Groovy DSLs in 2016

  1. 1. SDTÊDQOHG 25* Unless otherwise indicated, these slides are © 2015 Gradle, Inc. and licensed under a Creative Commons Attribution-NonCommemial license http: l/creativecommons. org/ licenses/ by-nC/ ÊLO/
  2. 2. Who aml speaker { name 'Cédric Champeau' company 'Gradle Inc' oss 'Apache Groovy committer', successes (['Static type checker', 'Static compi1ation', 'Traits', 'Markup template engine'. 'DSLs']) failures Stream. of(bugs), twitter '@CedricChampeau'. github 'me1ix', extraDescription "'Groovy in Action 2 co-author Misc OSS contribs (Gradle plugins, deck2pdf, jlangdetect, .. .)"' } I Gradle lšuikl Happiness / . l Sprlngone Aãåï Unless otherwise imlirdleti, these slides are "J 2015 (šrddle, Jnr. and lIFPHSI-'Kl Lmder a Creative (ïnmrnons . Almwlnilmn-NonComn1erridl lirense
  3. 3. Domain Specific Languages o Focused o Readable o Practical o (usually) embeddable o Examples: SQL, HTML, XSLT, Ant, / ' . y Kspnngone ljnless uiherwise imlirdleti, these slides are "i 2015 (Jradle, lnr, and lirensed under a (Éreaiwe Commons AllribulmnrNonComn1err1dl lirense e" hLLp: //rrealiveronnnx; ns. orq/ l1renses/ by-nr/ /
  4. 4. Disclaimer This is an opiniated talk about how a DSL designed with Apache Groovy should look like. l sprlngone Unless otherwise indicated, these 'I'd s are w* 2015 Cradle, Inc. and licensed under a Creative Commons AttributionvNonCommeri: ial license ' httpzl/ creaLivecommonsorg/ licen nc/ /
  5. 5. Apache Groovy for DSLs o Concise, clean syntax o Supports scrlpting o Supports metaprogramming o Embeddable o Mature tooling: Eclipse, lntelliJ, Netbeans. .. / ' . y Kspnngone Unless otherwise indiraled, these slides are "i 2015 (Jradle, lnr, and licensed under a CFPdlJVP Commons : Hlrlbllll0n'N()H(7()I`l`ll`i1(-'H`ldl license T" http: //ri'eal. iveroiiiiiixins. orq/ lii-enses/ by-ni-/ /
  6. 6. Some old Groovy DSLs /4 - - Kspnngone Unl otherwise ll"l(ll. (`dl<-'[l, these slides are "i 2015 (šradle, Jnr, and licensed under a CFPdllVP (Iommons : lttribtilion-Numïonimerrial license 2 hi. /rreal. iveroiiiiiioiis. orq/ lii'ei / by-n ' 0/
  7. 7. Groovy SQL sql. execute "insert into PROJECT (id, name, url) values ($i| ap. id, $nap. name, snap < > / < . Kspnngone ' therwise indicated, S (šradle, lnc, and licensed iinder a CFPdllV (Iommons ttrilitttionrNunüoninierrial license
  8. 8. i-i? gia-racial: esi-gelit , Itali-fl SDTÊDQOHG 25* Unless otherwise indicated, these slides are © 2015 Gradle, Inc. and licensed under a Creative Commons Attribution-NonCommercial license http: l/creativecommons. org/ licenses/ by-nC/ ÊLO/
  9. 9. Spring Boot @EnableAutoConfiguration ęcomponentscan ( "foo . ba r" ) class Application { static void main(String[] args){ new SpringApplication(Application) . run (args) } } o Not strictly speaking a DSL o But can be converted into one / < - - Kspnngone Unless otherwise indicated, these slides a 2 hLLp: l/crealivecomiiioiis. orq/ lice
  10. 10. iinlsiliëilall h! ) 4* l "ii-. ITLIi-v" zini-slktíiiall 'ml : l , trant-uu "namm" SDTÊDQOHG 25* Unless otherwise indicated, these slides are © 2015 Gradle, Inc. and licensed under a Creative Commons Attribution-NonCommercial license http: l/creativecommons. org/ licenses/ by-nC/ ÊLO/
  11. 11. Some thoughts o removing semicolons is not designing a DSL o removing parenthesís is not designing a DSL o user experience is important o consistency is important o Try to be idiomatic / /' N~ (x Sprmgone Unless otherwise indicated, these slides are iii 2015 Gradle, lnc. and licensed iinder a (Ireatiixe Commons Allrlblłll()n'N()H(7()l"t`tl`t1E-'H`ldl license 2" http: //ciealiveconinixins. orq/ Iicenses/ bx>iic/ /
  12. 12. Modern Apache Groovy DSLs Złlllb-Ijųiijła, Iii-i, .milllt-iaųsaiiiųuųiàtaųultųæizlntw HllųullilgbiåïlUli)lllll): učllullllmulàlllíhlUllúäghe
  13. 13. Spock Setup: def map = new HashMap() when: map. put(null, "elem") then: notThrown(NullPointerException) / “ . Ksprlngone T ' 2015 Gradle, lnc, and licensed iinder a Creative Commons ttribution-NonConiniercial license w 'eativecomiiiiiii )I'(}/ ll(`l-! I't
  14. 14. inni-geï: rlęlnàioniññlniøil líl l liauàiiilłaiiiia s: ', ,_ -' m ? ILÃVIS . l -Jielaiilsïisvfijíi SDTÊDQOHG 25* Unless otherwise indicated, these slides are © 2015 Gradle, Inc. and licensed under a Creative Commons Attribution-NonCommercial license http: l/creativecommons. org/ licenses/ by-nC/ ÊLO/
  15. 15. Gradle new model model { components { shared(CustomLibrary) { javaversions 6, 7 } main(JvmLib ra rySpec) { targetPlatform 'java6' targetPlatform 'java7' sources { java { dependencies { library 'shared' } Unless otherwise indicated, the ' , 2015 Gradle, lnc. and licensed under a Creative (Êommons Attribution-NonConiniercial license htLpJ/ cieativeconiiiioiis. orq/ lic '
  16. 16. Nail-midt '{ praniojłęur "ilçlClc- 'lt-irfloilr" i šlåililr"`wllhllllïlnl 'l øręni-: ł-. ur "tláúkc- -Jï niinl-it(ęiii. ~.. ii= _iiii; nr" SDTÊDQOHG 25* Unless otherwise indicated, these slides are © 2015 Gradle, Inc. and licensed under a Creative Commons Attribution-NonCommercial license http: l/creativecommons. org/ licenses/ by-nC/ ÊLO/
  17. 17. Jenkins Job DSL job { using 'TMPL-test' name 'PROJ - integ- tests' scm { git(gitUrl) } triggers { cron('15 1.13 * * *') } steps { maven('-e clean integTest') } i qglílilglültä g Zøllllbljųiíjła. lllll . availIl-iaųiaiiiųuiiiławęultųæialltvu dominis-maniak"ll-iuučlømlłuumiau-tłalinname
  18. 18. l op, ,ųmrlteÉninei iiinioítaliíriygisu - 'l Ljuiíųėïi: gr , øialramla : Il l , oi-, usionwuamclii l _ei r Li , Itulłïllllåt SDTÊDQOHG 25* Unless otherwise indicated, these slides are © 2015 Gradle, Inc. and licensed under a Creative Commons Attribution-NonCommercial license http: l/creativecommons. org/ licenses/ by-nC/ ÊLO/
  19. 19. SDTÊDQOHG 25* Unless otherwise indicated, these slides are © 2015 Gradle, Inc. and licensed under a Creative Commons Attribution-NonCommercial license http: l/creativecommons. org/ licenses/ by-nC/ ÊLO/
  20. 20. Thetoob o Closures with support annotations (@DelegatesTo, .. .) o Compilation customizers o AST transformations o Type checking extensions o Groovy Shell / Groovy Console / ' . y Kspnngone Unless otherwise indicated, these slides are iii 201 S Gradle, lnc, and licensed iinder a (Éreative Commons Allrlblłll()l't'N()HC()I`t`tl`t1(-'H`ldl license T" http: //creal. ivecoiiiiiions. orq/ licenses/ bv-ni-/ /
  21. 21. Closures o Still at the core of most DSLs o delegate is very important: ['Paris', Washington'. 'Berlin']. collect { it. length() = = 5 } o do we really need it? /4 - - Kspnngone Unless otherwise indicated, these slides are iii 201 S Gradle, lnc, and licensed iinder a (Éreative Commons Attribution-NonConinierrial license y' hLL eal. ivecoiiiiiioiis. orq/ lic / hx 0/
  22. 22. Setting the delegate class HelperExtension { public static <T, U> List<U> myCollect(List<T> items, Closure<U> action) { def clone = action. clone() clone. resolveStrategy = Closure. DELEGATE_FIRST def result = [] items. each { clone. delegate = it result << clone() } result } } HelperExtension. myCollect(['Paris', 'washington', 'Berlin']) { length() = = } / l Sprmgone Aãåï" Unless otherwise indicated, these slides are iLi 201 S (šradle, lnc. and licensed iinder a Creative Commons itttribution-NonConimercial license ' hi. Lp: //cieativecoiiiiiioiis. orq/ liiieiises/ bwiiii/ )/
  23. 23. Convert it to an extension module o META-INF I services o org. codehaus. groovy. runt-ime. ExtensionModule moduleName= My extension module moduleVersion=1. 0 extensionclasses= path . to . HelperExtension / ' . y Kspnngone Unless otherwise indicated, these slides are iii 201 S Gradle, lnc, and licensed iinder a (Éreatiixe Commons Allrlblłll()l't'N()HC()I`t`tl`t1(-'H`ldl license m" http 'real. ivecoiiiiiioiis. orq/ li ises/ bvii , U/
  24. 24. Convert it to an extension module o Consume it as if it was a regular Groovy method ['Paris', 'washington', 'Berlin']. myCollect{ length() = = } /4 - - Kspnngone Unless otherwise indicated, these slides are iii 201 S Gradle, lnc, and licensed iinder a (Éreatiixe Commons . ilttribution-NonConinierrial license y' http 'real. iveconinioiis. orq/ li s/ hv-n , U/
  25. 25. Declare the delegate type o Best IDE support o Only way to have static type checking public static <T, U> List<U> myCollect( List<T> items, @DelegatesTo(FirstParam. FirstGenericType) Closure<U> pction) { /4 - - Kspnngone Unless otherwise indicated, these slides are iii 201 S Gradle, lnc, and licensed iinder a (Éreatiixe Commons . ilttribution-NiinCiyninierrial license m' htl eal. iveconinioiis. orq/ lic
  26. 26. Removing Ceremony o Is your DSL self-contained? o If so I Try to remove explicit imports I Avoid usage of the new keyword I Avoid usage of annotations I Embrace SAM types / ' N (x 50009006 Unless otherwise indicated, these slides are iii 201S Gradle, lnc. and licensed iinder a (Irealiiøe Commons Allrlblłll()n'N()HC()H`tl`t1(-'H`ldl license y" http: //ci'ealiveconinions. on]/ licenses/ bv-nc/ /
  27. 27. iniuiøílkaliiàw a. h'l'u_lf'l" : gi max-twin) maai-tuie SDTÊDQOHG 25* Unless otherwise indicated, these slides are © 2015 Gradle, Inc. and licensed under a Creative Commons Attribution-NonCommercial license http: l/creativecommons. org/ licenses/ by-nC/ ÊLO/
  28. 28. SAM What? This is cool: handle { println message } SAM type coercion works for both interfaces and abstract classes. /4 - - Kspnngone Unless otherwise indicated, these slides are iii 201 S Gradle, lnc, and licensed iinder a (Éreatiixe Commons . ilttribution-NonConinierrial license y' http 'real. iveconinioiis. orq/ li s/ hv-n , U/
  29. 29. ihm: 'itųibàtar-uųr : i t SDTÊDQOHG 25* Unless otherwise indicated, these slides are © 2015 Gradle, Inc. and licensed under a Creative Commons Attribution-NonCommercial license http: l/creativecommons. org/ licenses/ by-nC/ ÊLO/
  30. 30. Compilation customizers def importcustomizer = new ImportCustomizer() importcustomizer. addstaticstars 'com. acme. webServer' def configuration = new CompilerConfiguration() configuration. addCompilationCustomizers(importCustomizer) def shell = new Groovyshell(configuration) shell. evaluate "' serve { port 86 } get('/ foo') { . .. } /4 - - Kspnngone ( Unless otherwise indicated, the ides are iti 201 S (šradle, lnc, and licensed iinder a Creative Commons Allrlbuii()l"t'N()l'tC()n`tl`t1E-! l'(`ldl license y htt / cieativecoiiiiiioiis. orq/ lic i i
  31. 31. Compilation customizers o Impo rtCustomi ze r: automatically add imports to your scripts o ASTT ransfo rmati onCustomi ze r: automatically apply AST transformations to your scripts o Secu reASTCustomi ze r: restrict the grammar of the language o Sou rceAwa reCustomize r: apply customizers based on the source file o See docs for customizers iii 201 S Gradle, lnc. and licensed iinder a (Irealive Commons AttriliutionrNonCommercial license lit l. p: / /cre aliveconinio ns. orq/ li ('HHSPS/ btïi
  32. 32. Avoiding imperative style class webserver { static void serve(@DelegatesTo(ServerSpec) Closure cl) { def spec = new ServerSpec() cl. delegate = spec cl. resolveStrategy = 'DELEGATE_FIRST' C1() def runner = new Runner() runner. execute(spec) / < . Kspnngone Unless otherwise indicated, the 201 S Gradle, lnc, and licensed iinder a Creative Commons Allrlblłii0n'NUHC()I`| `tl`t1E-Yl'(`ldl license eativecoiiiiiioiis. orq/ lic
  33. 33. Avoiding imperative style class ServerSpec { int port void port(int port) { this. port = port } void get(String path, @DelegatesTo(Handlerspec) Closure spec) { } } / < . Kspnngone y Unless otherwise indicated, the lides are iii 201 S Gradle, lnc, and licensed iinder a (Éreatiixe Commons . ilttribution-NonConinierrial license y eal. iveconinioiis. orq/ lic Ill` 0/
  34. 34. Avoiding imperative style o Use the ServerSpec style above o The closure should configure the model o Executlon can be deferred / ' . y Kspnngone Unless otherwise indicated, these slides are iii 201 S Gradle, lnc, and licensed iinder a (Éreatiixe Commons Allrlblłll()l't'N()HC()I`t`tl`t1(-'H`ldl license T" http: //creal. ivecoiiiiiions. orq/ licenses/ bv-ni-/ /
  35. 35. ?mini i{ oïlasimioítaniríiiai: il 1.3. . _mi naai "f-nir" 'tïlfoiarųlrjii 'iimjif icW/ “šnçiexczifxiirritzari Tlarí" : a aw^ciiçi= ii~içitai~ic~i ílmęïtíltlgl žímnèiužtfalajle SDTÊDQOHG 25* Unless otherwise indicated, these slides are © 2015 Gradle, Inc. and licensed under a Creative Commons Attribution-NonCommercial license http: l/creativecommons. org/ licenses/ by-nC/ ÊLO/
  36. 36. ,llalgialniøitęlniųmpięløtåitli. kitaar _ouųïęiøiiizbiizrüiųi , Ir-_igięiuioitęniųvnpiaidå _hit-ar `l.1'o| n=. ii1i-G'ií: ri3nųi Irilltt-f-IJ i CallÊlållïÊfíilllHhajplâlllílâlllqitFlglallki giailllųgisiaiøjłaiaiøýiųøul i: SDTÊDQOHG 25* Unless otherwise indicated, these slides are © 2015 Gradle, Inc. and licensed under a Creative Commons Attribution-NonCommercial license http: l/creativecommons. org/ licenses/ by-nC/ ÊLO/
  37. 37. immutable builders o A dependency spec is by default immutable public interface Dependencyspec { @Nullable St ring getP roj ectPath() ; @Nullable String getLibra ryName() ; / < . Kspnngone Unless otherwise indicated, these slides a http: l/crealiveconinioiis. orq/ lice
  38. 38. lmmutable builders o The builder specializes the spec interface public interface DependencySpecBuilder extends DependencySpec { DependencySpecBuilder project (St ring path ) ; DependencySpecBuilder lib ra ry (St ring name); DependencySpec build ( ); /4 - - Kspnngone Unless otherwise indicated, these slides a y http: l/ciealivecoiiinioiis. orq/ lice
  39. 39. immutable builders o Concrete implementation provides the builder public class Defaultnependencyspec implements DependencySpec { private final String projectPath; private final String libraryName; / / . .. public static class Builder implements DependencySpecBuilder { private String projectPath; private String libraryName; @0verride public DependencySpecBuilder project(String path) { projectPath = path; return this; } @0verride public DependencySpecBuilder library(String name) { libraryName = name; / l springone iãà Unless otherivise indicated, these slides a "i 201 S Gradle, lnc. and licensed under a Creative Commons Atlrlblłii0n'N()HC()n`tl`t1(-! l'(`ldl license ' http: //cieativecoiiiiiioiis. orq/ lic / bi-
  40. 40. immutable builders o And the container stores a list of builders public class DefaultDependencyspeccontainer implements DependencySpecContainer {^ private final List<DefaultDependencySpec. Builder> builders new LinkedList< @0verride public DependencySpecBuilder projectifinal String path) { return doCreate(new Action<DefaultDependencySpec. Builder>() { @Override public void execute(DefaultDependencySpec. Builder builder) { builder. project(path); } ł): } @0verride public DependencySpecBuilder libraryifinal String name) { return doCreate(new Action<DefaultDependencySpec. Builder>() { @Override nuhïir unit! exeriitelnefaiilthenendenrvšner, Riiilder hiiilrtpr) I XV / < . Kspnngone iãåï Unless otherwise indicated, these slides are iti 201 S Gradle, lnc, and licensed under a Creative Commons . ilttribution-NonConimercial license y' http: l/cieativecoiiiiiioiis. orq/ lice 0/
  41. 41. SDTÊDQOHG 25* Unless otherwise indicated, these slides are © 2015 Gradle, Inc. and licensed under a Creative Commons Attribution-NonCommercial license http: l/creativecommons. org/ licenses/ by-nC/ ÊLO/
  42. 42. Goals o Provide early feedback to the user o Type safety o Help the compiler understand your DSL / ' . y Kspnngone Unless otherwise indicated, these slides are iii 201 S Gradle, lnc, and licensed iinder a (Éreatiixe Commons Allrlblłll()l't'N()HC()I`t`tl`t1(-'H`ldl license y' http: //creal. ivecoiiiiiions. orq/ licenses/ bv-ni-/ ;š, U/
  43. 43. Type checking extensions API o Event-based API o React to events such as undefined Variable or method not found o Developer instructs the type checker what to do methodNotFound { receiver, name, argtist, argTypes, call -> if (receiver= =classNodeFor(String) && name= ='longueur' && argList. size()= =0) { handled = true return newMethod('longueur', classNodeFor(String)) /4 - _ Kspnngone Unless otherwise indicated, these slides are iii 201 S Gradle, lnc, and licensed iinder a (Éreatiixe Commons . ilttribution-NonConinierrial license y' http: //creal. iveconinioiis. orq/ Iicenses/ bi>iii'/ /
  44. 44. MarkupTemplateEngine example o Given the following template pages. each { page -> _ p("Page title: $page. title") } Dtpagexext) o How do you make sure that pages is a valid model type? o How do you notify the user that page doesn't have a text property? o How to make it fast? / < - _ Kspnngone Unless otherwise indicated, these slides a iii 201 S Gradle, lnc, and licensed iinder a (Éreatiixe Commons . ilttribution-NonConinierrial license y' http: //creal. iveconinioiis. orLi/ liiieiises/ bxvii
  45. 45. Solution o Declare the model types modelTypes = { List<Page> pages } pages. each { page -> p("Page title: $page. title") } p(page. text) o implement a type checking extension /4 - - Kspnngone iãåï Unless otherwise indicated, these slides a 201 S (šradle, lnc, and licensed iinder a Creative Commons Allrlbuli()l"t'N()l'tC()n`tl`t1E-! l'(`ldl license y' htt / creativecoiiiiiioiis. orq/ lic / bv
  46. 46. MarkupTemplateEngine extension o Recognizes unresolved method calls I converts them into direct methodMissing calls o Recognizes unresolved variables I checks if they are defined in the binding I if yes, instructs the type checker what the type is iii 201 S Gradle, lnc. and licensed iinder a (Irealiiøe Commons Allrlblłll()n'N()n(7()n`tl`t1(-'H`ldl license lit l. p: / /cre aliveconinio ns. oni/ li censes/ bvii
  47. 47. SDTÊDQOHG 25* Unless otherwise indicated, these slides are © 2015 Gradle, Inc. and licensed under a Creative Commons Attribution-NonCommercial license http: l/creativecommons. org/ licenses/ by-nC/ ÊLO/
  48. 48. "i" . l -aęulivłiríililjnxøïłavz- { : Iiizr l SDTÊDQOHG 25* Unless otherwise indicated, these slides are © 2015 Gradle, Inc. and licensed under a Creative Commons Attribution-NonCommemial license http: l/creativecommons. org/ licenses/ by-nC/ ÊLO/
  49. 49. (Optional) @ClosureParams public static <T> Co11ection<T> eachwithIndex( Col1ection<T> self, Qclosu rePa rams (va1ue= F romSt ring . class , options= "T , Integer") Closure closure) { Check out the documentation for more details. /4 - - Ksprlngone Unless nihenvise ln(ll(`dll-'[l, these slides ere W* 2015 Gradle, Jnr, and llrensed umler d CFPdlJVP (Inmmons : Xltribulmn-Nnnüomnïerridl lirense e' hLL edhverommrzns. orq/ lir
  50. 50. What we learnt o Leverage the lean syntax of Groovy o Scoping improves readabilíty o Use the delegate o Use @DelegatesTo and @ClosureParams for IDE/ type checker suppon o Use imperative style as last resort o Help yourself (builders, immutable datastructures, .. .) W* 7015 (Jrddle, lnr. dml lirensed Limler d (Irediwe (Iommons : Xllribul10neN<>nC0mn1err1dllicense ht l. p: / /('re dl. lx'P('()I1'lnllJ115.011]/ ll('enS(-'5/lJV~Il
  51. 51. Questions / < . Ksprlngone á: Unl 's nthenvise indicdied, these slides are W* 201 S (šrddle, lnc, and licensed under d CFPdliVP (Iommons : Xttribtiiien-Nunüomnïercidl license e' hi. /(`I'E'dl. ll'P('()I1iUl()IiS. Urq/ llceíi s/ bv-m ' (J/
  52. 52. We're hiring! httpJ/ gradIeorg/ gradIe-jobs/ I Gradle Bujld Happiness. / ' . y Ksprlngone Unless otherwise indicdied, these slides are W* 201 S (Jrddle, Inc, and licensed under d (Érediiiøe Commons Al. l.l"ll)llllüfłNünConlnïí-'iTldl license m" http: //(`I'ê'dlllfPfoilliilllIISJJYQ/ lltï-ł es/ bve (J/
  53. 53. Thank you! o slides and code: httpsJ/ github. comlmelixls2gx-groovy-dsls o Groovy documentation : httpJ/ groovy- Iang. org/ documentatiomhtml o Follow me: @CedricChampeau / /' X~ (x sprlngone L' ss (itherwise indicated, these slides are W* 'JOIS (Iradle, lnc. and licensed under a CFPdlJVc' Commons . Attribulioii-Nonüinimercial license e" h . i : l/rrealųveconinions. orq/ licenses/ bv-nr/ lill/

×