My Secret Life as a Spaghetti Coder
home | about | contact | privacy statement
low cou-pling and high co-he-sion
n.
  1. A standard bit of advice for people who are learning to design their code better, who want to write software with intention as opposed to coincidence, often parroted by the advisor with no attempt to explain the meaning.

Motivation

It's a great scam, don't you think? Someone asks a question about how to design their code, and we have these two nebulous words to throw back at them: coupling and cohesion. We even memorize a couple of adjectives that go with the words: low and high.

Cohesion Good. Coupling, Baaaaad!

Metallica Good, Napster Bad.

It's great because it shuts up the newbie who asks the question -- he doesn't want to appear dumb, after all -- and it gets all of those in-the-know to nod their heads in approval. "Yep, that's right. He's got it. +1."

But no one benefits from the exchange. The newbie is still frustrated, while the professional doesn't give a second thought to the fact that he probably doesn't know what he means. He's just parroting back the advice that someone gave to him. It's not malicious or even conscious, but nobody is getting smarter as a result of the practice.

Maybe we think the words are intuitive enough. Coupling means that something is depending on something else, multiple things are tied together. Cohesion means ... well, maybe the person asking the question heard something about it in high school chemistry and can recall it has something to do with sticking together. Maybe they don't know at all.

Maybe, if they're motivated enough (and not that we've done anything to help in that department), they'll look it up:

Types of Cohesion and Coupling

Types of Cohesion
Coincidental cohesion (worst) is when parts of a module are grouped arbitrarily (at random); the parts have no significant relationship (e.g. a module of frequently used functions).

Logical cohesion is when parts of a module are grouped because they logically are categorised to do the same thing, even if they are different by nature (e.g. grouping all I/O handling routines).

Temporal cohesion is when parts of a module are grouped by when they are processed - the parts are processed at a particular time in program execution (e.g. a function which is called after catching an exception which closes open files, creates an error log, and notifies the user).

Procedural cohesion is when parts of a module are grouped because they always follow a certain sequence of execution (e.g. a function which checks file permissions and then opens the file).

Communicational cohesion is when parts of a module are grouped because they operate on the same data (e.g. a module which operates on the same record of information).

Sequential cohesion is when parts of a module are grouped because the output from one part is the input to another part like an assembly line (e.g. a function which reads data from a file and processes the data).

Functional cohesion (best) is when parts of a module are grouped because they all contribute to a single well-defined task of the module
Types of Coupling
Content coupling (high) is when one module modifies or relies on the internal workings of another module (e.g. accessing local data of another module). Therefore changing the way the second module produces data (location, type, timing) will lead to changing the dependent module.

Common coupling is when two modules share the same global data (e.g. a global variable). Changing the shared resource implies changing all the modules using it.

External coupling occurs when two modules share an externally imposed data format, communication protocol, or device interface.

Control coupling is one module controlling the logic of another, by passing it information on what to do (e.g. passing a what-to-do flag).

Stamp coupling (Data-structured coupling) is when modules share a composite data structure and use only a part of it, possibly a different part (e.g. passing a whole record to a function which only needs one field of it). This may lead to changing the way a module reads a record because a field, which the module doesn't need, has been modified.

Data coupling is when modules share data through, for example, parameters. Each datum is an elementary piece, and these are the only data which are shared (e.g. passing an integer to a function which computes a square root).

Message coupling (low) is the loosest type of coupling. Modules are not dependent on each other, instead they use a public interface to exchange parameter-less messages (or events, see Message passing).

No coupling [is when] modules do not communicate at all with one another.

What does it all mean?

The Wikipedia entries mention that "low coupling often correlates with high cohesion" and "high cohesion often correlates with loose coupling, and vice versa."

However, that's not the intuitive result of simple evaluation, especially on the part of someone who doesn't know in the first place.

In the context of the prototypical question about how to improve the structure of code, one does not lead to the other. By reducing coupling, on the face of it the programmer is going to merge unrelated units of code, which would also reduce cohesion. Likewise, removing unrelated functions from a class will introduce another class on which the original will need to depend, increasing coupling.

