Plain-English Logic Is the Algorithm
"When adding a product: check whether it exists; if it exists, increase the quantity; otherwise create a new item." That is not a description of an algorithm you still have to find. It is the algorithm. If you can say what happens in numbered sentences, the hard part is done, and what remains is transcription.
The situation, the reflex, and why it stalls
Every lesson starts where being stuck starts: someone has a problem, and the first move that comes to mind feels like progress.
You can explain what "add to cart" does to a colleague in three sentences. Why does the code still feel out of reach — and what, exactly, is left to do?
You know the state and the operations. You could tell anyone how adding works: look for the product, bump it if it is there, otherwise put it in. And yet when you open the file, nothing comes — the gap between the sentences and the code feels like it needs something you do not have.
Search for "add to cart algorithm" or ask an assistant for the addItem function, because you assume there is a known algorithm for carts that you have not learned, the way there is one for sorting.
The search returns code, and the code does what your three sentences said — a find, a branch, an increment or an append. You had the algorithm; you went looking for it anyway, and now it is in someone else's words and you cannot tell whether their branch is your branch.
- The search returns code, and the code does what your three sentences said — a find, a branch, an increment or an append. You had the algorithm; you went looking for it anyway, and now it is in someone else's words and you cannot tell whether their branch is your branch.
- The assistant's function has a
find, and you do not recognise it as "check whether it exists" because you never wrote your sentences down in a form that could be lined up against code. The correspondence was there and nobody made it visible. - The feeling that something is missing does not go away, because the missing thing was never an algorithm. It was the habit of treating your own sentences as instructions rather than as commentary on instructions you had not found yet.
The move
Precisely enough to apply it to a problem you have never seen — not a slogan.
- Write the operation as numbered sentences in plain English, each sentence one step, each step something you could do by hand with a piece of paper and the cart drawn on it. The record's
addItem: check that the product exists; check that the quantity is positive; look for an existing entry with this product id; if one exists, increase its quantity; otherwise create a new entry; return the cart. - Then read the list as if it were code and notice that it already has code's three shapes: steps in sequence, a decision ("if one exists"), and a search ("look for"). Everything a program can do is one of a handful of shapes — do this then that, choose between paths, repeat over a collection — and the sentences have already chosen which ones this operation needs (Inputs, Outputs, State, Branches).
- Run the sentences by hand on a concrete example before touching a keyboard. Cart = [Laptop × 1]; add Laptop. Step 3 finds the entry; step 4 fires; the quantity becomes 2. If running the sentences by hand produces the
afteryour example said it should, the algorithm is correct, and the code cannot be more correct than that — only more precise (Predict the State Before Running the Code). - Recognise that what is left is transcription: each sentence becomes one to three lines in whichever notation you use next. The lesson after this one does the transcription into pseudocode; this one is about noticing that the transcription is the easy half, and that the sentences were the algorithm all along.
The sentences, run by hand
The record's plain-English steps for addItem, then one example run through them. The trace is the five stops every operation passes through, and every one of them is a sentence from the list — which is the whole claim: the list already has an input, a lookup, a branch, a mutation and an output.
- 1. Check that the product exists.
- 2. Check that the quantity is positive.
- 3. Look for an existing entry with this product id.
- 4. If one exists, increase its quantity.
- 5. Otherwise create a new entry with the given quantity.
- 6. Return the cart.
- inputproductId = laptop, quantity = 1 (the default); the catalog has laptop; steps 1 and 2 pass.
- lookupStep 3: look through the entries for one whose product id is laptop — the first entry matches.
- branchStep 4 against step 5: an entry exists, so step 4 fires and step 5 does not.
- mutationThe existing entry's quantity goes from 1 to 2; no entry is created.
- outputStep 6: the cart, now [ Laptop × 2 ] — which is exactly the after the example add-again wrote down.
What the by-hand run changed
The same run as a before/after, because the mutation is easier to see than to describe. The changed list is the check: if the hand-run had produced a second entry, the list would have said so, and the sentences — not the code — would have been wrong.
Cart = [ Laptop × 1 ]
Cart = [ Laptop × 2 ]
Asking for the algorithm you already have
The vague question sends the learner to a search box. The best form cannot be answered by a search, because it is about their own sentences — and it produces the observation that ends the search: the list has a lookup, a branch and a mutation, so it is an algorithm.
why The best form is answerable with paper and forces the learner to find the branch in their own words; the vague form assumes the algorithm is elsewhere and returns someone else's branch.
The implementation ladder
Concept, examples, pseudocode, code, tests, production — for the concept this lesson is about. Code is the fourth tab, not the first.
Shopping Cart = A temporary collection of products the user intends to purchase, held between browsing and checkout.
- Does a cart have identity? Yes, weakly. Two carts with the same items are still two carts, because each belongs to someone and will become a different order. It needs an id once it leaves memory; in memory the variable is the identity.
- Who owns it? A shopper — a logged-in user or an anonymous session. The owner is part of the state because "my cart" has to be findable again.
- How long does it exist? From the first add until checkout or abandonment. Whether it survives a reload, a closed browser or a login is not a property of the concept; it is a persistence decision made later, and each answer changes where the cart lives.
- Should it survive reload? Usually yes for a store, usually no for a demo. V1 in memory says no; V2 browser storage says yes on one device; V3 server storage says yes everywhere the user is logged in.
- Should it survive login? Only if an anonymous cart and a logged-in cart are merged — a rule that does not exist in V1 and appears as a modification later.
- itemscollection of CartItemkeepThe cart is its items; without them nothing else means anything.
- items[].productIdidkeepThe reference to what is being bought. The catalog owns the product; the cart only points at it.
- items[].quantityinteger > 0keepTwo laptops is one entry with quantity 2, not two entries — the rule "one entry per product" needs a quantity to hold.
- owneruser id or session iddependsSo the cart can be found again by the person it belongs to.
- items[].productNamestringderiveIt would be convenient to render the cart without a catalog lookup.
- items[].pricemoneydependsThe total needs a price per item.
- totalmoneydropEvery screen shows the total.
- currencycodedependsPrices need a currency to be added.
- createdAttimestampdropAbandoned carts might be expired or emailed about.
- update Add item — the updated cart
- delete Remove item — the updated cart
- update Change quantity — the updated cart
- read View items — the list of entries — product id and quantity — for rendering
- domain Calculate total — the sum of price × quantity over the entries
- delete Clear cart — the empty cart
- • Every quantity is greater than zero.
- • One logical entry per product.
- • The total is never negative.
- • An unknown product cannot be added.
- • Quantity cannot exceed available stock — if inventory is enforced here.
How to do it
Most important first.
- Number the sentences. A numbered list has an order and a count; a paragraph has neither, and code needs both.
- Make each sentence one step: one check, one search, one change. "Find the item and bump it" is two steps and hides the branch between them.
- Circle the words that are decisions ("if", "otherwise") and the words that are searches ("look for", "find"). Those are the branch and the lookup that the trace will make visible (Input → Lookup → Branch → Mutation → Output).
- Run the list by hand against the normal, edge and invalid examples (Normal, Edge, Invalid). A sentence that does not know what to do with the edge case is a sentence missing from the list.
- If a sentence is one you could not do by hand — "efficiently look up the entry" — it is not a step, it is a wish; ask what looking up means with the cart drawn on paper (Make It Smaller Until You Know How to Build It).
Worked on a concrete problem
The move has to produce something. This is what it produced.
- addItem, from the record: 1. check that the product exists; 2. check that the quantity is positive; 3. look for an existing entry with this product id; 4. if one exists, increase its quantity; 5. otherwise create a new entry with the given quantity; 6. return the cart. By hand on [Laptop × 1], add Laptop: 1 passes, 2 passes, 3 finds Laptop, 4 sets it to 2, 6 returns [Laptop × 2]. The example's
aftersays [Laptop × 2]. The algorithm is done. - changeQuantity, from the record: 1. find the entry; 2. if the new quantity is zero, remove the entry — a cart never holds a product with quantity 0; 3. if it is negative, reject; 4. otherwise set the quantity. Running it on [Laptop × 2], change to 0: step 2 fires and the cart is []. Note that step 2 contains a rule, and that the rule arrived in the sentence before any code could have encoded it.
- Search products by name, for contrast: 1. for each product in the catalog, 2. if its name contains what was typed, 3. keep it; 4. return what was kept. Four sentences, one loop, one branch — and the moment you ask "contains, or starts with?", you have found the operation's first real unknown, in English, before any code could hide it.
How you know it worked
What now exists that did not before, and what question you can now ask.
- The operation exists as a numbered list, each item something you could do by hand, and you have run it on at least one example and got the example's
after. - You can point at each sentence and name its shape — sequence, decision, search, repetition.
- The urge to search for "the algorithm" has gone, because you can see that your list is one.
The questions you can now ask
The field this whole domain exists for. After this lesson, these are the questions to put to an unfamiliar problem.
- ?Can I say what this operation does as numbered sentences I could carry out by hand on a drawing of the state?
- ?Which sentence is a decision, which is a search, and which is a change?
- ?Does running the sentences by hand on the edge example produce the after I wrote for it?
- ?What in the list is a wish rather than a step?
What can go wrong
- The sentences are written at the wrong altitude — "add the product to the cart correctly" — and are the operation's name restated, not its steps. A sentence you cannot do by hand is a heading.
- The list is written and then discarded when the code is typed, so the code has a branch the list did not and nobody notices the difference.
- Every operation is written as sentences including the ones that are one line —
clear: "replace the items with an empty collection" — and the ceremony makes the learner distrust the method on the ones that need it.
- Numbered sentences are slower than typing the function for an operation you have written many times, and on those they add nothing but a record.
- Plain English is ambiguous where code is not — "increase its quantity" by one or by the given quantity? — and the ambiguity is resolved by the example, which means the example has to exist.
- An operation whose sentences are correct can still be implemented wrongly; the method finds algorithmic mistakes, not typos, and the tests are still needed.
- "There is no algorithm for a cart, so this does not apply to real algorithms." A cart's add is find-then-increment; binary search is halve-then-compare; both are numbered sentences. What the learner calls "real algorithms" are the ones whose sentences someone else already wrote down and named.
- "If I can explain it I can code it." Precise only if the explanation is numbered steps you could do by hand. "The cart keeps one entry per product" is an explanation and not a step; the falsifiable version is "if I can do it by hand, step by step, on paper, I can transcribe it."
- "Plain English first means comments first." Comments describe code that exists. The sentences here exist before the code and are what the code is checked against — and if they survive as comments afterwards, that is a side effect, not the purpose.
Where this applies
Problem-solving advice is stated as universal far more often than it is. These labels say what each method is specific to — and where CONTESTED appears, the note gives the strongest form of the opposing view.
- GENERALEvery operation on every concept can be written as numbered, hand-executable sentences before it is code; a rate limiter's "count the requests in the window; if over the limit, refuse" is the same move as the cart's add.
- TEAM-SPECIFICA learner needs the list on paper and the hand-run; an engineer who has written the operation before does both silently and the visible artefact is the pseudocode. The move is the same, the amount written down changes with how new the operation is.
- ILLUSTRATIVEThe Laptop, its quantities and the four-sentence search are the concept record's invented example; no real store or catalog is described.
Where the depth lives
This domain asks the question and hands the answer off by name.