SlideShare uma empresa Scribd logo
1 de 149
Baixar para ler offline
Les nouveautés
de Groovy 2
GuillaumeLaforge
Groovy Project Manager
SpringSource / VMware
GuillaumeLaforge
@glaforge 
http://glaforge.appspot.com 
http://gplus.to/glaforge 
Langage dynamique
optionnellement typé
Groovy
...statiquement vérifié
et compilé
Groovy
syntaxe dérivant de Java :
facile à apprendre !
Groovy
1.7 million
downloads
Ablossoming
Ecosystem
GVM
GVM
GVM
GROOVY
ENVIRONMENT
MANAGER
GVM:GroovyenVironmentManager
• 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
Commençons
par Groovy2.0
Modularity
Java 7: ProjectCoin & invokedynamic
Static typechecking & compilation
Modularité
« Tout le monde n’a pas besoin de tout,
tout le temps, en même temps ! »
LamodularitédeGroovy
• 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
LesnouveauxJARs
• 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
LesnouveauxJARs
• 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
« Fais ton
marché »
Lesmodulesd’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")
Lesmodulesd’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
Lesmodulesd’extension
• Créer sa propre extension
• contribuer des méthodes statiques
package	
  foo
class	
  StaticStringExtension	
  {
	
  	
  	
  	
  static	
  hi(String	
  self)	
  {
	
  	
  	
  	
  	
  	
  	
  	
  "Hi!"
	
  	
  	
  	
  }
}
//	
  usage:	
  String.hi()
Descripteurdesmodulesd’extension
• META-INF/
• services/
• org.codehaus.groovy.runtime.ExtensionModule
moduleName	
  =	
  stringExtensions
moduleVersion	
  =	
  1.0
//	
  liste	
  de	
  noms	
  de	
  classe	
  séparées	
  par	
  des	
  virgules
extensionClasses	
  =	
  foo.StringExtension
//	
  liste	
  de	
  noms	
  de	
  classe	
  séparées	
  par	
  des	
  virgules
staticExtensionClasses	
  =	
  foo.StaticStringExtension
Thème Java 7
Syntaxe de « Project Coin »
Support d’invoke dynamic
Une histoire de
canard...
Littérauxbinaires
• En plus de décimal, octal, et héxa...
• On a une représentation binaire :
int	
  x	
  =	
  0b10101111
assert	
  x	
  ==	
  175
	
  
byte	
  aByte	
  =	
  0b00100001
assert	
  aByte	
  ==	
  33
	
  
int	
  anInt	
  =	
  0b1010000101000101
assert	
  anInt	
  ==	
  41285
Les«underscores»dansleslittéraux
• Utilisation des « underscores » pour séparer
les unités au choix
long	
  creditCardNumber	
  =	
  1234_5678_9012_3456L
long	
  socialSecurityNumbers	
  =	
  999_99_9999L
float	
  monetaryAmount	
  =	
  12_345_132.12
long	
  hexBytes	
  =	
  0xFF_EC_DE_5E
long	
  hexWords	
  =	
  0xFFEC_DE5E
long	
  maxLong	
  =	
  0x7fff_ffff_ffff_ffffL
long	
  alsoMaxLong	
  =	
  9_223_372_036_854_775_807L
long	
  bytes	
  =	
  0b11010010_01101001_10010100_10010010
Catchd’exceptionsmultiples
• Un seul bloc catch pour plusieurs
exceptions, plutôt que dupliquer les blocs
try	
  {
	
  	
  	
  	
  /*	
  ...	
  */
}	
  catch(IOException	
  |	
  NullPointerException	
  e)	
  {
	
  	
  	
  	
  /*	
  un	
  seul	
  bloc	
  */
}
Coin-Coin !
Supportd’invokedynamicdeJDK7
• 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
Thème « statique »
Vérification statique de type
Compilation statique
Vérificationstatiquesdetype
• But : rendre le compilateur « grincheux » !
• jeter des erreurs à la compilation
• et non pas au runtime !
Tout le monde n’a pas
besoin de dynamique
tout le temps !
Tout le monde n’a pas
besoin de dynamique
tout le temps !
Nah !
Vérificationstatiquedetype
• 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
Vérificationstatiquedetype
• Le compilateur doit inférer les types...
• moins besoin de types explicites et de casts
• inférence fine
• « flow typing »
• « lowest upper bound »
Vérificationstatiquedetype
• 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
Fautesdefrappe
import	
  groovy.transform.TypeChecked
	
  
void	
  method()	
  {}
	
  
@TypeChecked	
  test()	
  {
	
  	
  	
  	
  //	
  Cannot	
  find	
  matching	
  method	
  metthhoood()
	
  	
  	
  	
  metthhoood()
	
  
	
  	
  	
  	
  def	
  name	
  =	
  "Guillaume"
	
  	
  	
  	
  //	
  variable	
  naamme	
  is	
  undeclared
	
  	
  	
  	
  println	
  naamme
}
Fautesdefrappe
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
Fautesdefrappe
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
Fautesdefrappe
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
Mauvaisesaffectationsdevariable
//	
  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	
  =	
  0
i	
  +=	
  '1'
Mauvaisesaffectationsdevariable
//	
  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	
  =	
  0
i	
  +=	
  '1'
Erreurs de
compilation
Mauvaisesaffectationsdevariable
//	
  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	
  =	
  0
i	
  +=	
  '1'
Erreurs de
compilation
Erreurs de
compilation
Mauvaisesaffectationsdevariable
//	
  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	
  =	
  0
i	
  +=	
  '1'
Erreurs de
compilation
Erreurs de
compilation
Erreurs de
compilation
Mauvaistypederetour
//	
  checks	
  if/else	
  branch	
  return	
  values
@TypeChecked
int	
  method()	
  {
	
  	
  	
  	
  if	
  (true)	
  {	
  'String'	
  }
	
  	
  	
  	
  else	
  {	
  42	
  }
}
//	
  works	
  for	
  switch/case	
  &	
  try/catch/finally
	
  
//	
  transparent	
  toString()	
  implied
@TypeChecked
String	
  greeting(String	
  name)	
  {
	
  	
  	
  	
  def	
  sb	
  =	
  new	
  StringBuilder()
	
  	
  	
  	
  sb	
  <<	
  "Hi	
  "	
  <<	
  name
}
Mauvaistypederetour
//	
  checks	
  if/else	
  branch	
  return	
  values
@TypeChecked
int	
  method()	
  {
	
  	
  	
  	
  if	
  (true)	
  {	
  'String'	
  }
	
  	
  	
  	
  else	
  {	
  42	
  }
}
//	
  works	
  for	
  switch/case	
  &	
  try/catch/finally
	
  
//	
  transparent	
  toString()	
  implied
@TypeChecked
String	
  greeting(String	
  name)	
  {
	
  	
  	
  	
  def	
  sb	
  =	
  new	
  StringBuilder()
	
  	
  	
  	
  sb	
  <<	
  "Hi	
  "	
  <<	
  name
}
Erreur de
compilation
Mauvaistypederetour
//	
  checks	
  if/else	
  branch	
  return	
  values
@TypeChecked
int	
  method()	
  {
	
  	
  	
  	
  if	
  (true)	
  {	
  'String'	
  }
	
  	
  	
  	
  else	
  {	
  42	
  }
}
//	
  works	
  for	
  switch/case	
  &	
  try/catch/finally
	
  
//	
  transparent	
  toString()	
  implied
