@glaforge
#groovydvx
No semicolons!
class HelloParis {
private String message = 'Hello Paris!';
String greet(String name) {
"$message, $name speaking";
}
}
print new HelloParis().greet('Guillaume');
Slide 18
Slide 18 text
@glaforge
#groovydvx
No semicolons!
class HelloParis {
private String message = 'Hello Paris!';
String greet(String name) {
"$message, $name speaking";
}
}
print new HelloParis().greet('Guillaume');
Slide 19
Slide 19 text
@glaforge
#groovydvx
No semicolons!
class HelloParis {
private String message = 'Hello Paris!'
String greet(String name) {
"$message, $name speaking"
}
}
print new HelloParis().greet('Guillaume')
Slide 20
Slide 20 text
No content
Slide 21
Slide 21 text
@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"
}
}
Slide 22
Slide 22 text
@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
Slide 23
Slide 23 text
@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
Slide 24
Slide 24 text
@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!
Slide 25
Slide 25 text
No content
Slide 26
Slide 26 text
@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
}
}
Slide 27
Slide 27 text
@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
}
}
Slide 28
Slide 28 text
@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
}
}
Slide 29
Slide 29 text
@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
Slide 30
Slide 30 text
No content
Slide 31
Slide 31 text
@glaforge
#groovydvx
Return is optional too
String greet() {
return "$message, $name speaking"
}
Slide 32
Slide 32 text
@glaforge
#groovydvx
Return is optional too
String greet() {
return "$message, $name speaking"
}
Slide 33
Slide 33 text
@glaforge
#groovydvx
Return is optional too
String greet() {
"$message, $name speaking"
}
Slide 34
Slide 34 text
@glaforge
#groovydvx
Return is optional too
String greet() {
"$message, $name speaking"
}
But return is fine for
early returns, or for
clarity of intent
Slide 35
Slide 35 text
@glaforge
#groovydvx
Optional return for if / else
int color(String name) {
if (name == 'red')
1
else if (name == 'green')
2
else
-1
}
Slide 36
Slide 36 text
@glaforge
#groovydvx
Optional return for switch / case
int color(String name) {
switch (name) {
case 'red': 1; break
case 'green': 2; break
default: -1
}
}
Slide 37
Slide 37 text
@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…
@glaforge
#groovydvx
Command chains & named arguments
check that: wine tastes good
Slide 46
Slide 46 text
@glaforge
#groovydvx
Command chains & named arguments
check that: wine tastes good
Parsed as:
check(that: wine).tastes(good)
Slide 47
Slide 47 text
@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"
}
Slide 48
Slide 48 text
@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, {…})
Slide 49
Slide 49 text
No content
Slide 50
Slide 50 text
@glaforge
#groovydvx
Class as first-class citizen
connection.doPost("${BASE_URI}/submit", params,
ResourcesResponse.class)
Slide 51
Slide 51 text
@glaforge
#groovydvx
Class as first-class citizen
connection.doPost("${BASE_URI}/submit", params,
ResourcesResponse)
Slide 52
Slide 52 text
No content
Slide 53
Slide 53 text
@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
}
}
Slide 54
Slide 54 text
@glaforge
#groovydvx
No need for dumb getters and setters
class Person {
String name
int age
}
Slide 55
Slide 55 text
@glaforge
#groovydvx
No need for dumb getters and setters
class Person {
String name
int age
}
Icing on the cake:
add @Immutable
or @Canonical
Slide 56
Slide 56 text
@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
Slide 57
Slide 57 text
No content
Slide 58
Slide 58 text
@glaforge
#groovydvx
Use the named-argument constructor
def p = new Person(name: 'Guillaume',
age: 37)
Slide 59
Slide 59 text
@glaforge
#groovydvx
The @Builder transformation
import groovy.transform.builder.*
@Builder
class Person {
String name
int age
}
Person.builder()
.name('Guillaume')
.age(37)
.build()
Slide 60
Slide 60 text
@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
Slide 61
Slide 61 text
No content
Slide 62
Slide 62 text
@glaforge
#groovydvx
Equals and ==
status != null &&
status.equals(Control.STATUS_COMPLETED)
Slide 63
Slide 63 text
@glaforge
#groovydvx
Equals and ==
status == Control.STATUS_COMPLETED
Slide 64
Slide 64 text
No content
Slide 65
Slide 65 text
@glaforge
#groovydvx
Use single quotes for String constants
def msg = 'Groovy Rocks!'
Slide 66
Slide 66 text
No content
Slide 67
Slide 67 text
@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.*/
Slide 68
Slide 68 text
No content
Slide 69
Slide 69 text
@glaforge
#groovydvx
The Groovy Development Kit
Slide 70
Slide 70 text
@glaforge
#groovydvx
The Groovy Development Kit
Slide 71
Slide 71 text
@glaforge
#groovydvx
The Groovy Development Kit
Know your GDK!
So much groovy-ness in there!
Slide 72
Slide 72 text
No content
Slide 73
Slide 73 text
@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"
}
Slide 74
Slide 74 text
No content
Slide 75
Slide 75 text
@glaforge
#groovydvx
Import aliasing
import java.util.List as juList
import java.awt.List as aList
import javax.swing.WindowConstants as WC
Slide 76
Slide 76 text
@glaforge
#groovydvx
Import aliasing with static imports too
import static java.lang.Integer.parseInt as atoi
assert atoi('123') == 123
@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)
Slide 82
Slide 82 text
No content
Slide 83
Slide 83 text
No content
Slide 84
Slide 84 text
@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
Slide 85
Slide 85 text
@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!
Slide 86
Slide 86 text
No content
Slide 87
Slide 87 text
@glaforge
#groovydvx
Power Assert
def (a, b, c, d) = [10, 20, 30, 610]
assert a + b * c == d - 40
Slide 88
Slide 88 text
@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
Slide 89
Slide 89 text
No content
Slide 90
Slide 90 text
@glaforge
#groovydvx
Calling Elvis for default values
def result = name != null ? name : "Unknown"
def result = name ?: "Unknown"
Slide 91
Slide 91 text
@glaforge
#groovydvx
Calling Elvis for default values
def result = name != null ? name : "Unknown"
def result = name ?: "Unknown"
Groovy Truth
at play here
@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
Slide 97
Slide 97 text
@YourTwitterHandle
@YourTwitterHandle
@glaforge
#groovydvx
Thanks for your attention!
Slide 98
Slide 98 text
@YourTwitterHandle
@YourTwitterHandle
@glaforge
#groovydvx
Q & A