baking delicious modularity in scala

96
Baking Delicious Modularization in Scala Derek Wyatt Twitter: @derekwyatt Email: [email protected] Thursday, December 12, 13

Upload: derek-wyatt

Post on 06-May-2015

3.601 views

Category:

Technology


0 download

DESCRIPTION

This was a presentation I gave in October 2013 to the Waterloo Scala Meetup. It's probably the 437th presentation on Scala modularity to date. There's tons of them, but the group was curious about how it was done and wanted the personal touch, so I gave it to them...

TRANSCRIPT

Page 1: Baking Delicious Modularity in Scala

Baking

Delicious

Modularization

in ScalaDerek Wyatt

Twitter: @derekwyattEmail: [email protected]

Thursday, December 12, 13

Page 2: Baking Delicious Modularity in Scala

Object Oriented Modularity

OOD gives us...

Thursday, December 12, 13

Page 3: Baking Delicious Modularity in Scala

Object Oriented Modularity

OOD gives us... ClassesAbstract ClassesInterfacespublic

privateprotected

Inheritance&Composition

Thursday, December 12, 13

Page 4: Baking Delicious Modularity in Scala

Object Oriented Modularity

OOD gives us... ClassesAbstract ClassesInterfacespublic

privateprotected

C++ gave us... Multiple InheritanceJust Plain Evil Right?. . .

Inheritance&Composition

Thursday, December 12, 13

Page 5: Baking Delicious Modularity in Scala

The Diamond ProblemA

B CisAis

A

Thursday, December 12, 13

Page 6: Baking Delicious Modularity in Scala

The Diamond Problem

D

A

B CisAis

A

isAisA

Thursday, December 12, 13

Page 7: Baking Delicious Modularity in Scala

The Diamond Problem

D

?

A

B CisAis

A

isAisA

Who initializes A?

Thursday, December 12, 13

Page 8: Baking Delicious Modularity in Scala

The Diamond Problem

D

?

A

B CisAis

A

isAisA

Who initializes A?

B needs it initializedSo does C They can’t both do it!

Thursday, December 12, 13

Page 9: Baking Delicious Modularity in Scala

The Diamond Problem

D

?

A

B CisAis

A

isAisA

Who initializes A?

B needs it initializedSo does C They can’t both do it!

Enter: Virtual Inheritance

Thursday, December 12, 13

Page 10: Baking Delicious Modularity in Scala

The Diamond Problem

D

?

A

B CisAis

A

isAisA

Who initializes A?

B needs it initializedSo does C They can’t both do it!

Enter: Virtual InheritanceConvincing the world for decades that

Multiple Inheritance is BADThursday, December 12, 13

Page 11: Baking Delicious Modularity in Scala

Java’s Solution to Multiple Inheritance

Multiple Inheritance

Thursday, December 12, 13

Page 12: Baking Delicious Modularity in Scala

Java’s Solution to Multiple Inheritance

Multiple Inheritance

The powers that be just went and tossed it out

Thursday, December 12, 13

Page 13: Baking Delicious Modularity in Scala

Java’s Solution to Multiple Inheritance

Multiple Inheritance

The powers that be just went and tossed it out

Implementing multiple interfaces and extending one abstract classis not equivalent

Thursday, December 12, 13

Page 14: Baking Delicious Modularity in Scala

Java’s Solution to Multiple Inheritance

Multiple Inheritance

The powers that be just went and tossed it out

Implementing multiple interfaces and extending one abstract classis not equivalentImplementing the multiple interfaces is work

Thursday, December 12, 13

Page 15: Baking Delicious Modularity in Scala

Java’s Solution to Multiple Inheritance

Multiple Inheritance

The powers that be just went and tossed it out

Implementing multiple interfaces and extending one abstract classis not equivalentImplementing the multiple interfaces is workSharing code amongst implementations is hard Compose and

delegate

Thursday, December 12, 13

Page 16: Baking Delicious Modularity in Scala

Java’s Solution to Multiple Inheritance

Multiple Inheritance

The powers that be just went and tossed it out

Implementing multiple interfaces and extending one abstract classis not equivalentImplementing the multiple interfaces is workSharing code amongst implementations is hardInconsistencies show up very quickly and maintenance is a pain

Compose and

delegate

