This is one of the most precious assets of any development team because in it lies all of the work. In fact, it is the only artifact that every project will always need to build. Many teams don’t document it, nor make certain types of tests for it, but without code, there is no software. So, code is the one thing that software development teams will always have. This provides the guideline that it’s a fundamental area to pay attention to in order to control quality and reduce risks and costs, no matter what the organization’s goals and context may be.
When considering source code, we are referring to several things, but we’re mainly referring to code management and code quality. Both aspects should be considered in order to achieve a good continuous testing approach.
With code being such an important asset, a risk that’s essential to have under control is making sure to properly manage it and any amendments made thereto. There are specific tools to do this that are made for working with a centralized repository where all team members can reliably store it.
Today’s tools have evolved in terms of task focus, going from simple schemes like CVS to more sophisticated and flexible ones like Git. What they allow, some to a lesser or greater extent, is to have the code in a centralized location. Each developer can submit code, consult it, retrieve previous versions (which is useful when your code is not working properly and you need to go back to the previous working version), add comments to each “commit” made (e.g., comments indicating why one decided to send certain code to the repository) and much more.
These tools are also accompanied by a methodology. In particular, this is reflected in how the branches of the versions are administered (approved, removed, merged, etc.), which allows for different people to work on different versions of the code. There are those that maintain a branch for each customer (if each has different code), or a branch for larger versions of code, or at a finer level, where a new branch is opened for each functionality or fix someone makes.
On the other hand, it’s important to pay attention to the code quality for promoting maintainability. Code quality is typically an internal attribute of quality, as it’s not visible to the user. It’s possible that, even though the user perceives a software to be of high quality (easy to use, fast, without critical bugs, etc.), it can actually have troubling code quality problems. But since users can’t see nor analyze the code themselves, they would never know. Conversely, quality factors like performance, reliability, and usability, among others, are external, meaning, users do perceive them.
But, there may come a moment when internal quality factors transform into external ones. Take, for example, what happens when a change is made to the system in response to a user request. If the code quality is so poor that it takes several weeks to modify the system, then there is a huge maintainability problem which not only affects the development team, but also the user. The longer it takes for the change to be made due to the bad code, the worse the user satisfaction will be.
Maintainability depends on many aspects. There is a tired phrase that goes, “Code is written once and read many times,” meaning, it must be easy to read. But this doesn’t only include following the well-known conventions like when to use capitals and when to use lower case, or using the correct indentation, but it’s also necessary to keep the code complexity, coupling, size of the classes, amount of parameters, and many more factors in mind.
Years ago the term "technical debt" arose for easily explaining the problem of code maintainability to someone without programming skills. It makes an analogy with the more well-known concept of financial debt. It essentially says that if one schedules a certain functionality, and does it hurriedly due to lack of time, without complying with the team’s "definition of done," (for example, skipping documentation by putting comments in the code, not meeting standards and coding conventions nor implementing unit testing) then at that very moment, “debt” accumulates. The system is owed whatever it may be that was hastily foregone, for example, unit tests, putting them off for when time allows.
What’s the problem with that? Besides repaying the debt, “interest” will be added on so to speak, since it’s likely to take longer and more energy to fix things after some time has passed than doing it right in the moment.
Each maintainability problem generates technical debt and someone always pays: sometimes just the developer, or worse, the user who ends up suffering from the poor quality of the system.
Some very common defects in code quality are:
Modern development environments help immensely with some of these problems such as Visual Studio or Eclipse (to name a few popular ones), to the point that if some of the restrictions are not met, the code will not compile. At any rate, there are many things that can be analyzed with tools that were specifically made for analyzing code quality. Today, the most popular tool for this purpose is SonarQube, but there are several others such as PMD, Kiuwan and CheckStyle.
These tools perform a static study of code and are white-box, that is, they analyze the code without executing it. They check for the common defects mentioned above, such as duplicate code or cyclomatic complexity.
Something very impressive is that SonarQube and tools alike are able to indicate what exactly the technical debt is, calculating how many minutes it would take to resolve each issue it detects. For example, the following image is shown publicly on the SonarQube site as the result for MySQL. One can see that the software has a debt of 36,000 days, which means 36,000 days are needed to resolve all the detected incidents.
This much debt is not what anyone wants for their software!
While it’s great that SonarQube can provide information as to where the technical debt is, it is also important to know how to pay it. But, just sorting these issues by priority isn’t enough. The key here is finding the code that will give the best ROI if improved. It’s necessary to cross the information of the issues and their severity with the number of commits that there are in each class. In doing so, efforts can be focused on improving the maintainability of those classes that are modified more often. However, if there are maintainability problems of classes that are seldom touched, but they function properly, it’s better not to tackle them. As the saying goes, “If it ain’t broke, don’t fix it.”
To achieve continuous testing, a CI environment must be built, and to do so, it’s clear that code needs to be accessible in a well-organized repository, with various quality checks on the code being made, utilizing something like SonarQube.
Everything teams need to know to shift-left testing and reach the level of maturity in their quality engineering processes to enable CI/CD.