SlideShare a Scribd company logo
1 of 108
Download to read offline
Effective Groovy
     Hamlet D'Arcy
     Canoo Engineering AG
     @HamletDRC



www.canoo.com
Agenda


        Effective Java Reconsidered
        Effective Groovy




www.canoo.com
Groovy & Grails
Java
Rich Business Applications
Usability
Refactoring
@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 Member




www.canoo.com
Effective Groovy




www.canoo.com
Effective Groovy




www.canoo.com
Effective Java #2




                Consider a builder when faced with
                   many constructor parameters




www.canoo.com
Person p = new Person(1, "David", "Villa");




www.canoo.com
Person p = new Person(1, "David", "Villa");


     Person p = new PersonBuilder().
               withID(1).
               withFirstName("David").
               withLastName("Villa").
               build();




www.canoo.com
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
def p = new Person(
               id: 1,
               firstName: 'David',
               lastName: 'Villa'
     )




www.canoo.com
def p = new Person().with {
         id = 1
         firstName = 'David'
         lastName = 'Villa'
         delegate
     }




www.canoo.com
Effective Java #3




                Enforce the singleton property
                  with a private constructor




www.canoo.com
@Singleton
        class Zeus {
        }




www.canoo.com
Effective Java #5




                Avoid creating unnecessary objects




www.canoo.com
assert 12345G    instanceof BigInteger
assert 123.45G   instanceof BigDecimal




www.canoo.com
assert 12345G     instanceof BigInteger
assert 123.45G    instanceof BigDecimal

assert     []                 instanceof   ArrayList
assert     [:]                instanceof   LinkedHashMap
assert     ([] as Set)        instanceof   HashSet
assert     ([] as Stack)      instanceof   Stack




www.canoo.com
assert 12345G     instanceof BigInteger
assert 123.45G    instanceof BigDecimal

assert     []                 instanceof   ArrayList
assert     [:]                instanceof   LinkedHashMap
assert     ([] as Set)        instanceof   HashSet
assert     ([] as Stack)      instanceof   Stack

CaseInsensitiveList list = [] as CaseInsensitiveList
assert list instanceof CaseInsensitiveList




www.canoo.com
Effective Java #7




                Avoid Finalizers




www.canoo.com
Effective Java #7




                Avoid Finalizers




www.canoo.com
Effective Java #8




                Obey the general contract
                when overriding equals




www.canoo.com
@EqualsAndHashCode
        class Person {
            String firstName
            String lastName
            int id
        }




www.canoo.com
Effective Java #9




                Always override hashCode
                when your override equals




www.canoo.com
Effective Java #9




                Always override hashCode
                when your override equals




www.canoo.com
Effective Java #10




                Always override toString




www.canoo.com
@ToString
        class Person {
            String firstName
            String lastName
            int id
        }




www.canoo.com
Effective Java #12




                Consider implementing Comparable




www.canoo.com
def p1 = new Person(
     id: 1, firstName: 'Hamlet', lastName: "D'Arcy"
)

def p2 = new Person(
     id: 2, firstName: 'Bro', lastName: "D'Arcy"
)

assert p1 > p2
assert p2 < p1
assert (p1 <=> p2) == 1




www.canoo.com
Effective Java #15




                Minimize Mutability




www.canoo.com
@Immutable
        class Person {
            String firstName
            String lastName
            int id
        }




www.canoo.com
Effective Java #16




                Favor composition over inheritance




www.canoo.com
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
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
Effective Java #19




                Use interfaces only to define types




www.canoo.com
Effective Java #19




                Use interfaces only to define types




www.canoo.com
Effective Java #41




                Use Overloading Judiciously




www.canoo.com
def function(Collection c) {
            println 'received collection'
        }

        def function(ArrayList a) {
            println 'received arraylist'
        }

        function((Collection) [])




www.canoo.com
Effective Java Groovy #41




          Prefer default parameters to overloading




www.canoo.com
@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
@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
Effective Java #43




                Return empty arrays or collections,
                             not nulls




www.canoo.com
Effective Java #43




                Return empty arrays or collections,
                             not nulls




www.canoo.com
Effective Java #54




                Use native methods judiciously




www.canoo.com
Effective Java #54




                Use native methods judiciously




www.canoo.com
Effective Java #56




                Adhere to generally accepted
                    naming conventions




