Saturday, 14 December 2013

The Gas Factory Anti-Pattern

I know I promised to talk about the challenges of Unit Tests next (and I will soon) but I thought it an opportune moment to discuss a growing problem that greatly benefits from Unit Tests. I consider it to be one of the worst anti-patterns as it is largely unrecognized and has dreadful consequences for maintainability of software.

Luckily, most anti-patterns are occurring less frequently as more and more developers learn how to design and build software better. However, this anti-pattern
I sometimes discuss anti-patterns that I think are not well known or under emphasized. For example, see Layer Anti-pattern. If you don't know what anti-patterns are see the Wikipedia page.
seems to be on the rise. It also seems to occur most commonly in overtly well-designed code. I am talking about what some people have called the Gas Factory anti-pattern.

The Problem

Essentially the problem is caused by code that tries to do too much or be too flexible at the expense of being overly complex for the task for which it was intended. (I used to call it the Swiss Army Knife anti-pattern but Gas Factory has better negative connotations. :) This strikes at the heart of software design - see my first blog post Handling Software Design Complexity.

I first encountered this problem about 20 years ago (though it did not have a name until recently). I believe it is mainly due to the fact that about that time (or earlier) code reuse was being pushed as the software development "silver bullet" and a generation of designers got into the habit of trying to make their designs more general and flexible. But this flexibility comes at the largely unappreciated cost of complexity (and reducing complexity has always been my number one aim in life :). I have already covered a lot of this in my blog on the problems of making code reusable at Reusability Futility, so I won't go into that again.
Doing a Google search it seems that some people think that the Gas Factory is caused by the code bloat of a very inexperienced programmer. (You know the sort of code you would write when you first started to learn to program.) However, this is simply due to inexperience.

The Gas Factory anti-pattern actually tends to affect experienced developers more than inexperienced ones.

The problem is that the "best" designers are often the worst offenders. Just look at the horrendous Windows API which I have heard was created by very experienced developers. (Luckilly .Net is much better.) The practice is often motivated by the best of intentions and on the surface may even seem like the right thing to do, but the side-effects can be severe.

Thought Processes

I have identified some thought processes that I, and others, have been guilty of in the past that has caused the problem in some designs I have used:

1. An ambition to build some general purpose library that just happens to solve the problems at hand as a subset of a much more general set of problems. The cost is a library that has many disadvantages (longer to develop, harder to verify etc) but the main cost is in the increased complexity for anyone using or maintaining it.

The way to avoid this is to focus on the problem at hand and not on any more general problem, or possible future changes. This behavior is the motivation in Extreme Programming for the rule that you should never code for the future, only the immediate requirements (see YAGNI below).

2. When coding, a temptation to add some unneeded facility now, for a perceived negligible cost which would be hard to add later and (it is assumed) would surely be needed. I actually believe that it is sometimes a good idea to add such "free" features while the code is fresh in your memory as long as you can squeeze it into the sprint and it doesn't become an undocumented feature.

However, it may be a good idea to disallow this as a general policy of YAGNI. Prohibition reduces the chance of unauthorized changes and undocumented features creeping in, which can become a maintenance problem down the track.

The crucial part of this thought process is the phrase "hard to add later". Here again, Unit Tests (see previous post on Unit Tests) can help by making later changes much easier.

3. The desire to test some new technique or technology, even though its use will complicate the design for no real advantage. This is the worst reason, at least morally, as it places self-interest ahead of the interests of the customer or company. I am appalled that this practice is extremely common in the industry, since it is often tolerated or even goes unnoticed.
it places
self-interest
ahead of...
the customer

This problem is not often discussed but I am very glad that I read about it recently in "97 Things Every Software Architect Should Know". In fact it is "thing" number 1: Don't put your resume ahead of the requirements by Nitin Borwankar.

Of course, it may not be done consciously. It is often due to something the developer has recently read. They may, at that brief moment in time, honestly believe that trying some new pattern, practice, tool or algorithm is the best way to accomplish the task. However, I still feel that at the back of their mind their is some nagging guilt that it is not in the customer's best interests.

YAGNI

I have talked about the XP (Extreme Programming) principle of YAGNI (You Ain't Gonna Need It) before. To recap, this is a policy of only ever building what you know is needed right now. Actually many Agile proponents go further: only ever add the smallest incremental change that still leaves you with working software. YAGNI puzzled me at first but now I realize that not following this idea resulted in much of the problems and frustrations I have had to overcome in many projects in the past few decades.

Many of the libraries and tools I have worked with (and created too) have been overly complex by trying to anticipate future changes or other uses that almost always never eventuate. One former colleague, after spending many months creating such a library to be used as the basis of another program (hi Alex) described it as like "building the foundations for an airport runway, only to put a shack on it".

The counter-argument against YAGNI is that it will result in software that is harder to modify, because you are not allowing for future changes. First, I will say that often the simpler software ends up being easier to modify than the software that was designed to be modified. This is my experience, and I'm not sure why, but it may be that changes rarely eventuate as anticipated. However, I do agree that there is a lot of validity to this counter-argument but I have an ace up my sleeve...
  Unit Tests...
free you from the
burden
of thinking about
the future

There is also one final, crucial part of the puzzle: Unit Tests! If you have a full set of Unit Tests you can modify with impunity. This frees you from the burden of thinking about the future so you can concentrate on the important thing - what the customer wants right now.

Conclusion

The Gas Factory anti-pattern is growing. The unnecessary complexity it causes has many bad effects. First and foremost, it makes the the design of software hard to understand which makes it hard to build and maintain. Moreover, the reasons for doing it, are obviated by the use of Unit Tests.

If not (yet) the most serious bad design practice then it is the most insidious. It is so insidious that many people are not even aware of it -- it was even recently removed from the Wikipedia page on anti-patterns because somebody thought it was a furphy.

1 comment:

  1. This comment has been removed by a blog administrator.

    ReplyDelete