dependency injection in functional programming
TRANSCRIPT
![Page 1: Dependency Injection in Functional Programming](https://reader031.vdocument.in/reader031/viewer/2022030308/58ed368e1a28abd4108b466f/html5/thumbnails/1.jpg)
![Page 2: Dependency Injection in Functional Programming](https://reader031.vdocument.in/reader031/viewer/2022030308/58ed368e1a28abd4108b466f/html5/thumbnails/2.jpg)
![Page 3: Dependency Injection in Functional Programming](https://reader031.vdocument.in/reader031/viewer/2022030308/58ed368e1a28abd4108b466f/html5/thumbnails/3.jpg)
![Page 4: Dependency Injection in Functional Programming](https://reader031.vdocument.in/reader031/viewer/2022030308/58ed368e1a28abd4108b466f/html5/thumbnails/4.jpg)
![Page 5: Dependency Injection in Functional Programming](https://reader031.vdocument.in/reader031/viewer/2022030308/58ed368e1a28abd4108b466f/html5/thumbnails/5.jpg)
![Page 6: Dependency Injection in Functional Programming](https://reader031.vdocument.in/reader031/viewer/2022030308/58ed368e1a28abd4108b466f/html5/thumbnails/6.jpg)
![Page 7: Dependency Injection in Functional Programming](https://reader031.vdocument.in/reader031/viewer/2022030308/58ed368e1a28abd4108b466f/html5/thumbnails/7.jpg)
![Page 8: Dependency Injection in Functional Programming](https://reader031.vdocument.in/reader031/viewer/2022030308/58ed368e1a28abd4108b466f/html5/thumbnails/8.jpg)
Actually, I’m a Spy Turtle.
![Page 9: Dependency Injection in Functional Programming](https://reader031.vdocument.in/reader031/viewer/2022030308/58ed368e1a28abd4108b466f/html5/thumbnails/9.jpg)
Actually, I’m a Spy Turtle.
QW
I recommend Uncle Bob’s “The Little Mocker” post
![Page 10: Dependency Injection in Functional Programming](https://reader031.vdocument.in/reader031/viewer/2022030308/58ed368e1a28abd4108b466f/html5/thumbnails/10.jpg)
![Page 11: Dependency Injection in Functional Programming](https://reader031.vdocument.in/reader031/viewer/2022030308/58ed368e1a28abd4108b466f/html5/thumbnails/11.jpg)
![Page 12: Dependency Injection in Functional Programming](https://reader031.vdocument.in/reader031/viewer/2022030308/58ed368e1a28abd4108b466f/html5/thumbnails/12.jpg)
![Page 13: Dependency Injection in Functional Programming](https://reader031.vdocument.in/reader031/viewer/2022030308/58ed368e1a28abd4108b466f/html5/thumbnails/13.jpg)
![Page 14: Dependency Injection in Functional Programming](https://reader031.vdocument.in/reader031/viewer/2022030308/58ed368e1a28abd4108b466f/html5/thumbnails/14.jpg)
WS
![Page 15: Dependency Injection in Functional Programming](https://reader031.vdocument.in/reader031/viewer/2022030308/58ed368e1a28abd4108b466f/html5/thumbnails/15.jpg)
Validate client
Authenticate user
Issue access token
clientId, clientSecret
email, password
access token
Client
User
![Page 16: Dependency Injection in Functional Programming](https://reader031.vdocument.in/reader031/viewer/2022030308/58ed368e1a28abd4108b466f/html5/thumbnails/16.jpg)
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) }
![Page 17: Dependency Injection in Functional Programming](https://reader031.vdocument.in/reader031/viewer/2022030308/58ed368e1a28abd4108b466f/html5/thumbnails/17.jpg)
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) }
![Page 18: Dependency Injection in Functional Programming](https://reader031.vdocument.in/reader031/viewer/2022030308/58ed368e1a28abd4108b466f/html5/thumbnails/18.jpg)
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) }
![Page 19: Dependency Injection in Functional Programming](https://reader031.vdocument.in/reader031/viewer/2022030308/58ed368e1a28abd4108b466f/html5/thumbnails/19.jpg)
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
![Page 20: Dependency Injection in Functional Programming](https://reader031.vdocument.in/reader031/viewer/2022030308/58ed368e1a28abd4108b466f/html5/thumbnails/20.jpg)
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) }
![Page 21: Dependency Injection in Functional Programming](https://reader031.vdocument.in/reader031/viewer/2022030308/58ed368e1a28abd4108b466f/html5/thumbnails/21.jpg)
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)
![Page 22: Dependency Injection in Functional Programming](https://reader031.vdocument.in/reader031/viewer/2022030308/58ed368e1a28abd4108b466f/html5/thumbnails/22.jpg)
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)
![Page 23: Dependency Injection in Functional Programming](https://reader031.vdocument.in/reader031/viewer/2022030308/58ed368e1a28abd4108b466f/html5/thumbnails/23.jpg)
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)
![Page 24: Dependency Injection in Functional Programming](https://reader031.vdocument.in/reader031/viewer/2022030308/58ed368e1a28abd4108b466f/html5/thumbnails/24.jpg)
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)
![Page 25: Dependency Injection in Functional Programming](https://reader031.vdocument.in/reader031/viewer/2022030308/58ed368e1a28abd4108b466f/html5/thumbnails/25.jpg)
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
![Page 26: Dependency Injection in Functional Programming](https://reader031.vdocument.in/reader031/viewer/2022030308/58ed368e1a28abd4108b466f/html5/thumbnails/26.jpg)
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)
![Page 27: Dependency Injection in Functional Programming](https://reader031.vdocument.in/reader031/viewer/2022030308/58ed368e1a28abd4108b466f/html5/thumbnails/27.jpg)
"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)
}
![Page 28: Dependency Injection in Functional Programming](https://reader031.vdocument.in/reader031/viewer/2022030308/58ed368e1a28abd4108b466f/html5/thumbnails/28.jpg)
"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)
}
![Page 29: Dependency Injection in Functional Programming](https://reader031.vdocument.in/reader031/viewer/2022030308/58ed368e1a28abd4108b466f/html5/thumbnails/29.jpg)
"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)
}
![Page 30: Dependency Injection in Functional Programming](https://reader031.vdocument.in/reader031/viewer/2022030308/58ed368e1a28abd4108b466f/html5/thumbnails/30.jpg)
"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)
}
![Page 31: Dependency Injection in Functional Programming](https://reader031.vdocument.in/reader031/viewer/2022030308/58ed368e1a28abd4108b466f/html5/thumbnails/31.jpg)
"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)
}
![Page 32: Dependency Injection in Functional Programming](https://reader031.vdocument.in/reader031/viewer/2022030308/58ed368e1a28abd4108b466f/html5/thumbnails/32.jpg)
"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
![Page 33: Dependency Injection in Functional Programming](https://reader031.vdocument.in/reader031/viewer/2022030308/58ed368e1a28abd4108b466f/html5/thumbnails/33.jpg)
F
![Page 34: Dependency Injection in Functional Programming](https://reader031.vdocument.in/reader031/viewer/2022030308/58ed368e1a28abd4108b466f/html5/thumbnails/34.jpg)
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)
![Page 35: Dependency Injection in Functional Programming](https://reader031.vdocument.in/reader031/viewer/2022030308/58ed368e1a28abd4108b466f/html5/thumbnails/35.jpg)
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
![Page 36: Dependency Injection in Functional Programming](https://reader031.vdocument.in/reader031/viewer/2022030308/58ed368e1a28abd4108b466f/html5/thumbnails/36.jpg)
val jsonClient = JsonClient(host)
val clientService = new ClientService(jsonClient.getJson)
![Page 37: Dependency Injection in Functional Programming](https://reader031.vdocument.in/reader031/viewer/2022030308/58ed368e1a28abd4108b466f/html5/thumbnails/37.jpg)
val jsonClient = JsonClient(host)
val clientService = new ClientService(jsonClient.getJson)
![Page 38: Dependency Injection in Functional Programming](https://reader031.vdocument.in/reader031/viewer/2022030308/58ed368e1a28abd4108b466f/html5/thumbnails/38.jpg)
"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)}
![Page 39: Dependency Injection in Functional Programming](https://reader031.vdocument.in/reader031/viewer/2022030308/58ed368e1a28abd4108b466f/html5/thumbnails/39.jpg)
"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)}
![Page 40: Dependency Injection in Functional Programming](https://reader031.vdocument.in/reader031/viewer/2022030308/58ed368e1a28abd4108b466f/html5/thumbnails/40.jpg)
"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)}
![Page 41: Dependency Injection in Functional Programming](https://reader031.vdocument.in/reader031/viewer/2022030308/58ed368e1a28abd4108b466f/html5/thumbnails/41.jpg)
"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)}
![Page 42: Dependency Injection in Functional Programming](https://reader031.vdocument.in/reader031/viewer/2022030308/58ed368e1a28abd4108b466f/html5/thumbnails/42.jpg)
"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
![Page 43: Dependency Injection in Functional Programming](https://reader031.vdocument.in/reader031/viewer/2022030308/58ed368e1a28abd4108b466f/html5/thumbnails/43.jpg)
when(jsonClient.getJson(Path()/"clients"/"clientId")
.thenReturn(Future.value(jsonResponse))
:CA
![Page 44: Dependency Injection in Functional Programming](https://reader031.vdocument.in/reader031/viewer/2022030308/58ed368e1a28abd4108b466f/html5/thumbnails/44.jpg)
"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")}
![Page 45: Dependency Injection in Functional Programming](https://reader031.vdocument.in/reader031/viewer/2022030308/58ed368e1a28abd4108b466f/html5/thumbnails/45.jpg)
"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
![Page 46: Dependency Injection in Functional Programming](https://reader031.vdocument.in/reader031/viewer/2022030308/58ed368e1a28abd4108b466f/html5/thumbnails/46.jpg)
:MF
![Page 47: Dependency Injection in Functional Programming](https://reader031.vdocument.in/reader031/viewer/2022030308/58ed368e1a28abd4108b466f/html5/thumbnails/47.jpg)
–Martin Fowler
http://martinfowler.com/articles/mocksArentStubs.html#TheDifferenceBetweenMocksAndStubs
![Page 48: Dependency Injection in Functional Programming](https://reader031.vdocument.in/reader031/viewer/2022030308/58ed368e1a28abd4108b466f/html5/thumbnails/48.jpg)
~Martin Fowler
http://martinfowler.com/articles/mocksArentStubs.html#TheDifferenceBetweenMocksAndStubs
![Page 49: Dependency Injection in Functional Programming](https://reader031.vdocument.in/reader031/viewer/2022030308/58ed368e1a28abd4108b466f/html5/thumbnails/49.jpg)
~Martin Fowler
http://martinfowler.com/articles/mocksArentStubs.html#TheDifferenceBetweenMocksAndStubs
intermediate state
![Page 50: Dependency Injection in Functional Programming](https://reader031.vdocument.in/reader031/viewer/2022030308/58ed368e1a28abd4108b466f/html5/thumbnails/50.jpg)
~Martin Fowler
http://martinfowler.com/articles/mocksArentStubs.html#TheDifferenceBetweenMocksAndStubs
Side effects
![Page 51: Dependency Injection in Functional Programming](https://reader031.vdocument.in/reader031/viewer/2022030308/58ed368e1a28abd4108b466f/html5/thumbnails/51.jpg)
Yay! No more mock soup
FSB
![Page 52: Dependency Injection in Functional Programming](https://reader031.vdocument.in/reader031/viewer/2022030308/58ed368e1a28abd4108b466f/html5/thumbnails/52.jpg)
Validate client
Authenticate user
Issue access token
clientId, clientSecret
email, password
access token
Client
User
![Page 53: Dependency Injection in Functional Programming](https://reader031.vdocument.in/reader031/viewer/2022030308/58ed368e1a28abd4108b466f/html5/thumbnails/53.jpg)
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) }
![Page 54: Dependency Injection in Functional Programming](https://reader031.vdocument.in/reader031/viewer/2022030308/58ed368e1a28abd4108b466f/html5/thumbnails/54.jpg)
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) }
![Page 55: Dependency Injection in Functional Programming](https://reader031.vdocument.in/reader031/viewer/2022030308/58ed368e1a28abd4108b466f/html5/thumbnails/55.jpg)
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
![Page 56: Dependency Injection in Functional Programming](https://reader031.vdocument.in/reader031/viewer/2022030308/58ed368e1a28abd4108b466f/html5/thumbnails/56.jpg)
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) }}
![Page 57: Dependency Injection in Functional Programming](https://reader031.vdocument.in/reader031/viewer/2022030308/58ed368e1a28abd4108b466f/html5/thumbnails/57.jpg)
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) }}
![Page 58: Dependency Injection in Functional Programming](https://reader031.vdocument.in/reader031/viewer/2022030308/58ed368e1a28abd4108b466f/html5/thumbnails/58.jpg)
: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) }}
![Page 59: Dependency Injection in Functional Programming](https://reader031.vdocument.in/reader031/viewer/2022030308/58ed368e1a28abd4108b466f/html5/thumbnails/59.jpg)
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
![Page 60: Dependency Injection in Functional Programming](https://reader031.vdocument.in/reader031/viewer/2022030308/58ed368e1a28abd4108b466f/html5/thumbnails/60.jpg)
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) }
![Page 61: Dependency Injection in Functional Programming](https://reader031.vdocument.in/reader031/viewer/2022030308/58ed368e1a28abd4108b466f/html5/thumbnails/61.jpg)
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) }
![Page 62: Dependency Injection in Functional Programming](https://reader031.vdocument.in/reader031/viewer/2022030308/58ed368e1a28abd4108b466f/html5/thumbnails/62.jpg)
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
![Page 63: Dependency Injection in Functional Programming](https://reader031.vdocument.in/reader031/viewer/2022030308/58ed368e1a28abd4108b466f/html5/thumbnails/63.jpg)
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) }
![Page 64: Dependency Injection in Functional Programming](https://reader031.vdocument.in/reader031/viewer/2022030308/58ed368e1a28abd4108b466f/html5/thumbnails/64.jpg)
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
![Page 65: Dependency Injection in Functional Programming](https://reader031.vdocument.in/reader031/viewer/2022030308/58ed368e1a28abd4108b466f/html5/thumbnails/65.jpg)
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
![Page 66: Dependency Injection in Functional Programming](https://reader031.vdocument.in/reader031/viewer/2022030308/58ed368e1a28abd4108b466f/html5/thumbnails/66.jpg)
trait JsonClients { self: ConfigComponent =>
val clientsJsonClient = JsonClient(config.clientsHost) val tokensClient = JsonClient(config.tokensHost)}
![Page 67: Dependency Injection in Functional Programming](https://reader031.vdocument.in/reader031/viewer/2022030308/58ed368e1a28abd4108b466f/html5/thumbnails/67.jpg)
trait Repositories { self: ConfigComponent =>
val dbClient = MySqlClient(config.dbHost, config.dbName, ...) val passwordsRepo = new PasswordRepository(dbClient.prepare,
dbClient.execute)}
![Page 68: Dependency Injection in Functional Programming](https://reader031.vdocument.in/reader031/viewer/2022030308/58ed368e1a28abd4108b466f/html5/thumbnails/68.jpg)
trait Repositories { self: ConfigComponent =>
val dbClient = MySqlClient(config.dbHost, config.dbName, ...) val passwordRepo = new PasswordRepository(dbClient.prepare,
dbClient.execute)}
![Page 69: Dependency Injection in Functional Programming](https://reader031.vdocument.in/reader031/viewer/2022030308/58ed368e1a28abd4108b466f/html5/thumbnails/69.jpg)
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 )}
![Page 70: Dependency Injection in Functional Programming](https://reader031.vdocument.in/reader031/viewer/2022030308/58ed368e1a28abd4108b466f/html5/thumbnails/70.jpg)
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 )}
![Page 71: Dependency Injection in Functional Programming](https://reader031.vdocument.in/reader031/viewer/2022030308/58ed368e1a28abd4108b466f/html5/thumbnails/71.jpg)
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 )}
![Page 72: Dependency Injection in Functional Programming](https://reader031.vdocument.in/reader031/viewer/2022030308/58ed368e1a28abd4108b466f/html5/thumbnails/72.jpg)
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 )}
![Page 73: Dependency Injection in Functional Programming](https://reader031.vdocument.in/reader031/viewer/2022030308/58ed368e1a28abd4108b466f/html5/thumbnails/73.jpg)
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
![Page 74: Dependency Injection in Functional Programming](https://reader031.vdocument.in/reader031/viewer/2022030308/58ed368e1a28abd4108b466f/html5/thumbnails/74.jpg)
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
![Page 75: Dependency Injection in Functional Programming](https://reader031.vdocument.in/reader031/viewer/2022030308/58ed368e1a28abd4108b466f/html5/thumbnails/75.jpg)
H
![Page 76: Dependency Injection in Functional Programming](https://reader031.vdocument.in/reader031/viewer/2022030308/58ed368e1a28abd4108b466f/html5/thumbnails/76.jpg)
●●●●
E
![Page 77: Dependency Injection in Functional Programming](https://reader031.vdocument.in/reader031/viewer/2022030308/58ed368e1a28abd4108b466f/html5/thumbnails/77.jpg)
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)
![Page 79: Dependency Injection in Functional Programming](https://reader031.vdocument.in/reader031/viewer/2022030308/58ed368e1a28abd4108b466f/html5/thumbnails/79.jpg)
●
![Page 80: Dependency Injection in Functional Programming](https://reader031.vdocument.in/reader031/viewer/2022030308/58ed368e1a28abd4108b466f/html5/thumbnails/80.jpg)
TE
![Page 81: Dependency Injection in Functional Programming](https://reader031.vdocument.in/reader031/viewer/2022030308/58ed368e1a28abd4108b466f/html5/thumbnails/81.jpg)
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
![Page 82: Dependency Injection in Functional Programming](https://reader031.vdocument.in/reader031/viewer/2022030308/58ed368e1a28abd4108b466f/html5/thumbnails/82.jpg)
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!
![Page 83: Dependency Injection in Functional Programming](https://reader031.vdocument.in/reader031/viewer/2022030308/58ed368e1a28abd4108b466f/html5/thumbnails/83.jpg)
: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
![Page 84: Dependency Injection in Functional Programming](https://reader031.vdocument.in/reader031/viewer/2022030308/58ed368e1a28abd4108b466f/html5/thumbnails/84.jpg)
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
![Page 85: Dependency Injection in Functional Programming](https://reader031.vdocument.in/reader031/viewer/2022030308/58ed368e1a28abd4108b466f/html5/thumbnails/85.jpg)
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
![Page 86: Dependency Injection in Functional Programming](https://reader031.vdocument.in/reader031/viewer/2022030308/58ed368e1a28abd4108b466f/html5/thumbnails/86.jpg)
![Page 87: Dependency Injection in Functional Programming](https://reader031.vdocument.in/reader031/viewer/2022030308/58ed368e1a28abd4108b466f/html5/thumbnails/87.jpg)
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
![Page 88: Dependency Injection in Functional Programming](https://reader031.vdocument.in/reader031/viewer/2022030308/58ed368e1a28abd4108b466f/html5/thumbnails/88.jpg)
@ThoughtWorks, @SoundCloudDev
@chrisberkhout, @aaronmblevin, @bguthrie, @birgitta410,@davcamer, @rentalcustard
@theophani, @ellenkoenig, @harrydeanhudson
Questions @starkcoffee