Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Cleaner and Leaner Groovy

240 views

Published on

Groovy magic examples

Published in: Software
  • Be the first to comment

  • Be the first to like this

Cleaner and Leaner Groovy

  1. 1. CLEANER & LEANER GROOVY! © Rowell Belen
  2. 2. @BUILDER @Builder class Premise { def sqFeet def occupants def stories def heatingType def coolingType def homeType def yearBuilt } def premise = Premise.builder() .sqFeet(1200) .occupants(4) .stories(2) .heatingType('Furnace·(Gas)') .coolingType('Central·Air·Conditioning') .homeType('Single·Family·(detached)') .yearBuilt(1995).build() © Rowell Belen
  3. 3. @TOSTRING @ToString(includeNames=true, ignoreNulls = true, excludes="ssn") class Customer { String first, last int age Collection favItems String ssn } def customer = new Customer(first:'Tom', last:'Jones', age:21, favItems:['Books', 'Games'], ssn:'xxx-xx-xxxxx') assert customer.toString() == 'Customer(first:Tom, last:Jones, age:21, favItems:[Books, Games])' © Rowell Belen
  4. 4. @EQUALSANDHASHCODE @EqualsAndHashCode class Actor { String firstName, lastName } def magneto = new Actor(firstName:'Ian', lastName: 'McKellen') def gandalf = new Actor(firstName:'Ian', lastName: 'McKellen') assert magneto == gandalf © Rowell Belen
  5. 5. @TUPLECONSTRUCTOR import groovy.transform.TupleConstructor @TupleConstructor class Athlete { String firstName, lastName } def a1 = new Athlete('Michael', 'Jordan') def a2 = new Athlete('Michael') assert a1.firstName == a2.firstName © Rowell Belen
  6. 6. @LAZY class App { @Lazy AuthService authService = { ctx.getBean('AuthService.class') }() @Lazy // defer expensive initialization ApplicationContext ctx = { new AnnotationConfigApplicationContext(AppConfig.class) }() @Lazy UserService userService Profile getProfile(user){ authService.login(user) userService.findProfile(user) } } © Rowell Belen
  7. 7. @IMMUTABLE @Immutable class User { String email Collection roles } def u = new User(email: 'email@host.com', roles: ['admin', 'user']) // Properties are readonly. shouldFail(ReadOnlyPropertyException) { u.email = 'new@email.com' } // Collections are also wrapped in immutable wrapper classes shouldFail(UnsupportedOperationException) { u.roles << 'new role' } © Rowell Belen
  8. 8. @SINGLETON @Singleton class Zeus { ... } assert Zeus.instance def ex = shouldFail(RuntimeException) { new Zeus() } assert ex.message == "Can't instantiate singleton Zeus. Use Zeus.instance" © Rowell Belen
  9. 9. @DELEGATE class NoisySet { @Delegate Set delegate = new HashSet() @Override boolean add(item) { println "adding $item" delegate.add(item) } } def ns = new NoisySet() ns.add(1) ns.addAll([2, 3]) assert ns.size() == 3 © Rowell Belen
  10. 10. @MEMOIZED @Memoized Long fib(Integer n){ if (n < 2) { return 1 } return fib(n - 1) + fib(n - 2) } © Rowell Belen
  11. 11. @AUTOCLONE @AutoClone class Chef { String name List<String> recipes } def name = 'Gordon Ramsay' def recipes = ['Snail porridge', 'Bacon & egg ice cream'] def c1 = new Chef(name: name, recipes: recipes) def c2 = c1.clone() assert c2.recipes == recipes © Rowell Belen
  12. 12. "PIMP MY LIBRARY" PATTERN © Rowell Belen
  13. 13. @CATEGORY - OVERRIDE class Energy { def usage(){ .. } // return joules } @Category(Energy) class Therms { def usage(){ .. } // override - return therms } use(Therms){ def energy = new Energy() energy.usage() // returns usage in Therms } © Rowell Belen
  14. 14. @CATEGORY - ENHANCE class Energy { def usage(){ .. } // return joules } @Category(Energy) class KilowattHour { def kwUsage(){ .. } // enhance with new method - return usage in kWh } use(KilowattHour){ def energy = new Energy() energy.usage() // returns in joules energy.kwUsage() // returns in kWh } © Rowell Belen
  15. 15. WHAT ABOUT CONCURRENCY? © Rowell Belen
  16. 16. @WITHREADLOCK / @WITHWRITELOCK class PhoneBook { private final phoneNumbers = [:] // multiple readers can access simultaneously // unless lock is obtained by writer @WithReadLock def getNumber(key) { phoneNumbers[key] } // readers will block until lock is released by the writer @WithWriteLock def addNumber(key, value) { phoneNumbers[key] = value } } © Rowell Belen
  17. 17. Concurrent Map/Filter/Reduce Example import static groovyx.gpars.GParsPool.withPool withPool { def numbers = [1, 2, 3, 4, 5, 6] assert [1, 4, 9] == numbers.parallel .map { it * it } .filter { it < 10 } .collection } withPool { assert 55 == [0, 1, 2, 3, 4].parallel .map { it + 1 } .map { it ** 2 } .reduce { a, b -> a + b } } withPool(10) {...} withPool(20, exceptionHandler) {...} © Rowell Belen
  18. 18. Parallel Collections withPool { def numbers = [1, 2, 3, 4, 5, 6] // dynamically enhanced with parallel processing capabilities numbers.eachParallel{ .. } numbers.eachWithIndexParallel{ .. } numbers.collectParallel{ .. } numbers.findAllParallel{ .. } numbers.findAnyParallel{ .. } numbers.findParallel{ .. } numbers.everyParallel{ .. } numbers.anyParallel{ .. } numbers.grepParallel{ .. } numbers.groupByParallel{ .. } numbers.foldParallel{ .. } numbers.minParallel{ .. } numbers.maxParallel{ .. } numbers.sumParallel{ .. } numbers.splitParallel{ .. } numbers.countParallel{ .. } numbers.foldParallel{ .. } } © Rowell Belen
  19. 19. Implicit Task Coordination def getDashboardData(req) { def results = new Dataflows() // These 3 tasks will execute in parallel task { results.user = fetchUserData(req) } task { results.weather = fetchWeatherData(req) } task { results.savings = fetchSavingsData(req) } // Blocks until results.user is bound task { results.devices = fetchDevices(req, results.user.defaultDevice) } results } © Rowell Belen
  20. 20. ERRRMAHHHHGERDD!!! © Rowell Belen

×