How to Create Maintainable Application – Part 3 – Improvement

From the previous blogs, we’ve explored the meaning behind maintainable, and how to measure them. This section will explore a few ways to improve maintainability in an application.

These are ways that I have found to work in improving maintainability. 

Design Patterns

Using design patterns correctly allows others to modify and extend the program within the scope and intention of the designer. 

Let’s assume 2 similar complex functions in a program. The first function was created with an extension point via strategy pattern. The extension point allows others to use it and extend the program within the scope and boundary that exists inherently. When the business requested to extend the functionality, the maintainer only required to use the extension point. Several unit tests may already be available for the existing functionalities. The maintainer only requires to add a few new unit tests for the new extension.

The second function did not have any extension point. When the time comes to extend the functionality, the developer requires to open the function and modify the functionality directly. The original intention of the first writer dwindled every time this happened. There is no way to know confidently that the function would work as is. The maintainer would require to assess the new function individually and no longer within the scope of the previous developer. In this case, let’s assume that some unit tests are available for the existing functionality. As the maintainer requires to open and modify existing functionality, the existing unit tests are no longer valid and they all require to be replaced. The maintainer would have to then rewrite the unit test that tests previous functionality, as well as the new addition.

Knowing when to use a pattern is not an easy feat and it takes many practices of failure and error. The second scenario above is the most likely scenario that would occur. The first scenario could only happen by intention and may not always be successful. When it is successful however, the pay off is usually worth the effort. I have blogged about some design patterns such as the cascade pattern and command handler pattern previously.

Readability

The aim of having good readability is to help the maintainer understand the context and intention of the code written. It is to reduce the time required to debug, modify and extend the part of the application. The writer is required to convey information and ensure that their intention is clear.  A high level code reader could usually discern hidden intention and information from any code. They are able to read code and understand to a deeper level the thought process of the writer. Not every maintainer however, is a high level code reader. 

Proper Naming

To ensure that code in an application is readable, it is important to have a consistent way to name classes, functions and variables. There are many guidelines on how to do this already such as the naming convention in Wikipedia. What is also important is that the team as a whole follows a standard that they agreed upon. Having a code review process also helps to reduce naming issues and increase readability.

Cyclomatic Complexity Rating

Looking into the cyclomatic complexity rating can be a good indicator on how readable the part of the function is. A good cyclomatic rating indicates that the part of the code contains only some amount of decision points which increases readability. Jason Roberts from dontcodetired blogged about this with code samples in more detail.

Unit Testing

The aim for unit testing is to instill confidence when the code change during maintenance activity. By having “some” degree of unit testing, the maintainer would have some degree of confidence to modify existing code without breaking the existing functionalities. High level of confidence in this case is the key to continuous integration which leads to continuous deployement.

Code Coverage

When being asked how much coverage is enough, Testivus on test coverage by Alberto Savoia resonates with me, and answers this nicely.

In summary, when there are no unit tests at all, aim to just start writing some tests. There will be a point that we have an overload of unit tests. When an application reaches this point, it is the time that we need to start assessing their values and how are we creating them. At the end of the day, as a rule of thumb, it is generally good to have 80% of code coverage.

Code coverage is the insurance for the future at the cost of maintainability.

Quality Unit Test

Whilst having a good degree of coverage should be the aim of every application, it is also necessary to aim for quality unit tests. Creating quality unit tests takes practice. There are many guides on creating quality tests already. In general, these are some attributes that good unit tests have:

  • Fast: As unit tests are created to be repeatable, they require to be run very quickly as well. Developers could run unit tests several times in minutes to ensure that they don’t break existing functionalities.
  • Reliable: Each test created must be deterministic. When a unit test run, it must produce exactly the same output every time. This is the key to instil confidence in unit tests.
  • Independent: A unit test should only test one thing at a time and it should not rely on each other.
  • Readable: Unit tests should be able to be understood and the intent should be clear. If the test fails it needs to convey information of which behaviour of the application that fails.

Final Words

Knowing methods to measure and improve maintainability are a good start for any people working to improve their application. However, there are usually more challenges when someone or a group of people attempts to improve their software maintainability. The impact of these attempts can be negative and hinder the next attempt to improve maintainability.

In the next article we will be exploring these challenges in more detail.

References

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s