Day 24: Refactoring Code Frequently
Software is not a static entity that exists in a single, defined way. The great advantage of software over traditional engineering building material is that it can be modeled for different uses as necessary. This advantage, however, incurs in a penalty that is easily overlooked: it is necessary to maintain software during its life time so that it maintains the original qualities, even when facing changes in the way it is used.
This flexibility along with its associated maintenance problems can be easily seen in any non-trivial piece of software, be it commercial or open source. An application or library usually starts as a way of solving a particular need. As development progresses, however, the same software is frequently adapted to solve more and more complex use cases. As a result, code needs to adapt itself to these changing requirements, changes that sometimes modify important assumptions upon which the original code was written.
The main challenge faced by developers is to allow a piece of software to evolve in an organic way, so that it will be provide a response to these sometimes conflicting requirements. As an example, the same application that was once able to process a single file with a particular purpose may have, a few years later, be able to handle multiple files, each one with a different type of contents.
An Answer to Changing Requirements
Because of these difficult requirements, a lot of software artifacts just decay due to a lack of proper maintenance. As changes happen to the environment where it exists, a program will start to provide incorrect answers some of the times, or even most of the time. These are bugs that have been introduced by the very same evolution that is reshaping the program to be able to cope with different requirements.
Despite this, it is possible to maintain software properly even through big changes happen to its processing capabilities. Refactoring is the central concept enabling this adaptation on a daily basis. With the help of refactoring, programmers are able to slightly modify the way a piece of software works, so that it can satisfy specific characteristics needed by new requirements. At the same time, refactoring can be used along with unit testing to improve confidence on the quality of the existing code base.
Refactoring to the Rescue
Refactoring surfaced as an automated way of modifying programs, especially code written in an object-oriented fashion. Smalltalk was among the first languages to provide a refactoring facility, so that programmers could make small changes with confidence. It is important to understand that changes allowed by refactoring are usually minimal so that they could be easily automated. Examples include: renaming methods, changing the order of arguments in a method declaration and all method calls, or moving a method from a subclass to its parent class.
The main advantage of refactoring compared to other approaches for code modification is that refactoring is (or can be) completely automated. With the help of a refactoring tool, it is very simple to make changes to a code base that will make the program cleaner, while at the same time maintaining its correctness.
When to Use Refactoring
Another advantage of refactoring is that it doesn’t need to be considered as a task separated from coding. Good software engineers make liberal use of refactoring in their workflows. In fact, some people use refactoring very frequently, in order to provide one or more of the following:
Improving readability: a simple reason to use refactoring is to improve the readability of existing code. Sometimes it is possible to combine two or more statements and make a method much easier to read. Conversely, it is possible to split a statement in one or more, while at the same time improving the readability of the whole section of code. These are powerful uses of the capabilities of a refactoring tool.
Adapting to changes in the underlying code: sometimes the implementation of a new feature will require just a slight change to existing code. For example, that change may require a new parameter to be added to a method; or maybe an existing method will need to be moved to another class. Instead of doing this manually, one can use a refactoring tool to achieve the same results with less work.
Naming methods and variables properly: another good use of refactoring is making sure that methods and variables reflect their true meaning in the program. Sometimes, as a piece of software evolves, the names used in the initial implementation may lose their meaning, either because of business reasons or because other parts of the implementation have evolved too. Refactoring is a simple way to solve this issue, since it guarantees that all other parts depending on these methods or variables (including automatic tests) will be properly updated.
Conclusion
Refactoring is a powerful tool, and it should be part of any programmer’s tool chest. However, like any tool it takes some training to get used to it. Some of this ties with the general idea of properly learning your software environment. Most modern environments (command line or IDE-based) have provisions for running refactoring tools.
Also, refactoring tools are available for many modern languages, the most common ones including Java, Smalltalk, Python, and C++. Therefore, the use of refactoring has just become a matter of mastering the underlying programming system. The frequent utilization of such tools can make our lives easier, and our code even better.
Similar Posts:
About the Author
Carlos Oliveira holds a PhD in Systems Engineering and Optimization from University of Florida. He works as a software engineer, with more than 10 years of experience in developing high performance, commercial and scientific applications in C++, Java, and Objective-C. His most Recent Book is Practical C++ Financial Programming.