Why use scala's cake pattern rather than abstract fields? - scala

I have been reading about doing Dependency Injection in scala via the cake pattern. I think I understand it but I must have missed something because I still can't see the point in it! Why is it preferable to declare dependencies via self types rather than just abstract fields?
Given the example in Programming Scala TwitterClientComponent declares dependencies like this using the cake pattern:
//other trait declarations elided for clarity
...
trait TwitterClientComponent {
self: TwitterClientUIComponent with
TwitterLocalCacheComponent with
TwitterServiceComponent =>
val client: TwitterClient
class TwitterClient(val user: TwitterUserProfile) extends Tweeter {
def tweet(msg: String) = {
val twt = new Tweet(user, msg, new Date)
if (service.sendTweet(twt)) {
localCache.saveTweet(twt)
ui.showTweet(twt)
}
}
}
}
How is this better than declaring dependencies as abstract fields as below?
trait TwitterClient(val user: TwitterUserProfile) extends Tweeter {
//abstract fields instead of cake pattern self types
val service: TwitterService
val localCache: TwitterLocalCache
val ui: TwitterClientUI
def tweet(msg: String) = {
val twt = new Tweet(user, msg, new Date)
if (service.sendTweet(twt)) {
localCache.saveTweet(twt)
ui.showTweet(twt)
}
}
}
Looking at instantiation time, which is when DI actually happens (as I understand it), I am struggling to see the advantages of cake, especially when you consider the extra keyboard typing you need to do for the cake declarations (enclosing trait)
//Please note, I have stripped out some implementation details from the
//referenced example to clarify the injection of implemented dependencies
//Cake dependencies injected:
trait TextClient
extends TwitterClientComponent
with TwitterClientUIComponent
with TwitterLocalCacheComponent
with TwitterServiceComponent {
// Dependency from TwitterClientComponent:
val client = new TwitterClient
// Dependency from TwitterClientUIComponent:
val ui = new TwitterClientUI
// Dependency from TwitterLocalCacheComponent:
val localCache = new TwitterLocalCache
// Dependency from TwitterServiceComponent
val service = new TwitterService
}
Now again with abstract fields, more or less the same!:
trait TextClient {
//first of all no need to mixin the components
// Dependency on TwitterClient:
val client = new TwitterClient
// Dependency on TwitterClientUI:
val ui = new TwitterClientUI
// Dependency on TwitterLocalCache:
val localCache = new TwitterLocalCache
// Dependency on TwitterService
val service = new TwitterService
}
I'm sure I must be missing something about cake's superiority! However, at the moment I can't see what it offers over declaring dependencies in any other way (constructor, abstract fields).

Traits with self-type annotation is far more composable than old-fasioned beans with field injection, which you probably had in mind in your second snippet.
Let's look how you will instansiate this trait:
val productionTwitter = new TwitterClientComponent with TwitterUI with FSTwitterCache with TwitterConnection
If you need to test this trait you probably write:
val testTwitter = new TwitterClientComponent with TwitterUI with FSTwitterCache with MockConnection
Hmm, a little DRY violation. Let's improve.
trait TwitterSetup extends TwitterClientComponent with TwitterUI with FSTwitterCache
val productionTwitter = new TwitterSetup with TwitterConnection
val testTwitter = new TwitterSetup with MockConnection
Furthermore if you have a dependency between services in your component (say UI depends on TwitterService) they will be resolved automatically by the compiler.

Think about what happens if TwitterService uses TwitterLocalCache. It would be a lot easier if TwitterService self-typed to TwitterLocalCache because TwitterService has no access to the val localCache you've declared. The Cake pattern (and self-typing) allows for us to inject in a much more universal and flexible manner (among other things, of course).

