SlideShare a Scribd company logo
1 of 119
From dependency injection
to dependency rejection
Mark Seemann
http://blog.ploeh.dk
@ploeh
@ploeh
Object-oriented Functional
@ploeh
Object-oriented Functional
Dependency injection Partial application
Composition
@ploeh
Dependency injection is “really just
a pretentious way to say ‘taking an
argument’”
- Rúnar Bjarnason (@runarorama)
@ploeh
Example
Restaurant Reservation
@ploeh
Restaurant Reservation
Make a reservation
Date
Name
Email
Quantity
Submit
@ploeh
Restaurant Reservation
Make a reservation
Date 2
Name
Email
Quantity
Submit
@ploeh
Restaurant Reservation
Make a reservation
Date 20
Name
Email
Quantity
Submit
@ploeh
Restaurant Reservation
Make a reservation
Date 201
Name
Email
Quantity
Submit
@ploeh
Restaurant Reservation
Make a reservation
Date 2016
Name
Email
Quantity
Submit
@ploeh
Restaurant Reservation
Make a reservation
Date 2016-
Name
Email
Quantity
Submit
@ploeh
Restaurant Reservation
Make a reservation
Date 2016-1
Name
Email
Quantity
Submit
@ploeh
Restaurant Reservation
Make a reservation
Date 2016-12
Name
Email
Quantity
Submit
@ploeh
Restaurant Reservation
Make a reservation
Date 2016-12-
Name
Email
Quantity
Submit
@ploeh
Restaurant Reservation
Make a reservation
Date 2016-12-2
Name
Email
Quantity
Submit
@ploeh
Restaurant Reservation
Make a reservation
Date 2016-12-29
Name
Email
Quantity
Submit
@ploeh
Restaurant Reservation
Make a reservation
Date 2016-12-29
Name M
Email
Quantity
Submit
@ploeh
Restaurant Reservation
Make a reservation
Date 2016-12-29
Name Ma
Email
Quantity
Submit
@ploeh
Restaurant Reservation
Make a reservation
Date 2016-12-29
Name Mar
Email
Quantity
Submit
@ploeh
Restaurant Reservation
Make a reservation
Date 2016-12-29
Name Mark
Email
Quantity
Submit
@ploeh
Restaurant Reservation
Make a reservation
Date 2016-12-29
Name Mark
Email
Quantity
Submit
@ploeh
Restaurant Reservation
Make a reservation
Date 2016-12-29
Name Mark S
Email
Quantity
Submit
@ploeh
Restaurant Reservation
Make a reservation
Date 2016-12-29
Name Mark Se
Email
Quantity
Submit
@ploeh
Restaurant Reservation
Make a reservation
Date 2016-12-29
Name Mark See
Email
Quantity
Submit
@ploeh
Restaurant Reservation
Make a reservation
Date 2016-12-29
Name Mark Seem
Email
Quantity
Submit
@ploeh
Restaurant Reservation
Make a reservation
Date 2016-12-29
Name Mark Seema
Email
Quantity
Submit
@ploeh
Restaurant Reservation
Make a reservation
Date 2016-12-29
Name Mark Seeman
Email
Quantity
Submit
@ploeh
Restaurant Reservation
Make a reservation
Date 2016-12-29
Name Mark Seemann
Email
Quantity
Submit
@ploeh
Restaurant Reservation
Make a reservation
Date 2016-12-29
Name Mark Seemann
Email ma
Quantity
Submit
@ploeh
Restaurant Reservation
Make a reservation
Date 2016-12-29
Name Mark Seemann
Email mar
Quantity
Submit
@ploeh
Restaurant Reservation
Make a reservation
Date 2016-12-29
Name Mark Seemann
Email mark
Quantity
Submit
@ploeh
Restaurant Reservation
Make a reservation
Date 2016-12-29
Name Mark Seemann
Email mark@
Quantity
Submit
@ploeh
Restaurant Reservation
Make a reservation
Date 2016-12-29
Name Mark Seemann
Email mark@p
Quantity
Submit
@ploeh
Restaurant Reservation
Make a reservation
Date 2016-12-29
Name Mark Seemann
Email mark@pl
Quantity
Submit
@ploeh
Restaurant Reservation
Make a reservation
Date 2016-12-29
Name Mark Seemann
Email mark@plo
Quantity
Submit
@ploeh
Restaurant Reservation
Make a reservation
Date 2016-12-29
Name Mark Seemann
Email mark@ploe
Quantity
Submit
@ploeh
Restaurant Reservation
Make a reservation
Date 2016-12-29
Name Mark Seemann
Email mark@ploeh
Quantity
Submit
@ploeh
Restaurant Reservation
Make a reservation
Date 2016-12-29
Name Mark Seemann
Email mark@ploeh.
Quantity
Submit
@ploeh
Restaurant Reservation
Make a reservation
Date 2016-12-29
Name Mark Seemann
Email mark@ploeh.d
Quantity
Submit
@ploeh
Restaurant Reservation
Make a reservation
Date 2016-12-29
Name Mark Seemann
Email mark@ploeh.dk
Quantity
Submit
@ploeh
Restaurant Reservation
POST JSON
@ploeh
Make a reservation
Date 2016-12-29
Name Mark Seemann
Email mark@ploeh.dk
Quantity 4
Submit
Restaurant Reservation
POST JSON
@ploeh
Make a reservation
Date 2016-12-29
Name Mark Seemann
Email mark@ploeh.dk
Quantity 4
Submit
Validate
Get reserved
seats from
DB
Decide
Save
reservation
Create
response
@ploeh
Object-oriented
Dependency injection
@ploeh
public class ReservationsController : ApiController
{
public ReservationsController(IValidator validator, IMapper mapper, IMaîtreD maîtreD)
{
this.validator = validator;
this.mapper = mapper;
this.maîtreD = maîtreD;
}
public IHttpActionResult Post(ReservationRequestDto dto)
{
var validationMsg = validator.Validate(dto);
if (validationMsg != "")
return this.BadRequest(validationMsg);
var r = mapper.Map(dto);
var id = maîtreD.TryAccept(r);
if (id == null)
return this.StatusCode(HttpStatusCode.Forbidden);
return this.Ok();
}
}
POST /reservations HTTP/1.1
{
"date": "2016-12-08",
"name": "Mark Seemann",
"email": "mark@ploeh.dk",
"quantity": 4
}
@ploeh
public class MaîtreD : IMaîtreD
{
public MaîtreD(int capacity, IReservationsRepository reservationsRepository)
{
this.capacity = capacity;
this.reservationsRepository = reservationsRepository;
}
public int? TryAccept(Reservation reservation)
{
var reservedSeats = reservationsRepository
.ReadReservations(reservation.Date)
.Sum(r => r.Quantity);
if (reservedSeats + reservation.Quantity <= capacity)
{
reservation.IsAccepted = true;
return reservationsRepository.Create(reservation);
}
return null;
}
}
@ploeh
public interface IMaîtreD
{
int? TryAccept(Reservation reservation);
}
How do I do
dependency
injection in
Scala?
You don’t,
because Scala
is a functional
language.
Comic courtesy of
@jrecursive and @hmemcpy @ploeh
Fine, it’s functional.
How do I inject
dependencies?
You use a Free Monad,
which allows you to
build a Monad from
any Functor.
Comic courtesy of
@jrecursive and @hmemcpy @ploeh
Did you just
tell me to go
fuck myself?
I believe I
did, Bob.
Comic courtesy of
@jrecursive and @hmemcpy @ploeh
Partial application
An attempt at dependency injection with a functional language
@ploeh
// int -> (DateTimeOffset -> Reservation list) -> (Reservation -> int) -> Reservation
// -> int option
let tryAccept capacity readReservations createReservation reservation =
let reservedSeats =
readReservations reservation.Date |> List.sumBy (fun x -> x.Quantity)
if reservedSeats + reservation.Quantity <= capacity
then createReservation { reservation with IsAccepted = true } |> Some
else None
@ploeh
Repository
// Reservation -> int option
let tryAcceptComposition reservation =
let read = DB.readReservations connectionString
@ploeh
string -> DateTimeOffset -> Reservation list
// Reservation -> int option
let tryAcceptComposition reservation =
let read = DB.readReservations connectionString
@ploeh
string -> DateTimeOffset -> Reservation list
connectionString
// Reservation -> int option
let tryAcceptComposition reservation =
let read = DB.readReservations connectionString
@ploeh
string -> DateTimeOffset -> Reservation listconnectionString
// Reservation -> int option
let tryAcceptComposition reservation =
let read = DB.readReservations connectionString
@ploeh
DateTimeOffset -> Reservation list
// Reservation -> int option
let tryAcceptComposition reservation =
let read = DB.readReservations connectionString
let create = DB.createReservation connectionString
tryAccept 10 read create reservation
@ploeh
Reservation -> int
// Reservation -> int option
let tryAcceptComposition reservation =
let read = DB.readReservations connectionString
let create = DB.createReservation connectionString
tryAccept 10 read create reservation
@ploeh
// Reservation -> int option
let tryAcceptComposition =
let read = DB.readReservations connectionString
let create = DB.createReservation connectionString
tryAccept 10 read create
@ploeh
// Reservation -> int option
let tryAcceptComposition =
let read = DB.readReservations connectionString
let create = DB.createReservation connectionString
tryAccept 10 read create
@ploeh
IL
@ploeh
internal class tryAcceptComposition@17 : FSharpFunc<Reservation, FSharpOption<int>>
{
public int capacity;
public FSharpFunc<Reservation, int> createReservation;
public FSharpFunc<DateTimeOffset, FSharpList<Reservation>> readReservations;
internal tryAcceptComposition@17(
int capacity,
FSharpFunc<DateTimeOffset, FSharpList<Reservation>> readReservations,
FSharpFunc<Reservation, int> createReservation)
{
this.capacity = capacity;
this.readReservations = readReservations;
this.createReservation = createReservation;
}
public override FSharpOption<int> Invoke(Reservation reservation)
{
return MaîtreD.tryAccept<int>(
this.capacity, this.readReservations, this.createReservation, reservation);
}
}
@ploeh
Is it Functional?
Partial
application
Dependency
injection
@ploeh
Same
return
value for
same input
No side-
effects
Pure
function
@ploeh
Pure
function
Impure
function
@ploeh
Sanity check
@ploeh
tryAccept :: Int -> (ZonedTime -> [Reservation]) -> (Reservation -> Int) -> Reservation
-> Maybe Int
tryAccept capacity readReservations createReservation reservation =
let reservedSeats = sum $ map quantity $ readReservations $ date reservation
in if reservedSeats + quantity reservation <= capacity
then Just $ createReservation $ reservation { isAccepted = True }
else Nothing
@ploeh
Pure
tryAcceptComposition :: Reservation -> IO (Maybe Int)
tryAcceptComposition reservation =
let read = DB.readReservations connectionString
create = DB.createReservation connectionString
in tryAccept 10 read create reservation
@ploeh
ZonedTime -> IO [Reservation]
Reservation -> IO Int
ZonedTime -> [Reservation] Reservation -> Int
Not Functional
Partial
application
Dependency
injection
@ploeh
@ploeh
Dependency injection
makes everything impure
@ploeh
Dependency Rejection
@ploeh
Unit
Dependencies
Indirect
input
Indirect
output
Direct
input
Direct
output
@ploeh
Unit
Dependencies
Indirect
input
Direct
input
Direct
output
@ploeh
// int -> (DateTimeOffset -> Reservation list) -> (Reservation -> int) -> Reservation
// -> int option
let tryAccept capacity readReservations createReservation reservation =
@ploeh
// int -> (DateTimeOffset -> Reservation list) -> Reservation
// -> Reservation option
let tryAccept capacity readReservations reservation =
@ploeh
// int -> (DateTimeOffset -> Reservation list) -> Reservation
// -> Reservation option
let tryAccept capacity readReservations reservation =
@ploeh
// int -> (DateTimeOffset -> Reservation list) -> Reservation -> Reservation option
let tryAccept capacity readReservations reservation =
@ploeh
// int -> (DateTimeOffset -> Reservation list) -> Reservation -> Reservation option
let tryAccept capacity readReservations reservation =
let reservedSeats =
readReservations reservation.Date |> List.sumBy (fun x -> x.Quantity)
if reservedSeats + reservation.Quantity <= capacity
then { reservation with IsAccepted = true } |> Some
else None
@ploeh
// Reservation -> int option
let tryAcceptComposition reservation =
match tryAccept 10 (DB.readReservations connectionString) reservation with
| None -> None
| Some r -> (DB.createReservation connectionString) r |> Some
@ploeh
// Reservation -> int option
let tryAcceptComposition reservation =
tryAccept 10 (DB.readReservations connectionString) reservation
|> Option.map (fun r -> DB.createReservation connectionString r)
@ploeh
// Reservation -> int option
let tryAcceptComposition reservation =
tryAccept 10 (DB.readReservations connectionString) reservation
|> Option.map ( DB.createReservation connectionString )
@ploeh
// Reservation -> int option
let tryAcceptComposition reservation =
tryAccept 10 (DB.readReservations connectionString) reservation
|> Option.map (DB.createReservation connectionString)
@ploeh
// Reservation -> int option
let tryAcceptComposition reservation =
reservation
|> tryAccept 10 (DB.readReservations connectionString)
|> Option.map (DB.createReservation connectionString)
@ploeh
Unit
Dependencies
Indirect
input
Direct
input
Direct
output
@ploeh
Unit
Dependencies
Direct
input
Direct
output
@ploeh
// int -> (DateTimeOffset -> Reservation list) -> Reservation -> Reservation option
let tryAccept capacity readReservations reservation =
@ploeh
// int -> ( Reservation list) -> Reservation -> Reservation option
let tryAccept capacity readReservations reservation =
@ploeh
// int -> Reservation list -> Reservation -> Reservation option
let tryAccept capacity readReservations reservation =
@ploeh
// int -> Reservation list -> Reservation -> Reservation option
let tryAccept capacity radReservations reservation =
@ploeh
// int -> Reservation list -> Reservation -> Reservation option
let tryAccept capacity rdReservations reservation =
@ploeh
// int -> Reservation list -> Reservation -> Reservation option
let tryAccept capacity rReservations reservation =
@ploeh
// int -> Reservation list -> Reservation -> Reservation option
let tryAccept capacity reservations reservation =
@ploeh
// int -> Reservation list -> Reservation -> Reservation option
let tryAccept capacity reservations reservation =
@ploeh
// int -> Reservation list -> Reservation -> Reservation option
let tryAccept capacity reservations reservation =
@ploeh
// int -> Reservation list -> Reservation -> Reservation option
let tryAccept capacity reservations reservation =
@ploeh
// int -> Reservation list -> Reservation -> Reservation option
let tryAccept capacity reservations reservation =
@ploeh
// int -> Reservation list -> Reservation -> Reservation option
let tryAccept capacity reservations reservation =
@ploeh
// int -> Reservation list -> Reservation -> Reservation option
let tryAccept capacity reservations reservation =
@ploeh
// int -> Reservation list -> Reservation -> Reservation option
let tryAccept capacity reservations reservation =
@ploeh
// int -> Reservation list -> Reservation -> Reservation option
let tryAccept capacity reservations reservation =
@ploeh
// int -> Reservation list -> Reservation -> Reservation option
let tryAccept capacity reservations reservation =
@ploeh
// int -> Reservation list -> Reservation -> Reservation option
let tryAccept capacity reservations reservation =
@ploeh
// int -> Reservation list -> Reservation -> Reservation option
let tryAccept capacity reservations reservation =
@ploeh
// int -> Reservation list -> Reservation -> Reservation option
let tryAccept capacity reservations reservation =
@ploeh
// int -> Reservation list -> Reservation -> Reservation option
let tryAccept capacity reservations reservation =
@ploeh
// int -> Reservation list -> Reservation -> Reservation option
let tryAccept capacity reservations reservation =
@ploeh
// int -> Reservation list -> Reservation -> Reservation option
let tryAccept capacity reservations reservation =
@ploeh
// int -> Reservation list -> Reservation -> Reservation option
let tryAccept capacity reservations reservation =
let reservedSeats =
reservations |> List.sumBy (fun x -> x.Quantity)
if reservedSeats + reservation.Quantity <= capacity
then { reservation with IsAccepted = true } |> Some
else None
@ploeh
// int -> Reservation list -> Reservation -> Reservation option
let tryAccept capacity reservations reservation =
let reservedSeats = reservations |> List.sumBy (fun x -> x.Quantity)
if reservedSeats + reservation.Quantity <= capacity
then { reservation with IsAccepted = true } |> Some
else None
@ploeh
// ('a -> 'b -> 'c) -> 'b -> 'a -> 'c
let flip f x y = f y x
// Reservation -> int option
let tryAcceptComposition reservation =
reservation.Date
|> DB.readReservations connectionString
|> fun reservations -> tryAccept 10 reservations reservation
|> Option.map (DB.createReservation connectionString)
@ploeh
// ('a -> 'b -> 'c) -> 'b -> 'a -> 'c
let flip f x y = f y x
// Reservation -> int option
let tryAcceptComposition reservation =
reservation.Date
|> DB.readReservations connectionString
|> fun reservations -> flip (tryAccept 10) reservation reservations
|> Option.map (DB.createReservation connectionString)
@ploeh
// ('a -> 'b -> 'c) -> 'b -> 'a -> 'c
let flip f x y = f y x
// Reservation -> int option
let tryAcceptComposition reservation =
reservation.Date
|> DB.readReservations connectionString
|> -> flip (tryAccept 10) reservation
|> Option.map (DB.createReservation connectionString)
@ploeh
// ('a -> 'b -> 'c) -> 'b -> 'a -> 'c
let flip f x y = f y x
// Reservation -> int option
let tryAcceptComposition reservation =
reservation.Date
|> DB.readReservations connectionString
|> flip (tryAccept 10) reservation
|> Option.map (DB.createReservation connectionString)
@ploeh
Sanity check
@ploeh
tryAccept :: Int -> [Reservation] -> Reservation -> Maybe Reservation
tryAccept capacity reservations reservation =
let reservedSeats = sum $ map quantity reservations
in if reservedSeats + quantity reservation <= capacity
then Just $ reservation { isAccepted = True }
else Nothing
@ploeh
tryAcceptComposition :: Reservation -> IO (Maybe Int)
tryAcceptComposition reservation = runMaybeT $
liftIO (DB.readReservations connectionString $ date reservation)
>>= MaybeT . return . flip (tryAccept 10) reservation
>>= liftIO . DB.createReservation connectionString
@ploeh
Object-oriented Functional
Dependency injection Partial application
Composition
@ploeh
Mark Seemann
http://blog.ploeh.dk
http://bit.ly/ploehralsight
@ploeh

