Last active
July 20, 2019 23:21
-
-
Save steven-solomon/d7a06e591d8e6c6926cc89ae7da3ecd0 to your computer and use it in GitHub Desktop.
What Is A GenServer?
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
# test/account_test.exs | |
defmodule AccountTest do | |
use ExUnit.Case | |
test "fails" do | |
assert true == false | |
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 Account do | |
# ... | |
def get_balance(pid) do | |
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 Account do | |
# ... | |
def get_balance(pid) do | |
0 | |
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 Account do | |
# ... | |
def init(:ok) do | |
{:ok, %{balance: 0}} | |
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 Account do | |
# ... | |
def get_balance(pid) do | |
GenServer.call(pid, :get_balance) | |
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 Account do | |
# ... | |
def handle_call(:get_balance, _from, state) do | |
{:reply, Map.get(state, :balance), state} | |
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 AccountTest do | |
use ExUnit.Case | |
# ... | |
test 'depositing money changes the balance' do | |
{:ok, pid} = Account.start_link | |
Account.deposit(pid, 10.0) | |
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 Account | |
def deposit(pid, amount) do | |
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 AccountTest do | |
# ... | |
test 'depositing money changes the balance' do | |
{:ok, pid} = Account.start_link | |
Account.deposit(pid, 10.0) | |
assert 10.0 == Account.get_balance(pid) | |
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 Account do | |
# ... | |
def deposit(pid, amount) do | |
GenServer.cast(pid, {:deposit, 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 Account do | |
# ... | |
def handle_cast({:deposit, amount}, state) do | |
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 Account do | |
# ... | |
def handle_cast({:deposit, amount}, state) do | |
{:noreply, state} | |
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 Account do | |
# ... | |
def handle_cast({:deposit, amount}, state) do | |
balance = Map.get(state, :balance) | |
{:noreply, Map.put(state, :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 Account do | |
# ... | |
def handle_cast({:deposit, amount}, state) do | |
{_value, balance_with_deposit} = | |
Map.get_and_update(state, :balance, fn balance -> | |
{balance, balance + amount} | |
end) | |
{:noreply, balance_with_deposit} | |
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 AccountTest do | |
# ... | |
test 'withdraw money reduces the balance' do | |
{:ok, pid} = Account.start_link() | |
Account.withdraw(pid, 52.34) | |
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 Account do | |
# ... | |
def withdraw(pid, amount) do | |
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 AccountTest do | |
# ... | |
test 'withdraw money reduces the balance' do | |
{:ok, pid} = Account.start_link() | |
Account.withdraw(pid, 52.34) | |
assert -52.34 == Account.get_balance(pid) | |
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 Account do | |
# ... | |
def withdraw(pid, amount) do | |
GenServer.cast(pid, {:withdraw, 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 Account do | |
# ... | |
def handle_cast({:deposit, amount}, state) do | |
# ... | |
end | |
def handle_cast({:withdraw, amount}, state) do | |
{:noreply, state} | |
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 Account do | |
# ... | |
def handle_cast({:deposit, amount}, state) do | |
{_value, balance_with_deposit} = | |
Map.get_and_update(state, :balance, fn balance -> | |
{balance, balance + amount} | |
end) | |
{:noreply, balance_with_deposit} | |
end | |
def handle_cast({:withdraw, amount}, state) do | |
{_value, balance_with_deposit} = | |
Map.get_and_update(state, :balance, fn balance -> | |
{balance, balance - amount} | |
end) | |
{:noreply, balance_with_deposit} | |
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 Account do | |
# ... | |
def handle_cast({:deposit, amount}, state) do | |
# Extracted anonymous function | |
update_balance = fn balance, amount -> balance + amount end | |
{_value, balance_with_deposit} = | |
Map.get_and_update(state, :balance, fn balance -> | |
# we now call the function instead of doing a calculation | |
{balance, update_balance.(balance, amount)} | |
end) | |
{:noreply, balance_with_deposit} | |
end | |
# similar changes were made to this function | |
def handle_cast({:withdraw, amount}, state) do | |
update_balance = fn balance, amount -> balance - amount end | |
{_value, balance_with_deposit} = | |
Map.get_and_update(state, :balance, fn balance -> | |
{balance, update_balance.(balance, amount)} | |
end) | |
{:noreply, balance_with_deposit} | |
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 AccountTest do | |
use ExUnit.Case | |
test "initial balance is zero" do | |
{:ok, pid} = Account.start_link | |
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 AccountTest do | |
use ExUnit.Case | |
test "initial balance is zero" do | |
{:ok, pid} = Account.start_link() | |
assert 0 == Account.get_balance(pid) | |
end | |
test 'depositing money changes the balance' do | |
{:ok, pid} = Account.start_link() | |
Account.deposit(pid, 10.0) | |
assert 10.0 == Account.get_balance(pid) | |
end | |
test 'withdraw money reduces the balance' do | |
{:ok, pid} = Account.start_link() | |
Account.withdraw(pid, 52.34) | |
assert -52.34 == Account.get_balance(pid) | |
end | |
end | |
defmodule Account do | |
# ... | |
def handle_cast({:deposit, amount}, state) do | |
update_balance = fn balance, amount -> balance + amount end | |
# variable 'update_balance' changed to 'updated_balance' | |
{_value, updated_balance} = | |
Map.get_and_update(state, :balance, fn balance -> | |
{balance, update_balance.(balance, amount)} | |
end) | |
# variable name changed | |
{:noreply, updated_balance} | |
end | |
def handle_cast({:withdraw, amount}, state) do | |
update_balance = fn balance, amount -> balance - amount end | |
# variable name changed | |
{_value, updated_balance} = | |
Map.get_and_update(state, :balance, fn balance -> | |
{balance, update_balance.(balance, amount)} | |
end) | |
# variable name changed | |
{:noreply, updated_balance} | |
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 Account do | |
# ... | |
def handle_cast({:withdraw, amount}, state) do | |
update_balance = fn balance, amount -> balance - amount end | |
{:noreply, change_balance(state, amount, update_balance)} | |
end | |
# extracted function | |
defp change_balance(state, amount, update_balance) do | |
{_value, updated_balance} = | |
Map.get_and_update(state, :balance, fn balance -> | |
{balance, update_balance.(balance, amount)} | |
end) | |
updated_balance | |
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 Account do | |
# ... | |
def handle_cast({:withdraw, amount}, state) do | |
{:noreply, change_balance(state, amount, &(&1 - &2))} | |
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 Account do | |
# ... | |
defp change_balance(state, amount, calculate_balance) do | |
{_value, updated_balance} = | |
Map.get_and_update(state, :balance, fn balance -> | |
{balance, calculate_balance.(balance, amount)} | |
end) | |
updated_balance | |
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 Account do | |
# ... | |
def handle_cast({:withdraw, amount}, state) do | |
{:noreply, get_updated_balance(state, amount, &(&1 - &2))} | |
end | |
defp get_updated_balance(state, amount, calculate_balance) do | |
{_value, updated_balance} = | |
Map.get_and_update(state, :balance, fn balance -> | |
{balance, calculate_balance.(balance, amount)} | |
end) | |
updated_balance | |
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 Account do | |
# ... | |
# notice the only different is in the anonymous function | |
def handle_cast({:deposit, amount}, state) do | |
{:noreply, get_updated_balance(state, amount, &(&1 + &2))} | |
end | |
def handle_cast({:withdraw, amount}, state) do | |
{:noreply, get_updated_balance(state, amount, &(&1 - &2))} | |
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 Account do | |
use GenServer | |
def start_link do | |
GenServer.start_link(__MODULE__, :ok) | |
end | |
def init(:ok) do | |
{:ok, %{balance: 0}} | |
end | |
# API | |
def get_balance(pid) do | |
GenServer.call(pid, :get_balance) | |
end | |
def deposit(pid, amount) do | |
GenServer.cast(pid, {:deposit, amount}) | |
end | |
def withdraw(pid, amount) do | |
GenServer.cast(pid, {:withdraw, amount}) | |
end | |
# Callbacks | |
def handle_call(:get_balance, _from, state) do | |
{:reply, Map.get(state, :balance), state} | |
end | |
def handle_cast({:deposit, amount}, state) do | |
{:noreply, get_updated_balance(state, amount, &(&1 + &2))} | |
end | |
def handle_cast({:withdraw, amount}, state) do | |
{:noreply, get_updated_balance(state, amount, &(&1 - &2))} | |
end | |
# private | |
defp get_updated_balance(state, amount, calculate_balance) do | |
{_value, updated_balance} = | |
Map.get_and_update(state, :balance, fn balance -> | |
{balance, calculate_balance.(balance, amount)} | |
end) | |
updated_balance | |
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
# bank/lib/account.ex | |
defmodule Account | |
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
# lib\account.ex | |
defmodule Account do | |
def start_link do | |
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 Account do | |
use GenServer | |
def start_link do | |
GenServer.start_link(__MODULE__, :ok) | |
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 Account do | |
# ... | |
def init(:ok) do | |
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 Account do | |
# ... | |
def init(:ok) do | |
{:ok, %{}} | |
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
# test\account_test.exs | |
defmodule AccountTest do | |
use ExUnit.Case | |
test "initial balance is zero" do | |
{:ok, pid} = Account.start_link | |
assert 0 == Account.get_balance(pid) | |
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
This is a list of code samples for my post about writing GenServers with TDD. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment