Overview
Every per-language page in coding/ assumes these rules. When a language page contradicts one, the language page wins for that language. Start here, then read python, typescript, swift, pine-script, or shell.
Name things with specific nouns and units
A name says what the value is, not its category: activeUserIds, not data; retryBudgetMs, not timeout; parseInvoiceXml, not process. Spell words out; keep only abbreviations the field already uses (id, url, http, db). If a comment restates a variable, rename the variable and delete the comment. File naming rules are in naming-conventions.
Comment the why, never the what
Comments carry what the code cannot: why the constant is 7, why a branch exists (the upstream API returns null on Wednesdays), why the obvious version was rejected. Delete comments that paraphrase the next line. If a block needs a “what” comment to be readable, extract a named function instead.
Handle errors at boundaries
Internals raise; boundaries catch, log with context, and translate into something the caller can act on. A request handler, queue worker, CLI entry point, or UI event handler is a boundary. A try in the middle of business logic that swallows the exception and returns null is the source of silent production bugs: either the caller can recover, or the error propagates.
Vet a dependency before adding it
- Check the last release date, open issue count, and who maintains it.
- Check install size and the transitive tree; a small package that pulls dozens of others is supply-chain surface.
- If you need one small function, copy it with its license and skip the dependency.
- Commit the lockfile, and land Renovate or Dependabot updates as separate PRs with the changelog summarized.
Test four cases for every function worth testing
- Golden path: typical input, expected output.
- Empty: empty string or list, zero,
None/null/nil. - Boundary: maximum length, off-by-one, month rollover.
- Error: bad input, missing field, upstream timeout.
A suite that covers only the happy path covers nothing; coverage percentage is not the bar. Test strategy is in testing.
Delay abstraction until the third use
Two callers of similar code do not need a shared abstraction. When the third arrives, extract the shape the three actually share, not the one you imagined. Premature abstraction locks in the wrong shape before the real one is known.
Measure before optimizing
Write the obvious version, profile under realistic load, and optimize the one hot path the profile shows. Measure again afterward to confirm the change helped. A cleverer loop or a hand-rolled cache on a cold path costs readability and ships bugs.