What Is Cohesion?
Yesterday we examined Coupling. Today we’ll look at Coupling’s alter-ego: Cohesion.
You’ve probably heard that code with low Cohesion is likely to be problematic, while highly cohesive systems are easier to maintain.
It’s true; but why? What is Cohesion?
I like this definition:
“A class has high Cohesion if it contains methods and data that ‘naturally belong together’.
Conversely, a class has low Cohesion if the methods and data don’t fit well together.“
Unfortunately, this definition is a bit wishy-washy; what does ‘naturally belongs together‘ actually mean?
OK, time for a couple of examples.
Firstly, say, we have a Customer class in an eCommerce system. Customer has the following methods:
CalcDeliveryRoute()PrintOrderReport()Save()
Do these look like they belong together? No, they don’t. The responsibilities of the three methods vary wildly:
- Programmers from the IT department are responsible for data persistence. They change the implementation of the
Save() method. PrintOrderReport() is an administrative function. The Accounting department uses it to track large customer orders. Accountants are requesting modifications to this report. - Finally, Operations and Logistics drive changes to
CalcDeliveryRoute().
Let’s get more precise with our definition of Cohesion. Robert C. Martin (aka Uncle Bob) has restated the Single Responsibility Principle, which is all about Cohesion, as:
“A module (or class) should be responsible to one and only one actor.”
‘Actor‘ is a term from Unified Modelling Language (UML) meaning ‘a distinct group of system users’.
Is our Customer class cohesive? No, since three separate actors may request changes to it:
- Logistics for
CalcDeliveryRoute(), - the Accounting department for
PrintOrderReport(), and - IT to the
Save() method.
OK, what about an example of a cohesive class? Class ShoppingCart in the same eCommerce system has these methods and getter properties:
Add()Remove()Clear()TotalContents
All five behaviours manage merely the contents of ShoppingCart. A single ‘actor’ would request changes to the cart’s operations. ShoppingCart is highly cohesive.
Finally, it is worth noting that we developers can reduce Cohesion even if all existing methods and data structures reside inside the one class. How would this happen? Simple—by not putting a new behaviour onto the class that it naturally belongs to.
To illustrate this point, we’ll continue with the ShoppingCart example. Let’s say new legislation requires eCommerce websites to display the GST amount pre-checkout.
Programatically, one way to a high Cohesion implementation would be to put a GST or GstAmount getter property on the ShoppingCart class.
Unfortunately, the developer didn’t realise that the GST calculation depends on a fixed GST rate and ShoppingCart.Total and can therefore be encapsulated in ShoppingCart. No, they decided to implement GST calculations outside of ShoppingCart. In so doing, the developer has unwittingly dealt the eCommerce system a blow—Cohesion is now lower. This seemingly small mistake, left unchecked, will see us having code like this littering the application:
var gst = cart.Total * GST_RATE;
or even
var gstAmt = cart.Total * 0.15;
while the more cohesive outcome might have looked like this:
var subtotal = cart.Subtotal; // before GST
var gst = cart.GstAmount; // GST calculated inside ShoppingCart
var total = cart.Total; // Subtotal + GstAmount
Carefully consider where you place behaviour—small mistakes today may blow up into maintainability headaches in the future.
What Is Cohesion?
/0 Comments/in Today's Tip /by Olaf ThielkeWhat Is Cohesion?
Photo by Scott Sanker on Unsplash
Yesterday we examined Coupling. Today we’ll look at Coupling’s alter-ego: Cohesion.
You’ve probably heard that code with low Cohesion is likely to be problematic, while highly cohesive systems are easier to maintain.
It’s true; but why? What is Cohesion?
I like this definition:
Unfortunately, this definition is a bit wishy-washy; what does ‘naturally belongs together‘ actually mean?
OK, time for a couple of examples.
Firstly, say, we have a
Customerclass in an eCommerce system.Customerhas the following methods:CalcDeliveryRoute()PrintOrderReport()Save()Do these look like they belong together? No, they don’t. The responsibilities of the three methods vary wildly:
Save()method.PrintOrderReport()is an administrative function. The Accounting department uses it to track large customer orders. Accountants are requesting modifications to this report.CalcDeliveryRoute().Let’s get more precise with our definition of Cohesion. Robert C. Martin (aka Uncle Bob) has restated the Single Responsibility Principle, which is all about Cohesion, as:
“A module (or class) should be responsible to one and only one actor.”
‘Actor‘ is a term from Unified Modelling Language (UML) meaning ‘a distinct group of system users’.
Is our Customer class cohesive? No, since three separate actors may request changes to it:
CalcDeliveryRoute(),PrintOrderReport(), andSave()method.OK, what about an example of a cohesive class? Class
ShoppingCartin the same eCommerce system has these methods and getter properties:Add()Remove()Clear()TotalContentsAll five behaviours manage merely the contents of
ShoppingCart. A single ‘actor’ would request changes to the cart’s operations.ShoppingCartis highly cohesive.Finally, it is worth noting that we developers can reduce Cohesion even if all existing methods and data structures reside inside the one class. How would this happen? Simple—by not putting a new behaviour onto the class that it naturally belongs to.
To illustrate this point, we’ll continue with the
ShoppingCartexample. Let’s say new legislation requires eCommerce websites to display the GST amount pre-checkout.Programatically, one way to a high Cohesion implementation would be to put a
GSTorGstAmountgetter property on theShoppingCartclass.Unfortunately, the developer didn’t realise that the GST calculation depends on a fixed GST rate and
ShoppingCart.Totaland can therefore be encapsulated inShoppingCart. No, they decided to implement GST calculations outside ofShoppingCart. In so doing, the developer has unwittingly dealt the eCommerce system a blow—Cohesion is now lower. This seemingly small mistake, left unchecked, will see us having code like this littering the application:var gst = cart.Total * GST_RATE;or even
var gstAmt = cart.Total * 0.15;while the more cohesive outcome might have looked like this:
Carefully consider where you place behaviour—small mistakes today may blow up into maintainability headaches in the future.