To understand how the relationships become inversely correlated requires a larger step in logic, where examples of the different types of coupling and cohesion would prove helpful.

Examples from each category of cohesion

Coincidental cohesion often looks like this:

class Helpers;

class Util;

int main(void) {
  where almost all of your code goes here;
  return 0;
}

In other words, the code is organized with no special thought as to how it should be organized. General helper and utility classes, God Objects, Big Balls of Mud, and other anti-patterns are epitomes of coincidental cohesion. You might think of it as the lack of cohesion: we normally talk about cohesion being a good thing, whereas we'd like to avoid this type as much as possible.

(However, one interesting property of coincidental cohesion is that even though the code in question should not be stuck together, it tends to remain in that state because programmers are too afraid to touch it.)

With logical cohesion, you start to have a bit of organization. The Wikipedia example mentions "grouping all I/O handling routines." You might think, "what's wrong with that? It makes perfect sense." Then consider that you may have one file:

IO.somelang
function diskIO();
function screenIO();
function gameControllerIO();

While logical cohesion is much better than coincidental cohesion, it doesn't necessarily go far enough in terms of organizing your code. For one, we've got all IO in the same folder in the same file, no matter what type of device is doing the inputting and outputting. On another level, we've got functions that handle both input and output, when separating them out would make for better design.

Temporal cohesion is one where you might be thinking "duh, of course code that's executed based on some other event is tied to that event." Especially considering the Wikipedia example:
a function which is called after catching an exception which closes open files, creates an error log, and notifies the user.
But consider we're not talking about simple the relationship in time. We're really interested in the code's structure. So to be temporally cohesive, your code in that error handling situation should keep the closeFile, logError, and notifyUser functions close to where they are used. That doesn't mean you'll always do the lowest-level implementation in the same file -- you can create small functions that take care of setting up the boilerplate needed to call the real ones.

It's also important to note that you'll almost never want to implement all of that directly in the catch block. That's sloppy, and the antithesis of good design. (I say "almost" because I am wary of absolutes, yet I cannot think of a situation where I would do so.) Doing so violates functional cohesion, which is what we're really striving for.

Procedural cohesion is similar to temporal cohesion, but instead of time-based it's sequence-based. These are similar because many things we do close together in time are also done in sequence, but that's not always the case. There's not much to say here. You want to keep the definitions of functions that do things together structurally close together in your code, assuming they have a reason to be close to begin with. For instance, you wouldn't put two modules of code together if they're not at least logically cohesive to begin with. Ideally, as in every other type of cohesion, you'll strive for functional cohesion first.

Communicational cohesion typically looks like this:

some lines of code;
data = new Data();
function1(Data d) {...};
function2(Data d) {...};
some more lines of code;

In other words, you're keeping functions together that work on the same data.

Sequential cohesion is much like procedural and temporal cohesion, except the reasoning behind it is that functions would chain together where the output of one feeds the input of another.

Functional cohesion is the ultimate goal. It's The Single Responsibility Principle [PDF] in action. Your methods are short and to the point. Ones that are related are grouped together locally in a file. Even files or classes contribute to one purpose and do it well. Using the IO example from above, you might have a directory structure for each device, and within it, a class for Input and one for Output. Those would be children of abstract I/O classes that implemented all but the device-specific pieces of code.

