Peter
10/14/2021, 7:06 PMfun saveSession(session: Session): Either<Throwable, Unit>
fun getSession(id: SessionID): Either<Throwable, Session>
for a specific implementation (Redis vs Relational vs mock) with additional dependencies:
fun saveSession(connection: RedisConnection, session: Session): Either<Throwable, Unit>
fun getSession(connection: ResdisConnection, id: SessionID): Either<Throwable, Session>
this prevents grouping functions as an interface, even if using partial functions (i think)
or using an interface OO-style:
class RedisSessionManager(connection: RedisConnection): SessionManager {
fun saveSession(session: Session): Either<Throwable, Unit>
fun getSession(id: SessionID): Either<Throwable, Session>
}
side effects aside, no longer pure with the global external dependency
Reader monad perhaps? not sure one ever gets away from the external implementation specific dependency (eg: connection), what approaches have you taken?Nathan Bedell
10/14/2021, 7:26 PMinterface SessionCtx<Conn,SId
,Sess> {
fun getSession(connection: Conn, sessionId: SId): Either<Throwable, Sess>
}Peter
10/14/2021, 8:28 PMraulraja
10/14/2021, 8:49 PMfun interfaces
instances can also be constructed much easier and independently.pakoito
10/14/2021, 11:16 PMsoon
Peter
10/14/2021, 11:31 PMPeter
10/14/2021, 11:32 PMPeter
10/15/2021, 4:26 AMraulraja
10/15/2021, 1:08 PMraulraja
10/15/2021, 1:08 PMraulraja
10/15/2021, 1:08 PM* A service is a suspended function that returns either a Failure or a
* computed value of A
*/
fun interface Service<out A> {
suspend operator fun invoke(): Either<Failure, A>
}
raulraja
10/15/2021, 1:11 PMraulraja
10/15/2021, 1:13 PMSessionManager
may be but you can create its operation from Get, Set ad-hoc and simply write the concrete ones that match the shape of a Service
to work with the way you compose them.Peter
10/15/2021, 3:20 PMPeter
10/15/2021, 5:35 PMraulraja
10/15/2021, 6:43 PMnested design (service -> service -> service)
mean? Is there a benefit for this kind of architecture? it still looks like the abstraction in that shape is 3 suspend functions that execute one after another consuming the result of the previous.Peter
10/15/2021, 6:45 PMraulraja
10/15/2021, 6:57 PMRedisManager
depends on default impls of your functions which you can replace in testing simply creating a new instance with an altered get or set.
class RedisManager(
val connection: RedisConnection,
val save: (session: Session) -> Save<Unit> = connection::saveRedisSession,
val get: (session: SessionID) -> Get<Session> = connection::getRedisSession
)
raulraja
10/15/2021, 6:59 PMraulraja
10/15/2021, 7:01 PMPeter
10/15/2021, 11:00 PMBut not trying to demonstrate this is superior or anything like that
- absolutely! just trying learn about alternatives, great to be aware of various approaches to pick the best one for the situation at hand. this looks pretty good!Peter
10/15/2021, 11:00 PM