In this part of article series for "Software patterns- GRASP", we would explore the process of assigning responsibilities so has to handle the situation where the existing domain classes are violating the High cohesion and low coupling principles in turn using Pure Fabrication in such scenarios.
To understand the GRASP pattern “Pure Fabrication”
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. In this part VIII, we would focus on next GRASP pattern named “Pure Fabrication”. Generally working on existing system, everybody fumbles on a dilemma about changing the existing design. Imagine scenario where the existing classes have low cohesion and high coupling rather it violates the High cohesion and low coupling. It would be overkill to change the existing classes in entirety or even it could be unviable from the perspective of budget(and time). The principle behind this pattern is to resolve such a dilemma by deciding on “Whom to assign responsibilities when assigning to existing domain classes violates High cohesion and Low coupling?” These domain classes are generally the Information Expert classes.
Problem: Who should be responsible when an expert violates high cohesion and low coupling?
Solution: Assign the responsibility for handling a system event message to a class which is new fictitious (artificial) and doesn’t represent a concept in domain.
Assign the cohesive set of responsibilities to such class in order to support high cohesion, low coupling and reuse.
As this class is fictitious hence it can be called as its outcome of imagination or pure fabrication.
Step I: Closely look at domain/ design model and locate the classes with low cohesion and high coupling. e.g. “Sale” class doing all the database operation related to “Sale”
Step II: Create a new class to take the responsibility of functionality causing low cohesion and high coupling
Let’s extend an example of POS (Point Of Sale) systems explained in previous part. We are fairly aware of “Sale” class by now. By principle of “Information Expert”, the responsibility of saving the instance of “Sale” is with the “Sale” class. (Left part of Fig no.1 i.e. “Design I”)
This results in large number of database oriented operations which actually has nothing to do with “Sales”. Also there could be additional overhead of transaction related stuff. This leads the “Sale” class towards the low cohesion (remember the definition, “A Class responsible for many things in related areas”) i.e. the database operations are related but it ends up doing many things. Also while performing such database operations; it would need to employ the database interface culminating into low coupling. In fact, such database operations are generic in nature and have potential for reuse.
The solution is to create a new class say “StorageAgent“which would interact with database interface and saves the instance of “Sale” class. As “Sale” would be spared from saving its own instance into database thus giving rise to high cohesion and low coupling. In this fashion the “StorageAgent” is also highly cohesive by performing the sole responsibility of saving the instance / object. (Right part of Fig no.1 i.e. “Design II”)
Fig No. 1
Relationship with other classes
Responsibility and method
Call upon the StorageAgent- delegates the responsibility to other calls
To represent a particular “Sale”
A separate class having unique responsibility of saving the objects to database. This can be utilized by other classes like “Register”, “Payment” etc.
Saving the objects to database through “InsertToDatabase()”
As demonstrated, the “StorageAgent” is a generic and reusable class. All such classes i.e. pure fabrication (rather purely fabricated) classes are function centric. Other good examples are the adapters, observers and one would find many examples in a service layer.
As per Larman, there are 2 approaches of designing which the pure fabrication is the behavioural way
· Representation decomposition: Designing the objects the way they represent in the domain
· Behavioural decomposition: Designing the objects the way they do. These are function centric or encapsulate algorithm
Commonly, the pure fabrication is used to place / encapsulate the algorithm or function which doesn’t fit well in other classes.
· Supports Low Coupling
· Results in high cohesion
· Promotes reusability
· Sometimes such design may result into bunch of classes having a single method which is a kind of overkill.
Summary & Conclusion
In this part, we discussed what Pure Fabrication is and also the principle behind this. We discussed the steps for assigning responsibility. We saw practical example from POS (Point Of Sales) and explanation for having pure fabrication. Specifically we saw an example of “StorageAgent”. The benefits and contradiction are mentioned.
To reiterate, following/ employing these patterns for design would result into highly maintainable, robust and reusable systems.
Applying UML and Patterns