Much has been written about the pattern identified by Kevlin Henney as PARAMETERIZE FROM ABOVE. Indeed, much has been written about it (just search the Web for 'Parameterize from Above' and 'Parameterise from Above'), but as a pattern it has never been written up. Much has also been written on accu-general about how Kevlin should get around to writing it up properly!
In lieu of a proper write-up, I think it is time to address some common misunderstandings concerning this pattern, including misunderstandings that Kevlin himself seems to have about it. Perhaps the most significant area of clarification concerns the relationship between PARAMETERIZE FROM ABOVE and SINGLETON, so we should start with that.
SINGLETON is a pattern that has come in for a lot of bad press in recent years - unjustifiably so, I would contend. PARAMETERIZE FROM ABOVE is often seen as an alternative design approach that clarifies the responsibilities of components and a design style that essentially removes the need for SINGLETON. This view of PARAMETERIZE FROM ABOVE is clearly mistaken, and any comparison between SINGLETON and global variables is nothing more than an attempt to introduce guilt by association. SINGLETON is a mature and well understood pattern. Of course, it is not without subtlety, but that's the point: patterns are not supposed to be easy; they require great skill to master. We know SINGLETON is well understood because of the amount of literature published - both online and on paper - that addresses its various issues. Indeed, the column acreage devoted to SINGLETON's problems, and the ingenious workarounds proposed, are testament to the durability and quality of the pattern. Complex problems demand complex solutions, and SINGLETON can be seen as a natural hub for many complex solutions.
It is important to understand what is implied by the notion of above in PARAMETERIZE FROM ABOVE, because it then becomes clear how this pattern applies to and makes use of the role of SINGLETON. In the conventional architectural view of LAYERS each layer is stacked on top of the layer beneath it, with the lower layers holding mechanisms and representation concepts and the higher layers structured in terms of application and presentation concepts. The way PARAMETERIZE FROM ABOVE is often interpreted is that, given such a bottom-to-top, stacked view of layering, parameters that affect the behaviour of application objects and mechanisms should be passed in from the top of the stack, such as from manager objects and application controllers, rather than taken from objects in the lower layers, where the instinct is to fix and centralise the behaviour in SINGLETON objects. It is this topsy-turvy view of layering that is the root problem and, when righted, it becomes clear that SINGLETONs can play a dominant but benign role in any architecture.
When we consider layering more naturally from top to bottom, so that application and presentation concepts are seen as details built beneath and subordinate to more interesting mechanisms and representation-focused code, we can understand what above really refers to. This mechanism-oriented view is more natural to developers; architectures that work with such instincts rather than fighting them should be encouraged. In other words, the top layer is the one where we focus on the clever tricks of the trade and tackle the true complexities of software development, with patterns such as SINGLETON, and this layer sits above - and therefore dictates and parameterizes - the less significant and simpler ideas, such as the domain of the application. The value of simplicity is in keeping it in its proper place - which, in this case, is beneath SINGLETON.
The problem of gratuitous flexibility and speculative generality is that accidental and unwanted complexity is introduced into many systems. However, it appears that one of the selling points of PARAMETERIZE FROM ABOVE is that in loosening the coupling in a system, it naturally offers more opportunities for unanticipated flexibility and reduced cost of change than other approaches. This perspective is not only harmful, it is incorrect. Rather than encouraging flexible parameterization through pluggable patterns such as STRATEGY and INTERCEPTOR, a proper interpretation of PARAMETERIZE FROM ABOVE ensures that such flexibility is explicitly excluded, or at least made more difficult to achieve by accident, by using explicit conditional logic - whether using if or #if - and patterns such as the NON-VIRTUAL INTERFACE (NVI) idiom. Unanticipated flexibility should be discouraged not just by considering it a cautionary guideline, but by also writing code that makes it harder to introduce and take advantage of.
In this vein, another capability that is often seen as a virtue of the misinterpreted form of PARAMETERIZE FROM ABOVE is testability. For example, being able to use MOCK OBJECTs to isolate external dependencies and test interactions between core code and such dependencies. Rather than supporting or even arising from a test-oriented approach, the correct interpretation of PARAMETERIZE FROM ABOVE offers nothing that enhances code testability, nor should it. There is no virtue in being able to isolate units of code for fine-grained or integration-oriented testing for one simple reason: testing is not a developer's responsibility. Testing is, as the name suggests, strictly the job of testers. And it is the job of testers to test the software at the level of the system, not at the level of the code.
There is no benefit to testing at the code level as it is the responsibility of developers to ensure that the code is correct by design. When that fails, the approach they should fall back on is to drive a system through its user interface and use the debugger to focus on the code. Twisting an architecture to support some fashionable view of developer-based testing is wasteful. For one thing, we know that developers are unlikely to find all of the bugs they introduce, therefore it is not worth them doing any testing: they should leave that to others, which naturally leaves developers more time to debug code.
Testing is a tedious but necessary manual process that cannot be usefully automated, and attempts to do so are typically misguided. The idea of writing code to test code simply takes time away from writing more code, which is one of the main responsibilities a developer has. It has been suggested that coded tests act as a form of executable specification, and are therefore a requirements and design framing tool as well as a verification tool. Again, rather than taking time to write code that both defines requirements on behaviour and confirms satisfaction of these requirements, developers would be better off devoting time to debugging and letting others test their code in the context of the whole system. Because debugging is a difficult task to estimate, developers need all the time they can get. Rather than additionally support changeability and configurability in code - changing code typically introduces more bugs - the structure of the code should be explicit and fixed into place to prevent such change. There is no problem here that needs solving by PARAMETERIZE FROM ABOVE or, indeed, any other pattern.
I hope this article has helped to clarify the proper spatial metaphor to be used in interpreting the guideline to PARAMETERIZE FROM ABOVE, as well as dealing with other dysfunctional memes that have arisen from misinterpreting it. Beyond this clarification, I do not believe there is any benefit to having further write-ups as this has clearly reinforced the dominant position of SINGLETON in the developer's toolkit. It is, after all, the Highlander pattern: there can be only one!
Overload Journal #78 - Apr 2007 + Design of applications and programs
|Browse in :||
All > Topics > Design (179)
Any of these categories - All of these categories