Thursday, December 12, 13

Page 17: Baking Delicious Modularity in Scala

Java’s Solution to Multiple Inheritance

Multiple Inheritance

The powers that be just went and tossed it out

Implementing multiple interfaces and extending one abstract classis not equivalentImplementing the multiple interfaces is workSharing code amongst implementations is hardInconsistencies show up very quickly and maintenance is a pain

Compose and

delegate#FAIL

Thursday, December 12, 13

Page 18: Baking Delicious Modularity in Scala

Scala’s Solution to Multiple Inheritance

Thursday, December 12, 13

Page 19: Baking Delicious Modularity in Scala

Scala’s Solution to Multiple Inheritance

Crush the Diamond!

Thursday, December 12, 13

Page 20: Baking Delicious Modularity in Scala

Scala’s Solution to Multiple Inheritance

Crush the Diamond!Scala integrates inheritance with mixin functionality

Thursday, December 12, 13

Page 21: Baking Delicious Modularity in Scala

Scala’s Solution to Multiple Inheritance

Crush the Diamond!Scala integrates inheritance with mixin functionalityTraits provide the construct for mixins

trait Atrait B extends Atrait C extends Aclass D extends B with C

Thursday, December 12, 13

Page 22: Baking Delicious Modularity in Scala

Scala’s Solution to Multiple Inheritance

Crush the Diamond!Scala integrates inheritance with mixin functionalityTraits provide the construct for mixins

trait Atrait B extends Atrait C extends Aclass D extends B with C

Translates to

Any

AnyRef

A

B

C

D

Initia

lize

Thursday, December 12, 13

Page 23: Baking Delicious Modularity in Scala

Scala’s Solution to Multiple Inheritance

Crush the Diamond!Scala integrates inheritance with mixin functionalityTraits provide the construct for mixins

trait Atrait B extends Atrait C extends Aclass D extends B with C

If a conflict exists between B and C with respect to A, then C wins.

Translates to

Any

AnyRef

A

B

C

D

Initia

lize

Thursday, December 12, 13

Page 24: Baking Delicious Modularity in Scala

Origins of the Cake

Randomizer

Persistence

PicRetriever DatabasePersistence

HashMap TestPersistence

RESTPersistence

RandomRandomizer

Specifier TestRandomizer

def randomPic: Future[Pic]

Dependency Injection and Modularity

Thursday, December 12, 13

Page 25: Baking Delicious Modularity in Scala

Origins of the Cake

Randomizer

Persistence

PicRetriever DatabasePersistence

HashMap TestPersistence

RESTPersistence

RandomRandomizer

Specifier TestRandomizer

def randomPic: Future[Pic]

Dependency Injection and Modularity

Origins of the Cake

Thursday, December 12, 13

Page 26: Baking Delicious Modularity in Scala

Origins of the Cake

Randomizer

Persistence

PicRetriever DatabasePersistence

HashMap TestPersistence

RESTPersistence

RandomRandomizer

Specifier TestRandomizer

def randomPic: Future[Pic]

Declare reliance on

these modules

Dependency Injection and Modularity

Origins of the Cake

Thursday, December 12, 13

Page 27: Baking Delicious Modularity in Scala

Origins of the Cake

Randomizer

Persistence

PicRetriever DatabasePersistence

HashMap TestPersistence

RESTPersistence

RandomRandomizer

Specifier TestRandomizer

def randomPic: Future[Pic]

Declare reliance on

these modules

new PicRetriever extends Database with RandomChoose concrete implementations

Dependency Injection and Modularity

Origins of the Cake

Thursday, December 12, 13

Page 28: Baking Delicious Modularity in Scala

Origins of the Cake

Randomizer

Persistence

PicRetriever

DatabasePersistence

HashMap TestPersistence

RESTPersistence

RandomRandomizer

Specifier TestRandomizer

def randomPic: Future[Pic]

Declare reliance on

these modules

new PicRetriever extends Database with RandomChoose concrete implementations

Dependency Injection and Modularity

PicRetriever

mixes in the

interface

and the

implementation

Origins of the Cake

Thursday, December 12, 13

Page 29: Baking Delicious Modularity in Scala

The Basic Cupcaketrait Persistence { def pic(idx: Int): Future[Pic] = ??? def totalPics: Future[Int] = ???}