(I use inheritance terminology here only as a subject that I believe communicates the idea to others. Of course, you don't have to even have inheritance available to you to achieve the goal of keeping device agnostic code in one locale while keeping the device specific code apart from it).

Examples from each category of coupling

Content coupling is horrific. You see it all over the place. It's probably in a lot of your code, and you don't realize it. It's often referred to a violation of encapsulation in OO-speak, and it looks like one piece of code reaching into another, without regard to any specified interfaces or respecting privacy. The problem with it is that when you rely on an internal implementation as opposed to an explicit interface, any time that module you rely on changes, you have to change too:

module A
  data_member = 10
end

module B
  10 * A->data_member end

What if data_member was really called num_times_accessed? Well, now you're screwed since you're not calculating it.

Common coupling occurs all the time too. The Wikipedia article mentions global variables, but this could be just a member in a class where two or more functions rely on it if you consider it. It's not as bad when its encapsulated behind an interface, where instead of accessing the resource directly, you do so indirectly, which allows you to change internal behavior behind the wall, and keeps your other units of code from having to change every time the shared resource changes.

An example of external coupling is a program where one part of the code reads a specific file format that another part of the code wrote. Both pieces need to know the format so when one changes, the other must as well.

unit A
  write_csv_format();
end

unit B // in another file, probably
  read_csv_format();
end

Control coupling might look like:
// unit A
function do(what){
  if(what == 1) do_wop;
  else if (what == 2) ba_ba_da_da_da_do_wop;
}

// unit B
A.do(1);

Stamp coupling (Data-structured coupling) involved disparate pieces of code touching the same data structure in different ways. For example:

employee = { :age => 24, :compensation=> 2000 }

def age_range(employee)
  range = 1 if employee[:age] < 10
  range = 2 if employee[:age] > 10 && < 20;
  ...
  return range
end

def compensation_range(employee)
  ... only relies on employee[:compensation] ...
end

The two functions don't need the employee structure, but they rely on it and if it changes, those two functions have to change. It's much better to just pass the values and let them operate on that.

Data coupling is starting to get to where we need to be. One module depends on another for data. It's a typical function call with parameters:

// in module A
B.add(2, 4)

Message coupling looks like data coupling, but it's even looser because two modules communicate indirectly without ever passing each other data. Method calls have no parameters, in other words.

No coupling, like Wikipedia says, is when "modules do not communicate at all with one another." There is no dependency from code A to code B.

Concluding Remarks

So how do we reconcile the thought that "if I separate code to increase functional cohesion, I introduce dependencies which is going to increase coupling" with the assertion that low coupling and high cohesion go hand in hand? To do that, you must recognize that the dependencies already exist. Perhaps not at the class level, but they do at the lines of code level. By pulling them out into related units, you remove the spaghetti structure (if you can call it that) and turn it into something much more manageable.

Increasing cohesion and decreasing coupling.

A system of code can never be completely de-coupled unless it does nothing. Cohesion is a different story. I can't claim that your code cannot be perfectly cohesive, but I can't claim that it can. My belief is it can be very close, but at some point you'll encounter diminishing returns on your quest to make it so.

The key takeaway is to start looking at your code and think about what you can do to improve it as you notice the relationships between each line you write start take shape.

Comments and corrections(!) are encouraged. What are your thoughts?

Hey! Why don't you make your life easier and subscribe to the full post or short blurb RSS feed? I'm so confident you'll love my smelly pasta plate wisdom that I'm offering a no-strings-attached, lifetime money back guarantee!


Comments
Leave a comment

Thanks for this Sam.

Just two questions ...

In your opinion ...
i). Is Control Coupling an acceptable form of Coupling ? State rationale.
ii). Is Communication Cohesion an acceptable form of Cohesion. State rationale.

Many thnx.

Posted by John Barrett on Jan 07, 2010 at 07:32 AM UTC - 5 hrs

@John: as with most things in programming, the answer resides somewhere between the extremes of yes and no.

In the case of control coupling, in general I would say it is unacceptable. If I have a function:

doThisOrThat(whichOne);

I'd generally rather see two functions:

doThis();
doThat();

However, what happens in the case that "this" and "that" are very similar? I wouldn't violate DRY to have two functions that are not control-coupled. So, if the this and that are very cohesive, I'd keep them together.

Regarding communication cohesion: It's acceptable in that I think it's a good thing to keep things like that together - if you're working with a change in the data object, often you might need to change the functions that work on it.

