Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Groovy 2.0 and beyond

Groovy 2.0 and beyond

"Groovy 2.0 and beyond" presentation given at the Groovy / Grails eXchange conference.

Video of the presentation can be seen here:
http://skillsmatter.com/podcast/groovy-grails/keynote-speech

Guillaume Laforge

December 13, 2012
Tweet

More Decks by Guillaume Laforge

Other Decks in Technology

Transcript

  1. Guillaume Laforge • Groovy Project Manager at VMware • Initiator

    of the Grails framework • Creator of the Gaelyk • Co-author of Groovy in Action • Follow me on... • My blog: http://glaforge.appspot.com • Twitter: @glaforge • Google+: http://gplus.to/glaforge
  2. GVM

  3. GVM

  4. GVM: Groovy enVironment Manager • New kid in town! •

    http://gvmtool.net/ — @gvmtool • Manage parallel versions of various SDKs • Currently supports • Groovy, Grails, Griffon, Gradle, Vert.x • On Linux, MacOS, Cygwin, Solaris, FreeBSD
  5. Groovy 2.0 bird’s eye view Java 7 Project Coin Invoke

    Dynamic A more modular Groovy Static Type Checking Static Compilation
  6. Groovy Modularity • Groovy’s « all » JAR weighs in

    at 6 MB •Nobody needs everything • Template engine, Ant scripting, Swing UI building... • Provide a smaller core • and several smaller JARs per feature • Provide hooks for setting up DGM methods,
  7. The new JARs • A smaller JAR: 3MB • Modules

    – console – docgenerator – groovydoc – groovysh – ant – bsf – jsr-223 – jmx – sql – swing – servlet – templates – test – testng – json – xml
  8. The new JARs • A smaller JAR: 3MB • Modules

    – console – docgenerator – groovydoc – groovysh – ant – bsf – jsr-223 – jmx – sql – swing – servlet – templates – test – testng – json – xml
  9. Extension modules • Create your own module • contribute instance

    extension methods package  foo class  StringExtension  {        static  introduces(String  self,  String  name)  {                "Hi  ${name),  I’m  ${self}"        } } //  usage:  "Guillaume".introduces("Cédric")
  10. Extension modules • Create your own module • contribute instance

    extension methods package  foo class  StringExtension  {        static  introduces(String  self,  String  name)  {                "Hi  ${name),  I’m  ${self}"        } } //  usage:  "Guillaume".introduces("Cédric") Same structure as Categories
  11. Extension modules • Create your own module • contribute class

    extension methods package  foo class  StaticStringExtension  {        static  hi(String  self)  {                "Hi!"        } } //  usage:  String.hi()
  12. Extension module descriptor • Descriptor in: META-INF/services/ org.codehaus.groovy.runtime.ExtensionModule moduleName  =

     stringExtensions moduleVersion  =  1.0 //  comma-­‐separated  list  of  classes extensionClasses  =  foo.StringExtension //  comma-­‐separated  list  of  classes staticExtensionClasses  =   foo.StaticStringExtension
  13. Groovy 2.0 bird’s eye view Java 7 Project Coin Invoke

    Dynamic A more modular Groovy Static Type Checking Static Compilation
  14. Binary literals • We had decimal, octal and hexadecimal notations

    for number literals • We can now use binary representations too int  x  =  0b10101111 assert  x  ==  175   byte  aByte  =  0b00100001 assert  aByte  ==  33   int  anInt  =  0b1010000101000101 assert  anInt  ==  41285
  15. Underscore in literals • Now we can also add underscores

    in number literals for more readability 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
  16. Multicatch • One block for multiple exception caught • rather

    than duplicating the block try  {        /*  ...  */ }  catch(IOException  |  NullPointerException  e)  {        /*  one  block  to  treat  2  exceptions  */ }
  17. InvokeDynamic •Groovy 2.0 supports JDK 7’s invokeDynamic • compiler has

    a flag for compiling against JDK 7 • might use the invokeDynamic backport for < JDK 7 • Benefits • more runtime performance! • at least as fast as current « dynamic » Groovy • in the long run, will allow us to get rid of code! • call site caching, thanks to MethodHandles • metaclass registry, thanks to ClassValues • will let the JIT inline calls more easily
  18. Groovy 2.0 bird’s eye view Java 7 Project Coin Invoke

    Dynamic A more modular Groovy Static Type Checking Static Compilation
  19. Static Type Checking • Goal: make the Groovy compiler «

    grumpy »! • and throw compilation errors (not at runtime) •Not everybody needs dynamic features all the time • think Java libraries scripting • Grumpy should... • tell you about your method or variable typos • complain if you call methods that don’t exist • shout on assignments of wrong types • infer the types of your variables • figure out GDK methods
  20. Typos in a variable or method import  groovy.transform.TypeChecked   void

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

     method()  {}   @TypeChecked  test()  {        //  Cannot  find  matching  method  metthhoood()        metthhoood()          def  name  =  "Guillaume"        //  variable  naamme  is  undeclared        println  naamme } Compilation errors!
  22. Typos in a variable or method import  groovy.transform.TypeChecked   void

     method()  {}   @TypeChecked  test()  {        //  Cannot  find  matching  method  metthhoood()        metthhoood()          def  name  =  "Guillaume"        //  variable  naamme  is  undeclared        println  naamme } Compilation errors! Annotation can be at class or method level
  23. Wrong assignments //  cannot  assign  value  of  type...  to  variable...

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

    int  x  =  new  Object() Set  set  =  new  Object()   def  o  =  new  Object() int  x  =  o   String[]  strings  =  ['a','b','c'] int  str  =  strings[0]   //  cannot  find  matching  method  plus() int  i  =  0 i  +=  '1' Compilation errors!
  25. Wrong return types //  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 }
  26. Wrong return types //  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 } Compilation error!
  27. Type inference @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        } }
  28. Statically checked & dynamic methods @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() }
  29. Instanceof checks @TypeChecked   void  test(Object  val)  {    

       if  (val  instanceof  String)  {                println  val.toUpperCase()        }  else  if  (val  instanceof  Number)  {                println  "X"  *  val.intValue()        } }
  30. Instanceof checks @TypeChecked   void  test(Object  val)  {    

       if  (val  instanceof  String)  {                println  val.toUpperCase()        }  else  if  (val  instanceof  Number)  {                println  "X"  *  val.intValue()        } } No need for casts
  31. Instanceof checks @TypeChecked   void  test(Object  val)  {    

       if  (val  instanceof  String)  {                println  val.toUpperCase()        }  else  if  (val  instanceof  Number)  {                println  "X"  *  val.intValue()        } } No need for casts Can call String#multiply(int) from the Groovy Development Kit
  32. Lowest Upper Bound • Represents the lowest « super »

    type classes have in common • may be virtual (aka « non-denotable ») @TypeChecked  test()  {        //  an  integer  and  a  BigDecimal        return  [1234,  3.14] }
  33. Lowest Upper Bound • Represents the lowest « super »

    type classes have in common • may be virtual (aka « non-denotable ») @TypeChecked  test()  {        //  an  integer  and  a  BigDecimal        return  [1234,  3.14] } Inferred return type: List<Number & Comparable>
  34. Lowest Upper Bound • Represents the lowest « super »

    type classes have in common • may be virtual (aka « non-denotable ») @TypeChecked  test()  {        //  an  integer  and  a  BigDecimal        return  [1234,  3.14] } Inferred return type: List<Number & Comparable>
  35. Flow typing • Static type checking shouldn’t complain even for

    bad coding practicies which work without type checks @TypeChecked  test()  {        def  var  =  123                  //  inferred  type  is  int        int  x  =  var                      //  var  is  an  int        var  =  "123"                      //  assign  var  with  a  String        x  =  var.toInteger()      //  no  problem,  no  need  to  cast        var  =  123        x  =  var.toUpperCase()  //  error,  var  is  int! }
  36. Gotcha: static checking vs dynamic •Type checking works at compile-time

    • adding @TypeChecked doesn’t change behavior • do not confuse with static compilation • Most dynamic features cannot be type checked • metaclass changes, categories • dynamically bound variables (ex: script’s binding) • But compile-time metaprogramming works • as long as proper type information is defined
  37. Gotcha: runtime metaprogramming @TypeChecked   void  test()  {    

       Integer.metaClass.foo  =  {}        123.foo() }
  38. Gotcha: runtime metaprogramming @TypeChecked   void  test()  {    

       Integer.metaClass.foo  =  {}        123.foo() } Not allowed: metaClass property is dynamic
  39. Gotcha: runtime metaprogramming @TypeChecked   void  test()  {    

       Integer.metaClass.foo  =  {}        123.foo() } Not allowed: metaClass property is dynamic Method not recognized
  40. Gotcha: explicit type for closures @TypeChecked  test()  {    

       ["a",  "b",  "c"].collect  {                it.toUpperCase()  //  Not  OK        } }
  41. Gotcha: explicit type for closures @TypeChecked  test()  {    

       ["a",  "b",  "c"].collect  {  String  it  -­‐>                it.toUpperCase()  //  OK,  it’s  a  String        } }
  42. Closure shared variables @TypeChecked  test()  {        def

     var  =  "abc"                      def  cl  =  {  var  =  new  Date()  }        if  (random)  cl()        var.toUpperCase()    //  Not  OK! }
  43. Closure shared variables @TypeChecked  test()  {        def

     var  =  "abc"                      def  cl  =  {  var  =  new  Date()  }        if  (random)  cl()        var.toUpperCase()    //  Not  OK! } var assigned in the closure: « shared closure variable »
  44. Closure shared variables @TypeChecked  test()  {        def

     var  =  "abc"                      def  cl  =  {  var  =  new  Date()  }        if  (random)  cl()        var.toUpperCase()    //  Not  OK! } var assigned in the closure: « shared closure variable » Impossible to ensure the assignment really happens
  45. Closure shared variables @TypeChecked  test()  {        def

     var  =  "abc"                      def  cl  =  {  var  =  new  Date()  }        if  (random)  cl()        var.toUpperCase()    //  Not  OK! } var assigned in the closure: « shared closure variable » Impossible to ensure the assignment really happens Only methods of the most specific compatible type (LUB) are allowed by the type checker
  46. Closure shared variables class  A          

               {  void  foo()  {}  } class  B  extends  A  {  void  bar()  {}  } @TypeChecked  test()  {        def  var  =  new  A()        def  cl  =  {  var  =  new  B()  }        if  (random)  cl()        var.foo()      //  OK! }
  47. Closure shared variables class  A          

               {  void  foo()  {}  } class  B  extends  A  {  void  bar()  {}  } @TypeChecked  test()  {        def  var  =  new  A()        def  cl  =  {  var  =  new  B()  }        if  (random)  cl()        var.foo()      //  OK! } var is at least an instance of A
  48. Static Compilation • Given your Groovy code can be type

    checked... we can as well compile it « statically » • ie. generate the same byte code as javac • Also interesting for those stuck in JDK < 7 to benefit from performance improvements
  49. Static Compilation: advantages • You gain: •Type safety • thanks

    to static type checking • static compilation builds upon static type checking •Faster code • as close as possible to Java’s performance •Code immune to « monkey patching » • metaprogramming badly used can interfere with framework code • Smaller bytecode size
  50. Static Compilation: disadvantages • But you loose: • Dynamic features

    • metaclass changes, categories, etc. • Dynamic method dispatch • although as close as possible to « dynamic » Groovy
  51. Statically compiled & dynamic methods @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() }
  52. What about performance? • Comparisons between: • Java • Groovy

    static compilation (Groovy 2.0) • Groovy with primitive optimizations (Groovy 1.8+) • Groovy without optimizations (Groovy 1.7)
  53. What about performance? 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.7 1.8 2.0
  54. Full invoke dynamic support • In Groovy 2.0, not all

    call paths were going through invoke dynamic calls • essentially method calls only • still used call site caching techniques •On JDK 7 with the « indy » JAR, Groovy 2.1 uses invoke dynamic everywhere • On JDK < 7, still uses call site caching Groovy 2.1
  55. @DelegatesTo • Static type checking works nicely for certain Domain-Specific

    Languages • command chains, extension methods, etc. • But for changes of delegation within closures, it’s not helping • often used by DSLs like within Gradle • Enters @DelegatesTo! Groovy 2.1
  56. @DelegatesTo Groovy 2.1 class  ExecSpec  {        void

     foo() } void  exec(ExecSpec  sp,  Closure  c)  {        c.delegate  =  sp        c() }
  57. @DelegatesTo Groovy 2.1 class  ExecSpec  {        void

     foo() } void  exec(ExecSpec  sp,  Closure  c)  {        c.delegate  =  sp        c() } exec(spec)  {        foo() }
  58. @DelegatesTo Groovy 2.1 class  ExecSpec  {        void

     foo() } void  exec(ExecSpec  sp,  Closure  c)  {        c.delegate  =  sp        c() } exec(spec)  {        foo() } Static type checker doesn’t know about that foo() method
  59. @DelegatesTo Groovy 2.1 void  exec(ExecSpec  sp,  Closure  c)  {  

         c.delegate  =  sp        c() } Annotate with: @DelegatesTo(ExecSpec)
  60. @DelegatesTo • With a special delegation strategy Groovy 2.1 void

     exec(ExecSpec  sp,  Closure  c)  {        c.delegate  =  sp        c.resolveStrategy  =  DELEGATE_FIRST        c() }
  61. @DelegatesTo • With a special delegation strategy Groovy 2.1 void

     exec(ExecSpec  sp,  Closure  c)  {        c.delegate  =  sp        c.resolveStrategy  =  DELEGATE_FIRST        c() } Annotate with: @DelegatesTo(value = ExecSpec, strategy = DELEGATE_FIRST)
  62. @DelegatesTo • Use Target to specify the precise argument to

    delegate to Groovy 2.1 void  exec(ExecSpec  sp,  Closure  c)  {        c.delegate  =  sp        c() }
  63. @DelegatesTo • Use Target to specify the precise argument to

    delegate to Groovy 2.1 void  exec(ExecSpec  sp,  Closure  c)  {        c.delegate  =  sp        c() } @DelegatesTo.Target("id")
  64. @DelegatesTo • Use Target to specify the precise argument to

    delegate to Groovy 2.1 void  exec(ExecSpec  sp,  Closure  c)  {        c.delegate  =  sp        c() } @DelegatesTo.Target("id") @DelegatesTo(target = "id")
  65. @DelegatesTo • For DSLs using Groovy closure delegation • Great

    for... •documenting APIs •IDE integration • code completion, code navigation... • working nicely with static type checking and static compilation Groovy 2.1
  66. Custom type checking • You can make Groovy’s static type

    checking even smarter, with your own smarts! • even smarter than Java’s :-) • Create your own type checker extension Groovy 2.1 @TypeChecked(extensions  =                            'MyExtension.groovy') void  exec()  {        //  code  to  be  further  checked... }
  67. • Your own extension has access to an event-based API

    Custom type checking • onMethodSelection • afterMethodCall • beforeMethodCall • afterVisitMethod • beforeVisitMethod • methodNotFound • unresolvedVariable • unresolvedProperty • unresolvedAttribute • incompatibleAssignment Groovy 2.1
  68. Custom type checking onMethodSelection  {  expr,  method  -­‐>  ...  }

    afterMethodCall  {  mc  -­‐>  ...  } unresolvedVariable  {  var  -­‐>  ...  } methodNotFound  {  receiver,  name,  argList,  argTypes,  call  -­‐>  ...  } methodNotFound  {  receiver,  name,  argList,  argTypes,  call  -­‐>  ...  } incompatibleAssignment  {  lhsType,  rhsType,  expr  -­‐>  ...  } Groovy 2.1 MyExtension.groovy
  69. Custom type checking onMethodSelection  {  expr,  method  -­‐>  ...  }

    afterMethodCall  {  mc  -­‐>  ...  } unresolvedVariable  {  var  -­‐>  ...  } methodNotFound  {  receiver,  name,  argList,  argTypes,  call  -­‐>  ...  } methodNotFound  {  receiver,  name,  argList,  argTypes,  call  -­‐>  ...  } incompatibleAssignment  {  lhsType,  rhsType,  expr  -­‐>  ...  } Know your Groovy AST API well ;-) Groovy 2.1 MyExtension.groovy
  70. Custom type checking onMethodSelection  {  expr,  method  -­‐>  ...  }

    afterMethodCall  {  mc  -­‐>  ...  } unresolvedVariable  {  var  -­‐>  ...  } methodNotFound  {  receiver,  name,  argList,  argTypes,  call  -­‐>  ...  } methodNotFound  {  receiver,  name,  argList,  argTypes,  call  -­‐>  ...  } incompatibleAssignment  {  lhsType,  rhsType,  expr  -­‐>  ...  } Know your Groovy AST API well ;-) Groovy 2.1 MyExtension.groovy Doesn’t need to be compiled
  71. Alias annotations • Ability to create meta-annotations combining and/or parameterizing

    other annotations • Works also for local AST transformations and their annotations Groovy 2.1
  72. Alias annotations @Immutable @ToString(excludes  =  ["age"]) @AnnotationCollector @interface  MyAlias  {}

    Groovy 2.1 The « collector » Your own custom alias name Collected annotations
  73. Alias annotations @Immutable @ToString(excludes  =  ["age"]) @AnnotationCollector @interface  MyAlias  {}

    Groovy 2.1 @MyAlias class  Foo  {        String  name        int  age } The « collector » Your own custom alias name Collected annotations
  74. Alias annotations @Immutable @ToString(excludes  =  ["age"]) @AnnotationCollector @interface  MyAlias  {}

    Groovy 2.1 @MyAlias class  Foo  {        String  name        int  age } The « collector » Your own custom alias name Use your concise alias Collected annotations
  75. Take control of your Groovy! • Groovy 1.8 introduced compilation

    customizers • add imports, AST xforms, secure the AST... • With static type checking and static compilation, we received feedback from people wanting them applied « by default » • Allow to instruct the groovyc compiler with a configuration script • groovyc -configurator compConf.groovy Foo.groovy Groovy 2.1
  76. Take control of your Groovy! • Add a default @ToString

    transform • Groovy 2.1 import  groovy.transform.ToString import  org.codehaus.groovy.control.customizers              .ASTTransformationCustomizer config.addCompilationCustomizer(        new  ASTTransformationCustomizer(ToString) )
  77. Take control of your Groovy! • Add a default @ToString

    transform • Groovy 2.1 import  groovy.transform.ToString import  org.codehaus.groovy.control.customizers              .ASTTransformationCustomizer config.addCompilationCustomizer(        new  ASTTransformationCustomizer(ToString) ) Implicit «config» variable representing a CompilationConfiguration instance
  78. Take control of your Groovy! • You can use a

    builder syntax: Groovy 2.1 config.customizers  {        //  apply  to  MyBean.groovy        source(basename:  'MyBean')  {                ast(ToString)        } }
  79. Take control of your Groovy! • You can use a

    builder syntax: Groovy 2.1 config.customizers  {        //  apply  to  MyBean.groovy        source(basename:  'MyBean')  {                ast(ToString)        } } config.customizers  {        //  apply  to  *.gbean  files        source(extension:  '.gbean')  {                ast(ToString)        } }
  80. Take control of your Groovy! • You can use a

    builder syntax: Groovy 2.1 config.customizers  {        //  apply  to  MyBean.groovy        source(basename:  'MyBean')  {                ast(ToString)        } } config.customizers  {        //  apply  to  *.gbean  files        source(extension:  '.gbean')  {                ast(ToString)        } } config.customizers  {        //  custom  filter  logic          //  with  compilation  units        source(unitValidator:  {  unit  -­‐>  ...  })  {                ast(ToString)        } }
  81. End of 2012... and the world? Dec 17-23 2012 GGeX

    Groovy 2.1 beta End of the world
  82. End of 2012... and the world? Dec 17-23 2012 GGeX

    Groovy 2.1 beta Recovering from GGeX End of the world
  83. End of 2012... and the world? Dec 17-23 2012 GGeX

    Groovy 2.1 beta Recovering from GGeX End of the world
  84. End of 2012... and the world? Dec 17-23 2012 GGeX

    Groovy 2.1 beta Recovering from GGeX Christmas End of the world
  85. End of 2012... and the world? Dec 17-23 2012 GGeX

    Groovy 2.1 beta Recovering from GGeX Christmas End of the world
  86. End of 2012... and the world? Dec 17-23 2012 GGeX

    Groovy 2.1 beta Recovering from GGeX Christmas End of the world
  87. End of 2012... and the world? Dec 17-23 2012 GGeX

    Groovy 2.1 beta Recovering from GGeX Christmas Recovering again ! End of the world
  88. Happy New Year! Jan 14-21 Jan 7-13 Groovy 2.1 RC

    Wait for feedback Potential 2nd RC
  89. Happy New Year! Jan 22-29 Jan 14-21 Jan 7-13 Groovy

    2.1 RC Wait for feedback Potential 2nd RC
  90. Happy New Year! Jan 22-29 Jan 14-21 Jan 7-13 Groovy

    2.1 RC Wait for feedback Groovy 2.1 Final ! Potential 2nd RC
  91. Back to 2013 and beyond 2014 2014 2013 2012 Groovy

    2.1 Groovy 4.0 Groovy 3.0 Groovy 2.0
  92. Summary (1/2) • As always, a rich and blossoming ecosystem

    •Groovy 2.0 • more modularity • static theme • static type checking • static compilation • JDK 7 theme • invoke dynamic support • project coin syntax enhancements
  93. Summary (2/2) •Groovy 2.1 • complete indy support • @DelegatesTo

    • custom type checking for your DSLs • alias annotation • And beyond... • a new MOP (Meta-Object Protocol) • a new grammar with Antlr 4 • JDK 8 lambda support
  94. Thank you! Guillaume Laforge Head of Groovy Development Email: [email protected]

    Twitter: @glaforge Google+: http://gplus.to/glaforge Blog: http://glaforge.appspot.com
  95. Picture credits • London http://www.londonup.com/media/1251/Tower-Bridge-london-582331_1024_768.jpg • cherry blossom 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 • USA today http://www.adams-pr.com/images/uploads/USA_Today_logo.jpg • back to the future http://davidhiggerson.files.wordpress.com/2012/02/back-to-the-future-delorean.jpg • magnifying glass http://www.renders-graphiques.fr/image/upload/normal/loupe.png • Santa Claus http://icons.iconarchive.com/icons/fasticon/santa-claus/256/Happy-SantaClaus-icon.png • Champagne http://reallife101blogs.files.wordpress.com/2010/11/champagne_glasses2.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