trait Randomizer { def nextInt(upperBound: Int): Int = ???}

Thursday, December 12, 13

Page 30: Baking Delicious Modularity in Scala

The Basic Cupcaketrait Persistence { def pic(idx: Int): Future[Pic] = ??? def totalPics: Future[Int] = ???}

class PicRetriever { this: Persistence with Randomizer => def randomPic: Future[Pic] = ???}

object PicRetriever { def production: PicRetriever = new PicRetriever with Persistence with Randomizer}

trait Randomizer { def nextInt(upperBound: Int): Int = ???}

Declare PicRetri

ever

self type

Thursday, December 12, 13

Page 31: Baking Delicious Modularity in Scala

The Basic Cupcaketrait Persistence { def pic(idx: Int): Future[Pic] = ??? def totalPics: Future[Int] = ???}

class PicRetriever { this: Persistence with Randomizer => def randomPic: Future[Pic] = ???}

object PicRetriever { def production: PicRetriever = new PicRetriever with Persistence with Randomizer}

trait Randomizer { def nextInt(upperBound: Int): Int = ???}

Declare PicRetri

ever

self type

Define factory method that makes construction simpler

Thursday, December 12, 13

Page 32: Baking Delicious Modularity in Scala

The Basic Cupcaketrait Persistence { def pic(idx: Int): Future[Pic] = ??? def totalPics: Future[Int] = ???}

class PicRetriever { this: Persistence with Randomizer => def randomPic: Future[Pic] = ???}

object PicRetriever { def production: PicRetriever = new PicRetriever with Persistence with Randomizer}

trait Randomizer { def nextInt(upperBound: Int): Int = ???}

You could derive new Persistence and Randomizer traits and instantiate accordingly. Not great, but it does get the job done.

Declare PicRetri

ever

self type

Define factory method that makes construction simpler

Thursday, December 12, 13

Page 33: Baking Delicious Modularity in Scala

Adding a LayerThe lack of an “interface” requires overrides in the derivations

Thursday, December 12, 13

Page 34: Baking Delicious Modularity in Scala

Adding a LayerThe lack of an “interface” requires overrides in the derivations

We can add that layer, making derivations easier to write

Thursday, December 12, 13

Page 35: Baking Delicious Modularity in Scala

Adding a LayerThe lack of an “interface” requires overrides in the derivations

We can add that layer, making derivations easier to write

trait Persistence { def pic(idx: Int): Future[Pic] def totalPics: Future[Int]}trait Database extends Persistence { val dbUrl: String def pic(idx: Int): Future[Pic] = ??? def totalPics: Int = ???}

trait Randomizer { def nextInt(upperBound: Int): Int}trait RealRandomizer extends Randomizer { def nextInt(upperBound: Int): Int = ???}

Thursday, December 12, 13

Page 36: Baking Delicious Modularity in Scala

Adding a LayerThe lack of an “interface” requires overrides in the derivations

We can add that layer, making derivations easier to write

trait Persistence { def pic(idx: Int): Future[Pic] def totalPics: Future[Int]}trait Database extends Persistence { val dbUrl: String def pic(idx: Int): Future[Pic] = ??? def totalPics: Int = ???}

object PicRetriever { def production: PicRetriever = new PicRetriever with Database with RealRandomizer}

trait Randomizer { def nextInt(upperBound: Int): Int}trait RealRandomizer extends Randomizer { def nextInt(upperBound: Int): Int = ???}

Thursday, December 12, 13

Page 37: Baking Delicious Modularity in Scala

Eliminating Naming Conflicts

Thursday, December 12, 13

Page 38: Baking Delicious Modularity in Scala

Eliminating Naming ConflictsThere’s nothing to stop you from tromping all over your names

Thursday, December 12, 13

Page 39: Baking Delicious Modularity in Scala

Eliminating Naming ConflictsThere’s nothing to stop you from tromping all over your namesIt’s a good idea to give namespaces to the mixed-in modules

trait PersistenceComponent { val persistence: Persistence trait Persistence { def pic(idx: Int): Future[Pic] def totalPics: Future[Int] }}

trait RandomizerComponent { val randomizer: Randomizer trait Randomizer { def nextInt(upperBound: Int): Int }}

