Skip to content

Instantly share code, notes, and snippets.

@privateblue
Last active December 28, 2015 18:39
Show Gist options
  • Save privateblue/7544244 to your computer and use it in GitHub Desktop.
Save privateblue/7544244 to your computer and use it in GitHub Desktop.
mixed style dependency injection pattern for repositories and services
// COMMON-BASE LIBRARY
// dependencies
trait ConnectionPoolProvider {
protected val connectionPool: ConnectionPool
}
trait ExternalStuff {
protected val stuff = "stuff"
}
// BUSINESS LOGIC LIBRARY (depends on COMMON-BASE)
// models and messages
case class Post(name: String)
case class Blog(name: String)
case class DoFancy
case class IsLame
// repositories
abstract class Repository(cp: ConnectionPool)
class PostRepository(cp: ConnectionPool) extends Repository(cp) {
def get = Post("hello")
def add = ???
}
class BlogRepository(cp: ConnectionPool) extends Repository(cp) {
def get = Blog("world")
def add = ???
}
// internal services
trait ServiceComponent {
abstract class Service
}
trait PostReadServiceComponent extends ServiceComponent {
self: ConnectionPoolProvider with ExternalStuff =>
protected val postReadService = new PostReadService
class PostReadService extends Service {
private val postRepository = new PostRepository(connectionPool)
private val blogRepository = new BlogRepository(connectionPool)
def get = postRepository.get
def foobar = (stuff, blogRepository.get.name)
}
}
trait PostWriteServiceComponent {
self: ConnectionPoolProvider with PostReadServiceComponent =>
protected val postWriteService = new PostWriteService
class PostWriteService extends Service {
private val postRepository = new PostRepository(connectionPool)
def add = postRepository.add
def doSomething = postReadService.get
}
}
// client facing api services
trait ApiService
trait FancyFeatureService extends ApiService
with ConnectionPoolProvider
with ExternalStuff
with PostReadServiceComponent
with PostWriteServiceComponent {
def doFancy = {
postWriteService.add
postReadService.foobar
}
}
trait LameFeatureService extends ApiService
with ConnectionPoolProvider
with ExternalStuff
with PostReadServiceComponent
with PostWriteServiceComponent {
def isLame = postWriteService.doSomething == postReadService.get
}
// COMMON-PLAY or COMMON-UTILS LIBRARY (depends on COMMON-BASE)
// environment specific implementation of dependencies
trait ProductionConnectionPoolProvider extends ConnectionPoolProvider {
val cp = ???
}
trait ProductionExternalStuff extends ExternalStuff {
override val stuff = "stuff in this environment"
}
// CLIENT APP (depends on BUSINESS LOGIC LIBRARY, COMMON-PLAY LIBRARY)
// api service instances
object FancyFeature extends FancyFeatureService
with ProductionConnectionPoolProvider
with ProductionExternalStuff
object LameFeature extends LameFeatureService
with ProductionConnectionPoolProvider
with ProductionExternalStuff
// akka interface
class MyActor extends Actor {
def receive = {
case DoFancy => FancyFeature.doFancy
case IsLame => sender ! LameFeature.isLame
}
}
// http interface
class MyController extends Controller {
def doFancy = FancyFeature.doFancy
def isLame = LameFeature.isLame
}
// TESTS
trait TestConnectionPoolProvider extends ConnectionPoolProvider {
val cp = ???
}
trait TestExternalStuff extends ExternalStuff {
override val stuff = "test stuff"
}
object TestFancyFeature extends FancyFeatureService
with TestConnectionPoolProvider
with TestExternalStuff
object TestLameFeature extends LameFeatureService
with TestConnectionPoolProvider
with TestExternalStuff
object MyTest {
def run = {
TestFancyFeature.doFancy
TestLameFeature.isLame
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment