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

  1. Avoid over-complicating things.
  2. 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 or Payment methods, consider abstraction. Procedural code is harder to extend, while abstraction makes new functions harder to add.
  3. Don't duplicate code (the DRY principle). If it is used more than once, please make use of a reusable function.
  4. 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.
  5. Be consistent – in naming, structure, and architecture. It makes things predictable.
  6. Remove all unused code and comments. It just clutters and confuses.
  7. Use named constants instead of magic numbers e.g.SHIPMENT_STATUS_DELIVERED instead of "delivered" or even worse 15.
  8. 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.
— Ron Jeffries
Names in software are 90 percent of what make software readable.
— C. Martin Robert
  • 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 of s, unless it's in a short map/reduce/filter function or very short functions.
  • Use descriptive names e.g. updatedShipment instead of just shipment 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 have fetchShipments, fetchAccounts etc. and isLoading and setIsLoading vs. loading and setLoading.
  • Where possible, determine plurality of an item e.g. shipment if 1, otherwise shipments. As a last resort use shipment(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.
— Brian W. Kernighan

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.
— C., Martin Robert. Clean Code. Pearson Education. Kindle Edition.

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.
— C., Martin Robert. Clean Code. Pearson Education. Kindle Edition.

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.
— C., Martin Robert. Clean Code. Pearson Education. Kindle Edition.

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.
— C., Martin Robert. Clean Code. Pearson Education. Kindle Edition.

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.
— C., Martin Robert. Clean Code. Pearson Education. Kindle Edition.
  • Use verbs for function names e.g. calculateVAT, getShipments, updateAccount etc. In other words don't use something like db.ShipmentsWithReference but rather db.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.
— C., Martin Robert. Clean Code. Pearson Education. Kindle Edition.

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.
— C., Martin Robert. Clean Code. Pearson Education. Kindle Edition.

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))

Platform specific standards