Last active
July 18, 2017 13:18
-
-
Save Papipo/46544044f984c6eec0c85b2465341c05 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Aggregates are just collections of command functions, which emit events, | |
# and event handlers, which mutate state. | |
# In order to hold state, they should be also structs. | |
# There is no new() function because aggregates aren't supposed to appear | |
# out of the blue, they are always the result of a command. | |
# In this case, %OpenAccount{}. | |
defmodule Bank.Account do | |
defstruct [:account_number, :balance] | |
# I like my commands and events to live in commands.ex and events.ex files | |
# on the root folder of my application. | |
# I think it's wonderful to have all that information at hand. | |
defmodule Commands do | |
import Commanded, only: [command: 2] | |
command OpenAccount, :account_number, [:initial_balance] | |
command Deposit, :account_number, [:amount] | |
command Withdraw, :account_number, [:amount] | |
end | |
defmodule Events do | |
import Commanded, only: [event: 1] | |
event AccountOpened, [:initial_balance] | |
event MoneyDeposited, [:amount] | |
event MoneyWithtrawn, [:amount] | |
end | |
alias Bank.Account | |
alias Account.Commands.{OpenAccount,Deposit,Withdraw} | |
alias Account.Events.{AccountOpened,MoneyDeposited,MoneyWidthrawn} | |
def execute(_, %OpenAccount{initial_balance: balance}) when balance < 0 do | |
raise "Initial balance can't be negative" | |
end | |
def execute(%Account{}, %OpenAccount{initial_balance: balance}) do | |
# We just return an event or a list of events | |
# The actor in charge of aggregates could just call List.wrap on whatever | |
# the aggregate returns. | |
%AccountOpened{initial_balance: initial_balance} | |
end | |
def apply(%Account{} = state, %AccountOpened = event) do | |
# Here we just return a new state | |
%Account{balance: event.initial_balance) | |
end | |
def execute(%Account{}, %Deposit{amount: amount} do | |
%MoneyDeposited{amount: amount} | |
end | |
def apply(%Account{balance: balance}, %MoneyDeposited{amount: amount}) do | |
%Account{balance: balance + amount} | |
end | |
def execute(%Account{balance: balance}, %MoneyWithdrawn{amount: amount}) when amount <= balance do | |
%Account{balance: balance - amount} | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
defmodule Commanded do | |
defmacro command(name, identifier_key, keys) do | |
quote do | |
defmodule unquote(name) do | |
defstruct [unquote(identifier_key) | unquote(keys)] | |
end | |
end | |
end | |
defmacro event(name, keys) do | |
quote do | |
defmodule unquote(name) do | |
defstruct unquote(keys) | |
end | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment