SlideShare une entreprise Scribd logo
1  sur  108
Télécharger pour lire hors ligne
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

Contenu connexe

Tendances

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
 

Tendances (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
 

En vedette

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
 

En vedette (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
 

Similaire à 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
 

Similaire à 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
 

Plus de 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
 

Plus de 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
 

Dernier

The Future of Software Development - Devin AI Innovative Approach.pdf
The Future of Software Development - Devin AI Innovative Approach.pdfThe Future of Software Development - Devin AI Innovative Approach.pdf
The Future of Software Development - Devin AI Innovative Approach.pdfSeasiaInfotech2
 
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
 
Vector Databases 101 - An introduction to the world of Vector Databases
Vector Databases 101 - An introduction to the world of Vector DatabasesVector Databases 101 - An introduction to the world of Vector Databases
Vector Databases 101 - An introduction to the world of Vector DatabasesZilliz
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsMark Billinghurst
 
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticscarlostorres15106
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Mattias Andersson
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebUiPathCommunity
 
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)Wonjun Hwang
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsSergiu Bodiu
 
Vertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering TipsVertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering TipsMiki Katsuragi
 
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr LapshynFwdays
 
AI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsAI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsMemoori
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024Stephanie Beckett
 
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Patryk Bandurski
 
DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenHervé Boutemy
 
CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):comworks
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr BaganFwdays
 
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
 
Artificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxArtificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxhariprasad279825
 

Dernier (20)

The Future of Software Development - Devin AI Innovative Approach.pdf
The Future of Software Development - Devin AI Innovative Approach.pdfThe Future of Software Development - Devin AI Innovative Approach.pdf
The Future of Software Development - Devin AI Innovative Approach.pdf
 
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
 
Vector Databases 101 - An introduction to the world of Vector Databases
Vector Databases 101 - An introduction to the world of Vector DatabasesVector Databases 101 - An introduction to the world of Vector Databases
Vector Databases 101 - An introduction to the world of Vector Databases
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR Systems
 
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio Web
 
DMCC Future of Trade Web3 - Special Edition
DMCC Future of Trade Web3 - Special EditionDMCC Future of Trade Web3 - Special Edition
DMCC Future of Trade Web3 - Special Edition
 
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platforms
 
Vertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering TipsVertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering Tips
 
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
 
AI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsAI as an Interface for Commercial Buildings
AI as an Interface for Commercial Buildings
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024
 
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
 
DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache Maven
 
CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan
 
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!
 
Artificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxArtificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptx
 

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