Created
November 20, 2013 05:32
-
-
Save tlync/7558243 to your computer and use it in GitHub Desktop.
Isolate domain models from transaction management
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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) | |
} | |
} |
Author
tlync
commented
Nov 20, 2013
- ランタイムにキャストエラーが発生するのが微妙
- 実質 Repository は IoContextSupport なしには利用できないインターフェースになっているので、Repository と IoContextSupport が分かれている(お作法になってしまっている)のが微妙
App layer で implicit とか駆使すれば cast error は防げるかも
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment