From English to Pseudocode
The six sentences become eight lines. "Look for an existing entry with this product id" becomes item = find entry in cart.items with item.productId == productId; "if one exists, increase its quantity" becomes if item exists: item.quantity = item.quantity + quantity. Side by side, every line has a sentence and every sentence has a line — and the places where the line had to say more than the sentence are where the operation was underspecified.
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 have the numbered sentences. How do they become pseudocode — and what does the transformation reveal that the sentences hid?
Your list is on paper: check, check, look for, if, otherwise, return. You believe it. Now you have to write something the shape of code, and the first sentence — "look for an existing entry" — turns out to have three things in it you had not named: which collection, which field, and what "found nothing" looks like.
Skip pseudocode as a formality and go straight to TypeScript, because pseudocode is "just code with worse syntax" and the compiler will catch what the sentences missed.
The TypeScript arrives with the language's decisions in it — find returning undefined, === on strings, push mutating in place — and the learner cannot tell which of those were the operation's decisions and which were the language's. When they later write it in Python, undefined has no counterpart and they do not know whether that matters.
- The TypeScript arrives with the language's decisions in it —
findreturningundefined,===on strings,pushmutating in place — and the learner cannot tell which of those were the operation's decisions and which were the language's. When they later write it in Python,undefinedhas no counterpart and they do not know whether that matters. - The compiler catches type errors and says nothing about the sentence "increase its quantity" meaning by one or by the given amount. That ambiguity was in the English, it survives into the code, and the test that would catch it has not been written because nobody noticed the sentence was ambiguous.
- Without the intermediate, nothing lines up: sentence 3 is now two lines and a type annotation, and the correspondence — which is what would let a reader check the code against the meaning — is gone.
The move
Precisely enough to apply it to a problem you have never seen — not a slogan.
- Transcribe sentence by sentence, keeping the numbering. Each sentence becomes the fewest lines that say the same thing in a notation with code's discipline — named values, explicit conditions, explicit collections — and no language's syntax. The record's pseudocode for
addItemis eight lines for six sentences, and every line can be traced to its sentence. - Where a sentence turns into more than the line can carry, stop: that is the transformation doing its job. "Look for an existing entry with this product id" has to name the collection (
cart.items), the field (item.productId), the comparison (== productId) and the result when nothing matches (item existsis a question the next line asks). Each named thing is a decision the sentence had left to the reader. - Where a sentence is ambiguous, the pseudocode has to choose, and the example decides. "Increase its quantity": the example add-again with the default quantity gives 1 → 2, and adding Laptop × 3 to [Laptop × 1] should surely give 4, so the line is
item.quantity = item.quantity + quantity. The choice is written into a line rather than left in a sentence (Examples Before Algorithms). - Keep the sentences beside the lines. The point of pseudocode is that it can be read against the English and the English against the examples; the moment the code exists, the pseudocode is the bridge a reviewer walks across to check that the function does what the operation means (Pseudocode as a Thinking Tool).
Side by side
The record's plain-English steps on the left, its pseudocode on the right. The two are aligned by sentence number so that a reader can walk across: the three places where the right column says more than the left are the transformation's findings, and each is a decision the sentence had left open.
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.
function addItem(cart, productId, quantity = 1):
if not catalog.has(productId): reject "unknown product" -- 1
if quantity <= 0: reject "quantity must be positive" -- 2
item = find entry in cart.items -- 3: which collection
with item.productId == productId -- which field, which comparison
if item exists: -- 4: the not-found case, asked
item.quantity = item.quantity + quantity -- by the given quantity, not by 1
else:
append { productId, quantity } to cart.items -- 5
return cart -- 6The right column is not better code than the left is prose — it is the same algorithm with its open decisions closed: the collection and field that "look for" hid, the not-found case that "if one exists" implied, and the amount that "increase" did not specify. Each closed decision is checkable against an example, which the sentence was not.
The line that had to choose
"Increase its quantity" is the sentence that most often goes wrong in transcription. The before/after is the example that decides it — with a quantity of 3 rather than the default, because the default cannot tell + 1 from + quantity.
Cart = [ Laptop × 1 ]
Cart = [ Laptop × 4 ]
item.quantity + quantity, not + 1 · Number of entries: unchanged — the find succeeded, the append did not fire · What a + 1 transcription would have produced: [ Laptop × 2 ], and a shopper who asked for threeTranscription as a pipeline
The move as a sequence, with the way each step fails. The fourth step is the one that makes pseudocode more than a formality; a transcription that never stops has found nothing.
- 1Number
The sentences carry numbers; the lines will carry the same numbers as comments.
fails by A paragraph, transcribed as a whole, with no way to check coverage.
- 2Transcribe in order
Each sentence becomes the fewest lines that say the same thing with named values and explicit conditions.
fails by Reordering or merging on the first pass, so a sentence disappears and its reason with it.
- 3Name what was implied
"Look for" gets a collection, a field, a comparison and a not-found; "increase" gets an amount.
fails by Writing the line in a real language, whose defaults fill the gaps silently.
- 4Stop at every choice
Where the line says more than the sentence, find the example that decides it and write it beside the line.
fails by Choosing by habit; the
+ 1that nobody tests. - 5Run by hand
The same example the sentences were run on, expecting the same after.
fails by Trusting the transcription because it looks like code.
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.
- One sentence, one block: transcribe in order and do not reorder until the whole list is transcribed — reordering is a second pass with its own reason (From Pseudocode to Code).
- Name every collection, field and comparison the sentence implied. "Look for" always hides a where, a what and a not-found.
- When a line has to choose, write the example that decided it as a comment on the line.
+ quantity -- add-again: 1 → 2 with the default. - Use the same handful of words for the same shapes:
find … with …,if … exists,append … to …,reject "…". Consistency is what makes pseudocode readable without a definition (Language-Neutral Pseudocode). - Run the pseudocode by hand on the same example the sentences were run on, and confirm the same after (Predict the State Before Running the Code).
Worked on a concrete problem
The move has to produce something. This is what it produced.
- Sentence 3, "look for an existing entry with this product id", became
item = find entry in cart.items with item.productId == productId. Four things named that the sentence did not: the collection, the field, the comparison, and a name for the result. Sentence 4, "if one exists", becameif item exists:— the not-found case, which the sentence implied and the line has to ask about. - Sentence 4's "increase its quantity" became
item.quantity = item.quantity + quantity, not+ 1. The example that decided it: add-again with the default gives 2; a shopper adding three at once would expect the three to be added. The English was ambiguous; the line is not; and the example is the reason someone could read. - removeItem, whose sentences were "find the entry; if it is there, take it out; if not, nothing happens", became a single line:
cart.items = every entry in cart.items whose productId != productId. Three sentences collapsed into one filter — and the collapse is correct only because V1 chose no-op for the absent case; had it chosen an error, the find and the branch would have had to stay.
How you know it worked
What now exists that did not before, and what question you can now ask.
- Every line of pseudocode has a sentence number beside it, and every sentence has at least one line.
- The places where a line says more than its sentence are marked, and each carries the example that decided it.
- The pseudocode was run by hand on the edge example and produced the same after as the sentences did.
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.
- ?For each sentence, what collection, field, comparison and not-found case did the line have to name?
- ?Where did a line have to choose something the sentence left open — and which example made the choice?
- ?Can the pseudocode be read back into the sentences without loss?
- ?Which lines are the operation's decisions and which are the notation's?
What can go wrong
- The pseudocode is written in TypeScript with the semicolons removed, and the language's decisions —
undefined,===, in-place mutation — enter under the name of neutrality. - The transformation is done and the ambiguities it exposed are resolved by whatever felt natural rather than by an example, so the line commits to
+ 1and the test for adding three is never written. - Sentences are merged during transcription "to be efficient", and the correspondence is lost; three sentences became one filter for a reason (no-op on absent) that the merged line no longer records.
- An intermediate representation is one more artefact to keep in step with the code, and on a team that never reads it, it decays into a lie about what the function does.
- Transcribing sentence by sentence produces pseudocode that is longer than the idiomatic code — the filter in
removeItemshows how much shorter the real thing can be — and a learner may conclude that pseudocode is always verbose. - Pseudocode has no compiler; an error in it is found by hand-running, which is slower and less reliable than a type check on the real thing.
- "Pseudocode is code with worse syntax, so skip it." It is code without a language's decisions, which is exactly what lets you see the operation's decisions. The slogan is precise only for an engineer who can read the language's decisions out of real code on sight — and that skill is what the learner is building.
- "The compiler catches ambiguity." It catches inconsistency between what you declared and what you wrote.
+ 1and+ quantityboth typecheck. - "Once the code exists the pseudocode is dead." It is the map from meaning to code; the code can be regenerated from it in any language, and the sentences can be checked against it by someone who does not read the language. It dies only if nobody walks across it.
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.
- GENERALSentence-by-sentence transcription into a language-neutral notation, stopping wherever a line has to say more than its sentence, works for any operation on any concept; the four hidden things in "look for" — collection, field, comparison, not-found — are the same four in a search, a login or a queue.
- TEAM-SPECIFICSolo and learning, the pseudocode is written out; on a team with a shared notation and reviewers who read it, it is often the thing under review rather than the code; on a team that never reads it, it is better skipped than left to rot.
- ILLUSTRATIVEThe six sentences, eight lines, Laptop quantities and the shopper adding three at once are the concept record's invented example; no real store is described.
Where the depth lives
This domain asks the question and hands the answer off by name.