He estado leyendo sobre cómo hacer Inyección de Dependencia en scala a través del patrón de tarta . Creo que lo entiendo, pero debo haberme perdido algo, porque sigo sin verle el sentido. ¿Por qué es preferible declarar las dependencias a través de tipos propios en lugar de campos abstractos?
Teniendo en cuenta el ejemplo de Programación de Scala TwitterClientComponent
declara dependencias como esta utilizando el patrón de la tarta:
//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)
}
}
}
}
¿Cómo es esto mejor que declarar las dependencias como campos abstractos, como se indica a continuación?
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)
}
}
}
En el momento de la instanciación, que es cuando el DI ocurre realmente (según entiendo), me cuesta ver las ventajas de cake, especialmente si se tiene en cuenta el tecleo extra que hay que hacer para las declaraciones de cake (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
}
Ahora de nuevo con campos abstractos, ¡más o menos lo mismo!
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
}
Estoy seguro de que se me debe escapar algo sobre la superioridad de la tarta. Sin embargo, por el momento no puedo ver lo que ofrece sobre la declaración de dependencias de cualquier otra manera (constructor, campos abstractos).