Software design practice

Each challenge is a brief someone could plausibly hand you — a product manager, a retro, a support escalation, a pull request — followed by what is actually going on underneath it. Decide what you would do before you open anything else, and read the trap on every single one, because the trap is the fix that looks like good design and leaves the real problem in place.

The Third Argument Is `true`Naming

A helper is called as `notify(user, true, false, true)` in about fifty places. Nobody reading a call site can tell what any of it means without opening the function. Make the call sites readable.

The 1,400-Line `utils.ts`Smells

`utils.ts` is 1,400 lines and imported by every module in the codebase. It holds date formatting, a currency rounder used by invoicing, a retry wrapper, an email validator, a deep clone and a function called `process`. Two engineers added to it this week. Clean it up.

The Import Job That Always SucceedsErrors

A nightly patient-record import reports success every night. Downstream teams have been working from data that turned out to be missing three weeks of records. Each record is processed inside `try { ... } catch (e) { logger.debug(e) }`.

Cancelled And CompletedState

An `Appointment` row carries `isConfirmed`, `isCancelled`, `isCompleted` and `isNoShow`. A monthly report shows appointments that are both cancelled and completed. Finance asks which number is real.

The Test That Only Fails On The 31stEffects

One test in the billing suite fails when CI happens to run in the last hour of the last day of a month. It passes on every developer machine. The team has re-run the pipeline twice and moved on.

The Comment That Has Been Wrong For Two YearsDocs

A method carries `// Retries 3 times with exponential backoff`. It retries five times, linearly. A change two years ago altered the code and not the comment. A reviewer asks you to correct it.

The 340-Line Function And The 40-Line RuleRefactoring

`processShipment()` is 340 lines. The team standard is forty lines per function and the linter now fails the build. Split it.