Iterative Development
Implementation order, dependency-first and value-first, architecture that emerges from requirements, and the complexity ledger every new component must answer.
Change → run → observe → fix, in loops small enough that each one teaches something. A system is grown from one that already works; scale is added after a working system and a measured bottleneck, not before either exists.
Product model → display products → cart → checkout without payment → order persistence → payment → failure handling → admin: one defensible sequence for the store, with the reason for each step. Not the only sequence — and the device says so.
If B requires A, build or understand A first. Obvious when said, skipped constantly in practice: checkout built before the cart exists, payment integrated before anyone knows what an order is, a feature started on top of a concept nobody has understood.
When the dependencies permit, build the thing a user could actually use. A store that shows products and takes orders without payment is usable in a way that a perfect cart on top of nothing is not. Contested — against building the riskiest thing first — and this lesson says how.
Need persistence → a database. A browser interface → a frontend. Logic the client must not control → a backend. Payment → an external provider. Result: Browser → Backend → Database, plus the provider. Every box has a requirement that put it there, and no box is there without one.
Single server and database. Repeated expensive reads → maybe a cache. Long-running work in the request → maybe a queue and a worker. Each "maybe" waits for the symptom it treats; complexity should have a reason, and the reason should be something you observed.
Every new component answers three questions in writing: what problem does it solve, what complexity does it introduce, what happens if it fails. A component that cannot answer all three is not yet justified; one that can is accountable for as long as it lives.