This summer I went walking in the Lake District with my girlfriend, and on one of the days we found ourselves walking through a mist that reduced visibility to around 10 metres. Unable to use other mountains as reference points (or, indeed, much of the mountain we were on) we were reliant on a compass and dead reckoning. Despite our best efforts we eventually found ourselves on a scree slope with no sign of a path. We were not exactly lost - we had a bearing to follow and would eventually reach landmarks and a path leading us to our destination, but the going was slow and difficult.
While we were debating where we'd missed the path a voice came from the mists hiding the top of a near vertical rock face "you shouldn't be down there - the path is up here". While that gave a point of reference, it didn't solve the problem of how to proceed from where we had arrived. We had gone wrong, but we had company: another group of people arrived and by all sharing the results of exploration we found a way forward that eventually rejoined the path.
This story does have relevance to Overload but, before explaining the connection, I'm going discuss a little of what happens behind the scenes to produce the copies of Overload that arrive for you to read every couple of months. You have probably guessed a part of it, but the issue that I want to address is one that rarely makes an explicit appearance in the journal:
people write articles (volunteers to do this are always welcome);
the articles are reviewed by the panel of advisors (this usually leads the authors to revise the articles); and,
the editor chooses the articles to accept, pass to C Vu or which to reject completely.
Usually the review by the advisors is uncontroversial, but occasionally an article generates real debate. When considering Jeff Daudel's article "A Unified Singleton System" (Overload 56) there was such a concern over the content of the article that the editor (then John Merrells) was moved to include an editorial comment. And, in the next issue, one of the advisors (Mark Radford) wrote a balancing article "Singleton - The Anti-Pattern!" (Overload 56).
Such debate is rare, most articles present material that the whole editorial team is happy with. However, it has happened again (but on a lesser scale). One of the articles published in the last issue moved one of the advisors, Phil Bass, to email me re-iterating the concerns that he expressed about the article when first presented. I could have relegated this to the "letters" page but, by implication, it raises issues of editorial policy that I feel should be discussed.
First here is what Phil Bass has to say:
When Allan Kelly's article entitled "The Encapsulate Context Pattern" was circulated for review I expressed considerable disquiet. This is what I said in an email on 23rd August:
"It actually presents an Anti-Pattern as if it were a real Pattern giving the impression that it represents good practice when, in fact, the opposite is true.
Also, I believe the mention of Kevlin Henney, Frank Buschmann and EuroPLoP gives the article an unwarranted air of authority.
I would prefer this not to be published. If it is published I think it should be accompanied by further discussion so that dissenting views can be expressed.
You were not convinced by my argument, no-one else expressed any reservations and the article was published without comment. In spite of that I remain convinced that publication of this article did more harm than good and I would appreciate the opportunity to argue my case in the pages of Overload."
I will come back to Encapsulate Context in a moment, but first I would like to make an analogy:
Pattern 24 - Swap Colours
You are playing chess.
You are down to one bishop and it's on a black square. Unfortunately, your opponent's major pieces are all on white squares and you are struggling to create an effective attack.
The Bishop is a useful piece. You don't want to lose it.
The Bishop needs to be defended, but you would prefer to use your pieces to attack your opponent's position.
Change the colours of the squares on the board. Black squares become white and white squares becomes black. Now you have a bishop on a white square.
I won't try to push the analogy any further because this "pattern" is quite obviously complete nonsense. It describes a genuine problem and presents a false solution. Ignoring, for the moment, that changing the colours of the squares is against the rules, it actually doesn't address the real problem.
I believe "Encapsulate Context" has all the hallmarks of "Swap Colours". In my opinion, it describes a genuine problem and presents a false solution. I will try to explain why...
I think it is fair to summarise "Encapsulate Context" as follows:
Many systems contain data that must be generally available to divergent parts of the system.
Using global data is poor engineering practice.
Using long parameter lists in order to avoid global data has an adverse effect on maintainability and object substitutability.
Long parameter lists can be avoided by collecting common data together into a Context object and passing that in parameter lists.
- Resulting Context
Using a Context object improves substitutability, encapsulation and coupling, and reduces the need for copying data.
First of all I am not at all convinced that the pattern context occurs in well-designed systems. Allan presents an example that purports to illustrate how the context arises, but I don't find it at all convincing. Personally, I would not be tempted to design a stock exchange trading system like that example, so it looks like a straw man to me. However, let's give Allan the benefit of the doubt and work on the assumption that such systems do exist.
I agree that global data is a Bad Thing. And I agree that overly long parameter lists are a sign of a problem. But long parameter lists are only a symptom of a deeper problem. Coalescing several parameters into one changes the interface in only a trivial way. The same information is passed from the client code to the function, so coupling and cohesion are not significantly different.
Now, if we consider many different functions spread throughout the system and a Context object that contains all the global information that any of those functions might need, things definitely get worse. Where a function actually needs only one item of global data we provide it with all the global data items, introducing unnecessary coupling. And where that function originally had direct access to the one item of global data it needed, now it must extract it from a Context object, increasing the complexity of the interface.
The resulting context is a significantly more coupled system. As far as I can see, the effect on maintainability is minimal, there is no effect on substitutability, and encapsulation has suffered. We have gone from a Bad Thing to an even Worse Thing. That is the opposite of a design pattern; it is an Anti-Pattern.
I will add just one further comment. If you find yourself designing a system with significant amounts of global data and/or passing data between distant parts of a system, you have a problem. It may be a deep-seated problem. Think carefully about what this data is, where it is needed and how the system is partitioned. The problem can only be solved by a fundamental restructuring of the system. There probably isn't a single design pattern that will do that. "Encapsulate Context" won't help you. Don't use it.
OK, here we can see real concerns being expressed about the article. So why then did I choose to publish it without comment? Well, partly because the other advisors and I don't share these concerns.
While we agree with Phil that it would be better to have avoided arriving at the problem, people do get to this point and don't always have the opportunity for a "fundamental restructuring of the system". It is more helpful to facilitate the communication between such people than to take the part of the anonymous voice saying "you shouldn't be down there". It may serve as a warning to avoid retracing the steps that lead to the situation, but doesn't address the tactical problem of dealing with it.
Maybe I was wrong. I can imagine that some Overload reader somewhere is facing the problems described by Allan Kelly. They probably know they have problems, but upon reading the article they may get the impression that the solution presented solves the underlying problem and not only the symptomatic one. This too is a pattern "Shifting The Burden" - described by Peter Senge in "The Fifth Discipline" (an excellent book on organisational problems). "Shifting The Burden" is a bad practice or "anti-pattern" largely because by failing to address the true causes of a problem, but giving the appearance of fixing it, it encourages the problem to grow to proportions that make an eventual solution problematic.
Maybe I was right. I've used "Encapsulate Context" in the past - albeit long before reading the article. I took an application that had, scattered throughout its code, snippets of code that went to various sources of configuration data (the Windows registry, the command line, several databases, configuration files) and moved all of these snippets into a context object. This made it far simpler to test components (we didn't need to set up copies of all the sources of configuration data for each test). When additional configuration data was required by some new code, it was clear how to obtain it - from the context object. And the difference between live and test configurations became easy to parameterise. Even the author of the original code was impressed by the changes. That system is still running and being developed and - as of the last report - without suffering the high maintenance/low testability problems that are a risk of such highly-coupled approaches.
There is a fine line to be drawn here and, while I think that we got this one right, it is necessary to be vigilant. The role of the Overload team is to help the author present tools and techniques that may be of use to the reader and let the reader be the judge of when they are appropriate. I expect readers to use their judgement when considering the application of such ideas - they should know that there are always trade-offs. Knives and forks can be dangerous, but I don't insist my children eat with blunt sticks. And the lesson I take from my experience in the Lake District? While it is good to know where one should be it is also worth listening to the people solving the same problem you have encountered where you are.