Below are the sources I took notes and hope to learn about Cake Pattern from.
Videos:
- SF Scala, Peter Potts: Cake Pattern in Practice
- Cake Pattern: The Bakery from the Black Lagoon
- Dead-Simple Dependency Injection
Dead-Simple Dependency Injection
setUserPwd
- a Scala method that updates some data in a database- Version 1 - everything's hardcoded
- Everything = SQL driver + database URL
- It's self-contained, reusable, fine for little toy tests
- It's not how you wanna write your actual applications
- Version 2 - global factory
- Provides database connections
- What about closing a database connection?! Who's in charge? It's not clear whose responsibility it is to close a connection.
- Bad idea
- Hidden dependency on a global object
- Requires magic initialization step = you can't call this method before that object
- Inversion of control = pretentious way of saying "taking an argument"
- That reminds me the other presentation about functional programming...
- Connection taken from ...FIXME
- Version 3 - Inversion of Control
- taking an argument = injecting
c
which is a database connection - I don't care where this connection comes from - just accept that I have one and can use it.
- I don't care how it's discarded
- I just assume that the connection is open
- You may object and say "What if the thing that knows how to obtain and a connection is way up here "
- In the call graph it needs the connection. Do I need to pass the connection through? It can get pretty easily cumbersome.
- Version 4 - Currying
- Instead of passing in the connection right away, simply partially
apply
- Instead of returning
Unit
, I'm going to return a function that accepts a connection at convenient time - The only difference is that I'm delaying the actual passing-in a connection
- Design patten - Connection Reader
- Capture this idea in a data type - just for convenience (as usual, isn't it?)
case class DB[A](g: Connection => A)
- A wrapper around the type from
Connection
toA
DB[A]
= a database action = Given aConnection
produce some value of typeA
apply
to have a convenient call- Lift existing functions using
map
map[B](f: A => B): DB[B]
~(A => B) => (DB[A] => DB[B])
- Map (or promote) an existing function
A => B
toDB[A] => DB[B]
- Implementation of map is just a function composition
- Combine two actions
- I have an action that produces
DB[A]
and you callflatMap
with a function that
- I have an action that produces