0
Baking

Delicious

Modularization

cala
in S

Derek Wyatt
Twitter: @derekwyatt
Email: derek@derekwyatt.org

Thursday, Dece...
odularity
Oriented M
Object
OOD gives us...

Thursday, December 12, 13
odularity
Oriented M
Object
OOD gives us...

Thursday, December 12, 13

private
Inheritance
Clanc erfaces
I sist s&ro ses
...
odularity
Oriented M
Object
OOD gives us...

C++ gave us...

Thursday, December 12, 13

private
Inheritance
Clanc erfaces
...
d Problem
he Diamon
T
is
Thursday, December 12, 13

A

B

is

A

A

C
d Problem
he Diamon
T
A

is

is

A

A

C

A

is

Thursday, December 12, 13

D

is
A

B
d Problem
he Diamon
T
A
A

is

is

A

?

B

A

is

Thursday, December 12, 13

D

C
is
A

Who initializes A?
d Problem
he Diamon
T
A
is

A

D

C
is
A

A

Thursday, December 12, 13

?

B
is

They can’t both do it!

is

l d
s it init...
d Problem
he Diamon
T
A
is

A

Thursday, December 12, 13

D

C
is
A

A

Enter: Virtual Inheritance

?

B
is

They can’t bo...
d Problem
he Diamon
T
A
is

A

?
A

D

C
is
A

B
is

They can’t both do it!

is

l d
s it initiaoizeoes C
B need
S d

A

W...
Inheritance
to Multiple
’s Solution
Java

Multiple Inheritance

Thursday, December 12, 13
Inheritance
to Multiple
’s Solution
Java

Multiple Inheritance
The powers that be just went and tossed it out

Thursday, D...
Inheritance
to Multiple
’s Solution
Java

Multiple Inheritance
The powers that be just went and tossed it out
Implementing...
Inheritance
to Multiple
’s Solution
Java

Multiple Inheritance
The powers that be just went and tossed it out
Implementing...
Inheritance
to Multiple
’s Solution
Java

Multiple Inheritance
The powers that be just went and tossed it out
Implementing...
Inheritance
to Multiple
’s Solution
Java

Multiple Inheritance
The powers that be just went and tossed it out
Implementing...
Inheritance
to Multiple
’s Solution
Java

L
I
A
F
#

Multiple Inheritance

The powers that be just went and tossed it out
...
nheritance
to Multiple I
a’s Solution
Scal

Thursday, December 12, 13
nheritance
to Multiple I
a’s Solution
Scal

!

Crush the Diamond

Thursday, December 12, 13
nheritance
to Multiple I
a’s Solution
Scal

!

Crush the Diamond

Scala integrates inheritance with mixin functionality

T...
nheritance
to Multiple I
a’s Solution
Scal

!

Crush the Diamond

Scala integrates inheritance with mixin functionality
Tr...
nheritance
to Multiple I
a’s Solution
Scal

!

Crush the Diamond

trait
trait
trait
class

A
B extends A
C extends A
D ext...
nheritance
to Multiple I
a’s Solution
Scal

!

Crush the Diamond

trait
trait
trait
class

A
B extends A
C extends A
D ext...
Origins of the Cake
Dependency Injection and Modularity

Persistence

REST
Persistence

PicRetriever

Database
Persistence...
Origins of the Cake
Dependency Injection and Modularity

Persistence

REST
Persistence

PicRetriever

Database
Persistence...
Origins of the Cake
Dependency Injection and Modularity

Persistence

REST
Persistence

PicRetriever

ce on
lian
re re
Dec...
Origins of the Cake
Dependency Injection and Modularity

Persistence

REST
Persistence

PicRetriever

ce on
lian
re re
Dec...
Origins of the Cake

REST

Dependency Injection and Modularity
PicRetriever

ce on
lian
re re
Decla modules
hese
t

Persis...
The Basic Cupcake
trait Persistence {
def pic(idx: Int): Future[Pic] = ???
def totalPics: Future[Int] = ???
}

Thursday, D...
The Basic Cupcake
trait Persistence {
def pic(idx: Int): Future[Pic] = ???
def totalPics: Future[Int] = ???
}

trait Rando...
The Basic Cupcake
trait Persistence {
def pic(idx: Int): Future[Pic] = ???
def totalPics: Future[Int] = ???
}

trait Rando...
The Basic Cupcake
trait Persistence {
def pic(idx: Int): Future[Pic] = ???
def totalPics: Future[Int] = ???
}

trait Rando...
ng a Layer
Addi
The lack of an “interface” requires overrides in the derivations

