Sunday 14 June 2015

Recognising The Enemy


We're all familiar with software design patterns and we apply them when we recognise a common problem as our collective experience has taught us that they are effective solutions.
But not all patterns are born equal, sometimes they can be misused, this leads us to the concept of anti-patterns.
Generally anti-patterns can be described as being ineffectual solutions, on the surface they may appear to fix the problem but they usually are just converting one type of problem for another.
So how can we recognise an anti-pattern?
Square Peg In A Round Hole
Anti-patterns can sometimes be born by applying a well known pattern to a situation that requires a different solution, quite often this is caused by attempting to fix the wrong problem.
An example of this would be the over zealous use of the singleton pattern.
There are valid use cases for singletons but their automatic use in situations where allowing multiple instances of a class is problematic can make it become an anti-pattern.
Turning a class into a singleton may solve a problem your having related to multiple instances but singletons,
  • Hide dependencies.
  • Decrease Testability.
  • Decrease the opportunities for code re-use.
This is a good example of an anti-pattern, the solution to a problem in one class has now spread to several problems in every class that comes into contact with it.
When applying a design pattern we should be looking to satisfy the greater good, whenever the application of a pattern causes undesirable side-effects such as these the question must be asked are we fixing the right problem? How much impact does our solution have on the rest of the code base?
Fix For A Fix
Another symptom of an anti-pattern is rigidity and a general lack of adaptability, they often fix a specific problem in a specific way. This leads to you re-visiting an area of the code over and over again coming up with ever more inventive ways to keep the plates spinning and keep the pattern in place.
An example of this would be the inappropriate use of the template method pattern.
Again there are valid use cases for this pattern but its use of abstract classes and inheritance places restrictions on how the code base operates, this means you must be sure that all potential future uses of the functionality will fit the abstraction.
This is another trait of an anti-pattern, it doesn't fix the problem for very long, you end up returning to that area of the code base frequently and each time the original pattern used seems less appropriate for the situation.
I Thought It'd Be Easier Than This
Applying an anti-pattern often doesn't provide the benefits that you are lead to believe will follow, an example of this is the service locator pattern.
The service locator pattern is a necessary part of implementing dependency injection, however it is only part of the story.
The key aspect of implementing DI is the inversion of control where classes clearly state their dependencies and pass over control of providing them to the code constructing the class. Use of the service locator pattern inside the class doesn't provide this inversion and therefore doesn't reap all the benefits that DI should bring especially in relation to testing.
This is one more symptom of an anti-pattern, they do not provide well rounded or complete solutions to the problem at hand. They hint at the correct solution but have something missing.
You will on occasion end up coding an anti-pattern, software development is complicated not always getting it right is not a sin. The key is to recognise early on that something isn't right before the side effects permeate to far.
When you've decide on a pattern to use ask yourself if this leaves the code base in better shape than when you found it,
  • Can I think of way where the problem I'm trying to solve will still exist?
  • Can I think of a new problem I'll be creating if I use this pattern?
  • How far reaching are the consequences of using this pattern?
  • Is it clear how I will be able to test this code?
  • Is it clear how the code base will grow around the use of this pattern?
Satisfactory answers to these questions should give you a warm feeling inside, unsatisfactory answers will leave a niggling doubt in the back of your mind.
Do not ignore this doubt, its the product of experiencing and the surest way to recognise the presence of the enemy. 

No comments:

Post a Comment