decir que tengo dos dependencias en mi aplicación, una conexión a algún sistema secundario de pub y una conexión a una base de datos. Puedo hacer algo comopatrón de pastel de escama - ¿puedo tener varias capas de pastel?
trait DB {
def lookup(query:String):String
}
trait PubSub {
def subscribe(key:String, callback:String => Any)
}
entonces puedo escribir mi lógica como
trait Functionality { this:DB with PubSub =>
def doSomething() {
val key = lookup("get key")
subscribe(key, data => println(data))
}
}
y luego mi aplicación puede ser como
object Awesome extends App {
object repository extends Functionality with DB with PubSub {
def lookup(query:String) = "some key"
def subscribe(key:String, callback:String => Any) {
scala.concurrent.ops.spawn { while(true) { callback(key) ; Thread.Sleep(1000) } }
}
}
repository.doSomething()
}
y todo está bien y el bien en el mundo.
Pero, ¿qué ocurre si quiero conexiones a dos subsistemas de pub que comparten la misma implementación de base de datos en la misma aplicación?
quiero hacer algo como
object Awesome2 extends App {
object repository extends DB {
def lookup(query: String): String = "some other key"
object connection1 extends Functionality with PubSub with DB {
def subscribe(key: String, callback: (String) => Any) {
scala.concurrent.ops.spawn { while(true) { callback(key.toUpperCase) ; Thread.sleep(1000) } }
}
}
object connection2 extends Functionality with PubSub with DB {
def subscribe(key: String, callback: (String) => Any) {
scala.concurrent.ops.spawn { while(true) { callback(key.toLowerCase) ; Thread.sleep(1000) } }
}
}
}
}
donde los objetos en la segunda capa de pastel (implícitamente?) Sorber en la aplicación DB desde el nivel primario.
Pero el compilador Scala me dice
error: object creation impossible, since method lookup in trait DB of type (query:String) String is not defined
object connection2 extends Functionality with PubSub with DB {
si hacer lo siguiente entonces se hace lo que yo quiero
object Awesome3 extends App {
object repository extends DB {
override def lookup(query: String): String = "some other key"
object connection1 extends Functionality with PubSub with DB {
def subscribe(key: String, callback: (String) => Any) {
scala.concurrent.ops.spawn { while(true) { callback(key.toUpperCase) ; Thread.sleep(1000) } }
}
def lookup(query: String): String = repository.lookup(query)
}
object connection2 extends Functionality with PubSub with DB {
def subscribe(key: String, callback: (String) => Any) {
scala.concurrent.ops.spawn { while(true) { callback(key.toLowerCase) ; Thread.sleep(1000) } }
}
def lookup(query: String): String = repository.lookup(query)
}
}
repository.connection1.doSomething()
repository.connection2.doSomething()
}
pero esto es un poco desordenado
puedo añadir este rasgo
trait DB_Base extends DB {
private val db:DB = this
trait DB_Layer extends DB {
def lookup(query:String):String = db.lookup(query)
}
}
y luego los siguientes trabajos
object Awesome4 extends App {
object repository extends DB_Base {
override def lookup(query: String): String = "some other key"
object connection1 extends Functionality with PubSub with DB_Layer {
def subscribe(key: String, callback: (String) => Any) {
scala.concurrent.ops.spawn { while(true) { callback(key.toUpperCase) ; Thread.sleep(1000) } }
}
}
object connection2 extends Functionality with PubSub with DB_Layer {
def subscribe(key: String, callback: (String) => Any) {
scala.concurrent.ops.spawn { while(true) { callback(key.toLowerCase) ; Thread.sleep(1000) } }
}
}
}
repository.connection1.doSomething()
repository.connection2.doSomething()
}
así que ahora tengo dos capas. ¿Cómo consigo tres? Siento que estoy perdiendo la trama.
El pastel es alto en calorías y tiene una carga glucémica alta ... y ¿alguna vez has mirado la lista de ingredientes en un pastel en capas? Prefiera alimentos simples y naturales. Es decir, tenga un pastel de una sola capa como máximo y use un def para apuntar a los recursos que necesite que de otra manera necesitarían ser rellenos. (Esto es un comentario porque en realidad no es una solución a su problema, solo una sugerencia que va a ser difícil de manejar.) Dejar caer 'extiende DB_Base' y agregar' {dbbase => 'y soltar' con DB_Layer' y agregar 'def dbLayer = dbbase' o somesuch produce una alternativa explícita pero compacta. –
gracias rex. estoy confundido por tu comentario. primero, ¿qué hace '{dbbase =>' hacer exactamente? No estoy familiarizado con esa sintaxis. y segundo, ¿no se verá el resultado mucho como 'Awesome3'? – dvmlls
@RexKerr tiene razón, pero no veo cómo puede hacer rodar su propia Torta DI (como parece hacerlo OP) sin capas adicionales. Por ejemplo, supongamos que quieres hornear un pastel DAO. Necesitará gestionar la conexión de la base de datos (producción, etapa, prueba), el tipo de conexión (JNDI, JDBC) y el contrato DAO para implementar DAO. Como podemos ver con lo que presenta el OP, el patrón se vuelve complejo, provocando muchos arañazos en la cabeza ;-) Una vez más, no estoy seguro de cómo se puede hacer Torta DI en Scala sin bajar por el agujero – virtualeyes