Writing code cleanly
pointers and examples on how to write clean code for others to happily read
When a team of developers build an application together, often you need to make sense of code written by others to integrate your work. Developers should write code in a way that are self explanatory without having the author to tell you a story of how it works. Cleaner code have higher readability, maintainability, easier to extend and understand thus increasing team productivity.
Here, I will share my experience in writing clean code on Moodah POS.
Principles
There are some conventions and rules to keep in mind when writing code so it is clean. Below is a compilation of a few coupled with examples.
Readability through names
A good variable name that clearly expresses intent removes the need for reading other parts of code to understand it’s context. Choosing good names may be difficult but with a good name will answer a lot of questions.
There are only two hard things in Computer Science: cache invalidation and naming things — Phil Karlton
The variable name hasNextPage
, queriedResult
expresses intent without any background.
You can also guess what camelizeKeys
does, which is a function from humps
NPM package that camelize keys of object recursively, and infer that record
is in snake case, while naming convention in Javascript is camel case. That brings us to the next point which is to follow conventions in the langauge or library such as variable naming conventions.
Avoid redundant comments
// computes sum of a and b
function sum(a, b)
Sometimes there is still a need for knowing conventions on the library to understand the logic of a snippet of code. As an example, lines 3 to 5 may seem confusing without context.
It is actually implementation of cursor based pagination which involves querying an extra record to check whether there is still next page without returning the extra record to response. Now, there is no need for comments if developer is familiar with a concept used in the library which should be assumed. So your comments should target developers that are familiar with the library to avoid redundancy.
Refactor to not repeat yourself
There is a principle in programming called DRY, which is an acronym for Do Not Repeat yourself. It aims to reduce repetition of patterns with intent for painless modification in only one place instead of searching for many.
Above snippet refactors code by identifying similarities such as clientOptions
and the chaining of function calls from and after createService
into one place which is the utility function configureService
.
Testing conventions
To make a clean test, it should only have one assert per test to better isolate logic tested, is readable so when it fails developer immediately gets an idea of what went wrong, fast since developers or deployment pipeline often run the tests, independent and repeatable meaning output will be consistent.
Source code structure
Uniform styled code is best to avoid any confusion between developers. This includes keeping lines short, using white space to associate related things and proper indentation.
This can be automated to some degree using linter tools, a tool that analyzes source code to flag errors, bugs, stylistic errors and suspicious constructs. In our project we use ESLint to automatically fix auto-fixable style problems with a command.
Error and exception handling
Many code bases are completely dominated by error handling … it is nearly impossible to see what the code does because of all the scattered error handling. Error handling is important, but if it obscures logic, it’s wrong
Error and exception handling should not be implemented in a way that reduces readability. Each exception that is thrown should provide enough context to determine the source and location of an error.
Below is an example of error handling in GraphQL when input filter is invalid. The error message allows us to immediately pinpoint where was wrong, this case email
is not a valid key. Note that it is GraphQL convention to not throw errors but instead still return data that has errors
as key when something goes wrong.
Below is the code responsible for such messages, it can be read through clearly that there are two cases that is handled, one if filter argument is invalid, the second one (the one with onError:
) is the default error handling scheme by GraphQL.
As a takeaway, always try to write clean code to make other developers happy when they touch code written by you. If leveraged correctly, it can significantly boost your team’s productivity. Hopefully, few examples here can give you a brief idea of what clean code is like and motivate you to do similar. That is all from me, cheers~