Cohesion refers to how “closely the operations in a routine or class are related.” Some people refer to cohesion as “clarity” because the more operations are related in a routine or class the easier it is to understand the code and what it’s intended to do.
There are many kinds of Cohesion, but we tend to focus primarily on:
- Class cohesion: Each class has a single responsibility.
- Method cohesion: Each method performs a single function.
Strong cohesion is related to clarity and understanding. Cohesive things tend to be easy to understand because they have few moving parts. There is also a strong correlation between “cohesive” and “small.” Small things tend to be cohesive and cohesive things tend to be small. Note that these are not absolutes.
In addition to the direct benefits of cohesive classes and methods, cohesive designs are more resistant to decay. For instance, classes with multiple responsibilities have traditionally been more likely to have implementation coupling develop between some of their responsibilities than systems of cohesive classes that each address one responsibility. There are also several design flaws that are less likely to creep into well-organized systems of cohesive classes and methods than into larger structures with more comprehensive purposes.
Most obstacles to cohesion present themselves as objections. Some argue that you can break things down too far, that classes and methods can be too cohesive. Of course, everyone has different opinions, and you should do what helps you the most but several of the arguments are specious and should not be the reason why you lump responsibilities together.
There may or may not be good reasons to lump multiple responsibilities into a single class but the following are not them.
People sometimes claim that breaking things into multiple methods or classes can slow down a system. Adding abstractions may also reduce performance. Worse: these claims may technically be correct.
I Can’t See Everything
A frequent argument made against cohesive designs is that they hide implementation details. For instance, people will want to be able to see everything line of code that might be invoked by a single operation in one place.
Another argument commonly made against cohesion is the claim that cohesion is good, but only in small doses. This argument typically presents itself as a kind of Fabian strategy. Someone who (usually) doesn’t want to invest the effort in learning a new way of thinking about software will pretend to agree with the principle of cohesion while resisting its actual implementation with phrases like “yeah, but where does it end/how far do we really want to take this/that’s just too much?”
The best solution to any objection is to show that the objection is unfounded. That is, if you can get people to just try breaking down their classes into elements that address single responsibilities, then the code will eventually speak for itself.
Sometimes, you have to make counterarguments, so here they are.
Code Quality Doesn’t Cause the Big Performance Problems
Long ago, computers were slow and people were fast. Spending a lot of human time to save a little computer time was a potentially prudent move.
So, there’s some validity to the performance argument against cohesion and, in fact, against any code quality.
Even though humans haven’t gotten much faster since then, humans are now slow and computers are fast. It almost never makes sense to choose a design that is harder to maintain over the performance costs supposedly caused by better designs.
Cohesion, among the other qualities we focus on here, improves maintainability, and one form of maintenance is performance tuning. Therefore, if we start by making things cohesive then it will be easier to tune them for performance when they are proven to be too slow.
You Don’t Need to See Everything
Yes, dividing classes and methods up into smaller, more cohesive artifacts does hide implementation details. Why would someone want to see irrelevant implementation details?
If you’re writing a file server, you don’t care how the OS gets bytes off the disk. You just want to ask for your data and use it, trusting that the OS does its job.
That same what-oriented thinking applies to the contract between any two concerns.
So, even though the declaration that dividing code into smaller pieces makes it so you can’t see everything in one place is true, it turns out that’s a good thing so it doesn’t really matter.
Furthermore, cohesive classes and methods make it easier to give them intention-revealing names. If something’s name makes it clear what it does, you do not need to know how is does it unless it’s not working.
There is No “Overdoing It”
People who don’t like designs with very cohesive elements typically either haven’t worked that way in the past or have had a bad experience they associate with separation of concerns. Whatever the case, there is typically some fear, involved.
In order to overcome their objection, you’ll have to identify the root of their fear and help them see that everything is going to be okay. There are too many possible sources of fear to address in this article; however, until you know why someone is concerned about overdoing quality, you cannot address their concerns effectively.
Core Developer Skills Overview
- McConnell, Steve. Code Complete: A Practical Handbook of Software Construction. 1993.