Skip to content

Instantly share code, notes, and snippets.

@tlync
Created November 20, 2013 05:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tlync/7558243 to your computer and use it in GitHub Desktop.
Save tlync/7558243 to your computer and use it in GitHub Desktop.
Isolate domain models from transaction management
// dummy session classes for sample codes
final class AnormSession {
def anormMethod = {
println("anorm")
}
def start = {}
def commit = {}
}
final class SlickSession {
def slickMethod = {
println("slick")
}
def start = {}
def commit = {}
}
// domain layer
trait Entity
trait Repo
case class IoContext[T](session: T)
trait IoContextSupport[T] {
implicit def contextTo(context: IoContext[_]): T = {
context.session.asInstanceOf[T] // actually don't want to do this... this causes runtime casting error
}
}
case class User(id: Int, name: String) extends Entity
trait UserRepo extends Repo {
def find(id: Int)(implicit ctx: IoContext[_]): User
def store(name: String)(implicit ctx: IoContext[_]): User
}
// infra layer for persistence
class SlickUserRepo extends UserRepo with IoContextSupport[SlickSession] {
def find(id: Int)(implicit ctx: IoContext[_]): User = {
ctx.slickMethod
User(2, "slick")
}
def store(name: String)(implicit ctx: IoContext[_]): User = {
ctx.slickMethod
User(2, name)
}
}
class AnormUserRepo extends UserRepo with IoContextSupport[AnormSession]{
def find(id: Int)(implicit ctx: IoContext[_]): User = {
ctx.anormMethod
User(2, "anorm")
}
def store(name: String)(implicit ctx: IoContext[_]): User = {
ctx.anormMethod
User(2, name)
}
}
// app layer
object App {
def doSomethingWithSlick() = {
val session = new SlickSession
implicit val ctx = IoContext(session)
session.start
val repo = new SlickUserRepo
repo.store("slick")
repo.find(2)
session.commit
}
def doSomethingWithAnorm() = {
val session = new AnormSession
implicit val ctx = IoContext(session)
session.start
val repo = new AnormUserRepo
repo.store("anorm")
repo.find(2)
session.commit
}
def doSomethingButError() = {
case class InvalidSessionType()
val session = new InvalidSessionType
implicit val ctx = IoContext(session)
val repo = new SlickUserRepo
repo.store("slick")
repo.find(2)
}
}
@tlync
Copy link
Author

tlync commented Nov 20, 2013

  • ランタイムにキャストエラーが発生するのが微妙
  • 実質 Repository は IoContextSupport なしには利用できないインターフェースになっているので、Repository と IoContextSupport が分かれている(お作法になってしまっている)のが微妙

@tlync
Copy link
Author

tlync commented Nov 20, 2013

App layer で implicit とか駆使すれば cast error は防げるかも

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment