Problem Solving with Code
A repeatable process for turning real-world problems into working programs — without panicking.
In the previous page we met four mental moves: decomposition, pattern matching, abstraction, and algorithm design. This page turns those moves into a concrete, repeatable process you can apply to any programming problem, from a tiny exercise to a multi-week feature.
Most beginners get stuck not because they "can't program" but because they sit down in front of an empty editor and try to write the answer in one shot. There is a better way.
The five steps
- Understand — re-state the problem in your own words. List the inputs, outputs, and edge cases.
- Plan — sketch the algorithm in plain language or pseudo-code, before you touch the keyboard.
- Implement — write code in small increments. Run after each.
- Test — check the easy cases, the edge cases, the weird cases.
- Refine — clean up names, extract helpers, remove duplication.
Cycle through them. When a test fails, you go back to plan or implement. When the program works, you go to refine. Refine often exposes new things to test.
Worked example: shopping cart total with discount
Here is the problem we will solve, end to end, using the five steps:
Given a list of items in a shopping cart (each with a price and a quantity) and a discount code, compute the final total. Two discount codes are valid:
SAVE10for 10% off the subtotal, andFLAT5for $5 off the subtotal (but never below zero). Any other code (or no code) means no discount.
Step 1: Understand
Re-state the problem to yourself:
- Input: a list of
{ price, quantity }items, and a string (the discount code, possibly empty). - Output: a single number — the final total, in dollars.
What are the edge cases?
- The cart is empty.
- A quantity is zero (or negative? probably not allowed, but worth noticing).
- The discount code is not recognised.
FLAT5is applied to a tiny cart whose subtotal is below $5 — the total should be0, not negative.
Already, before writing any code, we have learned a lot about the problem. Beginners skip this step. Don't.
Step 2: Plan
Write the algorithm in plain English, indented like code:
function finalTotal(items, code):
subtotal = 0
for each item in items:
subtotal += item.price * item.quantity
if code == "SAVE10":
discount = subtotal * 0.10
else if code == "FLAT5":
discount = 5
else:
discount = 0
total = subtotal - discount
if total < 0:
total = 0
return totalThat is a complete plan. We have not used JavaScript syntax yet, but the shape of the program is decided.
Notice we did the decomposition (compute subtotal, then apply discount, then clamp at zero) and chose the right algorithm (loop and accumulate, conditional discount) before any keys were pressed.
Step 3: Implement (in small steps)
Now we type. But not all at once. We translate one chunk at a time and run after each. We start with the simplest piece: just the subtotal.
Run it. If the subtotal looks right, we move on. We add the discount logic:
We ran after each addition. That is the most important habit in this whole course. The smaller the gap between "wrote new code" and "saw it work", the faster you find bugs.
Step 4: Test the edge cases
Look at the output. Check every line against your expectations.
- Subtotal of the example cart:
2*10 + 1*4.5 + 5*1.2 = 30.5. ✓ SAVE10→ 10% off =30.5 - 3.05 = 27.45. ✓FLAT5→30.5 - 5 = 25.50. ✓FLAT5on a $2 cart → clamped to0. ✓- Unknown code → full subtotal. ✓
- Empty cart →
0. ✓
If any of those had been wrong, we would go back to plan or implement and figure out where the discrepancy is. That is the loop in the diagram above.
Step 5: Refine
The code works. Now, without changing its behaviour, we improve it.
- Extract the discount logic into its own function so the top-level reads more clearly.
- Extract the subtotal logic into its own function too.
Look at the new finalTotal. It reads almost like the original
problem statement: "compute the subtotal, work out the discount,
subtract, clamp at zero". That is what good code looks like.
Why refine matters
It is tempting to skip step 5 ("it works, move on"). Don't. Two big reasons:
- Refining makes future bugs visible. Clean code is easier to trace. When something breaks next month, you will silently thank past-you.
- Refining is how you learn. The very act of "this looks ugly — let me make it nicer" trains your taste. Over time, you will write the cleaner version on the first try.
When you are stuck
Sometimes a problem just doesn't yield. Some moves to try, in order:
- Re-read the question. Slowly. Underline every concrete noun and verb. Beginners often solve the wrong problem.
- Solve a smaller version first. Don't tackle "tax for any country and any product" — tackle "tax for one country and one product".
- Solve it by hand for one example. Take a single input and work out, on paper, exactly what the answer should be. Now your algorithm only has to do what your paper did.
- Add
console.logeverywhere. Print the values at every step. The bug is rarely where you think it is. - Explain it to someone (or something). Out loud. To a friend, a colleague, or a rubber duck. The act of explaining often reveals what you don't yet understand.
- Walk away. Take a five-minute break. Your brain finishes the work in the background more often than you would think.
Programming is mostly thinking, with a little typing on the side. If you are typing furiously and getting nowhere, stop typing.
A multi-file challenge
Real code lives in multiple files. Here is a challenge that uses the same shopping-cart problem, split into two files. Your job is to fill in the missing function.
The file cart.js defines finalTotal(items, code) partially — the discount logic is missing. Fill it in so the totals match what the tests expect.
The rules:
SAVE10→ 10% off the subtotal.FLAT5→ $5 off the subtotal, but never less than0.- Any other code (including empty string) → no discount.
According to this page, what is the most common mistake beginners make when given a programming problem?
They use the wrong text editor
They sit down and try to write the complete answer in one shot, instead of working in small understand → plan → implement → test → refine cycles
They use too many functions
They write too many tests