However, if you can see a better way to split it up, I definitely would. It's kind of lazy. It's better than no cohesion, but if you can drill down further, you definitely should.

Posted by Sammy Larbi on Jan 19, 2010 at 09:07 AM UTC - 5 hrs

Thanks for the interesting and though provoking read.

Posted by AndrewJacksonZA on Mar 30, 2010 at 07:06 AM UTC - 5 hrs

A few typos:

"But consider we're not talking about simple the relationship in time"

and

"It's not as bad when its encapsulated" ( -> it's)

Thanks much!

Posted by roger pack on May 28, 2010 at 04:17 PM UTC - 5 hrs

@roger pack- thanks for pointing that out. I'll correct it when I get a moment to log in.

Posted by Sammy Larbi on May 31, 2010 at 10:40 AM UTC - 5 hrs

Fantastic post. I shall recommend this to grads so that they create good s/w :)

Posted by Kiran Banda on Aug 16, 2010 at 04:03 AM UTC - 5 hrs

Thanks Kiran!

Posted by Sammy Larbi on Aug 16, 2010 at 09:11 AM UTC - 5 hrs

Finally!! Thanks a lot!!.
This is the kind of stuff I like to share in Facebook :D

Posted by Carlos Cuevas on Sep 26, 2010 at 11:16 PM UTC - 5 hrs

Thanks Carlos, I'm glad you found it useful!

Posted by Sammy Larbi on Sep 27, 2010 at 07:43 AM UTC - 5 hrs

I think you forgot one:

Sexual cohesion is when parts of a module penetrate another module that they have no logical explanation for other than that they are completely attracted by that module's features.

Posted by Danny boy on Apr 22, 2011 at 01:17 PM UTC - 5 hrs

I don’t think that the coincidental cohesion remains together because people are afraid to touch it. It is actually hard to touch it.
Let’s say you have three pieces of functionality in your ball of mud: A, B, and C. Where A uses B and B uses C. Let’s imagine that you are trying to extract B from the mud. You will end-up with a separate module that contains B that depends on mud because it depends on C and mud that depends on your module because A depends on B. This is circular dependency that cannot exist in the most programming environment. You need to extract A into separate module or in the same module as a B. It, in turn, can lead to other dependency to it from mud.
Such dependencies can be deep and require more time than you have for your particular tasks.
In any case it is a great article. Still reading.

Posted by Dennis on Jul 04, 2011 at 01:34 PM UTC - 5 hrs

@Dennis - I would say that because it's hard to touch, they are afraid that doing so will break it. Good catch on the distinction though, and I'm glad you're enjoying the post.

Posted by Sammy Larbi on Jul 05, 2011 at 12:36 PM UTC - 5 hrs

Good post.

I have come across architects who does not understand the difference between coupling and cohesion. And as you said, even trainers mostly do not get it right.

Posted by Subbu on Aug 20, 2011 at 02:52 PM UTC - 5 hrs

Very good post.

Really thanks for this valuable information about the difference between the cohesion and coupling

Posted by Asmaa on Sep 04, 2011 at 02:33 AM UTC - 5 hrs

Can I ask you How Could I Specify the design elements in my detailed design diagrams like class ,sequence ,deployment ...etc ?

- Do I have to consider that each class is a detailed design element?
- Do I have to consider that each table, Procedure, view and sequence in my DB is a detailed design element? or the diagram will be an element which contains this sub elements?

- How much deeply i have go in details ?


- How much deeply i have go in details ?

Posted by Asmaa on Sep 04, 2011 at 03:07 AM UTC - 5 hrs

@Asmaa - The answer to how deep you need to go into details is to go as deep as you need (or your team).

If specifying more detail helps you and those you work with, then you should do it. If it doesn't help you, then you are wasting time.

It doesn't help me in most cases, so I don't do it in most cases. However, there are times when I'm not sure how something should work, or perhaps it's just confusing, and in those situations I will play around with details on paper or a whiteboard until I have an understanding of what I should be doing.

