Groovy Refactoring Patterns

Naresha K
Naresha KDeveloper | Technical Excellence Coach | Consultant | Trainer at Independent
Groovy
Refactoring Patterns
Naresha K

@naresha_k

https://blog.nareshak.com/
About me
Developer, Coach, Consultant
Founder & Organiser
Bangalore Groovy User Group
Refactoring
noun: a change made to the internal structure
of software to make it easier to understand
and cheaper to modify without changing its
observable behaviour
verb: to restructure software by applying
a series of refactorings without changing
its observable behaviour.
Refactoring
https://refactoring.com/
Red Green
Refactor
TDD
Address Common Code Smells
A code smell is a surface indication that
usually corresponds to a deeper problem in
the system. The term was first coined by Kent
Beck while helping me with
my Refactoring book.
~ Martin Fowler
https://martinfowler.com/bliki/CodeSmell.html
{ Code Smells }
Long Methods
Duplicated Code Large Class
Long Param List
Primitive Obsession
Data Class
Inappropriate Intimacy
int calculateM1(int value1, int value2, int value3) {
int maxValue
if (value1 > value2 && value1 > value3) {
maxValue = value1
} else if (value2 > value3) {
maxValue = value2
} else {
maxValue = value3
}
maxValue + 1
}
int calculateM2(int value1, int value2, int value3) {
int maxValue
if (value1 > value2 && value1 > value3) {
maxValue = value1
} else if (value2 > value3) {
maxValue = value2
} else {
maxValue = value3
}
maxValue * 2
}
int calculateM1(int value1, int value2, int value3) {
int maxValue
if (value1 > value2 && value1 > value3) {
maxValue = value1
} else if (value2 > value3) {
maxValue = value2
} else {
maxValue = value3
}
maxValue + 1
}
int calculateM2(int value1, int value2, int value3) {
int maxValue
if (value1 > value2 && value1 > value3) {
maxValue = value1
} else if (value2 > value3) {
maxValue = value2
} else {
maxValue = value3
}
maxValue * 2
}
Duplicate Code
Reinventing the wheel
int calculateM1(int value1, int value2, int value3) {
Math.max(value1, Math.max(value2, value3)) + 1
}
int calculateM2(int value1, int value2, int value3) {
Math.max(value1, Math.max(value2, value3)) * 2
}
Groovy Refactoring Patterns
int calculateM1(int value1, int value2, int value3) {
int maxValue
if (value1 > value2 && value1 > value3) {
maxValue = value1
} else if (value2 > value3) {
maxValue = value2
} else {
maxValue = value3
}
maxValue + 1
}
int calculateM2(int value1, int value2, int value3) {
int maxValue
if (value1 > value2 && value1 > value3) {
maxValue = value1
} else if (value2 > value3) {
maxValue = value2
} else {
maxValue = value3
}
maxValue * 2
}
int calculateM1(int value1, int value2, int value3) {
int maxValue
if (value1 > value2 && value1 > value3) {
maxValue = value1
} else if (value2 > value3) {
maxValue = value2
} else {
maxValue = value3
}
maxValue + 1
}
int calculateM1(int value1, int value2, int value3) {
int maxValue = max(value1, value2, value3)
maxValue + 1
}
private int max(int value1, int value2, int value3) {
int maxValue
if (value1 > value2 && value1 > value3) {
maxValue = value1
} else if (value2 > value3) {
maxValue = value2
} else {
maxValue = value3
}
maxValue
}
Extract
Method
int calculateM1(int value1, int value2, int value3) {
int maxValue = max(value1, value2, value3)
maxValue + 1
}
private int max(int value1, int value2, int value3) {
int maxValue
if (value1 > value2 && value1 > value3) {
maxValue = value1
} else if (value2 > value3) {
maxValue = value2
} else {
maxValue = value3
}
maxValue
}
int calculateM2(int value1, int value2, int value3) {
int maxValue
if (value1 > value2 && value1 > value3) {
maxValue = value1
} else if (value2 > value3) {
maxValue = value2
} else {
maxValue = value3
}
maxValue * 2
}
int calculateM1(int value1, int value2, int value3) {
int maxValue = max(value1, value2, value3)
maxValue + 1
}
private int max(int value1, int value2, int value3) {
int maxValue
if (value1 > value2 && value1 > value3) {
maxValue = value1
} else if (value2 > value3) {
maxValue = value2
} else {
maxValue = value3
}
maxValue
}
int calculateM2(int value1, int value2, int value3) {
int maxValue = max(value1, value2, value3)
maxValue * 2
}
private int max(int value1, int value2, int value3) {
int maxValue
if (value1 > value2 && value1 > value3) {
maxValue = value1
} else if (value2 > value3) {
maxValue = value2
} else {
maxValue = value3
}
maxValue
}
private int max(int value1, int value2, int value3) {
Math.max(value1, Math.max(value2, value3))
}
private int max(int value1, int value2, int value3) {
Math.max(value1, Math.max(value2, value3))
}
int calculateM1(int value1, int value2, int value3) {
int maxValue = max(value1, value2, value3)
maxValue + 1
}
int calculateM2(int value1, int value2, int value3) {
int maxValue = max(value1, value2, value3)
maxValue * 2
}
private int max(int value1, int value2, int value3) {
Math.max(value1, Math.max(value2, value3))
}
int calculateM1(int value1, int value2, int value3) {
int maxValue = Math.max(value1, Math.max(value2, value3))
maxValue + 1
}
int calculateM2(int value1, int value2, int value3) {
int maxValue = Math.max(value1, Math.max(value2, value3))
maxValue * 2
}
Inline Method
int calculateM1(int value1, int value2, int value3) {
int maxValue = Math.max(value1, Math.max(value2, value3))
maxValue + 1
}
int calculateM2(int value1, int value2, int value3) {
int maxValue = Math.max(value1, Math.max(value2, value3))
maxValue * 2
}
int calculateM1(int value1, int value2, int value3) {
Math.max(value1, Math.max(value2, value3)) + 1
}
int calculateM2(int value1, int value2, int value3) {
Math.max(value1, Math.max(value2, value3)) * 2
}
Inline
Variable
Importance of small steps
in refactoring
Groovy Refactoring Patterns
List<Integer> numbers = [1, 2, 3, 4, 5]
for(number in numbers) {
println number
}
External Iterator
To
Internal Iterator
List<Integer> numbers = [1, 2, 3, 4, 5]
for(number in numbers) {
println number
}
List<Integer> numbers = [1, 2, 3, 4, 5]
numbers.forEach { println it }
List<Integer> numbers = [1, 2, 3, 4, 5]
numbers.forEach(System.out.&println)
Groovy Refactoring Patterns
Refactoring to
Idiomatic Groovy
def numbers = [1, 2, 3, 4, 5]
for(number in numbers) {
println number
}
def numbers = [1, 2, 3, 4, 5]
numbers.each { println it }
def evenNumbers = []
numbers.each { number ->
if (number % 2 == 0) {
evenNumbers << number
}
}
def evenNumbers = numbers
.findAll { it % 2 == 0}
def sum = 0
numbers.each {
sum += it
}
def sum = numbers.inject(0,
{ result, number -> result + number }
)
List<Integer> numbers = [1, 2, 3, 4, 5]
def result = [:]
numbers.forEach { number ->
result[number] = number * number
}
List<Integer> numbers = [1, 2, 3, 4, 5]
def result = numbers.collectEntries {
[it, it * it]
}
Groovy Refactoring Patterns
List<Integer> numbers = [1, 2, 3, 4, 5]
def evenNumbers = numbers.findAll { it % 2 == 0}
Extract Closure
List<Integer> numbers = [1, 2, 3, 4, 5]
def evenNumbers = numbers.findAll { it % 2 == 0}
List<Integer> numbers = [1, 2, 3, 4, 5]
def evenNumbers = numbers.findAll({ it % 2 == 0 })
List<Integer> numbers = [1, 2, 3, 4, 5]
def isEven = { it % 2 == 0 }
def evenNumbers = numbers.findAll(isEven)
Inline Closure
List<Integer> numbers = [1, 2, 3, 4, 5]
def isEven = { it % 2 == 0 }
def evenNumbers = numbers.findAll(isEven)
List<Integer> numbers = [1, 2, 3, 4, 5]
def evenNumbers = numbers.findAll { it % 2 == 0}
Groovy Refactoring Patterns
def numbers = [1, 2, 3, 4, 5]
def sumOfSuqaresOfEvenNumbers = 0
numbers.forEach { number ->
if(number % 2 == 0 ){
sumOfSuqaresOfEvenNumbers += number * number
}
}
To Functional Style
def numbers = [1, 2, 3, 4, 5]
def sumOfSuqaresOfEvenNumbers = 0
numbers.forEach { number ->
if(number % 2 == 0 ){
sumOfSuqaresOfEvenNumbers += number * number
}
}
def sumOfSuqaresOfEvenNumbers = numbers
.findAll { it % 2 == 0 }
.collect { it * it }
.sum()
Groovy Refactoring Patterns
def numbers = [1, 2, 3, 4, 5]
def sumOfSuqaresOfEvenNumbers = 0
numbers.forEach { number ->
if(number % 2 == 0 ){
sumOfSuqaresOfEvenNumbers += number * number
}
}
def square = { it * it }
def sumOfSuqaresOfEvenNumbers = 0
numbers.forEach { number ->
if(number % 2 == 0 ){
sumOfSuqaresOfEvenNumbers += square(number)
}
}
def square = { it * it }
def sumOfSuqaresOfEvenNumbers = 0
numbers.forEach { number ->
if(number % 2 == 0 ){
sumOfSuqaresOfEvenNumbers += square(number)
}
}
def sumOfSuqaresOfEvenNumbers = 0
def evenNumbers = numbers.findAll { it % 2 == 0}
evenNumbers.forEach { number ->
sumOfSuqaresOfEvenNumbers += square(number)
}
def sumOfSuqaresOfEvenNumbers = 0
def evenNumbers = numbers.findAll { it % 2 == 0}
evenNumbers.forEach { number ->
sumOfSuqaresOfEvenNumbers += square(number)
}
def sumOfSuqaresOfEvenNumbers = 0
def evenNumbers = numbers.findAll { it % 2 == 0}
def squaresOfEvenNumbers = evenNumbers.collect(square)
squaresOfEvenNumbers.forEach { number ->
sumOfSuqaresOfEvenNumbers += number
}
def square = { it * it }
def evenNumbers = numbers.findAll { it % 2 == 0 }
def squaresOfEvenNumbers = evenNumbers
.collect ( square )
def sumOfSuqaresOfEvenNumbers = squaresOfEvenNumbers.sum()
def sumOfSuqaresOfEvenNumbers = 0
def evenNumbers = numbers.findAll { it % 2 == 0}
def squaresOfEvenNumbers = evenNumbers.collect(square)
squaresOfEvenNumbers.forEach { number ->
sumOfSuqaresOfEvenNumbers += number
}
def square = { it * it }
def evenNumbers = numbers.findAll { it % 2 == 0 }
def squaresOfEvenNumbers = evenNumbers
.collect ( square )
def sumOfSuqaresOfEvenNumbers = squaresOfEvenNumbers.sum()
def sumOfSuqaresOfEvenNumbers = numbers
.findAll { it % 2 == 0 }
.collect (square)
.sum()
Inline
Groovy Refactoring Patterns
class Multiplier {
private final int times
Multiplier(int times) {
this.times = times
}
int multiply(int number) {
times * number
}
}
Multiplier doubler = new Multiplier(2)
Multiplier triple = new Multiplier(3)
println doubler.multiply(10)
println triple.multiply(10)
def multiply = { int times, int number ->
times * number
}
def doubler = multiply.curry(2)
def triple = multiply.curry(3)
println doubler(10)
println triple(10)
Groovy Refactoring Patterns
def numbers = [1, 2, 3, 4, 5, 6]
println numbers
.findAll { it % 2 == 0 }
.find { it > 2 }
To Streams API
def numbers = [1, 2, 3, 4, 5, 6]
println numbers
.findAll { it % 2 == 0 }
.find { it > 2 }
def numbers = [1, 2, 3, 4, 5, 6]
println numbers
.stream()
.filter { it % 2 == 0 }
.filter { it > 2 }
.findFirst()
.orElse(null)
Groovy Refactoring Patterns
interface CanSwim {
def swim()
}
class Fish implements CanSwim {
def swim() {
println "Fish Swimming"
}
}
class Person implements CanSwim {
def swim() {
println "Person Swimming"
}
}
To Dynamic Groovy
interface CanSwim {
def swim()
}
class Fish implements CanSwim {
def swim() {
println "Fish Swimming"
}
}
class Person implements CanSwim {
def swim() {
println "Person Swimming"
}
}
CanSwim swimmer = new Person() //new Fish()
swimmer.swim()
interface CanSwim {
def swim()
}
class Fish implements CanSwim {
def swim() {
println "Fish Swimming"
}
}
class Person implements CanSwim {
def swim() {
println "Person Swimming"
}
}
def swimmer = new Person() //new Fish()
swimmer.swim()
Groovy Refactoring Patterns
class Employee {
def employeeId
def firstName
def lastName
def dateOfBirth
def toSummaryString() {
"$employeeId -> $firstname"
}
}
class Employee {
def employeeId
def firstName
def lastName
def dateOfBirth
def toSummaryString() {
"$employeeId -> $firstname"
}
}
To Static Groovy
class Employee {
def employeeId
def firstName
def lastName
def dateOfBirth
def toSummaryString() {
"$employeeId -> $firstname"
}
}
Exception in thread "main" groovy.lang.MissingPropertyException:
No such property: firstname for class
@TypeChecked
class Employee {
def employeeId
def firstName
def lastName
def dateOfBirth
def toSummaryString() {
"$employeeId -> $firstname"
}
}
Error:(17, 30) Groovyc: [Static type checking] -
The variable [firstname] is undeclared.
@TypeChecked
class Employee {
def employeeId
def firstName
def lastName
def dateOfBirth
def toSummaryString() {
"$employeeId -> $firstname"
}
}
@TypeChecked
class Employee {
String employeeId
String firstName
String lastName
LocalDateTime dateOfBirth
def toSummaryString() {
"$employeeId -> $firstname"
}
}
TypeChecked
Vs
CompileStatic
class Greeter {
String message
def greet() {
message
}
}
@TypeChecked
def runTypeChecked(Greeter greeter) {
println greeter.greet()
}
@CompileStatic
def runCompileStatic(Greeter greeter) {
println greeter.greet()
}
def greeter = new Greeter(message: 'Good Morning')
greeter.metaClass.greet = { "Hello, ${delegate.message}" }
runTypeChecked(greeter)
runCompileStatic(greeter)
Hello, Good Morning
Good Morning
@Transactional
class MyService {
@Transactional(propagation = Propagation.REQUIRES_NEW)
def m1() {}
def m2(){
m1()
}
}
Introduce Meta-programming
@Transactional
class MyService implements ApplicationContextAware {
ApplicationContext context
@Transactional(propagation = Propagation.REQUIRES_NEW)
def m1() {}
def m2() {
MyService service = context.getBean('myService')
service.m1()
}
@Override
void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
context = applicationContext
}
}
def grailsApplication
def init = { servletContext ->
injectSelfProxy()
}
private def injectSelfProxy(){
for (sc in grailsApplication.serviceClasses) {
String propertyName = sc.propertyName
sc.clazz.metaClass.getMyProxy = { ->
grailsApplication.mainContext
.getBean(propertyName)
}
}
}
@Transactional
class MyService {
ApplicationContext context
@Transactional(propagation = Propagation.REQUIRES_NEW)
def m1() {}
def m2() {
myProxy.m1()
}
}
Introduce Traits
class Product {
UUID uuid = UUID.randomUUID()
//other fields
}
class Order {
UUID uuid = UUID.randomUUID()
//other fields
}
class Product {
UUID uuid = UUID.randomUUID()
//other fields
}
class Order {
UUID uuid = UUID.randomUUID()
//other fields
}
trait BusinessObject {
}
class Product implements BusinessObject {
//other fields
}
class Order implements BusinessObject {
//other fields
}
trait BusinessObject {
UUID uuid = UUID.randomUUID()
}
Groovy Refactoring Patterns
class Technologies extends ArrayList {
def filterGr8() {
this.findAll { it.startsWith('Gr')}
}
}
Technologies list =
[‘Groovy', 'Grails', 'Gradle', 'Java'] as Technologies
println list
println list.filterGr8()
Replace Inheritance
with Delegation
class Technologies {
@Delegate
private List list
Technologies(List list) {
this.list = list
}
def filterGr8() {
list.findAll { it.startsWith('Gr') }
}
}
Thank You
1 of 83

Recommended

Merge sort: illustrated step-by-step walk through by
Merge sort: illustrated step-by-step walk throughMerge sort: illustrated step-by-step walk through
Merge sort: illustrated step-by-step walk throughYoshi Watanabe
8.3K views48 slides
Python tuples and Dictionary by
Python   tuples and DictionaryPython   tuples and Dictionary
Python tuples and DictionaryAswini Dharmaraj
247 views29 slides
52 notation and algebra of functions by
52 notation and algebra of functions52 notation and algebra of functions
52 notation and algebra of functionsmath126
356 views95 slides
Alg2 lessons 3 1 and 3-2 by
Alg2 lessons 3 1 and 3-2Alg2 lessons 3 1 and 3-2
Alg2 lessons 3 1 and 3-2Carol Defreese
144 views11 slides
Python an-intro youtube-livestream-day2 by
Python an-intro youtube-livestream-day2Python an-intro youtube-livestream-day2
Python an-intro youtube-livestream-day2MAHALAKSHMI P
106 views25 slides
Pytho dictionaries by
Pytho dictionaries Pytho dictionaries
Pytho dictionaries BMS Institute of Technology
143 views15 slides

More Related Content

What's hot

Python Usage (5-minute-summary) by
Python Usage (5-minute-summary)Python Usage (5-minute-summary)
Python Usage (5-minute-summary)Ohgyun Ahn
5.1K views29 slides
Pre-Bootcamp introduction to Elixir by
Pre-Bootcamp introduction to ElixirPre-Bootcamp introduction to Elixir
Pre-Bootcamp introduction to ElixirPaweł Dawczak
128 views175 slides
Python Regular Expressions by
Python Regular ExpressionsPython Regular Expressions
Python Regular ExpressionsBMS Institute of Technology
414 views16 slides
Python lists by
Python listsPython lists
Python listsKrishna Nanda
104 views36 slides
DATA STRUCTURE CLASS 12 COMPUTER SCIENCE by
DATA STRUCTURE CLASS 12 COMPUTER SCIENCEDATA STRUCTURE CLASS 12 COMPUTER SCIENCE
DATA STRUCTURE CLASS 12 COMPUTER SCIENCEDev Chauhan
130 views6 slides
Python for High School Programmers by
Python for High School ProgrammersPython for High School Programmers
Python for High School ProgrammersSiva Arunachalam
1.9K views106 slides

What's hot(16)

Python Usage (5-minute-summary) by Ohgyun Ahn
Python Usage (5-minute-summary)Python Usage (5-minute-summary)
Python Usage (5-minute-summary)
Ohgyun Ahn5.1K views
Pre-Bootcamp introduction to Elixir by Paweł Dawczak
Pre-Bootcamp introduction to ElixirPre-Bootcamp introduction to Elixir
Pre-Bootcamp introduction to Elixir
Paweł Dawczak128 views
DATA STRUCTURE CLASS 12 COMPUTER SCIENCE by Dev Chauhan
DATA STRUCTURE CLASS 12 COMPUTER SCIENCEDATA STRUCTURE CLASS 12 COMPUTER SCIENCE
DATA STRUCTURE CLASS 12 COMPUTER SCIENCE
Dev Chauhan130 views
Python for High School Programmers by Siva Arunachalam
Python for High School ProgrammersPython for High School Programmers
Python for High School Programmers
Siva Arunachalam1.9K views
Algebra 6 by Mang Oha
Algebra 6Algebra 6
Algebra 6
Mang Oha2.5K views
Комплекс тоо цуврал хичээл-2 by Март
Комплекс тоо цуврал хичээл-2Комплекс тоо цуврал хичээл-2
Комплекс тоо цуврал хичээл-2
Март 2.5K views
Python data structures by Harry Potter
Python data structuresPython data structures
Python data structures
Harry Potter113 views
Day 4 reviewwithchainandpart by jbianco9910
Day 4  reviewwithchainandpartDay 4  reviewwithchainandpart
Day 4 reviewwithchainandpart
jbianco9910174 views
chap 2 Ex#1.1 by Ans Ali
chap 2 Ex#1.1chap 2 Ex#1.1
chap 2 Ex#1.1
Ans Ali89 views
10.5 more on language of functions x by math260
10.5 more on language of functions x10.5 more on language of functions x
10.5 more on language of functions x
math260202 views

Similar to Groovy Refactoring Patterns

bobok by
bobokbobok
bobokAdi Pandarangga
635 views45 slides
Coding Language Python Please look at the code that is give.pdf by
Coding Language Python Please look at the code that is give.pdfCoding Language Python Please look at the code that is give.pdf
Coding Language Python Please look at the code that is give.pdfaggarwalcollection1
3 views5 slides
11 1. multi-dimensional array eng by
11 1. multi-dimensional array eng11 1. multi-dimensional array eng
11 1. multi-dimensional array eng웅식 전
676 views16 slides
Hitchhiker's Guide to Functional Programming by
Hitchhiker's Guide to Functional ProgrammingHitchhiker's Guide to Functional Programming
Hitchhiker's Guide to Functional ProgrammingSergey Shishkin
207 views40 slides
Problem 1 Show the comparison of runtime of linear search and binar.pdf by
Problem 1 Show the comparison of runtime of linear search and binar.pdfProblem 1 Show the comparison of runtime of linear search and binar.pdf
Problem 1 Show the comparison of runtime of linear search and binar.pdfebrahimbadushata00
2 views8 slides
Gentle Introduction to Functional Programming by
Gentle Introduction to Functional ProgrammingGentle Introduction to Functional Programming
Gentle Introduction to Functional ProgrammingSaurabh Singh
276 views18 slides

Similar to Groovy Refactoring Patterns(20)

Coding Language Python Please look at the code that is give.pdf by aggarwalcollection1
Coding Language Python Please look at the code that is give.pdfCoding Language Python Please look at the code that is give.pdf
Coding Language Python Please look at the code that is give.pdf
11 1. multi-dimensional array eng by 웅식 전
11 1. multi-dimensional array eng11 1. multi-dimensional array eng
11 1. multi-dimensional array eng
웅식 전676 views
Hitchhiker's Guide to Functional Programming by Sergey Shishkin
Hitchhiker's Guide to Functional ProgrammingHitchhiker's Guide to Functional Programming
Hitchhiker's Guide to Functional Programming
Sergey Shishkin207 views
Problem 1 Show the comparison of runtime of linear search and binar.pdf by ebrahimbadushata00
Problem 1 Show the comparison of runtime of linear search and binar.pdfProblem 1 Show the comparison of runtime of linear search and binar.pdf
Problem 1 Show the comparison of runtime of linear search and binar.pdf
Gentle Introduction to Functional Programming by Saurabh Singh
Gentle Introduction to Functional ProgrammingGentle Introduction to Functional Programming
Gentle Introduction to Functional Programming
Saurabh Singh276 views
Raspberry Pi - Lecture 5 Python for Raspberry Pi by Mohamed Abdallah
Raspberry Pi - Lecture 5 Python for Raspberry PiRaspberry Pi - Lecture 5 Python for Raspberry Pi
Raspberry Pi - Lecture 5 Python for Raspberry Pi
Mohamed Abdallah1.8K views
I am working on a homework that requires us to write several functio.pdf by info961251
I am working on a homework that requires us to write several functio.pdfI am working on a homework that requires us to write several functio.pdf
I am working on a homework that requires us to write several functio.pdf
info9612512 views
Mixing functional programming approaches in an object oriented language by Mark Needham
Mixing functional programming approaches in an object oriented languageMixing functional programming approaches in an object oriented language
Mixing functional programming approaches in an object oriented language
Mark Needham719 views
Swift 5.1 Language Guide Notes.pdf by JkPoppy
Swift 5.1 Language Guide Notes.pdfSwift 5.1 Language Guide Notes.pdf
Swift 5.1 Language Guide Notes.pdf
JkPoppy8 views
Beautiful python - PyLadies by Alicia Pérez
Beautiful python - PyLadiesBeautiful python - PyLadies
Beautiful python - PyLadies
Alicia Pérez389 views
Basic operations by novi reandy sasmita by beasiswa
Basic operations by novi reandy sasmitaBasic operations by novi reandy sasmita
Basic operations by novi reandy sasmita
beasiswa358 views
Step 1 Implement the getSortedRunLength() methodImplement the get.pdf by aloeplusint
Step 1 Implement the getSortedRunLength() methodImplement the get.pdfStep 1 Implement the getSortedRunLength() methodImplement the get.pdf
Step 1 Implement the getSortedRunLength() methodImplement the get.pdf
aloeplusint67 views
Underscore.js by timourian
Underscore.jsUnderscore.js
Underscore.js
timourian1.6K views

More from Naresha K

The Groovy Way of Testing with Spock by
The Groovy Way of Testing with SpockThe Groovy Way of Testing with Spock
The Groovy Way of Testing with SpockNaresha K
240 views40 slides
Evolving with Java - How to Remain Effective by
Evolving with Java - How to Remain EffectiveEvolving with Java - How to Remain Effective
Evolving with Java - How to Remain EffectiveNaresha K
243 views74 slides
Take Control of your Integration Testing with TestContainers by
Take Control of your Integration Testing with TestContainersTake Control of your Integration Testing with TestContainers
Take Control of your Integration Testing with TestContainersNaresha K
268 views50 slides
Implementing Resilience with Micronaut by
Implementing Resilience with MicronautImplementing Resilience with Micronaut
Implementing Resilience with MicronautNaresha K
343 views20 slides
Take Control of your Integration Testing with TestContainers by
Take Control of your Integration Testing with TestContainersTake Control of your Integration Testing with TestContainers
Take Control of your Integration Testing with TestContainersNaresha K
281 views21 slides
Favouring Composition - The Groovy Way by
Favouring Composition - The Groovy WayFavouring Composition - The Groovy Way
Favouring Composition - The Groovy WayNaresha K
229 views48 slides

More from Naresha K(20)

The Groovy Way of Testing with Spock by Naresha K
The Groovy Way of Testing with SpockThe Groovy Way of Testing with Spock
The Groovy Way of Testing with Spock
Naresha K240 views
Evolving with Java - How to Remain Effective by Naresha K
Evolving with Java - How to Remain EffectiveEvolving with Java - How to Remain Effective
Evolving with Java - How to Remain Effective
Naresha K243 views
Take Control of your Integration Testing with TestContainers by Naresha K
Take Control of your Integration Testing with TestContainersTake Control of your Integration Testing with TestContainers
Take Control of your Integration Testing with TestContainers
Naresha K268 views
Implementing Resilience with Micronaut by Naresha K
Implementing Resilience with MicronautImplementing Resilience with Micronaut
Implementing Resilience with Micronaut
Naresha K343 views
Take Control of your Integration Testing with TestContainers by Naresha K
Take Control of your Integration Testing with TestContainersTake Control of your Integration Testing with TestContainers
Take Control of your Integration Testing with TestContainers
Naresha K281 views
Favouring Composition - The Groovy Way by Naresha K
Favouring Composition - The Groovy WayFavouring Composition - The Groovy Way
Favouring Composition - The Groovy Way
Naresha K229 views
Effective Java with Groovy - How Language Influences Adoption of Good Practices by Naresha K
Effective Java with Groovy - How Language Influences Adoption of Good PracticesEffective Java with Groovy - How Language Influences Adoption of Good Practices
Effective Java with Groovy - How Language Influences Adoption of Good Practices
Naresha K294 views
What's in Groovy for Functional Programming by Naresha K
What's in Groovy for Functional ProgrammingWhat's in Groovy for Functional Programming
What's in Groovy for Functional Programming
Naresha K275 views
Effective Java with Groovy & Kotlin - How Languages Influence Adoption of Goo... by Naresha K
Effective Java with Groovy & Kotlin - How Languages Influence Adoption of Goo...Effective Java with Groovy & Kotlin - How Languages Influence Adoption of Goo...
Effective Java with Groovy & Kotlin - How Languages Influence Adoption of Goo...
Naresha K208 views
Effective Java with Groovy & Kotlin How Languages Influence Adoption of Good ... by Naresha K
Effective Java with Groovy & Kotlin How Languages Influence Adoption of Good ...Effective Java with Groovy & Kotlin How Languages Influence Adoption of Good ...
Effective Java with Groovy & Kotlin How Languages Influence Adoption of Good ...
Naresha K162 views
Eclipse Collections, Java Streams & Vavr - What's in them for Functional Pro... by Naresha K
Eclipse Collections, Java Streams & Vavr - What's in them for  Functional Pro...Eclipse Collections, Java Streams & Vavr - What's in them for  Functional Pro...
Eclipse Collections, Java Streams & Vavr - What's in them for Functional Pro...
Naresha K499 views
Implementing Cloud-Native Architectural Patterns with Micronaut by Naresha K
Implementing Cloud-Native Architectural Patterns with MicronautImplementing Cloud-Native Architectural Patterns with Micronaut
Implementing Cloud-Native Architectural Patterns with Micronaut
Naresha K402 views
Groovy - Why and Where? by Naresha K
Groovy  - Why and Where?Groovy  - Why and Where?
Groovy - Why and Where?
Naresha K79 views
Leveraging Micronaut on AWS Lambda by Naresha K
Leveraging Micronaut on AWS LambdaLeveraging Micronaut on AWS Lambda
Leveraging Micronaut on AWS Lambda
Naresha K310 views
Implementing Cloud-native Architectural Patterns with Micronaut by Naresha K
Implementing Cloud-native Architectural Patterns with MicronautImplementing Cloud-native Architectural Patterns with Micronaut
Implementing Cloud-native Architectural Patterns with Micronaut
Naresha K667 views
Effective Java with Groovy by Naresha K
Effective Java with GroovyEffective Java with Groovy
Effective Java with Groovy
Naresha K501 views
Evolving with Java - How to remain Relevant and Effective by Naresha K
Evolving with Java - How to remain Relevant and EffectiveEvolving with Java - How to remain Relevant and Effective
Evolving with Java - How to remain Relevant and Effective
Naresha K294 views
Effective Java with Groovy - How Language can Influence Good Practices by Naresha K
Effective Java with Groovy - How Language can Influence Good PracticesEffective Java with Groovy - How Language can Influence Good Practices
Effective Java with Groovy - How Language can Influence Good Practices
Naresha K311 views
Beyond Lambdas & Streams - Functional Fluency in Java by Naresha K
Beyond Lambdas & Streams - Functional Fluency in JavaBeyond Lambdas & Streams - Functional Fluency in Java
Beyond Lambdas & Streams - Functional Fluency in Java
Naresha K186 views
GORM - The polyglot data access toolkit by Naresha K
GORM - The polyglot data access toolkitGORM - The polyglot data access toolkit
GORM - The polyglot data access toolkit
Naresha K523 views

Recently uploaded

360 graden fabriek by
360 graden fabriek360 graden fabriek
360 graden fabriekinfo33492
138 views25 slides
Using Qt under LGPL-3.0 by
Using Qt under LGPL-3.0Using Qt under LGPL-3.0
Using Qt under LGPL-3.0Burkhard Stubert
12 views11 slides
Airline Booking Software by
Airline Booking SoftwareAirline Booking Software
Airline Booking SoftwareSharmiMehta
6 views26 slides
HarshithAkkapelli_Presentation.pdf by
HarshithAkkapelli_Presentation.pdfHarshithAkkapelli_Presentation.pdf
HarshithAkkapelli_Presentation.pdfharshithakkapelli
12 views16 slides
What is API by
What is APIWhat is API
What is APIartembondar5
10 views15 slides
JioEngage_Presentation.pptx by
JioEngage_Presentation.pptxJioEngage_Presentation.pptx
JioEngage_Presentation.pptxadmin125455
6 views4 slides

Recently uploaded(20)

360 graden fabriek by info33492
360 graden fabriek360 graden fabriek
360 graden fabriek
info33492138 views
Airline Booking Software by SharmiMehta
Airline Booking SoftwareAirline Booking Software
Airline Booking Software
SharmiMehta6 views
JioEngage_Presentation.pptx by admin125455
JioEngage_Presentation.pptxJioEngage_Presentation.pptx
JioEngage_Presentation.pptx
admin1254556 views
How Workforce Management Software Empowers SMEs | TraQSuite by TraQSuite
How Workforce Management Software Empowers SMEs | TraQSuiteHow Workforce Management Software Empowers SMEs | TraQSuite
How Workforce Management Software Empowers SMEs | TraQSuite
TraQSuite5 views
20231129 - Platform @ localhost 2023 - Application-driven infrastructure with... by sparkfabrik
20231129 - Platform @ localhost 2023 - Application-driven infrastructure with...20231129 - Platform @ localhost 2023 - Application-driven infrastructure with...
20231129 - Platform @ localhost 2023 - Application-driven infrastructure with...
sparkfabrik8 views
Dapr Unleashed: Accelerating Microservice Development by Miroslav Janeski
Dapr Unleashed: Accelerating Microservice DevelopmentDapr Unleashed: Accelerating Microservice Development
Dapr Unleashed: Accelerating Microservice Development
Miroslav Janeski12 views
predicting-m3-devopsconMunich-2023.pptx by Tier1 app
predicting-m3-devopsconMunich-2023.pptxpredicting-m3-devopsconMunich-2023.pptx
predicting-m3-devopsconMunich-2023.pptx
Tier1 app7 views
Unlocking the Power of AI in Product Management - A Comprehensive Guide for P... by NimaTorabi2
Unlocking the Power of AI in Product Management - A Comprehensive Guide for P...Unlocking the Power of AI in Product Management - A Comprehensive Guide for P...
Unlocking the Power of AI in Product Management - A Comprehensive Guide for P...
NimaTorabi215 views
Bootstrapping vs Venture Capital.pptx by Zeljko Svedic
Bootstrapping vs Venture Capital.pptxBootstrapping vs Venture Capital.pptx
Bootstrapping vs Venture Capital.pptx
Zeljko Svedic12 views
Quality Engineer: A Day in the Life by John Valentino
Quality Engineer: A Day in the LifeQuality Engineer: A Day in the Life
Quality Engineer: A Day in the Life
John Valentino6 views
DRYiCE™ iAutomate: AI-enhanced Intelligent Runbook Automation by HCLSoftware
DRYiCE™ iAutomate: AI-enhanced Intelligent Runbook AutomationDRYiCE™ iAutomate: AI-enhanced Intelligent Runbook Automation
DRYiCE™ iAutomate: AI-enhanced Intelligent Runbook Automation
HCLSoftware6 views
Introduction to Git Source Control by John Valentino
Introduction to Git Source ControlIntroduction to Git Source Control
Introduction to Git Source Control
John Valentino5 views
Generic or specific? Making sensible software design decisions by Bert Jan Schrijver
Generic or specific? Making sensible software design decisionsGeneric or specific? Making sensible software design decisions
Generic or specific? Making sensible software design decisions

Groovy Refactoring Patterns

  • 2. About me Developer, Coach, Consultant Founder & Organiser Bangalore Groovy User Group
  • 4. noun: a change made to the internal structure of software to make it easier to understand and cheaper to modify without changing its observable behaviour verb: to restructure software by applying a series of refactorings without changing its observable behaviour. Refactoring https://refactoring.com/
  • 7. A code smell is a surface indication that usually corresponds to a deeper problem in the system. The term was first coined by Kent Beck while helping me with my Refactoring book. ~ Martin Fowler https://martinfowler.com/bliki/CodeSmell.html
  • 8. { Code Smells } Long Methods Duplicated Code Large Class Long Param List Primitive Obsession Data Class Inappropriate Intimacy
  • 9. int calculateM1(int value1, int value2, int value3) { int maxValue if (value1 > value2 && value1 > value3) { maxValue = value1 } else if (value2 > value3) { maxValue = value2 } else { maxValue = value3 } maxValue + 1 } int calculateM2(int value1, int value2, int value3) { int maxValue if (value1 > value2 && value1 > value3) { maxValue = value1 } else if (value2 > value3) { maxValue = value2 } else { maxValue = value3 } maxValue * 2 }
  • 10. int calculateM1(int value1, int value2, int value3) { int maxValue if (value1 > value2 && value1 > value3) { maxValue = value1 } else if (value2 > value3) { maxValue = value2 } else { maxValue = value3 } maxValue + 1 } int calculateM2(int value1, int value2, int value3) { int maxValue if (value1 > value2 && value1 > value3) { maxValue = value1 } else if (value2 > value3) { maxValue = value2 } else { maxValue = value3 } maxValue * 2 } Duplicate Code Reinventing the wheel
  • 11. int calculateM1(int value1, int value2, int value3) { Math.max(value1, Math.max(value2, value3)) + 1 } int calculateM2(int value1, int value2, int value3) { Math.max(value1, Math.max(value2, value3)) * 2 }
  • 13. int calculateM1(int value1, int value2, int value3) { int maxValue if (value1 > value2 && value1 > value3) { maxValue = value1 } else if (value2 > value3) { maxValue = value2 } else { maxValue = value3 } maxValue + 1 } int calculateM2(int value1, int value2, int value3) { int maxValue if (value1 > value2 && value1 > value3) { maxValue = value1 } else if (value2 > value3) { maxValue = value2 } else { maxValue = value3 } maxValue * 2 }
  • 14. int calculateM1(int value1, int value2, int value3) { int maxValue if (value1 > value2 && value1 > value3) { maxValue = value1 } else if (value2 > value3) { maxValue = value2 } else { maxValue = value3 } maxValue + 1 } int calculateM1(int value1, int value2, int value3) { int maxValue = max(value1, value2, value3) maxValue + 1 } private int max(int value1, int value2, int value3) { int maxValue if (value1 > value2 && value1 > value3) { maxValue = value1 } else if (value2 > value3) { maxValue = value2 } else { maxValue = value3 } maxValue } Extract Method
  • 15. int calculateM1(int value1, int value2, int value3) { int maxValue = max(value1, value2, value3) maxValue + 1 } private int max(int value1, int value2, int value3) { int maxValue if (value1 > value2 && value1 > value3) { maxValue = value1 } else if (value2 > value3) { maxValue = value2 } else { maxValue = value3 } maxValue } int calculateM2(int value1, int value2, int value3) { int maxValue if (value1 > value2 && value1 > value3) { maxValue = value1 } else if (value2 > value3) { maxValue = value2 } else { maxValue = value3 } maxValue * 2 }
  • 16. int calculateM1(int value1, int value2, int value3) { int maxValue = max(value1, value2, value3) maxValue + 1 } private int max(int value1, int value2, int value3) { int maxValue if (value1 > value2 && value1 > value3) { maxValue = value1 } else if (value2 > value3) { maxValue = value2 } else { maxValue = value3 } maxValue } int calculateM2(int value1, int value2, int value3) { int maxValue = max(value1, value2, value3) maxValue * 2 }
  • 17. private int max(int value1, int value2, int value3) { int maxValue if (value1 > value2 && value1 > value3) { maxValue = value1 } else if (value2 > value3) { maxValue = value2 } else { maxValue = value3 } maxValue } private int max(int value1, int value2, int value3) { Math.max(value1, Math.max(value2, value3)) }
  • 18. private int max(int value1, int value2, int value3) { Math.max(value1, Math.max(value2, value3)) } int calculateM1(int value1, int value2, int value3) { int maxValue = max(value1, value2, value3) maxValue + 1 } int calculateM2(int value1, int value2, int value3) { int maxValue = max(value1, value2, value3) maxValue * 2 }
  • 19. private int max(int value1, int value2, int value3) { Math.max(value1, Math.max(value2, value3)) } int calculateM1(int value1, int value2, int value3) { int maxValue = Math.max(value1, Math.max(value2, value3)) maxValue + 1 } int calculateM2(int value1, int value2, int value3) { int maxValue = Math.max(value1, Math.max(value2, value3)) maxValue * 2 } Inline Method
  • 20. int calculateM1(int value1, int value2, int value3) { int maxValue = Math.max(value1, Math.max(value2, value3)) maxValue + 1 } int calculateM2(int value1, int value2, int value3) { int maxValue = Math.max(value1, Math.max(value2, value3)) maxValue * 2 } int calculateM1(int value1, int value2, int value3) { Math.max(value1, Math.max(value2, value3)) + 1 } int calculateM2(int value1, int value2, int value3) { Math.max(value1, Math.max(value2, value3)) * 2 } Inline Variable
  • 21. Importance of small steps in refactoring
  • 23. List<Integer> numbers = [1, 2, 3, 4, 5] for(number in numbers) { println number }
  • 25. List<Integer> numbers = [1, 2, 3, 4, 5] for(number in numbers) { println number } List<Integer> numbers = [1, 2, 3, 4, 5] numbers.forEach { println it } List<Integer> numbers = [1, 2, 3, 4, 5] numbers.forEach(System.out.&println)
  • 28. def numbers = [1, 2, 3, 4, 5] for(number in numbers) { println number } def numbers = [1, 2, 3, 4, 5] numbers.each { println it }
  • 29. def evenNumbers = [] numbers.each { number -> if (number % 2 == 0) { evenNumbers << number } } def evenNumbers = numbers .findAll { it % 2 == 0}
  • 30. def sum = 0 numbers.each { sum += it } def sum = numbers.inject(0, { result, number -> result + number } )
  • 31. List<Integer> numbers = [1, 2, 3, 4, 5] def result = [:] numbers.forEach { number -> result[number] = number * number } List<Integer> numbers = [1, 2, 3, 4, 5] def result = numbers.collectEntries { [it, it * it] }
  • 33. List<Integer> numbers = [1, 2, 3, 4, 5] def evenNumbers = numbers.findAll { it % 2 == 0}
  • 35. List<Integer> numbers = [1, 2, 3, 4, 5] def evenNumbers = numbers.findAll { it % 2 == 0} List<Integer> numbers = [1, 2, 3, 4, 5] def evenNumbers = numbers.findAll({ it % 2 == 0 }) List<Integer> numbers = [1, 2, 3, 4, 5] def isEven = { it % 2 == 0 } def evenNumbers = numbers.findAll(isEven)
  • 37. List<Integer> numbers = [1, 2, 3, 4, 5] def isEven = { it % 2 == 0 } def evenNumbers = numbers.findAll(isEven) List<Integer> numbers = [1, 2, 3, 4, 5] def evenNumbers = numbers.findAll { it % 2 == 0}
  • 39. def numbers = [1, 2, 3, 4, 5] def sumOfSuqaresOfEvenNumbers = 0 numbers.forEach { number -> if(number % 2 == 0 ){ sumOfSuqaresOfEvenNumbers += number * number } }
  • 41. def numbers = [1, 2, 3, 4, 5] def sumOfSuqaresOfEvenNumbers = 0 numbers.forEach { number -> if(number % 2 == 0 ){ sumOfSuqaresOfEvenNumbers += number * number } } def sumOfSuqaresOfEvenNumbers = numbers .findAll { it % 2 == 0 } .collect { it * it } .sum()
  • 43. def numbers = [1, 2, 3, 4, 5] def sumOfSuqaresOfEvenNumbers = 0 numbers.forEach { number -> if(number % 2 == 0 ){ sumOfSuqaresOfEvenNumbers += number * number } } def square = { it * it } def sumOfSuqaresOfEvenNumbers = 0 numbers.forEach { number -> if(number % 2 == 0 ){ sumOfSuqaresOfEvenNumbers += square(number) } }
  • 44. def square = { it * it } def sumOfSuqaresOfEvenNumbers = 0 numbers.forEach { number -> if(number % 2 == 0 ){ sumOfSuqaresOfEvenNumbers += square(number) } } def sumOfSuqaresOfEvenNumbers = 0 def evenNumbers = numbers.findAll { it % 2 == 0} evenNumbers.forEach { number -> sumOfSuqaresOfEvenNumbers += square(number) }
  • 45. def sumOfSuqaresOfEvenNumbers = 0 def evenNumbers = numbers.findAll { it % 2 == 0} evenNumbers.forEach { number -> sumOfSuqaresOfEvenNumbers += square(number) } def sumOfSuqaresOfEvenNumbers = 0 def evenNumbers = numbers.findAll { it % 2 == 0} def squaresOfEvenNumbers = evenNumbers.collect(square) squaresOfEvenNumbers.forEach { number -> sumOfSuqaresOfEvenNumbers += number }
  • 46. def square = { it * it } def evenNumbers = numbers.findAll { it % 2 == 0 } def squaresOfEvenNumbers = evenNumbers .collect ( square ) def sumOfSuqaresOfEvenNumbers = squaresOfEvenNumbers.sum() def sumOfSuqaresOfEvenNumbers = 0 def evenNumbers = numbers.findAll { it % 2 == 0} def squaresOfEvenNumbers = evenNumbers.collect(square) squaresOfEvenNumbers.forEach { number -> sumOfSuqaresOfEvenNumbers += number }
  • 47. def square = { it * it } def evenNumbers = numbers.findAll { it % 2 == 0 } def squaresOfEvenNumbers = evenNumbers .collect ( square ) def sumOfSuqaresOfEvenNumbers = squaresOfEvenNumbers.sum() def sumOfSuqaresOfEvenNumbers = numbers .findAll { it % 2 == 0 } .collect (square) .sum() Inline
  • 49. class Multiplier { private final int times Multiplier(int times) { this.times = times } int multiply(int number) { times * number } } Multiplier doubler = new Multiplier(2) Multiplier triple = new Multiplier(3) println doubler.multiply(10) println triple.multiply(10)
  • 50. def multiply = { int times, int number -> times * number } def doubler = multiply.curry(2) def triple = multiply.curry(3) println doubler(10) println triple(10)
  • 52. def numbers = [1, 2, 3, 4, 5, 6] println numbers .findAll { it % 2 == 0 } .find { it > 2 }
  • 54. def numbers = [1, 2, 3, 4, 5, 6] println numbers .findAll { it % 2 == 0 } .find { it > 2 } def numbers = [1, 2, 3, 4, 5, 6] println numbers .stream() .filter { it % 2 == 0 } .filter { it > 2 } .findFirst() .orElse(null)
  • 56. interface CanSwim { def swim() } class Fish implements CanSwim { def swim() { println "Fish Swimming" } } class Person implements CanSwim { def swim() { println "Person Swimming" } }
  • 58. interface CanSwim { def swim() } class Fish implements CanSwim { def swim() { println "Fish Swimming" } } class Person implements CanSwim { def swim() { println "Person Swimming" } } CanSwim swimmer = new Person() //new Fish() swimmer.swim()
  • 59. interface CanSwim { def swim() } class Fish implements CanSwim { def swim() { println "Fish Swimming" } } class Person implements CanSwim { def swim() { println "Person Swimming" } } def swimmer = new Person() //new Fish() swimmer.swim()
  • 61. class Employee { def employeeId def firstName def lastName def dateOfBirth def toSummaryString() { "$employeeId -> $firstname" } }
  • 62. class Employee { def employeeId def firstName def lastName def dateOfBirth def toSummaryString() { "$employeeId -> $firstname" } }
  • 64. class Employee { def employeeId def firstName def lastName def dateOfBirth def toSummaryString() { "$employeeId -> $firstname" } } Exception in thread "main" groovy.lang.MissingPropertyException: No such property: firstname for class
  • 65. @TypeChecked class Employee { def employeeId def firstName def lastName def dateOfBirth def toSummaryString() { "$employeeId -> $firstname" } } Error:(17, 30) Groovyc: [Static type checking] - The variable [firstname] is undeclared.
  • 66. @TypeChecked class Employee { def employeeId def firstName def lastName def dateOfBirth def toSummaryString() { "$employeeId -> $firstname" } } @TypeChecked class Employee { String employeeId String firstName String lastName LocalDateTime dateOfBirth def toSummaryString() { "$employeeId -> $firstname" } }
  • 68. class Greeter { String message def greet() { message } } @TypeChecked def runTypeChecked(Greeter greeter) { println greeter.greet() } @CompileStatic def runCompileStatic(Greeter greeter) { println greeter.greet() }
  • 69. def greeter = new Greeter(message: 'Good Morning') greeter.metaClass.greet = { "Hello, ${delegate.message}" } runTypeChecked(greeter) runCompileStatic(greeter) Hello, Good Morning Good Morning
  • 70. @Transactional class MyService { @Transactional(propagation = Propagation.REQUIRES_NEW) def m1() {} def m2(){ m1() } }
  • 72. @Transactional class MyService implements ApplicationContextAware { ApplicationContext context @Transactional(propagation = Propagation.REQUIRES_NEW) def m1() {} def m2() { MyService service = context.getBean('myService') service.m1() } @Override void setApplicationContext(ApplicationContext applicationContext) throws BeansException { context = applicationContext } }
  • 73. def grailsApplication def init = { servletContext -> injectSelfProxy() } private def injectSelfProxy(){ for (sc in grailsApplication.serviceClasses) { String propertyName = sc.propertyName sc.clazz.metaClass.getMyProxy = { -> grailsApplication.mainContext .getBean(propertyName) } } }
  • 74. @Transactional class MyService { ApplicationContext context @Transactional(propagation = Propagation.REQUIRES_NEW) def m1() {} def m2() { myProxy.m1() } }
  • 76. class Product { UUID uuid = UUID.randomUUID() //other fields } class Order { UUID uuid = UUID.randomUUID() //other fields }
  • 77. class Product { UUID uuid = UUID.randomUUID() //other fields } class Order { UUID uuid = UUID.randomUUID() //other fields } trait BusinessObject { }
  • 78. class Product implements BusinessObject { //other fields } class Order implements BusinessObject { //other fields } trait BusinessObject { UUID uuid = UUID.randomUUID() }
  • 80. class Technologies extends ArrayList { def filterGr8() { this.findAll { it.startsWith('Gr')} } } Technologies list = [‘Groovy', 'Grails', 'Gradle', 'Java'] as Technologies println list println list.filterGr8()
  • 82. class Technologies { @Delegate private List list Technologies(List list) { this.list = list } def filterGr8() { list.findAll { it.startsWith('Gr') } } }