Skip to content

Instantly share code, notes, and snippets.

@privateblue
Last active December 18, 2015 15:49
Show Gist options
  • Save privateblue/5806836 to your computer and use it in GitHub Desktop.
Save privateblue/5806836 to your computer and use it in GitHub Desktop.
cake pattern based dependency injection pattern for repositories and services
// a dependency
trait Driver {
val message: String
}
trait ProductionDriver extends Driver {
val message = "production "
}
trait TestDriver extends Driver {
val message = "test "
}
// repositories
abstract class Repository {
self: Driver =>
}
class PostRepository extends Repository {
self: Driver =>
def hello = message + "post"
}
class BlogRepository extends Repository {
self: Driver =>
def hello = message + "blog"
def bar = message + "blog bar"
}
trait RepositoryContext {
val postRepository: PostRepository
val blogRepository: BlogRepository
}
trait ProductionRepositoryContext extends RepositoryContext {
val postRepository = new PostRepository with ProductionDriver
val blogRepository = new BlogRepository with ProductionDriver
}
trait TestRepositoryContext extends RepositoryContext {
val postRepository = new PostRepository with TestDriver
val blogRepository = new BlogRepository with TestDriver
}
// services
trait ServiceComponent {
self: RepositoryContext =>
abstract class Service
}
trait PostServiceComponent extends ServiceComponent {
self: RepositoryContext with SomeBehaviourServiceComponent with BlogServiceComponent =>
val postService: PostService
class PostService extends Service
with SomeBehaviourService {
def foo = postRepository.hello
def bar = blogRepository.bar
def baz = blogService.bar
}
}
// extra PostService behaviour factored out to separate trait
trait SomeBehaviourServiceComponent extends ServiceComponent {
self: PostServiceComponent with RepositoryContext =>
trait SomeBehaviourService {
self: PostService =>
def behave = postRepository.hello + " with a twist"
}
}
trait BlogServiceComponent {
self: RepositoryContext with PostServiceComponent =>
val blogService: BlogService
class BlogService extends Service {
def foo = blogRepository.hello
def bar = postService.bar
}
}
trait ServiceContext extends RepositoryContext
with SomeBehaviourServiceComponent
with PostServiceComponent
with BlogServiceComponent {
val postService = new PostService
val blogService = new BlogService
}
trait ProductionServiceContext extends ServiceContext
with ProductionRepositoryContext
trait TestServiceContext extends ServiceContext
with TestRepositoryContext {
// mocking PostService
override val postService = new PostService {
override def bar = "mock bar"
}
}
// client code (application)
trait Controller
object MyController extends Controller
with ProductionServiceContext {
def foo =
postService.foo + "\n" +
postService.bar + "\n" +
postService.baz + "\n" +
postService.behave + "\n" +
blogService.foo + "\n" +
blogService.bar
}
trait Test
object MyTest extends Test
with TestServiceContext {
def foo =
postService.foo + "\n" +
postService.bar + "\n" +
postService.baz + "\n" +
postService.behave + "\n" +
blogService.foo + "\n" +
blogService.bar
}
MyController.foo
MyTest.foo
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment