Senior Software Developer
defmodule Checkout do
def run(order, payment) do
with {:ok, order} <- Payment.authorize(order, payment),
{:ok, order} <- Product.book(order),
{:ok, order} <- Payment.capture(order) do
:ok
end
end
end
defmodule Product do
def book(order) do
tx_id = UUID.uuid4()
request = %{
transaction_id: tx_id,
ticket_details: order.some_details
}
with {:ok, order} <- save_transaction_id(order, tx_id),
{:ok, response} <- send_request(request),
{:ok, ticket} <- handle_response(response),
{:ok, order} <- save_ticket(order, ticket) do
Logger.info("We have a ticket!")
{:ok, order}
end
end
end
test "booking a ticket" do
order = %{ some_details: "booking data" }
StoreMock
|> expect(:save_transaction_id, fn order, tx_id ->
{:ok, order}
end)
APIMock
|> expect(:send_request, fn request ->
response = ...
{:ok, response}
end)
StoreMock
|> expect(:save_ticket, fn order, ticket ->
{:ok, order}
end)
assert {:ok, order} = Product.book(order)
assert order.ticket != nil
end
test "booking a ticket" do
order = %{ some_details: "booking data" }
StoreMock
|> expect(:save_transaction_id, fn order, tx_id ->
{:ok, order}
end)
APIMock
|> expect(:send_request, fn request ->
response = ...
{:ok, response}
end)
StoreMock
|> expect(:save_ticket, fn order, ticket ->
{:ok, order}
end)
assert {:ok, order} = Product.book(order)
assert order.ticket != nil
end
defmodule Product do
def book(order) do
tx_id = UUID.uuid4()
request = %{
transaction_id: tx_id,
ticket_details: order.some_details
}
with {:ok, order} <- save_transaction_id(order, tx_id),
{:ok, response} <- send_request(request),
{:ok, ticket} <- handle_response(response),
{:ok, order} <- save_ticket(order, ticket) do
Logger.info("We have a ticket!")
{:ok, order}
end
end
end
defmodule Product do
def book(order) do
tx_id = UUID.uuid4()
request = %{
transaction_id: tx_id,
ticket_details: order.some_details
}
with {:ok, order} <- save_transaction_id(order, tx_id),
{:ok, response} <- send_request(request),
{:ok, ticket} <- handle_response(response),
{:ok, order} <- save_ticket(order, ticket) do
Logger.info("We have a ticket!")
{:ok, order}
end
end
end
defp prepare(order) do
tx_id = UUID.uuid4()
request = %{
transaction_id: tx_id,
ticket_details: order.some_details
}
with {:ok, order} <- save_transaction_id(order, tx_id) do
{:ok, order, request}
end
end
defp commit(order, request) do
with {:ok, response} <- send_request(request),
{:ok, ticket} <- handle_response(response),
{:ok, order} <- save_ticket(order, ticket) do
{:ok, order}
end
end
def book(order) do
with {:ok, order, request} <- prepare(order),
{:ok, order} <- commit(order, request) do
Logger.info("We have a ticket!")
{:ok, order}
end
end
defp prepare(order)
defp commit(order, request)
defp prepare(order) do
tx_id = UUID.uuid4()
request = %{
transaction_id: tx_id,
ticket_details: order.some_details
}
with {:ok, order} <- save_transaction_id(order, tx_id) do
{:ok, order, request}
end
end
defp commit(order, request) do
with {:ok, response} <- send_request(request),
{:ok, ticket} <- handle_response(response),
{:ok, order} <- save_ticket(order, ticket) do
{:ok, order}
end
end
defp prepare(order) do
tx_id = UUID.uuid4()
request = %{
transaction_id: tx_id,
ticket_details: order.some_details
}
with {:ok, order} <- save_request(order, request) do
{:ok, order, request}
end
end
defp commit(order, request) do
with {:ok, response} <- send_request(request),
{:ok, ticket} <- handle_response(response),
{:ok, order} <- update_order(
%Order{order | ticket: ticket}) do
{:ok, order}
end
end
defmodule Product do
def prepare(order) do
tx_id = UUID.uuid4()
request = %{
transaction_id: tx_id,
ticket_details: order.some_details
}
{:ok, request}
end
def commit(order, request) do
with {:ok, response} <- send_request(request),
{:ok, ticket} <- handle_response(response) do
{:ok, %Order{order | ticket: ticket}}
end
end
end
defmodule Store do
def save_request(order, request)
def update_order(order)
end
defmodule Product do
def prepare(order)
def commit(order, request)
end
defmodule Store do
def save_request(order, request)
def update_order(order)
end
def book(order) do
with {:ok, request} <- Product.prepare(order),
{:ok, request} <- Store.save_request(order, request),
{:ok, order} <- Product.commit(order, request),
{:ok, order} <- Store.update_order(order) do
Logger.info("We have a ticket!")
{:ok, order}
end
end
test "booking a ticket" do
order = %{ some_details: "booking data" }
StoreMock
|> expect(:save_transaction_id, fn order, tx_id ->
{:ok, order}
end)
APIMock
|> expect(:send_request, fn request ->
response = ...
{:ok, response}
end)
StoreMock
|> expect(:save_ticket, fn order, ticket ->
{:ok, order}
end)
assert {:ok, order} = Product.book(order)
assert order.ticket != nil
end
test "booking a ticket" do
order = %{ some_details: "booking data" }
assert {:ok, request} = Product.prepare(order)
assert request.transaction_id != nil
APIMock
|> expect(:send_request, fn request ->
response = ...
{:ok, response}
end)
assert {:ok, order} = Product.commit(order, request)
assert order.ticket != nil
end
defmodule Product do
def prepare(order)
def commit(order, request)
end
defmodule Store do
def save_request(order, request)
def update_order(order)
end
def book(order) do
with {:ok, request} <- Product.prepare(order),
{:ok, request} <- Store.save_request(order, request),
{:ok, order} <- Product.commit(order, request),
{:ok, order} <- Store.update_order(order) do
Logger.info("We have a ticket!")
{:ok, order}
end
end
defmodule AnotherProduct do
def prepare(order)
def commit(order, transaction)
end
defmodule Store do
def prepare(order, transaction)
def commit(order)
end
def book(order) do
with {:ok, transaction} <- AnotherProduct.prepare(order),
{:ok, transaction} <- Store.prepare(order,
transaction),
{:ok, order} <- AnotherProduct.commit(order, transaction),
{:ok, order} <- Store.commit(order) do
Logger.info("We have a ticket!")
{:ok, order}
end
end
Tobias Kräntzer
tobias@qixxit.de
https://qixxit.com
https://medium.com/qixxit-development
https://tobias-kraentzer.de/expecting-the-unexpected