Me gustaría utilizar el patrón Cake para dividir partes de algún sistema de software en componentes para hacerlo completamente modular como se propone en this article. En el caso más simple, me gustaría tener algunos componentes ficticios, digamos Logging, Config, Database, Scripts, etc., que potencialmente podrían usarse entre sí. El código podría ser comoScala Cake Pattern: división de componentes grandes en archivos separados
trait AbstractConfig {
def config: AbstractConfigInterface
trait AbstractConfigInterface {
def test: Unit
}
}
trait SomeConfig extends AbstractConfig {
this: Core =>
def config = SomeConfigImplementation
object SomeConfigImplementation extends AbstractConfigInterface {
def test = println("conf.test method called")
}
}
trait AbstractDatabase {
def database: AbstractDatabaseInterface
trait AbstractDatabaseInterface {
def connect: Unit
}
}
trait SomeDatabase extends AbstractDatabase {
this: Core =>
def database = SomeDatabaseImplementation
object SomeDatabaseImplementation extends AbstractDatabaseInterface {
def connect = {
println("connect method called")
core.conf.test
}
}
}
trait Core {
this: AbstractDatabase with AbstractConfig =>
def core = CoreInterface
object CoreInterface {
def db = database
def conf = config
}
}
object app extends Core with SomeDatabase with SomeConfig
object Run {
def main(args: Array[String]) = {
app.core.db.connect
}
}
Aquí las bases de datos y configuración de componentes (SomeConfig
SomeDatabase
y rasgos) son enchufable y se puede cambiar a algunas otras implementaciones si alguna vez es necesario. Sus implementaciones tienen acceso al objeto core
que contiene bases de datos y configuraciones, por lo que la base de datos puede acceder a la configuración si es necesario y viceversa.
Así que la pregunta es: ¿Alguna vez, algún rasgo como SomeDatabase
se vuelve grande y no cabe en un solo archivo cómo dividirlo en clases separadas conservando el acceso al objeto core
? Para ser más específico, digamos que necesito mover algo de código de método connect en SomeDatabase
a otro archivo:
// SomeDatabase.scala
trait SomeDatabase extends AbstractDatabase {
this: Core =>
def database = SomeDatabaseImplementation
object SomeDatabaseImplementation extends AbstractDatabaseInterface {
def connect = {
val obj = new SomeClass()
}
}
}
// SomeClass.scala in the same package
class SomeClass {
core.conf.test // Does not compile - how to make it work??
}
SomeClass
es detalles de implementación de cómo SomeDatabase obras, por lo que, obviamente, no les gustaría que sea una rasgo y mezclarlo en la aplicación. ¿Hay alguna manera de proporcionar acceso al objeto core
para SomeClass
?
Algunos enlaces relacionados:
- Dependency Injection vs Cake Pattern by Jan Machacek
- Real World Scala: Dependency Injection by Jonas Boner
- Dependency Injection in Scala: Extending the Cake Pattern by Adam Warsky
- Scalable Component Abstractions by Martin Odersky & Matthias Zenger
Dave, gracias por la respuesta. Hasta ahora, parece ser la única forma razonable. Lo único que no me interesa es la necesidad de escribir 'coreComp' en cada invocación de cualquier método central. Lamentablemente, no parece haber una opción para trabajar directamente con 'CoreInterface', ¿o sí? – nab
Puede 'importar coreComp._' para reducir el tipeo. – leedm777