SlideShare a Scribd company logo
Actually, I’m a
Spy Turtle.
Actually, I’m a
Spy Turtle.
QW
I recommend Uncle
Bob’s “The Little
Mocker” post
WS
Validate client
Authenticate user
Issue access token
clientId, clientSecret
email, password
access token
Client
User
class SignInService(clientService: ClientService,
authenticatorService: AuthentictorService,
accessTokenService: TokenService
) {
def signIn(clientId: String, clientSecret: String, email: String,
password: String): Future[AccessToken] = {
for {
client <- clientService.validateClient(clientId, clientSecret)
user <- authenticatorService.authenticateUser(email, password)
accessToken <- accessTokenService.createAccessToken(user.id,
client.id)
} yield (accessToken)
}
class SignInService(clientService: ClientService,
authenticatorService: AuthentictorService,
accessTokenService: TokenService
) {
def signIn(clientId: String, clientSecret: String, email: String,
password: String): Future[AccessToken] = {
for {
client <- clientService.validateClient(clientId, clientSecret)
user <- authenticatorService.authenticateUser(email, password)
accessToken <- accessTokenService.createAccessToken(user.id,
client.id)
} yield (accessToken)
}
class SignInService(clientService: ClientService,
authenticatorService: AuthentictorService,
accessTokenService: TokenService
) {
def signIn(clientId: String, clientSecret: String, email: String,
password: String): Future[AccessToken] = {
for {
client <- clientService.validateClient(clientId, clientSecret)
user <- authenticatorService.authenticateUser(email, password)
accessToken <- accessTokenService.createAccessToken(user.id,
client.id)
} yield (accessToken)
}
class SignInService(clientService: ClientService,
authenticatorService: AuthentictorService,
accessTokenService: TokenService
) {
def signIn(clientId: String, clientSecret: String, email: String,
password: String): Future[AccessToken] = {
for {
client <- clientService.validateClient(clientId, clientSecret)
user <- authenticatorService.authenticateUser(email, password)
accessToken <- accessTokenService.createAccessToken(user.id,
client.id)
} yield (accessToken)
}
T
class SignInService(clientService: ClientService,
authenticatorService: AuthentictorService,
accessTokenService: TokenService
) {
def signIn(clientId: String, clientSecret: String, email: String,
password: String): Future[AccessToken] = {
for {
client <- clientService.validateClient(clientId, clientSecret)
user <- authenticatorService.authenticateUser(email, password)
accessToken <- accessTokenService.createAccessToken(user.id,
client.id)
} yield (accessToken)
}
class ClientService(jsonClient: JsonClient) {
def validateClient(clientId: String, clientSecret: String):
Future[Client]={
jsonClient.getJson(
Path() / "clients" / clientId
).map {
case JsonResponse(OkStatus, json, _, _) => {
val id = (json  "id").as[Long]
val secret = (json  "secret").as[String]
if (secret != clientSecret) {
throw new Exception("Client doesn't match")
}
Client(id)
class ClientService(jsonClient: JsonClient) {
def validateClient(clientId: String, clientSecret: String):
Future[Client]={
jsonClient.getJson(
Path() / "clients" / clientId
).map {
case JsonResponse(OkStatus, json, _, _) => {
val id = (json  "id").as[Long]
val secret = (json  "secret").as[String]
if (secret != clientSecret) {
throw new Exception("Client doesn't match")
}
Client(id)
class ClientService(jsonClient: JsonClient) {
def validateClient(clientId: String, clientSecret: String):
Future[Client]={
jsonClient.getJson(
Path() / "clients" / clientId
).map {
case JsonResponse(OkStatus, json, _, _) => {
val id = (json  "id").as[Long]
val secret = (json  "secret").as[String]
if (secret != clientSecret) {
throw new Exception("Client doesn't match")
}
Client(id)
class ClientService(jsonClient: JsonClient) {
def validateClient(clientId: String, clientSecret: String):
Future[Client]={
jsonClient.getJson(
Path() / "clients" / clientId
).map {
case JsonResponse(OkStatus, json, _, _) => {
val id = (json  "id").as[Long]
val secret = (json  "secret").as[String]
if (secret != clientSecret) {
throw new Exception("Client doesn't match")
}
Client(id)
class ClientService(jsonClient: JsonClient) {
def validateClient(clientId: String, clientSecret: String):
Future[Client]={
jsonClient.getJson(
Path() / "clients" / clientId
).map {
case JsonResponse(OkStatus, json, _, _) => {
val id = (json  "id").as[Long]
val secret = (json  "secret").as[String]
if (secret != clientSecret) {
throw new Exception("Client doesn't match")
}
Client(id)
EL
class ClientService(jsonClient: JsonClient) {
def validateClient(clientId: String, clientSecret: String):
Future[Client]={
jsonClient.getJson(
Path() / "clients" / clientId
).map {
case JsonResponse(OkStatus, json, _, _) => {
val id = (json  "id").as[Long]
val secret = (json  "secret").as[String]
if (secret != clientSecret) {
throw new Exception("Client doesn't match")
}
Client(id)
"returns client if credentials match" in new Scope {
val jsonClient = mock[JsonClient]
val clientService = new ClientService(jsonClient)
val jsonResponse = JsonResponse(OkStatus, Json.fromString(...))
when(jsonClient.get(Path() / "clients" / "clientId")
.thenReturn(Future.value(jsonResponse))
clientService.validateClient("clientId", "secret")
==== Client(5)
}
"returns client if credentials match" in new Scope {
val jsonClient = mock[JsonClient]
val clientService = new ClientService(jsonClient)
val jsonResponse = JsonResponse(OkStatus,Json.fromString(...))
when(jsonClient.get(Path() / "clients" / "clientId")
.thenReturn(Future.value(jsonResponse))
clientService.validateClient("clientId", "secret")
==== Client(5)
}
"returns client if credentials match" in new Scope {
val jsonClient = mock[JsonClient]
val clientService = new ClientService(jsonClient)
val jsonResponse = JsonResponse(OkStatus, Json.fromString(...)
when(jsonClient.get(Path() / "clients" / "clientId")
.thenReturn(Future.value(jsonResponse))
clientService.validateClient("clientId", "secret")
==== Client(5)
}
"returns client if credentials match" in new Scope {
val jsonClient = mock[JsonClient]
val clientService = new ClientService(jsonClient)
val jsonResponse = JsonResponse(OkStatus,Json.fromString(...))
when(jsonClient.get(Path() / "clients" / "clientId")
.thenReturn(Future.value(jsonResponse))
clientService.validateClient("clientId", "secret")
==== Client(5)
}
"returns client if credentials match" in new Scope {
val jsonClient = mock[JsonClient]
val clientService = new ClientService(jsonClient)
val jsonResponse = JsonResponse(OkStatus,Json.fromString(...))
when(jsonClient.get(Path() / "clients" / "clientId")
.thenReturn(Future.value(jsonResponse))
clientService.validateClient("clientId", "secret")
==== Client(5)
}
"returns client if credentials match" in new Scope {
val jsonClient = mock[JsonClient]
val clientService = new ClientService(jsonClient)
val jsonResponse = JsonResponse(OkStatus,Json.fromString(...))
when(jsonClient.get(Path() / "clients" / "clientId")
.thenReturn(Future.value(jsonResponse))
clientService.validateClient("clientId", "secret")
==== Client(5)
}
B
F
class ClientService(jsonClient: JsonClient) {
def validateClient(clientId: String, clientSecret: String):
Future[Client]={
jsonClient.getJson(
Path() / "clients" / clientId
).map {
case JsonResponse(OkStatus, json, _, _) => {
val id = (json  "id").as[Long]
val secret = (json  "secret").as[String]
if (secret != clientSecret) {
throw new Exception("Client doesn't match")
}
Client(id)
class ClientService(getJson: (Path) => Future[JsonResponse]) {
def validateClient(clientId: String, clientSecret: String):
Future[Client]={
getJson(
Path() / "clients" / clientId
).map {
case JsonResponse(OkStatus, json, _, _) => {
val id = (json  "id").as[Long]
val secret = (json  "secret").as[String]
if (secret != clientSecret) {
throw new Exception("Client doesn't match")
}
Client(id)
:I
val jsonClient = JsonClient(host)
val clientService = new ClientService(jsonClient.getJson)
val jsonClient = JsonClient(host)
val clientService = new ClientService(jsonClient.getJson)
"returns client if credentials match" in new Scope {
val jsonResponse = JsonResponse(OkStatus, Json.fromString(...)
val clientService = new ClientService(_ => Future.value(jsonResponse))
clientService.validateClient("clientId", "secret") ==== Client(5)
}
"returns client if credentials match" in new Scope {
val jsonResponse = JsonResponse(OkStatus, Json.fromString(...)
val clientService = new ClientService(_ => Future.value(jsonResponse))
clientService.validateClient("clientId", "secret") ==== Client(5)
}
"returns client if credentials match" in new Scope {
val jsonResponse = JsonResponse(OkStatus, Json.fromString(...)
val clientService = new ClientService(_ => Future.value(jsonResponse))
clientService.validateClient("clientId", "secret") ==== Client(5)
}
"returns client if credentials match" in new Scope {
val jsonResponse = JsonResponse(OkStatus, Json.fromString(...)
val clientService = new ClientService(_ => Future.value(jsonResponse))
clientService.validateClient("clientId", "secret") ==== Client(5)
}
"returns client if credentials match" in new Scope {
val jsonResponse = JsonResponse(OkStatus, Json.fromString(...)
val clientService = new ClientService(_ => Future.value(jsonResponse))
clientService.validateClient("clientId", "secret") ==== Client(5)
}
!E
when(jsonClient.getJson(Path()/"clients"/"clientId")
.thenReturn(Future.value(jsonResponse))
:CA
"returns client if credentials match" in new Scope {
val jsonResponse = JsonResponse(OkStatus, Json.fromString(...)
var arg: Option[Path] = None
val getJson = (path:Path) => {
arg = Some(path)
Future.value(jsonResponse)
}
val clientService = new ClientService(getJson)
clientService.validateClient("clientId", "secret")) ==== Client(5)
arg ==== Some(Path() / "clients" / "clientId")
}
"returns client if credentials match" in new Scope {
val jsonResponse = JsonResponse(OkStatus, Json.fromString(...)
var arg: Option[Path] = None
val getJson = (path:Path) => {
arg = Some(path)
Future.value(jsonResponse)
}
val clientService = new ClientService(getJson)
clientService.validateClient("clientId", "secret")) ==== Client(5)
arg ==== Some(Path() / "clients" / "clientId")
}
:S
:MF
–Martin Fowler
http://martinfowler.com/articles/mocksArentStubs.html#TheDifferenceBetweenMocksAndStubs
~Martin Fowler
http://martinfowler.com/articles/mocksArentStubs.html#TheDifferenceBetweenMocksAndStubs
~Martin Fowler
http://martinfowler.com/articles/mocksArentStubs.html#TheDifferenceBetweenMocksAndStubs
intermediate state
~Martin Fowler
http://martinfowler.com/articles/mocksArentStubs.html#TheDifferenceBetweenMocksAndStubs
Side effects
Yay! No more
mock soup
FSB
Validate client
Authenticate user
Issue access token
clientId, clientSecret
email, password
access token
Client
User
class SignInService(
clientService: ClientService,
authenticatorService: AuthentictorService,
accessTokenService: TokenService
) {
def signIn(clientId: String, clientSecret: String, email: String,
password: String): Future[AccessToken] = {
for {
client <- clientService.validateClient(clientId, clientSecret)
user <- authenticatorService.authenticateUser(email, password)
accessToken <- accessTokenService.createAccessToken(user.id,
client.id)
} yield (accessToken)
}
class SignInService(
clientService: ClientService,
authenticatorService: AuthentictorService,
accessTokenService: TokenService
) {
def signIn(clientId: String, clientSecret: String, email: String,
password: String): Future[AccessToken] = {
for {
client <- clientService.validateClient(clientId, clientSecret)
user <- authenticatorService.authenticateUser(email, password)
accessToken <- accessTokenService.createAccessToken(user.id,
client.id)
} yield (accessToken)
}
class SignInService(
validateClient: (String, String) => Future[Client],
authenticateUser: (String, String) => Future[User],
createAccessToken: (Long, Long) => Future[AccessToken]
) {
def signIn(clientId: String, clientSecret: String, email: String,
password: String): Future[AccessToken] = {
for {
client <- validateClient(clientId, clientSecret)
user <- authenticateUser(email, password)
accessToken <- createAccessToken(user.id, client.id)
} yield (accessToken)
}
:FO
object SignIn {
def signIn(validateClient: (String, String) => Future[Client],
authenticateUser: (String, String) => Future[User],
createAccessToken: (Long, Long) => Future[AccessToken])
(clientId: String, clientSecret: String, email: String,
password: String): Future[AccessToken] = {
for {
client <- validateClient(clientId, clientSecret)
user <- authenticateUser(email, password)
accessToken <- createAccessToken(user.id, client.id)
} yield (accessToken)
}
}
object SignIn {
def signIn(validateClient: (String, String) => Future[Client],
authenticateUser: (String, String) => Future[User],
createAccessToken: (Long, Long) => Future[AccessToken])
(clientId: String, clientSecret: String, email: String,
password: String): Future[AccessToken] = {
for {
client <- validateClient(clientId, clientSecret)
user <- authenticateUser(email, password)
accessToken <- createAccessToken(user.id, client.id)
} yield (accessToken)
}
}
:C
object SignIn {
def signIn(validateClient: (String, String) => Future[Client],
authenticateUser: (String, String) => Future[User],
createAccessToken: (Long, Long) => Future[AccessToken])
(clientId: String, clientSecret: String, email: String,
password: String): Future[AccessToken] = {
for {
client <- validateClient(clientId, clientSecret)
user <- authenticateUser(email, password)
accessToken <- createAccessToken(user.id, client.id)
} yield (accessToken)
}
}
class SignInService(
validateClient: (String, String) => Future[Client],
authenticateUser: (String, String) => Future[User],
createAccessToken: (Long, Long) => Future[AccessToken]
) {
def signIn(clientId: String, clientSecret: String, email: String,
password: String): Future[AccessToken] = {
for {
client <- validateClient(clientId, clientSecret)
user <- authenticateUser(email, password)
accessToken <- createAccessToken(user.id, client.id)
} yield (accessToken)
}
:N
class SignInService(
validateClient: (String, String) => Future[Client],
authenticateUser: (String, String) => Future[User],
createAccessToken: (Long, Long) => Future[AccessToken]
) {
def signIn(clientId: String, clientSecret: String, email: String,
password: String): Future[AccessToken] = {
for {
client <- validateClient(clientId, clientSecret)
user <- authenticateUser(email, password)
accessToken <- createAccessToken(user.id, client.id)
} yield (accessToken)
}
class SignInService(
validateClient: (String, String) => Future[Client],
authenticateUser: (String, String) => Future[User],
createAccessToken: (Long, Long) => Future[AccessToken]
) {
def signIn(clientId: String, clientSecret: String, email: String,
password: String): Future[AccessToken] = {
for {
client <- validateClient(clientId, clientSecret)
user <- authenticateUser(email, password)
accessToken <- createAccessToken(user.id, client.id)
} yield (accessToken)
}
class SignInService(
validateClient: (String, String) => Future[Client],
authenticateUser: (String, String) => Future[User],
createAccessToken: (Long, Long) => Future[AccessToken]
) {
def signIn(clientId: String, clientSecret: String, email: String,
password: String): Future[AccessToken] = {
for {
client <- validateClient(clientId, clientSecret)
user <- authenticateUser(email, password)
accessToken <- createAccessToken(user.id, client.id)
} yield (accessToken)
}
:IJA
class SignInService(
validateClient: (String, String) => Future[Client],
authenticateUser: (String, String) => Future[User],
createAccessToken: (Long, Long) => Future[AccessToken]
) {
def signIn(clientId: String, clientSecret: String, email: String,
password: String): Future[AccessToken] = {
for {
client <- validateClient(clientId, clientSecret)
user <- authenticateUser(email, password)
accessToken <- createAccessToken(user.id, client.id)
} yield (accessToken)
}
class SignInService(
validateClient: (ClientId, ClientSecret) => Future[Client],
authenticateUser: (String, String) => Future[User],
createAccessToken: (Long, Long) => Future[AccessToken]
) {
def signIn(clientId: String, clientSecret: String, email: String,
password: String): Future[AccessToken] = {
for {
client <- validateClient(clientId, clientSecret)
user <- authenticateUser(email, password)
accessToken <- createAccessToken(user.id, client.id)
} yield (accessToken)
}
:W
object SignInApi extends FinagleBasedServer with AppConfigComponent{
val clientsJsonClient = JsonClient(host)
val tokensClient = JsonClient(host)
val dbClient = MySqlClient(dbconfig)
val passwordsRepo = new PasswordRepository(dbClient.prepare, dbClient.execute)
val clientService = new ClientService(clientsJsonClient.get)
val authenticatorService = new AuthentictorService(passwordsRepo.getPassword)
val tokenService = new TokenService(tokensClient.get)
val signInService = new SignInService(
clientService.validateClient,
authenticatorService.authenticateUser,
tokenService.createAccessToken
)
val signInHandler = new SignInHandler(signInService.signIn)
override def createRoutes(httpServer: HttpServer): Unit = {
httpServer.register("/sign-in", signInHandler)
}
}
MSEV
trait JsonClients {
self: ConfigComponent =>
val clientsJsonClient = JsonClient(config.clientsHost)
val tokensClient = JsonClient(config.tokensHost)
}
trait Repositories {
self: ConfigComponent =>
val dbClient = MySqlClient(config.dbHost, config.dbName, ...)
val passwordsRepo = new PasswordRepository(dbClient.prepare,
dbClient.execute)
}
trait Repositories {
self: ConfigComponent =>
val dbClient = MySqlClient(config.dbHost, config.dbName, ...)
val passwordRepo = new PasswordRepository(dbClient.prepare,
dbClient.execute)
}
trait Services extends JsonClients with Repositories {
self: ConfigComponent =>
val clientService = new ClientService(clientsJsonClient.get)
val authenticatorService = new AuthentictorService(passwordsRepo.getPassword
val tokenService = new TokenService(tokensClient.get)
val signInService = new SignInService(
clientService.validateClient,
authenticatorService.authenticateUser,
tokenService.createAccessToken
)
}
trait Services extends JsonClients with Repositories {
self: ConfigComponent =>
val clientService = new ClientService(clientsJsonClient.get)
val authenticatorService = new AuthentictorService(passwordsRepo.getPassword
val tokenService = new TokenService(tokensClient.get)
val signInService = new SignInService(
clientService.validateClient,
authenticatorService.authenticateUser,
tokenService.createAccessToken
)
}
trait Services extends JsonClients with Repositories {
self: ConfigComponent =>
val clientService = new ClientService(clientsJsonClient.get)
val authenticatorService = new AuthentictorService(passwordsRepo.getPassword
val tokenService = new TokenService(tokensClient.get)
val signInService = new SignInService(
clientService.validateClient,
authenticatorService.authenticateUser,
tokenService.createAccessToken
)
}
trait Services extends JsonClients with Repositories {
self: ConfigComponent =>
val clientService = new ClientService(clientsJsonClient.get)
val authenticatorService = new AuthentictorService(passwordsRepo.getPassword
val tokenService = new TokenService(tokensClient.get)
val signInService = new SignInService(
clientService.validateClient,
authenticatorService.authenticateUser,
tokenService.createAccessToken
)
}
object ExampleSignInApi extends FinagleBasedServer
with ConfigComponent
with Services{
val signInHandler = new SignInHandler(signInService.signIn)
override def createRoutes(httpServer: HttpServer): Unit = {
httpServer.register("/sign-in", signInHandler)
}
}
S
object ExampleSignInApi extends FinagleBasedServer
with ConfigComponent
with Services{
val signInHandler = new SignInHandler(signInService.signIn)
override def createRoutes(httpServer: HttpServer): Unit = {
httpServer.register("/sign-in", signInHandler)
}
}
S
H
●
●
●
●
E
def getUser(id: Int): Reader[DB,User]
= Reader( (db:DB) => User("duana") )
def getTracks(user: User): Reader[DB,Track]
= Reader( (db:DB) => Track(42))
val myProgram: Reader[DB,String] =
for {
user <- getUser(123)
track <- getTracks(user)
} yield track.toString
myProgram.perform(db)
●
●
●
●
TE
Manual DI Magic DI
● Requires discipline
● Static check
● No framework or fancy
language features to learn
● Boring
● Enforces consistency
● Runtime check?
● Problems can be hare-y
● Slick
U
Manual DI Magic DI (Framework)
● Requires discipline
● Static check
● No framework or fancy
language features to learn
● Boring
● Enforces consistency
● Runtime check?
● Problems can be hare-y
● Slick
Stop spreading
the news!
:L
Manual DI Magic DI (Framework)
● Requires discipline
● Static check
● No framework or fancy
language features to learn
● Boring
● Enforces consistency
● Runtime check?
● Problems can be hare-y
● Slick
Manual DI Magic DI (Framework)
● Requires discipline
● Static check
● No framework or fancy
language features to learn
● Boring
● Enforces consistency
● Runtime check?
● Problems can be hare-y
● Slick
Manual DI Magic DI (Framework)
● Requires discipline
● Static check
● No framework or fancy
language features to learn
● Boring
● Enforces consistency
● Runtime check?
● Problems can be hare-y
● Slick
:M
def makeTalk(
askChrisBerkhout: (Talk) => Better[Talk],
askAaronLevinAboutFP: (None) => Some[Idea],
askBrianGuthrieAboutClojure: (Idea) => Better[Idea]
)(ideas: Talk): Better[Talk]
makeTalk(..) was invoked by com.thoughtworks.Birgitta
@ThoughtWorks, @SoundCloudDev
@chrisberkhout, @aaronmblevin, @bguthrie, @birgitta410,
@davcamer, @rentalcustard
@theophani, @ellenkoenig, @harrydeanhudson
Questions @starkcoffee

More Related Content

Viewers also liked (7)

Actividad de aprendizaje gustavo
Actividad de aprendizaje gustavoActividad de aprendizaje gustavo
Actividad de aprendizaje gustavo
 
Resume_Rajini (1)
Resume_Rajini (1)Resume_Rajini (1)
Resume_Rajini (1)
 
Contratacion electronica y contratacion informatica
Contratacion electronica y contratacion informaticaContratacion electronica y contratacion informatica
Contratacion electronica y contratacion informatica
 
IOT
IOTIOT
IOT
 
Bab 6
Bab 6Bab 6
Bab 6
 
The matrix
The matrix The matrix
The matrix
 
sanny
sannysanny
sanny
 

Similar to Dependency Injection in Functional Programming

Websockets talk at Rubyconf Uruguay 2010
Websockets talk at Rubyconf Uruguay 2010Websockets talk at Rubyconf Uruguay 2010
Websockets talk at Rubyconf Uruguay 2010
Ismael Celis
 
AWS에서 자바스크립트 활용 - 서비스와 개발 도구 - AWS Summit Seoul 2017
AWS에서 자바스크립트 활용 - 서비스와 개발 도구 - AWS Summit Seoul 2017AWS에서 자바스크립트 활용 - 서비스와 개발 도구 - AWS Summit Seoul 2017
AWS에서 자바스크립트 활용 - 서비스와 개발 도구 - AWS Summit Seoul 2017
Amazon Web Services Korea
 

Similar to Dependency Injection in Functional Programming (15)

Use Kotlin scripts and Clova SDK to build your Clova extension
Use Kotlin scripts and Clova SDK to build your Clova extensionUse Kotlin scripts and Clova SDK to build your Clova extension
Use Kotlin scripts and Clova SDK to build your Clova extension
 
The Testing Games: Mocking, yay!
The Testing Games: Mocking, yay!The Testing Games: Mocking, yay!
The Testing Games: Mocking, yay!
 
Azure Key Vault Integration in Scala
Azure Key Vault Integration in ScalaAzure Key Vault Integration in Scala
Azure Key Vault Integration in Scala
 
Monolith to Reactive Microservices
Monolith to Reactive MicroservicesMonolith to Reactive Microservices
Monolith to Reactive Microservices
 
10 Lessons Learned from using Kafka in 1000 Scala microservices - Scalar Online
10 Lessons Learned from using Kafka in 1000 Scala microservices - Scalar Online10 Lessons Learned from using Kafka in 1000 Scala microservices - Scalar Online
10 Lessons Learned from using Kafka in 1000 Scala microservices - Scalar Online
 
The Ring programming language version 1.5.4 book - Part 44 of 185
The Ring programming language version 1.5.4 book - Part 44 of 185The Ring programming language version 1.5.4 book - Part 44 of 185
The Ring programming language version 1.5.4 book - Part 44 of 185
 
Leveraging Symfony2 Forms
Leveraging Symfony2 FormsLeveraging Symfony2 Forms
Leveraging Symfony2 Forms
 
つくってあそぼ Kotlin DSL 第2版
つくってあそぼ Kotlin DSL 第2版つくってあそぼ Kotlin DSL 第2版
つくってあそぼ Kotlin DSL 第2版
 
An Introduction to Faye
An Introduction to FayeAn Introduction to Faye
An Introduction to Faye
 
Kotlin coroutines
Kotlin coroutines Kotlin coroutines
Kotlin coroutines
 
Kotlin : Advanced Tricks - Ubiratan Soares
Kotlin : Advanced Tricks - Ubiratan SoaresKotlin : Advanced Tricks - Ubiratan Soares
Kotlin : Advanced Tricks - Ubiratan Soares
 
Websockets talk at Rubyconf Uruguay 2010
Websockets talk at Rubyconf Uruguay 2010Websockets talk at Rubyconf Uruguay 2010
Websockets talk at Rubyconf Uruguay 2010
 
[JCConf 2020] 用 Kotlin 跨入 Serverless 世代
[JCConf 2020] 用 Kotlin 跨入 Serverless 世代[JCConf 2020] 用 Kotlin 跨入 Serverless 世代
[JCConf 2020] 用 Kotlin 跨入 Serverless 世代
 
AWS에서 자바스크립트 활용 - 서비스와 개발 도구 - AWS Summit Seoul 2017
AWS에서 자바스크립트 활용 - 서비스와 개발 도구 - AWS Summit Seoul 2017AWS에서 자바스크립트 활용 - 서비스와 개발 도구 - AWS Summit Seoul 2017
AWS에서 자바스크립트 활용 - 서비스와 개발 도구 - AWS Summit Seoul 2017
 
Data in Motion: Streaming Static Data Efficiently
Data in Motion: Streaming Static Data EfficientlyData in Motion: Streaming Static Data Efficiently
Data in Motion: Streaming Static Data Efficiently
 

Recently uploaded

Recently uploaded (20)

Studiovity film pre-production and screenwriting software
Studiovity film pre-production and screenwriting softwareStudiovity film pre-production and screenwriting software
Studiovity film pre-production and screenwriting software
 
TROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERROR
TROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERRORTROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERROR
TROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERROR
 
Abortion ^Clinic ^%[+971588192166''] Abortion Pill Al Ain (?@?) Abortion Pill...
Abortion ^Clinic ^%[+971588192166''] Abortion Pill Al Ain (?@?) Abortion Pill...Abortion ^Clinic ^%[+971588192166''] Abortion Pill Al Ain (?@?) Abortion Pill...
Abortion ^Clinic ^%[+971588192166''] Abortion Pill Al Ain (?@?) Abortion Pill...
 
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital TransformationWSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
 
Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...
Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...
Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...
 
Crafting the Perfect Measurement Sheet with PLM Integration
Crafting the Perfect Measurement Sheet with PLM IntegrationCrafting the Perfect Measurement Sheet with PLM Integration
Crafting the Perfect Measurement Sheet with PLM Integration
 
Accelerate Enterprise Software Engineering with Platformless
Accelerate Enterprise Software Engineering with PlatformlessAccelerate Enterprise Software Engineering with Platformless
Accelerate Enterprise Software Engineering with Platformless
 
SOCRadar Research Team: Latest Activities of IntelBroker
SOCRadar Research Team: Latest Activities of IntelBrokerSOCRadar Research Team: Latest Activities of IntelBroker
SOCRadar Research Team: Latest Activities of IntelBroker
 
De mooiste recreatieve routes ontdekken met RouteYou en FME
De mooiste recreatieve routes ontdekken met RouteYou en FMEDe mooiste recreatieve routes ontdekken met RouteYou en FME
De mooiste recreatieve routes ontdekken met RouteYou en FME
 
Vitthal Shirke Microservices Resume Montevideo
Vitthal Shirke Microservices Resume MontevideoVitthal Shirke Microservices Resume Montevideo
Vitthal Shirke Microservices Resume Montevideo
 
Beyond Event Sourcing - Embracing CRUD for Wix Platform - Java.IL
Beyond Event Sourcing - Embracing CRUD for Wix Platform - Java.ILBeyond Event Sourcing - Embracing CRUD for Wix Platform - Java.IL
Beyond Event Sourcing - Embracing CRUD for Wix Platform - Java.IL
 
OpenFOAM solver for Helmholtz equation, helmholtzFoam / helmholtzBubbleFoam
OpenFOAM solver for Helmholtz equation, helmholtzFoam / helmholtzBubbleFoamOpenFOAM solver for Helmholtz equation, helmholtzFoam / helmholtzBubbleFoam
OpenFOAM solver for Helmholtz equation, helmholtzFoam / helmholtzBubbleFoam
 
iGaming Platform & Lottery Solutions by Skilrock
iGaming Platform & Lottery Solutions by SkilrockiGaming Platform & Lottery Solutions by Skilrock
iGaming Platform & Lottery Solutions by Skilrock
 
AI/ML Infra Meetup | Reducing Prefill for LLM Serving in RAG
AI/ML Infra Meetup | Reducing Prefill for LLM Serving in RAGAI/ML Infra Meetup | Reducing Prefill for LLM Serving in RAG
AI/ML Infra Meetup | Reducing Prefill for LLM Serving in RAG
 
top nidhi software solution freedownload
top nidhi software solution freedownloadtop nidhi software solution freedownload
top nidhi software solution freedownload
 
Into the Box 2024 - Keynote Day 2 Slides.pdf
Into the Box 2024 - Keynote Day 2 Slides.pdfInto the Box 2024 - Keynote Day 2 Slides.pdf
Into the Box 2024 - Keynote Day 2 Slides.pdf
 
Cyaniclab : Software Development Agency Portfolio.pdf
Cyaniclab : Software Development Agency Portfolio.pdfCyaniclab : Software Development Agency Portfolio.pdf
Cyaniclab : Software Development Agency Portfolio.pdf
 
A Python-based approach to data loading in TM1 - Using Airflow as an ETL for TM1
A Python-based approach to data loading in TM1 - Using Airflow as an ETL for TM1A Python-based approach to data loading in TM1 - Using Airflow as an ETL for TM1
A Python-based approach to data loading in TM1 - Using Airflow as an ETL for TM1
 
Breaking the Code : A Guide to WhatsApp Business API.pdf
Breaking the Code : A Guide to WhatsApp Business API.pdfBreaking the Code : A Guide to WhatsApp Business API.pdf
Breaking the Code : A Guide to WhatsApp Business API.pdf
 
Advanced Flow Concepts Every Developer Should Know
Advanced Flow Concepts Every Developer Should KnowAdvanced Flow Concepts Every Developer Should Know
Advanced Flow Concepts Every Developer Should Know
 

Dependency Injection in Functional Programming

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 9. Actually, I’m a Spy Turtle. QW I recommend Uncle Bob’s “The Little Mocker” post
  • 10.
  • 11.
  • 12.
  • 13.
  • 14. WS
  • 15. Validate client Authenticate user Issue access token clientId, clientSecret email, password access token Client User
  • 16. class SignInService(clientService: ClientService, authenticatorService: AuthentictorService, accessTokenService: TokenService ) { def signIn(clientId: String, clientSecret: String, email: String, password: String): Future[AccessToken] = { for { client <- clientService.validateClient(clientId, clientSecret) user <- authenticatorService.authenticateUser(email, password) accessToken <- accessTokenService.createAccessToken(user.id, client.id) } yield (accessToken) }
  • 17. class SignInService(clientService: ClientService, authenticatorService: AuthentictorService, accessTokenService: TokenService ) { def signIn(clientId: String, clientSecret: String, email: String, password: String): Future[AccessToken] = { for { client <- clientService.validateClient(clientId, clientSecret) user <- authenticatorService.authenticateUser(email, password) accessToken <- accessTokenService.createAccessToken(user.id, client.id) } yield (accessToken) }
  • 18. class SignInService(clientService: ClientService, authenticatorService: AuthentictorService, accessTokenService: TokenService ) { def signIn(clientId: String, clientSecret: String, email: String, password: String): Future[AccessToken] = { for { client <- clientService.validateClient(clientId, clientSecret) user <- authenticatorService.authenticateUser(email, password) accessToken <- accessTokenService.createAccessToken(user.id, client.id) } yield (accessToken) }
  • 19. class SignInService(clientService: ClientService, authenticatorService: AuthentictorService, accessTokenService: TokenService ) { def signIn(clientId: String, clientSecret: String, email: String, password: String): Future[AccessToken] = { for { client <- clientService.validateClient(clientId, clientSecret) user <- authenticatorService.authenticateUser(email, password) accessToken <- accessTokenService.createAccessToken(user.id, client.id) } yield (accessToken) } T
  • 20. class SignInService(clientService: ClientService, authenticatorService: AuthentictorService, accessTokenService: TokenService ) { def signIn(clientId: String, clientSecret: String, email: String, password: String): Future[AccessToken] = { for { client <- clientService.validateClient(clientId, clientSecret) user <- authenticatorService.authenticateUser(email, password) accessToken <- accessTokenService.createAccessToken(user.id, client.id) } yield (accessToken) }
  • 21. class ClientService(jsonClient: JsonClient) { def validateClient(clientId: String, clientSecret: String): Future[Client]={ jsonClient.getJson( Path() / "clients" / clientId ).map { case JsonResponse(OkStatus, json, _, _) => { val id = (json "id").as[Long] val secret = (json "secret").as[String] if (secret != clientSecret) { throw new Exception("Client doesn't match") } Client(id)
  • 22. class ClientService(jsonClient: JsonClient) { def validateClient(clientId: String, clientSecret: String): Future[Client]={ jsonClient.getJson( Path() / "clients" / clientId ).map { case JsonResponse(OkStatus, json, _, _) => { val id = (json "id").as[Long] val secret = (json "secret").as[String] if (secret != clientSecret) { throw new Exception("Client doesn't match") } Client(id)
  • 23. class ClientService(jsonClient: JsonClient) { def validateClient(clientId: String, clientSecret: String): Future[Client]={ jsonClient.getJson( Path() / "clients" / clientId ).map { case JsonResponse(OkStatus, json, _, _) => { val id = (json "id").as[Long] val secret = (json "secret").as[String] if (secret != clientSecret) { throw new Exception("Client doesn't match") } Client(id)
  • 24. class ClientService(jsonClient: JsonClient) { def validateClient(clientId: String, clientSecret: String): Future[Client]={ jsonClient.getJson( Path() / "clients" / clientId ).map { case JsonResponse(OkStatus, json, _, _) => { val id = (json "id").as[Long] val secret = (json "secret").as[String] if (secret != clientSecret) { throw new Exception("Client doesn't match") } Client(id)
  • 25. class ClientService(jsonClient: JsonClient) { def validateClient(clientId: String, clientSecret: String): Future[Client]={ jsonClient.getJson( Path() / "clients" / clientId ).map { case JsonResponse(OkStatus, json, _, _) => { val id = (json "id").as[Long] val secret = (json "secret").as[String] if (secret != clientSecret) { throw new Exception("Client doesn't match") } Client(id) EL
  • 26. class ClientService(jsonClient: JsonClient) { def validateClient(clientId: String, clientSecret: String): Future[Client]={ jsonClient.getJson( Path() / "clients" / clientId ).map { case JsonResponse(OkStatus, json, _, _) => { val id = (json "id").as[Long] val secret = (json "secret").as[String] if (secret != clientSecret) { throw new Exception("Client doesn't match") } Client(id)
  • 27. "returns client if credentials match" in new Scope { val jsonClient = mock[JsonClient] val clientService = new ClientService(jsonClient) val jsonResponse = JsonResponse(OkStatus, Json.fromString(...)) when(jsonClient.get(Path() / "clients" / "clientId") .thenReturn(Future.value(jsonResponse)) clientService.validateClient("clientId", "secret") ==== Client(5) }
  • 28. "returns client if credentials match" in new Scope { val jsonClient = mock[JsonClient] val clientService = new ClientService(jsonClient) val jsonResponse = JsonResponse(OkStatus,Json.fromString(...)) when(jsonClient.get(Path() / "clients" / "clientId") .thenReturn(Future.value(jsonResponse)) clientService.validateClient("clientId", "secret") ==== Client(5) }
  • 29. "returns client if credentials match" in new Scope { val jsonClient = mock[JsonClient] val clientService = new ClientService(jsonClient) val jsonResponse = JsonResponse(OkStatus, Json.fromString(...) when(jsonClient.get(Path() / "clients" / "clientId") .thenReturn(Future.value(jsonResponse)) clientService.validateClient("clientId", "secret") ==== Client(5) }
  • 30. "returns client if credentials match" in new Scope { val jsonClient = mock[JsonClient] val clientService = new ClientService(jsonClient) val jsonResponse = JsonResponse(OkStatus,Json.fromString(...)) when(jsonClient.get(Path() / "clients" / "clientId") .thenReturn(Future.value(jsonResponse)) clientService.validateClient("clientId", "secret") ==== Client(5) }
  • 31. "returns client if credentials match" in new Scope { val jsonClient = mock[JsonClient] val clientService = new ClientService(jsonClient) val jsonResponse = JsonResponse(OkStatus,Json.fromString(...)) when(jsonClient.get(Path() / "clients" / "clientId") .thenReturn(Future.value(jsonResponse)) clientService.validateClient("clientId", "secret") ==== Client(5) }
  • 32. "returns client if credentials match" in new Scope { val jsonClient = mock[JsonClient] val clientService = new ClientService(jsonClient) val jsonResponse = JsonResponse(OkStatus,Json.fromString(...)) when(jsonClient.get(Path() / "clients" / "clientId") .thenReturn(Future.value(jsonResponse)) clientService.validateClient("clientId", "secret") ==== Client(5) } B
  • 33. F
  • 34. class ClientService(jsonClient: JsonClient) { def validateClient(clientId: String, clientSecret: String): Future[Client]={ jsonClient.getJson( Path() / "clients" / clientId ).map { case JsonResponse(OkStatus, json, _, _) => { val id = (json "id").as[Long] val secret = (json "secret").as[String] if (secret != clientSecret) { throw new Exception("Client doesn't match") } Client(id)
  • 35. class ClientService(getJson: (Path) => Future[JsonResponse]) { def validateClient(clientId: String, clientSecret: String): Future[Client]={ getJson( Path() / "clients" / clientId ).map { case JsonResponse(OkStatus, json, _, _) => { val id = (json "id").as[Long] val secret = (json "secret").as[String] if (secret != clientSecret) { throw new Exception("Client doesn't match") } Client(id) :I
  • 36. val jsonClient = JsonClient(host) val clientService = new ClientService(jsonClient.getJson)
  • 37. val jsonClient = JsonClient(host) val clientService = new ClientService(jsonClient.getJson)
  • 38. "returns client if credentials match" in new Scope { val jsonResponse = JsonResponse(OkStatus, Json.fromString(...) val clientService = new ClientService(_ => Future.value(jsonResponse)) clientService.validateClient("clientId", "secret") ==== Client(5) }
  • 39. "returns client if credentials match" in new Scope { val jsonResponse = JsonResponse(OkStatus, Json.fromString(...) val clientService = new ClientService(_ => Future.value(jsonResponse)) clientService.validateClient("clientId", "secret") ==== Client(5) }
  • 40. "returns client if credentials match" in new Scope { val jsonResponse = JsonResponse(OkStatus, Json.fromString(...) val clientService = new ClientService(_ => Future.value(jsonResponse)) clientService.validateClient("clientId", "secret") ==== Client(5) }
  • 41. "returns client if credentials match" in new Scope { val jsonResponse = JsonResponse(OkStatus, Json.fromString(...) val clientService = new ClientService(_ => Future.value(jsonResponse)) clientService.validateClient("clientId", "secret") ==== Client(5) }
  • 42. "returns client if credentials match" in new Scope { val jsonResponse = JsonResponse(OkStatus, Json.fromString(...) val clientService = new ClientService(_ => Future.value(jsonResponse)) clientService.validateClient("clientId", "secret") ==== Client(5) } !E
  • 44. "returns client if credentials match" in new Scope { val jsonResponse = JsonResponse(OkStatus, Json.fromString(...) var arg: Option[Path] = None val getJson = (path:Path) => { arg = Some(path) Future.value(jsonResponse) } val clientService = new ClientService(getJson) clientService.validateClient("clientId", "secret")) ==== Client(5) arg ==== Some(Path() / "clients" / "clientId") }
  • 45. "returns client if credentials match" in new Scope { val jsonResponse = JsonResponse(OkStatus, Json.fromString(...) var arg: Option[Path] = None val getJson = (path:Path) => { arg = Some(path) Future.value(jsonResponse) } val clientService = new ClientService(getJson) clientService.validateClient("clientId", "secret")) ==== Client(5) arg ==== Some(Path() / "clients" / "clientId") } :S
  • 46. :MF
  • 51. Yay! No more mock soup FSB
  • 52. Validate client Authenticate user Issue access token clientId, clientSecret email, password access token Client User
  • 53. class SignInService( clientService: ClientService, authenticatorService: AuthentictorService, accessTokenService: TokenService ) { def signIn(clientId: String, clientSecret: String, email: String, password: String): Future[AccessToken] = { for { client <- clientService.validateClient(clientId, clientSecret) user <- authenticatorService.authenticateUser(email, password) accessToken <- accessTokenService.createAccessToken(user.id, client.id) } yield (accessToken) }
  • 54. class SignInService( clientService: ClientService, authenticatorService: AuthentictorService, accessTokenService: TokenService ) { def signIn(clientId: String, clientSecret: String, email: String, password: String): Future[AccessToken] = { for { client <- clientService.validateClient(clientId, clientSecret) user <- authenticatorService.authenticateUser(email, password) accessToken <- accessTokenService.createAccessToken(user.id, client.id) } yield (accessToken) }
  • 55. class SignInService( validateClient: (String, String) => Future[Client], authenticateUser: (String, String) => Future[User], createAccessToken: (Long, Long) => Future[AccessToken] ) { def signIn(clientId: String, clientSecret: String, email: String, password: String): Future[AccessToken] = { for { client <- validateClient(clientId, clientSecret) user <- authenticateUser(email, password) accessToken <- createAccessToken(user.id, client.id) } yield (accessToken) } :FO
  • 56. object SignIn { def signIn(validateClient: (String, String) => Future[Client], authenticateUser: (String, String) => Future[User], createAccessToken: (Long, Long) => Future[AccessToken]) (clientId: String, clientSecret: String, email: String, password: String): Future[AccessToken] = { for { client <- validateClient(clientId, clientSecret) user <- authenticateUser(email, password) accessToken <- createAccessToken(user.id, client.id) } yield (accessToken) } }
  • 57. object SignIn { def signIn(validateClient: (String, String) => Future[Client], authenticateUser: (String, String) => Future[User], createAccessToken: (Long, Long) => Future[AccessToken]) (clientId: String, clientSecret: String, email: String, password: String): Future[AccessToken] = { for { client <- validateClient(clientId, clientSecret) user <- authenticateUser(email, password) accessToken <- createAccessToken(user.id, client.id) } yield (accessToken) } }
  • 58. :C object SignIn { def signIn(validateClient: (String, String) => Future[Client], authenticateUser: (String, String) => Future[User], createAccessToken: (Long, Long) => Future[AccessToken]) (clientId: String, clientSecret: String, email: String, password: String): Future[AccessToken] = { for { client <- validateClient(clientId, clientSecret) user <- authenticateUser(email, password) accessToken <- createAccessToken(user.id, client.id) } yield (accessToken) } }
  • 59. class SignInService( validateClient: (String, String) => Future[Client], authenticateUser: (String, String) => Future[User], createAccessToken: (Long, Long) => Future[AccessToken] ) { def signIn(clientId: String, clientSecret: String, email: String, password: String): Future[AccessToken] = { for { client <- validateClient(clientId, clientSecret) user <- authenticateUser(email, password) accessToken <- createAccessToken(user.id, client.id) } yield (accessToken) } :N
  • 60. class SignInService( validateClient: (String, String) => Future[Client], authenticateUser: (String, String) => Future[User], createAccessToken: (Long, Long) => Future[AccessToken] ) { def signIn(clientId: String, clientSecret: String, email: String, password: String): Future[AccessToken] = { for { client <- validateClient(clientId, clientSecret) user <- authenticateUser(email, password) accessToken <- createAccessToken(user.id, client.id) } yield (accessToken) }
  • 61. class SignInService( validateClient: (String, String) => Future[Client], authenticateUser: (String, String) => Future[User], createAccessToken: (Long, Long) => Future[AccessToken] ) { def signIn(clientId: String, clientSecret: String, email: String, password: String): Future[AccessToken] = { for { client <- validateClient(clientId, clientSecret) user <- authenticateUser(email, password) accessToken <- createAccessToken(user.id, client.id) } yield (accessToken) }
  • 62. class SignInService( validateClient: (String, String) => Future[Client], authenticateUser: (String, String) => Future[User], createAccessToken: (Long, Long) => Future[AccessToken] ) { def signIn(clientId: String, clientSecret: String, email: String, password: String): Future[AccessToken] = { for { client <- validateClient(clientId, clientSecret) user <- authenticateUser(email, password) accessToken <- createAccessToken(user.id, client.id) } yield (accessToken) } :IJA
  • 63. class SignInService( validateClient: (String, String) => Future[Client], authenticateUser: (String, String) => Future[User], createAccessToken: (Long, Long) => Future[AccessToken] ) { def signIn(clientId: String, clientSecret: String, email: String, password: String): Future[AccessToken] = { for { client <- validateClient(clientId, clientSecret) user <- authenticateUser(email, password) accessToken <- createAccessToken(user.id, client.id) } yield (accessToken) }
  • 64. class SignInService( validateClient: (ClientId, ClientSecret) => Future[Client], authenticateUser: (String, String) => Future[User], createAccessToken: (Long, Long) => Future[AccessToken] ) { def signIn(clientId: String, clientSecret: String, email: String, password: String): Future[AccessToken] = { for { client <- validateClient(clientId, clientSecret) user <- authenticateUser(email, password) accessToken <- createAccessToken(user.id, client.id) } yield (accessToken) } :W
  • 65. object SignInApi extends FinagleBasedServer with AppConfigComponent{ val clientsJsonClient = JsonClient(host) val tokensClient = JsonClient(host) val dbClient = MySqlClient(dbconfig) val passwordsRepo = new PasswordRepository(dbClient.prepare, dbClient.execute) val clientService = new ClientService(clientsJsonClient.get) val authenticatorService = new AuthentictorService(passwordsRepo.getPassword) val tokenService = new TokenService(tokensClient.get) val signInService = new SignInService( clientService.validateClient, authenticatorService.authenticateUser, tokenService.createAccessToken ) val signInHandler = new SignInHandler(signInService.signIn) override def createRoutes(httpServer: HttpServer): Unit = { httpServer.register("/sign-in", signInHandler) } } MSEV
  • 66. trait JsonClients { self: ConfigComponent => val clientsJsonClient = JsonClient(config.clientsHost) val tokensClient = JsonClient(config.tokensHost) }
  • 67. trait Repositories { self: ConfigComponent => val dbClient = MySqlClient(config.dbHost, config.dbName, ...) val passwordsRepo = new PasswordRepository(dbClient.prepare, dbClient.execute) }
  • 68. trait Repositories { self: ConfigComponent => val dbClient = MySqlClient(config.dbHost, config.dbName, ...) val passwordRepo = new PasswordRepository(dbClient.prepare, dbClient.execute) }
  • 69. trait Services extends JsonClients with Repositories { self: ConfigComponent => val clientService = new ClientService(clientsJsonClient.get) val authenticatorService = new AuthentictorService(passwordsRepo.getPassword val tokenService = new TokenService(tokensClient.get) val signInService = new SignInService( clientService.validateClient, authenticatorService.authenticateUser, tokenService.createAccessToken ) }
  • 70. trait Services extends JsonClients with Repositories { self: ConfigComponent => val clientService = new ClientService(clientsJsonClient.get) val authenticatorService = new AuthentictorService(passwordsRepo.getPassword val tokenService = new TokenService(tokensClient.get) val signInService = new SignInService( clientService.validateClient, authenticatorService.authenticateUser, tokenService.createAccessToken ) }
  • 71. trait Services extends JsonClients with Repositories { self: ConfigComponent => val clientService = new ClientService(clientsJsonClient.get) val authenticatorService = new AuthentictorService(passwordsRepo.getPassword val tokenService = new TokenService(tokensClient.get) val signInService = new SignInService( clientService.validateClient, authenticatorService.authenticateUser, tokenService.createAccessToken ) }
  • 72. trait Services extends JsonClients with Repositories { self: ConfigComponent => val clientService = new ClientService(clientsJsonClient.get) val authenticatorService = new AuthentictorService(passwordsRepo.getPassword val tokenService = new TokenService(tokensClient.get) val signInService = new SignInService( clientService.validateClient, authenticatorService.authenticateUser, tokenService.createAccessToken ) }
  • 73. object ExampleSignInApi extends FinagleBasedServer with ConfigComponent with Services{ val signInHandler = new SignInHandler(signInService.signIn) override def createRoutes(httpServer: HttpServer): Unit = { httpServer.register("/sign-in", signInHandler) } } S
  • 74. object ExampleSignInApi extends FinagleBasedServer with ConfigComponent with Services{ val signInHandler = new SignInHandler(signInService.signIn) override def createRoutes(httpServer: HttpServer): Unit = { httpServer.register("/sign-in", signInHandler) } } S
  • 75. H
  • 77. def getUser(id: Int): Reader[DB,User] = Reader( (db:DB) => User("duana") ) def getTracks(user: User): Reader[DB,Track] = Reader( (db:DB) => Track(42)) val myProgram: Reader[DB,String] = for { user <- getUser(123) track <- getTracks(user) } yield track.toString myProgram.perform(db)
  • 79.
  • 80. TE
  • 81. Manual DI Magic DI ● Requires discipline ● Static check ● No framework or fancy language features to learn ● Boring ● Enforces consistency ● Runtime check? ● Problems can be hare-y ● Slick
  • 82. U Manual DI Magic DI (Framework) ● Requires discipline ● Static check ● No framework or fancy language features to learn ● Boring ● Enforces consistency ● Runtime check? ● Problems can be hare-y ● Slick Stop spreading the news!
  • 83. :L Manual DI Magic DI (Framework) ● Requires discipline ● Static check ● No framework or fancy language features to learn ● Boring ● Enforces consistency ● Runtime check? ● Problems can be hare-y ● Slick
  • 84. Manual DI Magic DI (Framework) ● Requires discipline ● Static check ● No framework or fancy language features to learn ● Boring ● Enforces consistency ● Runtime check? ● Problems can be hare-y ● Slick
  • 85. Manual DI Magic DI (Framework) ● Requires discipline ● Static check ● No framework or fancy language features to learn ● Boring ● Enforces consistency ● Runtime check? ● Problems can be hare-y ● Slick :M
  • 86.
  • 87. def makeTalk( askChrisBerkhout: (Talk) => Better[Talk], askAaronLevinAboutFP: (None) => Some[Idea], askBrianGuthrieAboutClojure: (Idea) => Better[Idea] )(ideas: Talk): Better[Talk] makeTalk(..) was invoked by com.thoughtworks.Birgitta
  • 88. @ThoughtWorks, @SoundCloudDev @chrisberkhout, @aaronmblevin, @bguthrie, @birgitta410, @davcamer, @rentalcustard @theophani, @ellenkoenig, @harrydeanhudson Questions @starkcoffee