Different types of routine cohesion
I. What is routine cohesion?
For routines, cohesion refers to how closely the operations in a routine are related. Some programmers prefer the term “strength”: how strongly related are the operations in a routine? A function like Cosine() is perfectly cohesive because the whole routine is dedicated to performing on function. A function like CosineAndTan() has lower cohesion because it tries to do more than one thing. The goal is to have each routine do one thing well and not do anything else.
Discussions about cohesion typically refer to several levels of cohesion. Understanding the concepts is more important than remembering specific terms. Use the concepts as aids in thinking about how to make routines as cohesive as possible.
II. Levels of cohesion
This evaluation of routine cohesion assumes that the routines do what their names say they do – if they do anything else, they are less cohesive and poorly named. Below is the list of all levels of cohesion.
- Functional cohesion:
This is the best and strongest kind of cohesion, occurring when a routine performs one and only one operation. Here are some examples of routines with functional cohesion:
- Sequential cohesion:
This cohesion exists when a routine contains operations that must be performed in a specific order, that share data from step to step, and that don’t make up a complete function when done together.
Here is an example
In the example above, the routine calculates the age and then uses that result to calculate the retirement time, so it has sequential cohesion.
If the routine calculates the age and then calculates the time to retirement in a completely separate computation that happens to use the same birth-date data, it has only communicational cohesion.
You can refactor to make the routine functionally cohesive by this way
- Communicational cohesion:
This cohesion occurs when operations in a routine make use of the same data and aren’t related in any other way. Example
To give this routine better cohesion, separate it to two routines, like what I do with sequential cohesion section above.
- Temporal cohesion:
This cohesion occurs when operations are combined into a routine because they are all done at the same time. Example
Some programmers consider temporal cohesion to be unacceptable because its sometimes associated with bad programming practices such as having a hodgepodge of code in a Initialize() routine above.
To avoid this problem, think of temporal routines as organizers of other events. The Initialize() routine, for example, might read a configuration file, set up a memory manager,… To make it most effective, have the temporally cohesive routine call other routines to perform specific activities rather than performing the operations directly itself, like this
This example raises the issue of choosing a name that describes the routine at the right level of abstraction. You could decide to name the routine above something like ReadConfigFileSetupMemorySetupMorething(), which would imply that the routine had only coincidental cohesion. If you name it Initializes(), however, it would be clear that it had a single purpose and clear that it had functional cohesion.
The remaining kinds of cohesion are generally unacceptable. They result in code that’s poorly organized, hard to debug, and hard to modify. If a routine has bad cohesion, it’s better to put effort into a rewrite to have better cohesion than investing in a pinpoint diagnosis of the problem. Knowing what to avoid can be useful, however, so here are the unacceptable kinds of cohesion:
- Procedural cohesion:
This cohesion occurs when operations in a routine are done in a specified order. This is similar to sequential cohesion except that elements are unrelated. Here is an example
The order of these operations is important only because it matches the order in which the user is asked for the data on the input screen.
The routine has procedural cohesion because it puts a set of operations in a specified order and the operation doesn’t need to be combined for any other reason.
To achieve better cohesion, put the separate operations into their own routines, like this
- Logical cohesion:
This cohesion occurs when several operations are stuffed into the same routine and one of the operations is selected by a control flag that’s passed in. It’s called logical cohesion because the control flow or “login” of the routine is the only thing that ties the operations together – they’re all in a big if statement or case statement together. Example
As you can see, it isn’t because the operations are logically cohesion in any other sense. Considering that the defining attribute of logical cohesion is that the operations are unrelated, a better name might “illogical cohesion”.
The main problem with such routines is that you shouldn’t need to pass in a flag to control another routine’s processing. Instead of having a routine that does one of three distinct operations, depending on a flag passed to it, it’s cleaner to have three routines, each of which does one distinct operation, like this
- Coincidental cohesion:
This cohesion occurs when the operations in a routine have no discernible relationship to each other. Other good names are “no cohesion” or “chaotic cohesion”. Example
It’s hard to convert coincidental cohesion to any better kind of cohesion, so you will need to do a deeper redesign and reimplementation to achieve better cohesion.
III. Key point
None of these terms are magical or sacred. Learn the ideas rather than the terminology. It’s nearly always possible to write routines with functional cohesion, so focus your attention on functional cohesion for maximum benefit.
Here is the list of all levels of routine cohesion
- Functional cohesion (best)
- Sequential cohesion (acceptable)
- Communicational cohesion (acceptable)
- Temporal cohesion (acceptable)
- Procedural cohesion (not acceptable)
- Logical cohesion (not acceptable)
- Coincidental cohesion (worst)
Reference: Code Complete 2