3

The Cake Pattern article suggests using traits as namespaces:

trait UserRepositoryComponent {  
  val userRepository: UserRepository  
  class UserRepository {...}
}

trait UserServiceComponent {this: UserRepositoryComponent =>   
  val userService: UserService    
  class UserService {...}  
}

class Context extends UserServiceComponent with UserRepositoryComponent {  
  val userRepository = new UserRepository  
  val userService = new UserService  
} 

However do we really need these "namespace traits" (UserServiceComponent and UserRepositoryComponent) if we can do the following ?

trait UserRepository {...}

trait UserService {this: UserRepository => 
  ...
}

class Context extends UserRepositoryImpl with UserService

So, my question is when and why we need the "namespace" trait in the Cake Pattern.

Michael
  • 10,185
  • 12
  • 59
  • 110
  • 1
    A while ago, I've also answered your question on DAOs at `ru_scala`, but, for some reason, it has been blocked by the moderator... Here's the gist with the code for that answer: https://gist.github.com/933872. Explanations below are valid both for the DAOs' question and the current one. – Vasil Remeniuk May 05 '11 at 13:21
  • @Vasil Thanks a lot. BTW, why do you use `self` instead of `this` in your "gist" example ? – Michael May 05 '11 at 13:46
  • 1
    Giving `this` an alias (traditionally, `self`) simplifies accessing `this` reference from inner-classes ~> http://stackoverflow.com/questions/4017357/difference-between-this-and-self-in-self-type-annotations – Vasil Remeniuk May 05 '11 at 13:53

2 Answers2

5

There're 2 drawbacks in your approach:

  1. Context gets too much responsibility, mixing up methods from UserRepository, UserService, etc.;
  2. In the first snippet, you can control the order of initialization, or delay it for some components - e.g., you can make userRepository a lazy val, which will significantly simplify testing, if you want to test userService only (and, thus, don't want to bootstrap the entire infrastructure);

Though I wouldn't recommend it, in the first case you can also change injecting entities at the runtime (using vars).

Vasil Remeniuk
  • 20,519
  • 6
  • 71
  • 81
2

As with any pattern, you need it when it makes your code cleaner/more readable/more maintainable/more testable.

In this case, you may well want to create an alternate context for testing purposes, substituting some or all of the components used in the "production" version - a task which is more easily achieved, and more self-documenting, if done via the pattern as outlined in the article.

As Vasil pointed out, the separation of concerns here is a Good Thing(tm), and is pretty much the entire point of the cake pattern.

Kevin Wright
  • 49,540
  • 9
  • 105
  • 155