Skip to content

General coding standards and guidelines

Coding standards are a set of guidelines and best practices that we follow to ensure that our code is consistent and concise. Fortunately, modern tools and IDEs automate most of the formatting of your code according to standards on saving.

So, why should we all follow a certain standard, we ask? 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."

Clean code

Let's keep things simple and write easy-to-read code

Indeed, the ratio of time spent reading versus writing is well over 10 to 1.
We are constantly reading old code as part of the effort to write new code.
... [Therefore,] making it easy to read makes it easier to write.

― Robert C. Martin, Clean Code: A Handbook of Agile Software Craftsmanship

The logic should be straightforward to make it hard for bugs to hide,
the dependencies minimal to ease maintenance, error handling complete ...
and performance close to optimal so as not to tempt people to make
the code messy with unprincipled optimizations.

― Bjarne Stroustrup, inventor of C++

Some things to note

  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 on a shipping platform or Payment methods on a payment platform, do however consider abstracting them out. Procedural (non-abstract) code makes it hard to add new implementations of a concept because all the functions must change. Abstraction code makes it hard to add new functions because all the classes must change.
  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. If you do something a certain way, do all similar things in the same way. This is with reference to naming, structure and overall 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." It's worth spending time on naming things properly and descriptively.

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.

Expressiveness goes beyond names, however.
I also look at whether an object or method is doing more than one thing.
If it’s an object, it probably needs to be broken into two or more objects.
If it’s a method, I will always use the Extract Method refactoring on it,
resulting in one method that says more clearly what it does,
and some submethods saying how it is done.

― Ron Jeffries, author of Extreme Programming Installed and Extreme Programming Adventures in C#

Names in software are 90 percent of what make software readable.

― C., Martin Robert. Clean Code (p. 613). Pearson Education. Kindle Edition.

  • 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 not shipment/s
  • Use US English for variable names etc. in code but UK English for UI elements such as labels and text shown to the user.
  • 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 for comments is to put a space after the // and write the comment in sentence case e.g. // This function does X.

Don’t comment bad code—rewrite it.

― Brian W. Kernighan and P. J. Plaugher

Too much information

Writing code that needs paragraphs of comments to explain what it does (with the exception of listing complex business rules). Rather refactor and use meaningful names to make code easy to understand.

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.
  • 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.

― C., Martin Robert. Clean Code (p. 52). Pearson Education. Kindle Edition.

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 Date 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 over negative ones

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