Cake pattern and re-using "singleton" traits

248 views
Skip to first unread message

Colin Yates

unread,
Dec 20, 2012, 11:12:38 AM12/20/12
to scala...@googlegroups.com
TLDR; how can I integrate true singletons (like a datasource) in the Cake pattern when I have multiple "cake" assemblies?

Longer version:
Hi all,

First - I am a Scala newbie (although a very long in the tooth Enterprise Java developer familiar with Spring), and this is typed from memory so treat it as pseudo code rather than Scala ;).

I am using the cake pattern to assemble my components.  I don't want to have a single monolithic "env" comprised of every trait, rather I want assemblies for each component.  My question is how do I reuse truly singleton objects like a data source?

For example, let's say I have two services which both require a data source:

[code]
trait ServiceOneComponent {
  def serviceOne: ServiceOne

  class ServiceOne {
    def doSomething:String = { dataSource....}
  }
}

trait ServiceTwoComponent {
  def serviceTwo: ServiceTwo

  class ServiceTwo {
    def doSomething:String = { dataSource....}
  }
}
[/code]

now imagine that each service has an implementation which requires a singleton component which cannot be shared (i.e. the dataSource):

[code]
trait SomeImplementationOfServiceOneComponent {
  def dataSource:DataSource
  override def serviceOne:ServiceOne = new SomeImplementationOfServiceOne(dataSource)
  
  // eluded...
}
[/code]

and imagine SomeImplementationOfServiceTwoComponent needed exactly the same instance of the dataSource.

If I have:

[code]
trait Production 
 with SomeImplementationOfServiceOneComponent 
 with SomeImplementationOfServiceTwoComponent 
 with ProductionDataSource
[/code]

then my understanding is that a single instance of ProductionDataSource is created.  However, I have some complex graphs and I really want to do:

[code]
trait Production {
  // pretend the following is real code
  def serviceOne = (new {} SomeImplementationOfServiceOneComponent with ProductionDataSource).serviceOne
  def serviceTwo = (new {} SomeImplementationOfServiceTwoComponent with ProductionDataSource).serviceTwo
}
[/code]

My understanding is that this will cause two instances of ProductionDataSource to be created.

I hope my question is clear, although as ever with learning new things I expect I am asking a silly question from the wrong place, and if only I knew about Scala capability XYZ I would realise this question is moot :).

Any ideas - and thanks in advance for your gentle, patient treatment of a newbie!

Col

pil

unread,
Dec 20, 2012, 3:57:08 PM12/20/12
to scala...@googlegroups.com
To scratch similar itches, at some point, we've been doing something like "sub-cakes" initialized using the "environment-cake" as service provider.

Using your last snippet of code as a base, the idea could go like this (absolutely untested):

trait Production with ProductionDataSource {
  env =>
  def serviceOne = (new SomeImplementationOfServiceOneComponent with DelegatingDataSource { def dataSource = env.dataSource }).serviceOne
  def serviceTwo = (new SomeImplementationOfServiceTwoComponent with DelegatingDataSource { def dataSource = env.dataSource }).serviceTwo
}

Although in our case we built more complex "sub-cakes" with many components each, some of which services delegated to a "superior" service.

This is not too unfamiliar for those that have been exposed to Guice's "injector hierarchies" and similar approaches on other DI libs.

Colin Yates

unread,
Dec 21, 2012, 9:10:04 AM12/21/12
to scala...@googlegroups.com
Thanks Pil.

I don't understand where "env" comes from - it is provided by ProductionDataSource?

Pablo Lalloni

unread,
Dec 21, 2012, 9:17:18 AM12/21/12
to Colin Yates, scala...@googlegroups.com
"env" comes from the self reference annotation in "Production":

trait Production with ProductionDataSource {
  env =>

That annotation gives a new name ("env") in that scope to the self reference ("this") pointing to the "Production with ProductionDataSource" instance.



2012/12/21 Colin Yates <colin...@gmail.com>

Colin Yates

unread,
Dec 21, 2012, 9:56:29 AM12/21/12
to scala...@googlegroups.com, Colin Yates
Thanks for the clarification.
Reply all
Reply to author
Forward
0 new messages