Coding standards
Coding standards are the set of guidelines and best practices that we follow to ensure that our code is consistent and concise. Fortunately, nowadays modern tools and IDEs automate most of the formatting of your code according to standards on saving.
As Michael Feathers, author of Working Effectively with Legacy Code said:
“One difference between a smart programmer and a professional programmer is that the professional understands that clarity is king. Professionals use their powers for good and write code that others can understand... Clean code always looks like it was written by someone who cares. There is nothing obvious that you can do to make it better.”
General guidelines
- Avoid over-complicating things.
- Only abstract code when really needed and only when it doesn't over-complicate things. Where you have many different things implementing the same principle e.g.
Couriers
orPayment methods
, consider abstraction. Procedural code is harder to extend, while abstraction makes new functions harder to add. - Don't duplicate code (the DRY principle). If it is used more than once, please make use of a reusable function.
- Keep global variables and state to a minimum. Code that uses globals can have surprising and unintended side effects, which reduces the ability to understand and mentally model the codebase.
- Be consistent – in naming, structure, and architecture. It makes things predictable.
- Remove all unused code and comments. It just clutters and confuses.
- Use named constants instead of magic numbers e.g.
SHIPMENT_STATUS_DELIVERED
instead of"delivered"
or even worse15
. - Keep configurable data and constants at high levels. Don't bury a constant e.g.
SHIPMENT_STATUS_DELIVERED
in a low-level function. Also ideally, group pieces of configurable data and constants together in one place.
Naming things
Name things well. Phil Karlton said: “There are only two hard things in Computer Science: cache invalidation and naming things.”
Expressiveness to me includes meaningful names, and I am likely to change the names of things several times before I settle in. With modern coding tools ... renaming is quite inexpensive, so it doesn’t trouble me to change.
Names in software are 90 percent of what make software readable.
- Don't use single-letter names and numeric constants as they are not easy to locate across a body of text and are not very descriptive. Use e.g.
shipment
instead ofs
, unless it's in a short map/reduce/filter function or very short functions. - Use descriptive names e.g.
updatedShipment
instead of justshipment
to describe intent. - Use longer descriptive names, as opposed to truncated names which can be ambiguous e.g.
delShipment
. - Use pronounceable names. If we can't pronounce it, we can't discuss it without sounding stupid e.g. "Did you check the numSpaceRD to see if it added spaces"?
- Pick one word for one concept and stick to it e.g.
fetch
so that you havefetchShipments
,fetchAccounts
etc. andisLoading
andsetIsLoading
vs.loading
andsetLoading
. - Where possible, determine plurality of an item e.g.
shipment
if 1, otherwiseshipments
. As a last resort useshipment(s)
and notshipment/s
. - Use US English for code, UK English for UI.
- Use a code spell checker to get rid of typos and common mistakes.
- Use sentence case in all text displayed to the user unless referring to proper nouns.
- Use all uppercase for acronyms e.g.
calculateVAT
.iVeri
=>IVeri
. If 2 acronyms, only capitalise the second one e.g.EftPOP
.
Comments
The general rule is: put a space after //
and use sentence case. Rather refactor and use meaningful names instead of paragraphs of comments.
Don’t comment bad code—rewrite it.
Inappropriate information
It is inappropriate for a comment to hold information better held in a different kind of system such as your source code control system, your issue tracking system, or any other record-keeping system.
Change histories, for example, just clutter up source files with volumes of historical and uninteresting text. In general, meta-data such as authors, last-modified-date ... and so on should not appear in comments. Comments should be reserved for technical notes about the code and design.
Obsolete comments
A comment that has gotten old, irrelevant, and incorrect is obsolete. Comments get old quickly. It is best not to write a comment that will become obsolete.
If you find an obsolete comment, it is best to update it or get rid of it as quickly as possible.
Poorly written comments
A comment worth writing is worth writing well. Choose your words carefully. Use correct grammar and punctuation. Don’t ramble. Don’t state the obvious. Be brief.
Commented out code
It makes me crazy to see stretches of code that are commented out. Who knows how old it is? Who knows whether or not it’s meaningful? Yet no one will delete it because everyone assumes someone else needs it or has plans for it.
When you see commented-out code, delete it! Don’t worry, the source code control system still remembers it.
Functions
Clean code is focused. Each function, each class, each module exposes a single-minded attitude that remains entirely undistracted, and unpolluted, by the surrounding details.
- Use verbs for function names e.g.
calculateVAT
,getShipments
,updateAccount
etc. In other words don't use something likedb.ShipmentsWithReference
but ratherdb.getShipmentsWithReference
. - Do not leave an open line after the function declaration. Immediately start with the first line of code.
Dependant functions
If one function calls another function, they should be vertically close. The caller should also be above the callee if possible to give the code a natural top-down flow.
Too many arguments
Functions should have a small number of arguments. No argument is best, followed by one, two, and three. More than three is very questionable and should be avoided with prejudice. Arguments makes it hard[er] from a testing point of view. Imagine the difficulty of writing all the test cases to ensure that all the various combinations of arguments work properly.
Unused functions
Methods that are never called should be discarded. Keeping dead code around is wasteful. Don’t be afraid to delete the function. Remember, your source code control system still remembers it.
Obscured intent
We want code to be as expressive and intentional as possible. To aid this, a function should ideally only do one thing. Function names should say what they do. Don't e.g. name a function person.getFullName
which in turns set the member variable person.fullName = this.firstName + this.lastName
and returns person.fullName
. A getter should only "get" for example.
Another example: Look at newDate = date.add(1);
. Does this add 1 hour, 1 day or 1 year? If this was days, rather call the method addDays
or let it take a type constant as an additional function call e.g. add(1, date.DAYS)
.
Prevent your function from having side effects. If your function promises to do one thing, but it also does other hidden things, bugs will appear sooner or later.
Conditionals (if statements)
Encapsulate long conditionals
Extract functions that explain the intent of the conditional e.g.if(canCollect(shipment))
instead of if(shipment.status === SHIPMENT_STATUS_COLLECTION_ASSIGNED && shipment.collection_agent_id && shipment.collection_address)
Prefer positive conditionals
Negatives (especially double negatives) are just a bit harder to understand than positives e.g. if(canCollect(shipment))
is easier than if(!cannotCollect(shipment))