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.
Related
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.
I am trying to create an abstraction for a SearchService using the Cake pattern. This is what I have currently:
trait SearchServiceComponent{
val searchService:SearchService
trait SearchService{
def searchForSomething(..):List[String]
def updateIndex(..):Boolean
}
}
Lets say I have a DbSearchServiceComponent and LuceneSearchServiceComponent as follows:
trait DbSearchServiceComponent extends SearchServiceComponent{
class DbSearchService extends SearchService{
//Initialize the db client
//Implement all the trait methods
}
}
Similarly...
trait LuceneSearchServiceComponent extends SearchServiceComponent{
class LuceneSearchService extends SearchService{
//Initialize the lucene client
//Implement all the trait methods
}
}
The issue I have with the above snippet is that
I have initialized instances of lucene client and the db client in the Service implementations.
Ideally I would want to "mix-in" a "Client" base type that can be either a Db client or a Lucene client but I am pretty confused as to how to inject a polymorphic client type here.
Can somebody point out how I may be able to refactor the code so that I can inject different versions of the client to my implementations of the SearchService trait?
Not sure if I interpret your question correctly, but that's how you could use the cake pattern for this:
trait SearchServiceComponent {
val searchService: SearchService
trait SearchService {
def searchForSomething(...): List[String]
def updateIndex(...): Boolean
}
}
trait DbSearchServiceComponent extends SearchServiceComponent {
override val searchService = new SearchService {
// Initialize client, implement methods
}
}
trait trait LuceneSearchServiceComponent extends SearchServiceComponent {
override val searchService = new SearchService {
// Initialize client, implement methods
}
}
and upon instantiation:
val myLucenceApp = new Whatever with LuceneSearchServiceComponent
val myDbApp = new Whatever with DbSearchServiceComponent
where Whatever would typically be something along the lines of
class Whatever { this: SearchServiceComponent =>
// ... use `searchService` and do lots of other things
}
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))
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.
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.