In my previous post, I’ve discussed the importance of identifying domain-specific Design Patterns in an organization. Equally important is the need to identify Anti-Patterns.
This is the definition of Anti-Patterns from Wikipedia:
“An anti-pattern is a pattern that may be commonly used but is ineffective and/or counterproductive in practice.”
The first interesting aspect in this definition is that anti-patterns are commonly used despite being ineffective or counterproductive. There may be two main reasons for this clear contradiction:
The programmers using the anti-pattern are inexperienced, so they are unaware of the fact that these patterns are ineffective or counterproductive.
The programmers using the anti-pattern have experience on a different kind of systems, which were less demanding or based on older architectural approaches. Thus, they are not aware that the patterns they have used in the past are no longer appropriate for the new category of systems under development.
The second interesting aspect in the definition is that an anti-pattern is ineffective or counterproductive, but it still implements correct functionality, so the use of an anti-pattern is not a bug. Most often the anti-pattern provides a poor implementation that fails to satisfy non-functional requirements. Here also there are two main cases:
Bad design: The usage of the anti-pattern causes the code to be hard to understand and hard to maintain.
Bad performance: The usage of the anti-pattern causes the code to be inefficient, not scalable or non-robust.
Normally, inexperienced programmers use anti-patterns that cause the system to have both bad design and bad performance. It is necessary to show them the problematic code and teach them better alternatives.
Experienced programmers, on the other hand, may use anti-patterns that implement very elegant designs, but that provide bad performance. This happens because these patterns were good enough for the systems they have implemented previously, but they are no longer able to satisfy the more demanding non-functional requirements of current systems, such as higher scalability and increased robustness. Another common problem is that patterns that were once appropriate for older architectural approaches are no longer suitable for systems with modern architectures.
In an organization, there are three main opportunities to identify anti-patterns: During design reviews, during code reviews and during refactoring of legacy code.
Design reviews are a great opportunity to find anti-patterns. A software architect should be present in each review, and be responsible for indicating if there is any problematic aspect in the design being proposed, either because it doesn’t fit the overall system architecture or because it doesn’t satisfy the non-functional requirements.
Code reviews are the right place to locate bad code, either because it is inefficient or because it is hard to understand and to maintain. They are an excellent opportunity to teach inexperienced programmers about better alternatives.
During the refactoring of legacy code it should be easy to locate anti-patterns, simply because the system requirements have evolved since the code was written. In this case, the person responsible for the refactoring should have a plan for converting each anti-pattern into appropriate code that satisfies the current requirements. Very often this involves adapting old code to fit the new architecture.
So good luck finding your anti-patterns, there will be only benefits!