SlideShare ist ein Scribd-Unternehmen logo
1 von 108
Downloaden Sie, um offline zu lesen
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

Weitere ähnliche Inhalte

Was ist angesagt?

Template Haskell Tutorial
Template Haskell TutorialTemplate Haskell Tutorial
Template Haskell Tutorialkizzx2
 
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...takeoutweight
 
Groovy grails types, operators, objects
Groovy grails types, operators, objectsGroovy grails types, operators, objects
Groovy grails types, operators, objectsHusain Dalal
 
Poor Man's Functional Programming
Poor Man's Functional ProgrammingPoor Man's Functional Programming
Poor Man's Functional ProgrammingDmitry Buzdin
 
Being functional in PHP (DPC 2016)
Being functional in PHP (DPC 2016)Being functional in PHP (DPC 2016)
Being functional in PHP (DPC 2016)David de Boer
 
Refactoring to Macros with Clojure
Refactoring to Macros with ClojureRefactoring to Macros with Clojure
Refactoring to Macros with ClojureDmitry Buzdin
 
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 codeKonrad Malawski
 
Is Haskell an acceptable Perl?
Is Haskell an acceptable Perl?Is Haskell an acceptable Perl?
Is Haskell an acceptable Perl?osfameron
 
Grails: a quick tutorial (1)
Grails: a quick tutorial (1)Grails: a quick tutorial (1)
Grails: a quick tutorial (1)Davide Rossi
 
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?Nikita Popov
 
Scalaz 8 vs Akka Actors
Scalaz 8 vs Akka ActorsScalaz 8 vs Akka Actors
Scalaz 8 vs Akka ActorsJohn De Goes
 
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 yearsSaurabh Nanda
 
(map Clojure everyday-tasks)
(map Clojure everyday-tasks)(map Clojure everyday-tasks)
(map Clojure everyday-tasks)Jacek Laskowski
 
Pig Introduction to Pig
Pig Introduction to PigPig Introduction to Pig
Pig Introduction to PigChris Wilkes
 

