These are listed in no particular order, but are numbered so they can referenced more easily.
- No interface should accept data that is not necessary for it to do its job. "Interface" includes: HTTP APIs (e.g. REST), function & method signatures, and React Component props, among others.
- Functions and methods should never mutate their arguments. Avoid patterns that rely on mutation of arguments.
- Prefer "flatter" codepaths. Nesting lots of
if
/else
statements is hard to follow and re-organize. Bail early usingreturn
instead of nesting subsequent code. - Prefer flat data structures instead of deeply nested objects.
- If the majority of a routine is inside a loop, extract the core of the loop into a separate routine that operates on a single item.
- Extract magic strings and numbers from logic. At minimum, they should be declared as constants at the top of the file that uses them. Ideally, constants that influence observable behavior should be provided by a constants file (or environment variables, for Node/Electron).
- Express your intent as precisely as possible:
haystack.includes(needle)
is often better thanhaystack.indexOf(needle) >= 0
, even though both will produce the same result. - When throwing errors in JS, always throw a
new Error( your_message )
(or something that inherits fromError
) instead of throwing a plain string or object. - Always use the best tools available (e.g. don't write your own email validation regex -- use the already-installed
validator
library; don't write your own date logic -- usemomentjs
ordate-fns
). - Avoid any kind of "junk drawer": folders like
utils
&misc
are junk drawers. Try hard to never even create those folders. - Avoid generalizing too early. It is okay to duplicate a few lines of code verbatim.
- Perform appropriate logging. Many routines probably don't need
fatal
,error
,warn
, or eveninfo
, but almost every single routine should havedebug
and/ortrace
. - New application code should be accompanied by new, relevant tests.
- Even in the absence of tests, code should be organized such that it is testable.
- Where appropriate, ensure that semver is respected.
When I was a kid, I wished someone would tell me "how to program," just general rules of the road. Everybody had one of two answers: (A) read this 500-page book written by CompSci PhDs; or (B) there are no rules, write whatever works. After twenty years, I can confidently say both answers are BS.
The above list is guidance that applies regardless of the kind of application, the layers you need, etc. Most of them are relevant at and below the level of individual functions. They are all drawn from concrete cases I've encountered in the wild. If your functions are a mess, everything you do with them will also be a mess. These guidelines will help you keep your functions from becoming a mess.