More Related Content

More from NETFest

.NET Fest 2019. Halil Ibrahim Kalkan. Implementing Domain Driven Design
.NET Fest 2019. Halil Ibrahim Kalkan. Implementing Domain Driven Design.NET Fest 2019. Halil Ibrahim Kalkan. Implementing Domain Driven Design
.NET Fest 2019. Halil Ibrahim Kalkan. Implementing Domain Driven DesignNETFest
 
.NET Fest 2019. Сергій Бута. Feature Toggles: Dynamic Configuration at Wirex
.NET Fest 2019. Сергій Бута. Feature Toggles: Dynamic Configuration at Wirex.NET Fest 2019. Сергій Бута. Feature Toggles: Dynamic Configuration at Wirex
.NET Fest 2019. Сергій Бута. Feature Toggles: Dynamic Configuration at WirexNETFest
 
.NET Fest 2019. Michael Staib. Hot Chocolate: GraphQL Schema Stitching with A...
.NET Fest 2019. Michael Staib. Hot Chocolate: GraphQL Schema Stitching with A....NET Fest 2019. Michael Staib. Hot Chocolate: GraphQL Schema Stitching with A...
.NET Fest 2019. Michael Staib. Hot Chocolate: GraphQL Schema Stitching with A...NETFest
 
.NET Fest 2019. Андрей Литвинов. Async lifetime tests with xUnit and AutoFixture
.NET Fest 2019. Андрей Литвинов. Async lifetime tests with xUnit and AutoFixture.NET Fest 2019. Андрей Литвинов. Async lifetime tests with xUnit and AutoFixture
.NET Fest 2019. Андрей Литвинов. Async lifetime tests with xUnit and AutoFixtureNETFest
 
