One of the biggest factors that help us separate good programmers from great ones is their ability to write clean code. So what does it mean to write clean code? Code that is readable, maintainable, well supported through documentation and makes it easy for the team to scale the product is code that is well written. Let’s dive into a bit more detail on these topics.
Readable code is just how it sounds — readable. A person with basic familiarity of the programming language — or software development in general — should be able to skim through the code and easily understand what the code is accomplishing. A few ways to ensure this are:
- Formatting: the code should be well formatted to allow a person to easily digest each line of code in bite-sized forms. Much like reading a book, a long run-off sentence will often leave us confused and require us to re-read it, similarly, code that is convoluted will often end up being confusing for everyone except the person who wrote it (and sometimes even the person writing it will come back to it and not know what they wrote). IDE plugins like Prettier are highly recommended to assist with this task.
- Comments: blocks of code that are performing complex functionality or taking assumptions into account that a new person may not be aware of should be documented with comments within the code itself. Code that is elementary and speaks for itself need not be commented, but it is generally good practice to write comments in the form of pseudo-code before writing the code itself, and then just filling in the syntax to fulfill the logic written down in the comments. This is a good habit to form and will go a long way in helping you write clean code.
- Clear naming convention: This is an extremely important aspect of clean code, and one where a lot of developers often struggle. Ensuring that the names of your methods, variables and other custom definitions are descriptive and easy to understand will be extremely beneficial not just for the people who will interact with your code, but even you as the author of the code, as it will make the code read more like English. Programmers are often in a hurry to pick any name for a variable or function and move on to writing the code quickly. We would advise that you sit and think about the name for a little bit and think about all its interaction points, and whether those read well.
- Consistency: To build on the previous point, a huge part of good naming convention is to be consistent with it. Not only should the formatting be consistent and in accordance with the best practice defined by that language (i.e. Kebab case, Camel Case, etc.) but the prefix and suffixes used should also follow convention. For example, in React, when defining a method that is invoked upon a button being clicked in the UI, the method should usually begin with ‘handle’ — so, if a submit button is clicked in a form, the method that is called when that happens would be called ‘handleSubmit’. Simple enough, but it loses its power if the convention is not consistently followed across the entire code-base.
Writing highly readable code is a fantastic step in the right direction. However, in larger products, it will only get you so far before things start to get extremely complicated and messy. In order to manage massive products with several moving parts, it is important to create supporting documents. Here are some that we lean heavily on at AAR Technologies.
- API documents: When building services, it is safe to assume that several different areas of the products will be interacting with them (web, iOS, Android, etc.) and other software engineers will need to know how to interact with the service you have built, without wanting to delve into the code. This is where API documents come in. They document what parameters or arguments the API call expects, what keys, tokens or other important authentication information it will need, and what the output should look like. There is a lot more that goes into this, but these are some of the basics. This allows an engineer who wants to utilize the API to have the ability to invoke it with all the right parameters in place without needing to look at the code.
- Data structure: A data structure diagram, or entity-relation diagram (depending on what type of database you are using) is essential when it comes to building the architecture of the product and ensuring that it is optimized from a resource efficiency standpoint. Being able to look at the different tables, documents and their relationships from a bird’s eye view is crucial for an architect to be able to ensure that the system is well built.
- Flow diagram: flow diagrams are common when there are complex algorithms that need to be built with several branches where the logic can split. For example, if you are building a notification system for Slack, there are many things to take into consideration when delivering a notification to a user, such as; does the user have do not disturb mode on, has the user muted the channel, etc. In order to make sure that none of the scenarios are missed, and to be able to clearly explain / understand all the different possible paths that the algorithm can take to achieve its final goal, a flow diagram is extremely helpful.
Why does all of this matter?
The biggest advantage of having clean, well documented code is that it gives you the ability to maintain the code over a long period of time. Imagine a product that is being built today and needs to be supported for the next 10 years. The number of people that will come and go while working on that code-base will be quite large, and all of these people will be on boarded with little to no knowledge of the work completed up to that point. We should always write code and support it with concise documentation with the frame of mind that this code will one day be read by someone who has none of the pre-conceived knowledge that you possess when writing this code, and our goal should be for them to still be able to understand all of it.
To double down on the previous statement, if a product is to have a 10 year shelf-life, it will definitely need to scale in order to be successful. For a product to scale, its team usually needs to scale as well. In order to help facilitate both of these things, the existing product’s code base and supporting documentation needs to be extremely strong in order for new engineers & designers to join the product team and continue building upon the foundation laid by the ones before them. They will only have this ability if they are able to understand what is going on. Clean, well documented, maintainable code will go a long way in accomplishing this.
The best part about all of the practices mentioned above is that they are not difficult at all. These are just habits that one should get into, and it becomes second nature. Once an engineer has built these good habits, they will wonder how they ever managed to code without them. They not only make you a better team-player, but even working on your own code will feel a lot better.