@TypeChecked
String	
  greeting(String	
  name)	
  {
	
  	
  	
  	
  def	
  sb	
  =	
  new	
  StringBuilder()
	
  	
  	
  	
  sb	
  <<	
  "Hi	
  "	
  <<	
  name
}
Erreur de
compilation
Au final, appèle le
toString() de
StringBuilder
Inférencedetype
@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
	
  	
  	
  	
  }
}
Inférencedetype
@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
Inférencedetype
@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é
Inférencedetype
@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é
Inférencedetype
@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é
Mélangerdynamiqueetstatiquementvérifié
@TypeChecked
String	
  greeting(String	
  name)	
  {
	
  	
  	
  	
  //	
  call	
  method	
  with	
  dynamic	
  behavior
	
  	
  	
  	
  //	
  but	
  with	
  proper	
  signature
	
  	
  	
  	
  generateMarkup(name.toUpperCase())
}
	
  
//	
  usual	
  dynamic	
  behavior
String	
  generateMarkup(String	
  name)	
  {
	
  	
  	
  	
  def	
  sw	
  =	
  new	
  StringWriter()
	
  	
  	
  	
  new	
  MarkupBuilder(sw).html	
  {
	
  	
  	
  	
  	
  	
  	
  	
  body	
  {
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  div	
  name
	
  	
  	
  	
  	
  	
  	
  	
  }
	
  	
  	
  	
  }
	
  	
  	
  	
  sw.toString()
}
Mélangerdynamiqueetstatiquementvérifié
@TypeChecked
String	
  greeting(String	
  name)	
  {
	
  	
  	
  	
  //	
  call	
  method	
  with	
  dynamic	
  behavior
	
  	
  	
  	
  //	
  but	
  with	
  proper	
  signature
	
  	
  	
  	
  generateMarkup(name.toUpperCase())
}
	
  
//	
  usual	
  dynamic	
  behavior
String	
  generateMarkup(String	
  name)	
  {
	
  	
  	
  	
  def	
  sw	
  =	
  new	
  StringWriter()
	
  	
  	
  	
  new	
  MarkupBuilder(sw).html	
  {
	
  	
  	
  	
  	
  	
  	
  	
  body	
  {
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  div	
  name
	
  	
  	
  	
  	
  	
  	
  	
  }
	
  	
  	
  	
  }
	
  	
  	
  	
  sw.toString()
}
Statiquement vérifié
Mélangerdynamiqueetstatiquementvérifié
@TypeChecked
String	
  greeting(String	
  name)	
  {
	
  	
  	
  	
  //	
  call	
  method	
  with	
  dynamic	
  behavior
	
  	
  	
  	
  //	
  but	
  with	
  proper	
  signature
	
  	
  	
  	
  generateMarkup(name.toUpperCase())
}
	
  
//	
  usual	
  dynamic	
  behavior
String	
  generateMarkup(String	
  name)	
  {
	
  	
  	
  	
  def	
  sw	
  =	
  new	
  StringWriter()
	
  	
  	
  	
  new	
  MarkupBuilder(sw).html	
  {
	
  	
  	
  	
  	
  	
  	
  	
  body	
  {
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  div	
  name
	
  	
  	
  	
  	
  	
  	
  	
  }
	
  	
  	
  	
  }
	
  	
  	
  	
  sw.toString()
}
Statiquement vérifié
Dynamique
Vérificationsparinstanceof
@TypeChecked	
  
void	
  test(Object	
  val)	
  {
	
  	
  	
  	
  if	
  (val	
  instanceof	
  String)	
  {
	
  	
  	
  	
  	
  	
  	
  	
  println	
  val.toUpperCase()
	
  	
  	
  	
  }	
  else	
  if	
  (val	
  instanceof	
  Number)	
  {
	
  	
  	
  	
  	
  	
  	
  	
  println	
  "X"	
  *	
  val.intValue()
	
  	
  	
  	
  }
}
Vérificationsparinstanceof
@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
Vérificationsparinstanceof
@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
Vérificationsparinstanceof
@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)
LowestUpperBound
• Le plus petit « super » type commun
• peut-être virtuel (« non-dénotable »)
@TypeChecked	
  test()	
  {
	
  	
  	
  	
  //	
  an	
  integer	
  and	
  a	
  BigDecimal
	
  	
  	
  	
  return	
  [1234,	
  3.14]
}
LowestUpperBound
• 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>
Flowtyping
• 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	
  !
}
Pô très clean ton code,
non mais allô quoi ?
Pô très clean ton code,
non mais allô quoi ?
Ben non !
Vérificationstatiqueetcodedynamique
• 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
Pasdemétaprogrammationdynamique
@TypeChecked	
  
void	
  test()	
  {
	
  	
  	
  	
  Integer.metaClass.foo	
  =	
  {}
	
  	
  	
  	
  123.foo()
}
Pasdemétaprogrammationdynamique
@TypeChecked	
  
void	
  test()	
  {
	
  	
  	
  	
  Integer.metaClass.foo	
  =	
  {}
	
  	
  	
  	
  123.foo()
}
Accès au champ
dynamique
metaClass interdit
Pasdemétaprogrammationdynamique
@TypeChecked	
  
void	
  test()	
  {
	
  	
  	
  	
  Integer.metaClass.foo	
  =	
  {}
	
  	
  	
  	
  123.foo()
}
Accès au champ
dynamique
metaClass interditMéthode non
reconnue
Typeexplicitepourlesparamètresdeclosure
@TypeChecked	
  test()	
  {
	
  	
  	
  	
  ["a",	
  "b",	
  "c"].collect	
  {
	
  	
  	
  	
  	
  	
  	
  	
  it.toUpperCase()	
  //	
  Pas	
  d’accord	
  !
	
  	
  	
  	
  }
}
Typeexplicitepourlesparamètresdeclosure
@TypeChecked	
  test()	
  {
	
  	
  	
  	
  ["a",	
  "b",	
  "c"].collect	
  {	
  String	
  it	
  -­‐>
	
  	
  	
  	
  	
  	
  	
  	
  it.toUpperCase()	
  //	
  OK,	
  une	
  String
	
  	
  	
  	
  }
}
Typeexplicitepourlesparamètresdeclosure
@TypeChecked	
  test()	
  {
	
  	
  	
  	
  ["a",	
  "b",	
  "c"].collect	
  {	
  String	
  it	
  -­‐>
	
  	
  	
  	
  	
  	
  	
  	
  it.toUpperCase()	
  //	
  OK,	
  une	
  String
	
  	
  	
  	
  }
}
Obligé d’indiquer le
type explicitement
Typeexplicitepourlesparamètresdeclosure
@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 !
Mais si c’est pô dynamique,
on peut compiler
statiquement ?
Mais si c’est pô dynamique,
on peut compiler
statiquement ?
Ben oui !
Compilationstatique
• 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
Avantagesdelacompilationstatique
• 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
Ouais, ch’fais
c’que j’veux
avec ton code
Ouais, ch’fais
c’que j’veux
avec ton code
Niark !
Inconvénientsdelacompilationstatique
• 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
Mixercompilationstatiqueetcodedynamique
@CompileStatic
String	
  greeting(String	
  name)	
  {
	
  	
  	
  	
  //	
  call	
  method	
  with	
  dynamic	
  behavior
	
  	
  	
  	
  //	
  but	
  with	
  proper	
  signature
	
  	
  	
  	
  generateMarkup(name.toUpperCase())
}
	
  
//	
  usual	
  dynamic	
  behavior
String	
  generateMarkup(String	
  name)	
  {
	
  	
  	
  	
  def	
  sw	
  =	
  new	
  StringWriter()
	
  	
  	
  	
  new	
  MarkupBuilder(sw).html	
  {
	
  	
  	
  	
  	
  	
  	
  	
  body	
  {
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  div	
  name
	
  	
  	
  	
  	
  	
  	
  	
  }
	
  	
  	
  	
  }
	
  	
  	
  	
  sw.toString()
}
Mixercompilationstatiqueetcodedynamique
@CompileStatic
String	
  greeting(String	
  name)	
  {
	
  	
  	
  	
  //	
  call	
  method	
  with	
  dynamic	
  behavior
	
  	
  	
  	
  //	
  but	
  with	
  proper	
  signature
	
  	
  	
  	
  generateMarkup(name.toUpperCase())
}
	
  
//	
  usual	
  dynamic	
  behavior
