Incremental Problem Solving

Expected level: Proficient

Incremental problem solving means breaking a large task into small steps, each of which you can finish and verify before taking the next. You always keep a working state and always know which step introduced a problem.

The loop

Instead of writing a whole feature and then seeing whether it works, repeat a short loop:

  1. Choose the smallest next step that moves you forward.
  2. Make it.
  3. Check that it works, by running the code, a test or a manual check.
  4. Commit, then choose the next step.

If a step fails, the cause is almost certainly in the few lines you just wrote.

Breaking a task down

  • Start with the goal, and write it as something you can observe: “the endpoint returns the invoice as JSON”.
  • List the steps needed, then order them so that each one can be checked on its own.
  • Do a thin vertical slice first. Get a minimal version working from input to output, then widen it. This is often easier than perfecting one layer at a time.
  • Make the hard or risky part small and early. If you are unsure whether an approach works, try it in a tiny experiment before building around it.
  • Keep different kinds of change apart. Do not mix refactoring, new behaviour and formatting in one step. See Refactoring Basics.

Techniques that support it

  • Write the test first or along the way. A failing test defines the next step, and a passing one confirms it. See Unit Testing.
  • Return hard-coded data from a stub first, and replace it with the real source once the surrounding code works.
  • Commit after each working step, so you can return to a good state. See Commit Hygiene and Undoing Mistakes.
  • Open small pull requests. They are reviewed faster and more carefully. See Pull Requests and Code Reviews.
  • Keep a short to-do list so that interruptions do not cost you your place.

When you are stuck or debugging

The same approach applies to a problem you do not understand. Reduce it: get a smaller input to fail, remove code until the error vanishes, or build the simplest possible version and add things back. See Debugging Fundamentals.

Ways it goes wrong

  • A “small” step that takes a day. Split it again.
  • Building features that nobody asked for because you might need them later.
  • Not checking after each step, which brings back the big-bang problem.
  • Skipping the plan completely and wandering. A few minutes of breakdown is enough.

Try it

Choose a small feature, for example a command that reads a text file and prints the ten most common words. Write down at least five steps, each with a way to verify it (such as reading a file and printing the line count). Implement them one at a time, committing after each. Notice where a step had to be split.

Common mistakes

  • A small step that takes a day; split it again.
  • Building features nobody asked for because you might need them.
  • Not checking after each step.
  • Skipping the breakdown and wandering.

Check yourself

  • What are the four steps of the loop?
  • What is a thin vertical slice?
  • Why commit after each working step?

Related topics

Terms

Further reading