I was unsure how the actual wiring would work, so I've adapted the simple example in the blog entry you linked to using abstract properties like you suggested.
// =======================
// service interfaces
trait OnOffDevice {
def on: Unit
def off: Unit
}
trait SensorDevice {
def isCoffeePresent: Boolean
}
// =======================
// service implementations
class Heater extends OnOffDevice {
def on = println("heater.on")
def off = println("heater.off")
}
class PotSensor extends SensorDevice {
def isCoffeePresent = true
}
// =======================
// service declaring two dependencies that it wants injected
// via abstract fields
abstract class Warmer() {
val sensor: SensorDevice
val onOff: OnOffDevice
def trigger = {
if (sensor.isCoffeePresent) onOff.on
else onOff.off
}
}
trait PotSensorMixin {
val sensor = new PotSensor
}
trait HeaterMixin {
val onOff = new Heater
}
val warmer = new Warmer with PotSensorMixin with HeaterMixin
warmer.trigger
in this simple case it does work (so the technique you suggest is indeed usable).
However, the same blog shows at least other three methods to achieve the same result; I think the choice is mostly about readability and personal preference. In the case of the technique you suggest IMHO the Warmer class communicates poorly its intent to have dependencies injected. Also to wire up the dependencies, I had to create two more traits (PotSensorMixin and HeaterMixin), but maybe you had a better way in mind to do it.

In this example I think there is no big difference. Self-types can potentially bring more clarity in cases when a trait declares several abstract values, like
trait ThreadPool {
val minThreads: Int
val maxThreads: Int
}
Then instead of depending on several abstract values you just declare dependency on a ThreadPool.
Self-types (as used in Cake pattern) for me are just a way to declare several abstract members at once, giving those a convenient name.

Related

What is the purpose of AbstractSystem trait in akka-spray-websocket activator?

I'm learning Spray and Akka. And I'm learning it through TypeSafe's templates, and this one is very complex at least:
http://typesafe.com/activator/template/akka-spray-websocket
I now understand the werid structure this template has is to separate routing logic and business logic and it's amazingly done. However, although I know the purpose of this structure, I don't know what's the functionality of this small piece and why is it necessary:
They have a class called MainActors.scala:
trait MainActors {
this: AbstractSystem =>
lazy val find = system.actorOf(Props[FindActor], "find")
lazy val hide = system.actorOf(Props[HideActor], "hide")
}
Then the template concatenates all the routings under a class called ReactiveApi.scala:
trait AbstractSystem {
implicit def system: ActorSystem
}
trait ReactiveApi extends RouteConcatenation with StaticRoute with AbstractSystem {
this: MainActors =>
val rootService = system.actorOf(Props(classOf[RootService], routes))
lazy val routes = logRequest(showReq _) {
new FindService(find).route ~
new HideService(hide).route ~
staticRoute
}
private def showReq(req : HttpRequest) = LogEntry(req.uri, InfoLevel)
}
Actually, my question is simple: what is the purpose of AbstractSystem trait? how is it used and why is it used?
This trait is also passed into actual actor:
class FindService(find : ActorRef)(implicit system : ActorSystem) extends Directives {
lazy val route = ...
}
Also, if it is not entirely inconvenient, what's the functionality of logRequest() and showReq()?
For Spray: why do I have to pass an actor (ActorRef) into FindServce? I don't see any specific methods being invoked from inside.
This is a very simple example of using abstract defs in order to do the cake pattern (very simplified though). The goal is to say "hey, I need this thing", and the implementor must then provide the actor system to you – by implementing the def system. The goal is of course to make this def available to MainActors.
As for the self type reference, you can refer to ktoso/types-of-types#self-type-annotation to find out more about it.

Scala Cake Pattern and Dependency Collisions

I'm trying to implement dependency injection in Scala with the Cake Pattern, but am running into dependency collisions. Since I could not find a detailed example with such dependencies, here's my problem:
Suppose we have the following trait (with 2 implementations):
trait HttpClient {
def get(url: String)
}
class DefaultHttpClient1 extends HttpClient {
def get(url: String) = ???
}
class DefaultHttpClient2 extends HttpClient {
def get(url: String) = ???
}
And the following two cake pattern modules (which in this example are both APIs that depend on our HttpClient for their functionality):
trait FooApiModule {
def httpClient: HttpClient // dependency
lazy val fooApi = new FooApi() // providing the module's service
class FooApi {
def foo(url: String): String = {
val res = httpClient.get(url)
// ... something foo specific
???
}
}
}
and
trait BarApiModule {
def httpClient: HttpClient // dependency
lazy val barApi = new BarApi() // providing the module's service
class BarApi {
def bar(url: String): String = {
val res = httpClient.get(url)
// ... something bar specific
???
}
}
}
Now when creating the final app that uses both modules, we need to provide the httpClient dependency for both of the modules. But what if we want to provide a different implementation of it for each of the modules? Or simply provide different instances of the dependency configured differently (say with a different ExecutionContext for example)?
object MyApp extends FooApiModule with BarApiModule {
// the same dependency supplied to both modules
val httpClient = new DefaultHttpClient1()
def run() = {
val r1 = fooApi.foo("http://...")
val r2 = barApi.bar("http://...")
// ...
}
}
We could name the dependencies differently in each module, prefixing them with the module name, but that would be cumbersome and inelegant, and also won't work if we don't have full control of the modules ourselves.
Any ideas? Am I misinterpreting the Cake Pattern?
You get the pattern correctly and you've just discovered its important limitation. If two modules depend on some object (say HttpClient) and happen to declare it under the same name (like httpClient), the game is over - you won't configure them separately inside one Cake. Either have two Cakes, like Daniel advises or change modules' sources if you can (as Tomer Gabel is hinting).
Each of those solutions has its problems.
Having two Cakes (Daniel's advice) looks well as long they don't need some common dependencies.
Renaming some dependencies (provided it's possible) forces you to adjust all code that uses those.
Therefore some people (including me) prefer solutions immune to those problems, like using plain old constructors and avoid Cake altogether. If you measured it, they don't add much bloat to the code (Cake is already pretty verbose) and they're much more flexible.
"You're doing it wrong" (TM). You'd have the exact same problem with Spring, Guice or any IoC container: you're treating types as names (or symbols); you're saying "Give me an HTTP client" instead of "Give me an HTTP client suitable for communicating with fooApi".
In other words, you have multiple HTTP clients all named httpClient, which does not allow you to make any distinction between different instances. It's kind of like taking an #Autowired HttpClient without some way to qualify the reference (in Spring's case, usually by bean ID with external wiring).
In the cake pattern, one way to resolve this is to qualify that distinction with a different name: FooApiModule requires e.g. a def http10HttpClient: HttpClient and BarApiModule requires def connectionPooledHttpClient: HttpClient. When "filling in" the different modules, the different names both reference two different instances but are also indicative of the constraints the two modules place on their dependencies.
An alternative (workable albeit not as clean in my opinion) is to simply require a module-specific named dependency, i.e. def fooHttpClient: HttpClient, which simply forces an explicit external wiring on whomever mixes your module in.
Instead of extending FooApiModule and BarApiModule in a single place -- which would mean they share dependencies -- make them both separate objects, each with their dependencies solved accordingly.
Seems to be the known "robot legs" problem. You need to construct two legs of a robot, however you need to supply two different feet to them.
How to use the cake pattern to have both common dependencies and separate?
Let's have L1 <- A, B1; L2 <- A, B2. And you want to have Main <- L1, L2, A.
To have separate dependencies we need two instances of smaller cakes, parameterized with common dependencies.
trait LegCommon { def a:A}
trait Bdep { def b:B }
class L(val common:LegCommon) extends Bdep {
import common._
// declarations of Leg. Have both A and B.
}
trait B1module extends Bdep {
val b = new B1
}
trait B2module extends Bdep {
def b = new B2
}
In Main we'll have common part in cake and two legs:
trait Main extends LegCommon {
val l1 = new L(this) with B1module
val l2 = new L(this) with B2module
val a = new A
}
Your final app should look like this:
object MyApp {
val fooApi = new FooApiModule {
val httpClient = new DefaultHttpClient1()
}.fooApi
val barApi = new BarApiModule {
val httpClient = new DefaultHttpClient2()
}.barApi
...
def run() = {
val r1 = fooApi.foo("http://...")
val r2 = barApi.bar("http://...")
// ...
}
}
That should work. (Adapted from this blog post: http://www.cakesolutions.net/teamblogs/2011/12/19/cake-pattern-in-depth/)

Abstract fields for dependency injection

In Scala, is there there anything wrong with using the below method of dependency injection.
// Define an interface
trait FileStorage {
def readFile(filename:String):OutputStream
}
// And an implementation
class S3FileStorage extends FileStorage {
def readFile(filename:String):OutputStream = ???
}
// Define our service as a trait with abstract fields that need to be
// injected in order to construct. All implementation details go here.
trait FileHTTPServer {
val fileStorage:FileStorage
def fetchFile( session:Session, filename:String ) = ???
}
Now we wire things up
// Wire up a concrete file service that we actually use in code
// No implementation details should go here, we're simply wiring up a FileHttpServerl
// An entire project could be wired up this way in a central location if desired.
object S3FileHttpServer extends FileHTTPServer {
val fileStorage = new S3FileStorage
}
// We could also do this anonymously
val myHttpServer = new FileHttpServer {
val fileStorage = new S3FileStorage
}
// Or create a mocked version for testing
val mockedHttpServer = new FileHttpServer {
val fileStorage = mock[FileStorage]
}
Obviously the Cake pattern provides more flexibility (particularly around self-types), however for simpler use cases this has much less boilerplate, while still providing compile time checking and a clean unambiguous interface.
Yes, this is absolutely fine approach. And yes, sometimes you can use constructor injection, nothing wrong with that too. But with constructor injection you have to propagate your dependencies manually, while with cake pattern your dependencies are propagated automatically via self-type annotations. So for big projects constructor injection actually lead to more boilerplate than cake pattern, especially at the construction site (where you create all your objects and set up dependencies between them).
However, what you have presented is not full-fledged cake pattern. In real cake pattern there is an additional layer around business logic classes, so-called components, and you do not wire up logic classes directly but components instead.
trait FileStorageComponent {
def fileStorage: FileStorage
trait FileStorage {
def readFile(filename: String): OutputStream
}
}
trait S3FileStorageComponent extends FileStorageComponent {
val fileStorage = new S3FileStorage
class S3FileStorage extends FileStorage {
def readFile(filename: String): OutputStream = ???
}
}
trait FileHttpServerComponent {
self: FileStorageComponent =>
val fileHttpServer = new FileHttpServer
class FileHttpServer {
def fetchFile(session: Session, filename: String) = ???
}
}
// Wiring
object S3FileHttpServer extends FileHttpServerComponent with S3FileStorageComponent
// Anonymous
val server = new FileHttpServerComponent with S3FileStorageComponent
// Mocking
object TestFileHttpServer extends FileHttpServerComponent with FileStorageComponent {
val fileStorage = mock[FileStorage]
}
In this approach there are more boilerplate in traits definitions, but in return you have greater flexibility and very clear dependency management on the use place. For example, here is how program entry point in one of my projects looks like:
object Main
extends MainUI
with DefaultActorsManagerComponent
with DefaultPreferencesAccessComponent
with DefaultModelComponent
with DefaultMainWindowViewComponent
with DefaultMainWindowControllerComponent
with MainWindowReporterComponent
with DefaultClientActorComponent
with DefaultResponseParserActorComponent
with DefaultArchiverActorComponent
with DefaultMainWindowAccessActorComponent
with DefaultUrlParserComponent
with DefaultListenerActorComponent
with DefaultXmlPrettifierComponent
All main program components are in one place. Pretty neat IMO.

Using Reader Monad for Dependency Injection

I recently saw the talks Dead-Simple Dependency Injection and Dependency Injection Without the Gymnastics about DI with Monads and was impressed. I tried to apply it on a simple problem, but failed as soon as it got non-trivial. I really would like to see a running version of dependency injection where
a class that depends on more than one value that has to be injected
a class that depends on a class that depends on something to be injected
as in the following example
trait FlyBehaviour { def fly() }
trait QuackBehaviour { def quack() }
trait Animal { def makeSound() }
// needs two behaviours injected
class Duck(val flyBehaviour: FlyBehaviour, val quackBehaviour: QuackBehaviour) extends Animal
{
def quack() = quackBehaviour.quack()
def fly() = flyBehaviour.fly()
def makeSound() = quack()
}
// needs an Animal injected (e.g. a Duck)
class Zoo(val animal: Animal)
// Spring for example would be able to provide a Zoo instance
// assuming a Zoo in configured to get a Duck injected and
// a Duck is configured to get impl. of FlyBehaviour and QuackBehaviour injected
val zoo: Zoo = InjectionFramework.get("Zoo")
zoo.animal.makeSound()
It would be really helpful to see a sample implementation using the reader Monad since I just feel that I am missing a push in the right direction.
Thanks!
The "reader monad" is just Function1, so all you need to do is accept an argument containing all the things you need. For example:
trait Config {
def fly: FlyBehaviour
def quack: QuackBehaviour
}
type Env[A] = Config => A
Now if you want to construct a Duck based on this environment:
val a: Env[Animal] = c => new Duck(c.fly, c.quack)
And then constructing a Zoo based on that is easy:
val z: Env[Zoo] = a andThen (new Zoo(_))
Using Scalaz (or with a bit of work on your own) you can make use of some syntax niceties to "ask" for the config c:
val z: Env[Zoo] = for {
c <- ask
} yield new Zoo(Duck(c.fly, c.quack))

Question about Cake Pattern

Let there a few separate DAO classes OrderDAO, ProductDAO, and CustomerDAO that store/retrieve data in the database and share a single instance DataSource (the database connection factory).
In order to create a DataSource instance and plug it in DAOs we usually use Spring DI. Now I would like to do that in Scala without any DI framework.
I've read about the cake pattern, and it looks like I should do the following:
trait DatabaseContext { val dataSource:Datasource }
trait OrderDAO {this:DatabaseContext =>
... // use dataSource of DatabaseContext
}
trait ProductDAO {this:DatabaseContext =>
... // use dataSource of DatabaseContext
}
object DAOImpl extends OrderDAO with ProductDAO with DatabaseContext {
val dataSource = ... // init the data source
}
Do I understand the cake pattern correctly?
Can I implement these DAOs differently using the cake pattern ?
What does it provide that DI frameworks like Spring do not ?
How can I create separate OrderDAOImpl and ProductDAOImpl objects sharing the same DataSource instance instead of one big DAOImpl?
The advantages of the cake pattern are:
Unlike configuration-file-based DI solutions, matching contracts to
implementations is done at compile time, which reduces class-finding
and compatibility issues. However, many DI engines have an
alternative in-code configuration feature
No third-party libraries
are used. Self-type annotations which let you use the pattern are a
native language feature. No special syntax is used to retrieve the
implementation of the contract
Forgetting to specify an
implementation for a component needed by another component results in
a runtime error - just check this article
http://jonasboner.com/2008/10/06/real-world-scala-dependency-injection-di.html
and try not specifying one of the components or specifying a
trait instead of a concrete class in any of the cake pattern
examples or even forgetting to initialize a val corresponding to a component needed
However, to experience these advantages, you need to more strictly adhere to the architecture of the pattern - check the same article and note the wrapping traits that contain the actual contracts and implementations.
Your examples do not seem to be strictly the cake pattern. In your case you could've just used inheritance to create implementations for your traits and use separate classes for each DAO component. In the cake pattern the consuming code would be a component just like the DAO code, and the code assembling the dependencies together would stand alone from it.
To illustrate the cake pattern, you would have to add consuming classes (domain layer or UI layer) to your example. Or it the case your DAO components accessed each other's features you could illustrate the cake pattern on you DAO alone.
to make it short,
trait OrderDAOComponent {
val dao: OrderDAO
trait OrderDAO {
def create: Order
def delete(id: Int): Unit
//etc
}
}
trait OrderDAOComponentImpl extends OrderDAOComponent {
class OrderDAOJDBCImpl extends OrderDAO {
def create: Order = {/*JDBC-related code here*/}
def delete(id: Int) {/*JDBC-related code here*/}
//etc
}
}
//This one has a dependency
trait OrderWebUIComponentImpl {
this: OrderDAOComponent =>
class OrderWebUI {
def ajaxDelete(request:HttpRequest) = {
val id = request.params("id").toInt
try {
dao.delete(id)
200
}
catch {
case _ => 500
}
}
}
}
//This matches contracts to implementations
object ComponentRegistry extends
OrderDAOComponentImpl with
OrderWebUIComponentImpl
{
val dao = new OrderDAOJDBCImpl
val ui = new OrderWebUI
}
//from some front-end code
val status = ComponentRegistry.ui.ajaxDelete(request)
More on your example. I think it could be more like cake if:
trait DatabaseContext { val dataSource:Datasource }
trait OrderDAOComponent {this:DatabaseContext =>
trait OrderDAOImpl {
... // use dataSource of DatabaseContext
}
}
trait ProductDAOComponent {this:DatabaseContext =>
trait ProductDAOImpl {
... // use dataSource of DatabaseContext
}
}
object Registry extends OrderDAOComponent with ProductDAOComponent with DatabaseContextImpl {
val dataSource = new DatasourceImpl //if Datasource is a custom trait, otherwise wrapping needed
val orderDAO = new OrderDAOImpl
val productDAO = new ProductDAOImpl
}
//now you may use them separately
Registry.orderDAO.//
Maybe:
Statically checked at compile time.