Patterns are social animals and are often found in the company of others. This issue, Kevlin Henney looks at where 'Parameterise from Above' has been hanging out.
In this second instalment of 'The PfA Papers' we look at how the Parameterize from Above (PFA) pattern came of age. It got a name for itself and joined a touring company of recommendations, the Programmer's Dozen .
Last time [ Henney2007 ] I described the genesis of the (to date undocumented) Parameterize from Above pattern in a review of a system for a client of mine. It was described originally under the heading of 'Parameterisation from the Top'. The theme of the original write-up was to (1) make globals parameters rather than globals and (2) move them to the top layer of the system, from where they would be passed down as parameters. This upward movement is the key and applies to many kinds of objects, not just simple configuration constants.
The concern most commonly addressed by PfA is that of configuration, a common motivation (or excuse) for globals of different types: global constants scattered arbitrarily across different headers and classes or coincidentally grouped into a single uncohesive header; global objects representing raw or encapsulated handles to external resources, such as registries and configuration files; free functions offering sometimes stateful APIs to these external resources; Singleton objects that offer apparent absolution of the guilt of globals through the blessing of a recognised pattern. Free functions in a namespace or static methods in a class may have scope etiquette, but they are globally accessible nonetheless.
In discussions I had at the time with Hubert Matthews he suggested the name 'Configuration from Above'. And I am pretty sure that it was Hubert rather than me who suggested the more relative - '... from Above' - rather than absolute - '... from the Top' - naming of the practice. This name also plays to the recursive, recurrent and typically scale-free nature of software structure [ Potanin+2002 ]. The practice is not simply about hoisting the configuration decisions all the way up to the top of the system, the idea applies consistently to any calling, usage or client-supplier relationship we find, whether a layer-to-layer, a package-to-package, a class-to-class or a function-to-function relationship. Importantly, even when there is no obvious 'top' to speak of, the recommendation still applies.
The discussions we had also made clear to me the styles of usage and range of applicability of this pattern, clarifying in my mind that although configuration was one of the most common motivators, it was not the only one. The parameterization applies to many cases where we pull out some common parameter - whether a runtime variable or a compile-time type - and have the user (or its user) responsible for making the policy decision. Hence my preference for sticking with a name that focused on parameterization rather than just configuration.
The shift in name from 'Parameterization from Above' to 'Parameterize from Above' was motivated by considering PfA to be an active recommendation rather than simply a passive description of structure. This took place - and the pattern took its place - in the context of a set of thirteen recommendations I named the Programmer's Dozen .
Like PfA, the Programmer's Dozen grew out of code and design consultancy on a client's C++ code base. In looking for a way to organise and present specific recommendations, I found twelve headings that worked well, each one phrased positively as a guideline. I published these guidelines in two of my C++ Workshop columns in Application Development Advisor [ Henney2002a ] [ Henney2002b ].
However, even before these two articles had been published, during the many months between article submission and the echo of print, I had consolidated, reorganized, generalized and augmented the recommendations. Some of the recommendations were merged because they could be considered two different takes on the same guideline. Some new ones were introduced, which is when Parameterize from Above made its appearance. The recommendations were also no longer presented as C++-specific recommendations: I had found them useful in Java-related work, as well as elsewhere. And there were no longer twelve of them: there were thirteen. The creative tension between my lingering fondness for the numerical convenience of the original dozen and the obvious inequality with the number thirteen ultimately inspired the name Programmer's Dozen .
I first presented the Programmer's Dozen in a talk at the JAOO conference in Aarhus in 2002 [ Henney2002c ]. I have had a long-standing interest in the idea of 'less code, more software' and 'decremental development', and I found that the thirteen recommendations tended to enforce this. This was one reason they were presented under the heading of 'Minimalism: A Practical Guide to Writing Less Code'. That, and the fact that I submitted the talk abstract before realising that the dozen would fit the bill! It was a short talk, so each recommendation took only a slide. Here is the presentation of PfA:
- Global packages, Singletons and bundles of constants should be rationalised or eliminated. They introduce coincidental coupling, so code is less adaptable and harder to test.
- Use arguments and interfaces to invert dependencies.
There is, of course, (a lot) more to say on it than just this, but all the ingredients are there - including an explicit mention of Singleton. Later presentations also tended to use the phrase 'parameterize with parameters', which helps make both the motivation and the style of PfA clear.
Although the names and ordering of the Programmer's Dozen changed a couple of times from 2002 to 2004, the actual set of recommendations has been stable since its inception. Here's the full dozen as they currently stand:
- Prefer Code to Comments
- Follow Consistent Form
- Employ the Contract Metaphor
- Express Independent Ideas Independently
- Parameterize from Above
- Restrict Mutability of State
- Favour Symmetry over Asymmetry
- Sharpen Fuzzy Logic
- Go with the Flow
- Let Code Decide
- Omit Needless Code
- Unify Duplicate Code
They fall into four categories: (0-2) code meaning; (3-7) code dependencies; (8-10) code execution; (11-12) code consolidation. Since its creation I have used Programmer's Dozen as a teaching aid, a reviewing framework, a conference tutorial and a standalone seminar. It has not escaped my attention - or indeed the attention of publishers, conference goers and colleagues - that the Programmer's Dozen would make a good book. Who knows, that may happen.
But I digress. This series of articles exists because, more specifically, Parameterize from Above would make a good article.
Of patterns and recommendations
It may sound like there is a contradiction or conflict in containing Parameterize from Above, which is normally referred to as a pattern, within a set of recommendations. So, is it a pattern or is it a recommendation? It is both: there is no exclusive-or relationship between the two concepts. By definition, a pattern makes a recommendation. A pattern is neither a law nor a hard rule but a recommendation that addresses a particular recurring problem. A pattern is contingent and contextual rather than unconditional and universal. In such cases whether a practice is considered a recommendation or a pattern is mostly a matter of form and presentation. In presenting a pattern, there are matters of style and content that are normally considered important - context, problem forces, solution structure, consequences - that a reader may consider less valuable if they are looking for a more conventional exposition of a practice, one that is perhaps less problem focused and less constrained in its prose and presentation.
The term recommendation also sets a different expectation in the mind of the reader and the listener, one that is perhaps less charged and sometimes more accessible than pattern. Although recommendation needs a little qualification - e.g., weaker than a rule, stronger than a consideration - it is a less polarised and misunderstood term than pattern, which can be appreciated and reasoned about at many different levels and from many different perspectives [ Buschmann+2007 ]. On the other hand, one of the benefits of focusing on a recommendation as a pattern is that it encourages a strong focus on the rationale for the recommendation and the empirical support for it. It is a useful exercise to examine your own development habits and design preferences and the recommendations of others in this light. You may find the process of identifying the nature of the problem, including its context and forces, and weighing up the consequences of the proposed solution, both pros and cons, reveals both surprising insights and contradictions.
Although I have favoured a more conventional presentation of the Programmer's Dozen recommendations, the pattern perspective has never been far from my thoughts, especially for Parameterize from Above - and not just because of some nagging sense of guilt that I should write it up! The advice to Parameterize from Above offers an obvious counterbalance to the common alternative - which, for the sake of comparison, we could term Hardwire from Below. The pattern perspective can encourage a more rigorous and balanced assessment of a practice, which is no bad thing when the alternative pattern space is populated and popularised with Singleton, Monostate and the assorted application of global and static variables.
Of course, simply because something is made as a recommendation or documented as a pattern, does not mean that it is necessarily good. Singleton and co are often expressed as unconditionally good ideas - assuming that pattern → good or 'it's popular, so it must be good' - whereas in practice they are either dysfunctional at heart or dysfunctionally applied [ Buschmann+2007 ]. The benefit of really working through a documented pattern form is that, if studied and applied diligently, limitations and conflicts should become more obvious than is often the case when a recommendation is described in more freeform prose.
When Programmer's Dozen was first drawn up I also put together notes for writing up and connecting the recommendations as a pattern language. A pattern language is a collection of patterns that are connected in a form that supports incremental application and growth. However, this work never saw the light of day. In its original form, apart from seeing them as a collection of mutually supporting patterns, the dozen did not obviously form an actual pattern language: the individual patterns were easy to describe, but a simple, non-web-like set of interconnections eluded me. If I were to return to it today, the current ordering of the patterns (as listed earlier) offers a more obvious progression than the order I used five years ago, and is therefore a better pattern sequence around which to form a language. There's a lot more to be said on how to document patterns, pattern sequences and pattern languages, as well as on the role of pattern collections in capturing a particular development style, but that is beyond the scope of the current series of articles [ Buschmann+2007 ].
[ Henney2002a] Kevlin Henney, 'Six of the Best', Application Development Advisor , May 2002, available from http://www.curbralan.com
[ Henney2002b] Kevlin Henney, 'The Rest of the Best', Application Development Advisor , June 2002, available from http://www.curbralan.com
[ Henney2002c] Kevlin Henney, 'Minimalism: A Practical Guide to Writing Less Code', JAOO, September 2002, available from http://www.curbralan.com
[ Henney2007] Kevlin Henney, 'The PfA Papers: From the Top', Overload 80 , August 2007, http://accu.org/index.php/journals/1411
[ Potantin+2002] Alex Potanin, James Noble, Marcus Frean and Robert Biddle, 'Scale-free Geometry in Object-Oriented Programs', Victoria University of Wellington Computer Science Technical Report , December 2002, http://www.mcs.vuw.ac.nz/comp/Publications/CS-TR-02-30.abs.html , published in Communications of the ACM, May 2005