.NET Fest 2019. Анатолий Колесник. Love, Death & F# Tests
.NET Fest 2019. Анатолий Колесник. Love, Death & F# Tests.NET Fest 2019. Анатолий Колесник. Love, Death & F# Tests
.NET Fest 2019. Анатолий Колесник. Love, Death & F# TestsNETFest
 
.NET Fest 2019. Алексей Голуб. Монадные парсер-комбинаторы в C# (простой спос...
.NET Fest 2019. Алексей Голуб. Монадные парсер-комбинаторы в C# (простой спос....NET Fest 2019. Алексей Голуб. Монадные парсер-комбинаторы в C# (простой спос...
.NET Fest 2019. Алексей Голуб. Монадные парсер-комбинаторы в C# (простой спос...NETFest
 
.NET Fest 2019. Roberto Freato. Azure App Service deep dive
.NET Fest 2019. Roberto Freato. Azure App Service deep dive.NET Fest 2019. Roberto Freato. Azure App Service deep dive
.NET Fest 2019. Roberto Freato. Azure App Service deep diveNETFest
 
.NET Fest 2019. Леонид Молотиевский. DotNet Core in production
.NET Fest 2019. Леонид Молотиевский. DotNet Core in production.NET Fest 2019. Леонид Молотиевский. DotNet Core in production
.NET Fest 2019. Леонид Молотиевский. DotNet Core in productionNETFest
 
.NET Fest 2019. Александр Демчук. How to measure relationships within the Com...
.NET Fest 2019. Александр Демчук. How to measure relationships within the Com....NET Fest 2019. Александр Демчук. How to measure relationships within the Com...
.NET Fest 2019. Александр Демчук. How to measure relationships within the Com...NETFest
 
.NET Fest 2019. Anna Melashkina та Philipp Bauknecht. Dragons in a Mixed Real...
.NET Fest 2019. Anna Melashkina та Philipp Bauknecht. Dragons in a Mixed Real....NET Fest 2019. Anna Melashkina та Philipp Bauknecht. Dragons in a Mixed Real...
.NET Fest 2019. Anna Melashkina та Philipp Bauknecht. Dragons in a Mixed Real...NETFest
 
.NET Fest 2019. Alex Thissen. Architecting .NET solutions in a Docker ecosystem
.NET Fest 2019. Alex Thissen. Architecting .NET solutions in a Docker ecosystem.NET Fest 2019. Alex Thissen. Architecting .NET solutions in a Docker ecosystem
.NET Fest 2019. Alex Thissen. Architecting .NET solutions in a Docker ecosystemNETFest
 
