In this part of article series for "Software patterns- GRASP", we would explore the process of assigning responsibilities so as to protect the objects from variations in other objects/elements.
To understand the GRASP pattern “Protected Variations”.
We have explored what are patterns and GRASP (in part I), Information Expert in part II and Creator in part II, Controller in Part IV, “Low Coupling” in part V and “High Cohesion” in part VI and Polymorphism in Part VII, Pure Fabrication in Part VIII, “Indirection” in this part IX, we would focus on next GRASP pattern named “Protected Variations”. This is going to be last pattern in the series and we would end this series with one more article summarizing all our discussions.
This pattern is in line with the pure fabrication and Indirections in a sense that it addresses similar concerns. The principles are same like low coupling high cohesion, reuse but the focus is on protecting the existing objects from variations. i.e. creating a stable interface so to protect from variations in coupled objects.
As in the programming world, the change is the only constant thing. Everything right from user requirements, business domain, technologies and even human resources also change (thanks to attrition).
So the changes (variations) in the software systems are inevitable. If some part in a system is changed it would have effect on other parts/elements of the system. Many a times such changes are destabilizing ones.
Take an example of change in .NET framework from 1.1. to 2.0. Many can remember the breaking changes occurred in the system may be because of lack of proper system design. Similarly it is true for other versions or technologies or the changes in requirements too.
So is there any way to minimize the effects or way to ensure that such changes (variations) don’t have undesirable effects on other elements or system operation? Yes, exactly that’s the principle for pattern “Protected Variation”.
The principle behind this pattern is “How to design objects so that variation or instability does not have an undesirable impact on other elements?”
Problem: How responsibilities should be assigned in such a fashion that the current or future variations in the system do not cause major problems with system operation and/or revision?
Solution: Assign responsibilities to create stable interfaces around current and future variations.
This may involve creation of entirely new classes to encapsulate such variations.
Step I: Closely look for elements with direct coupling and also relatively prone to change.
Step II: Identify for the objects or points of predicted variation
Step III: Assign these responsibilities in such a way to create a stable interface around them.
In short “Find what varies and encapsulate it.”
In a nutshell, Protected Variations addresses the problem of assigning responsibilities in such a way that variations that might occur do not have undesirable effects upon other elements in the system. In this context, the interface is used in the broadest sense and need not be similar to C# construct called an “Interface”. This could be a complete separate subsystem fronting a much larger set of variable subsystem. This pattern, or rule, is very broad and complex. This is a fundamental design principle and used in conjunction with polymorphism and indirection.
This is also very closely linked or similar to the principle of information hiding (which was proposed by David Parnas) that underlies OOP and Bertrand Meyer’s Open-Close Principle.
According to Larman, PV (Protected Variations) is a very important and root principle motivating most of the mechanism and patterns in programming and design to provide flexibility and protection from variation, almost every design trick in his book is a specialization of the Protected Variations pattern.
As usual let’s see a practical example for this pattern in POS. We are fairly aware of the classes like Sale, Payment, and SaleLineItem etc. Every sale amount has taxes applied to arrive at the total. There are different tax rules at different places and tax rates are different also. On top of this the rates and rules are bound to changes which makes the design of such systems tricky. The best approach is design the tax calculation as separate system. There could be different tax calculator systems (third party) available or there could be web service providing the tax calculation services. There might be reason for having multiple systems or move to different system. As mentioned above, the rules, rates are the moving target and as these changes the tax calculation systems have to follow. This is the point of variation or stability. In such scenario, the changes would be the consumers or users of such systems, to change also. These changes or variations would cause the changes in POS system or it may require revision.
This is where the “protected Variations” pattern helps to design in such a way that the changes in the tax calculation system would not cause major problems. This is accomplished through implementation of polymorphism and indirection as depicted in the following diagram.
Fig No. 1
Responsibility and method
Facilitator for different adapters to different systems
Provides polymorphic behaviour and handles the variations based on the type.
Facilitator for particular Tax System
These classes provide indirection i.e. facilitates low coupling and reuse.
Hopefully the above diagram would help to understand this pattern.
As PV is omnipresent in the world of patterns and also motivate many patterns, it got to have some mechanism and principles. They are
· Core: The “Core” mechanism for PV is as following
§ Data encapsulation
· Date driven Design
§ Reading codes, class file paths, class name
· Service Look up
§ UDDI :Universal Description, Discovery and Integration is a registry which is platform independent which is modality to register and locate web services i.e. in turn it helps to look up the services
§ LDAP: It is Lightweight Directory Access Protocol which is meant for accessing (connecting), search and modify the internet directories. This is service protocol running a layer above TCP/IP stack.
· Interpreter Driven Design
§ Virtual machines
§ Neural networks
§ Logic engines
§ Rule interpreters
· Reflective of meta level design
§ Java introspector
§ .NET reflectors
· Uniform access
§ Language supported constructs that do not change with underlying implementation
E.g. method and attributes are invoked same way (C#), Standards (e.g. APIs like ADO.NET, ODBC, JDBC etc)
These mechanism means wherever these mechanisms are encountered e.g. data encapsulation, service look up, one has to implement PV in some or other form.
Related Patterns and Principles:
As stated above PV is fundamental principle, so lot of patterns in programming are related to this. In the landscape of GRASP, Pure fabrication and indirection are related patterns. There are many principles or rules or guidelines which are related to PV. They are
· Don’t talk to strangers – i.e. only send messages to the objects if the sending object has direct reference to
· Law of Demeter: This is specific instance of loose coupling which advocates that the given class or object have least knowledge of other elements i.e. the structure or properties of other elements.
· Liskov’s substitution principle: This states that “The derived types must be completely substitutable for their base types.”
· Parnas information hiding: David Parnas proposed this idea in his paper in 1972. This was proposed for modular programming practice which eventually become part of object oriented design. It is the principle of segregating the “difficult design decisions or design decisions which are likely to change." Hiding information in that manner isolates clients from requiring intimate knowledge of the design to use a module, and from the effects of changing those decisions
· Meyer’s open closed principle: In 1988, Meyer coined this term in his principle which states that the “module shall be open for extension and closed for modification”. This in turn conveys that the implementation of a class could only be modified to correct errors but new or changed features would require that a different class be created inherited from the existing one.
· Extensions required for new variations are easy to add.
· New implementations can be introduced without affecting clients.
· Coupling is lowered.
· The impact or cost of changes can be lowered
Liabilities / Contradictions:
The design cost of speculative “future-proofing” i.e. protecting from future variations at evolution point may outweigh the design cost incurred by a simple design that is reworked as necessary. Evolution point is a speculative point of instability or variation that may arise in future, but not specified in current requirement. This means sometime a simple design with no PV can cost a lot less in the current time and this can be reworked when future variation becomes reality.
Summary & Conclusion
In this part, we discussed the “Protected Variations” and also understood that it is fundamental principle in software design practices. We discussed the practical example from POS and also the approach. What is more interesting was to discuss the related patterns and principles which uncovered many principles and rules in software design.
To reiterate, following such patterns for design would result into highly maintainable, robust and reusable systems.
Applying UML and Patterns