www.canoo.com
Effective Java #56




                Adhere to generally accepted
                    naming conventions




www.canoo.com
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
Effective Java #57 – #61


    Use exceptions only for exceptional conditions

    Avoid unnecessary use of checked exceptions

    Use checked exceptions for recoverable conditions

    … and more


www.canoo.com
Effective Java #65




                Don't ignore exceptions




www.canoo.com
Effective Java #65




                Don't ignore exceptions




www.canoo.com
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
Effective Groovy #7




          Implement interfaces as maps judiciously




www.canoo.com
Effective Java #47




                Know and use the libraries




www.canoo.com
Effective Groovy #2




         Know and use the Collection methods




www.canoo.com
List<Person> people = Person.findAll();


        List<Integer> ids = new ArrayList<Integer>();
        for (Person p : people) {
                ids.add(p.getId());
        }




www.canoo.com
def people = Person.findAll()

        def ids = people.collect { it.id }




www.canoo.com
def people = Person.findAll()

        def ids = people*.id




www.canoo.com
Effective Groovy #2a




                Use collect for List transformations




www.canoo.com
List<Person> people = Person.findAll();


        Person joe = null;
        for (Person p : people) {
                if ("Joe".equals(p.getFirstName())) {
                    joe = p;
                    break;
                }
        }



www.canoo.com
def people = Person.findAll()

        def joe = people.find { it.firstName == 'Joe' }




www.canoo.com
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
def people = Person.findAll()


        def bucks = people.findAll {
            it.lastName == 'Buck'
        }




www.canoo.com
Effective Groovy #2b




            Use find and findAll to search lists




www.canoo.com
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
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
Effective Groovy #2c




                Use inject to accumulate data
                 (when collect isn't enough)




www.canoo.com
def people = Person.findAll()

        def families = people.unique() { it.lastName }




www.canoo.com
Effective Groovy #2d




                Use unique to filter results




www.canoo.com
@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
def fib
        fib = { seed   ->
            if (seed   == 0) return seed
            if (seed   == 1) return seed
            fib(seed   - 2) + fib(seed – 1)
        }.memoize()




www.canoo.com
Effective Groovy #2d




                 Use memoize to cache
                idempotent method results




www.canoo.com
def fact
        fact = {int n, BigInteger acc ->
            n > 1 ?
                 fact.trampoline(n - 1, n * acc) :
                 acc
        }.trampoline()




www.canoo.com
Effective Groovy #2e




          Use trampoline for recursive functions




www.canoo.com
Effective Groovy #2f




         Use join for converting Lists to Strings




www.canoo.com
def people = Person.findAll()

        assert people.any { it.firstName == 'Joe' }




www.canoo.com
def people = Person.findAll()

        def b = people.every { it.firstName == 'Joe' }

        assert !b




www.canoo.com
Effective Groovy #2g




                Use any and every for logical
                    operations on Lists




www.canoo.com
def people = Person.findAll()

        for (Person p : people) {
            println p.firstName
        }




www.canoo.com
Effective Groovy #2h




    Prefer Java for-each to Collections.each




www.canoo.com
Effective Groovy #3




                Know and use the File methods




www.canoo.com
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
def file = new File('./01.groovy')
        println file.text




www.canoo.com
def file = new File('./02.groovy')
        file.eachLine { println it }




www.canoo.com
def file = new File('./03.groovy')
        file.text = file.text + 'n // hello! '




www.canoo.com
def file = new File('./04.groovy')
        file.append 'n // better hello! '




www.canoo.com
Effective Java #66 – #74




                  Concurrency




www.canoo.com
class MyDataStore {
            private final map = [:]

                def add(key, value) {
                    map.put(key, value)
                }

                def getAt(key) {
                    map[key]
                }
        }




www.canoo.com
class MyDataStore {
            private final map = [:]

                def synchronized add(key, value) {
                    map.put(key, value)
                }

                def synchronized getAt(key) {
                    map[key]
                }
        }




www.canoo.com
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
class MyDataStore {
            private final map = [:]

                @Synchronized
                def add(key, value) {
                    map.put(key, value)
                }

                @Synchronized
                def getAt(key) {
                    map[key]
                }
        }


www.canoo.com
Effective Groovy #4a




                Prefer Declarative Synchronization




www.canoo.com
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
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
Effective Groovy #8




                Prefer ARM blocks to try-finally




www.canoo.com
class MyDataStore {
            private final map = [:]

                @WithWriteLock
                def add(key, value) {
                    map.put(key, value)
                }

                @WithReadLock
                def getAt(key) {
                    map[key]
                }
        }


www.canoo.com
Effective Groovy #4b




                Prefer Declarative Locking




www.canoo.com
def count
        def t = Thread.start {
                count = Person.findAll()?.size()
        }


        t.join()
        println count




www.canoo.com
def exe = Executors.newSingleThreadExecutor()

        def future = exe.submit({
            Person.findAll()?.size()
        } as Callable)

        println future.get()

        exe.shutdown()




www.canoo.com
Effective Java #69




                Prefer Concurrency Utilities




www.canoo.com
Effective Java #68




                Prefer executors and tasks to threads




www.canoo.com
@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.val


www.canoo.com
task {
            total << personCount.val + personCount.val
        }

        task {
            personCount << Person.findAll().size()
        }

        task {
            addressCount << Address.findAll().size()
        }

        println "Total: $total.val"

www.canoo.com
Effective Groovy #5




                Prefer Declarative Coordination




www.canoo.com
Effective Groovy #5½




                Learn to Use @Grab




www.canoo.com
More Effective Java
    #21: Use function objects to represent strategies
    #36: Consistently use @Override
    #71: Use Lazy Initialization judiciously – See Groovy's @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, @Canonical




www.canoo.com
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 Overloading

www.canoo.com
More Effective Groovy (with static analysis)




www.canoo.com
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 or
www.canoo.com
                         hamlet.darcy@canoo.com

More Related Content

What's hot

Template Haskell Tutorial
Template Haskell TutorialTemplate Haskell Tutorial
Template Haskell Tutorial
kizzx2
 
Poor Man's Functional Programming
Poor Man's Functional ProgrammingPoor Man's Functional Programming
Poor Man's Functional Programming
Dmitry Buzdin
 
Refactoring to Macros with Clojure
Refactoring to Macros with ClojureRefactoring to Macros with Clojure
Refactoring to Macros with Clojure
Dmitry Buzdin
 

What's hot (20)

Template Haskell Tutorial
Template Haskell TutorialTemplate Haskell Tutorial
Template Haskell Tutorial
 
Haste (Same Language, Multiple Platforms) and Tagless Final Style (Same Synta...
Haste (Same Language, Multiple Platforms) and Tagless Final Style (Same Synta...Haste (Same Language, Multiple Platforms) and Tagless Final Style (Same Synta...
Haste (Same Language, Multiple Platforms) and Tagless Final Style (Same Synta...
 
Groovy grails types, operators, objects
Groovy grails types, operators, objectsGroovy grails types, operators, objects
Groovy grails types, operators, objects
 
はじめてのGroovy
はじめてのGroovyはじめてのGroovy
はじめてのGroovy
 
Don't do this
Don't do thisDon't do this
Don't do this
 
Poor Man's Functional Programming
Poor Man's Functional ProgrammingPoor Man's Functional Programming
Poor Man's Functional Programming
 
Groovy intro for OUDL
Groovy intro for OUDLGroovy intro for OUDL
Groovy intro for OUDL
 
Being functional in PHP (DPC 2016)
Being functional in PHP (DPC 2016)Being functional in PHP (DPC 2016)
Being functional in PHP (DPC 2016)
 
Refactoring to Macros with Clojure
Refactoring to Macros with ClojureRefactoring to Macros with Clojure
Refactoring to Macros with Clojure
 
Scalding - Hadoop Word Count in LESS than 70 lines of code
Scalding - Hadoop Word Count in LESS than 70 lines of codeScalding - Hadoop Word Count in LESS than 70 lines of code
Scalding - Hadoop Word Count in LESS than 70 lines of code
 
Is Haskell an acceptable Perl?
Is Haskell an acceptable Perl?Is Haskell an acceptable Perl?
Is Haskell an acceptable Perl?
 
Gorm
GormGorm
Gorm
 
GORM
GORMGORM
GORM
 
Grails: a quick tutorial (1)
Grails: a quick tutorial (1)Grails: a quick tutorial (1)
Grails: a quick tutorial (1)
 
What's new in PHP 8.0?
What's new in PHP 8.0?What's new in PHP 8.0?
What's new in PHP 8.0?
 
Scalaz 8 vs Akka Actors
Scalaz 8 vs Akka ActorsScalaz 8 vs Akka Actors
Scalaz 8 vs Akka Actors
 
Getting property based testing to work after struggling for 3 years
Getting property based testing to work after struggling for 3 yearsGetting property based testing to work after struggling for 3 years
Getting property based testing to work after struggling for 3 years
 
(map Clojure everyday-tasks)
(map Clojure everyday-tasks)(map Clojure everyday-tasks)
(map Clojure everyday-tasks)
 
Unit testing pig
Unit testing pigUnit testing pig
Unit testing pig
 
Pig Introduction to Pig
Pig Introduction to PigPig Introduction to Pig
Pig Introduction to Pig
 

Viewers also liked

Hooked: How to Build Habit-Forming Products
Hooked: How to Build Habit-Forming ProductsHooked: How to Build Habit-Forming Products
Hooked: How to Build Habit-Forming Products
Kissmetrics on SlideShare
 

Viewers also liked (13)

Analyze and Visualize Git Log for Fun and Profit
Analyze and Visualize Git Log for Fun and ProfitAnalyze and Visualize Git Log for Fun and Profit
Analyze and Visualize Git Log for Fun and Profit
 
Infographic - Pragmatic Technical Debt Management
Infographic - Pragmatic Technical Debt ManagementInfographic - Pragmatic Technical Debt Management
Infographic - Pragmatic Technical Debt Management
 
Towards a Principle-based Classification of Structural Design Smells
Towards a Principle-based Classification of Structural Design SmellsTowards a Principle-based Classification of Structural Design Smells
Towards a Principle-based Classification of Structural Design Smells
 
PHAME: Principles of Hierarchy Abstraction Modularization and Encapsulation
PHAME: Principles of Hierarchy Abstraction Modularization and EncapsulationPHAME: Principles of Hierarchy Abstraction Modularization and Encapsulation
PHAME: Principles of Hierarchy Abstraction Modularization and Encapsulation
 
Tools for refactoring
Tools for refactoringTools for refactoring
Tools for refactoring
 
Pragmatic Technical Debt Management
Pragmatic Technical Debt ManagementPragmatic Technical Debt Management
Pragmatic Technical Debt Management
 
Why care about technical debt?
Why care about technical debt?Why care about technical debt?
Why care about technical debt?
 
Refactoring for Software Design Smells: Managing Technical Debt
Refactoring for Software Design Smells: Managing Technical DebtRefactoring for Software Design Smells: Managing Technical Debt
Refactoring for Software Design Smells: Managing Technical Debt
 
Applying Design Principles in Practice
Applying Design Principles in PracticeApplying Design Principles in Practice
Applying Design Principles in Practice
 
SOLID Principles and Design Patterns
SOLID Principles and Design PatternsSOLID Principles and Design Patterns
SOLID Principles and Design Patterns
 
A Checklist for Design Reviews
A Checklist for Design ReviewsA Checklist for Design Reviews
A Checklist for Design Reviews
 
Tools for Identifying and Addressing Technical Debt
Tools for Identifying and Addressing Technical DebtTools for Identifying and Addressing Technical Debt
Tools for Identifying and Addressing Technical Debt
 
Hooked: How to Build Habit-Forming Products
Hooked: How to Build Habit-Forming ProductsHooked: How to Build Habit-Forming Products
Hooked: How to Build Habit-Forming Products
 

Similar to GR8Conf 2011: Effective Groovy

Jython: Python para la plataforma Java (EL2009)
Jython: Python para la plataforma Java (EL2009)Jython: Python para la plataforma Java (EL2009)
Jython: Python para la plataforma Java (EL2009)
Leonardo Soto
 
Jython: Python para la plataforma Java (JRSL 09)
Jython: Python para la plataforma Java (JRSL 09)Jython: Python para la plataforma Java (JRSL 09)
Jython: Python para la plataforma Java (JRSL 09)
Leonardo Soto
 
CodeCamp Iasi 10 march 2012 - Practical Groovy
CodeCamp Iasi 10 march 2012 - Practical GroovyCodeCamp Iasi 10 march 2012 - Practical Groovy
CodeCamp Iasi 10 march 2012 - Practical Groovy
Codecamp Romania
 
FP in Java - Project Lambda and beyond
FP in Java - Project Lambda and beyondFP in Java - Project Lambda and beyond
FP in Java - Project Lambda and beyond
Mario Fusco
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
Hiroshi Ono
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
Hiroshi Ono
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
Hiroshi Ono
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
Hiroshi Ono
 

Similar to GR8Conf 2011: Effective Groovy (20)

Jython: Python para la plataforma Java (EL2009)
Jython: Python para la plataforma Java (EL2009)Jython: Python para la plataforma Java (EL2009)
Jython: Python para la plataforma Java (EL2009)
 
Jython: Python para la plataforma Java (JRSL 09)
Jython: Python para la plataforma Java (JRSL 09)Jython: Python para la plataforma Java (JRSL 09)
Jython: Python para la plataforma Java (JRSL 09)
 
Grails Launchpad - From Ground Zero to Orbit
Grails Launchpad - From Ground Zero to OrbitGrails Launchpad - From Ground Zero to Orbit
Grails Launchpad - From Ground Zero to Orbit
 
ConFess Vienna 2015 - Metaprogramming with Groovy
ConFess Vienna 2015 - Metaprogramming with GroovyConFess Vienna 2015 - Metaprogramming with Groovy
ConFess Vienna 2015 - Metaprogramming with Groovy
 
Herding types with Scala macros
Herding types with Scala macrosHerding types with Scala macros
Herding types with Scala macros
 
CodeCamp Iasi 10 march 2012 - Practical Groovy
CodeCamp Iasi 10 march 2012 - Practical GroovyCodeCamp Iasi 10 march 2012 - Practical Groovy
CodeCamp Iasi 10 march 2012 - Practical Groovy
 
What's New In C# 7
What's New In C# 7What's New In C# 7
What's New In C# 7
 
Grails 1.2 探検隊 -新たな聖杯をもとめて・・・-
Grails 1.2 探検隊 -新たな聖杯をもとめて・・・-Grails 1.2 探検隊 -新たな聖杯をもとめて・・・-
Grails 1.2 探検隊 -新たな聖杯をもとめて・・・-
 
2007 09 10 Fzi Training Groovy Grails V Ws
2007 09 10 Fzi Training Groovy Grails V Ws2007 09 10 Fzi Training Groovy Grails V Ws
2007 09 10 Fzi Training Groovy Grails V Ws
 
FP in Java - Project Lambda and beyond
FP in Java - Project Lambda and beyondFP in Java - Project Lambda and beyond
FP in Java - Project Lambda and beyond
 
Groovy puzzlers по русски с Joker 2014
Groovy puzzlers по русски с Joker 2014Groovy puzzlers по русски с Joker 2014
Groovy puzzlers по русски с Joker 2014
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
 
Groovy Basics
Groovy BasicsGroovy Basics
Groovy Basics
 
ES6 - Next Generation Javascript
ES6 - Next Generation JavascriptES6 - Next Generation Javascript
ES6 - Next Generation Javascript
 
PhpUnit - The most unknown Parts
PhpUnit - The most unknown PartsPhpUnit - The most unknown Parts
PhpUnit - The most unknown Parts
 
Atlassian Groovy Plugins
Atlassian Groovy PluginsAtlassian Groovy Plugins
Atlassian Groovy Plugins
 
Groovy for java developers
Groovy for java developersGroovy for java developers
Groovy for java developers
 

More from GR8Conf

More from GR8Conf (20)

DevOps Enabling Your Team
DevOps Enabling Your TeamDevOps Enabling Your Team
DevOps Enabling Your Team
 
Creating and testing REST contracts with Accurest Gradle
Creating and testing REST contracts with Accurest Gradle Creating and testing REST contracts with Accurest Gradle
Creating and testing REST contracts with Accurest Gradle
 
Mum, I want to be a Groovy full-stack developer
Mum, I want to be a Groovy full-stack developerMum, I want to be a Groovy full-stack developer
Mum, I want to be a Groovy full-stack developer
 
Metaprogramming with Groovy
Metaprogramming with GroovyMetaprogramming with Groovy
Metaprogramming with Groovy
 
Scraping with Geb
Scraping with GebScraping with Geb
Scraping with Geb
 
How to create a conference android app with Groovy and Android
How to create a conference android app with Groovy and AndroidHow to create a conference android app with Groovy and Android
How to create a conference android app with Groovy and Android
 
Ratpack On the Docks
Ratpack On the DocksRatpack On the Docks
Ratpack On the Docks
 
Groovy Powered Clean Code
Groovy Powered Clean CodeGroovy Powered Clean Code
Groovy Powered Clean Code
 
Cut your Grails application to pieces - build feature plugins
Cut your Grails application to pieces - build feature pluginsCut your Grails application to pieces - build feature plugins
Cut your Grails application to pieces - build feature plugins
 
Performance tuning Grails applications
 Performance tuning Grails applications Performance tuning Grails applications
Performance tuning Grails applications
 
Ratpack and Grails 3
 Ratpack and Grails 3 Ratpack and Grails 3
Ratpack and Grails 3
 
Grails & DevOps: continuous integration and delivery in the cloud
Grails & DevOps: continuous integration and delivery in the cloudGrails & DevOps: continuous integration and delivery in the cloud
Grails & DevOps: continuous integration and delivery in the cloud
 
Functional testing your Grails app with GEB
Functional testing your Grails app with GEBFunctional testing your Grails app with GEB
Functional testing your Grails app with GEB
 
Deploying, Scaling, and Running Grails on AWS and VPC
Deploying, Scaling, and Running Grails on AWS and VPCDeploying, Scaling, and Running Grails on AWS and VPC
Deploying, Scaling, and Running Grails on AWS and VPC
 
The Grails introduction workshop
The Grails introduction workshopThe Grails introduction workshop
The Grails introduction workshop
 
Idiomatic spock
Idiomatic spockIdiomatic spock
Idiomatic spock
 
The Groovy Ecosystem Revisited
The Groovy Ecosystem RevisitedThe Groovy Ecosystem Revisited
The Groovy Ecosystem Revisited
 
Groovy 3 and the new Groovy Meta Object Protocol in examples
Groovy 3 and the new Groovy Meta Object Protocol in examplesGroovy 3 and the new Groovy Meta Object Protocol in examples
Groovy 3 and the new Groovy Meta Object Protocol in examples
 
Integration using Apache Camel and Groovy
Integration using Apache Camel and GroovyIntegration using Apache Camel and Groovy
Integration using Apache Camel and Groovy
 
CRaSH the shell for the Java Virtual Machine
CRaSH the shell for the Java Virtual MachineCRaSH the shell for the Java Virtual Machine
CRaSH the shell for the Java Virtual Machine
 

Recently uploaded

Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Victor Rentea
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Safe Software
 
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Victor Rentea
 

Recently uploaded (20)

Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
 
DBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor PresentationDBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor Presentation
 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...
 
Exploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with MilvusExploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with Milvus
 
Six Myths about Ontologies: The Basics of Formal Ontology
Six Myths about Ontologies: The Basics of Formal OntologySix Myths about Ontologies: The Basics of Formal Ontology
Six Myths about Ontologies: The Basics of Formal Ontology
 
[BuildWithAI] Introduction to Gemini.pdf
[BuildWithAI] Introduction to Gemini.pdf[BuildWithAI] Introduction to Gemini.pdf
[BuildWithAI] Introduction to Gemini.pdf
 
Corporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptxCorporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptx
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
 
DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 AmsterdamDEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
 
Vector Search -An Introduction in Oracle Database 23ai.pptx
Vector Search -An Introduction in Oracle Database 23ai.pptxVector Search -An Introduction in Oracle Database 23ai.pptx
Vector Search -An Introduction in Oracle Database 23ai.pptx
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a Fresher
 
presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century education
 
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodPolkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
 
AWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of Terraform
 
Platformless Horizons for Digital Adaptability
Platformless Horizons for Digital AdaptabilityPlatformless Horizons for Digital Adaptability
Platformless Horizons for Digital Adaptability
 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
 
Introduction to Multilingual Retrieval Augmented Generation (RAG)
Introduction to Multilingual Retrieval Augmented Generation (RAG)Introduction to Multilingual Retrieval Augmented Generation (RAG)
Introduction to Multilingual Retrieval Augmented Generation (RAG)
 
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
 
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
 
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
 

GR8Conf 2011: Effective Groovy

  • 1. Effective Groovy Hamlet D'Arcy Canoo Engineering AG @HamletDRC www.canoo.com
  • 2. Agenda Effective Java Reconsidered Effective Groovy www.canoo.com
  • 3. Groovy & Grails Java Rich Business Applications Usability Refactoring
  • 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 Member www.canoo.com
  • 7. Effective Java #2 Consider a builder when faced with many constructor parameters www.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 constructor www.canoo.com
  • 14. @Singleton class Zeus { } www.canoo.com
  • 15. Effective Java #5 Avoid creating unnecessary objects www.canoo.com
  • 16. assert 12345G instanceof BigInteger assert 123.45G instanceof BigDecimal www.canoo.com
  • 17. assert 12345G instanceof BigInteger assert 123.45G instanceof BigDecimal assert [] instanceof ArrayList assert [:] instanceof LinkedHashMap assert ([] as Set) instanceof HashSet assert ([] as Stack) instanceof Stack www.canoo.com
  • 18. assert 12345G instanceof BigInteger assert 123.45G instanceof BigDecimal assert [] instanceof ArrayList assert [:] instanceof LinkedHashMap assert ([] as Set) instanceof HashSet assert ([] as Stack) instanceof Stack CaseInsensitiveList list = [] as CaseInsensitiveList assert list instanceof CaseInsensitiveList www.canoo.com
  • 19. Effective Java #7 Avoid Finalizers www.canoo.com
  • 20. Effective Java #7 Avoid Finalizers www.canoo.com
  • 21. Effective Java #8 Obey the general contract when overriding equals www.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 equals www.canoo.com
  • 24. Effective Java #9 Always override hashCode when your override equals www.canoo.com
  • 25. Effective Java #10 Always override toString www.canoo.com
  • 26. @ToString class Person { String firstName String lastName int id } www.canoo.com
  • 27. Effective Java #12 Consider implementing Comparable www.canoo.com
  • 28. def p1 = new Person( id: 1, firstName: 'Hamlet', lastName: "D'Arcy" ) def p2 = new Person( id: 2, firstName: 'Bro', lastName: "D'Arcy" ) assert p1 > p2 assert p2 < p1 assert (p1 <=> p2) == 1 www.canoo.com
  • 29. Effective Java #15 Minimize Mutability www.canoo.com
  • 30. @Immutable class Person { String firstName String lastName int id } www.canoo.com
  • 31. Effective Java #16 Favor composition over inheritance www.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 types www.canoo.com
  • 35. Effective Java #19 Use interfaces only to define types www.canoo.com
  • 36. Effective Java #41 Use Overloading Judiciously www.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 overloading www.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 nulls www.canoo.com
  • 42. Effective Java #43 Return empty arrays or collections, not nulls www.canoo.com
  • 43. Effective Java #54 Use native methods judiciously www.canoo.com
  • 44. Effective Java #54 Use native methods judiciously www.canoo.com
  • 45. Effective Java #56 Adhere to generally accepted naming conventions www.canoo.com
  • 46. Effective Java #56 Adhere to generally accepted naming conventions www.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 more www.canoo.com
  • 49. Effective Java #65 Don't ignore exceptions www.canoo.com
  • 50. Effective Java #65 Don't ignore exceptions www.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 judiciously www.canoo.com
  • 53. Effective Java #47 Know and use the libraries www.canoo.com
  • 54. Effective Groovy #2 Know and use the Collection methods www.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*.id www.canoo.com
  • 58. Effective Groovy #2a Use collect for List transformations www.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 lists www.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 isn't 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 results www.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 results www.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 functions www.canoo.com
  • 74. Effective Groovy #2f Use join for converting Lists to Strings www.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 !b www.canoo.com
  • 77. Effective Groovy #2g Use any and every for logical operations on Lists www.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.each www.canoo.com
  • 80. Effective Groovy #3 Know and use the File methods www.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.text www.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 Concurrency www.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 Synchronization www.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-finally www.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 Locking www.canoo.com
  • 97. def count def t = Thread.start { count = Person.findAll()?.size() } t.join() println count www.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 Utilities www.canoo.com
  • 100. Effective Java #68 Prefer executors and tasks to threads www.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.val www.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 Coordination www.canoo.com
  • 104. Effective Groovy #5½ Learn to Use @Grab www.canoo.com
  • 105. More Effective Java #21: Use function objects to represent strategies #36: Consistently use @Override #71: Use Lazy Initialization judiciously – See Groovy's @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, @Canonical www.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 Overloading www.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 or www.canoo.com hamlet.darcy@canoo.com