I would like to use the Cake template to separate parts of some software system into components, to make it fully modular, as suggested in this article . In the simplest case, I would like to have some mock components, say Logging, Config, Database, Scripts, etc. .d., which potentially can use each other. The code may look like
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 } }
Here, the database and configuration components ( SomeConfig
and SomeDatabase
) are pluggable and can be changed to some other implementations if it is ever needed. Their implementations have access to the core
object, which contains both the database and the configuration, so the database can access the configuration, if necessary, and vice versa.
So, the question is, if any feature, such as SomeDatabase
, becomes large and does not fit into a single file, how to split it into separate classes while maintaining access to the core
object? To be more specific, let's say I need to move some code from the connect method to SomeDatabase
to another file:
// 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
are implementation details of how SomeDatabase works, so I obviously would not want to make this a dash and mix it with the application. Is there a way to provide access to the core
object for SomeClass
?
Some related links: