You're already doing TDD

Decision-making

Big decisions are combinations of small decisions

What meal should Ι eat?

Don't take my word for it

  • Descartes
  • Fermi

Cartesian method

  1. Accept as true only what is indubitable.
  2. Divide every question into manageable parts.
  3. Begin with the simplest issues and ascend to the more complex.
  4. Review frequently enough to retain the whole argument at once.

Fermi questions

break a big measurement into smaller estimatable measurements

How many piano tuners are there in Chicago?

Decompose

Number of pianos divided by number of tunings in a year

  • # pianos?
  • # pianos per tuner per day?

How many pianos?

  • # people in Chicago?
  • # people per household?
  • # households w/ regularly tuned piano?

how many pianos per tuner per day?

  • # hours per tuning?
  • # hours per tuner?

plug in some numbers

variable value
population 9M
people per household 2
houses w/ piano 20
hours per tuning 2
hours per tuner 50 * 5 * 8

mix it all up

Number of pianos divided by number of tunings in a year

9000000 / 2 / 20 / (50 * 5 * 8 / 2)

Boom

225

Decomposing

Good enough for Descartes

Good enough for Fermi

In programming

decomposition is called factoring

Refactoring

Yep. re-factoring.

Okay okay, TDD

Real talk now (wake up your neighbor)

Usual steps of TDD

  1. Write a failing test
  2. Make it pass
  3. Refactor
  4. Continue

So why are you already doing TDD?

  • break down problem into smaller parts
  • implement bits of it
  • connect the implemented bits
  • profit

Steps of Test-Driven Design

  1. Define non-existent behavior
  2. Write test
  3. Marie-Kondo the code you just wrote
  4. Think of how it will fail
  5. Run it, verify your hypothesis
  6. Implement just enough to make it pass
  7. Refactor as desired

Connecting the dots

  1. set our goal
  2. decompose (factor)
  3. choose the simplest issue
  4. review frequently enough to retain the whole argument

1. set our goal

  1. Think of the feature you want
  2. Write a test representing the feature

decompose & choose simplest issue

  1. Write a failing test for a small part of the feature

review frequently enough to retain the whole argument

  1. Verify that you know how it will fail
  2. Make it pass
  3. Optionally, refactor

And on and on we go

Decompose the problem, think about the implementation

You have to be able to refactor the implementation under test

Desired behavior

def test_same_modality
  one_mod = ["CR", "CR"]
  two_mods = ["CR", "CT"]
  assert same_modality?(one_mod)
  refute same_modality?(two_mods)
end

Years ago I wrote this

def same_modality?(documents)
  modalities = []
  documents.each do |document|
    unless modalities.include?(document.modality)
      modalities << document.modality
    end
  end
  modalities.size == 1
end

A year and a half later, I changed it to this

documents.map(&:modality).uniq.size == 1

Conclusion

Descartes invented TDD

Resources

Q&A

Aldric Giacomoni

@trevoke

Wake up your neighbor

Send flames to /dev/null