.NET Fest 2019. Stas Lebedenko. Practical serverless use cases in Azure with ...
.NET Fest 2019. Stas Lebedenko. Practical serverless use cases in Azure with ....NET Fest 2019. Stas Lebedenko. Practical serverless use cases in Azure with ...
.NET Fest 2019. Stas Lebedenko. Practical serverless use cases in Azure with ...NETFest
 
.NET Fest 2019. Сергей Медведев. How serverless makes Integration TDD a reali...
.NET Fest 2019. Сергей Медведев. How serverless makes Integration TDD a reali....NET Fest 2019. Сергей Медведев. How serverless makes Integration TDD a reali...
.NET Fest 2019. Сергей Медведев. How serverless makes Integration TDD a reali...NETFest
 
.NET Fest 2019. Сергей Корж. Natural Language Processing in .NET
.NET Fest 2019. Сергей Корж. Natural Language Processing in .NET.NET Fest 2019. Сергей Корж. Natural Language Processing in .NET
.NET Fest 2019. Сергей Корж. Natural Language Processing in .NETNETFest
 
.NET Fest 2019. Eran Stiller. Create Your Own Serverless PKI with .NET & Azur...
.NET Fest 2019. Eran Stiller. Create Your Own Serverless PKI with .NET & Azur....NET Fest 2019. Eran Stiller. Create Your Own Serverless PKI with .NET & Azur...
.NET Fest 2019. Eran Stiller. Create Your Own Serverless PKI with .NET & Azur...NETFest
 
.NET Fest 2019. Eran Stiller. 6 Lessons I Learned on My Journey from Monolith...
.NET Fest 2019. Eran Stiller. 6 Lessons I Learned on My Journey from Monolith....NET Fest 2019. Eran Stiller. 6 Lessons I Learned on My Journey from Monolith...
.NET Fest 2019. Eran Stiller. 6 Lessons I Learned on My Journey from Monolith...NETFest
 
.NET Fest 2019. Kevin Dockx. Uncovering Swagger/OpenAPI
.NET Fest 2019. Kevin Dockx. Uncovering Swagger/OpenAPI.NET Fest 2019. Kevin Dockx. Uncovering Swagger/OpenAPI
.NET Fest 2019. Kevin Dockx. Uncovering Swagger/OpenAPINETFest
 
.NET Fest 2019. Kevin Dockx. OpenID Connect In Depth
.NET Fest 2019. Kevin Dockx. OpenID Connect In Depth.NET Fest 2019. Kevin Dockx. OpenID Connect In Depth
.NET Fest 2019. Kevin Dockx. OpenID Connect In DepthNETFest
 
.NET Fest 2019. Андрей Антиликаторов. Проектирование и разработка Big Data ре...
.NET Fest 2019. Андрей Антиликаторов. Проектирование и разработка Big Data ре....NET Fest 2019. Андрей Антиликаторов. Проектирование и разработка Big Data ре...
.NET Fest 2019. Андрей Антиликаторов. Проектирование и разработка Big Data ре...NETFest
 
.NET Fest 2019. Irina Scurtu. Forget about HTTP
.NET Fest 2019. Irina Scurtu. Forget about HTTP.NET Fest 2019. Irina Scurtu. Forget about HTTP
.NET Fest 2019. Irina Scurtu. Forget about HTTPNETFest
 

More from NETFest (20)

.NET Fest 2019. Halil Ibrahim Kalkan. Implementing Domain Driven Design
.NET Fest 2019. Halil Ibrahim Kalkan. Implementing Domain Driven Design.NET Fest 2019. Halil Ibrahim Kalkan. Implementing Domain Driven Design
.NET Fest 2019. Halil Ibrahim Kalkan. Implementing Domain Driven Design
 
.NET Fest 2019. Сергій Бута. Feature Toggles: Dynamic Configuration at Wirex
.NET Fest 2019. Сергій Бута. Feature Toggles: Dynamic Configuration at Wirex.NET Fest 2019. Сергій Бута. Feature Toggles: Dynamic Configuration at Wirex
.NET Fest 2019. Сергій Бута. Feature Toggles: Dynamic Configuration at Wirex
 
.NET Fest 2019. Michael Staib. Hot Chocolate: GraphQL Schema Stitching with A...
.NET Fest 2019. Michael Staib. Hot Chocolate: GraphQL Schema Stitching with A....NET Fest 2019. Michael Staib. Hot Chocolate: GraphQL Schema Stitching with A...
.NET Fest 2019. Michael Staib. Hot Chocolate: GraphQL Schema Stitching with A...
 
.NET Fest 2019. Андрей Литвинов. Async lifetime tests with xUnit and AutoFixture
.NET Fest 2019. Андрей Литвинов. Async lifetime tests with xUnit and AutoFixture.NET Fest 2019. Андрей Литвинов. Async lifetime tests with xUnit and AutoFixture
.NET Fest 2019. Андрей Литвинов. Async lifetime tests with xUnit and AutoFixture
 
.NET Fest 2019. Анатолий Колесник. Love, Death & F# Tests
.NET Fest 2019. Анатолий Колесник. Love, Death & F# Tests.NET Fest 2019. Анатолий Колесник. Love, Death & F# Tests
.NET Fest 2019. Анатолий Колесник. Love, Death & F# Tests
 
.NET Fest 2019. Алексей Голуб. Монадные парсер-комбинаторы в C# (простой спос...
.NET Fest 2019. Алексей Голуб. Монадные парсер-комбинаторы в C# (простой спос....NET Fest 2019. Алексей Голуб. Монадные парсер-комбинаторы в C# (простой спос...
.NET Fest 2019. Алексей Голуб. Монадные парсер-комбинаторы в C# (простой спос...
 
.NET Fest 2019. Roberto Freato. Azure App Service deep dive
.NET Fest 2019. Roberto Freato. Azure App Service deep dive.NET Fest 2019. Roberto Freato. Azure App Service deep dive
.NET Fest 2019. Roberto Freato. Azure App Service deep dive
 
.NET Fest 2019. Леонид Молотиевский. DotNet Core in production
.NET Fest 2019. Леонид Молотиевский. DotNet Core in production.NET Fest 2019. Леонид Молотиевский. DotNet Core in production
.NET Fest 2019. Леонид Молотиевский. DotNet Core in production
 
.NET Fest 2019. Александр Демчук. How to measure relationships within the Com...
.NET Fest 2019. Александр Демчук. How to measure relationships within the Com....NET Fest 2019. Александр Демчук. How to measure relationships within the Com...
.NET Fest 2019. Александр Демчук. How to measure relationships within the Com...
 
.NET Fest 2019. Anna Melashkina та Philipp Bauknecht. Dragons in a Mixed Real...
.NET Fest 2019. Anna Melashkina та Philipp Bauknecht. Dragons in a Mixed Real....NET Fest 2019. Anna Melashkina та Philipp Bauknecht. Dragons in a Mixed Real...
.NET Fest 2019. Anna Melashkina та Philipp Bauknecht. Dragons in a Mixed Real...
 
.NET Fest 2019. Alex Thissen. Architecting .NET solutions in a Docker ecosystem
.NET Fest 2019. Alex Thissen. Architecting .NET solutions in a Docker ecosystem.NET Fest 2019. Alex Thissen. Architecting .NET solutions in a Docker ecosystem
.NET Fest 2019. Alex Thissen. Architecting .NET solutions in a Docker ecosystem
 
.NET Fest 2019. Stas Lebedenko. Practical serverless use cases in Azure with ...
.NET Fest 2019. Stas Lebedenko. Practical serverless use cases in Azure with ....NET Fest 2019. Stas Lebedenko. Practical serverless use cases in Azure with ...
.NET Fest 2019. Stas Lebedenko. Practical serverless use cases in Azure with ...
 
.NET Fest 2019. Сергей Медведев. How serverless makes Integration TDD a reali...
.NET Fest 2019. Сергей Медведев. How serverless makes Integration TDD a reali....NET Fest 2019. Сергей Медведев. How serverless makes Integration TDD a reali...
.NET Fest 2019. Сергей Медведев. How serverless makes Integration TDD a reali...
 
.NET Fest 2019. Сергей Корж. Natural Language Processing in .NET
.NET Fest 2019. Сергей Корж. Natural Language Processing in .NET.NET Fest 2019. Сергей Корж. Natural Language Processing in .NET
.NET Fest 2019. Сергей Корж. Natural Language Processing in .NET
 
.NET Fest 2019. Eran Stiller. Create Your Own Serverless PKI with .NET & Azur...
.NET Fest 2019. Eran Stiller. Create Your Own Serverless PKI with .NET & Azur....NET Fest 2019. Eran Stiller. Create Your Own Serverless PKI with .NET & Azur...
.NET Fest 2019. Eran Stiller. Create Your Own Serverless PKI with .NET & Azur...
 
.NET Fest 2019. Eran Stiller. 6 Lessons I Learned on My Journey from Monolith...
.NET Fest 2019. Eran Stiller. 6 Lessons I Learned on My Journey from Monolith....NET Fest 2019. Eran Stiller. 6 Lessons I Learned on My Journey from Monolith...
.NET Fest 2019. Eran Stiller. 6 Lessons I Learned on My Journey from Monolith...
 
.NET Fest 2019. Kevin Dockx. Uncovering Swagger/OpenAPI
.NET Fest 2019. Kevin Dockx. Uncovering Swagger/OpenAPI.NET Fest 2019. Kevin Dockx. Uncovering Swagger/OpenAPI
.NET Fest 2019. Kevin Dockx. Uncovering Swagger/OpenAPI
 
.NET Fest 2019. Kevin Dockx. OpenID Connect In Depth
.NET Fest 2019. Kevin Dockx. OpenID Connect In Depth.NET Fest 2019. Kevin Dockx. OpenID Connect In Depth
.NET Fest 2019. Kevin Dockx. OpenID Connect In Depth
 
.NET Fest 2019. Андрей Антиликаторов. Проектирование и разработка Big Data ре...
.NET Fest 2019. Андрей Антиликаторов. Проектирование и разработка Big Data ре....NET Fest 2019. Андрей Антиликаторов. Проектирование и разработка Big Data ре...
.NET Fest 2019. Андрей Антиликаторов. Проектирование и разработка Big Data ре...
 
.NET Fest 2019. Irina Scurtu. Forget about HTTP
.NET Fest 2019. Irina Scurtu. Forget about HTTP.NET Fest 2019. Irina Scurtu. Forget about HTTP
.NET Fest 2019. Irina Scurtu. Forget about HTTP
 

Recently uploaded

Introduction to Nonprofit Accounting: The Basics
Introduction to Nonprofit Accounting: The BasicsIntroduction to Nonprofit Accounting: The Basics
Introduction to Nonprofit Accounting: The BasicsTechSoup
 
Z Score,T Score, Percential Rank and Box Plot Graph
Z Score,T Score, Percential Rank and Box Plot GraphZ Score,T Score, Percential Rank and Box Plot Graph
Z Score,T Score, Percential Rank and Box Plot GraphThiyagu K
 
Software Engineering Methodologies (overview)
Software Engineering Methodologies (overview)Software Engineering Methodologies (overview)
Software Engineering Methodologies (overview)eniolaolutunde
 
Interactive Powerpoint_How to Master effective communication
Interactive Powerpoint_How to Master effective communicationInteractive Powerpoint_How to Master effective communication
Interactive Powerpoint_How to Master effective communicationnomboosow
 
BAG TECHNIQUE Bag technique-a tool making use of public health bag through wh...
BAG TECHNIQUE Bag technique-a tool making use of public health bag through wh...BAG TECHNIQUE Bag technique-a tool making use of public health bag through wh...
BAG TECHNIQUE Bag technique-a tool making use of public health bag through wh...Sapna Thakur
 
Separation of Lanthanides/ Lanthanides and Actinides
Separation of Lanthanides/ Lanthanides and ActinidesSeparation of Lanthanides/ Lanthanides and Actinides
Separation of Lanthanides/ Lanthanides and ActinidesFatimaKhan178732
 
Sports & Fitness Value Added Course FY..
Sports & Fitness Value Added Course FY..Sports & Fitness Value Added Course FY..
Sports & Fitness Value Added Course FY..Disha Kariya
 
A Critique of the Proposed National Education Policy Reform
A Critique of the Proposed National Education Policy ReformA Critique of the Proposed National Education Policy Reform
A Critique of the Proposed National Education Policy ReformChameera Dedduwage
 
The byproduct of sericulture in different industries.pptx
The byproduct of sericulture in different industries.pptxThe byproduct of sericulture in different industries.pptx
The byproduct of sericulture in different industries.pptxShobhayan Kirtania
 
Measures of Dispersion and Variability: Range, QD, AD and SD
Measures of Dispersion and Variability: Range, QD, AD and SDMeasures of Dispersion and Variability: Range, QD, AD and SD
Measures of Dispersion and Variability: Range, QD, AD and SDThiyagu K
 
1029 - Danh muc Sach Giao Khoa 10 . pdf
1029 -  Danh muc Sach Giao Khoa 10 . pdf1029 -  Danh muc Sach Giao Khoa 10 . pdf
1029 - Danh muc Sach Giao Khoa 10 . pdfQucHHunhnh
 
Organic Name Reactions for the students and aspirants of Chemistry12th.pptx
Organic Name Reactions  for the students and aspirants of Chemistry12th.pptxOrganic Name Reactions  for the students and aspirants of Chemistry12th.pptx
Organic Name Reactions for the students and aspirants of Chemistry12th.pptxVS Mahajan Coaching Centre
 
Sanyam Choudhary Chemistry practical.pdf
Sanyam Choudhary Chemistry practical.pdfSanyam Choudhary Chemistry practical.pdf
Sanyam Choudhary Chemistry practical.pdfsanyamsingh5019
 
POINT- BIOCHEMISTRY SEM 2 ENZYMES UNIT 5.pptx
POINT- BIOCHEMISTRY SEM 2 ENZYMES UNIT 5.pptxPOINT- BIOCHEMISTRY SEM 2 ENZYMES UNIT 5.pptx
POINT- BIOCHEMISTRY SEM 2 ENZYMES UNIT 5.pptxSayali Powar
 
1029-Danh muc Sach Giao Khoa khoi 6.pdf
1029-Danh muc Sach Giao Khoa khoi  6.pdf1029-Danh muc Sach Giao Khoa khoi  6.pdf
1029-Danh muc Sach Giao Khoa khoi 6.pdfQucHHunhnh
 
9548086042 for call girls in Indira Nagar with room service
9548086042  for call girls in Indira Nagar  with room service9548086042  for call girls in Indira Nagar  with room service
9548086042 for call girls in Indira Nagar with room servicediscovermytutordmt
 
APM Welcome, APM North West Network Conference, Synergies Across Sectors
APM Welcome, APM North West Network Conference, Synergies Across SectorsAPM Welcome, APM North West Network Conference, Synergies Across Sectors
APM Welcome, APM North West Network Conference, Synergies Across SectorsAssociation for Project Management
 
Kisan Call Centre - To harness potential of ICT in Agriculture by answer farm...
Kisan Call Centre - To harness potential of ICT in Agriculture by answer farm...Kisan Call Centre - To harness potential of ICT in Agriculture by answer farm...
Kisan Call Centre - To harness potential of ICT in Agriculture by answer farm...Krashi Coaching
 
