Programming, Design, Engineering
Three questions, three levels: can I make it work (programming), can I structure it clearly (design), can it operate in a real system (engineering). The domain's three stages — Discover, Implement, Engineer — and the fuller path Discover → Model → Implement → Engineer → Operate.
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 been "learning to code" for months and still cannot build the feature you want. Which level are you actually stuck at, and what does each level need from the one below it?
You can write loops and functions, you have finished a course, and you cannot make a cart that survives a reload and does not duplicate entries. Everything you know feels one level too small, and every tutorial feels one level too big. It is not clear which thing to learn next, because it is not clear which thing is missing.
Learn another course, one level up: a framework course, then a system-design course, on the theory that the higher level will make the lower ones make sense. Or one level down: more algorithms, on the theory that the foundations are the gap.
The framework course teaches structure for behaviour you have not derived, so you learn where to put a cart reducer without knowing what "add" should do when the product is already there.
- The framework course teaches structure for behaviour you have not derived, so you learn where to put a cart reducer without knowing what "add" should do when the product is already there.
- The system-design course teaches operating a cart that does not exist; you can discuss sharding carts by owner and cannot write the find-and-increase.
- The algorithms course teaches the primitive — a linear scan — without the concept that needs it, so the scan is memorised and never recognised when it is the thing addItem requires.
- Months pass at the wrong level, with a growing sense that the problem is ability, when it is the sequence.
The move
Precisely enough to apply it to a problem you have never seen — not a slogan.
- Separate three questions and answer them in order. Programming: can I make it work — can I write addItem so that the six examples pass? Design: can I structure it clearly — are the state, operations and rules named so that another person, or you in a month, can find and change them? Engineering: can it operate in a real system — does it survive, is it reachable, does it fail safely, can it be trusted? Each level takes the previous one's output as its material.
- Locate yourself. "I can make it work but cannot explain the structure" is a design gap; "I can explain the structure and it works in a test but not in the app" is an engineering gap; "I cannot make it work" is a programming gap — and the programming gap is closed by making the thing smaller, not by learning a higher level.
- Map the levels onto the domain's stages. Discover — "I don't know what I need" — precedes all three. Implement — "I know what I need but not how to code it" — is programming and most of design. Engineer — "I can code it but not make it production-ready" — is the rest. The fuller path is Discover → Model → Implement → Engineer → Operate: modelling is the state/operations/rules work that sits between knowing and coding, and operating is what happens after shipping.
- Learn at the level of the gap, and only what the gap needs. A programming gap in addItem needs arrays, iteration and comparison — not a framework. A design gap needs the rule → validation → code chain, not architecture. An engineering gap needs persistence and an API for *this* cart, not a distributed-systems syllabus.
The three levels, as a ladder
Each level exists because the one below it produces something the one above needs. A design without a working operation structures nothing; an engineering step without a design has nothing to persist except fields nobody challenged.
- Programming — can I make it work?addItem over an array; the add-again and invalid-zero examples pass. — Everything above is structure and environment for a behaviour; the behaviour has to exist first.
- Design — can I structure it clearly?State named and challenged; operations with contracts; each rule with its validation and its line. — Engineering moves rules to places that enforce them — a constraint, a route — which requires knowing where the rules are.
- Engineering — can it operate in a real system?Browser storage, then the API and the rows with a unique constraint, then the stock check. — The cart must survive, be reachable and be trusted, and each of those is a requirement that arrives with real use.
The domain's stages, and the fuller path
The three stages are what the home page says; the five-step path adds the two that are easy to forget. Model is the work between knowing what you need and writing code — this whole track. Operate is what happens once shoppers are using it.
- 1Discover
"I don't know what I need." Framing, requirements, decomposition — the first thirty-three modules.
fails by Building a cart for a store that turns out to need a quote request.
- 2Model
Meaning, state, operations, rules, examples, representation — the cart as a page of English.
fails by Code with fields nobody challenged and rules nobody can locate.
- 3Implement
Pseudocode, one operation, tests from the examples.
fails by A class with methods whose bodies were guessed.
- 4Engineer
Persistence, API, where the code lives, frontend, failure handling.
fails by A cart that works in a test and vanishes on reload.
- 5Operate
Stale products from storage, abandoned carts, the two-tab race — seen in use and fed back.
fails by Nobody notices the duplicate rows until the support ticket.
The arrows go forward and back. A requirement discovered in Operate — merge carts at login — re-enters at Model as a new operation with a new rule.
Locating the stuck
The same sentence from a learner decomposes into a question per level, and each question has an observation that would show it answered. The leaf you cannot pass is the level you are at.
- ├Programming— can I make it work?
- └One operation passes its examplestestable addItem over an array passes add-first, add-again and invalid-zero as tests.
- └The missing primitive is namedtestable If it does not pass, the stuck names a primitive — find in a list, compare ids — not "the cart".
- ├Design— can I structure it clearly?
- └Every rule has an addresstestable For "one entry per product", you can point at the line and say what breaks if it is removed.
- └Every field has a readertestable For each stored field, an operation that reads it is named; total and productName are absent with reasons.
- ├Engineering— can it operate in a real system?
- └It survives the requirement that arrivedtestable After a reload, the cart shows the same items; the persistence level is named and its cost written down.
- └Its rules hold at the boundarytestable POST /cart/items with quantity 0 returns 400 naming the rule; two tabs adding Laptop leave one row.
Most "I can't build a cart" is one failed leaf under Programming, and the fix is a primitive — not a course.
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.
- Before choosing what to learn next, write the feature you cannot build and the sentence that describes the stuck: "it works but I can't explain it" / "I can't make it work" / "it works in a test but not in the app".
- Answer the programming question with one operation and its examples (Implement One Operation).
- Answer the design question by naming state, operations and rules where they can be found — the feature worksheet is the minimum (Operation Contracts).
- Answer the engineering question by the requirement that forced it, one level at a time (Implementation Is Not Engineering, The Cart Disappears).
- When the programming question stalls, go down the ladder rather than up the syllabus (Go One Primitive Lower, When the Rung Below Is a Foundation).
Worked on a concrete problem
The move has to produce something. This is what it produced.
- The cart at the programming level: addItem, removeItem, changeQuantity, getItems, total, clear over { items: [] }; the tests from add-again, invalid-zero and to-zero pass. "Can I make it work?" — yes, in an afternoon, once the examples existed.
- At the design level: the state is a list of { productId, quantity } and nothing else, with the reasons for dropping total and productName written down; each operation has inputs, reads, changes, output, errors; each rule has a validation and the line that encodes it. Someone reading the file can find where "one entry per product" lives — the find before the push — and what breaks if it is removed.
- At the engineering level: V2 serialises to browser storage; V3 puts the same functions behind GET /cart and POST /cart/items with cart_item rows and a unique (cart_id, product_id) constraint; V5 asks inventory at add and again at checkout. Each level was triggered by a requirement — reload, trust, stock — and none changed the programming-level functions.
- The learner's actual stuck, located: "I can't make add not duplicate" is programming, and it dissolves at the example "[ Laptop × 1 ] + Laptop" plus a linear scan. No framework course was needed; one primitive and one example were.
How you know it worked
What now exists that did not before, and what question you can now ask.
- You can say which of the three questions you are currently unable to answer for the feature in front of you.
- The next thing you learn is named by the gap, and it is small — a primitive, a device, one persistence level.
- A working operation exists before any structuring; a structured concept exists before any engineering.
- The stages Discover / Implement / Engineer describe where you are in the project, not how good you are.
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 make it work — is there one operation with examples that pass?
- ?Can I structure it clearly — could someone else find where each rule lives?
- ?Can it operate in a real system — what requirement is forcing the next engineering step?
- ?Which stage am I in — Discover, Implement or Engineer — and what does the previous stage owe me that I do not have?
What can go wrong
- Levels are treated as ranks. "I am at the engineering level" becomes an identity, and the engineer who cannot write the scan avoids the programming question instead of answering it in a minute.
- The design level is skipped because the code works. It works until someone asks where the rule lives, and the answer "somewhere in add" is the start of the duplicate bug's second life.
- Operate is forgotten. The path ends at "shipped", and nobody asks what a stale product in a stored cart does to a real shopper until the support ticket arrives.
- The model is used to dismiss whole domains: "system design is engineering, I am at programming, so I ignore it". The point is order, not omission.
- Answering the three questions in order is slower than one full-stack tutorial for a feature the tutorial happens to cover.
- Locating the gap honestly can mean going back to arrays after months of "learning React", which feels like regression and is not.
- A three-level model is a simplification; real work interleaves the levels, and the model is for finding the stuck, not for scheduling the week.
- "Programming is the beginner level, engineering is the senior level." Seniors answer all three for every feature; they answer the first two so fast that only the third is visible.
- "Design means design patterns." Design here means state, operations and rules named where they can be found; patterns are one vocabulary for the structuring, and the cart needs none of them.
- "Discover / Model / Implement / Engineer / Operate is a project plan." It is a way of locating yourself. A feature can be in Operate while its next requirement sends part of it back to Discover.
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.
- GENERALCan I make it work, structure it, operate it — the three questions apply to any feature in any stack; the stages are how this domain sequences them.
- SIMPLIFIEDThree levels and five stages are a teaching model; real work interleaves them constantly, and the model deliberately leaves out testing, review and team process as separate concerns.
- ILLUSTRATIVEThe learner, the months and the course are invented for the argument; the cart's V2, V3 and V5 are the concept record's own versions.
Where the depth lives
This domain asks the question and hands the answer off by name.
- — The manifesto's layers page at /manifesto/layers is the Engineer and Operate stages drawn as a stack — read it once the programming and design questions are answered for the cart.