designing with groovy traits - gr8conf india

40
Designing with Groovy Traits Naresha K Chief Technologist Channel Bridge Software Labs [email protected] @naresha_k

Upload: naresha-k

Post on 19-Jan-2017

933 views

Category:

Technology


3 download

TRANSCRIPT

Designing withGroovy Traits

Naresha K Chief Technologist

Channel Bridge Software Labs [email protected]

@naresha_k

About Me

OOP

Object Oriented Maturity Model

0

1

2

I made up the term ‘object-oriented', and I can tell you

I didn't have that in mind

Alan Kay

iskov Substitution Principle

"Favour 'object composition' over

'class inheritance'."

A case for Traits

The Problem

Bird charlie = new Bird()charlie.fly()

Butterfly aButterFly = new Butterfly()aButterFly.fly()

Recall Interfaces

interface Flyable {def fly()

}

class Bird implements Flyable {def fly() {println "Flying..."

}}

class Butterfly implements Flyable {def fly() {println "Flying..."

}}

The Smell

class Bird implements Flyable {def fly() {

println "Flying..."}

}

class Butterfly implements Flyable {def fly() {

println "Flying..."}

}

DRYclass FlyableImpl implements Flyable {def fly() {println 'Flying...'

}}

class Bird implements Flyable {def fly() {new FlyableImpl().fly()

}}

Making it Groovierclass DefaultFlyable implements Flyable {def fly() {println 'Flying...'

}}

class Bird {@DelegateFlyable flyable = new DefaultFlyable()

}

Summarizinginterface Flyable {def fly()

}

class DefaultFlyable implements Flyable {def fly() {println 'Flying...'

}}

class Bird {@DelegateFlyable flyable = new DefaultFlyable()

}

Introducing Trait

trait Flyable {def fly() {println "Flying.."

}}

class Bird implements Flyable {}

Multiple Capabilities

trait CanSing {def sing() {println "Singing"

}}

trait CanDance {def dance() {println "Dancing"

}}

class Person implements CanSing, CanDance {}

Person reema = new Person()reema.sing()reema.dance()

The Mechanics

Overriding Methods from a Trait

trait Speaker {def speak() {println "speaking"

}}

class Gr8ConfSpeaker implements Speaker {def speak() {println "Groovy is Groovy!"

}}

new Gr8ConfSpeaker().speak()

Traits can implement interfacesinterface Programmer {def code()

}

trait GroovyProgrammer implements Programmer {def code() {println 'coding Groovy'

}}

class Engineer implements GroovyProgrammer {}

new Engineer().code()

Traits can declare abstract methods

trait Programmer {abstract String getLanguage()def code() {println "Coding ${getLanguage()}"

}}

class GroovyProgrammer implements Programmer {String getLanguage() { "Groovy"}

}

new GroovyProgrammer().code()

Traits can have a state

trait Programmer {String languagedef code() {println "Coding ${language}"

}}

class GroovyProgrammer implements Programmer {}

new GroovyProgrammer(language: 'Groovy').code()

A trait can extend another traittrait JavaProgrammer {def codeObjectOriented() {println 'Coding OOP'

}}trait GroovyProgrammer extends JavaProgrammer {def codeFunctional() {println 'Coding FP'

}}class Engineer implements GroovyProgrammer {}Engineer raj = new Engineer()raj.codeFunctional()raj.codeObjectOriented()

A trait can extend from multiple traits

trait Reader {def read() { println 'Reading'}

}trait Evaluator {def eval() { println 'Evaluating'}

}trait Printer {def printer() { println 'Printing'}

}trait Repl implements Reader, Evaluator, Printer {}

The diamond problemtrait GroovyProgrammer {def learn() { println 'Learning Traits'}

}

trait JavaProgrammer {def learn() { println 'Busy coding'}

}

class Dev implements JavaProgrammer, GroovyProgrammer {}

new Dev().learn()

Finer control on the diamond problem

class Dev implements JavaProgrammer, GroovyProgrammer {

def learn() {JavaProgrammer.super.learn()

}

}

Applying traits at run time

trait Flyable{def fly(){println "Flying.."

}}

class Person {}new Person().fly()

Applying traits at run time

def boardAPlane(Person person) {person.withTraits Flyable

}

def passenger = boardAPlane(new Person())passenger.fly()

More examples

Composing Behaviours

trait UserContextAware {UserContext getUserContext(){// implementation

}}

class ProductApi implements UserContextAware {}

class PriceApi implements UserContextAware {}

common fieldstrait Auditable {String createdByString modifiedByDate dateCreatedDate lastUpdated

}

class Price implements Auditable {String productCodeBigDecimal mrpBigDecimal sellingPrice

}

common fields - a trait approach

Price groovyInActionToday = new Price(productCode: '9789351198260', mrp: 899, sellingPrice: 751,createdBy: 'admin',modifiedBy: 'rk')

println groovyInActionToday.createdByprintln groovyInActionToday.modifiedBy

Chaining

interface Manager {def approve(BigDecimal amount)

}

Chainingtrait JuniorManager implements Manager {def approve(BigDecimal amount){if(amount < 10000G){ println "Approved by JM” }else{println "Sending to SM"super.approve()

}}

}trait SeniorManager implements Manager {def approve(BigDecimal amount){println "Approved by SM"

}}

Chaining

class FinanceDepartment implements SeniorManager, JuniorManager {}FinanceDepartment finance = new FinanceDepartment()finance.approve(3000)finance.approve(30000)

Groovy Coding!