Presentation by Andreas Schleicher Tackling the School Absenteeism Crisis 30 ...
Presentation by Andreas Schleicher Tackling the School Absenteeism Crisis 30 ...Presentation by Andreas Schleicher Tackling the School Absenteeism Crisis 30 ...
Presentation by Andreas Schleicher Tackling the School Absenteeism Crisis 30 ...EduSkills OECD
 

Recently uploaded (20)

Introduction to Nonprofit Accounting: The Basics
Introduction to Nonprofit Accounting: The BasicsIntroduction to Nonprofit Accounting: The Basics
Introduction to Nonprofit Accounting: The Basics
 
Z Score,T Score, Percential Rank and Box Plot Graph
Z Score,T Score, Percential Rank and Box Plot GraphZ Score,T Score, Percential Rank and Box Plot Graph
Z Score,T Score, Percential Rank and Box Plot Graph
 
Software Engineering Methodologies (overview)
Software Engineering Methodologies (overview)Software Engineering Methodologies (overview)
Software Engineering Methodologies (overview)
 
Interactive Powerpoint_How to Master effective communication
Interactive Powerpoint_How to Master effective communicationInteractive Powerpoint_How to Master effective communication
Interactive Powerpoint_How to Master effective communication
 
BAG TECHNIQUE Bag technique-a tool making use of public health bag through wh...
BAG TECHNIQUE Bag technique-a tool making use of public health bag through wh...BAG TECHNIQUE Bag technique-a tool making use of public health bag through wh...
BAG TECHNIQUE Bag technique-a tool making use of public health bag through wh...
 
Separation of Lanthanides/ Lanthanides and Actinides
Separation of Lanthanides/ Lanthanides and ActinidesSeparation of Lanthanides/ Lanthanides and Actinides
Separation of Lanthanides/ Lanthanides and Actinides
 
Sports & Fitness Value Added Course FY..
Sports & Fitness Value Added Course FY..Sports & Fitness Value Added Course FY..
Sports & Fitness Value Added Course FY..
 
A Critique of the Proposed National Education Policy Reform
A Critique of the Proposed National Education Policy ReformA Critique of the Proposed National Education Policy Reform
A Critique of the Proposed National Education Policy Reform
 
The byproduct of sericulture in different industries.pptx
The byproduct of sericulture in different industries.pptxThe byproduct of sericulture in different industries.pptx
The byproduct of sericulture in different industries.pptx
 
Measures of Dispersion and Variability: Range, QD, AD and SD
Measures of Dispersion and Variability: Range, QD, AD and SDMeasures of Dispersion and Variability: Range, QD, AD and SD
Measures of Dispersion and Variability: Range, QD, AD and SD
 
1029 - Danh muc Sach Giao Khoa 10 . pdf
1029 -  Danh muc Sach Giao Khoa 10 . pdf1029 -  Danh muc Sach Giao Khoa 10 . pdf
1029 - Danh muc Sach Giao Khoa 10 . pdf
 
Organic Name Reactions for the students and aspirants of Chemistry12th.pptx
Organic Name Reactions  for the students and aspirants of Chemistry12th.pptxOrganic Name Reactions  for the students and aspirants of Chemistry12th.pptx
Organic Name Reactions for the students and aspirants of Chemistry12th.pptx
 
Sanyam Choudhary Chemistry practical.pdf
Sanyam Choudhary Chemistry practical.pdfSanyam Choudhary Chemistry practical.pdf
Sanyam Choudhary Chemistry practical.pdf
 
Mattingly "AI & Prompt Design: The Basics of Prompt Design"
Mattingly "AI & Prompt Design: The Basics of Prompt Design"Mattingly "AI & Prompt Design: The Basics of Prompt Design"
Mattingly "AI & Prompt Design: The Basics of Prompt Design"
 
POINT- BIOCHEMISTRY SEM 2 ENZYMES UNIT 5.pptx
POINT- BIOCHEMISTRY SEM 2 ENZYMES UNIT 5.pptxPOINT- BIOCHEMISTRY SEM 2 ENZYMES UNIT 5.pptx
POINT- BIOCHEMISTRY SEM 2 ENZYMES UNIT 5.pptx
 
1029-Danh muc Sach Giao Khoa khoi 6.pdf
1029-Danh muc Sach Giao Khoa khoi  6.pdf1029-Danh muc Sach Giao Khoa khoi  6.pdf
1029-Danh muc Sach Giao Khoa khoi 6.pdf
 
9548086042 for call girls in Indira Nagar with room service
9548086042  for call girls in Indira Nagar  with room service9548086042  for call girls in Indira Nagar  with room service
9548086042 for call girls in Indira Nagar with room service
 
APM Welcome, APM North West Network Conference, Synergies Across Sectors
APM Welcome, APM North West Network Conference, Synergies Across SectorsAPM Welcome, APM North West Network Conference, Synergies Across Sectors
APM Welcome, APM North West Network Conference, Synergies Across Sectors
 
Kisan Call Centre - To harness potential of ICT in Agriculture by answer farm...
Kisan Call Centre - To harness potential of ICT in Agriculture by answer farm...Kisan Call Centre - To harness potential of ICT in Agriculture by answer farm...
Kisan Call Centre - To harness potential of ICT in Agriculture by answer farm...
 
Presentation by Andreas Schleicher Tackling the School Absenteeism Crisis 30 ...
Presentation by Andreas Schleicher Tackling the School Absenteeism Crisis 30 ...Presentation by Andreas Schleicher Tackling the School Absenteeism Crisis 30 ...
Presentation by Andreas Schleicher Tackling the School Absenteeism Crisis 30 ...
 

