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

Groovy with Style -- Devoxx 2015

Groovy with Style -- Devoxx 2015

Advice, tricks'n tips about Groovy, how to use it, and more.

Avatar for Guillaume Laforge

Guillaume Laforge

April 09, 2015
Tweet

More Decks by Guillaume Laforge

Other Decks in Technology

Transcript

  1. <=>

  2. @glaforge #groovydvx No semicolons! class HelloParis {
 private String message

    = 'Hello Paris!';
 String greet(String name) {
 "$message, $name speaking";
 } 
 }
 
 print new HelloParis().greet('Guillaume');
  3. @glaforge #groovydvx No semicolons! class HelloParis {
 private String message

    = 'Hello Paris!';
 String greet(String name) {
 "$message, $name speaking";
 } 
 }
 
 print new HelloParis().greet('Guillaume');
  4. @glaforge #groovydvx No semicolons! class HelloParis {
 private String message

    = 'Hello Paris!'
 String greet(String name) {
 "$message, $name speaking"
 } 
 }
 
 print new HelloParis().greet('Guillaume')
  5. @glaforge #groovydvx Public by default public class HelloParis {
 private

    String message = 'Hello Paris'
 private String name
 
 public HelloParis(String name) {
 this.name = name
 }
 public String greet() {
 return "$message, $name speaking"
 } 
 }
  6. @glaforge #groovydvx Public by default class HelloParis {
 private String

    message = 'Hello Paris'
 private String name
 
 HelloParis(String name) {
 this.name = name
 }
 String greet() {
 return "$message, $name speaking"
 } 
 } Methods and classes are public by default
  7. @glaforge #groovydvx class HelloParis {
 String message = 'Hello Paris!’


    String name
 
 HelloParis(String name) {
 this.name = name
 }
 String greet() {
 return "$message, $name speaking"
 } 
 } Fields and static fields require visibility
  8. @glaforge #groovydvx class HelloParis {
 String message = 'Hello Paris!’


    String name
 
 HelloParis(String name) {
 this.name = name
 }
 String greet() {
 return "$message, $name speaking"
 } 
 } Fields and static fields require visibility You created both an instance property and a static property!
  9. @glaforge #groovydvx Get rid of the useless ‘def’ class HelloParis

    {
 private String message = 'Hello Paris!'
 private def String name
 def HelloParis(def String name) {
 this.name = name
 }
 public def String greet() {
 def String result = "$message, $name speaking"
 return result
 } 
 }

  10. @glaforge #groovydvx Get rid of the useless ‘def’ class HelloParis

    {
 private String message = 'Hello Paris!'
 private def String name
 def HelloParis(def String name) {
 this.name = name
 }
 public def String greet() {
 def String result = "$message, $name speaking"
 return result
 } 
 }

  11. @glaforge #groovydvx Get rid of the useless ‘def’ class HelloParis

    {
 private String message = 'Hello Paris!'
 private String name
 HelloParis(String name) {
 this.name = name
 }
 String greet() {
 String result = "$message, $name speaking"
 return result
 } 
 }

  12. @glaforge #groovydvx Get rid of the useless ‘def’ class HelloParis

    {
 private String message = 'Hello Paris!'
 private String name
 HelloParis(String name) {
 this.name = name
 }
 String greet() {
 def result = "$message, $name speaking"
 return result
 } 
 }
 But it’s fine to use ‘def’ for local variables
  13. @glaforge #groovydvx Return is optional too String greet() { 


    "$message, $name speaking"
 } But return is fine for early returns, or for clarity of intent
  14. @glaforge #groovydvx Optional return for if / else int color(String

    name) {
 if (name == 'red')
 1
 else if (name == 'green')
 2
 else
 -1
 }
  15. @glaforge #groovydvx Optional return for switch / case int color(String

    name) {
 switch (name) {
 case 'red': 1; break
 case 'green': 2; break
 default: -1
 }
 }
  16. @glaforge #groovydvx Optional return for switch / case int color(String

    name) {
 switch (name) {
 case 'red': 1; break
 case 'green': 2; break
 default: -1
 }
 } Yeah, yeah, ugly semicolon and break…
  17. @glaforge #groovydvx Optional return for try / catch boolean isInt(String

    s) {
 try {
 Integer.parseInt(s)
 true
 } catch (NumberFormatException nfe) {
 false
 } finally {
 println 'done'
 }
 }
 
 assert isInt('123') && assert !isInt('abc')
  18. @glaforge #groovydvx Optional return for try / catch boolean isInt(String

    s) {
 try {
 Integer.parseInt(s)
 true
 } catch (NumberFormatException nfe) {
 false
 } finally {
 println 'done'
 }
 }
 
 assert isInt('123') && assert !isInt('abc') ‘finally’ blocks don’t return a value
  19. @glaforge #groovydvx Command chains & named arguments check that: wine

    tastes good Parsed as: check(that: wine).tastes(good)
  20. @glaforge #groovydvx Trailing closure argument gets out void unless(boolean b,

    Closure c) {
 if (!b) c()
 }
 
 def (speed, limit) = [80, 90]
 
 unless(speed > limit) {
 println "speed up a notch"
 }
  21. @glaforge #groovydvx Trailing closure argument gets out void unless(boolean b,

    Closure c) {
 if (!b) c()
 }
 
 def (speed, limit) = [80, 90]
 
 unless(speed > limit) {
 println "speed up a notch"
 } Parsed as: unless(speed > limit, {…})
  22. @glaforge #groovydvx No need for dumb getters and setters class

    Person {
 private String name
 private int age
 
 void setName(String name) {
 this.name = name
 }
 String getName() {
 this.name
 }
 void setAge(int age) {
 this.age = age
 }
 int getAge() {
 this.age
 }
 }
  23. @glaforge #groovydvx No need for dumb getters and setters class

    Person {
 String name
 int age
 }
  24. @glaforge #groovydvx No need for dumb getters and setters class

    Person {
 String name
 int age
 } Icing on the cake: add @Immutable or @Canonical
  25. @glaforge #groovydvx Use the property notation class Person {
 String

    name
 int age
 }
 
 def p = new Person(name: 'Guillaume', 
 age: 36)
 assert p.name == 'Guillaume'
 
 p.age = 37
 assert p.age == 37
  26. @glaforge #groovydvx The @Builder transformation import groovy.transform.builder.*
 
 @Builder
 class

    Person {
 String name
 int age
 }
 
 Person.builder() .name('Guillaume') .age(37) .build()
  27. @glaforge #groovydvx The @Builder transformation import groovy.transform.builder.*
 
 @Builder
 class

    Person {
 String name
 int age
 }
 
 Person.builder() .name('Guillaume') .age(37) .build() Different strategies available: chained setters, external builder class, type-safe initializer
  28. @glaforge #groovydvx Native syntax for data structures def list =

    [1, 2, 3]
 def range = 'a'..'b'
 def map = [a: 1, b: 2, c: 3]
 def regex = ~/.*foo.*/
  29. @glaforge #groovydvx Switch / case on steroids switch(obj) {
 case

    123: "number 123"; break
 case "abc": "string abc"; break
 case String: "is a string"; break
 case [1, 2, 3]: "in list"; break
 case ~/.*o+.*/: "regex match"; break
 case { it < 3 }: "closure criteria"; break
 default: "unknown"
 }
  30. @glaforge #groovydvx Import aliasing with static imports too import static

    java.lang.Integer.parseInt as atoi
 
 assert atoi('123') == 123
  31. @glaforge #groovydvx Groovy Truth assert !( null )
 assert !(

    "" )
 assert !( [] )
 assert !( 0 ) assert new Object()
 assert "string"
 assert [1, 2, 3]
 assert 1234
  32. @glaforge #groovydvx Groovy Truth assert !( null )
 assert !(

    "" )
 assert !( [] )
 assert !( 0 ) assert new Object()
 assert "string"
 assert [1, 2, 3]
 assert 1234 False
  33. @glaforge #groovydvx Groovy Truth assert !( null )
 assert !(

    "" )
 assert !( [] )
 assert !( 0 ) assert new Object()
 assert "string"
 assert [1, 2, 3]
 assert 1234 False True
  34. @glaforge #groovydvx Customize the truth with asBoolean() class Account {


    String name
 boolean disabled = false
 
 boolean asBoolean() { !disabled }
 }
 
 assert new Account(name: 'current')
 assert !new Account(name: 'old', disabled: true)
  35. @glaforge #groovydvx Safe navigation // Java if (order != null)

    {
 if (order.getCustomer() != null) {
 if (order.getCustomer().getAddress() != null) {
 System.out.println(order.getCustomer().getAddress());
 }
 }
 }
 // Groovy println order?.customer?.address
  36. @glaforge #groovydvx Safe navigation // Java if (order != null)

    {
 if (order.getCustomer() != null) {
 if (order.getCustomer().getAddress() != null) {
 System.out.println(order.getCustomer().getAddress());
 }
 }
 }
 // Groovy println order?.customer?.address Also give more meaningful NPEs!
  37. @glaforge #groovydvx Power Assert def (a, b, c, d) =

    [10, 20, 30, 610]
 assert a + b * c == d - 40
  38. @glaforge #groovydvx Power Assert def (a, b, c, d) =

    [10, 20, 30, 610]
 assert a + b * c == d - 40 Assertion failed:
 
 assert a + b * c == d - 40
 | | | | | | | |
 10| 20| 30| | 570
 610 600 | 610
 false
  39. @glaforge #groovydvx Calling Elvis for default values def result =

    name != null ? name : "Unknown"
 
 def result = name ?: "Unknown"
  40. @glaforge #groovydvx Calling Elvis for default values def result =

    name != null ? name : "Unknown"
 
 def result = name ?: "Unknown" Groovy Truth 
 at play here
  41. @glaforge #groovydvx Catch ‘any’ exception try {
 something()
 } catch

    (any) {
 // ...
 } Someone suggested me: catch(emAll)
  42. @glaforge #groovydvx Of the importance of contracts • Use explicit

    typing for • method signatures • properties & fields • Nice for • Java interoperability • documenting your APIs • IDE auto-completion and refactoring
  43. @glaforge #groovydvx Picture credits Style: http://1hdwallpapers.com/wallpapers/my_style.jpg Eurostar: http://www.whatsupwhatson.com/wp-content/uploads/2014/04/Eurostar_3012_Waterloo.jpg Puzzle: http://joyinthecause.org/wp-content/uploads/2014/03/missing-puzzle-piece_00449088.jpg

    Gems: http://www.freewhd.com/blue-gems-wallpaper/ Wise: http://fc00.deviantart.net/fs70/i/2012/044/f/6/three_wise_men_color_by_csoro-d4pmlv2.jpg Ready: http://nameshapers.com/wp-content/uploads/2013/12/Social-Media-Coaching-for-CEOs-Getting-started.jpg Semicolon: http://www.freeimageslive.co.uk/image/view/3944/_original Till death to us part: https://mypencillines.files.wordpress.com/2013/04/img_0171.jpg Public: http://www.levelupliving.com/wp-content/uploads/2012/05/Fear-of-Public-Speaking-image.jpg Contract: https://www.icts.uiowa.edu/sites/default/files/contract.jpg Exception: http://www.quotescover.com/wp-content/uploads/Its-the-exception-that-proves__quotes-by-French-Proverb-77.png Banana: http://texturetaddka.com/wp-content/uploads/2011/10/DSC2008.jpg Elvis: http://natedsanders.com/blog/wp-content/uploads/2013/10/Elvis-Presley-Wallpaper-1280-x-960.jpeg Assert: http://www.itshouldjustworktm.com/wp-content/uploads/2012/03/assert-sign-photoshopped.jpg Compass: https://lh4.ggpht.com/WtY8QL0re9kMssF6q4RopDHC6QEpou7ybQo7qNRjn1X8Iu5uKUZv7huHA_PxPB8iGfs=h900 Safety vest: http://media.nautisports.com/catalog/product/image/gilet-de-sauvetage-gonflable-hydrostatique-hammar-pilot-275-n-avec-harnais-pro-rouge-nav_17452_web_1_1.jpg Class: http://upload.wikimedia.org/wikipedia/en/5/50/A_Class_in_Progress.jpg Aliasing: http://i.imgur.com/JrFly.png Light switch: http://www.hapihour.org/wp-content/uploads/2014/04/lighting-design-wall-light-winsome-designer-light-switches-australia-designer-light-switchesdesigner-light-switches-and-platesdesigner-light-switches-coversdesigner- light-switches-graydesign.jpg Steel structure: http://www.jingtabuilding.com/UploadFiles/sl6.jpg Quotes: http://g.fastcompany.net/multisite_files/fastcompany/poster/2013/09/3018353-poster-1280-quotess3.jpg Setter: http://upload.wikimedia.org/wikipedia/commons/b/b4/Rzesz%C3%B3w_Irish_Red_and_White_Setter_1pl.jpg Argument: http://www.familytreecounseling.com/kathysblog/wp-content/uploads/2014/01/arguing_couple.jpg Equal cupcake: http://static.communitytable.com/wp-content/uploads/2013/04/marriage-equality-cupcakes-ftr.jpg Obama truth: http://upload.wikimedia.org/wikipedia/commons/7/7c/Obama_swearing_in.JPG Quiz: http://a622.phobos.apple.com/us/r30/Purple/v4/df/a9/6e/dfa96e6c-ea9b-ee4c-4d6c-f9edf2775e1d/mzl.exfkkuro.png return: http://legacyofshadow.com/wp-content/uploads/2012/04/no-return-sign.jpg spock: http://trekcore.com/gallery/albums/spock09/spock_pb04.jpg London: http://www.100percentoptical.com/images/2014/10/london.jpg Tie fighter: http://img3.wikia.nocookie.net/__cb20090419001710/uncyclopedia/images/f/fe/Darthvader_tie_fighter.jpg