elixirian · elixir · recipes · pipelines

Elixiran | Recipes | Recipe 5: Use pipelining instead of nesting

Try to think about long flow as recipe of multiple steps and build a pipeline.


🍳 Recipe 5: Pipelines with Clean Function Chains

defmodule User do
  def process(data) do
    data
    |> normalize()
    |> validate()
    |> store()
  end

  defp normalize(data), do: String.trim(data)
  defp validate(data), do: if String.length(data) > 0, do: data, else: raise "Invalid"
  defp store(data), do: IO.puts("Saved: #{data}")
end


benefit 1: each stage in a pipeline can be inspected easily

data
|> normalize()
|> tap(&IO.inspect(&1, label: "After normalize"))
|> validate()
|> tap(&IO.inspect(&1, label: "After validate"))
|> store()


benefit 2: each function becomes a clean, composable step that: 1. Takes input 2. Returns output

This encourages writing pure functions and makes testing of each one easier.


benefit 3: functional thinking

Pipelines match Elixir’s functional model: 1. No mutation 2. No side effects (except at the end, like IO.puts) 3. Emphasis on transformation of data


benefi 4: scales better with more steps

imagine this:

data
|> step1()
|> step2()
|> step3()
|> step4()
|> step5()

vs

step5(step4(step3(step2(step1(data)))))

during reviewing code, pipelines help developers think in clean, linear transformations - and that’s a big win in Elixir


🔥 Real-world example

recipe 6, 1: cognito token example