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.
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.
`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.
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) }`.
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.
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.
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.
`processShipment()` is 340 lines. The team standard is forty lines per function and the linter now fails the build. Split it.