Self-Documenting Code
Use of || / short-circuiting for control flow
- Many dislike patterns like
cond || throwError()in JS: seen as non-idiomatic, harder to read, and potentially dangerous due to truthiness (e.g., 0/""/false). - Some note this is common in shell/Ruby, but others respond that shell syntax is notoriously opaque and not a good readability model.
- Short-circuiting is generally seen as fine for a few conventional patterns (defaults, “cheap || expensive”, guarded conditions in loops), but controversial when used to encode primary control flow and exceptions.
- A minority say they’d get used to it if consistently applied, but most call it cleverness over clarity.
Self-documenting code vs comments
- Broad agreement that “self-documenting” really means “code that reads clearly,” not literally zero comments.
- Several argue all comments (including JSDoc) are a smell: they rot, are ignored by tools/people, and often cover for confusing code that should be refactored.
- Others push back: comments are essential for explaining why code is the way it is, documenting edge cases, hacks, business decisions, and serving as a “parity bit” to detect when behavior has drifted.
- Middle-ground view: comments should explain non-obvious logic and rationale; avoid narrating obvious code.
Types, TypeScript, and JSDoc
- Some see TypeScript (or strong typing in general) as the best form of documentation: machine-checked, close to the code, and more readable than JSDoc.
- Others criticize heavy JSDoc/“docstring for every function” styles as redundant boilerplate that no one maintains.
- There is concern that calling JSDoc-based static checking “self-documenting” contradicts the “no comments” ethos.
Password validation example & regex readability
- Many call uncommented regexes a “code smell” and advocate brief comments or mapping rule names to regexes.
- Suggestions include:
- Using named constants for rules.
- Refactoring to return specific failing rule or user-friendly error messages.
- Avoiding
\Wdue to subtle character-class issues.
- Some note the article “missed the opportunity” to better factor this example.
Function structure, abstraction, and early returns
- Disagreement on “tiny functions” vs single larger function:
- One camp prefers local booleans and fewer jumps, arguing too many helpers make control flow hard to follow.
- Another camp values small, well-named functions for abstraction, testability, and top-down understanding.
- Similar split on early returns vs
if/elsenesting:- Early-return proponents like linear “guard clauses” and a clear happy path.
- Critics warn that many return points can obscure which conditions apply at a given line.
Error handling and control flow
- Debate over using exceptions for expected conditions, like invalid user input:
- Some insist returning result objects/union types is superior and more type-safe.
- Others argue exceptions are fine for these errors and more ergonomic than error codes.
- Fail-fast styles are defended in some domains, but others warn about timing attacks and misusing abstractions like
throwError().
Broader reflections
- Several point out there is no universally self-documenting code; readability depends on audience, shared norms, and context.
- Multiple comments stress that naming and visual structure do matter, though some downplay their impact relative to domain complexity.
- A recurring theme: favor clarity over cleverness; refactor when feasible, but accept that comments and non-ideal structures are sometimes the pragmatic choice.