Thursday, December 12, 13

Page 40: Baking Delicious Modularity in Scala

Eliminating Naming ConflictsThere’s nothing to stop you from tromping all over your namesIt’s a good idea to give namespaces to the mixed-in modules

trait PersistenceComponent { val persistence: Persistence trait Persistence { def pic(idx: Int): Future[Pic] def totalPics: Future[Int] }}

trait RandomizerComponent { val randomizer: Randomizer trait Randomizer { def nextInt(upperBound: Int): Int }}

Everything can be

solved with another

layer of indirection

Thursday, December 12, 13

Page 41: Baking Delicious Modularity in Scala

Eliminating Naming ConflictsThere’s nothing to stop you from tromping all over your namesIt’s a good idea to give namespaces to the mixed-in modules

trait PersistenceComponent { val persistence: Persistence trait Persistence { def pic(idx: Int): Future[Pic] def totalPics: Future[Int] }}

trait RandomizerComponent { val randomizer: Randomizer trait Randomizer { def nextInt(upperBound: Int): Int }}

class PicRetriever { this: PersistenceComponent with RandomizerComponent => // ...}object PicRetriever { def production: PicRetriever = new PicRetriever with ProdPersistence with ProdRandomizer { val persistence = new Persistence { } val randomizer = new Randomizer { }}

Thursday, December 12, 13

Page 42: Baking Delicious Modularity in Scala

Taming the Test

Thursday, December 12, 13

Page 43: Baking Delicious Modularity in Scala

trait TestRand

omizerComp ext

ends Randomize

rComponent {

val randomiz

er: Randomizer

trait TestRa

ndomizer exten

ds Randomizer

{

val i: Int

def nextIn

t(upperBound:

Int): Int = i

}}

Taming the Test

Thursday, December 12, 13

Page 44: Baking Delicious Modularity in Scala

trait TestRand

omizerComp ext

ends Randomize

rComponent {

val randomiz

er: Randomizer

trait TestRa

ndomizer exten

ds Randomizer

{

val i: Int

def nextIn

t(upperBound:

Int): Int = i

}}

trait TestPersiste

nceComp extends Pe

rsistenceComponent

{

val persistence:

PersistenceCompon

ent

trait TestPersis

tence extends Pers

istence {

val pics: Vect

or[Pic]

def pic(idx: I

nt): Future[Pic] =

Future(pics(idx))

def totalPics:

Future[Int] = Fut

ure(pics.size)

}}

Taming the Test

Thursday, December 12, 13

Page 45: Baking Delicious Modularity in Scala

trait TestRand

omizerComp ext

ends Randomize

rComponent {

val randomiz

er: Randomizer

trait TestRa

ndomizer exten

ds Randomizer

{

val i: Int

def nextIn

t(upperBound:

Int): Int = i

}}

trait TestPersiste

nceComp extends Pe

rsistenceComponent

{

val persistence:

PersistenceCompon

ent

trait TestPersis

tence extends Pers

istence {

val pics: Vect

or[Pic]

def pic(idx: I

nt): Future[Pic] =

Future(pics(idx))

def totalPics:

Future[Int] = Fut

ure(pics.size)

}}

Taming the Test

object TestPicRetriever { def test(num: Int, images: Vector[Pic]): PicRetriever = new PicRetriever with TestPersistenceComp with TestRandomizerComp { val persistence = new TestPersistence { val pics = images } val randomizer = new TestRandomizer { val i = num } }

Thursday, December 12, 13

Page 46: Baking Delicious Modularity in Scala

trait TestRand

omizerComp ext

ends Randomize

rComponent {

val randomiz

er: Randomizer

trait TestRa

ndomizer exten

ds Randomizer

{

val i: Int

def nextIn

t(upperBound:

Int): Int = i

}}

trait TestPersiste

nceComp extends Pe

rsistenceComponent

{

val persistence:

PersistenceCompon

ent

trait TestPersis

tence extends Pers

istence {

val pics: Vect

or[Pic]

def pic(idx: I

nt): Future[Pic] =

Future(pics(idx))

def totalPics:

Future[Int] = Fut

ure(pics.size)

}}

Taming the Test

object TestPicRetriever { def test(num: Int, images: Vector[Pic]): PicRetriever = new PicRetriever with TestPersistenceComp with TestRandomizerComp { val persistence = new TestPersistence { val pics = images } val randomizer = new TestRandomizer { val i = num } }

val pic = loadPic(“pic1”)val retriever = TestPicRetriever.test(0, Vector(pic))Await.result(retriever.randomPic, 1.second) should be (pic)

Thursday, December 12, 13

Page 47: Baking Delicious Modularity in Scala

Enough Analogues... Modularity!

Thursday, December 12, 13

Page 48: Baking Delicious Modularity in Scala

Enough Analogues... Modularity!

You don’t have to “self type” in order to establish the contract

Thursday, December 12, 13

Page 49: Baking Delicious Modularity in Scala

Enough Analogues... Modularity!

You don’t have to “self type” in order to establish the contract

Abstract types and constraints can solve the problem with greater flexibility

Thursday, December 12, 13

Page 50: Baking Delicious Modularity in Scala

Enough Analogues... Modularity!

You don’t have to “self type” in order to establish the contract

Abstract types and constraints can solve the problem with greater flexibility

trait PersistenceLike { def pic(idx: Int): Future[Pic] def totalPics: Future[Int]}

trait RandomizerLike { def nextInt(upperBound: Int): Int}

Thursday, December 12, 13

Page 51: Baking Delicious Modularity in Scala

Enough Analogues... Modularity!

You don’t have to “self type” in order to establish the contract

Abstract types and constraints can solve the problem with greater flexibility

trait PersistenceLike { def pic(idx: Int): Future[Pic] def totalPics: Future[Int]}

trait PicRetriever { type Persistence <: PersistenceLike type Randomizer <: RandomizerLike

val persistence: Persistence val randomizer: Randomizer

// ...}

trait RandomizerLike { def nextInt(upperBound: Int): Int}

Thursday, December 12, 13

Page 52: Baking Delicious Modularity in Scala

Enough Analogues... Modularity!

You don’t have to “self type” in order to establish the contract

Abstract types and constraints can solve the problem with greater flexibility

trait PersistenceLike { def pic(idx: Int): Future[Pic] def totalPics: Future[Int]}

trait PicRetriever { type Persistence <: PersistenceLike type Randomizer <: RandomizerLike

val persistence: Persistence val randomizer: Randomizer

// ...}

trait RandomizerLike { def nextInt(upperBound: Int): Int}

Abstract types define enough to work with for the PicRetriever, but allow for further specification later

Thursday, December 12, 13

Page 53: Baking Delicious Modularity in Scala

Use Case... Configuration

Thursday, December 12, 13

Page 54: Baking Delicious Modularity in Scala

Use Case... Configuration

Let’s say you want to declare a method for configuring objects

trait Configclass DBConfig extends Config { val dbHost: String val dbPort: Int}class RandomizerConfig extends Config { val randomSeed: Int val randomScale: Int}class RESTConfig extends Config { val restHost: String val restPort: Int}

Thursday, December 12, 13

Page 55: Baking Delicious Modularity in Scala

Use Case... Configuration

Let’s say you want to declare a method for configuring objects

You want generality, so you can’t pass multiple configs

abstract class Component(config: Config) trait Configclass DBConfig extends Config { val dbHost: String val dbPort: Int}class RandomizerConfig extends Config { val randomSeed: Int val randomScale: Int}class RESTConfig extends Config { val restHost: String val restPort: Int}

Thursday, December 12, 13

Page 56: Baking Delicious Modularity in Scala

Use Case... Configuration

Let’s say you want to declare a method for configuring objects

You want generality, so you can’t pass multiple configs

abstract class Component(config: Config)

class Database(config: Config) extends Component(config) { require(config.isInstanceOf[DBConfig])}

class Randomizer(config: Config) extends Component(config) { require(config.isInstanceOf[RandomizerConfig])}

class REST(config: Config) extends Component(config) { require(config.isInstanceOf[RESTConfig])}

trait Configclass DBConfig extends Config { val dbHost: String val dbPort: Int}class RandomizerConfig extends Config { val randomSeed: Int val randomScale: Int}class RESTConfig extends Config { val restHost: String val restPort: Int}

Thursday, December 12, 13

Page 57: Baking Delicious Modularity in Scala

Use Case... Configuration

Let’s say you want to declare a method for configuring objects

You want generality, so you can’t pass multiple configs

abstract class Component(config: Config)

class Database(config: Config) extends Component(config) { require(config.isInstanceOf[DBConfig])}

class Randomizer(config: Config) extends Component(config) { require(config.isInstanceOf[RandomizerConfig])}

class REST(config: Config) extends Component(config) { require(config.isInstanceOf[RESTConfig])}

trait Configclass DBConfig extends Config { val dbHost: String val dbPort: Int}class RandomizerConfig extends Config { val randomSeed: Int val randomScale: Int}class RESTConfig extends Config { val restHost: String val restPort: Int}

Ugly, Unsafe, and

Annoying

Thursday, December 12, 13

Page 58: Baking Delicious Modularity in Scala

Configuring through Inverse Generality

Database Config

REST Config

Randomization Config

Thursday, December 12, 13

Page 59: Baking Delicious Modularity in Scala

Configuring through Inverse GeneralityConfig

IsAIsA

IsA

Database Config

REST Config

Randomization Config

Thursday, December 12, 13

Page 60: Baking Delicious Modularity in Scala

Configuring through Inverse GeneralityConfig Empty generalization

IsAIsA

IsA

Database Config

REST Config

Randomization Config

Thursday, December 12, 13

Page 61: Baking Delicious Modularity in Scala

Configuring through Inverse GeneralityDatabase Config

REST Config

Randomization Config

DatabaseREST

Randomization

CONFIG OBJECT

Highly Specificand Type safe

Thursday, December 12, 13

Page 62: Baking Delicious Modularity in Scala

Thickly Typed Objects Kinda stolen from Daniel Spiewak❊

Thursday, December 12, 13

Page 63: Baking Delicious Modularity in Scala

Thickly Typed Objects Kinda stolen from Daniel Spiewak❊

trait ConfigComponent { type Config def config: Config}

Declare a way to configure things

Thursday, December 12, 13

Page 64: Baking Delicious Modularity in Scala

Thickly Typed Objects Kinda stolen from Daniel Spiewak❊

trait DBComponent extends PersistenceComponent with ConfigComponent { type Config <: DBConfig

val persistence = new DB class DB extends Persistence { def pic(idx: Int): Future[Pic] = ??? def totalPics: Future[Int] = ??? }

trait DBConfig { val dbHost: String val dbPort: Int }}

trait ConfigComponent { type Config def config: Config}

Declare a way to configure things

Thursday, December 12, 13

Page 65: Baking Delicious Modularity in Scala

Thickly Typed Objects Kinda stolen from Daniel Spiewak❊

trait DBComponent extends PersistenceComponent with ConfigComponent { type Config <: DBConfig

val persistence = new DB class DB extends Persistence { def pic(idx: Int): Future[Pic] = ??? def totalPics: Future[Int] = ??? }

trait DBConfig { val dbHost: String val dbPort: Int }}

trait ConfigComponent { type Config def config: Config}

Declare a way to configure things

Define how to configure this component

Thursday, December 12, 13

Page 66: Baking Delicious Modularity in Scala

Thickly Typed Objects Kinda stolen from Daniel Spiewak❊

trait DBComponent extends PersistenceComponent with ConfigComponent { type Config <: DBConfig

val persistence = new DB class DB extends Persistence { def pic(idx: Int): Future[Pic] = ??? def totalPics: Future[Int] = ??? }

trait DBConfig { val dbHost: String val dbPort: Int }}

trait ConfigComponent { type Config def config: Config}

Declare a way to configure things

Define how to configure this component

Repeat for REST and Randomizer

Thursday, December 12, 13

Page 67: Baking Delicious Modularity in Scala

Thickly Typed Objects Continuedclass TheFinalThing extends DBComponent with RandomizerComponent with RESTComponent { type Config = DBConfig with RESTConfig with RandomzierConfig

object config extends DBConfig with RESTConfig with RandomzierConfig { val dbHost = “dbhost1” val dbPort = 56872 val restHost = “resthost1” val restPort = 8080 val randomSeed = System.currentTimeMillis.toInt val randomScale = 6 } // etc...}

Thursday, December 12, 13

Page 68: Baking Delicious Modularity in Scala

Thickly Typed Objects Continuedclass TheFinalThing extends DBComponent with RandomizerComponent with RESTComponent { type Config = DBConfig with RESTConfig with RandomzierConfig

object config extends DBConfig with RESTConfig with RandomzierConfig { val dbHost = “dbhost1” val dbPort = 56872 val restHost = “resthost1” val restPort = 8080 val randomSeed = System.currentTimeMillis.toInt val randomScale = 6 } // etc...}

The config object now conforms to the types

requested by everything that’s been mixed in.

Thursday, December 12, 13

Page 69: Baking Delicious Modularity in Scala

Thickly Typed Objects Continuedclass TheFinalThing extends DBComponent with RandomizerComponent with RESTComponent { type Config = DBConfig with RESTConfig with RandomzierConfig

object config extends DBConfig with RESTConfig with RandomzierConfig { val dbHost = “dbhost1” val dbPort = 56872 val restHost = “resthost1” val restPort = 8080 val randomSeed = System.currentTimeMillis.toInt val randomScale = 6 } // etc...}

The config object now conforms to the types

requested by everything that’s been mixed in.

Each Component can access the fields of their slice of the config object without the need for casting. The compiler already

knows it’s right.

Thursday, December 12, 13

Page 70: Baking Delicious Modularity in Scala

Pain and Frustration

Thursday, December 12, 13

Page 71: Baking Delicious Modularity in Scala

Pain and FrustrationCakes generally involve abstract vals

Thursday, December 12, 13

Page 72: Baking Delicious Modularity in Scala

Pain and FrustrationCakes generally involve abstract valsThey also involve “Multiple Inheritance”

Thursday, December 12, 13

Page 73: Baking Delicious Modularity in Scala

Pain and FrustrationCakes generally involve abstract valsThey also involve “Multiple Inheritance”

This presents an interesting initialization problem

Thursday, December 12, 13

Page 74: Baking Delicious Modularity in Scala

Pain and FrustrationCakes generally involve abstract valsThey also involve “Multiple Inheritance”

This presents an interesting initialization problem

trait A { val s: String val t: String = s.substring(0, 2)}

trait B { val s: String = “What?”}

Thursday, December 12, 13

Page 75: Baking Delicious Modularity in Scala

Pain and FrustrationCakes generally involve abstract valsThey also involve “Multiple Inheritance”

This presents an interesting initialization problem

trait A { val s: String val t: String = s.substring(0, 2)}

trait B { val s: String = “What?”}

class C extends A with B

val c = new C

Thursday, December 12, 13

Page 76: Baking Delicious Modularity in Scala

Pain and FrustrationCakes generally involve abstract valsThey also involve “Multiple Inheritance”

This presents an interesting initialization problem

trait A { val s: String val t: String = s.substring(0, 2)}

trait B { val s: String = “What?”}

class C extends A with B

val c = new C

Thursday, December 12, 13

Page 77: Baking Delicious Modularity in Scala

Pain and FrustrationCakes generally involve abstract valsThey also involve “Multiple Inheritance”

This presents an interesting initialization problem

trait A { val s: String val t: String = s.substring(0, 2)}

trait B { val s: String = “What?”}

class C extends A with B

val c = new C

NPE!!!!!!

Thursday, December 12, 13

Page 78: Baking Delicious Modularity in Scala

Null Pointer Exceptions?!

Thursday, December 12, 13

Page 79: Baking Delicious Modularity in Scala

Null Pointer Exceptions?!We’re not used to these any more

Thursday, December 12, 13

Page 80: Baking Delicious Modularity in Scala

Null Pointer Exceptions?!We’re not used to these any moreThey’re an artifact of initialization order and usage

Thursday, December 12, 13

Page 81: Baking Delicious Modularity in Scala

Null Pointer Exceptions?!We’re not used to these any moreThey’re an artifact of initialization order and usage

ABC

Thursday, December 12, 13

Page 82: Baking Delicious Modularity in Scala

Null Pointer Exceptions?!We’re not used to these any moreThey’re an artifact of initialization order and usage

ABC

Initialization Order

Thursday, December 12, 13

Page 83: Baking Delicious Modularity in Scala

Null Pointer Exceptions?!We’re not used to these any moreThey’re an artifact of initialization order and usage

ABC

Initialization Order

A is referencing ‘s’

Thursday, December 12, 13

Page 84: Baking Delicious Modularity in Scala

Null Pointer Exceptions?!We’re not used to these any moreThey’re an artifact of initialization order and usage

ABC

Initialization Order

A is referencing ‘s’

‘s’ hasn’t been initialized yet!

Thursday, December 12, 13

Page 85: Baking Delicious Modularity in Scala

Null Pointer Exceptions?!We’re not used to these any moreThey’re an artifact of initialization order and usage

ABC

Initialization Order

A is referencing ‘s’

‘s’ hasn’t been initialized yet!The only sane value for ‘s’ at this point is null

Thursday, December 12, 13

Page 86: Baking Delicious Modularity in Scala

Dealing with the Pain

Thursday, December 12, 13

Page 87: Baking Delicious Modularity in Scala

Dealing with the PainMethods aren’t susceptible to this problem

Thursday, December 12, 13

Page 88: Baking Delicious Modularity in Scala

Dealing with the PainMethods aren’t susceptible to this problem

Neither are lazy vals

Thursday, December 12, 13

Page 89: Baking Delicious Modularity in Scala

Dealing with the PainMethods aren’t susceptible to this problem

Neither are lazy vals

Neither are constructor parameters

Thursday, December 12, 13

Page 90: Baking Delicious Modularity in Scala

Dealing with the PainMethods aren’t susceptible to this problem

Neither are lazy vals

Neither are constructor parameters

trait A { val s: String val t: String = s.substring(0, 2)}

class B(val s) extends A

val b = new B(“What?”)

Thursday, December 12, 13

Page 91: Baking Delicious Modularity in Scala

Dealing with the PainMethods aren’t susceptible to this problem

Neither are lazy vals

Neither are constructor parameters

trait A { val s: String val t: String = s.substring(0, 2)}

class B(val s) extends A

val b = new B(“What?”)

OK

Thursday, December 12, 13

Page 92: Baking Delicious Modularity in Scala

Dealing with the PainMethods aren’t susceptible to this problem

Neither are lazy vals

Neither are constructor parameters

trait A { val s: String val t: String = s.substring(0, 2)}

class B(val s) extends A

val b = new B(“What?”)

trait A { val s: String val t: String = s.substring(0, 2)}

class B extends A { lazy val s = “What?”}

val b = new B

OK

Thursday, December 12, 13

Page 93: Baking Delicious Modularity in Scala

Dealing with the PainMethods aren’t susceptible to this problem

Neither are lazy vals

Neither are constructor parameters

trait A { val s: String val t: String = s.substring(0, 2)}

class B(val s) extends A

val b = new B(“What?”)

trait A { val s: String val t: String = s.substring(0, 2)}

class B extends A { lazy val s = “What?”}

val b = new B

OK OK

Thursday, December 12, 13

Page 94: Baking Delicious Modularity in Scala

Dealing with the PainMethods aren’t susceptible to this problem

Neither are lazy vals

Neither are constructor parameters

trait A { val s: String val t: String = s.substring(0, 2)}

class B(val s) extends A

val b = new B(“What?”)

trait A { val s: String val t: String = s.substring(0, 2)}

class B extends A { lazy val s = “What?”}

val b = new B

trait A { val s: String val t: String = s.substring(0, 2)}

class B extends A { def s = “What?”}

val b = new B

OK OK

Thursday, December 12, 13

Page 95: Baking Delicious Modularity in Scala

Dealing with the PainMethods aren’t susceptible to this problem

Neither are lazy vals

Neither are constructor parameters

trait A { val s: String val t: String = s.substring(0, 2)}

class B(val s) extends A

val b = new B(“What?”)

trait A { val s: String val t: String = s.substring(0, 2)}

class B extends A { lazy val s = “What?”}

val b = new B

trait A { val s: String val t: String = s.substring(0, 2)}

class B extends A { def s = “What?”}

val b = new B

OKOK

OK

Thursday, December 12, 13

Page 96: Baking Delicious Modularity in Scala

Now go get Fat

Derek WyattTwitter: @derekwyatt

Email: [email protected]

Eat lots of cakeAND

Maudularize Yore Coad

Thursday, December 12, 13