Posted by Sammy Larbi on Sep 05, 2011 at 11:40 AM UTC - 5 hrs

Sammy,

Great explanation of coupling and cohesion. I am not a software coder, but I do work in systems engineering and I am currently working on a master's in systems engineering. They love throwing out low coupling and high cohesion statement without explanation as to what that means in system elements interfacing. The way they describe the ideal state of system element interaction is low coupling, high cohesion, high binding and low connectivity. And then it doesn't get explained. This gets me 50% of the way their in developing my system specification for the class. Thanks.

Tony

Posted by Tony Magorno on Feb 23, 2012 at 03:12 PM UTC - 5 hrs

Hey Tony, I'm glad you found some use for it!

Posted by Sammy Larbi on Feb 23, 2012 at 04:51 PM UTC - 5 hrs

Enjoyed reading this, I have been taught the basics of the high cohesion low coupling principles but did not understand fully. Nice examples, the fact that there are different types of both cohesion and coupling has helped me look some of my code and re-think it. +1

Posted by Chris Parry on Mar 25, 2012 at 12:05 PM UTC - 5 hrs

Difference between content coupling and common coupling?

Posted by prasad on May 02, 2012 at 05:52 AM UTC - 5 hrs

Really nice post. THANKS for the info..

Posted by webdevil_coder on May 16, 2012 at 12:28 AM UTC - 5 hrs

Yep, that's right. He's got it. +1.
Seriously though, I really enjoyed your post. Thanks for explaining a sometimes difficult concept in plain english.

Posted by Brad on Sep 20, 2012 at 08:01 AM UTC - 5 hrs

The best post on this topic I've encountered so far.

But I was really hoping for guidelines, instructions on how to implement these concepts. It would be awesome if you can start with a small project refectoring it to use high cohesion and low coupling and mentioning guide lines. It would be great help if you can suggest few good books in which these concepts are explained in detail.

Posted by Jay on Jul 19, 2013 at 01:01 AM UTC - 5 hrs

Thanks for the feedback Jay. I did include some examples, which I hoped would be sufficient to explain the concept. I'm not aware of any books which treat these as the subject matter of the book, though both wikipedia articles I linked to do include some references.

I like the idea of this small project, and in fact I started one to show an improvement in design in Rails apps, but it turned out to be much larger an undertaking than I could motivate myself to complete.

Posted by Sammy Larbi on Jul 22, 2013 at 07:54 AM UTC - 5 hrs

it's very good , but have some lack things, so complete it for future guys,,,,...??? thanks.....

Posted by hadi jutt on Dec 01, 2013 at 10:55 PM UTC - 5 hrs

Leave a comment

Leave this field empty
Your Name
Email (not displayed, more info?)
Website

Comment:

Subcribe to this comment thread
Remember my details
Google
Web CodeOdor.com

Me
Picture of me

Topics
.NET (19)
AI/Machine Learning (14)
Answers To 100 Interview Questions (10)
Bioinformatics (2)
Business (1)
C and C++ (6)
cfrails (22)
ColdFusion (78)
Customer Relations (15)
Databases (3)
DRY (18)
DSLs (11)
Future Tech (5)
Games (5)
Groovy/Grails (8)
Hardware (1)
IDEs (9)
Java (38)
JavaScript (4)
Linux (2)
Lisp (1)
Mac OS (4)
Management (15)
MediaServerX (1)
Miscellany (75)
OOAD (37)
Productivity (11)
Programming (168)
Programming Quotables (9)
Rails (31)
Ruby (67)
Save Your Job (58)
scriptaGulous (4)
Software Development Process (23)
TDD (41)
TDDing xorblog (6)
Tools (5)
Web Development (7)
Windows (1)
With (1)
YAGNI (10)

Resources
Agile Manifesto & Principles
Principles Of OOD
ColdFusion
CFUnit
Ruby
Ruby on Rails
JUnit



RSS 2.0: Full Post | Short Blurb
Subscribe by email:

Delivered by FeedBurner