In this part of article series for "Software patterns- GRASP", we would explore the process of assigning responsibilties so has to support high cohesion resulting in less complexity and promoting reuse through the implemention of the pattern "High Cohesion".
To understand the GRASP pattern “High Cohesion”
We have explored what are patterns and GRASP (in part I), Information Expert in part II and Creator in part II and “Controller” in part IV, “Low Coupling” in part V. This has been long series but interesting though. In this part V, we would focus on next GRASP pattern named “High Cohesion”. The dictionary meaning of the word “cohesion” is “the state of cohering or sticking together”. In botany world “the process of some parts (which are generally separate) of plant growing together” and in physics world “it’s the intermolecular force that holds together the molecules in solid or liquid”. So this meaning would give us good forethought as what would “High Cohesion” would mean in the context of responsibilities? As we have proceeded through this series, we have seen principles behind assigning the responsibilities. Once they are assigned or being assigned, an important aspect is how they are related or focused? If they are related, sticking together or focussed, the element carrying to those responsibilities would become bloated and result into system quite complex and harder to maintain and reuse. The principle behind this pattern is “How to keep complexity manageable?
Cohesion can be said to a measure of “relatedness” or “how related all the attributes
and behaviour in a class are”. High cohesion refers to how strongly related the responsibilities are.
A class with low cohesion i.e. carrying out the unrelated responsibilities in turn does so many unrelated things or end up doing too much of a work. Such classes culminates into
· Hard to comprehend or understand
· Harder to reuse as it is tough job to segregate and mark the reusable elements
· Harder to maintain and extend
Problem: How to keep classes focused and manageable?
Solution: Assign responsibility so that cohesion remains high
Step I: Closely look for classes with probability of many responsibilities i.e. classes with too-few or disconnected methods.
Step II: Look for the methods which do a lot (look for method names having words like “AND”, “OR”)
Step III: Assign a responsibility in such a way that all the responsibilities in a class are related
Let’s extend an example of POS (Point Of Sale) systems carried in series of articles. In the domain model, following classes like Register, Payment and Sale are identified. In the upper part of diagram (Fig. No.1) a class “Register” is displayed carrying out many unrelated responsibilities. There are many system operations such as closing a sale, make payment etc which are related to business function “Sales”.
Fig No. 1
Relationship with other classes
Responsibility and method
“Register” of Design I
Creator of the “Payment”,
“Sale” and “SaleLineItem”
Carries out responsibilities for adding sale, payment and also the sale line item.
These are absolutely unrelated responsibilities resulting in low cohesion
“Register” and “Sale” of Design II
Controller of “Sale” and “Sale” being the creator of “Payment”
Creating an instance “create”
Controlling the Sale through makePayment()
This results in division of responsibilities according to relations among them and reduces the complexity hence high cohesion
The common examples of Low cohesion are
· System level: ATM having functionality for getting “Teller Reports” i.e. for user this is not required and related
· Class level: An “Employee” class with a method called “getDrivingRecords()”
· Method level: The methods with having “AND”,”OR” in their names which implies that the method is going to execute multiple functions making it difficult to reuse.
· This also applies to subsystem (package), component level. E.g. a component for exception handling also doing job of caching.
One of the fundamental goals of an effective design is to achieve high cohesion with low coupling.
Larman has described degree of cohesion from low to high
· Very low cohesion:- Class responsible for many things in unrelated areas
· Low cohesion:-Class responsible for many things in related areas
· Moderate cohesion :- Class has few responsibilities in different areas which are related to the class but not to each other
· High Cohesion- Class has few responsibilities in one area and collaborates with other classes to fulfill tasks
Related Patterns: This pattern is related rather complementary to “Low Coupling” and little contradictory to information expert.
· Understandability :- Clarity and ease of understanding design is increased
· Maintainability :- Maintenance and enhancements are simplified
· Low coupling is often supported
· Reusability :Small size classes with highly related functionality increases reuse
Liabilities / Contradictions:
· In scenarios of server objects, it would be desirable to have less cohesive server objects due t o performance needs. Remote objects and remote communication are the examples where performance matters than anything else. In this case, an interface provided for many operations would be recommended than having highly cohesive but different interfaces/ components.
· While grouping the responsibilities or code into one class or component motivated by maintainability from view of one person is not desirable as it would end up in maintainability for one person but not for all. This happens when the responsibilities could be related to class but not to each other. This is a good trap for any developer who can never imagine there would be somebody else working on it and he/she has preferred to keep things at one place for better traceability.
Summary & Conclusion
In this part, we discussed the “High Cohesion” and also the principle behind this. We discussed the steps for locating the avenues for lowly cohesive design and assigning responsibility so as to achieve high cohesion. We saw practical example from POS (Point Of Sales) and explanation as how to have low coupling.
To reiterate, following such patterns for design would result into highly maintainable, robust and reusable systems.
Applying UML and Patterns