Skip to content

Instantly share code, notes, and snippets.

@tomprogers
Last active June 1, 2021 04:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tomprogers/a5594cdb8fbe59e040dbcd89308d639b to your computer and use it in GitHub Desktop.
Save tomprogers/a5594cdb8fbe59e040dbcd89308d639b to your computer and use it in GitHub Desktop.
javascript coding guidelines

Javascript coding guidelines

These are listed in no particular order, but are numbered so they can referenced more easily.

  1. 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.
  2. Functions and methods should never mutate their arguments. Avoid patterns that rely on mutation of arguments.
  3. Prefer "flatter" codepaths. Nesting lots of if / else statements is hard to follow and re-organize. Bail early using return instead of nesting subsequent code.
  4. Prefer flat data structures instead of deeply nested objects.
  5. 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.
  6. 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).
  7. Express your intent as precisely as possible: haystack.includes(needle) is often better than haystack.indexOf(needle) >= 0, even though both will produce the same result.
  8. When throwing errors in JS, always throw a new Error( your_message ) (or something that inherits from Error) instead of throwing a plain string or object.
  9. 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 -- use momentjs or date-fns).
  10. Avoid any kind of "junk drawer": folders like utils & misc are junk drawers. Try hard to never even create those folders.
  11. Avoid generalizing too early. It is okay to duplicate a few lines of code verbatim.
  12. Perform appropriate logging. Many routines probably don't need fatal, error, warn, or even info, but almost every single routine should have debug and/or trace.
  13. New application code should be accompanied by new, relevant tests.
  14. Even in the absence of tests, code should be organized such that it is testable.
  15. Where appropriate, ensure that semver is respected.
@tomprogers
Copy link
Author

tomprogers commented Aug 8, 2020

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.

@tomprogers
Copy link
Author

tomprogers commented May 21, 2021

A codebase is easier to work with if it has adequate conventions, and they are applied extensively and rigorously. The things that matter most are all related to function signatures: what words make it into names, the order of those words, lettercase1, order of positional arguments, whether to use positional arguments or an options hash, whether arguments get mutated, whether to be async, how to report bad news (e.g. undefined vs null vs false vs throw for getters/finders).


1 The biggest problem with lettercase is not that devs can't agree on a general convention (e.g. pascalCase vs snake_case, etc.), it's that sometimes you panic when you discover you must weld together a name for concepts like these:

  • most recent ajax request = lastXhr ( or should it be lastXHR? holding Shift for three letters is actually mildly uncomfortable )
  • item does exist on at least one parent or child in a list of parents = isInAGroup ( olympicHurdler is faster, despite being longer, because there are fewer word breaks; not just because of Shift: type isinagroup and I bet you pause between each word )
  • has a record in the FBI database = hasFBIDBID ( it might be easier to use 🍓 )

So, there are some natural names out there that developers will avoid for reasons having nothing to do with software design or patterns or clarity. I believe probably the biggest culprit is the physicality of typing on a keyboard. Some things are actually tricky to type, and if feels kind of like a tire-hopping exercise. Others force your hands into positions that are very slightly uncomfortable, and although it is subtle, it can get to you over time. So, consider that every time you find you must invent a new name, in addition to the little angel and demon sitting on your shoulders, there is another demon sitting on your hands. It really does require a kind of daily discipline to insist just with yourself that you'll ignore what your hands complain about while you're writing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment