Elixir basics · Lesson 26 (open contents)
01 · Let the code speak02 · Meet six kinds of values03 · Put values together04 · Build a new list05 · Make the shapes match06 · Choose with case07 · Parse a number safely08 · Unpack &1 and the pipe09 · Put code in a project10 · Ask precise true-or-false questions11 · Read and update nested data12 · Count visible text and bytes13 · Let function clauses choose14 · Solve a list twice15 · Choose the smallest clear control form16 · Give domain data a shape17 · Put one tested module in Mix18 · Make success and failure predictable19 · Read and write one real file20 · Take only the data you need21 · Give different data one shared action22 · Write a callback contract23 · Write down the data contract24 · Test behavior and boundaries25 · Turn a project into a command26 · Write the project promise27 · Parse one real line28 · Keep the public API small29 · Make the promise executable30 · Package the edge and leave clues31 · Prove the project is done
ELIXIR · PROJECT · LESSON 2635 minutes

Write the project promise

Turn a vague log-cleaner idea into input, output, and error examples.

01 · Start with the whole example

Run this first

Run it once, change one input, and compare the new result.

Elixir
# Describe the project before implementing it
examples = [
  %{input: "  INFO ready  ", output: {:ok, {:info, "ready"}}},
  %{input: "", output: :skip},
  %{input: "BROKEN", output: {:error, :invalid_line}}
]

Enum.count(examples)
Check the result first
  • The brief contains three executable examples.
02 · Take the code apart

Read from the first line down

  1. Read %{input: ..., output: ...}: Store one executable example as data.
  2. Read :skip: Label a line the project intentionally ignores.
  3. Read :invalid: Label input the project must report.
03 · Meet the new symbols

Symbols are not secret signs

%{input: ..., output: ...}

Store one executable example as data.

:skip

Label a line the project intentionally ignores.

:invalid

Label input the project must report.

04 · Ideas inside the code

Match each name to its meaning

01

acceptance example

A concrete input and expected output makes a requirement testable.

02

scope

Scope lists what this project will and will not do.

03

invariant

An invariant is a rule that must hold for every accepted result.

05 · Make the idea clear

Why these forms are useful

Run the example first. Predict one result, then change one input and run it again.

A concrete input and expected output makes a requirement testable.

Scope lists what this project will and will not do.

06 · Change it yourself

Close the answer and try

Add an example for WARN hot.

Practice starting point
%{input: "WARN hot", output: ____}

Target result: Use {:ok, {:warn, "hot"}}.

Stuck? Read one hint

Keep the same tagged shape.

After you run it, see one answer
One answer
%{input: "WARN hot", output: {:ok, {:warn, "hot"}}}
Think about it: Why write examples before modules?

They keep implementation choices from changing the promised behavior.

Take with you

Remember these three lines

  1. 1

    Start with observable examples.

  2. 2

    Keep the first scope small.

  3. 3

    Write invariants before optimizations.

Lesson completeRun the code once, then mark this lesson as done.