Thursday, December 12, 13
ng a Layer
Addi
The lack of an “interface” requires overrides in the derivations
We can add that layer, making derivations...
ng a Layer
Addi
The lack of an “interface” requires overrides in the derivations
We can add that layer, making derivations...
ng a Layer
Addi
The lack of an “interface” requires overrides in the derivations
We can add that layer, making derivations...
Eliminating Naming Conflicts

Thursday, December 12, 13
Eliminating Naming Conflicts
There’s nothing to stop you from tromping all over your names

Thursday, December 12, 13
Eliminating Naming Conflicts
There’s nothing to stop you from tromping all over your names
It’s a good idea to give namesp...
Eliminating Naming Conflicts
There’s nothing to stop you from tromping all over your names
It’s a good idea to give namesp...
Eliminating Naming Conflicts
There’s nothing to stop you from tromping all over your names
It’s a good idea to give namesp...
he Test
aming t
T

Thursday, December 12, 13
he Test
aming t
T

ze
ndomi
Ra

r

t
ponen
Com

ds
exten
p
{
erCom zer
izer
miz
om
i
do
stRan r: Random tends Rand
Te
e
ra...
he Test
aming t
T

ze
ndomi
Ra

r

t
ponen
Com

{

ds
exten
p
{
erCom zer
izer
miz
om
i
do
{
stRan r: Random tends Rand
Te...
he Test
aming t
T

ze
ndomi
Ra

r

t
ponen
Com

{

ds
exten
p
{
erCom zer
izer
miz
om
i
do
{
stRan r: Random tends Rand
Te...
he Test
aming t
T

ze
ndomi
Ra

r

t
ponen
Com

{

ds
exten
p
{
erCom zer
izer
miz
om
i
do
{
stRan r: Random tends Rand
Te...
nough Analogues... Modularity!
E

Thursday, December 12, 13
nough Analogues... Modularity!
E
You don’t have to “self type” in order to establish the contract

Thursday, December 12, ...
nough Analogues... Modularity!
E
You don’t have to “self type” in order to establish the contract
Abstract types and const...
nough Analogues... Modularity!
E
You don’t have to “self type” in order to establish the contract
Abstract types and const...
nough Analogues... Modularity!
E
You don’t have to “self type” in order to establish the contract
Abstract types and const...
nough Analogues... Modularity!
E
You don’t have to “self type” in order to establish the contract
Abstract types and const...
Use Case... Configuration

Thursday, December 12, 13
Use Case... Configuration
Let’s say you want to declare a method for configuring objects

trait
class
val
val
}
class
val
...
Use Case... Configuration
Let’s say you want to declare a method for configuring objects
You want generality, so you can’t...
Use Case... Configuration
Let’s say you want to declare a method for configuring objects
You want generality, so you can’t...
Use Case... Configuration
Let’s say you want to declare a method for configuring objects
You want generality, so you can’t...
ring through Inverse Generality
Configu

Database
Config

Thursday, December 12, 13

REST
Config

Randomization
Config
ring through Inverse Generality
Configu
Config

sA
I
Database
Config

Thursday, December 12, 13

IsA
REST
Config

IsA
Rand...
ring through Inverse Generality
Configu
Config

sA
I
Database
Config

Thursday, December 12, 13

IsA
REST
Config

Empty ge...
ring through Inverse Generality
Configu
Database
Config

Randomization
Config

REST
Config

Da

REST

iz
m

ti
a

n
o

CON...
Thickly Typed Objects

Thursday, December 12, 13

❊
Kinda stolen from Daniel Spiewak
Thickly Typed Objects
trait ConfigComponent {
type Config
def config: Config
}

Thursday, December 12, 13

❊
Kinda stolen ...
Thickly Typed Objects
trait ConfigComponent {
type Config
def config: Config
}

❊
Kinda stolen from Daniel Spiewak

Declar...
Thickly Typed Objects
trait ConfigComponent {
type Config
def config: Config
}

❊
Kinda stolen from Daniel Spiewak

Declar...
Thickly Typed Objects
trait ConfigComponent {
type Config
def config: Config
}

❊
Kinda stolen from Daniel Spiewak

Declar...
Typed Objects Continued
Thickly
class TheFinalThing extends DBComponent with RandomizerComponent
with RESTComponent {
type...
Typed Objects Continued
Thickly
class TheFinalThing extends DBComponent with RandomizerComponent
with RESTComponent {
type...
Typed Objects Continued
Thickly
class TheFinalThing extends DBComponent with RandomizerComponent
with RESTComponent {
type...
n and Frustration
ai
P

Thursday, December 12, 13
n and Frustration
ai
P
Cakes generally involve abstract

Thursday, December 12, 13

vals
n and Frustration
ai
P
Cakes generally involve abstract

vals

They also involve “Multiple Inheritance”

Thursday, Decembe...
n and Frustration
ai
P
Cakes generally involve abstract

vals

They also involve “Multiple Inheritance”
This presents an i...
n and Frustration
ai
P
Cakes generally involve abstract

vals

They also involve “Multiple Inheritance”
This presents an i...
n and Frustration
ai
P
Cakes generally involve abstract

vals

They also involve “Multiple Inheritance”
This presents an i...
n and Frustration
ai
P
Cakes generally involve abstract

vals

They also involve “Multiple Inheritance”
This presents an i...
n and Frustration
ai
P
Cakes generally involve abstract

vals

They also involve “Multiple Inheritance”
This presents an i...
Null Pointer Exceptions?!

Thursday, December 12, 13
Null Pointer Exceptions?!
We’re not used to these any more

Thursday, December 12, 13
Null Pointer Exceptions?!
We’re not used to these any more
They’re an artifact of initialization order and usage

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

A
B
C
Th...
Null Pointer Exceptions?!
We’re not used to these any more
They’re an artifact of initialization order and usage

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

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

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

Thursday...
Dealing with the Pain

Thursday, December 12, 13
Dealing with the Pain
Methods aren’t susceptible to this problem

Thursday, December 12, 13
Dealing with the Pain
Methods aren’t susceptible to this problem
Neither are lazy vals

Thursday, December 12, 13
Dealing with the Pain
Methods aren’t susceptible to this problem
Neither are lazy vals
Neither are constructor parameters
...
Dealing with the Pain
Methods aren’t susceptible to this problem
Neither are lazy vals
Neither are constructor parameters
...
Dealing with the Pain
Methods aren’t susceptible to this problem
Neither are lazy vals
Neither are constructor parameters
...
Dealing with the Pain
Methods aren’t susceptible to this problem
Neither are lazy vals
Neither are constructor parameters
...
Dealing with the Pain
Methods aren’t susceptible to this problem
Neither are lazy vals
Neither are constructor parameters
...
Dealing with the Pain
Methods aren’t susceptible to this problem
Neither are lazy vals
Neither are constructor parameters
...
Dealing with the Pain
Methods aren’t susceptible to this problem
Neither are lazy vals
Neither are constructor parameters
...
Now go get Fat

Eat lots of cake

AND

audularize Yore Coad
M
Derek Wyatt
Twitter: @derekwyatt
Email: derek@derekwyatt.org...
Upcoming SlideShare
Loading in...5
×

Baking Delicious Modularity in Scala

3,795

Published on

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...

Published in: Technology
7 Comments
18 Likes
Statistics
Notes
  • In slide 94-95, I think trait A should have s and t as "def", and class B can override it as "val" (or "def").
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • @RobbyPelssers1 I actually played more with this in a recent 'for fun' project. In the end, I think it works out pretty well and allows me to construct an 'application object' by mixing everything together. You can see it at https://github.com/derekwyatt/shorty-dqw, if you want to get a more concrete example of using the 'thick-type' pattern.
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • @DerekWyatt1 Yes... I understand.. I was just wondering. I also viewed Daniel's original article about this subject and I agree that delaying the concrete type is really cool and that this is the actual subject of your presentation.
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • @RobbyPelssers1 You certainly could. It can reduce the generality of the Component trait a fair bit, though. What's really the point, is that it's a limiting construct. By abstracting the type (on the following slides) you can delay the concrete type of 'Config' until later, and let other components take greater advantage of the upper level trait, and thus achieve a greater amount of modularity.

    In the end, it's just a slide :)
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • Am I missing something or couldn't you rewrite the code from slide 56 to this?

    trait Config

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

    trait RESTConfig extends Config {
    val restHost: String
    val restPort: Int
    }

    abstract class Component(config: Config)

    class Database(config: DBConfig) extends Component(config)

    class REST(config: RESTConfig) extends Component(config)
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
No Downloads
Views
Total Views
3,795
On Slideshare
0
From Embeds
0
Number of Embeds
14
Actions
Shares
0
Downloads
62
Comments
7
Likes
18
Embeds 0
No embeds

No notes for slide

Transcript of "Baking Delicious Modularity in Scala"

  1. 1. Baking Delicious Modularization cala in S Derek Wyatt Twitter: @derekwyatt Email: derek@derekwyatt.org Thursday, December 12, 13
  2. 2. odularity Oriented M Object OOD gives us... Thursday, December 12, 13
  3. 3. odularity Oriented M Object OOD gives us... Thursday, December 12, 13 private Inheritance Clanc erfaces I sist s&ro ses ubl e p tlas p Cected Composition act str Ab
  4. 4. odularity Oriented M Object OOD gives us... C++ gave us... Thursday, December 12, 13 private Inheritance Clanc erfaces I sist s&ro ses ubl e p tlas p Cected Composition act str Ab ht? R ig ... l Ev i Multiple Inheritance lain st P Ju
  5. 5. d Problem he Diamon T is Thursday, December 12, 13 A B is A A C
  6. 6. d Problem he Diamon T A is is A A C A is Thursday, December 12, 13 D is A B
  7. 7. d Problem he Diamon T A A is is A ? B A is Thursday, December 12, 13 D C is A Who initializes A?
  8. 8. d Problem he Diamon T A is A D C is A A Thursday, December 12, 13 ? B is They can’t both do it! is l d s it initiaoizeoes C B need S d A Who initializes A?
  9. 9. d Problem he Diamon T A is A Thursday, December 12, 13 D C is A A Enter: Virtual Inheritance ? B is They can’t both do it! is l d s it initiaoizeoes C B need S d A Who initializes A?
  10. 10. d Problem he Diamon T A is A ? A D C is A B is They can’t both do it! is l d s it initiaoizeoes C B need S d A Who initializes A? Enter: Virtual Inheritance Convincing the world for decades that Multiple Inheritance is BAD Thursday, December 12, 13
  11. 11. Inheritance to Multiple ’s Solution Java Multiple Inheritance Thursday, December 12, 13
  12. 12. Inheritance to Multiple ’s Solution Java Multiple Inheritance The powers that be just went and tossed it out Thursday, December 12, 13
  13. 13. Inheritance to Multiple ’s Solution Java Multiple Inheritance The powers that be just went and tossed it out Implementing multiple interfaces and extending one abstract class is not equivalent Thursday, December 12, 13
  14. 14. Inheritance to Multiple ’s Solution Java Multiple Inheritance The powers that be just went and tossed it out Implementing multiple interfaces and extending one abstract class is not equivalent Implementing the multiple interfaces is work Thursday, December 12, 13
  15. 15. Inheritance to Multiple ’s Solution Java Multiple Inheritance The powers that be just went and tossed it out Implementing multiple interfaces and extending one abstract class is not equivalent Implementing the multiple interfaces is work and ose e mp gat Sharing code amongst implementations is hard Co le de Thursday, December 12, 13
  16. 16. Inheritance to Multiple ’s Solution Java Multiple Inheritance The powers that be just went and tossed it out Implementing multiple interfaces and extending one abstract class is not equivalent Implementing the multiple interfaces is work and ose e mp gat Sharing code amongst implementations is hard Co le de Inconsistencies show up very quickly and maintenance is a pain Thursday, December 12, 13
  17. 17. Inheritance to Multiple ’s Solution Java L I A F # Multiple Inheritance The powers that be just went and tossed it out Implementing multiple interfaces and extending one abstract class is not equivalent Implementing the multiple interfaces is work and ose e mp gat Sharing code amongst implementations is hard Co le de Inconsistencies show up very quickly and maintenance is a pain Thursday, December 12, 13
  18. 18. nheritance to Multiple I a’s Solution Scal Thursday, December 12, 13
  19. 19. nheritance to Multiple I a’s Solution Scal ! Crush the Diamond Thursday, December 12, 13
  20. 20. nheritance to Multiple I a’s Solution Scal ! Crush the Diamond Scala integrates inheritance with mixin functionality Thursday, December 12, 13
  21. 21. nheritance to Multiple I a’s Solution Scal ! Crush the Diamond Scala integrates inheritance with mixin functionality Traits provide the construct for mixins trait trait trait class Thursday, December 12, 13 A B extends A C extends A D extends B with C
  22. 22. nheritance to Multiple I a’s Solution Scal ! Crush the Diamond trait trait trait class A B extends A C extends A D extends B with C AnyRef A Translates to B C D Thursday, December 12, 13 Initialize Scala integrates inheritance with mixin functionality Traits provide the construct for mixins Any
  23. 23. nheritance to Multiple I a’s Solution Scal ! Crush the Diamond trait trait trait class A B extends A C extends A D extends B with C A Translates to If a conflict exists between B and C with respect to A, then C wins. Thursday, December 12, 13 AnyRef B C D Initialize Scala integrates inheritance with mixin functionality Traits provide the construct for mixins Any
  24. 24. Origins of the Cake Dependency Injection and Modularity Persistence REST Persistence PicRetriever Database Persistence Persistence Randomizer def randomPic: Future[Pic] HashMap Randomizer Random Randomizer Specifier Thursday, December 12, 13 Test Test
  25. 25. Origins of the Cake Dependency Injection and Modularity Persistence REST Persistence PicRetriever Database Persistence Persistence Randomizer def randomPic: Future[Pic] HashMap Randomizer Random Randomizer Specifier Thursday, December 12, 13 Test Test
  26. 26. Origins of the Cake Dependency Injection and Modularity Persistence REST Persistence PicRetriever ce on lian re re Decla modules hese t Database Persistence Persistence Randomizer def randomPic: Future[Pic] HashMap Randomizer Random Randomizer Specifier Thursday, December 12, 13 Test Test
  27. 27. Origins of the Cake Dependency Injection and Modularity Persistence REST Persistence PicRetriever ce on lian re re Decla modules hese t Persistence Persistence Randomizer def randomPic: Future[Pic] new PicRetriever extends Database with Random Choos e concrete implementa tions Thursday, December 12, 13 Database HashMap Test Randomizer Random Randomizer Specifier Test
  28. 28. Origins of the Cake REST Dependency Injection and Modularity PicRetriever ce on lian re re Decla modules hese t Persistence Persistence Database Randomizer Randomizer Random Persistence iever Retr Pic the Persistence es in Test mix HashMap face ter in the and tion enta plem im def randomPic: Future[Pic] new PicRetriever extends Database with Random Choos e concrete implementa tions Thursday, December 12, 13 Randomizer Specifier Test
  29. 29. The Basic Cupcake trait Persistence { def pic(idx: Int): Future[Pic] = ??? def totalPics: Future[Int] = ??? } Thursday, December 12, 13 trait Randomizer { def nextInt(upperBound: Int): Int = ??? }
  30. 30. The Basic Cupcake trait Persistence { def pic(idx: Int): Future[Pic] = ??? def totalPics: Future[Int] = ??? } trait Randomizer { def nextInt(upperBound: Int): Int = ??? } cRe Pi ever tri lare Dec ype elf t s class PicRetriever { this: Persistence with Randomizer => def randomPic: Future[Pic] = ??? } object PicRetriever { def production: PicRetriever = new PicRetriever with Persistence with Randomizer } Thursday, December 12, 13
  31. 31. The Basic Cupcake trait Persistence { def pic(idx: Int): Future[Pic] = ??? def totalPics: Future[Int] = ??? } trait Randomizer { def nextInt(upperBound: Int): Int = ??? } cRe Pi ever tri lare Dec ype elf t s class PicRetriever { this: Persistence with Randomizer => def randomPic: Future[Pic] = ??? } Define factory method that makes construction simpler object PicRetriever { def production: PicRetriever = new PicRetriever with Persistence with Randomizer } Thursday, December 12, 13
  32. 32. The Basic Cupcake trait Persistence { def pic(idx: Int): Future[Pic] = ??? def totalPics: Future[Int] = ??? } trait Randomizer { def nextInt(upperBound: Int): Int = ??? } cRe Pi ever tri lare Dec ype elf t s class PicRetriever { this: Persistence with Randomizer => def randomPic: Future[Pic] = ??? } Define factory method that makes construction simpler object PicRetriever { def production: PicRetriever = new PicRetriever with Persistence with Randomizer } You could derive new Persistence and Randomizer traits and instantiate accordingly. Not great, but it does get the job done. Thursday, December 12, 13
  33. 33. ng a Layer Addi The lack of an “interface” requires overrides in the derivations Thursday, December 12, 13
  34. 34. ng a Layer Addi The lack of an “interface” requires overrides in the derivations We can add that layer, making derivations easier to write Thursday, December 12, 13
  35. 35. ng a Layer Addi The lack of an “interface” requires overrides in the derivations We can add that layer, making derivations easier to write trait def def } trait val def def } Persistence { pic(idx: Int): Future[Pic] totalPics: Future[Int] Database extends Persistence { dbUrl: String pic(idx: Int): Future[Pic] = ??? totalPics: Int = ??? Thursday, December 12, 13 trait def } trait def } Randomizer { nextInt(upperBound: Int): Int RealRandomizer extends Randomizer { nextInt(upperBound: Int): Int = ???
  36. 36. ng a Layer Addi The lack of an “interface” requires overrides in the derivations We can add that layer, making derivations easier to write trait def def } trait val def def } Persistence { pic(idx: Int): Future[Pic] totalPics: Future[Int] Database extends Persistence { dbUrl: String pic(idx: Int): Future[Pic] = ??? totalPics: Int = ??? trait def } trait def } Randomizer { nextInt(upperBound: Int): Int RealRandomizer extends Randomizer { nextInt(upperBound: Int): Int = ??? object PicRetriever { def production: PicRetriever = new PicRetriever with Database with RealRandomizer } Thursday, December 12, 13
  37. 37. Eliminating Naming Conflicts Thursday, December 12, 13
  38. 38. Eliminating Naming Conflicts There’s nothing to stop you from tromping all over your names Thursday, December 12, 13
  39. 39. Eliminating Naming Conflicts There’s nothing to stop you from tromping all over your names It’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] } } Thursday, December 12, 13 trait RandomizerComponent { val randomizer: Randomizer trait Randomizer { def nextInt(upperBound: Int): Int } }
  40. 40. Eliminating Naming Conflicts There’s nothing to stop you from tromping all over your names It’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 } } g can be Everythin th another solved wi indirection layer of Thursday, December 12, 13
  41. 41. Eliminating Naming Conflicts There’s nothing to stop you from tromping all over your names It’s a good idea to give namespaces to the mixed-in modules trait PersistenceComponent { trait RandomizerComponent { val persistence: Persistence val randomizer: Randomizer trait Persistence { trait Randomizer { def pic(idx: Int): Future[Pic] def nextInt(upperBound: Int): Int def totalPics: Future[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
  42. 42. he Test aming t T Thursday, December 12, 13
  43. 43. he Test aming t T ze ndomi Ra r t ponen Com ds exten p { erCom zer izer miz om i do stRan r: Random tends Rand Te e rait t domiz omizer ex i an nt = val r estRand I Int): t T : trai Int Bound r : val i tInt(uppe ex def n } } Thursday, December 12, 13 {
  44. 44. he Test aming t T ze ndomi Ra r t ponen Com { ds exten p { erCom zer izer miz om i do { stRan r: Random tends Rand Te ponent om trait andomize mizer ex tenceC i is nt = val r estRando s Pers I nd p exte mponent Int): t T : Com trai { Int Bound stence istenceCo i: per tence ersi is up tP val tInt( it Tes stence: Pers extends Pers ex tra )) def n cs(idx persi ence pi st val uture( ize) tPersi r[Pic] es = F } .s rait T s: Vecto [Pic] t ture e(pics u r c val pi idx: Int): F [Int] = Futu } ( ef pic Pics: Future d l f tota de } } Thursday, December 12, 13
  45. 45. he Test aming t T ze ndomi Ra r t ponen Com { ds exten p { erCom zer izer miz om i do { stRan r: Random tends Rand Te ponent om trait andomize mizer ex tenceC i is nt = val r estRando s Pers I nd p exte mponent Int): t T : Com trai { Int Bound stence istenceCo i: per tence ersi is up tP val tInt( it Tes stence: Pers extends Pers ex tra )) def n cs(idx persi ence pi st val uture( ize) tPersi r[Pic] es = F } .s rait T s: Vecto [Pic] t ture e(pics u r c val pi idx: Int): F [Int] = Futu } ( ef pic Pics: Future d l f tota de } object TestPicRetriever } { def test(num: Int, images : Vector[Pic]): PicRetri ever = new PicRetriever with Te stPersistenceComp with TestRandomizerComp { val persistence = new Te stPersistence { val pics = images } val randomizer = new Test Randomizer { val i = num } } Thursday, December 12, 13
  46. 46. he Test aming t T ze ndomi Ra r t ponen Com { ds exten p { erCom zer izer miz om i do { stRan r: Random tends Rand Te ponent om trait andomize mizer ex tenceC i is nt = val r estRando s Pers I nd p exte mponent Int): t T : Com trai { Int Bound stence istenceCo i: per tence ersi is up tP val tInt( it Tes stence: Pers extends Pers ex tra )) def n cs(idx val pic = loadPic(“pic1”) rsi pe ence pi st val uture( ize) tPersi r[Pic] es ] val retriever = TestPicRetriever.test(0, Vector(pic))= F pics.s } rait T s: Vecto t re[Pic ture( u Await.result(retriever.randomPic,:1.second)t should be (pic) l pic t): Fu nt] = Fu va In } I (idx pic uture[ F def lPics: ta def to } object TestPicRetriever } { def test(num: Int, images : Vector[Pic]): PicRetri ever = new PicRetriever with Te stPersistenceComp with TestRandomizerComp { val persistence = new Te stPersistence { val pics = images } val randomizer = new Test Randomizer { val i = num } } Thursday, December 12, 13
  47. 47. nough Analogues... Modularity! E Thursday, December 12, 13
  48. 48. nough Analogues... Modularity! E You don’t have to “self type” in order to establish the contract Thursday, December 12, 13
  49. 49. nough Analogues... Modularity! E 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
  50. 50. nough Analogues... Modularity! E 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] } Thursday, December 12, 13 trait RandomizerLike { def nextInt(upperBound: Int): Int }
  51. 51. nough Analogues... Modularity! E 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 } trait PicRetriever { type Persistence <: PersistenceLike type Randomizer <: RandomizerLike val persistence: Persistence val randomizer: Randomizer } Thursday, December 12, 13 // ...
  52. 52. nough Analogues... Modularity! E 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] } Abstract types define enough to work with for the PicRetriever, but allow for further specification later Thursday, December 12, 13 trait RandomizerLike { def nextInt(upperBound: Int): Int } trait PicRetriever { type Persistence <: PersistenceLike type Randomizer <: RandomizerLike val persistence: Persistence val randomizer: Randomizer } // ...
  53. 53. Use Case... Configuration Thursday, December 12, 13
  54. 54. Use Case... Configuration Let’s say you want to declare a method for configuring objects trait class val val } class val val } class val val } Thursday, December 12, 13 Config DBConfig extends Config { dbHost: String dbPort: Int RandomizerConfig extends Config { randomSeed: Int randomScale: Int RESTConfig extends Config { restHost: String restPort: Int
  55. 55. 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) Thursday, December 12, 13 trait class val val } class val val } class val val } Config DBConfig extends Config { dbHost: String dbPort: Int RandomizerConfig extends Config { randomSeed: Int randomScale: Int RESTConfig extends Config { restHost: String restPort: Int
  56. 56. 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 Config class DBConfig extends Config { val dbHost: String class Database(config: Config) extends Component(config) ort: Int val dbP { require(config.isInstanceOf[DBConfig]) } } class RandomizerConfig extends Config { val randomSeed: Int val randomScale: Int class Randomizer(config: Config) extends Component(config) { } require(config.isInstanceOf[RandomizerConfig]) ss RESTConfig extends Config { cla } val restHost: String val restPort: Int } class REST(config: Config) extends Component(config) { require(config.isInstanceOf[RESTConfig]) } Thursday, December 12, 13
  57. 57. 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 d an e, af s n ,U g ly in g U oy n n A abstract class Component(config: Config) trait Config class DBConfig extends Config { val dbHost: String class Database(config: Config) extends Component(config) ort: Int val dbP { require(config.isInstanceOf[DBConfig]) } } class RandomizerConfig extends Config { val randomSeed: Int val randomScale: Int class Randomizer(config: Config) extends Component(config) { } require(config.isInstanceOf[RandomizerConfig]) ss RESTConfig extends Config { cla } val restHost: String val restPort: Int } class REST(config: Config) extends Component(config) { require(config.isInstanceOf[RESTConfig]) } Thursday, December 12, 13
  58. 58. ring through Inverse Generality Configu Database Config Thursday, December 12, 13 REST Config Randomization Config
  59. 59. ring through Inverse Generality Configu Config sA I Database Config Thursday, December 12, 13 IsA REST Config IsA Randomization Config
  60. 60. ring through Inverse Generality Configu Config sA I Database Config Thursday, December 12, 13 IsA REST Config Empty generalization IsA Randomization Config
  61. 61. ring through Inverse Generality Configu Database Config Randomization Config REST Config Da REST iz m ti a n o CONFIG OBJECT ba do s ta e an R Highly Specific and Type safe Thursday, December 12, 13
  62. 62. Thickly Typed Objects Thursday, December 12, 13 ❊ Kinda stolen from Daniel Spiewak
  63. 63. Thickly Typed Objects trait ConfigComponent { type Config def config: Config } Thursday, December 12, 13 ❊ Kinda stolen from Daniel Spiewak Declare a way to configure things
  64. 64. Thickly Typed Objects trait ConfigComponent { type Config def config: Config } ❊ Kinda stolen from Daniel Spiewak Declare a way to configure things 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 } Thursday, December 12, 13
  65. 65. Thickly Typed Objects trait ConfigComponent { type Config def config: Config } ❊ Kinda stolen from Daniel Spiewak Declare a way to configure things 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 } Thursday, December 12, 13 Define how to configure this component
  66. 66. Thickly Typed Objects trait ConfigComponent { type Config def config: Config } ❊ Kinda stolen from Daniel Spiewak Declare a way to configure things Repeat for REST and Randomizer 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 } Thursday, December 12, 13 Define how to configure this component
  67. 67. Typed Objects Continued Thickly class 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
  68. 68. Typed Objects Continued Thickly class 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 The config object now conforms to the types requested by everything that’s been mixed in.
  69. 69. Typed Objects Continued Thickly class 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 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.
  70. 70. n and Frustration ai P Thursday, December 12, 13
  71. 71. n and Frustration ai P Cakes generally involve abstract Thursday, December 12, 13 vals
  72. 72. n and Frustration ai P Cakes generally involve abstract vals They also involve “Multiple Inheritance” Thursday, December 12, 13
  73. 73. n and Frustration ai P Cakes generally involve abstract vals They also involve “Multiple Inheritance” This presents an interesting initialization problem Thursday, December 12, 13
  74. 74. n and Frustration ai P Cakes generally involve abstract vals They 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
  75. 75. n and Frustration ai P Cakes generally involve abstract vals They 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 class C extends A with B val c = new C
  76. 76. n and Frustration ai P Cakes generally involve abstract vals They 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 class C extends A with B val c = new C
  77. 77. n and Frustration ai P Cakes generally involve abstract vals They 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 PE N !! !!! ! class C extends A with B val c = new C
  78. 78. Null Pointer Exceptions?! Thursday, December 12, 13
  79. 79. Null Pointer Exceptions?! We’re not used to these any more Thursday, December 12, 13
  80. 80. Null Pointer Exceptions?! We’re not used to these any more They’re an artifact of initialization order and usage Thursday, December 12, 13
  81. 81. Null Pointer Exceptions?! We’re not used to these any more They’re an artifact of initialization order and usage A B C Thursday, December 12, 13
  82. 82. Null Pointer Exceptions?! We’re not used to these any more They’re an artifact of initialization order and usage Thursday, December 12, 13 Initialization Order A B C
  83. 83. Null Pointer Exceptions?! We’re not used to these any more They’re an artifact of initialization order and usage Thursday, December 12, 13 Initialization Order A B C A is referencing ‘s’
  84. 84. Null Pointer Exceptions?! We’re not used to these any more They’re an artifact of initialization order and usage Thursday, December 12, 13 Initialization Order A B C A is referencing ‘s’ ‘s’ hasn’t been initialized yet!
  85. 85. Null Pointer Exceptions?! We’re not used to these any more They’re an artifact of initialization order and usage Thursday, December 12, 13 Initialization Order A B C A is referencing ‘s’ ‘s’ hasn’t been initialized yet! The only sane value for ‘s’ at this point is null
  86. 86. Dealing with the Pain Thursday, December 12, 13
  87. 87. Dealing with the Pain Methods aren’t susceptible to this problem Thursday, December 12, 13
  88. 88. Dealing with the Pain Methods aren’t susceptible to this problem Neither are lazy vals Thursday, December 12, 13
  89. 89. Dealing with the Pain Methods aren’t susceptible to this problem Neither are lazy vals Neither are constructor parameters Thursday, December 12, 13
  90. 90. Dealing with the Pain Methods 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
  91. 91. Dealing with the Pain Methods 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) } OK class B(val s) extends A val b = new B(“What?”) Thursday, December 12, 13
  92. 92. Dealing with the Pain Methods 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) } trait A { val s: String val t: String = s.substring(0, 2) } class B(val s) extends A class B extends A { lazy val s = “What?” } OK val b = new B(“What?”) val b = new B Thursday, December 12, 13
  93. 93. Dealing with the Pain Methods 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) } trait A { val s: String val t: String = s.substring(0, 2) } class B(val s) extends A class B extends A { lazy val s = “What?” } OK val b = new B(“What?”) OK val b = new B Thursday, December 12, 13
  94. 94. Dealing with the Pain Methods aren’t susceptible to this problem Neither are lazy vals Neither are constructor parameters trait A { trait A { val s: String val s: String val t: String = s.substring(0, 2) val t: String = s.substring(0, 2) trait A { } } val s: String val t: String = s.substring(0, 2) class B extends A { class B(val s) extends} A lazy val s = “What?” val b = new B(“What?”)class B extends A { } def s = “What?” val b = new B } OK OK val b = new B Thursday, December 12, 13
  95. 95. Dealing with the Pain Methods aren’t susceptible to this problem Neither are lazy vals Neither are constructor parameters trait A { trait A { val s: String val s: String val t: String = s.substring(0, 2) val t: String = s.substring(0, 2) trait A { } } val s: String val t: String = s.substring(0, 2) class B extends A { class B(val s) extends} A lazy val s = “What?” val b = new B(“What?”)class B extends A { } def s = “What?” val b = new B } OK OK val b = new B Thursday, December 12, 13 OK
  96. 96. Now go get Fat Eat lots of cake AND audularize Yore Coad M Derek Wyatt Twitter: @derekwyatt Email: derek@derekwyatt.org Thursday, December 12, 13
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×