.NET Fest 2017. Mark Seemann. From Dependency injection to dependency rejection

  • 1. From dependency injection to dependency rejection Mark Seemann http://blog.ploeh.dk @ploeh
  • 4. Object-oriented Functional Dependency injection Partial application Composition @ploeh
  • 5. Dependency injection is “really just a pretentious way to say ‘taking an argument’” - Rúnar Bjarnason (@runarorama) @ploeh
  • 7. Restaurant Reservation Make a reservation Date Name Email Quantity Submit @ploeh
  • 8. Restaurant Reservation Make a reservation Date 2 Name Email Quantity Submit @ploeh
  • 9. Restaurant Reservation Make a reservation Date 20 Name Email Quantity Submit @ploeh
  • 10. Restaurant Reservation Make a reservation Date 201 Name Email Quantity Submit @ploeh
  • 11. Restaurant Reservation Make a reservation Date 2016 Name Email Quantity Submit @ploeh
  • 12. Restaurant Reservation Make a reservation Date 2016- Name Email Quantity Submit @ploeh
  • 13. Restaurant Reservation Make a reservation Date 2016-1 Name Email Quantity Submit @ploeh
  • 14. Restaurant Reservation Make a reservation Date 2016-12 Name Email Quantity Submit @ploeh
  • 15. Restaurant Reservation Make a reservation Date 2016-12- Name Email Quantity Submit @ploeh
  • 16. Restaurant Reservation Make a reservation Date 2016-12-2 Name Email Quantity Submit @ploeh
  • 17. Restaurant Reservation Make a reservation Date 2016-12-29 Name Email Quantity Submit @ploeh
  • 18. Restaurant Reservation Make a reservation Date 2016-12-29 Name M Email Quantity Submit @ploeh
  • 19. Restaurant Reservation Make a reservation Date 2016-12-29 Name Ma Email Quantity Submit @ploeh
  • 20. Restaurant Reservation Make a reservation Date 2016-12-29 Name Mar Email Quantity Submit @ploeh
  • 21. Restaurant Reservation Make a reservation Date 2016-12-29 Name Mark Email Quantity Submit @ploeh
  • 22. Restaurant Reservation Make a reservation Date 2016-12-29 Name Mark Email Quantity Submit @ploeh
  • 23. Restaurant Reservation Make a reservation Date 2016-12-29 Name Mark S Email Quantity Submit @ploeh
  • 24. Restaurant Reservation Make a reservation Date 2016-12-29 Name Mark Se Email Quantity Submit @ploeh
  • 25. Restaurant Reservation Make a reservation Date 2016-12-29 Name Mark See Email Quantity Submit @ploeh
  • 26. Restaurant Reservation Make a reservation Date 2016-12-29 Name Mark Seem Email Quantity Submit @ploeh
  • 27. Restaurant Reservation Make a reservation Date 2016-12-29 Name Mark Seema Email Quantity Submit @ploeh
  • 28. Restaurant Reservation Make a reservation Date 2016-12-29 Name Mark Seeman Email Quantity Submit @ploeh
  • 29. Restaurant Reservation Make a reservation Date 2016-12-29 Name Mark Seemann Email Quantity Submit @ploeh
  • 30. Restaurant Reservation Make a reservation Date 2016-12-29 Name Mark Seemann Email ma Quantity Submit @ploeh
  • 31. Restaurant Reservation Make a reservation Date 2016-12-29 Name Mark Seemann Email mar Quantity Submit @ploeh
  • 32. Restaurant Reservation Make a reservation Date 2016-12-29 Name Mark Seemann Email mark Quantity Submit @ploeh
  • 33. Restaurant Reservation Make a reservation Date 2016-12-29 Name Mark Seemann Email mark@ Quantity Submit @ploeh
  • 34. Restaurant Reservation Make a reservation Date 2016-12-29 Name Mark Seemann Email mark@p Quantity Submit @ploeh
  • 35. Restaurant Reservation Make a reservation Date 2016-12-29 Name Mark Seemann Email mark@pl Quantity Submit @ploeh
  • 36. Restaurant Reservation Make a reservation Date 2016-12-29 Name Mark Seemann Email mark@plo Quantity Submit @ploeh
  • 37. Restaurant Reservation Make a reservation Date 2016-12-29 Name Mark Seemann Email mark@ploe Quantity Submit @ploeh
  • 38. Restaurant Reservation Make a reservation Date 2016-12-29 Name Mark Seemann Email mark@ploeh Quantity Submit @ploeh
  • 39. Restaurant Reservation Make a reservation Date 2016-12-29 Name Mark Seemann Email mark@ploeh. Quantity Submit @ploeh
  • 40. Restaurant Reservation Make a reservation Date 2016-12-29 Name Mark Seemann Email mark@ploeh.d Quantity Submit @ploeh
  • 41. Restaurant Reservation Make a reservation Date 2016-12-29 Name Mark Seemann Email mark@ploeh.dk Quantity Submit @ploeh
  • 42. Restaurant Reservation POST JSON @ploeh Make a reservation Date 2016-12-29 Name Mark Seemann Email mark@ploeh.dk Quantity 4 Submit
  • 43. Restaurant Reservation POST JSON @ploeh Make a reservation Date 2016-12-29 Name Mark Seemann Email mark@ploeh.dk Quantity 4 Submit
  • 46. public class ReservationsController : ApiController { public ReservationsController(IValidator validator, IMapper mapper, IMaîtreD maîtreD) { this.validator = validator; this.mapper = mapper; this.maîtreD = maîtreD; } public IHttpActionResult Post(ReservationRequestDto dto) { var validationMsg = validator.Validate(dto); if (validationMsg != "") return this.BadRequest(validationMsg); var r = mapper.Map(dto); var id = maîtreD.TryAccept(r); if (id == null) return this.StatusCode(HttpStatusCode.Forbidden); return this.Ok(); } } POST /reservations HTTP/1.1 { "date": "2016-12-08", "name": "Mark Seemann", "email": "mark@ploeh.dk", "quantity": 4 } @ploeh
  • 47. public class MaîtreD : IMaîtreD { public MaîtreD(int capacity, IReservationsRepository reservationsRepository) { this.capacity = capacity; this.reservationsRepository = reservationsRepository; } public int? TryAccept(Reservation reservation) { var reservedSeats = reservationsRepository .ReadReservations(reservation.Date) .Sum(r => r.Quantity); if (reservedSeats + reservation.Quantity <= capacity) { reservation.IsAccepted = true; return reservationsRepository.Create(reservation); } return null; } } @ploeh public interface IMaîtreD { int? TryAccept(Reservation reservation); }
  • 48. How do I do dependency injection in Scala? You don’t, because Scala is a functional language. Comic courtesy of @jrecursive and @hmemcpy @ploeh
  • 49. Fine, it’s functional. How do I inject dependencies? You use a Free Monad, which allows you to build a Monad from any Functor. Comic courtesy of @jrecursive and @hmemcpy @ploeh
  • 50. Did you just tell me to go fuck myself? I believe I did, Bob. Comic courtesy of @jrecursive and @hmemcpy @ploeh
  • 51. Partial application An attempt at dependency injection with a functional language @ploeh
  • 52. // int -> (DateTimeOffset -> Reservation list) -> (Reservation -> int) -> Reservation // -> int option let tryAccept capacity readReservations createReservation reservation = let reservedSeats = readReservations reservation.Date |> List.sumBy (fun x -> x.Quantity) if reservedSeats + reservation.Quantity <= capacity then createReservation { reservation with IsAccepted = true } |> Some else None @ploeh Repository
  • 53. // Reservation -> int option let tryAcceptComposition reservation = let read = DB.readReservations connectionString @ploeh string -> DateTimeOffset -> Reservation list
  • 54. // Reservation -> int option let tryAcceptComposition reservation = let read = DB.readReservations connectionString @ploeh string -> DateTimeOffset -> Reservation list connectionString
  • 55. // Reservation -> int option let tryAcceptComposition reservation = let read = DB.readReservations connectionString @ploeh string -> DateTimeOffset -> Reservation listconnectionString
  • 56. // Reservation -> int option let tryAcceptComposition reservation = let read = DB.readReservations connectionString @ploeh DateTimeOffset -> Reservation list
  • 57. // Reservation -> int option let tryAcceptComposition reservation = let read = DB.readReservations connectionString let create = DB.createReservation connectionString tryAccept 10 read create reservation @ploeh Reservation -> int
  • 58. // Reservation -> int option let tryAcceptComposition reservation = let read = DB.readReservations connectionString let create = DB.createReservation connectionString tryAccept 10 read create reservation @ploeh
  • 59. // Reservation -> int option let tryAcceptComposition = let read = DB.readReservations connectionString let create = DB.createReservation connectionString tryAccept 10 read create @ploeh
  • 60. // Reservation -> int option let tryAcceptComposition = let read = DB.readReservations connectionString let create = DB.createReservation connectionString tryAccept 10 read create @ploeh
  • 62. internal class tryAcceptComposition@17 : FSharpFunc<Reservation, FSharpOption<int>> { public int capacity; public FSharpFunc<Reservation, int> createReservation; public FSharpFunc<DateTimeOffset, FSharpList<Reservation>> readReservations; internal tryAcceptComposition@17( int capacity, FSharpFunc<DateTimeOffset, FSharpList<Reservation>> readReservations, FSharpFunc<Reservation, int> createReservation) { this.capacity = capacity; this.readReservations = readReservations; this.createReservation = createReservation; } public override FSharpOption<int> Invoke(Reservation reservation) { return MaîtreD.tryAccept<int>( this.capacity, this.readReservations, this.createReservation, reservation); } } @ploeh
  • 64. Same return value for same input No side- effects Pure function @ploeh
  • 67. tryAccept :: Int -> (ZonedTime -> [Reservation]) -> (Reservation -> Int) -> Reservation -> Maybe Int tryAccept capacity readReservations createReservation reservation = let reservedSeats = sum $ map quantity $ readReservations $ date reservation in if reservedSeats + quantity reservation <= capacity then Just $ createReservation $ reservation { isAccepted = True } else Nothing @ploeh Pure
  • 68. tryAcceptComposition :: Reservation -> IO (Maybe Int) tryAcceptComposition reservation = let read = DB.readReservations connectionString create = DB.createReservation connectionString in tryAccept 10 read create reservation @ploeh ZonedTime -> IO [Reservation] Reservation -> IO Int ZonedTime -> [Reservation] Reservation -> Int
  • 75. // int -> (DateTimeOffset -> Reservation list) -> (Reservation -> int) -> Reservation // -> int option let tryAccept capacity readReservations createReservation reservation = @ploeh
  • 76. // int -> (DateTimeOffset -> Reservation list) -> Reservation // -> Reservation option let tryAccept capacity readReservations reservation = @ploeh
  • 77. // int -> (DateTimeOffset -> Reservation list) -> Reservation // -> Reservation option let tryAccept capacity readReservations reservation = @ploeh
  • 78. // int -> (DateTimeOffset -> Reservation list) -> Reservation -> Reservation option let tryAccept capacity readReservations reservation = @ploeh
  • 79. // int -> (DateTimeOffset -> Reservation list) -> Reservation -> Reservation option let tryAccept capacity readReservations reservation = let reservedSeats = readReservations reservation.Date |> List.sumBy (fun x -> x.Quantity) if reservedSeats + reservation.Quantity <= capacity then { reservation with IsAccepted = true } |> Some else None @ploeh
  • 80. // Reservation -> int option let tryAcceptComposition reservation = match tryAccept 10 (DB.readReservations connectionString) reservation with | None -> None | Some r -> (DB.createReservation connectionString) r |> Some @ploeh
  • 81. // Reservation -> int option let tryAcceptComposition reservation = tryAccept 10 (DB.readReservations connectionString) reservation |> Option.map (fun r -> DB.createReservation connectionString r) @ploeh
  • 82. // Reservation -> int option let tryAcceptComposition reservation = tryAccept 10 (DB.readReservations connectionString) reservation |> Option.map ( DB.createReservation connectionString ) @ploeh
  • 83. // Reservation -> int option let tryAcceptComposition reservation = tryAccept 10 (DB.readReservations connectionString) reservation |> Option.map (DB.createReservation connectionString) @ploeh
  • 84. // Reservation -> int option let tryAcceptComposition reservation = reservation |> tryAccept 10 (DB.readReservations connectionString) |> Option.map (DB.createReservation connectionString) @ploeh
  • 87. // int -> (DateTimeOffset -> Reservation list) -> Reservation -> Reservation option let tryAccept capacity readReservations reservation = @ploeh
  • 88. // int -> ( Reservation list) -> Reservation -> Reservation option let tryAccept capacity readReservations reservation = @ploeh
  • 89. // int -> Reservation list -> Reservation -> Reservation option let tryAccept capacity readReservations reservation = @ploeh
  • 90. // int -> Reservation list -> Reservation -> Reservation option let tryAccept capacity radReservations reservation = @ploeh
  • 91. // int -> Reservation list -> Reservation -> Reservation option let tryAccept capacity rdReservations reservation = @ploeh
  • 92. // int -> Reservation list -> Reservation -> Reservation option let tryAccept capacity rReservations reservation = @ploeh
  • 93. // int -> Reservation list -> Reservation -> Reservation option let tryAccept capacity reservations reservation = @ploeh
  • 94. // int -> Reservation list -> Reservation -> Reservation option let tryAccept capacity reservations reservation = @ploeh
  • 95. // int -> Reservation list -> Reservation -> Reservation option let tryAccept capacity reservations reservation = @ploeh
  • 96. // int -> Reservation list -> Reservation -> Reservation option let tryAccept capacity reservations reservation = @ploeh
  • 97. // int -> Reservation list -> Reservation -> Reservation option let tryAccept capacity reservations reservation = @ploeh
  • 98. // int -> Reservation list -> Reservation -> Reservation option let tryAccept capacity reservations reservation = @ploeh
  • 99. // int -> Reservation list -> Reservation -> Reservation option let tryAccept capacity reservations reservation = @ploeh
  • 100. // int -> Reservation list -> Reservation -> Reservation option let tryAccept capacity reservations reservation = @ploeh
  • 101. // int -> Reservation list -> Reservation -> Reservation option let tryAccept capacity reservations reservation = @ploeh
  • 102. // int -> Reservation list -> Reservation -> Reservation option let tryAccept capacity reservations reservation = @ploeh
  • 103. // int -> Reservation list -> Reservation -> Reservation option let tryAccept capacity reservations reservation = @ploeh
  • 104. // int -> Reservation list -> Reservation -> Reservation option let tryAccept capacity reservations reservation = @ploeh
  • 105. // int -> Reservation list -> Reservation -> Reservation option let tryAccept capacity reservations reservation = @ploeh
  • 106. // int -> Reservation list -> Reservation -> Reservation option let tryAccept capacity reservations reservation = @ploeh
  • 107. // int -> Reservation list -> Reservation -> Reservation option let tryAccept capacity reservations reservation = @ploeh
  • 108. // int -> Reservation list -> Reservation -> Reservation option let tryAccept capacity reservations reservation = @ploeh
  • 109. // int -> Reservation list -> Reservation -> Reservation option let tryAccept capacity reservations reservation = let reservedSeats = reservations |> List.sumBy (fun x -> x.Quantity) if reservedSeats + reservation.Quantity <= capacity then { reservation with IsAccepted = true } |> Some else None @ploeh
  • 110. // int -> Reservation list -> Reservation -> Reservation option let tryAccept capacity reservations reservation = let reservedSeats = reservations |> List.sumBy (fun x -> x.Quantity) if reservedSeats + reservation.Quantity <= capacity then { reservation with IsAccepted = true } |> Some else None @ploeh
  • 111. // ('a -> 'b -> 'c) -> 'b -> 'a -> 'c let flip f x y = f y x // Reservation -> int option let tryAcceptComposition reservation = reservation.Date |> DB.readReservations connectionString |> fun reservations -> tryAccept 10 reservations reservation |> Option.map (DB.createReservation connectionString) @ploeh
  • 112. // ('a -> 'b -> 'c) -> 'b -> 'a -> 'c let flip f x y = f y x // Reservation -> int option let tryAcceptComposition reservation = reservation.Date |> DB.readReservations connectionString |> fun reservations -> flip (tryAccept 10) reservation reservations |> Option.map (DB.createReservation connectionString) @ploeh
  • 113. // ('a -> 'b -> 'c) -> 'b -> 'a -> 'c let flip f x y = f y x // Reservation -> int option let tryAcceptComposition reservation = reservation.Date |> DB.readReservations connectionString |> -> flip (tryAccept 10) reservation |> Option.map (DB.createReservation connectionString) @ploeh
  • 114. // ('a -> 'b -> 'c) -> 'b -> 'a -> 'c let flip f x y = f y x // Reservation -> int option let tryAcceptComposition reservation = reservation.Date |> DB.readReservations connectionString |> flip (tryAccept 10) reservation |> Option.map (DB.createReservation connectionString) @ploeh
  • 116. tryAccept :: Int -> [Reservation] -> Reservation -> Maybe Reservation tryAccept capacity reservations reservation = let reservedSeats = sum $ map quantity reservations in if reservedSeats + quantity reservation <= capacity then Just $ reservation { isAccepted = True } else Nothing @ploeh
  • 117. tryAcceptComposition :: Reservation -> IO (Maybe Int) tryAcceptComposition reservation = runMaybeT $ liftIO (DB.readReservations connectionString $ date reservation) >>= MaybeT . return . flip (tryAccept 10) reservation >>= liftIO . DB.createReservation connectionString @ploeh
  • 118. Object-oriented Functional Dependency injection Partial application Composition @ploeh