String	
  generateMarkup(String	
  name)	
  {
	
  	
  	
  	
  def	
  sw	
  =	
  new	
  StringWriter()
	
  	
  	
  	
  new	
  MarkupBuilder(sw).html	
  {
	
  	
  	
  	
  	
  	
  	
  	
  body	
  {
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  div	
  name
	
  	
  	
  	
  	
  	
  	
  	
  }
	
  	
  	
  	
  }
	
  	
  	
  	
  sw.toString()
}
Statiquement compilé
Mixercompilationstatiqueetcodedynamique
@CompileStatic
String	
  greeting(String	
  name)	
  {
	
  	
  	
  	
  //	
  call	
  method	
  with	
  dynamic	
  behavior
	
  	
  	
  	
  //	
  but	
  with	
  proper	
  signature
	
  	
  	
  	
  generateMarkup(name.toUpperCase())
}
	
  
//	
  usual	
  dynamic	
  behavior
String	
  generateMarkup(String	
  name)	
  {
	
  	
  	
  	
  def	
  sw	
  =	
  new	
  StringWriter()
	
  	
  	
  	
  new	
  MarkupBuilder(sw).html	
  {
	
  	
  	
  	
  	
  	
  	
  	
  body	
  {
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  div	
  name
	
  	
  	
  	
  	
  	
  	
  	
  }
	
  	
  	
  	
  }
	
  	
  	
  	
  sw.toString()
}
Statiquement compilé
Dynamique
Mixercompilationstatiqueetcodedynamique
@CompileStatic
String	
  greeting(String	
  name)	
  {
	
  	
  	
  	
  //	
  call	
  method	
  with	
  dynamic	
  behavior
	
  	
  	
  	
  //	
  but	
  with	
  proper	
  signature
	
  	
  	
  	
  generateMarkup(name.toUpperCase())
}
	
  
//	
  usual	
  dynamic	
  behavior
String	
  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
Mixercompilationstatiqueetcodedynamique
@CompileStatic
String	
  greeting(String	
  name)	
  {
	
  	
  	
  	
  //	
  call	
  method	
  with	
  dynamic	
  behavior
	
  	
  	
  	
  //	
  but	
  with	
  proper	
  signature
	
  	
  	
  	
  generateMarkup(name.toUpperCase())
}
	
  
//	
  usual	
  dynamic	
  behavior
String	
  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 !
Etlaperformancedanstoutça?
• Comparaisons entre :
• Java
• Groovy
• avec compilation statique — Groovy 2.0
• avec optimisations types primitifs — Groovy 1.8+
• sans optimisation — Groovy 1.7
Etlaperformancedanstoutça?
Fibonacci
Pi (π)
quadrature
Binary
trees
Java
Static
compilation
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 s
1.71.82.x
...maintenant
Groovy2.1
Support complet d’invoke dynamic
Méta-annotations
Configuration avancée du compilateur
Extensions du typechecker
Invoke Dynamic
Support complet
de Invoke Dynamic
Supportcompletd’invokedynamic
• 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 »
Méta-annotations
Un annotation pour
les gouverner toutes !
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
Méta-annotations
@Immutable
@ToString(excludes	
  =	
  ["age"])
@AnnotationCollector
@interface	
  MyAlias	
  {}
Méta-annotations
@Immutable
@ToString(excludes	
  =	
  ["age"])
@AnnotationCollector
@interface	
  MyAlias	
  {}
Annotations collectées
Méta-annotations
@Immutable
@ToString(excludes	
  =	
  ["age"])
@AnnotationCollector
@interface	
  MyAlias	
  {}
Annotations collectées
Le collecteur
Méta-annotations
@Immutable
@ToString(excludes	
  =	
  ["age"])
@AnnotationCollector
@interface	
  MyAlias	
  {}
Annotations collectées
Le collecteur
Votre propre alias
d’annotation
Méta-annotations
@Immutable
@ToString(excludes	
  =	
  ["age"])
@AnnotationCollector
@interface	
  MyAlias	
  {}
@MyAlias
class	
  Foo	
  {
	
  	
  	
  	
  String	
  name
	
  	
  	
  	
  int	
  age
}
Annotations collectées
Le collecteur
Votre propre alias
d’annotation
Méta-annotations
@Immutable
@ToString(excludes	
  =	
  ["age"])
@AnnotationCollector
@interface	
  MyAlias	
  {}
@MyAlias
class	
  Foo	
  {
	
  	
  	
  	
  String	
  name
	
  	
  	
  	
  int	
  age
}
Annotations collectées
Le collecteur
Votre propre alias
d’annotation
Utilisez votre
méta-annotation
L’annotation
@DelegatesTo
Améliorer l’outillage
pour le support des
Domain-Specific Languages
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'
}
Annotation@DelegatesTo
exec(spec)	
  {
	
  	
  	
  	
  foo()
}
Annotation@DelegatesTo
class	
  ExecSpec	
  {
	
  	
  	
  	
  void	
  foo()
}
exec(spec)	
  {
	
  	
  	
  	
  foo()
}
Annotation@DelegatesTo
class	
  ExecSpec	
  {
	
  	
  	
  	
  void	
  foo()
}
void	
  exec(ExecSpec	
  sp,	
  Closure	
  c)	
  {
	
  	
  	
  	
  c.delegate	
  =	
  sp
	
  	
  	
  	
  c()
}
exec(spec)	
  {
	
  	
  	
  	
  foo()
}
Annotation@DelegatesTo
class	
  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()
Annotation@DelegatesTo
class	
  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()
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()
}
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)
Annotation@DelegatesTo
• Utiliser Target pour préciser à qui déléguer
void	
  exec(ExecSpec	
  sp,	
  Closure	
  c)	
  {
	
  	
  	
  	
  c.delegate	
  =	
  sp
	
  	
  	
  	
  c()
}
Annotation@DelegatesTo
• Utiliser Target pour préciser à qui déléguer
void	
  exec(ExecSpec	
  sp,	
  Closure	
  c)	
  {
	
  	
  	
  	
  c.delegate	
  =	
  sp
	
  	
  	
  	
  c()
}
@DelegatesTo.Target(‘‘id’’)
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’’)
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
Etendre le
vérificateur
Pour aller plus loin
que Java lui même
Etendrelevérificateurstatiquedetype
• 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...
}
Etendrelevérificateurstatiquedetype
• 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
• Aider le vérificateur lorsque...
• impossible d’inférer un type
• aucune méthode trouvée
• pas d’attribut trouvé
• assignation incorrecte
Etendrelevérificateurstatiquedetype
• Votre extension a accès à
une API orientée événement
Etendrelevérificateurstatiquedetype
• onMethodSelection
• afterMethodCall
• beforeMethodCall
• afterVisitMethod
• beforeVisitMethod
• methodNotFound
• unresolvedVariable
• unresolvedProperty
• unresolvedAttribute
• incompatibleAssignment
Etendrelevérificateurstatiquedetype
onMethodSelection	
  {	
  expr,	
  method	
  -­‐>	
  ...	
  }
afterMethodCall	
  {	
  mc	
  -­‐>	
  ...	
  }
unresolvedVariable	
  {	
  var	
  -­‐>	
  ...	
  }
methodNotFound	
  {	
  receiver,	
  name,	
  argList,	
  argTypes,	
  call	
  -­‐>	
  ...	
  }
incompatibleAssignment	
  {	
  lhsType,	
  rhsType,	
  expr	
  -­‐>	
  ...	
  }
Etendrelevérificateurstatiquedetype
onMethodSelection	
  {	
  expr,	
  method	
  -­‐>	
  ...	
  }
afterMethodCall	
  {	
  mc	
  -­‐>	
  ...	
  }
unresolvedVariable	
  {	
  var	
  -­‐>	
  ...	
  }
methodNotFound	
  {	
  receiver,	
  name,	
  argList,	
  argTypes,	
  call	
  -­‐>	
  ...	
  }
incompatibleAssignment	
  {	
  lhsType,	
  rhsType,	
  expr	
  -­‐>	
  ...	
  }
MyExtension.groovy
Etendrelevérificateurstatiquedetype
onMethodSelection	
  {	
  expr,	
  method	
  -­‐>	
  ...	
  }
afterMethodCall	
  {	
  mc	
  -­‐>	
  ...	
  }
unresolvedVariable	
  {	
  var	
  -­‐>	
  ...	
  }
methodNotFound	
  {	
  receiver,	
  name,	
  argList,	
  argTypes,	
  call	
  -­‐>	
  ...	
  }
incompatibleAssignment	
  {	
  lhsType,	
  rhsType,	
  expr	
  -­‐>	
  ...	
  }
MyExtension.groovy
Apprenez votre
AST Groovy !
Etendrelevérificateurstatiquedetype
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é
• 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
Etendrelevérificateurstatiquedetype
Configurer le
compilateur
Classe de script de base
Script de configuration
DSL de configuration
Customiserlecompilateur
• 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
Customiserlecompilateur
• Nouvelles options
• --basescript
pour définir une classe de base pour les scripts
• --configscript
pour indiquer un script qui va configurer
CompilerConfiguration
Customiserlecompilateur
• Rajouter la transformation @ToString
•
import	
  groovy.transform.ToString
import	
  org.codehaus.groovy.control.customizers
	
  	
  	
  	
  	
  	
  	
  .ASTTransformationCustomizer
configuration.addCompilationCustomizer(
	
  	
  	
  	
  new	
  ASTTransformationCustomizer(ToString)
)
Customiserlecompilateur
• Rajouter la transformation @ToString
•
import	
  groovy.transform.ToString
import	
  org.codehaus.groovy.control.customizers
	
  	
  	
  	
  	
  	
  	
  .ASTTransformationCustomizer
configuration.addCompilationCustomizer(
	
  	
  	
  	
  new	
  ASTTransformationCustomizer(ToString)
)
Instance de CompilerConfiguration
injectée par défaut
Customiserlecompilateur
• Un petit DSL pour simplifier la configuration
configuration.customizers	
  {
	
  	
  	
  	
  //	
  apply	
  to	
  MyBean.groovy
	
  	
  	
  	
  source(basename:	
  'MyBean')	
  {
	
  	
  	
  	
  	
  	
  	
  	
  ast(ToString)
	
  	
  	
  	
  }
}
Customiserlecompilateur
• Un petit DSL pour simplifier la configuration
configuration.customizers	
  {
	
  	
  	
  	
  //	
  apply	
  to	
  MyBean.groovy
	
  	
  	
  	
  source(basename:	
  'MyBean')	
  {
	
  	
  	
  	
  	
  	
  	
  	
  ast(ToString)
	
  	
  	
  	
  }
}
configuration.customizers	
  {
	
  	
  	
  	
  //	
  apply	
  to	
  *.gbean	
  files
	
  	
  	
  	
  source(extension:	
  '.gbean')	
  {
	
  	
  	
  	
  	
  	
  	
  	
  ast(ToString)
	
  	
  	
  	
  }
}
Customiserlecompilateur
• Un petit DSL pour simplifier la configuration
configuration.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'
	
  	
  	
  	
  	
  	
  	
  	
  }
	
  	
  	
  	
  }
}
Pour en savoir plus...
Groovy2.0
http://groovy.codehaus.org/Groovy+2.0+release+notes
Groovy2.1
http://groovy.codehaus.org/Groovy+2.1+release+notes
Et après ?
Groovy3 !
Nouveau « MOP »
Nouvellegrammaire Antlr v4
Support des lambdasdeJava8
Parlonsunpeuderoadmap...
2014201420132012
Groovy 2.1
Groovy 3.0Groovy 2.0
Parlonsunpeuderoadmap...
2014201420132012
Groovy 2.1
Groovy 3.0Groovy 2.0
Parlonsunpeuderoadmap...
2014201420132012
Groovy 2.1
Groovy 3.0Groovy 2.0
MOP
2
Grammaire
Antlr4
λ
Lambdas
JDK
8
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
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
Questions&Réponses
N’oubliez pas l’atelier...
Groovy,lesmainsdanslecambouis
14h30 — 16h00 / Salle Dijkstra
Merci!
@glaforge 
http://glaforge.appspot.com 
http://gplus.to/glaforge 
Créditsimages
• cerisier
http://wallpaperswide.com/cherry_blossom_3-wallpapers.html
• NKOTB
http://images1.fanpop.com/images/photos/2300000/nkotb-new-kids-on-the-block-2314664-1280-960.jpg
• tomates
http://www.infoescola.com/wp-content/uploads/2011/01/tomate.jpg
• patates
http://toooof.free.fr/blogs/captainslip/screenshots/pommes_de_terre.jpg
• canard
http://www.objets-publicitaires-pro.com/images/objet-publicitaire/produit/large/canard-geant-a-personnaliser-jaune.jpg
• grincheux
https://si0.twimg.com/profile_images/3115998027/b47c180a703a5ffa7d1437a66f545dc0.jpeg
• singe
http://static.ddmcdn.com/gif/how-to-draw-animals-31.jpg
• warning
http://th07.deviantart.net/fs71/PRE/i/2012/261/8/6/warning_gangnam_style_zone_by_untoucheddesigns-d5f6bal.png
• coyote
http://nittygriddy.com/wp-content/uploads/2011/01/Wiley-Coyote-Help.jpg
• ring
http://img.banggood.com/images/upload/2012/limin/SKU028431_11.JPG
• magnifying glass
http://www.renders-graphiques.fr/image/upload/normal/loupe.png
• chronomètre
http://www.moineau-instruments.com/59-thickbox/chronometre-mecanique-1-10-t15-mn-2-fonctions.jpg
• that’s all folks
http://4.bp.blogspot.com/-wJxosualm48/T4M_spcUUjI/AAAAAAAAB8E/njfLjNZQdsc/s1600/thats-all-folks.jpg
• MOP
http://imagethumbnails.milo.com/024/913/894/trimmed/24913521_25989894_trimmed.jpg
• grammar
http://edudemic.com/wp-content/uploads/2012/11/connected-learner-grammar.jpg

Mais conteúdo relacionado

Mais procurados

Introduction à l’orienté objet en Python
Introduction à l’orienté objet en PythonIntroduction à l’orienté objet en Python
Introduction à l’orienté objet en PythonAbdoulaye Dieng
 
Chapitre6: Surcharge des opérateurs
Chapitre6:  Surcharge des opérateursChapitre6:  Surcharge des opérateurs
Chapitre6: Surcharge des opérateursAziz Darouichi
 
Initiation au code : Ateliers en C# (applications desktop et mobile native)
Initiation au code : Ateliers en C# (applications desktop et mobile native)Initiation au code : Ateliers en C# (applications desktop et mobile native)
Initiation au code : Ateliers en C# (applications desktop et mobile native)Stéphanie Hertrich
 
C++ Metaprogramming : multidimensional typelist
C++ Metaprogramming : multidimensional typelistC++ Metaprogramming : multidimensional typelist
C++ Metaprogramming : multidimensional typelistVincent Agnus
 
CocoaHeads Rennes #10 : Mock Objects
CocoaHeads Rennes #10 : Mock ObjectsCocoaHeads Rennes #10 : Mock Objects
CocoaHeads Rennes #10 : Mock ObjectsCocoaHeadsRNS
 
Csharp3 heritage-polymorphisme-interface
Csharp3 heritage-polymorphisme-interfaceCsharp3 heritage-polymorphisme-interface
Csharp3 heritage-polymorphisme-interfaceAbdoulaye Dieng
 
Formation C# - Cours 2 - Programmation procédurale
Formation C# - Cours 2 - Programmation procéduraleFormation C# - Cours 2 - Programmation procédurale
Formation C# - Cours 2 - Programmation procéduralekemenaran
 
Une introduction à Javascript et ECMAScript 6
Une introduction à Javascript et ECMAScript 6Une introduction à Javascript et ECMAScript 6
Une introduction à Javascript et ECMAScript 6Jean-Baptiste Vigneron
 
Csharp2 : classes et objets
Csharp2 : classes et objetsCsharp2 : classes et objets
Csharp2 : classes et objetsAbdoulaye Dieng
 
Chapitre 5 classes abstraites et interfaces
Chapitre 5  classes abstraites et interfacesChapitre 5  classes abstraites et interfaces
Chapitre 5 classes abstraites et interfacesAmir Souissi
 
Les fonctions lambdas en C++11 et C++14
Les fonctions lambdas en C++11 et C++14Les fonctions lambdas en C++11 et C++14
Les fonctions lambdas en C++11 et C++14Aurélien Regat-Barrel
 
Chapitre 4 heritage et polymorphisme
Chapitre 4 heritage et polymorphismeChapitre 4 heritage et polymorphisme
Chapitre 4 heritage et polymorphismeAmir Souissi
 
Chapitre5: Classes et objets
Chapitre5: Classes et objetsChapitre5: Classes et objets
Chapitre5: Classes et objetsAziz Darouichi
 
Javascript un langage supérieur
Javascript un langage supérieurJavascript un langage supérieur
Javascript un langage supérieurFredy Fadel
 

Mais procurados (20)

Introduction à l’orienté objet en Python
Introduction à l’orienté objet en PythonIntroduction à l’orienté objet en Python
Introduction à l’orienté objet en Python
 
Introduction à jQuery
Introduction à jQueryIntroduction à jQuery
Introduction à jQuery
 
Chapitre6: Surcharge des opérateurs
Chapitre6:  Surcharge des opérateursChapitre6:  Surcharge des opérateurs
Chapitre6: Surcharge des opérateurs
 
Initiation au code : Ateliers en C# (applications desktop et mobile native)
Initiation au code : Ateliers en C# (applications desktop et mobile native)Initiation au code : Ateliers en C# (applications desktop et mobile native)
Initiation au code : Ateliers en C# (applications desktop et mobile native)
 
C++ Metaprogramming : multidimensional typelist
C++ Metaprogramming : multidimensional typelistC++ Metaprogramming : multidimensional typelist
C++ Metaprogramming : multidimensional typelist
 
CocoaHeads Rennes #10 : Mock Objects
CocoaHeads Rennes #10 : Mock ObjectsCocoaHeads Rennes #10 : Mock Objects
CocoaHeads Rennes #10 : Mock Objects
 
Csharp3 heritage-polymorphisme-interface
Csharp3 heritage-polymorphisme-interfaceCsharp3 heritage-polymorphisme-interface
Csharp3 heritage-polymorphisme-interface
 
Formation C# - Cours 2 - Programmation procédurale
Formation C# - Cours 2 - Programmation procéduraleFormation C# - Cours 2 - Programmation procédurale
Formation C# - Cours 2 - Programmation procédurale
 
Part1
Part1Part1
Part1
 
Csharp2014
Csharp2014Csharp2014
Csharp2014
 
Une introduction à Javascript et ECMAScript 6
Une introduction à Javascript et ECMAScript 6Une introduction à Javascript et ECMAScript 6
Une introduction à Javascript et ECMAScript 6
 
Csharp2 : classes et objets
Csharp2 : classes et objetsCsharp2 : classes et objets
Csharp2 : classes et objets
 
Polymorphisme, interface et classe abstraite
Polymorphisme, interface et classe abstraitePolymorphisme, interface et classe abstraite
Polymorphisme, interface et classe abstraite
 
Chapitre 5 classes abstraites et interfaces
Chapitre 5  classes abstraites et interfacesChapitre 5  classes abstraites et interfaces
Chapitre 5 classes abstraites et interfaces
 
Les fonctions lambdas en C++11 et C++14
Les fonctions lambdas en C++11 et C++14Les fonctions lambdas en C++11 et C++14
Les fonctions lambdas en C++11 et C++14
 
Polymorphisme
PolymorphismePolymorphisme
Polymorphisme
 
Chapitre 4 heritage et polymorphisme
Chapitre 4 heritage et polymorphismeChapitre 4 heritage et polymorphisme
Chapitre 4 heritage et polymorphisme
 
Chapitre5: Classes et objets
Chapitre5: Classes et objetsChapitre5: Classes et objets
Chapitre5: Classes et objets
 
Javascript un langage supérieur
Javascript un langage supérieurJavascript un langage supérieur
Javascript un langage supérieur
 
De Java à .NET
De Java à .NETDe Java à .NET
De Java à .NET
 

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

Présentation Groovy
Présentation GroovyPrésentation Groovy
Présentation GroovyJS Bournival
 
Comment écrire du code testable ?
Comment écrire du code testable ?Comment écrire du code testable ?
Comment écrire du code testable ?Fou Cha
 
Design Pattern introduction
Design Pattern introductionDesign Pattern introduction
Design Pattern introductionneuros
 
Qualité logicielle
Qualité logicielleQualité logicielle
Qualité logiciellecyrilgandon
 
GWT : under the hood
GWT : under the hoodGWT : under the hood
GWT : under the hoodsvuillet
 
Introduction à Groovy - OpenSource eXchange 2008
Introduction à Groovy - OpenSource eXchange 2008Introduction à Groovy - OpenSource eXchange 2008
Introduction à Groovy - OpenSource eXchange 2008Guillaume Laforge
 
Cours j query-id1575
Cours j query-id1575Cours j query-id1575
Cours j query-id1575kate2013
 
Voxxdays luxembourg 2016 retours java 8
Voxxdays luxembourg 2016 retours java 8Voxxdays luxembourg 2016 retours java 8
Voxxdays luxembourg 2016 retours java 8Jean-Michel Doudoux
 
Android Optimisations Greendroid
Android Optimisations GreendroidAndroid Optimisations Greendroid
Android Optimisations GreendroidGDG Nantes
 
Refined, des types sur mesure
Refined, des types sur mesureRefined, des types sur mesure
Refined, des types sur mesureMohamad Kassir
 
Traits : de la théorie à la pratique
Traits : de la théorie à la pratiqueTraits : de la théorie à la pratique
Traits : de la théorie à la pratiqueFrederic Hardy
 
Présentation Javascript à l'ESI (Alger)
Présentation Javascript à l'ESI (Alger)Présentation Javascript à l'ESI (Alger)
Présentation Javascript à l'ESI (Alger)Dr Samir A. ROUABHI
 
Java 9 modulo les modules devoxx fr 2017
Java 9 modulo les modules devoxx fr 2017Java 9 modulo les modules devoxx fr 2017
Java 9 modulo les modules devoxx fr 2017Jean-Michel Doudoux
 
Grails from scratch to prod - MixIT 2010
Grails from scratch to prod - MixIT 2010Grails from scratch to prod - MixIT 2010
Grails from scratch to prod - MixIT 2010Aurélien Maury
 
Javascript ne se limite pas à jquery
Javascript ne se limite pas à jqueryJavascript ne se limite pas à jquery
Javascript ne se limite pas à jqueryneuros
 
