GR8Conf 2011: Effective Groovy
Upcoming SlideShare
Loading in...5
×
 

Like this? Share it with your network

Share

GR8Conf 2011: Effective Groovy

on

  • 1,867 views

 

Statistics

Views

Total Views
1,867
Views on SlideShare
1,864
Embed Views
3

Actions

Likes
6
Downloads
38
Comments
0

2 Embeds 3

http://innobead.blogspot.com 2
http://blog.ultrainno.com 1

Accessibility

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

GR8Conf 2011: Effective Groovy Presentation Transcript

  • 1. Effective Groovy Hamlet DArcy Canoo Engineering AG @HamletDRCwww.canoo.com
  • 2. Agenda Effective Java Reconsidered Effective Groovywww.canoo.com
  • 3. Groovy & GrailsJavaRich Business ApplicationsUsabilityRefactoring
  • 4. @HamletDRC http://hamletdarcy.blogspot.com http://www.manning.com/koenig2/ Groovy, CodeNarc, JConch Committer GPars, Griffon, Gradle, etc. Contributor GroovyMag, NFJS magazine author JetBrains Academy Memberwww.canoo.com
  • 5. Effective Groovywww.canoo.com
  • 6. Effective Groovywww.canoo.com
  • 7. Effective Java #2 Consider a builder when faced with many constructor parameterswww.canoo.com
  • 8. Person p = new Person(1, "David", "Villa");www.canoo.com
  • 9. Person p = new Person(1, "David", "Villa"); Person p = new PersonBuilder(). withID(1). withFirstName("David"). withLastName("Villa"). build();www.canoo.com
  • 10. public class PersonBuilder { private String firstName private String lastName private Integer id public PersonBuilder withID(int id) { this.id = id; return this; } public PersonBuilder withFirstName(String firstName) { this.firstName = firstName; return this; } public PersonBuilder withLastName(String lastName) { this.lastName = lastName; return this; } public Person build() { return new Person(id, firstName, lastName); } }www.canoo.com
  • 11. def p = new Person( id: 1, firstName: David, lastName: Villa )www.canoo.com
  • 12. def p = new Person().with { id = 1 firstName = David lastName = Villa delegate }www.canoo.com
  • 13. Effective Java #3 Enforce the singleton property with a private constructorwww.canoo.com
  • 14. @Singleton class Zeus { }www.canoo.com
  • 15. Effective Java #5 Avoid creating unnecessary objectswww.canoo.com
  • 16. assert 12345G instanceof BigIntegerassert 123.45G instanceof BigDecimalwww.canoo.com
  • 17. assert 12345G instanceof BigIntegerassert 123.45G instanceof BigDecimalassert [] instanceof ArrayListassert [:] instanceof LinkedHashMapassert ([] as Set) instanceof HashSetassert ([] as Stack) instanceof Stackwww.canoo.com
  • 18. assert 12345G instanceof BigIntegerassert 123.45G instanceof BigDecimalassert [] instanceof ArrayListassert [:] instanceof LinkedHashMapassert ([] as Set) instanceof HashSetassert ([] as Stack) instanceof StackCaseInsensitiveList list = [] as CaseInsensitiveListassert list instanceof CaseInsensitiveListwww.canoo.com
  • 19. Effective Java #7 Avoid Finalizerswww.canoo.com
  • 20. Effective Java #7 Avoid Finalizerswww.canoo.com
  • 21. Effective Java #8 Obey the general contract when overriding equalswww.canoo.com
  • 22. @EqualsAndHashCode class Person { String firstName String lastName int id }www.canoo.com
  • 23. Effective Java #9 Always override hashCode when your override equalswww.canoo.com
  • 24. Effective Java #9 Always override hashCode when your override equalswww.canoo.com
  • 25. Effective Java #10 Always override toStringwww.canoo.com
  • 26. @ToString class Person { String firstName String lastName int id }www.canoo.com
  • 27. Effective Java #12 Consider implementing Comparablewww.canoo.com
  • 28. def p1 = new Person( id: 1, firstName: Hamlet, lastName: "DArcy")def p2 = new Person( id: 2, firstName: Bro, lastName: "DArcy")assert p1 > p2assert p2 < p1assert (p1 <=> p2) == 1www.canoo.com
  • 29. Effective Java #15 Minimize Mutabilitywww.canoo.com
  • 30. @Immutable class Person { String firstName String lastName int id }www.canoo.com
  • 31. Effective Java #16 Favor composition over inheritancewww.canoo.com
  • 32. class NoisySet extends HashSet { @Override boolean add(i) { println "adding $i" super.add(i) } @Override boolean addAll(Collection i) { for(def x : i) { println "adding $x" } super.addAll(i) } }www.canoo.com
  • 33. class NoisySet implements Set { @Delegate Set delegate = new HashSet() @Override boolean add(i) { println "adding $i" delegate.add(i) } @Override boolean addAll(Collection i) { for(def x : i) { println "adding $x" } delegate.addAll(i) } }www.canoo.com
  • 34. Effective Java #19 Use interfaces only to define typeswww.canoo.com
  • 35. Effective Java #19 Use interfaces only to define typeswww.canoo.com
  • 36. Effective Java #41 Use Overloading Judiciouslywww.canoo.com
  • 37. def function(Collection c) { println received collection } def function(ArrayList a) { println received arraylist } function((Collection) [])www.canoo.com
  • 38. Effective Java Groovy #41 Prefer default parameters to overloadingwww.canoo.com
  • 39. @Log class Calculator { def log(method, parm1, parm2) { log.info( "Method Called: $method" + (parm1 ? ", p1: $parm1" : ) + (parm2 ? ", p2: $parm2" : ) ) } def log(methodName, parm1) { log(methodName, parm1, null) } def log(methodName) { log(methodName, null, null) } def add(x, y) { log(add, x, y); x+y } def increment(x) { log(increment, x); x++ } }www.canoo.com
  • 40. @Log class Calculator { def log(method, parm1 = null, parm2 = null) { log.info( "Method Called: $method" + (parm1 ? ", p1: $parm1" : ) + (parm2 ? ", p2: $parm2" : ) ) } def add(x, y) { log(add, x, y); x+y } def increment(x) { log(increment, x); x++ } }www.canoo.com
  • 41. Effective Java #43 Return empty arrays or collections, not nullswww.canoo.com
  • 42. Effective Java #43 Return empty arrays or collections, not nullswww.canoo.com
  • 43. Effective Java #54 Use native methods judiciouslywww.canoo.com
  • 44. Effective Java #54 Use native methods judiciouslywww.canoo.com
  • 45. Effective Java #56 Adhere to generally accepted naming conventionswww.canoo.com
  • 46. Effective Java #56 Adhere to generally accepted naming conventionswww.canoo.com
  • 47. Effective Java #57 – #61 Use exceptions only for exceptional conditions Avoid unnecessary use of checked exceptions Use checked exceptions for recoverable conditions ...www.canoo.com
  • 48. Effective Java #57 – #61 Use exceptions only for exceptional conditions Avoid unnecessary use of checked exceptions Use checked exceptions for recoverable conditions … and morewww.canoo.com
  • 49. Effective Java #65 Dont ignore exceptionswww.canoo.com
  • 50. Effective Java #65 Dont ignore exceptionswww.canoo.com
  • 51. def b new SwingBuilder().frame( size: [300, 300], show: true, defaultCloseOperation: EXIT_ON_CLOSE) { b = button(text: Click Me) } b.addMouseListener( [ mouseClicked: { println clicked! } ] as MouseListener)www.canoo.com
  • 52. Effective Groovy #7 Implement interfaces as maps judiciouslywww.canoo.com
  • 53. Effective Java #47 Know and use the librarieswww.canoo.com
  • 54. Effective Groovy #2 Know and use the Collection methodswww.canoo.com
  • 55. List<Person> people = Person.findAll(); List<Integer> ids = new ArrayList<Integer>(); for (Person p : people) { ids.add(p.getId()); }www.canoo.com
  • 56. def people = Person.findAll() def ids = people.collect { it.id }www.canoo.com
  • 57. def people = Person.findAll() def ids = people*.idwww.canoo.com
  • 58. Effective Groovy #2a Use collect for List transformationswww.canoo.com
  • 59. List<Person> people = Person.findAll(); Person joe = null; for (Person p : people) { if ("Joe".equals(p.getFirstName())) { joe = p; break; } }www.canoo.com
  • 60. def people = Person.findAll() def joe = people.find { it.firstName == Joe }www.canoo.com
  • 61. List<Person> people = Person.findAll(); List<Person> bucks = new ArrayList<Person>(); for (Person p : people) { if ("Buck".equals(p.getLastName())) { bucks.add(p); } }www.canoo.com
  • 62. def people = Person.findAll() def bucks = people.findAll { it.lastName == Buck }www.canoo.com
  • 63. Effective Groovy #2b Use find and findAll to search listswww.canoo.com
  • 64. List<Person> people = Person.findAll() Map<String, List<Person>> frequencies = new HashMap<String, List<Person>>() for (Person p : people) { if (frequencies.containsKey(p.getLastName())) { frequencies.get(p.getLastName()).add(p) } else { frequencies.put(p.getLastName(), [p]) } }www.canoo.com
  • 65. def people = Person.findAll() def frequencies = people.inject([:]) { acc, p -> acc[p.lastName] ? acc[p.lastName].add(p) : (acc[p.lastName] = [p]) acc }www.canoo.com
  • 66. Effective Groovy #2c Use inject to accumulate data (when collect isnt enough)www.canoo.com
  • 67. def people = Person.findAll() def families = people.unique() { it.lastName }www.canoo.com
  • 68. Effective Groovy #2d Use unique to filter resultswww.canoo.com
  • 69. @Field Map cache = new HashMap<Integer, Integer>() int fib(int seed) { if (seed == 0) return seed if (seed == 1) return seed int minus2 = cache.get(seed - 2) ?: fib(seed – 2) int minus1 = cache.get(seed - 1) ?: fib(seed – 1) cache.put(seed-2, minus2) cache.put(seed-1, minus1) minus2 + minus1 }www.canoo.com
  • 70. def fib fib = { seed -> if (seed == 0) return seed if (seed == 1) return seed fib(seed - 2) + fib(seed – 1) }.memoize()www.canoo.com
  • 71. Effective Groovy #2d Use memoize to cache idempotent method resultswww.canoo.com
  • 72. def fact fact = {int n, BigInteger acc -> n > 1 ? fact.trampoline(n - 1, n * acc) : acc }.trampoline()www.canoo.com
  • 73. Effective Groovy #2e Use trampoline for recursive functionswww.canoo.com
  • 74. Effective Groovy #2f Use join for converting Lists to Stringswww.canoo.com
  • 75. def people = Person.findAll() assert people.any { it.firstName == Joe }www.canoo.com
  • 76. def people = Person.findAll() def b = people.every { it.firstName == Joe } assert !bwww.canoo.com
  • 77. Effective Groovy #2g Use any and every for logical operations on Listswww.canoo.com
  • 78. def people = Person.findAll() for (Person p : people) { println p.firstName }www.canoo.com
  • 79. Effective Groovy #2h Prefer Java for-each to Collections.eachwww.canoo.com
  • 80. Effective Groovy #3 Know and use the File methodswww.canoo.com
  • 81. FileReader reader = new FileReader("./01.groovy"); BufferedReader input = new BufferedReader(reader); String str; while ((str = input.readLine()) != null) { System.out.println(str); } try {input.close();} catch (IOException ex) {}www.canoo.com
  • 82. def file = new File(./01.groovy) println file.textwww.canoo.com
  • 83. def file = new File(./02.groovy) file.eachLine { println it }www.canoo.com
  • 84. def file = new File(./03.groovy) file.text = file.text + n // hello! www.canoo.com
  • 85. def file = new File(./04.groovy) file.append n // better hello! www.canoo.com
  • 86. Effective Java #66 – #74 Concurrencywww.canoo.com
  • 87. class MyDataStore { private final map = [:] def add(key, value) { map.put(key, value) } def getAt(key) { map[key] } }www.canoo.com
  • 88. class MyDataStore { private final map = [:] def synchronized add(key, value) { map.put(key, value) } def synchronized getAt(key) { map[key] } }www.canoo.com
  • 89. class MyDataStore { private final map = [:] private final lock = new Object() def add(key, value) { synchronized(lock) { map.put(key, value) } } def getAt(key) { synchronized(lock) { map[key] } } }www.canoo.com
  • 90. class MyDataStore { private final map = [:] @Synchronized def add(key, value) { map.put(key, value) } @Synchronized def getAt(key) { map[key] } }www.canoo.com
  • 91. Effective Groovy #4a Prefer Declarative Synchronizationwww.canoo.com
  • 92. class MyDataStore { private final map = [:] private final lock = new ReentrantReadWriteLock() def add(key, value) { lock.writeLock().lock() try { map.put(key, value) } finally { lock.writeLock().unlock() } } def getAt(key) { lock.readLock().lock() try { map[key] } finally { lock.readLock().unlock() } } }www.canoo.com
  • 93. class MyDataStore { private final map = [:] private final lock = new ReentrantReadWriteLock() def add(key, value) { withWriteLock(lock) { map.put(key, value) } } def getAt(key) { withReadLock(lock) { map[key] } } private static withWriteLock(def lock, Closure f) { lock.writeLock().lock() try { f() } finally { lock.writeLock().unlock() } } private static withReadLock(def lock, Closure f) { lock.readLock().lock() try { f() } finally { lock.readLock().unlock() } } }www.canoo.com
  • 94. Effective Groovy #8 Prefer ARM blocks to try-finallywww.canoo.com
  • 95. class MyDataStore { private final map = [:] @WithWriteLock def add(key, value) { map.put(key, value) } @WithReadLock def getAt(key) { map[key] } }www.canoo.com
  • 96. Effective Groovy #4b Prefer Declarative Lockingwww.canoo.com
  • 97. def count def t = Thread.start { count = Person.findAll()?.size() } t.join() println countwww.canoo.com
  • 98. def exe = Executors.newSingleThreadExecutor() def future = exe.submit({ Person.findAll()?.size() } as Callable) println future.get() exe.shutdown()www.canoo.com
  • 99. Effective Java #69 Prefer Concurrency Utilitieswww.canoo.com
  • 100. Effective Java #68 Prefer executors and tasks to threadswww.canoo.com
  • 101. @Grab( group = org.codehaus.gpars, module = gpars, version = 0.11) import static groovyx.gpars.dataflow.DataFlow.task import groovyx.gpars.dataflow.DataFlowVariable final count = new DataFlowVariable() task { count << Person.findAll().size() } println count.valwww.canoo.com
  • 102. task { total << personCount.val + personCount.val } task { personCount << Person.findAll().size() } task { addressCount << Address.findAll().size() } println "Total: $total.val"www.canoo.com
  • 103. Effective Groovy #5 Prefer Declarative Coordinationwww.canoo.com
  • 104. Effective Groovy #5½ Learn to Use @Grabwww.canoo.com
  • 105. More Effective Java #21: Use function objects to represent strategies #36: Consistently use @Override #71: Use Lazy Initialization judiciously – See Groovys @Lazy #47: Know & use the libraries – Read the GDK Docs and Release Notes #63: Include Failure-capture information in detailed messages #11: Override Clone Judiciously – See @AutoClone, @Canonicalwww.canoo.com
  • 106. More Effective Groovy #9: Learn to Write a Builder #10: XMLSlurper/Parser - Do not mix with business logic/layers/etc #11: Effective Java #21: Use Function Objects to represent strategies #12: Threading: Avoid Busy Wait #13: Threading: Avoid Double Checked Locking #14: Threading: Avoid Inconsistent Property Locking #15: Threading: Avoid Inconsistent Property Synchronization #16: Threading: Avoid Synchronizing On Boxed Primitive #17: Know and use Elvis operator ?: #18: Excessively use the null-safe dereference operator #19: Understand Operator Overloadingwww.canoo.com
  • 107. More Effective Groovy (with static analysis)www.canoo.com
  • 108. Thanks! http://canoo.com/blog http://hamletdarcy.blogspot.com @HamletDRC http://tv.jetbrains.net/tags/hamlet http://www.youtube.com/hamletdrc Groovy, Grails, Griffon, and Agile Consulting info@canoo.com orwww.canoo.com hamlet.darcy@canoo.com