Les nouveautés de Groovy 2 -- Mix-IT 2013

149

description

Fort de ses 1.7 millions de téléchargements l'an passé, Groovy continue son bonhomme de chemin en tête parmi les langages de programmation alternatifs pour la JVM. Groovy 2.0, sorti l'an passé, introduisait dans son offre de la modularité, le support de JDK 7 au niveau syntaxique avec "Project Coin" autant qu'au niveau JVM avec l'utilisation d'"invoke dynamic", et proposait des fonctionnalités de typage et de compilation statique. Groovy 2.1, quant à lui, s'appuie sur ces bases pour compléter le support d'"invoke dynamic" pour plus de performances. Il propose des améliorations permettant de documenter, d'aider les IDEs, et de vérifier statiquement les Domain-Specific Languages construits avec Groovy. Vous pourrez créer des méta-annotations regroupant d'autres annotations, pour éviter l'annotation "hell". Et enfin, vous irez encore plus loin dans la customisation du compilateur ! Accrochez votre ceinture, paré au décollage !

Transcript of Les nouveautés de Groovy 2 -- Mix-IT 2013

Page 1: Les nouveautés de Groovy 2 -- Mix-IT 2013
Page 2: Les nouveautés de Groovy 2 -- Mix-IT 2013

Les nouveautés de Groovy 2

Guillaume LaforgeGroovy Project ManagerSpringSource / VMware

Page 3: Les nouveautés de Groovy 2 -- Mix-IT 2013

Guillaume Laforge @glaforge

http://glaforge.appspot.com http://gplus.to/glaforge

Page 4: Les nouveautés de Groovy 2 -- Mix-IT 2013

Langage dynamiqueoptionnellement typé

Groovy

Page 5: Les nouveautés de Groovy 2 -- Mix-IT 2013

...statiquement vérifié et compilé

Groovy

Page 6: Les nouveautés de Groovy 2 -- Mix-IT 2013

syntaxe dérivant de Java :facile à apprendre !

Groovy

Page 7: Les nouveautés de Groovy 2 -- Mix-IT 2013

1.7 million downloads

Page 8: Les nouveautés de Groovy 2 -- Mix-IT 2013

A blossomingEcosystem

Page 9: Les nouveautés de Groovy 2 -- Mix-IT 2013
Page 10: Les nouveautés de Groovy 2 -- Mix-IT 2013
Page 11: Les nouveautés de Groovy 2 -- Mix-IT 2013
Page 12: Les nouveautés de Groovy 2 -- Mix-IT 2013
Page 13: Les nouveautés de Groovy 2 -- Mix-IT 2013

GV

M

Page 14: Les nouveautés de Groovy 2 -- Mix-IT 2013
Page 15: Les nouveautés de Groovy 2 -- Mix-IT 2013

GVM

Page 16: Les nouveautés de Groovy 2 -- Mix-IT 2013

GVMGROOVYENVIRONMENTMANAGER

Page 17: Les nouveautés de Groovy 2 -- Mix-IT 2013

GVM: Groovy enVironment Manager

• Nouveau venu dans la communauté• http://gvmtool.net/ — @gvmtool

• Gérer les versions parallèles de différents projets de l’écosystème

• Supporte...• Groovy, Grails, Griffon, Gradle, Vert.x

• Sur Linux, MacOS, Cygwin, Solaris, FreeBSD

Page 18: Les nouveautés de Groovy 2 -- Mix-IT 2013

Commençons par Groovy 2.0

ModularityJava 7: Project Coin & invoke dynamicStatic type checking & compilation

Page 19: Les nouveautés de Groovy 2 -- Mix-IT 2013

Modularité

« Tout le monde n’a pas besoin de tout,tout le temps, en même temps ! »

Page 20: Les nouveautés de Groovy 2 -- Mix-IT 2013

La modularité de Groovy

• Le JAR « groovy-all » de... 6 Mo !

• En plus du langage, des APIs :• moteur de template, scripting the tâches Ant,

construction d’interfaces Swing...

• Proposer un coeur plus léger• et des modules par API

• Brancher des méthodes d’extension

Page 21: Les nouveautés de Groovy 2 -- Mix-IT 2013

Les nouveaux JARs

• Un JAR principal plus petit 3 Mo

• Modules

– console– docgenerator– groovydoc– groovysh– ant– bsf

– jsr-223– jmx– sql– swing– servlet– templates

– test– testng– json– xml

Page 22: Les nouveautés de Groovy 2 -- Mix-IT 2013

Les nouveaux JARs

• Un JAR principal plus petit 3 Mo

• Modules

– console– docgenerator– groovydoc– groovysh– ant– bsf

– jsr-223– jmx– sql– swing– servlet– templates

– test– testng– json– xml

Page 23: Les nouveautés de Groovy 2 -- Mix-IT 2013

« Fais ton marché »

Page 24: Les nouveautés de Groovy 2 -- Mix-IT 2013

Les modules d’extension

• Créer sa propre extension• contribuer des méthodes d’instance

package  foo

class  StringExtension  {        static  introduces(String  self,  String  name)  {                "Hi  ${name),  I’m  ${self}"        }}

//  usage:  "Guillaume".introduces("Cédric")

Page 25: Les nouveautés de Groovy 2 -- Mix-IT 2013

Les modules d’extension

• Créer sa propre extension• contribuer des méthodes d’instance

package  foo

class  StringExtension  {        static  introduces(String  self,  String  name)  {                "Hi  ${name),  I’m  ${self}"        }}

//  usage:  "Guillaume".introduces("Cédric")

Même structure que les catégories

Page 26: Les nouveautés de Groovy 2 -- Mix-IT 2013

Les modules d’extension

• Créer sa propre extension• contribuer des méthodes statiques

package  foo

class  StaticStringExtension  {        static  hi(String  self)  {                "Hi!"        }}

//  usage:  String.hi()

Page 27: Les nouveautés de Groovy 2 -- Mix-IT 2013

Descripteur des modules d’extension

• META-INF/• services/• org.codehaus.groovy.runtime.ExtensionModule

