A Definitive Guide to Understandability
January 5, 2020
When you start working on a new project for the first time, everything usually seems quite clear, including the steps you need to follow to write the necessary code.
When you first begin to build your application, you have a very abstract idea of what the final product will look like and you might think it’s all very clear and easy to understand. Even when you start writing the first lines of code and create the first functions, classes and modules, everything might still seem very simple.
But will things stay the same in a few weeks, months, or maybe even years, especially when the code bases will increase and more components will be added to the architecture?
Will your code, and essentially your software, be understandable?
Here is all you need to know about understandability when it comes to software development, as well as why it’s important to make sure your code is easy to read.
Essentially, it means that your application can effortlessly be comprehended by developers, both by those who created it and by those who join along the way.
You can say that understandability is achieved when developers on all levels can make updates to it in a way that is clear, safe, and predictable, all without breaking current functionalities.
Here’s how understandability plays an important role in the functionality and performance of web-based applications, or any application in fact.
A code that is easy to understand will be easier to debug.
When you work with code that is tangled (spaghetti code) or more complex than it needs to be, you will have difficulty spotting any potential problems.
In the fortunate case where you have tests, most of the bugs will be spotted in that development phase. If they’re not spotted by the time your software is live, then these bugs will be raised by users, which is something that will affect the user experience.
For example, take these two snippets. They are two versions of implementation for the FizzBuzz code challenge. The first one represents the most basic implementation, while the second one is trickier.
In terms of performance, they are both the same O(n), where n is 100. So neither of these versions is better in terms of performance.
The above image represents the basic implementation that is very easy to understand and therefore it’s much easier to spot any problems.
The second implementation has a bug. Because the code is not so easy to understand, it may be hard to spot it. Try to figure it out yourself before scrolling down.
Did you figure it out? The issue is here:
You have to include a negation sign.
The speed that’s being referred to here is the speed of development. A lack of observability will, more often than not, cause the development team to move very slowly.
When dealing with legacy code you will often see some sort of spaghetti code. The substantial problem here is that, due to lack of visibility, it is almost impossible to see how even a small change affects the overall code.
This is why the process of developing the application code will be a very slow one. You have to ensure that the current code remains correct even while you’re making changes.
In other words, you need to check that you’re not creating new problems while trying to solve old ones.
Another side effect borne from a lack of understandability can be found on the security and maintenance side.
Not only will the flaws in the code or architecture be hard to spot, but keeping the code and the packages (libraries & dependencies) up to date will be a very tedious process. This will affect the security of the application.
Lastly, but not the least significant field that will be affected, is the budget. When there are issues with a team’s velocity, the first and easiest solution is to bring more developers on board. But this is just another patch on a broken bag until things go south again because the true problem was never treated.
In the end, the biggest impact will be on the budget, whether this is in the form of more paychecks or users who simply give up.
Understandability can be divided into more categories and can be extended to users – not only developers – as well.
The obvious one is the codebase and architecture understandability that we covered previously.
This problem can be extended to the documentation and instructions that the application provides.
I think it is safe to say that we have all come across an application or a specific tool where the documentation it had made no sense and in the best case scenario it only gave you some basic information.
Another underrated scenario of this issue refers to the user interface.
“A user interface is like a joke. If you have to explain it, it’s not that good.” – Martin LeBlanc
For an app to achieve understandability, UX must be taken into account as well. The application should be easily used by users without them being disoriented and confused.
Here is a checklist you can take into account when creating understandable code.
- Choose a Suitable Pattern and Write the Code According to It
Some of the most well-known design patterns are OOP, MVC and Component Based.
For example, you can take AngularJS, which is a framework built on MVC. For Component Based, on the other hand, you can use Angular, React and actually most modern web frameworks as examples.
For modern web development, I would say that a component-based architecture solves most of the problems. However, the idea is that no matter what pattern you choose, it’s important to write the code according to it.
Let’s say that you have a new developer joining the team and they are taking a look at the code for the first time. If the code is written according to a known pattern that they are acquainted with, then there’s a high chance that they already know where to look to solve a particular problem or where to find the implementation for a specific job.
If there is no design pattern then they will have to find where in those files is the logic that makes X and then in which other files it is linked with Y and so on. This becomes tedious really fast and causes a decrease in productivity for everyone.
As the name suggests, modular programming refers to the process of subdividing an application into separate sub-programs.
This will make the code much easier to understand and read, as this technique achieves a separation of concepts. Thus, each module is independent of the others and each module has a single purpose.
At the same time, this allows engineers to develop faster because the modules can be easily integrated from one application to another.
The previous examples were referring to the application architecture and structure, but we can make use of some clean code principles as well. For example:
- KISS – keep it stupid simple or keep it simple, stupid. According to this principle, most systems perform best when they are kept simple rather than made complicated. That’s why simplicity should be a key goal if someone wants to achieve understandability across their codebase. Avoid any unnecessary complexity.
- DRY – Don’t Repeat Yourself. This principle states that each piece of code must be unique and have a well-defined purpose. For example, if five lines of code are repeated several times across your program then, in order to be in accordance with this principle, you should take those lines of code and write a separate function which you call. Don’t rewrite the same thing every time.
- YAGNI – You aren’t gonna need it. This principle is simple. Don’t add functionality until deemed necessary. Only implement things that are required.
Another example of code that is not that easy to understand can be found in the following snippet:
This code rewrites a text from right to left. In other words, this is an example of string reversal.
A better approach would be the following:
One common misconception is to think that understandability and observability are the same. However, in reality they are complementary. The second one focuses on the ability to alert the dev team when the system misbehaves and help them identify the causes of any problems, so that normal service can be restored.
In other words, observability is achieved when you collect enough data from your application that identifies the root of your problems or helps you predict any future problems, such as performance bottlenecks.
Therefore the understandability of your system, the way that it behaves, and the way users and developers interact with it can be improved by collecting more data from your software.
There are several tools that can help you collect more data from your application.
Rookout is a tool that helps you achieve greater understandability in your application by enabling the retrieval of any required data from live code, in just one click. In other words, it allows developers to do remote debugging on production servers without breaking anything, because of its non-breaking breakpoints.
Understandability is something to always keep in mind. If you ignore it, your team will suffer for it.
It is much better to take the time to get things done right the first time around. That way, you won’t waste unnecessary time and effort when other improvements are needed or when certain problems arise.