importance of cake pattern in scala
Asked Answered
N

3

6

I have started learning scala for a while now and now looking at cake pattern. I got the example from here

trait UserRepositoryComponent {
  def userLocator: UserLocator

  trait UserLocator {
    def findAll: List[User]
  }
}

trait UserRepositoryJPAComponent extends UserRepositoryComponent {
  val em: EntityManager

  def userLocator = new UserLocatorJPA(em)

  class UserLocatorJPA(val em: EntityManager) extends UserLocator {
    def findAll = {
      println("Executing a JPA query")
      List(new User, new User)
    }
  }
}

trait UserServiceComponent {
  def userService: UserService

  trait UserService {
    def findAll: List[User]
  }
}

trait DefaultUserServiceComponent extends UserServiceComponent {
  this: UserRepositoryComponent =>

  def userService = new DefaultUserService

  class DefaultUserService extends UserService {
    def findAll = userLocator.findAll
  }
}

To me it looks like too many boilerplate code to get the JPA repository injected to service.

However this code would do the same with much lesser number of lines

trait UserRepository {
  def findAll
}

trait JPAUserRepository extends UserRepository {
  val em: EntityManager
  def findAll = {
    em.createQuery
    println("find using JPA")
  }
}

trait MyService {
  def findAll
}

trait MyDefaultService extends MyService {
  this: UserRepository=>
}

Instantiating both scenarios.

val t1 = new DefaultUserServiceComponent with UserRepositoryJPAComponent {
  val em = new EntityManager()
}
t1.userService.findAll


val t2 = new MyDefaultService with JPAUserRepository {
  val em = new EntityManager
}

t2.findAll

Second scenario uses much less code, and uses DI. Can you help me understand what extra advantages cake pattern brings.

Neoteric answered 12/10, 2015 at 14:28 Comment(1)
As @Archeg says, your second example is also a variant of cake pattern.Doubleripper
F
2

As I understand it, there is no much difference. Actually cake pattern is IoC. It's just the idea of implementing IoC and DI, without separate DI framework, but just with scala code. You probably should prefer it over separate DI container unless you need more functionality.

Also it looks to me like both of your examples are cake patterns. At least that's how I understand it. But Martin didn't name it "cake pattern" in his book, and I base my knowledge of scala mosly on a single book, so I might be missing something. My understanding is that cake pattern is idea combining different traits to achieve DI

I think Martin specifically mentioned in his book, that it is alright to use DI-containers such as Spring in scala, but I unfortunately cannot find this place

Update

Found it: http://www.artima.com/pins1ed/modular-programming-using-objects.html See last subparagraph of 27.1 The problem. But as I said, he is not talking about "cakes" here, though the idea looks the same from the article you gave

Update 2

I've just reread my answer and understood that I need to improve it, as it does not fully answers the question.

You should prefer "cake pattern", because it is simpler. If you use Spring, you have to maintain configuration, whether it is XML or annotations, you may also have some requirements over your classes (I haven't used Spring, so I'm not sure whether there are any), and you have to bring whole Spring with you. With cake pattern you just write code as simple as it is (your second example is simple, you should agree). What's nice about scala is that you can do a lot of stuff with it, and use only a few frameworks - if you compare it to java, - you usually use many more external libraries

If you ever need more advanced functionality, like proxies - you may switch to Spring, or continue use Scala and solve your problems with the language itself, hopefully scala is extremely powerful and should cover even complicated cases.

The difference between two code pieces you provided is just abstraction: the first one has one more abstraction over operations defined in repository and service, and these are not part of the pattern. I do not feel like this is required, but author decided to show it like this.

Falange answered 12/10, 2015 at 16:25 Comment(0)
S
2

What the cake pattern gives you compared to an IoC type of code injection system is that at compile time you have an explicit dependency on the implementation you are going to use as opposed to a set up which involves runtime checks against a bunch of XML files or annotations. That is to say, the distinction is compile time vs runtime.

In testing, you can put in mock impls and just mix them in. In production, you can use the "real" impls and just mix those in. The compiler will tell you when you did something wrong.

(The reality is much more complex as you can get null pointer issues and various sorts of non-determinism if mixing and matching static objects.)

Summerly answered 12/10, 2015 at 15:32 Comment(6)
The IoC is not about XML in any way. Usually you can set up dependencies in the code in compile time, and I personally prefer it that way. It's still IoCFalange
@Falange My answer is colored by my experiences with Spring and other similar IoC solutions which involve large amounts of XML configuration files.Summerly
Isn't the second method also allows you to mix both mock / real implementations. Complier will flag errors if you try to mix in wrong types. Still do not see advantage Cake brings for all that extra code.Neoteric
@Summerly You don't have to use XML in Spring, you can use annotations : tutorialspoint.com/spring/spring_java_based_configuration.htm Lots of other languages support IoC often without annotations due to various reasons, so you can configure it in one place, but with the imperative code (like C#, Enterprise Library). I've never seen any benefits of XML for IoC in practice, but having strict typing is definitely a benefit.Falange
@SajithSilva I'm not a defender of Cake Pattern. I'm merely stating one of the reasons people like to use it. It's explicit.Summerly
Thanks for the replies. As you pointed out, both scenarios are different versions of cake. Now I have to read up on the Martins book to understand this more.Neoteric
F
2

As I understand it, there is no much difference. Actually cake pattern is IoC. It's just the idea of implementing IoC and DI, without separate DI framework, but just with scala code. You probably should prefer it over separate DI container unless you need more functionality.

Also it looks to me like both of your examples are cake patterns. At least that's how I understand it. But Martin didn't name it "cake pattern" in his book, and I base my knowledge of scala mosly on a single book, so I might be missing something. My understanding is that cake pattern is idea combining different traits to achieve DI

I think Martin specifically mentioned in his book, that it is alright to use DI-containers such as Spring in scala, but I unfortunately cannot find this place

Update

Found it: http://www.artima.com/pins1ed/modular-programming-using-objects.html See last subparagraph of 27.1 The problem. But as I said, he is not talking about "cakes" here, though the idea looks the same from the article you gave

Update 2

I've just reread my answer and understood that I need to improve it, as it does not fully answers the question.

You should prefer "cake pattern", because it is simpler. If you use Spring, you have to maintain configuration, whether it is XML or annotations, you may also have some requirements over your classes (I haven't used Spring, so I'm not sure whether there are any), and you have to bring whole Spring with you. With cake pattern you just write code as simple as it is (your second example is simple, you should agree). What's nice about scala is that you can do a lot of stuff with it, and use only a few frameworks - if you compare it to java, - you usually use many more external libraries

If you ever need more advanced functionality, like proxies - you may switch to Spring, or continue use Scala and solve your problems with the language itself, hopefully scala is extremely powerful and should cover even complicated cases.

The difference between two code pieces you provided is just abstraction: the first one has one more abstraction over operations defined in repository and service, and these are not part of the pattern. I do not feel like this is required, but author decided to show it like this.

Falange answered 12/10, 2015 at 16:25 Comment(0)
D
1

In the second example you just use JPAUserRepository's findAll implementation. But, basically, the problem of second approach in my opinion is that you expose api via business interface that shouldn't be exposed(aka UserRepositor api should't be exposed when using object of Service type t2)

Indeed cake pattern introduces a bit more code than you can write using some IoC framework. But you can also structure your code in slightly different way. For example, writing component trait not per some service, but per group of services that are logically related. As an example, all kind of Repository services may reside in RespositoryComponent and all kind of business services may reside in BusinessLogicComponent). To compare with spring, the idea is in that component implementaion trait is just the same XML decalration of beans.

To use spring like DI in scala I suggest you to look at MacWire

Dorinedorion answered 13/10, 2015 at 14:30 Comment(1)
Thanks I agree. I believe modules are the key. Its not just DI. Cake allows to create modules and modules can inherit each other. Self type annotations allows modules to associate. I'm reading up on modules an there are very interesting discussion over that.Neoteric

© 2022 - 2024 — McMap. All rights reserved.