moduleName  =  stringExtensionsmoduleVersion  =  1.0//  liste  de  noms  de  classe  séparées  par  des  virgulesextensionClasses  =  foo.StringExtension//  liste  de  noms  de  classe  séparées  par  des  virgulesstaticExtensionClasses  =  foo.StaticStringExtension

Page 28: Les nouveautés de Groovy 2 -- Mix-IT 2013

Thème Java 7

Syntaxe de « Project Coin »Support d’invoke dynamic

Page 29: Les nouveautés de Groovy 2 -- Mix-IT 2013

Une histoire de canard...

Page 30: Les nouveautés de Groovy 2 -- Mix-IT 2013

Littéraux binaires

• En plus de décimal, octal, et héxa...

• On a une représentation binaire :

int  x  =  0b10101111assert  x  ==  175  byte  aByte  =  0b00100001assert  aByte  ==  33  int  anInt  =  0b1010000101000101assert  anInt  ==  41285

Page 31: Les nouveautés de Groovy 2 -- Mix-IT 2013

Les « underscores » dans les littéraux

• Utilisation des « underscores » pour séparer les unités au choix

long  creditCardNumber  =  1234_5678_9012_3456Llong  socialSecurityNumbers  =  999_99_9999Lfloat  monetaryAmount  =  12_345_132.12long  hexBytes  =  0xFF_EC_DE_5Elong  hexWords  =  0xFFEC_DE5Elong  maxLong  =  0x7fff_ffff_ffff_ffffLlong  alsoMaxLong  =  9_223_372_036_854_775_807Llong  bytes  =  0b11010010_01101001_10010100_10010010

Page 32: Les nouveautés de Groovy 2 -- Mix-IT 2013

Catch d’exceptions multiples

• Un seul bloc catch pour plusieurs exceptions, plutôt que dupliquer les blocs

try  {        /*  ...  */}  catch(IOException  |  NullPointerException  e)  {        /*  un  seul  bloc  */}

Page 33: Les nouveautés de Groovy 2 -- Mix-IT 2013
Page 34: Les nouveautés de Groovy 2 -- Mix-IT 2013

Coin-Coin !

Page 35: Les nouveautés de Groovy 2 -- Mix-IT 2013

Support d’invoke dynamic de JDK 7

• Nouveau « flag » pour compiler avec « indy »• on proposera peut-être un backport (pour JDK < 7)

• Avantages• plus de performance à l’exécution• en théorie...

• Sur le long terme, on pourra remplacer• « call site caching » ➔ MethodHandles• « metaclass registry » ➔ ClassValues

• et le JIT « inlinera » plus facilement le code

Page 36: Les nouveautés de Groovy 2 -- Mix-IT 2013

Thème « statique »

Vérification statique de typeCompilation statique

Page 37: Les nouveautés de Groovy 2 -- Mix-IT 2013

Vérification statiques de type

• But : rendre le compilateur « grincheux » !

• jeter des erreurs à la compilation• et non pas au runtime !

Page 38: Les nouveautés de Groovy 2 -- Mix-IT 2013

Tout le monde n’a pas besoin de dynamique

tout le temps !

Page 39: Les nouveautés de Groovy 2 -- Mix-IT 2013

Tout le monde n’a pas besoin de dynamique

tout le temps !

Nah !

Page 40: Les nouveautés de Groovy 2 -- Mix-IT 2013

Vérification statique de type

• Le compilateur grincheux souhaite...

• dire quand il y a une faute de frappe dans le nom d’une méthode ou d’une variable

• râler quand on appelle une méthode inexistante

• ou quand on fait de mauvaises affectations ou utilise un mauvais type de retour

Page 41: Les nouveautés de Groovy 2 -- Mix-IT 2013

Vérification statique de type

• Le compilateur doit inférer les types...

• moins besoin de types explicites et de casts

• inférence fine • « flow typing »• « lowest upper bound »

Page 42: Les nouveautés de Groovy 2 -- Mix-IT 2013

Vérification statique de type

• Mais le compilateur doit comprendre les méthodes d’extension de Groovy

• permet d’avoir un bon niveau de dynamisme malgré les restrictions supplémentaires

Page 43: Les nouveautés de Groovy 2 -- Mix-IT 2013

Fautes de frappe

import  groovy.transform.TypeChecked  void  method()  {}  @TypeChecked  test()  {        //  Cannot  find  matching  method  metthhoood()        metthhoood()          def  name  =  "Guillaume"        //  variable  naamme  is  undeclared        println  naamme}

Page 44: Les nouveautés de Groovy 2 -- Mix-IT 2013

Fautes de frappe

import  groovy.transform.TypeChecked  void  method()  {}  @TypeChecked  test()  {        //  Cannot  find  matching  method  metthhoood()        metthhoood()          def  name  =  "Guillaume"        //  variable  naamme  is  undeclared        println  naamme}

Erreur de compilation

Page 45: Les nouveautés de Groovy 2 -- Mix-IT 2013

Fautes de frappe

import  groovy.transform.TypeChecked  void  method()  {}  @TypeChecked  test()  {        //  Cannot  find  matching  method  metthhoood()        metthhoood()          def  name  =  "Guillaume"        //  variable  naamme  is  undeclared        println  naamme}

Erreur de compilation

Erreur de compilation

Page 46: Les nouveautés de Groovy 2 -- Mix-IT 2013

Fautes de frappe

import  groovy.transform.TypeChecked  void  method()  {}  @TypeChecked  test()  {        //  Cannot  find  matching  method  metthhoood()        metthhoood()          def  name  =  "Guillaume"        //  variable  naamme  is  undeclared        println  naamme}

Erreur de compilation

Erreur de compilation

Annotation niveau classe ou méthode

Page 47: Les nouveautés de Groovy 2 -- Mix-IT 2013

Mauvaises affectations de variable

//  cannot  assign  value  of  type...  to  variable...int  x  =  new  Object()Set  set  =  new  Object()  String[]  strings  =  ['a','b','c']int  str  =  strings[0]  //  cannot  find  matching  method  plus()int  i  =  0i  +=  '1'

Page 48: Les nouveautés de Groovy 2 -- Mix-IT 2013

Mauvaises affectations de variable

//  cannot  assign  value  of  type...  to  variable...int  x  =  new  Object()Set  set  =  new  Object()  String[]  strings  =  ['a','b','c']int  str  =  strings[0]  //  cannot  find  matching  method  plus()int  i  =  0i  +=  '1'

Erreurs de compilation

Page 49: Les nouveautés de Groovy 2 -- Mix-IT 2013

Mauvaises affectations de variable

//  cannot  assign  value  of  type...  to  variable...int  x  =  new  Object()Set  set  =  new  Object()  String[]  strings  =  ['a','b','c']int  str  =  strings[0]  //  cannot  find  matching  method  plus()int  i  =  0i  +=  '1'

Erreurs de compilation

Erreurs de compilation

Page 50: Les nouveautés de Groovy 2 -- Mix-IT 2013

Mauvaises affectations de variable

//  cannot  assign  value  of  type...  to  variable...int  x  =  new  Object()Set  set  =  new  Object()  String[]  strings  =  ['a','b','c']int  str  =  strings[0]  //  cannot  find  matching  method  plus()int  i  =  0i  +=  '1'

Erreurs de compilation

Erreurs de compilation

Erreurs de compilation

Page 51: Les nouveautés de Groovy 2 -- Mix-IT 2013

Mauvais type de retour

//  checks  if/else  branch  return  values@TypeCheckedint  method()  {        if  (true)  {  'String'  }        else  {  42  }}//  works  for  switch/case  &  try/catch/finally  //  transparent  toString()  implied@TypeCheckedString  greeting(String  name)  {        def  sb  =  new  StringBuilder()        sb  <<  "Hi  "  <<  name}

Page 52: Les nouveautés de Groovy 2 -- Mix-IT 2013

Mauvais type de retour

//  checks  if/else  branch  return  values@TypeCheckedint  method()  {        if  (true)  {  'String'  }        else  {  42  }}//  works  for  switch/case  &  try/catch/finally  //  transparent  toString()  implied@TypeCheckedString  greeting(String  name)  {        def  sb  =  new  StringBuilder()        sb  <<  "Hi  "  <<  name}

Erreur de compilation

Page 53: Les nouveautés de Groovy 2 -- Mix-IT 2013

Mauvais type de retour

//  checks  if/else  branch  return  values@TypeCheckedint  method()  {        if  (true)  {  'String'  }        else  {  42  }}//  works  for  switch/case  &  try/catch/finally  //  transparent  toString()  implied@TypeCheckedString  greeting(String  name)  {        def  sb  =  new  StringBuilder()        sb  <<  "Hi  "  <<  name}

Erreur de compilation

Au final, appèle le toString() de StringBuilder

Page 54: Les nouveautés de Groovy 2 -- Mix-IT 2013

Inférence de type

@TypeChecked  test()  {        def  name  =  "    Guillaume    "          //  String  type  infered  (even  inside  GString)        println  "NAME  =  ${name.toUpperCase()}"            //  Groovy  GDK  method  support        //  (GDK  operator  overloading  too)        println  name.trim()          int[]  numbers  =  [1,  2,  3]        //  Element  n  is  an  int        for  (int  n  in  numbers)  {                println  n        }}

Page 55: Les nouveautés de Groovy 2 -- Mix-IT 2013

Inférence de type

@TypeChecked  test()  {        def  name  =  "    Guillaume    "          //  String  type  infered  (even  inside  GString)        println  "NAME  =  ${name.toUpperCase()}"            //  Groovy  GDK  method  support        //  (GDK  operator  overloading  too)        println  name.trim()          int[]  numbers  =  [1,  2,  3]        //  Element  n  is  an  int        for  (int  n  in  numbers)  {                println  n        }}

Variable optionnellement typée

Page 56: Les nouveautés de Groovy 2 -- Mix-IT 2013

Inférence de type

@TypeChecked  test()  {        def  name  =  "    Guillaume    "          //  String  type  infered  (even  inside  GString)        println  "NAME  =  ${name.toUpperCase()}"            //  Groovy  GDK  method  support        //  (GDK  operator  overloading  too)        println  name.trim()          int[]  numbers  =  [1,  2,  3]        //  Element  n  is  an  int        for  (int  n  in  numbers)  {                println  n        }}

Variable optionnellement typée

Type String inféré

Page 57: Les nouveautés de Groovy 2 -- Mix-IT 2013

Inférence de type

@TypeChecked  test()  {        def  name  =  "    Guillaume    "          //  String  type  infered  (even  inside  GString)        println  "NAME  =  ${name.toUpperCase()}"            //  Groovy  GDK  method  support        //  (GDK  operator  overloading  too)        println  name.trim()          int[]  numbers  =  [1,  2,  3]        //  Element  n  is  an  int        for  (int  n  in  numbers)  {                println  n        }}

Variable optionnellement typée

Méthode trim() ajoutée dynamiquement par Groovy

Type String inféré

Page 58: Les nouveautés de Groovy 2 -- Mix-IT 2013

Inférence de type

@TypeChecked  test()  {        def  name  =  "    Guillaume    "          //  String  type  infered  (even  inside  GString)        println  "NAME  =  ${name.toUpperCase()}"            //  Groovy  GDK  method  support        //  (GDK  operator  overloading  too)        println  name.trim()          int[]  numbers  =  [1,  2,  3]        //  Element  n  is  an  int        for  (int  n  in  numbers)  {                println  n        }}

Variable optionnellement typée

Type des éléments d’un tableau inféré

Méthode trim() ajoutée dynamiquement par Groovy

Type String inféré

Page 59: Les nouveautés de Groovy 2 -- Mix-IT 2013

Mélanger dynamique et statiquement vérifié

@TypeCheckedString  greeting(String  name)  {        //  call  method  with  dynamic  behavior        //  but  with  proper  signature        generateMarkup(name.toUpperCase())}  //  usual  dynamic  behaviorString  generateMarkup(String  name)  {        def  sw  =  new  StringWriter()        new  MarkupBuilder(sw).html  {                body  {                        div  name                }        }        sw.toString()}

Page 60: Les nouveautés de Groovy 2 -- Mix-IT 2013

Mélanger dynamique et statiquement vérifié

@TypeCheckedString  greeting(String  name)  {        //  call  method  with  dynamic  behavior        //  but  with  proper  signature        generateMarkup(name.toUpperCase())}  //  usual  dynamic  behaviorString  generateMarkup(String  name)  {        def  sw  =  new  StringWriter()        new  MarkupBuilder(sw).html  {                body  {                        div  name                }        }        sw.toString()}

Statiquement vérifié

Page 61: Les nouveautés de Groovy 2 -- Mix-IT 2013

Mélanger dynamique et statiquement vérifié

@TypeCheckedString  greeting(String  name)  {        //  call  method  with  dynamic  behavior        //  but  with  proper  signature        generateMarkup(name.toUpperCase())}  //  usual  dynamic  behaviorString  generateMarkup(String  name)  {        def  sw  =  new  StringWriter()        new  MarkupBuilder(sw).html  {                body  {                        div  name                }        }        sw.toString()}

Statiquement vérifié

Dynamique

Page 62: Les nouveautés de Groovy 2 -- Mix-IT 2013

Vérifications par instanceof

@TypeChecked  void  test(Object  val)  {

       if  (val  instanceof  String)  {                println  val.toUpperCase()        }  else  if  (val  instanceof  Number)  {                println  "X"  *  val.intValue()        }}

Page 63: Les nouveautés de Groovy 2 -- Mix-IT 2013

Vérifications par instanceof

@TypeChecked  void  test(Object  val)  {

       if  (val  instanceof  String)  {                println  val.toUpperCase()        }  else  if  (val  instanceof  Number)  {                println  "X"  *  val.intValue()        }}

Pas besoin de cast

Page 64: Les nouveautés de Groovy 2 -- Mix-IT 2013

Vérifications par instanceof

@TypeChecked  void  test(Object  val)  {

       if  (val  instanceof  String)  {                println  val.toUpperCase()        }  else  if  (val  instanceof  Number)  {                println  "X"  *  val.intValue()        }}

Pas besoin de cast

Pas besoin de cast

Page 65: Les nouveautés de Groovy 2 -- Mix-IT 2013

Vérifications par instanceof

@TypeChecked  void  test(Object  val)  {

       if  (val  instanceof  String)  {                println  val.toUpperCase()        }  else  if  (val  instanceof  Number)  {                println  "X"  *  val.intValue()        }}

Pas besoin de cast

Pas besoin de cast

Comprends la méthode du GDK : String#multuply(int)

Page 66: Les nouveautés de Groovy 2 -- Mix-IT 2013

Lowest Upper Bound

• Le plus petit « super » type commun• peut-être virtuel (« non-dénotable »)

@TypeChecked  test()  {        //  an  integer  and  a  BigDecimal        return  [1234,  3.14]}

Page 67: Les nouveautés de Groovy 2 -- Mix-IT 2013

Lowest Upper Bound

• Le plus petit « super » type commun• peut-être virtuel (« non-dénotable »)

@TypeChecked  test()  {        //  an  integer  and  a  BigDecimal        return  [1234,  3.14]}

Type inféré :List<Number & Comparable>

Page 68: Les nouveautés de Groovy 2 -- Mix-IT 2013

Flow typing

• La vérification statique « suit » le type des valeurs assignées dans les variables

@TypeChecked  test()  {        def  var  =  123                  //  int  inferé        int  x  =  var                      //  var  est  un  int        var  =  "123"                      //  assigne  une  String  dans  var

       x  =  var.toInteger()      //  pas  besoin  de  cast

       var  =  123        x  =  var.toUpperCase()  //  erreur,  var  est  un  int  !}

Page 69: Les nouveautés de Groovy 2 -- Mix-IT 2013

Pô très clean ton code, non mais allô quoi ?

Page 70: Les nouveautés de Groovy 2 -- Mix-IT 2013

Pô très clean ton code, non mais allô quoi ?

Ben non !

Page 71: Les nouveautés de Groovy 2 -- Mix-IT 2013

Vérification statique et code dynamique

• La vérification statique à la compilation• @TypeChecked ne change pas le comportement• ne pas confondre avec compilation statique

• La plupart des fonctionnalités dynamiques ne peuvent être vérifiées

• changement de métaclasse, catégories...• variables dynamiques dans le « script binding »

• Mais métaprogrammation compile-time OK• si suffisamment d’informations de type

Page 72: Les nouveautés de Groovy 2 -- Mix-IT 2013

Pas de métaprogrammation dynamique

@TypeChecked  void  test()  {        Integer.metaClass.foo  =  {}        123.foo()}

Page 73: Les nouveautés de Groovy 2 -- Mix-IT 2013

Pas de métaprogrammation dynamique

@TypeChecked  void  test()  {        Integer.metaClass.foo  =  {}        123.foo()}

Accès au champ dynamique

metaClass interdit

Page 74: Les nouveautés de Groovy 2 -- Mix-IT 2013

Pas de métaprogrammation dynamique

@TypeChecked  void  test()  {        Integer.metaClass.foo  =  {}        123.foo()}

Accès au champ dynamique

metaClass interditMéthode non reconnue

Page 75: Les nouveautés de Groovy 2 -- Mix-IT 2013

Type explicite pour les paramètres de closure

@TypeChecked  test()  {        ["a",  "b",  "c"].collect  {                it.toUpperCase()  //  Pas  d’accord  !        }}

Page 76: Les nouveautés de Groovy 2 -- Mix-IT 2013

Type explicite pour les paramètres de closure

@TypeChecked  test()  {        ["a",  "b",  "c"].collect  {  String  it  -­‐>                it.toUpperCase()  //  OK,  une  String        }}

Page 77: Les nouveautés de Groovy 2 -- Mix-IT 2013

Type explicite pour les paramètres de closure

@TypeChecked  test()  {        ["a",  "b",  "c"].collect  {  String  it  -­‐>                it.toUpperCase()  //  OK,  une  String        }}

Obligé d’indiquer le type explicitement

Page 78: Les nouveautés de Groovy 2 -- Mix-IT 2013

Type explicite pour les paramètres de closure

@TypeChecked  test()  {        ["a",  "b",  "c"].collect  {  String  it  -­‐>                it.toUpperCase()  //  OK,  une  String        }}

Obligé d’indiquer le type explicitement

La liste peut contenir n’importe quoi à l’exécution !

Page 79: Les nouveautés de Groovy 2 -- Mix-IT 2013

Mais si c’est pô dynamique, on peut compiler statiquement ?

Page 80: Les nouveautés de Groovy 2 -- Mix-IT 2013

Mais si c’est pô dynamique, on peut compiler statiquement ?

Ben oui !

Page 81: Les nouveautés de Groovy 2 -- Mix-IT 2013

Compilation statique

• Etant donné que le code est vérifié, que l’on infère beaucoup d’information de type...on peut aussi bien compiler statiquement !

• càd générer le même bytecode que javac

• Aussi intéressant pour ceux qui sont bloqués en JDK < 7, pour bénéficier d’améliorations de performances

Page 82: Les nouveautés de Groovy 2 -- Mix-IT 2013

Avantages de la compilation statique

• On gagne :• de la « type safety »• grâce à la vérification statique • car la compilation statique s’appuie dessus

• du code plus rapide• aussi proche que la performance de Java

• du code immunisé contre le « monkey patching »• la métaprogrammation dynamique peut

interférer avec vos frameworks• du bytecode généré plus petit

Page 83: Les nouveautés de Groovy 2 -- Mix-IT 2013

Ouais, ch’fais c’que j’veux

avec ton code

Page 84: Les nouveautés de Groovy 2 -- Mix-IT 2013

Ouais, ch’fais c’que j’veux

avec ton code

Niark !

Page 85: Les nouveautés de Groovy 2 -- Mix-IT 2013

Inconvénients de la compilation statique

• On y perds...

• Certaines fonctionnalités dynamiques• changement de métaclasse, catégories

• Le « dynamic dispatch » de méthode peut différer• même si grâce à l’inférence de type, elle est aussi

proche de Groovy « classique » que possible

Page 86: Les nouveautés de Groovy 2 -- Mix-IT 2013

Mixer compilation statique et code dynamique@CompileStaticString  greeting(String  name)  {        //  call  method  with  dynamic  behavior        //  but  with  proper  signature        generateMarkup(name.toUpperCase())}  //  usual  dynamic  behaviorString  generateMarkup(String  name)  {        def  sw  =  new  StringWriter()        new  MarkupBuilder(sw).html  {                body  {                        div  name                }        }        sw.toString()}

Page 87: Les nouveautés de Groovy 2 -- Mix-IT 2013

Mixer compilation statique et code dynamique@CompileStaticString  greeting(String  name)  {        //  call  method  with  dynamic  behavior        //  but  with  proper  signature        generateMarkup(name.toUpperCase())}  //  usual  dynamic  behaviorString  generateMarkup(String  name)  {        def  sw  =  new  StringWriter()        new  MarkupBuilder(sw).html  {                body  {                        div  name                }        }        sw.toString()}

Statiquement compilé

Page 88: Les nouveautés de Groovy 2 -- Mix-IT 2013

Mixer compilation statique et code dynamique@CompileStaticString  greeting(String  name)  {        //  call  method  with  dynamic  behavior        //  but  with  proper  signature        generateMarkup(name.toUpperCase())}  //  usual  dynamic  behaviorString  generateMarkup(String  name)  {        def  sw  =  new  StringWriter()        new  MarkupBuilder(sw).html  {                body  {                        div  name                }        }        sw.toString()}

Statiquement compilé

Dynamique

Page 89: Les nouveautés de Groovy 2 -- Mix-IT 2013

Mixer compilation statique et code dynamique@CompileStaticString  greeting(String  name)  {        //  call  method  with  dynamic  behavior        //  but  with  proper  signature        generateMarkup(name.toUpperCase())}  //  usual  dynamic  behaviorString  generateMarkup(String  name)  {        def  sw  =  new  StringWriter()        new  MarkupBuilder(sw).html  {                body  {                        div  name                }        }        sw.toString()}

Statiquement compilé

Dynamique

Appel d’une méthode au

contenu dynamique

Page 90: Les nouveautés de Groovy 2 -- Mix-IT 2013

Mixer compilation statique et code dynamique@CompileStaticString  greeting(String  name)  {        //  call  method  with  dynamic  behavior        //  but  with  proper  signature        generateMarkup(name.toUpperCase())}  //  usual  dynamic  behaviorString  generateMarkup(String  name)  {        def  sw  =  new  StringWriter()        new  MarkupBuilder(sw).html  {                body  {                        div  name                }        }        sw.toString()}

Statiquement compilé

Dynamique

Appel d’une méthode au

contenu dynamique

La signature d’une méthode est un

contrat !

Page 91: Les nouveautés de Groovy 2 -- Mix-IT 2013

Et la performance dans tout ça ?

• Comparaisons entre :

• Java

• Groovy• avec compilation statique — Groovy 2.0• avec optimisations types primitifs — Groovy 1.8+• sans optimisation — Groovy 1.7

Page 92: Les nouveautés de Groovy 2 -- Mix-IT 2013

Et la performance dans tout ça ?

Fibonacci Pi (π) quadrature

Binarytrees

Java

Staticcompilation

Primitive optimizations

No prim.optimizations

191 ms 97 ms 3.6 s

197 ms 101 ms 4.3 s

360 ms 111 ms 23.7 s

2590 ms 3220 ms 50.0 s1.7

1.8

2.x

Page 93: Les nouveautés de Groovy 2 -- Mix-IT 2013

...maintenantGroovy 2.1

Support complet d’invoke dynamicMéta-annotationsConfiguration avancée du compilateurExtensions du type checker

Page 94: Les nouveautés de Groovy 2 -- Mix-IT 2013

Invoke Dynamic

Support complet de Invoke Dynamic

Page 95: Les nouveautés de Groovy 2 -- Mix-IT 2013

Support complet d’invoke dynamic

• Dans Groovy 2.0, tous les appels de méthode ne passaient pas par « indy »

• seulement les appels de méthodes normals• utilisation conjointe du « call site caching »

• Sur JDK 7, avec le JAR « indy », Groovy 2.1 utilise « invoke dynamic » partout

• Sur JDK < 7, encore du « call site caching »

Page 96: Les nouveautés de Groovy 2 -- Mix-IT 2013

Méta-annotations

Un annotation pour les gouverner toutes !

Page 97: Les nouveautés de Groovy 2 -- Mix-IT 2013

Méta-annotations

• Créer des méta-annotations qui combinent et / ou paramétrisent d’autres annotations

• Et qui fonctionnent avec les annotations des transformations d’AST

Page 98: Les nouveautés de Groovy 2 -- Mix-IT 2013

Méta-annotations

@Immutable@ToString(excludes  =  ["age"])@AnnotationCollector@interface  MyAlias  {}

Page 99: Les nouveautés de Groovy 2 -- Mix-IT 2013

Méta-annotations

@Immutable@ToString(excludes  =  ["age"])@AnnotationCollector@interface  MyAlias  {}

Annotations collectées

Page 100: Les nouveautés de Groovy 2 -- Mix-IT 2013

Méta-annotations

@Immutable@ToString(excludes  =  ["age"])@AnnotationCollector@interface  MyAlias  {}

Annotations collectées

Le collecteur

Page 101: Les nouveautés de Groovy 2 -- Mix-IT 2013

Méta-annotations

@Immutable@ToString(excludes  =  ["age"])@AnnotationCollector@interface  MyAlias  {}

Annotations collectées

Le collecteur

Votre propre alias d’annotation

Page 102: Les nouveautés de Groovy 2 -- Mix-IT 2013

Méta-annotations

@Immutable@ToString(excludes  =  ["age"])@AnnotationCollector@interface  MyAlias  {}

@MyAliasclass  Foo  {        String  name        int  age}

Annotations collectées

Le collecteur

Votre propre alias d’annotation

Page 103: Les nouveautés de Groovy 2 -- Mix-IT 2013

Méta-annotations

@Immutable@ToString(excludes  =  ["age"])@AnnotationCollector@interface  MyAlias  {}

@MyAliasclass  Foo  {        String  name        int  age}

Annotations collectées

Le collecteur

Votre propre alias d’annotation

Utilisez votre méta-annotation

Page 104: Les nouveautés de Groovy 2 -- Mix-IT 2013

L’annotation@DelegatesTo

Améliorer l’outillage pour le support des

Domain-Specific Languages

Page 105: Les nouveautés de Groovy 2 -- Mix-IT 2013

Annotation @DelegatesTo

• La vérification statique fonctionne bien avec certains Domain-Specific Languages

• « command chains », méthodes d’extension...

• Mais pas pour les DSLs utilisant des closures et de la délégation d’appel

• souvent utilisé dans les DSLs comme Gradle

task  copyTask(type:  Copy)  {        from  'src/main/webapp'        into  'build/explodedWar'}

Page 106: Les nouveautés de Groovy 2 -- Mix-IT 2013

Annotation @DelegatesTo

exec(spec)  {        foo()}

Page 107: Les nouveautés de Groovy 2 -- Mix-IT 2013

Annotation @DelegatesToclass  ExecSpec  {        void  foo()}

exec(spec)  {        foo()}

Page 108: Les nouveautés de Groovy 2 -- Mix-IT 2013

Annotation @DelegatesToclass  ExecSpec  {        void  foo()}

void  exec(ExecSpec  sp,  Closure  c)  {        c.delegate  =  sp        c()}

exec(spec)  {        foo()}

Page 109: Les nouveautés de Groovy 2 -- Mix-IT 2013

Annotation @DelegatesToclass  ExecSpec  {        void  foo()}

void  exec(ExecSpec  sp,  Closure  c)  {        c.delegate  =  sp        c()}

exec(spec)  {        foo()}

Le vérificateur statique ne sait rien de la méthode foo()

Page 110: Les nouveautés de Groovy 2 -- Mix-IT 2013

Annotation @DelegatesToclass  ExecSpec  {        void  foo()}

void  exec(ExecSpec  sp,  Closure  c)  {        c.delegate  =  sp        c()}

exec(spec)  {        foo()}

Annoter avec @DelegatesTo(ExecSpec)

Le vérificateur statique ne sait rien de la méthode foo()

Page 111: Les nouveautés de Groovy 2 -- Mix-IT 2013

Annotation @DelegatesTo

• Avec une autre stratégie de délégation

void  exec(ExecSpec  sp,  Closure  c)  {        c.delegate  =  sp        c.resolveStrategy  =  DELEGATE_FIRST        c()}

Page 112: Les nouveautés de Groovy 2 -- Mix-IT 2013

Annotation @DelegatesTo

• Avec une autre stratégie de délégation

void  exec(ExecSpec  sp,  Closure  c)  {        c.delegate  =  sp        c.resolveStrategy  =  DELEGATE_FIRST        c()}

Annoter avec@DelegatesTo(value = ExecSpec,

strategy = DELEGATE_FIRST)

Page 113: Les nouveautés de Groovy 2 -- Mix-IT 2013

Annotation @DelegatesTo

• Utiliser Target pour préciser à qui déléguer

void  exec(ExecSpec  sp,  Closure  c)  {        c.delegate  =  sp        c()}

Page 114: Les nouveautés de Groovy 2 -- Mix-IT 2013

Annotation @DelegatesTo

• Utiliser Target pour préciser à qui déléguer

void  exec(ExecSpec  sp,  Closure  c)  {        c.delegate  =  sp        c()}

@DelegatesTo.Target(‘‘id’’)

Page 115: Les nouveautés de Groovy 2 -- Mix-IT 2013

Annotation @DelegatesTo

• Utiliser Target pour préciser à qui déléguer

void  exec(ExecSpec  sp,  Closure  c)  {        c.delegate  =  sp        c()}

@DelegatesTo.Target(‘‘id’’) @DelegatesTo(target = ‘‘id’’)

Page 116: Les nouveautés de Groovy 2 -- Mix-IT 2013

Annotation @DelegatesTo

• Intéressant surtout pour les DSLs utilisation la délégation d’appel dans les closures

• Excellent pour...• documenter les APIs• l’intégration avec l’IDE• complétion de code, navigation...

• fonctionne avec la vérification statique et la compilation statique

Page 117: Les nouveautés de Groovy 2 -- Mix-IT 2013

Etendre le vérificateur

Pour aller plus loin que Java lui même

Page 118: Les nouveautés de Groovy 2 -- Mix-IT 2013

Etendre le vérificateur statique de type

• Etendre le vérificateur pour le rendre encore plus intelligent !

• voire même plus intelligent que celui de Java :-)

• En créant sa propre extension

@TypeChecked(extensions  =                            'MyExtension.groovy')void  exec()  {        //  code  to  be  further  checked...}

Page 119: Les nouveautés de Groovy 2 -- Mix-IT 2013

Etendre le vérificateur statique de type

• Etendre le vérificateur pour le rendre encore plus intelligent !

• voire même plus intelligent que celui de Java :-)

• En créant sa propre extension

@TypeChecked(extensions  =                            'MyExtension.groovy')void  exec()  {        //  code  to  be  further  checked...}

On pourra créer une méta-annotation

Page 120: Les nouveautés de Groovy 2 -- Mix-IT 2013

• Aider le vérificateur lorsque...

• impossible d’inférer un type

• aucune méthode trouvée

• pas d’attribut trouvé

• assignation incorrecte

Etendre le vérificateur statique de type

Page 121: Les nouveautés de Groovy 2 -- Mix-IT 2013

• Votre extension a accès à une API orientée événement

Etendre le vérificateur statique de type

• onMethodSelection

• afterMethodCall• beforeMethodCall

• afterVisitMethod• beforeVisitMethod• methodNotFound

• unresolvedVariable• unresolvedProperty• unresolvedAttribute

• incompatibleAssignment

Page 122: Les nouveautés de Groovy 2 -- Mix-IT 2013

Etendre le vérificateur statique de type

onMethodSelection  {  expr,  method  -­‐>  ...  }afterMethodCall  {  mc  -­‐>  ...  }unresolvedVariable  {  var  -­‐>  ...  }methodNotFound  {  receiver,  name,  argList,  argTypes,  call  -­‐>  ...  }incompatibleAssignment  {  lhsType,  rhsType,  expr  -­‐>  ...  }

Page 123: Les nouveautés de Groovy 2 -- Mix-IT 2013

Etendre le vérificateur statique de type

onMethodSelection  {  expr,  method  -­‐>  ...  }afterMethodCall  {  mc  -­‐>  ...  }unresolvedVariable  {  var  -­‐>  ...  }methodNotFound  {  receiver,  name,  argList,  argTypes,  call  -­‐>  ...  }incompatibleAssignment  {  lhsType,  rhsType,  expr  -­‐>  ...  }

MyExtension.groovy

Page 124: Les nouveautés de Groovy 2 -- Mix-IT 2013

Etendre le vérificateur statique de type

onMethodSelection  {  expr,  method  -­‐>  ...  }afterMethodCall  {  mc  -­‐>  ...  }unresolvedVariable  {  var  -­‐>  ...  }methodNotFound  {  receiver,  name,  argList,  argTypes,  call  -­‐>  ...  }incompatibleAssignment  {  lhsType,  rhsType,  expr  -­‐>  ...  }

MyExtension.groovy

Apprenez votre AST Groovy !

Page 125: Les nouveautés de Groovy 2 -- Mix-IT 2013

Etendre le vérificateur statique de type

onMethodSelection  {  expr,  method  -­‐>  ...  }afterMethodCall  {  mc  -­‐>  ...  }unresolvedVariable  {  var  -­‐>  ...  }methodNotFound  {  receiver,  name,  argList,  argTypes,  call  -­‐>  ...  }incompatibleAssignment  {  lhsType,  rhsType,  expr  -­‐>  ...  }

MyExtension.groovy

Apprenez votre AST Groovy !

Pas besoin d’être compilé

Page 126: Les nouveautés de Groovy 2 -- Mix-IT 2013

• Quelques exemples...

• Vérifier qu’une chaîne représentant une requête SQL est valide

• Vérifier le type des arguments passés à sprintf() avec le pattern de la chaîne

Etendre le vérificateur statique de type

Page 127: Les nouveautés de Groovy 2 -- Mix-IT 2013

Configurer le compilateur

Classe de script de baseScript de configuration

DSL de configuration

Page 128: Les nouveautés de Groovy 2 -- Mix-IT 2013

Customiser le compilateur

• Groovy 1.8 a introduit la notion de « customizer »

• rajouter des imports transparents• appliquer des transformations d’AST• filtrer / sécuriser les scripts

• Avec le « static type checker » et la « compilation statique », on nous a demandé s’il était possible de les appliquer par défaut

Page 129: Les nouveautés de Groovy 2 -- Mix-IT 2013

Customiser le compilateur

• Nouvelles options

• --basescript pour définir une classe de base pour les scripts

• --configscript pour indiquer un script qui va configurer CompilerConfiguration

Page 130: Les nouveautés de Groovy 2 -- Mix-IT 2013

Customiser le compilateur

• Rajouter la transformation @ToString

•import  groovy.transform.ToStringimport  org.codehaus.groovy.control.customizers              .ASTTransformationCustomizer

configuration.addCompilationCustomizer(        new  ASTTransformationCustomizer(ToString))

Page 131: Les nouveautés de Groovy 2 -- Mix-IT 2013

Customiser le compilateur

• Rajouter la transformation @ToString

•import  groovy.transform.ToStringimport  org.codehaus.groovy.control.customizers              .ASTTransformationCustomizer

configuration.addCompilationCustomizer(        new  ASTTransformationCustomizer(ToString))

Instance de CompilerConfigurationinjectée par défaut

Page 132: Les nouveautés de Groovy 2 -- Mix-IT 2013

Customiser le compilateur

• Un petit DSL pour simplifier la configurationconfiguration.customizers  {        //  apply  to  MyBean.groovy        source(basename:  'MyBean')  {                ast(ToString)        }}

Page 133: Les nouveautés de Groovy 2 -- Mix-IT 2013

Customiser le compilateur

• Un petit DSL pour simplifier la configurationconfiguration.customizers  {        //  apply  to  MyBean.groovy        source(basename:  'MyBean')  {                ast(ToString)        }}

configuration.customizers  {        //  apply  to  *.gbean  files        source(extension:  '.gbean')  {                ast(ToString)        }}

Page 134: Les nouveautés de Groovy 2 -- Mix-IT 2013

Customiser le compilateur

• Un petit DSL pour simplifier la configurationconfiguration.customizers  {        //  apply  to  MyBean.groovy        source(basename:  'MyBean')  {                ast(ToString)        }}

configuration.customizers  {        //  apply  to  *.gbean  files        source(extension:  '.gbean')  {                ast(ToString)        }}

configuration.customizers  {        //  custom  filter  logic        source(unitValidator:  {  unit  -­‐>  ...  })  {                ast(ToString)                imports  {                        staticStar  'java.lang.Math'                }        }}

Page 135: Les nouveautés de Groovy 2 -- Mix-IT 2013

Pour en savoir plus...Groovy 2.0http://groovy.codehaus.org/Groovy+2.0+release+notes

Groovy 2.1http://groovy.codehaus.org/Groovy+2.1+release+notes

Page 136: Les nouveautés de Groovy 2 -- Mix-IT 2013

Et après ?Groovy 3 !

Nouveau « MOP »Nouvelle grammaire Antlr v4Support des lambdas de Java 8

Page 137: Les nouveautés de Groovy 2 -- Mix-IT 2013

Parlons un peu de roadmap...

2014 2014 20132012

Groovy 2.1

Groovy 3.0Groovy 2.0

Page 138: Les nouveautés de Groovy 2 -- Mix-IT 2013

Parlons un peu de roadmap...

2014 2014 20132012

Groovy 2.1

Groovy 3.0Groovy 2.0

Page 139: Les nouveautés de Groovy 2 -- Mix-IT 2013

Parlons un peu de roadmap...

2014 2014 20132012

Groovy 2.1

Groovy 3.0Groovy 2.0

Page 140: Les nouveautés de Groovy 2 -- Mix-IT 2013

MOP

2

Page 141: Les nouveautés de Groovy 2 -- Mix-IT 2013

GrammaireAntlr 4

Page 142: Les nouveautés de Groovy 2 -- Mix-IT 2013

λLambdas

JDK 8

Page 143: Les nouveautés de Groovy 2 -- Mix-IT 2013
Page 144: Les nouveautés de Groovy 2 -- Mix-IT 2013

Conclusion — 1/2

• Un écosystème riche et fleurissant

• Groovy 2.0• plus de modularité• un thème « statique »• vérification statique de type• compilation statique

• un thème JDK 7• support de invoke dynamic• syntaxe project coin

Page 145: Les nouveautés de Groovy 2 -- Mix-IT 2013

Conclusion — 2/2

• Groovy 2.1• support complet de invoke dynamic• @DelegatesTo• extension du type checker pour les DSLSs• méta-annotations

• Et au-delà... • un nouveau MOP (Meta-Object Protocol)• une nouvelle grammaire avec Antlr v4• le support des lambdas de JDK 8

Page 146: Les nouveautés de Groovy 2 -- Mix-IT 2013

Questions & Réponses

Page 147: Les nouveautés de Groovy 2 -- Mix-IT 2013

N’oubliez pas l’atelier...

Groovy, les mains dans le cambouis

14h30 — 16h00 / Salle Dijkstra

Page 148: Les nouveautés de Groovy 2 -- Mix-IT 2013

Merci ! @glaforge

http://glaforge.appspot.com http://gplus.to/glaforge

Page 149: Les nouveautés de Groovy 2 -- Mix-IT 2013

Crédits images• cerisier

http://wallpaperswide.com/cherry_blossom_3-wallpapers.html

• NKOTBhttp://images1.fanpop.com/images/photos/2300000/nkotb-new-kids-on-the-block-2314664-1280-960.jpg

• tomateshttp://www.infoescola.com/wp-content/uploads/2011/01/tomate.jpg

• patateshttp://toooof.free.fr/blogs/captainslip/screenshots/pommes_de_terre.jpg

• canardhttp://www.objets-publicitaires-pro.com/images/objet-publicitaire/produit/large/canard-geant-a-personnaliser-jaune.jpg

• grincheuxhttps://si0.twimg.com/profile_images/3115998027/b47c180a703a5ffa7d1437a66f545dc0.jpeg

• singehttp://static.ddmcdn.com/gif/how-to-draw-animals-31.jpg

• warninghttp://th07.deviantart.net/fs71/PRE/i/2012/261/8/6/warning_gangnam_style_zone_by_untoucheddesigns-d5f6bal.png

• coyotehttp://nittygriddy.com/wp-content/uploads/2011/01/Wiley-Coyote-Help.jpg

• ringhttp://img.banggood.com/images/upload/2012/limin/SKU028431_11.JPG

• magnifying glasshttp://www.renders-graphiques.fr/image/upload/normal/loupe.png

• chronomètrehttp://www.moineau-instruments.com/59-thickbox/chronometre-mecanique-1-10-t15-mn-2-fonctions.jpg

• that’s all folkshttp://4.bp.blogspot.com/-wJxosualm48/T4M_spcUUjI/AAAAAAAAB8E/njfLjNZQdsc/s1600/thats-all-folks.jpg

• MOPhttp://imagethumbnails.milo.com/024/913/894/trimmed/24913521_25989894_trimmed.jpg

• grammarhttp://edudemic.com/wp-content/uploads/2012/11/connected-learner-grammar.jpg