Skip to content

Latest commit

 

History

History
executable file
·
174 lines (120 loc) · 2.81 KB

Slides.md

File metadata and controls

executable file
·
174 lines (120 loc) · 2.81 KB

Offensive Programming

in Elixir with Uptight Library

Jonn Mostovoy

Serokell.io & Doma.dev


Let's talk about errors!

  • Recoverable (think Result<E, O>)
  • Irrecoverable (think panic!())

Fault-tolerant

  • Recoverable (think Result<E, O>)
  • Supervised (think throw-catch)

Fault-tolerant vs correctness

  • FT systems: survive the "chaos monkey"
  • Correct systems (?): evidence that "chaos monkey" won't happen

Correctness and complex systems

  • Complexity causes emergence
  • You can't precisely / statically analyse it

Offensive Programming

Fault tolerance maximised


Erlang's legacy

cat <<EOF | iex -S mix
File.read("flake.nix") |> elem(0)
EOF

Erlang's legacy: minimise data flow

  • Atoms encode into ints
  • Lightest error tagging under distribution
  • For most use cases it's a non-issue
    • (we wouldn't have been using HTTP then)

Erlang's legacy: nonsense

{:ok, {:error, "Something went wrong"}}

Erlang's legacy: cardinality

{:error, "Something went boom"}
{:error, "Something went boom", %{original :data}}
{:error, %{original: :data}}

Erlang's legacy: BOTH AT THE SAME TIME!

# Yes, this exists in the wild!
{:ok, %{error:
    %{reason: "something went boom",
      data: %{original: :data}}
}}

Elixir: Exceptions!

  • Exceptions are verbose
  • Allow access to stacktrace

Uptight

cat <<EOF | iex -S mix
File.read!("flake.nixx")
EOF

Uptight

cat <<EOF | iex -S mix
alias Uptight.Result
:erlang.system_flag(:backtrace_depth, 1)
Result.new(fn -> File.read!("flake.nixx") end)
EOF

Uptight: Functional

cat <<EOF | iex -S mix
use Witchcraft
alias Uptight.Result
import Witchcraft.Comonad

Result.new(fn -> 42 end)
~> (&(&1 + 1))
|> extract() == 43
EOF

Uptight: Monadic

cat <<EOF | iex -S mix
use Witchcraft
alias Uptight.Result
import Witchcraft.Comonad
:erlang.system_flag(:backtrace_depth, 1)

Result.new(fn -> 5 = 2 + 2 end)
~> (&(&1 + 1))
~> (&(&1 + 1))
EOF

Uptight: Budget-friendly

cat <<EOF | iex -S mix
alias Uptight.Result
import Uptight.Assertions
:erlang.system_flag(:backtrace_depth, 1)
Result.new(fn -> 
    assert match?(5, 2 + 2), "big brother is watching"
end).err.exception.message
EOF

Links