Was ist angesagt? (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
 

Andere mochten auch

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 ProfitRaimonds Simanovskis
 
Infographic - Pragmatic Technical Debt Management
Infographic - Pragmatic Technical Debt ManagementInfographic - Pragmatic Technical Debt Management
Infographic - Pragmatic Technical Debt ManagementTushar Sharma
 
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 SmellsTushar Sharma
 
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 EncapsulationTushar Sharma
 
Tools for refactoring
Tools for refactoringTools for refactoring
Tools for refactoringTushar Sharma
 
Pragmatic Technical Debt Management
Pragmatic Technical Debt ManagementPragmatic Technical Debt Management
Pragmatic Technical Debt ManagementTushar Sharma
 
Why care about technical debt?
Why care about technical debt?Why care about technical debt?
Why care about technical debt?Tushar Sharma
 
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 DebtTushar Sharma
 
Applying Design Principles in Practice
Applying Design Principles in PracticeApplying Design Principles in Practice
Applying Design Principles in PracticeTushar Sharma
 
SOLID Principles and Design Patterns
SOLID Principles and Design PatternsSOLID Principles and Design Patterns
SOLID Principles and Design PatternsGanesh Samarthyam
 
A Checklist for Design Reviews
A Checklist for Design ReviewsA Checklist for Design Reviews
A Checklist for Design ReviewsTushar Sharma
 
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 DebtTushar Sharma
 

Andere mochten auch (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
 

Ähnlich wie Effective Groovy: Consider a Builder

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
 
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 OrbitZachary Klein
 
ConFess Vienna 2015 - Metaprogramming with Groovy
ConFess Vienna 2015 - Metaprogramming with GroovyConFess Vienna 2015 - Metaprogramming with Groovy
ConFess Vienna 2015 - Metaprogramming with GroovyIván López Martín
 
Herding types with Scala macros
Herding types with Scala macrosHerding types with Scala macros
Herding types with Scala macrosMarina Sigaeva
 
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 GroovyCodecamp Romania
 
Grails 1.2 探検隊 -新たな聖杯をもとめて・・・-
Grails 1.2 探検隊 -新たな聖杯をもとめて・・・-Grails 1.2 探検隊 -新たな聖杯をもとめて・・・-
Grails 1.2 探検隊 -新たな聖杯をもとめて・・・-Tsuyoshi Yamamoto
 
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 Wsloffenauer
 
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 beyondMario Fusco
 
Groovy puzzlers по русски с Joker 2014
Groovy puzzlers по русски с Joker 2014Groovy puzzlers по русски с Joker 2014
Groovy puzzlers по русски с Joker 2014Baruch Sadogursky
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfHiroshi Ono
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfHiroshi Ono
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfHiroshi Ono
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfHiroshi Ono
 
ES6 - Next Generation Javascript
ES6 - Next Generation JavascriptES6 - Next Generation Javascript
ES6 - Next Generation JavascriptRamesh Nair
 
PhpUnit - The most unknown Parts
PhpUnit - The most unknown PartsPhpUnit - The most unknown Parts
PhpUnit - The most unknown PartsBastian Feder
 
Atlassian Groovy Plugins
Atlassian Groovy PluginsAtlassian Groovy Plugins
Atlassian Groovy PluginsPaul King
 
Groovy for java developers
Groovy for java developersGroovy for java developers
Groovy for java developersPuneet Behl
 

Ähnlich wie Effective Groovy: Consider a Builder (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
 

Mehr von GR8Conf

DevOps Enabling Your Team
DevOps Enabling Your TeamDevOps Enabling Your Team
DevOps Enabling Your TeamGR8Conf
 
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 GR8Conf
 
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 developerGR8Conf
 
Metaprogramming with Groovy
Metaprogramming with GroovyMetaprogramming with Groovy
Metaprogramming with GroovyGR8Conf
 
Scraping with Geb
Scraping with GebScraping with Geb
Scraping with GebGR8Conf
 
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 AndroidGR8Conf
 
Ratpack On the Docks
Ratpack On the DocksRatpack On the Docks
Ratpack On the DocksGR8Conf
 
Groovy Powered Clean Code
Groovy Powered Clean CodeGroovy Powered Clean Code
Groovy Powered Clean CodeGR8Conf
 
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 pluginsGR8Conf
 
Performance tuning Grails applications
 Performance tuning Grails applications Performance tuning Grails applications
Performance tuning Grails applicationsGR8Conf
 
Ratpack and Grails 3
 Ratpack and Grails 3 Ratpack and Grails 3
Ratpack and Grails 3GR8Conf
 
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 cloudGR8Conf
 
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 GEBGR8Conf
 
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 VPCGR8Conf
 
The Grails introduction workshop
The Grails introduction workshopThe Grails introduction workshop
The Grails introduction workshopGR8Conf
 
Idiomatic spock
Idiomatic spockIdiomatic spock
Idiomatic spockGR8Conf
 
The Groovy Ecosystem Revisited
The Groovy Ecosystem RevisitedThe Groovy Ecosystem Revisited
The Groovy Ecosystem RevisitedGR8Conf
 
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 examplesGR8Conf
 
Integration using Apache Camel and Groovy
Integration using Apache Camel and GroovyIntegration using Apache Camel and Groovy
Integration using Apache Camel and GroovyGR8Conf
 
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 MachineGR8Conf
 

Mehr von 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
 

Kürzlich hochgeladen

Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxLoriGlavin3
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfAlex Barbosa Coqueiro
 
unit 4 immunoblotting technique complete.pptx
unit 4 immunoblotting technique complete.pptxunit 4 immunoblotting technique complete.pptx
unit 4 immunoblotting technique complete.pptxBkGupta21
 
SALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICESSALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICESmohitsingh558521
 
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024BookNet Canada
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc
 
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Mark Simos
 
Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 3652toLead Limited
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationSlibray Presentation
 
Take control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteTake control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteDianaGray10
 
Commit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyCommit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyAlfredo García Lavilla
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr BaganFwdays
 
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxThe Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxLoriGlavin3
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brandgvaughan
 
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxDigital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxLoriGlavin3
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Commit University
 
DSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningDSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningLars Bell
 
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 
Advanced Computer Architecture – An Introduction
Advanced Computer Architecture – An IntroductionAdvanced Computer Architecture – An Introduction
Advanced Computer Architecture – An IntroductionDilum Bandara
 

Kürzlich hochgeladen (20)

Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdf
 
unit 4 immunoblotting technique complete.pptx
unit 4 immunoblotting technique complete.pptxunit 4 immunoblotting technique complete.pptx
unit 4 immunoblotting technique complete.pptx
 
SALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICESSALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICES
 
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
 
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
 
Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck Presentation
 
Take control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteTake control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test Suite
 
Commit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyCommit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easy
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan
 
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxThe Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brand
 
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxDigital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!
 
DSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningDSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine Tuning
 
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 
Advanced Computer Architecture – An Introduction
Advanced Computer Architecture – An IntroductionAdvanced Computer Architecture – An Introduction
Advanced Computer Architecture – An Introduction
 

Effective Groovy: Consider a Builder

  • 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