When are you done writing a piece of code? Is it when you have implemented the necessary functionality? When you have tested it? I believe there is more to professional-quality code than just getting it to function properly. What else is there? Making sure the code is maintainable - well designed and understandable. I use the term polishing code to refer to this kind of work that is done on a code base after it is functioning properly. I like the analogy with woodworking: once a piece is assembled and finished, the final step is to polish the surface to make it shine.
Based on the code bases I have seen and worked with, polishing code is not a frequent practice. In fact, I have encountered people who are surprised by my commitment to it, or who do not believe in its value. Many of these people are not developers, or have not spent much time doing ongoing software maintenance. Part of the reason for the lack of appreciation is that polishing code provides long term benefits for a short term cost. This induces project managers and developers on development projects with compressed time frames to skip such kinds of activities. In other cases, non-technical managers simply have no idea of the poor quality of code their developers are producing. One project manager I dealt with personally reviewed and made minor grammatical corrections to the documentation produced by the project team, but had no similar processes in place for the poor quality code produced by the project team.
So why do I believe that polishing code is valuable? I have several reasons. The most important is that it minimizes the long term cost of maintaining the software. To explain this, I like to use the concept of technical debt. Quality issues such as poor design in software represent a debt for which you will need to make continuing interest payments later in the form of increased effort to understand or change the software. This is the case even if the software functions correctly. To pay off that debt, you must address the underlying quality issues - in other words, you must polish the code. Martin Fowler wrote a recent article about this topic in the context of good design that explains the trade-offs involved. Another reason I polish my code is that it is a permanent record of my capabilities as a professional software developer. My reputation amongst developers who need to work with my code later is in large part determined by my code's quality. Code of mine that is difficult to understand or change or is riddled with defects will have maintenance developers cursing at me. I would rather have them be pleasantly surprised at finding helpful comments and a clean design.
So now you hopefully believe that polishing code is valuable, but you may be asking how exactly to go about it. In terms of timing, polishing of code should ideally be done throughout the development of a section of code. In reality, however, it is much easier to focus on one issue at a time, and the primary issue is just getting the code to work. Therefore after the code is written and passing the automated unit tests, it is only natural for it to have some rough spots. This is the ideal point to do a review of your code to identify places to polish. My basic goals when polishing are to improve the understandability of the code and to improve its design. During the review, I look for specific problems impacting these two goals. When I find such a problem, I immediately rectify it by refactoring the code. Often it is as easy as using one of the built-in refactoring tools of the development environment to safely make the change with a near-zero risk of introducing defects.
Some examples of specific problems I look for are:
- Duplication of logic in two or more places.
- Undesired dependencies. For applications divided into layers such as persistence, business and user interface, the dependencies between the layers need to be managed. Finding undesired dependencies such as the use of persistence code directly within the user interface layer is a strong indicator of a design problem.
- Overly complex logic, like a large switch statement or series of nested if-else statements. Sometimes such logic can be drastically simplified through the use of object-oriented design principles.
- Too many classes within one package.
- Too many methods within a class, particularly public methods. This is often an indicator that the class is trying to do too much and should be split into multiple classes.
- Overly long file, in excess of a couple thousand lines. Even in Java where each public class is forced to be in its own file, it is possible to end up with very long files. This may be because there is too much logic within the class, or it may be because of many nested classes or private classes in the same file. In the latter case, these can be moved to one or more separate files.
- Overly long methods. Anything longer than about one screen warrants a closer look to see if it can be simplified, usually via an extract method refactoring.
- Poorly named classes, methods, fields or local variables. One indicator I look for is a one-sentence comment describing a vaguely named variable or method. Usually the variable or method can be renamed to capture the essence of the comment and the comment can then be deleted.
- Lack of a class comment. A concise summary of the purpose of the class is often quite useful. If it is difficult to come up with such a summary, it is an indicator that the class may be trying to do too much or does not have a clear focus.
Ron Jeffries' site http://www.xprogramming.com/ has a great series of articles that provide concrete examples of polishing code, including before and after samples of the source code.
Polishing your own code is good, but it is better if your entire team adopts the practice. An effective way to ensure code is polished within a team is via code reviews. While ideally everyone should polish their own code, having a separate reviewer check for code quality problems is a big help. This is especially true for ensuring that the code is understandable by someone other than the original developer.
Applications with polished code are easier to understand and modify, which helps extend their useful life. Applications with poor quality code are more likely to be partially rewritten or even completely replaced if the cost of ongoing maintenance becomes too high. Which of these applications would you prefer to contribute to? The choice is yours.
If you find this article helpful, please make a donation.