Scala Cake Pattern: splitting large components into separate files

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:

+6
source share
1 answer

The simplest task would be to pass Core as a constructor parameter to SomeClass .

 // SomeDatabase.scala trait SomeDatabase extends AbstractDatabase { this: Core => def database = SomeDatabaseImplementation object SomeDatabaseImplementation extends AbstractDatabaseInterface { def connect = { val obj = new SomeClass(SomeDatabase.this) // pass it here } } } // SomeClass.scala in the same package class SomeClass(coreComp: Core) { // use it here coreComp.core.conf.test } 

Interestingly, I just wanted to pass CoreInterface or AbstractConfigInterface , but the fact that they are internal types really made the job difficult.

+2
source

Source: https://habr.com/ru/post/913743/


All Articles