Writing Clean Code
Code-in-the-small: how a single name, function, comment or error path is written so intent is visible at a glance. This is the material reviewers comment on daily and the level a take-home assignment is judged at.
part ofSoftware design & architectureoverview, primer and where to startread it →on this pageshowhide
explore
- Meaningful Naming6 questions
- Small Functions6 questions
- Comments and Documentation6 questions
- Formatting and Structure6 questions
- Cognitive Complexity & Readability6 questions
- Clean Error Handling6 questions
- Boundaries, Objects & Data Structures6 questions
questions
page 2 of 2Comments and documents drift out of sync with the code they describe. Explain the mechanism behind this drift and the techniques that keep explanatory material trustworthy over time.
basics
~20 sCode is verified by compilers and tests; prose is verified by nobody. So edits update the code and skip the comment, and the comment quietly becomes false. Fixes: fewer comments, put facts in code/tests/types, and review comments as code.
When should a function return a Result/Either type instead of throwing an exception, and what are the trade-offs of each style?
basics
~20 sThrow for unexpected failures the caller usually can't handle locally — bugs, infrastructure outages. Return a Result/Either when failure is an expected outcome the caller must decide about, because it puts the failure in the type signature and can't be forgotten.
What does file and function length tell you about a codebase, and why do experienced engineers treat a growing file as a design signal rather than a formatting problem?
basics
~20 sSmall files are easier to understand than large ones. A file that keeps growing usually means it has taken on several responsibilities, so the fix is splitting it up — not adding more comments, headers, or blank lines.
In what way is a hard-to-choose name design feedback, and what makes renaming expensive once an identifier has crossed a module or published-API boundary?
basics
~20 sIf you cannot name something without "And" or a vague word like "Manager", it probably does more than one job — the naming problem is really a design problem. Renaming is free inside a function, but a name in a public API, database column, event field, or metric is a contract others depend on.
How should a name's length and specificity relate to the size of its scope, and what makes a name "searchable" and "pronounceable"?
basics
~20 sThe further a name travels from its declaration, the more descriptive it must be. i is fine in a three-line loop; a module-level export needs a full phrase. Searchable means findable by text search — MAX_RETRIES can be found, 3 cannot. Pronounceable means you can say it aloud.
When does hiding an external dependency behind your own abstraction stop paying for itself, and how do you decide where to place - or not place - a boundary?
basics
~20 sA boundary pays off when the thing behind it is likely to change, is hard to test, or would otherwise spread everywhere. It stops paying when the abstraction just mirrors the dependency, when the dependency is a stable standard, or when its behaviour leaks through anyway.
How would you introduce complexity thresholds as a CI quality gate across a large legacy codebase without stalling delivery or provoking metric gaming?
basics
~20 sDo not fail the build on existing code. Freeze current violations as a baseline and enforce the threshold only on new and changed code, so the codebase improves as it is touched instead of demanding a big-bang cleanup.
You own engineering standards for a large multi-team codebase. How would you decide which knowledge belongs in inline comments versus other artifacts, and how would you keep TODO markers from decaying into noise?
basics
~20 sGive each kind of knowledge one home: code and tests for behaviour, comments for local why and hazards, commit history for change history, issue tracker for planned work, ADRs for decisions, generated reference for public APIs. Require TODOs to link an issue and expire them.
How would you design a consistent error-handling strategy across a multi-service system so failures are diagnosable, retryable where safe, and never silent?
basics
~20 sAgree one error taxonomy (client error / business rejection / transient infrastructure / bug), give each a stable code and a retryable flag, translate to transport in one place per service, log once with a correlation id, and make retries safe by requiring idempotency.
An experienced engineer joins a team whose committed formatting standard conflicts with their own strong preferences. How should this be handled, and what principle governs whose style wins?
basics
~20 sThe team standard wins. Code should look like one person wrote it, so personal preference gives way to the committed convention; if you disagree, propose a change to the standard rather than formatting your own files differently.
"Extract till you drop" produces very small functions. As a technical leader, how do you decide when further decomposition stops paying off, and what team-level policy do you set instead of a line-count rule?
basics
~20 sStop when a helper isn't a nameable concept — when its name just paraphrases the caller, it has one caller, or it needs many parameters to rebuild the caller's context. Set a policy on naming, cohesion, and abstraction level in review; use line-count linting only as a smell trigger, never as a gate.
showing 31–42 of 42