💭 Coding Style
Coding style is the “look and feel” of the code that we write. It is a personal preference, and people rarely have exactly the same preferences.
Thanks to style guides (e.g. Swift API Design Guidelines ) and formatters (e.g. Prettier ), we can avoid lengthy debates over code style in code reviews.
Below is the coding style that I use in my personal projects and when there are no conflicting team rules.
Principles
- Be Precise, yet Concise; Value Clarity over Brevity.
- For APIs (functions, etc.), prioritize Clarity at the Call Site.
- Avoid noise and low or no value chores, in code and future change diffs.
General
File Structure
There are two popular flavors on file structure:
- Grouping by file type (
src/ & test/
,models/ & controllers/
,components/ & hooks/
, etc.) - Grouping by features (colocation)
I prefer colocation, “things change together are placed close to each other.”
The file nesting feature from JetBrains IDEs makes the experience even better with colocation.
Naming
My favourite style guide on naming is from Swift API Design Guidelines . There is one thing that I do differently:
Acronyms and initialisms that commonly appear as all upper case in American English should be uniformly up- or down-cased according to case conventions:
I find camelCase
easier to read when the acronym isn’t the last word,
particularly when one acronym follows another.
JavaScript / TypeScript
Prettier
Configurations I prefer over the defaults:
These are mostly personal preferences, but also to avoid “noise and chores”, or as Kent C. Dodds puts it in his words , to avoid “babysitting”.
let v.s. const
I used to prefer-const for many years, like most of the others. However, after reading const-antly Confused from the book You Don’t Know JS Yet , I reflected on my own code and realized that it has little value for me, but sometimes add noises:
- Cause Prettier to break lines when
let
could fit the code in one line. - Need to change
const
tolet
when needed to reassign later. Especially annoying when the variable is in destructuring.
So I now use let
by default and only use const
for true “constants”.
== v.s. ===
Another rule I used to follow until read the book
You Don’t Know JS Yet
was eqeqeq ,
“Require the use of ===
and !==
”.
After reading Type Aware Equality ,
I realized that in most cases, x === y
logically equals to
typeof x == typeof y && x == y
. Interestingly,
eqeqeq has a “smart” option ,
in which you can use x == y
when it is clear whether typeof x == typeof y
.
When use TypeScript
, it is clear most of the time.
So the extra =
in ===
is mostly noise in TypeScript
code except for a few cases.
One of the cases is type unions, as in let x: string | number | boolean
.
I may consider using ===
for early returns, for instance, if (x === false) return
,
However, type checks like if (typeof x == 'boolean')...
are more preferred.
Another (edge) case is [] == ![]
. I am not sure if I will ever encounter it.
Will update if I ever do.
Named exports v.s. Default exports
For a JavaScript module, export
s are public APIs,
for which I prioritize Clarity at the Call Site.
So whether to use named or default exports depends on how the module is used.
When the export
is imported on the call site and used in code with a name,
the name should be part of the API, Therefore, named exports should be used.
When a third-party tool loads the module, instead of it being imported and used in code, a default export should be used. In most cases, it is the sole purpose of the entire module.