Introduction au langage Go
Introduction au langage GoIntroduction au langage Go
Introduction au langage GoSylvain Wallez
 

Semelhante a Les nouveautés de Groovy 2 -- Mix-IT 2013 (20)

Présentation Groovy
Présentation GroovyPrésentation Groovy
Présentation Groovy
 
Comment écrire du code testable ?
Comment écrire du code testable ?Comment écrire du code testable ?
Comment écrire du code testable ?
 
Ruby Pour RoR
Ruby Pour RoRRuby Pour RoR
Ruby Pour RoR
 
Design Pattern introduction
Design Pattern introductionDesign Pattern introduction
Design Pattern introduction
 
Qualité logicielle
Qualité logicielleQualité logicielle
Qualité logicielle
 
GWT : under the hood
GWT : under the hoodGWT : under the hood
GWT : under the hood
 
Introduction à Groovy - OpenSource eXchange 2008
Introduction à Groovy - OpenSource eXchange 2008Introduction à Groovy - OpenSource eXchange 2008
Introduction à Groovy - OpenSource eXchange 2008
 
Cours j query-id1575
Cours j query-id1575Cours j query-id1575
Cours j query-id1575
 
Voxxdays luxembourg 2016 retours java 8
Voxxdays luxembourg 2016 retours java 8Voxxdays luxembourg 2016 retours java 8
Voxxdays luxembourg 2016 retours java 8
 
Android Optimisations Greendroid
Android Optimisations GreendroidAndroid Optimisations Greendroid
Android Optimisations Greendroid
 
Javascript proprement
Javascript proprementJavascript proprement
Javascript proprement
 
Refined, des types sur mesure
Refined, des types sur mesureRefined, des types sur mesure
Refined, des types sur mesure
 
Traits : de la théorie à la pratique
Traits : de la théorie à la pratiqueTraits : de la théorie à la pratique
Traits : de la théorie à la pratique
 
Vert.x 3
Vert.x 3Vert.x 3
Vert.x 3
 
Présentation Javascript à l'ESI (Alger)
Présentation Javascript à l'ESI (Alger)Présentation Javascript à l'ESI (Alger)
Présentation Javascript à l'ESI (Alger)
 
Des tests modernes pour Drupal
Des tests modernes pour DrupalDes tests modernes pour Drupal
Des tests modernes pour Drupal
 
Java 9 modulo les modules devoxx fr 2017
Java 9 modulo les modules devoxx fr 2017Java 9 modulo les modules devoxx fr 2017
Java 9 modulo les modules devoxx fr 2017
 
Grails from scratch to prod - MixIT 2010
Grails from scratch to prod - MixIT 2010Grails from scratch to prod - MixIT 2010
Grails from scratch to prod - MixIT 2010
 
Javascript ne se limite pas à jquery
Javascript ne se limite pas à jqueryJavascript ne se limite pas à jquery
Javascript ne se limite pas à jquery
 
Introduction au langage Go
Introduction au langage GoIntroduction au langage Go
Introduction au langage Go
 

Mais de Guillaume Laforge

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

