31

I am a student who recently joined a software development company as an intern. Back at the university, one of my professors used to say that we have to strive to achieve "Low coupling and high cohesion".

I understand the meaning of low coupling. It means to keep the code of separate components separately, so that a change in one place does not break the code in another.

But what is meant by high cohesion. If it means integrating the various pieces of the same component well with each other, I dont understand how that becomes advantageous.

What is meant by high cohesion? Can an example be explained to understand its benefits?

5
  • possible duplicate of Are There Metrics For Cohesion And Coupling?
    – gnat
    Aug 31, 2012 at 4:22
  • 1
    Does the wikipedia article not answer your question sufficiently? en.wikipedia.org/wiki/Cohesion_(computer_science) Aug 31, 2012 at 8:25
  • There is a good article about this at: msdn.microsoft.com/en-us/magazine/cc947917.aspx
    – NoChance
    Aug 31, 2012 at 8:42
  • 1
    @EoinCarroll: Unfortunately the wikipedia article at the current moment does not give any good concrete examples that new programmers can work with. Theory is good and all, but doesn't really stick until you've done the mistakes surrounding low cohesion. High cohesion is one of those topics that has taken me several years of programming to fully understand why it is important and how to achieve it.
    – Spoike
    Aug 31, 2012 at 14:32
  • I never really understood Cohesion until I read Clean Code. You should too. Sep 14, 2014 at 10:48

3 Answers 3

33

One way of looking at cohesion in terms of OO is if the methods in the class are using any of the private attributes. Using metrics such as LCOM4 (Lack of Cohesive Methods), as pointed out by gnat in this answer here, you can identify classes that could be refactored. The reason you want to refactor methods or classes to be more cohesive is that it makes the code design simpler for others to use it. Trust me; most tech leads and maintenance programmers will love you when you fix these issues.

You can use tools in your build process such as Sonar to identify low cohesion in the code base. There are a couple of very common cases that I can think of where methods are low in "cohesiveness":

Case 1: Method is not related to the class at all

Consider the following example:

public class Food {
   private int _foodValue = 10;

   public void Eat() {
     _foodValue -= 1;
   }

   public void Replenish() {
     _foodValue += 1;
   }

   public void Discharge() {
     Console.WriteLine("Nnngghhh!");
   }
}

One of the methods, Discharge(), lacks cohesion because it doesn't touch any of the class's private members. In this case there is only one private member: _foodValue. If it doesn't do anything with the class internals, then does it really belong there? The method could be moved to another class that could be named e.g.FoodDischarger.

// Non-cohesive function extracted to another class, which can
// be potentially reused in other contexts
public FoodDischarger {
  public void Discharge() {
    Console.WriteLine("Nnngghhh!");
  }
}

In you're doing it in Javascript, since functions are first-class objects, the discharge can be a free function:

function Food() {
    this._foodValue = 10;
}
Food.prototype.eat = function() {
    this._foodValue -= 1;
};
Food.prototype.replenish = function() {
    this._foodValue += 1;
};

// This
Food.prototype.discharge = function() {
    console.log('Nnngghhh!');
};
// can easily be refactored to:
var discharge = function() {
    console.log('Nnngghhh!');
};
// making it easily reusable without creating a class

Case 2: Utility Class

This is actually a common case that breaks cohesion. Everyone loves utility classes, but these usually indicate design flaws and most of the time makes the codebase trickier to maintain (because of the high dependency associated with utility classes). Consider the following classes:

public class Food {
    public int FoodValue { get; set; }
}

public static class FoodHelper {

    public static void EatFood(Food food) {
        food.FoodValue -= 1;
    }

    public static void ReplenishFood(Food food) {
        food.FoodValue += 1;
    }

}

Here we can see that the utility class needs to access a property in the class Food. The methods in the utility class has no cohesion at all in this case because it needs outside resources to do it's work. In this case, wouldn't it be better to have the methods in the class they're working with itself (much like in the first case)?

Case 2b: Hidden objects in Utility Classes

There is another case of utility classes where there are unrealized domain objects. The first knee-jerk reaction a programmer has when programming string manipulation is to write a utility class for it. Like the one here that validates a couple of common string representations:

public static class StringUtils {

  public static bool ValidateZipCode(string zipcode) {
    // validation logic
  }

  public static bool ValidatePhoneNumber(string phoneNumber) {
    // validation logic
  }

}

What most don't realize here is that a zip code, a phone number, or any other string repesentation can be an object itself:

public class ZipCode {
    private string _zipCode;
    public bool Validates() {
      // validation logic for _zipCode
    }
}

public class PhoneNumber {
    private string _phoneNumber;
    public bool Validates() {
      // validation logic for _phoneNumber
    }
}

The notion that you shouldn't "handle strings" directly is detailed in this blogpost by @codemonkeyism, but is closely related to cohesion because the way programmers use strings by putting logic in utility classes.

3
10

High cohesion means to keep similar and related things together, to couple or fuse parts which share content, functionality, reason or goal. In other words, low cohesion could for example mean a function/class/code entity which serves multiple purposes rather than being "to the point". One of the carrying ideas is to do one thing and do it well. Others could include the obvious fact that you don't replicate similar functionality in many places. This also improves locality of the code base, certain kinds of things are found at a certain place(file, class, set of functions, ...) rather than being scattered around.

As an example, consider a class which serves two or three purposes: Loads/stores resources(for example a file) and then analyses and displays the content. Such a class has low cohesion because it manages at least two separate tasks which aren't related at all(file I/O, analysis and display). A high cohesion design could use distinct classes for loading and storing the resource, analysing it and then displaying it.

On the other hand, low coupling aims to keep distinct things separated - so that they interact with each other as little as possible which then reduces complexity and simplifies the design.

7

It means that the parts of an object are closely related to the function of the object. This means that there is very little or no waste within the object in terms of function or responsibility. This in turn can improve the understanding of what the object in question is supposed to be used for.

1
  • doesn't it also apply to a higher level than just objects? eg grouping objcts/functions related to a task in namespaces?
    – stijn
    Aug 31, 2012 at 6:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.