Cohesion

Cohesion

Cohesion is a measure of how well a module fits together.
It was described in Structured DesignMyers as, 'Module strength(cohesion), ..., is a measurement of the relationships among elements within a single module.'.
Cohesion is not exactly easy to quantify and there are seven types (below) which I'm going to attempt to explain, with examples.
  1. Coincidental cohesion (worst)
  2. Logical cohesion
  3. Classical cohesion
  4. Procedural cohesion
  5. Communicational cohesion
  6. Functional cohesion(best)
  7. Type cohesion (best)

Coincidental

Coincidental cohesion is a module that does completely unrelated things and the module can't really be defined, such as a CommonUtilities class that contains completely arbitrary methods.
This can also occur through some misguided standards, which state some arbitrary rule, such as a class should only ever take up a page. This leads to the developer chopping programs that should otherwise be complete and placing methods into a general purpose class.
For example:
interface Coincidental {
    int GetUserId();
    char GetKeyboardInput();
    string CalcStockShare();
    void BeepCarhorn();
}

Logical

Logical cohesion is when a set of related functions are called from another function and it sends arguments which chose which function.
As we have multiple function calls within one function this can lead to extensibility issues.
Here's an example showing the method and calling section:
enum GeneralAccountType {
    salary,
    name,
    DOB,
}

public void GeneralUpdater(int userId, double? salary, string name, DateTime DOB, GeneralAccountType generalAccountType) {
    switch (generalAccountType) {
        case GeneralAccountType.salary:
            UpdateSalary(userId, salary);
            break;
        case GeneralAccountType.name:
            UpdateName(userId, salary);
            break;
        case GeneralAccountType.DOB:
            UpdateDOB(userId, DOB);
            break;
    }
}
With the method calls looking like:
somewhere.GeneralUpdater(1, 100000.01, null, null, GeneralAccountType.salary);

somewhereElse.GeneralUpdater(1, null, "Bryane", null, GeneralAccountType.name);

whoKnowsWhere.GeneralUpdater(1, null, null, new DateTime(1990, 8, 8), GeneralAccountType.DOB);

The extensibility issues are clear, for example, if I change or add another method call to GeneralUpdater, then I'd have to change all the calls which could be spread through a large program.
Also, to use the method call GeneralUpdater then the programmer has to have full knowledge of what is going on within the function, as it is difficult to imagine which parameters need to be used.
We can imagine a clever programmer that realises that it's impossible to change all the calls throughout the solution and so, uses one of the parameters(arguments) for another method call, but not the one it's intended.
The maintainance of the program is getting more difficult as the project gets larger, until eventually the programming team don't know about clever solutions or added function calls, which will eventually be a disaster.

Classical

Classical cohesion (aka: Temporal) is when the functions are weakly related but are carried out is some sort of weird space-time continuum order.
The functions could to be initialisation and finalisation functions (and the functions in-between).
For example:
init(func1, func2, var1);
doThisAfterInit();
doThisNext();
...
finalise(func3, var2);

It's difficult to see the problem with this, but the issue is that within the called functions there is probably unrelated functions being called and these may be called again elsewhere.
This is leading to difficult to maintain and unreadable code.

Procedural

Procedural cohesion is when functions are still weakly related and need to be carried out in a certain order.
It's a little difficult to quantify but imagine something like this example:
foreach(file in GetFiles()){
    var isError = ProcessFile(file);
    if (isError){
        Bin(file);
        UIErrorTxtBox.Text=ERROR_MESSAGE;
        UISuccessTxtBox.Text=string.Empty;
    } else {
        InsertFileInDb(file);
        UISuccessTxtBox.Text=SUCCESS_MESSAGE;
        UIErrorTxtBox.Text=string.Empty;
    }
}
I think everyone should be able to see the issue here, in that, we're 'contacting' the UI, with UIErrorTxtBox.Text... and UISuccessTxtBox.Text... assignment calls.
Eventhough, there is a need to display a message on the UI it shouldn't be done from here and this makes the code unusable elsewhere in the project.

Communicational

Communicational cohesion is very similar to Procedural but the functions are related and act upon the same data.
For example:
foreach(file in GetFiles()){
    var isError = ProcessFile(file);
    if (isError){
        Bin(file);
    } else {
        var cleanedFile = Clean(file);
        InsertFileInDb(cleanedFile);
        PutFileOnQueue(cleanedFile);
         // do other stuff with file
    }
}
I can here you saying, 'what the hell is wrong with that!', and I have to agree.
I've written plenty of similar code, but it's unlikely to be reusable elsewhere and cohesion is about an ideal and to try to drive your code toward maximum cohesion.

Functional

Functional cohesion is the ideal cohesion and if you can get your code to this level then it is probably reusable, resillient and scalable.
Functional cohesion is when the function carries out a single task and each parts primary goal is only on that task.
A simple example of the magical world of functional cohesion is:
double SquareRoot(double x) {
    return x * x;
}
Similarily, the Sort functions have this cohesion and are reusable across the project.

Type

Type cohesion is a little different to functional cohesion, but also ideal and I've produced a very convoluted example below, which checks if two types are equal and returns the first type a if true, else returns the second:
T Check(T a, T b) {
    if (a.Equals(b)) return a;
    return b;
}
Myers calls this informational cohesion but this probably not appropriate but the idea is relatively similar.
The idea is that a function can be related when it's called and can 'answer' different calls but carry out the same functionality under one heading.

Summary

Well, that's my 'stab' at explaining cohesion, which was as I expected quite difficult (but not as difficult as I thought!).

References

wiki
Washington
Myers
The Pragmatic Programmer