Mais de Guillaume Laforge (20)

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

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

  • 1.
  • 2. Les nouveautés de Groovy 2 GuillaumeLaforge Groovy Project Manager SpringSource / VMware
  • 6. syntaxe dérivant de Java : facile à apprendre ! Groovy
  • 9.
  • 10.
  • 11.
  • 12.
  • 13. GVM
  • 14.
  • 15. GVM
  • 17. GVM:GroovyenVironmentManager • 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
  • 18. Commençons par Groovy2.0 Modularity Java 7: ProjectCoin & invokedynamic Static typechecking & compilation
  • 19. Modularité « Tout le monde n’a pas besoin de tout, tout le temps, en même temps ! »
  • 20. LamodularitédeGroovy • 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
  • 21. LesnouveauxJARs • 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
  • 22. LesnouveauxJARs • 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
  • 24. Lesmodulesd’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")
  • 25. Lesmodulesd’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
  • 26. Lesmodulesd’extension • Créer sa propre extension • contribuer des méthodes statiques package  foo class  StaticStringExtension  {        static  hi(String  self)  {                "Hi!"        } } //  usage:  String.hi()
  • 27. Descripteurdesmodulesd’extension • META-INF/ • services/ • org.codehaus.groovy.runtime.ExtensionModule moduleName  =  stringExtensions moduleVersion  =  1.0 //  liste  de  noms  de  classe  séparées  par  des  virgules extensionClasses  =  foo.StringExtension //  liste  de  noms  de  classe  séparées  par  des  virgules staticExtensionClasses  =  foo.StaticStringExtension
  • 28. Thème Java 7 Syntaxe de « Project Coin » Support d’invoke dynamic
  • 30. Littérauxbinaires • En plus de décimal, octal, et héxa... • On a une représentation binaire : int  x  =  0b10101111 assert  x  ==  175   byte  aByte  =  0b00100001 assert  aByte  ==  33   int  anInt  =  0b1010000101000101 assert  anInt  ==  41285
  • 31. Les«underscores»dansleslittéraux • Utilisation des « underscores » pour séparer les unités au choix long  creditCardNumber  =  1234_5678_9012_3456L long  socialSecurityNumbers  =  999_99_9999L float  monetaryAmount  =  12_345_132.12 long  hexBytes  =  0xFF_EC_DE_5E long  hexWords  =  0xFFEC_DE5E long  maxLong  =  0x7fff_ffff_ffff_ffffL long  alsoMaxLong  =  9_223_372_036_854_775_807L long  bytes  =  0b11010010_01101001_10010100_10010010
  • 32. Catchd’exceptionsmultiples • Un seul bloc catch pour plusieurs exceptions, plutôt que dupliquer les blocs try  {        /*  ...  */ }  catch(IOException  |  NullPointerException  e)  {        /*  un  seul  bloc  */ }
  • 33.
  • 35. Supportd’invokedynamicdeJDK7 • 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
  • 36. Thème « statique » Vérification statique de type Compilation statique
  • 37. Vérificationstatiquesdetype • But : rendre le compilateur « grincheux » ! • jeter des erreurs à la compilation • et non pas au runtime !
  • 38. Tout le monde n’a pas besoin de dynamique tout le temps !
  • 39. Tout le monde n’a pas besoin de dynamique tout le temps ! Nah !
  • 40. Vérificationstatiquedetype • 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
  • 41. Vérificationstatiquedetype • Le compilateur doit inférer les types... • moins besoin de types explicites et de casts • inférence fine • « flow typing » • « lowest upper bound »
  • 42. Vérificationstatiquedetype • 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
  • 43. Fautesdefrappe import  groovy.transform.TypeChecked   void  method()  {}   @TypeChecked  test()  {        //  Cannot  find  matching  method  metthhoood()        metthhoood()          def  name  =  "Guillaume"        //  variable  naamme  is  undeclared        println  naamme }
  • 44. Fautesdefrappe 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
  • 45. Fautesdefrappe 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
  • 46. Fautesdefrappe 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
  • 47. Mauvaisesaffectationsdevariable //  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  =  0 i  +=  '1'
  • 48. Mauvaisesaffectationsdevariable //  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  =  0 i  +=  '1' Erreurs de compilation
  • 49. Mauvaisesaffectationsdevariable //  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  =  0 i  +=  '1' Erreurs de compilation Erreurs de compilation
  • 50. Mauvaisesaffectationsdevariable //  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  =  0 i  +=  '1' Erreurs de compilation Erreurs de compilation Erreurs de compilation
  • 51. Mauvaistypederetour //  checks  if/else  branch  return  values @TypeChecked int  method()  {        if  (true)  {  'String'  }        else  {  42  } } //  works  for  switch/case  &  try/catch/finally   //  transparent  toString()  implied @TypeChecked String  greeting(String  name)  {        def  sb  =  new  StringBuilder()        sb  <<  "Hi  "  <<  name }
  • 52. Mauvaistypederetour //  checks  if/else  branch  return  values @TypeChecked int  method()  {        if  (true)  {  'String'  }        else  {  42  } } //  works  for  switch/case  &  try/catch/finally   //  transparent  toString()  implied @TypeChecked String  greeting(String  name)  {        def  sb  =  new  StringBuilder()        sb  <<  "Hi  "  <<  name } Erreur de compilation
  • 53. Mauvaistypederetour //  checks  if/else  branch  return  values @TypeChecked int  method()  {        if  (true)  {  'String'  }        else  {  42  } } //  works  for  switch/case  &  try/catch/finally   //  transparent  toString()  implied @TypeChecked String  greeting(String  name)  {        def  sb  =  new  StringBuilder()        sb  <<  "Hi  "  <<  name } Erreur de compilation Au final, appèle le toString() de StringBuilder
  • 54. Inférencedetype @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        } }
  • 55. Inférencedetype @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
  • 56. Inférencedetype @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é
  • 57. Inférencedetype @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é
  • 58. Inférencedetype @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é
  • 59. Mélangerdynamiqueetstatiquementvérifié @TypeChecked String  greeting(String  name)  {        //  call  method  with  dynamic  behavior        //  but  with  proper  signature        generateMarkup(name.toUpperCase()) }   //  usual  dynamic  behavior String  generateMarkup(String  name)  {        def  sw  =  new  StringWriter()        new  MarkupBuilder(sw).html  {                body  {                        div  name                }        }        sw.toString() }
  • 60. Mélangerdynamiqueetstatiquementvérifié @TypeChecked String  greeting(String  name)  {        //  call  method  with  dynamic  behavior        //  but  with  proper  signature        generateMarkup(name.toUpperCase()) }   //  usual  dynamic  behavior String  generateMarkup(String  name)  {        def  sw  =  new  StringWriter()        new  MarkupBuilder(sw).html  {                body  {                        div  name                }        }        sw.toString() } Statiquement vérifié
  • 61. Mélangerdynamiqueetstatiquementvérifié @TypeChecked String  greeting(String  name)  {        //  call  method  with  dynamic  behavior        //  but  with  proper  signature        generateMarkup(name.toUpperCase()) }   //  usual  dynamic  behavior String  generateMarkup(String  name)  {        def  sw  =  new  StringWriter()        new  MarkupBuilder(sw).html  {                body  {                        div  name                }        }        sw.toString() } Statiquement vérifié Dynamique
  • 62. Vérificationsparinstanceof @TypeChecked   void  test(Object  val)  {        if  (val  instanceof  String)  {                println  val.toUpperCase()        }  else  if  (val  instanceof  Number)  {                println  "X"  *  val.intValue()        } }
  • 63. Vérificationsparinstanceof @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
  • 64. Vérificationsparinstanceof @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
  • 65. Vérificationsparinstanceof @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)
  • 66. LowestUpperBound • Le plus petit « super » type commun • peut-être virtuel (« non-dénotable ») @TypeChecked  test()  {        //  an  integer  and  a  BigDecimal        return  [1234,  3.14] }
  • 67. LowestUpperBound • 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>
  • 68. Flowtyping • 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  ! }
  • 69. Pô très clean ton code, non mais allô quoi ?
  • 70. Pô très clean ton code, non mais allô quoi ? Ben non !
  • 71. Vérificationstatiqueetcodedynamique • 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
  • 72. Pasdemétaprogrammationdynamique @TypeChecked   void  test()  {        Integer.metaClass.foo  =  {}        123.foo() }
  • 73. Pasdemétaprogrammationdynamique @TypeChecked   void  test()  {        Integer.metaClass.foo  =  {}        123.foo() } Accès au champ dynamique metaClass interdit
  • 74. Pasdemétaprogrammationdynamique @TypeChecked   void  test()  {        Integer.metaClass.foo  =  {}        123.foo() } Accès au champ dynamique metaClass interditMéthode non reconnue
  • 75. Typeexplicitepourlesparamètresdeclosure @TypeChecked  test()  {        ["a",  "b",  "c"].collect  {                it.toUpperCase()  //  Pas  d’accord  !        } }
  • 76. Typeexplicitepourlesparamètresdeclosure @TypeChecked  test()  {        ["a",  "b",  "c"].collect  {  String  it  -­‐>                it.toUpperCase()  //  OK,  une  String        } }
  • 77. Typeexplicitepourlesparamètresdeclosure @TypeChecked  test()  {        ["a",  "b",  "c"].collect  {  String  it  -­‐>                it.toUpperCase()  //  OK,  une  String        } } Obligé d’indiquer le type explicitement
  • 78. Typeexplicitepourlesparamètresdeclosure @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 !
  • 79. Mais si c’est pô dynamique, on peut compiler statiquement ?
  • 80. Mais si c’est pô dynamique, on peut compiler statiquement ? Ben oui !
  • 81. Compilationstatique • 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
  • 82. Avantagesdelacompilationstatique • 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
  • 85. Inconvénientsdelacompilationstatique • 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
  • 86. Mixercompilationstatiqueetcodedynamique @CompileStatic String  greeting(String  name)  {        //  call  method  with  dynamic  behavior        //  but  with  proper  signature        generateMarkup(name.toUpperCase()) }   //  usual  dynamic  behavior String  generateMarkup(String  name)  {        def  sw  =  new  StringWriter()        new  MarkupBuilder(sw).html  {                body  {                        div  name                }        }        sw.toString() }
  • 87. Mixercompilationstatiqueetcodedynamique @CompileStatic String  greeting(String  name)  {        //  call  method  with  dynamic  behavior        //  but  with  proper  signature        generateMarkup(name.toUpperCase()) }   //  usual  dynamic  behavior String  generateMarkup(String  name)  {        def  sw  =  new  StringWriter()        new  MarkupBuilder(sw).html  {                body  {                        div  name                }        }        sw.toString() } Statiquement compilé
  • 88. Mixercompilationstatiqueetcodedynamique @CompileStatic String  greeting(String  name)  {        //  call  method  with  dynamic  behavior        //  but  with  proper  signature        generateMarkup(name.toUpperCase()) }   //  usual  dynamic  behavior String  generateMarkup(String  name)  {        def  sw  =  new  StringWriter()        new  MarkupBuilder(sw).html  {                body  {                        div  name                }        }        sw.toString() } Statiquement compilé Dynamique
  • 89. Mixercompilationstatiqueetcodedynamique @CompileStatic String  greeting(String  name)  {        //  call  method  with  dynamic  behavior        //  but  with  proper  signature        generateMarkup(name.toUpperCase()) }   //  usual  dynamic  behavior String  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
  • 90. Mixercompilationstatiqueetcodedynamique @CompileStatic String  greeting(String  name)  {        //  call  method  with  dynamic  behavior        //  but  with  proper  signature        generateMarkup(name.toUpperCase()) }   //  usual  dynamic  behavior String  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 !
  • 91. Etlaperformancedanstoutça? • Comparaisons entre : • Java • Groovy • avec compilation statique — Groovy 2.0 • avec optimisations types primitifs — Groovy 1.8+ • sans optimisation — Groovy 1.7
  • 93. ...maintenant Groovy2.1 Support complet d’invoke dynamic Méta-annotations Configuration avancée du compilateur Extensions du typechecker
  • 95. Supportcompletd’invokedynamic • 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 »
  • 97. 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
  • 101. Méta-annotations @Immutable @ToString(excludes  =  ["age"]) @AnnotationCollector @interface  MyAlias  {} Annotations collectées Le collecteur Votre propre alias d’annotation
  • 102. Méta-annotations @Immutable @ToString(excludes  =  ["age"]) @AnnotationCollector @interface  MyAlias  {} @MyAlias class  Foo  {        String  name        int  age } Annotations collectées Le collecteur Votre propre alias d’annotation
  • 103. Méta-annotations @Immutable @ToString(excludes  =  ["age"]) @AnnotationCollector @interface  MyAlias  {} @MyAlias class  Foo  {        String  name        int  age } Annotations collectées Le collecteur Votre propre alias d’annotation Utilisez votre méta-annotation
  • 104. L’annotation @DelegatesTo Améliorer l’outillage pour le support des Domain-Specific Languages
  • 105. 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' }
  • 107. Annotation@DelegatesTo class  ExecSpec  {        void  foo() } exec(spec)  {        foo() }
  • 108. Annotation@DelegatesTo class  ExecSpec  {        void  foo() } void  exec(ExecSpec  sp,  Closure  c)  {        c.delegate  =  sp        c() } exec(spec)  {        foo() }
  • 109. Annotation@DelegatesTo class  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()
  • 110. Annotation@DelegatesTo class  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()
  • 111. 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() }
  • 112. 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)
  • 113. Annotation@DelegatesTo • Utiliser Target pour préciser à qui déléguer void  exec(ExecSpec  sp,  Closure  c)  {        c.delegate  =  sp        c() }
  • 114. Annotation@DelegatesTo • Utiliser Target pour préciser à qui déléguer void  exec(ExecSpec  sp,  Closure  c)  {        c.delegate  =  sp        c() } @DelegatesTo.Target(‘‘id’’)
  • 115. 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’’)
  • 116. 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
  • 117. Etendre le vérificateur Pour aller plus loin que Java lui même
  • 118. Etendrelevérificateurstatiquedetype • 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... }
  • 119. Etendrelevérificateurstatiquedetype • 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
  • 120. • Aider le vérificateur lorsque... • impossible d’inférer un type • aucune méthode trouvée • pas d’attribut trouvé • assignation incorrecte Etendrelevérificateurstatiquedetype
  • 121. • Votre extension a accès à une API orientée événement Etendrelevérificateurstatiquedetype • onMethodSelection • afterMethodCall • beforeMethodCall • afterVisitMethod • beforeVisitMethod • methodNotFound • unresolvedVariable • unresolvedProperty • unresolvedAttribute • incompatibleAssignment
  • 122. Etendrelevérificateurstatiquedetype onMethodSelection  {  expr,  method  -­‐>  ...  } afterMethodCall  {  mc  -­‐>  ...  } unresolvedVariable  {  var  -­‐>  ...  } methodNotFound  {  receiver,  name,  argList,  argTypes,  call  -­‐>  ...  } incompatibleAssignment  {  lhsType,  rhsType,  expr  -­‐>  ...  }
  • 123. Etendrelevérificateurstatiquedetype onMethodSelection  {  expr,  method  -­‐>  ...  } afterMethodCall  {  mc  -­‐>  ...  } unresolvedVariable  {  var  -­‐>  ...  } methodNotFound  {  receiver,  name,  argList,  argTypes,  call  -­‐>  ...  } incompatibleAssignment  {  lhsType,  rhsType,  expr  -­‐>  ...  } MyExtension.groovy
  • 124. Etendrelevérificateurstatiquedetype onMethodSelection  {  expr,  method  -­‐>  ...  } afterMethodCall  {  mc  -­‐>  ...  } unresolvedVariable  {  var  -­‐>  ...  } methodNotFound  {  receiver,  name,  argList,  argTypes,  call  -­‐>  ...  } incompatibleAssignment  {  lhsType,  rhsType,  expr  -­‐>  ...  } MyExtension.groovy Apprenez votre AST Groovy !
  • 125. Etendrelevérificateurstatiquedetype 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é
  • 126. • 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 Etendrelevérificateurstatiquedetype
  • 127. Configurer le compilateur Classe de script de base Script de configuration DSL de configuration
  • 128. Customiserlecompilateur • 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
  • 129. Customiserlecompilateur • Nouvelles options • --basescript pour définir une classe de base pour les scripts • --configscript pour indiquer un script qui va configurer CompilerConfiguration
  • 130. Customiserlecompilateur • Rajouter la transformation @ToString • import  groovy.transform.ToString import  org.codehaus.groovy.control.customizers              .ASTTransformationCustomizer configuration.addCompilationCustomizer(        new  ASTTransformationCustomizer(ToString) )
  • 131. Customiserlecompilateur • Rajouter la transformation @ToString • import  groovy.transform.ToString import  org.codehaus.groovy.control.customizers              .ASTTransformationCustomizer configuration.addCompilationCustomizer(        new  ASTTransformationCustomizer(ToString) ) Instance de CompilerConfiguration injectée par défaut
  • 132. Customiserlecompilateur • Un petit DSL pour simplifier la configuration configuration.customizers  {        //  apply  to  MyBean.groovy        source(basename:  'MyBean')  {                ast(ToString)        } }
  • 133. Customiserlecompilateur • Un petit DSL pour simplifier la configuration configuration.customizers  {        //  apply  to  MyBean.groovy        source(basename:  'MyBean')  {                ast(ToString)        } } configuration.customizers  {        //  apply  to  *.gbean  files        source(extension:  '.gbean')  {                ast(ToString)        } }
  • 134. Customiserlecompilateur • Un petit DSL pour simplifier la configuration configuration.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'                }        } }
  • 135. Pour en savoir plus... Groovy2.0 http://groovy.codehaus.org/Groovy+2.0+release+notes Groovy2.1 http://groovy.codehaus.org/Groovy+2.1+release+notes
  • 136. Et après ? Groovy3 ! Nouveau « MOP » Nouvellegrammaire Antlr v4 Support des lambdasdeJava8
  • 140. MOP 2
  • 143.
  • 144. 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
  • 145. 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
  • 149. Créditsimages • cerisier http://wallpaperswide.com/cherry_blossom_3-wallpapers.html • NKOTB http://images1.fanpop.com/images/photos/2300000/nkotb-new-kids-on-the-block-2314664-1280-960.jpg • tomates http://www.infoescola.com/wp-content/uploads/2011/01/tomate.jpg • patates http://toooof.free.fr/blogs/captainslip/screenshots/pommes_de_terre.jpg • canard http://www.objets-publicitaires-pro.com/images/objet-publicitaire/produit/large/canard-geant-a-personnaliser-jaune.jpg • grincheux https://si0.twimg.com/profile_images/3115998027/b47c180a703a5ffa7d1437a66f545dc0.jpeg • singe http://static.ddmcdn.com/gif/how-to-draw-animals-31.jpg • warning http://th07.deviantart.net/fs71/PRE/i/2012/261/8/6/warning_gangnam_style_zone_by_untoucheddesigns-d5f6bal.png • coyote http://nittygriddy.com/wp-content/uploads/2011/01/Wiley-Coyote-Help.jpg • ring http://img.banggood.com/images/upload/2012/limin/SKU028431_11.JPG • magnifying glass http://www.renders-graphiques.fr/image/upload/normal/loupe.png • chronomètre http://www.moineau-instruments.com/59-thickbox/chronometre-mecanique-1-10-t15-mn-2-fonctions.jpg • that’s all folks http://4.bp.blogspot.com/-wJxosualm48/T4M_spcUUjI/AAAAAAAAB8E/njfLjNZQdsc/s1600/thats-all-folks.jpg • MOP http://imagethumbnails.milo.com/024/913/894/trimmed/24913521_25989894_trimmed.jpg • grammar http://edudemic.com/wp-content/uploads/2012/11/connected-learner-grammar.jpg