Clean Up Design at Class Level with Sonar
When learning Object-oriented programming, two of the concepts are fairly difficult to understand and therefore to digest : classes must be loosely coupled and highly cohesive. In today’s post, I am going to explain why this is important and how Sonar can help you evaluating how cohesive are your classes.
A few weeks ago, I started a discussion on how to Fight Back Design Erosion by Breaking Cycles with Sonar in which I mentioned that good design should enable to replace any part of a system by a new piece of code with little pain. The first aspect to look at is really the “macro level”, i.e. packages, to ensure for instance that there are no cycles between packages. But to obtain modularity at any level of the design you also need to consider the “micro level”, i.e. the classes / methods, by keeping it loosely coupled and highly cohesive.
Coupling is the degree to which each class is tight to the others. In other words if a class is highly coupled, any change you make to this class can have direct or indirect impact on many other classes : not what I would call great modularity ! You can use for example the inversion of control principle to reduce the coupling between classes.
Cohesion is the degree to which the methods of a single class are tight together. When two methods in a class do not use a common attribute or a common method, it means that they share nothing and should probably not belong to the same class to respect the Single Responsibility Principle. In other words you can split your class into several new classes to gain modularity at class level.
So whereas classes should be very unrelated with lowest possible coupling, methods should on the opposite be strongly related with high possible cohesion. This is pretty similar to an agile organization : each team (class) should be very autonomous (low coupling) but all members (methods) of a team should be very tight to each other (high cohesion).
Sonar 2.0 comes with a new experimental and very promising metric : LCOM4 (Lack Of Cohesion Methods) to measure how cohesive classes are. Interpreting this metric is pretty simple as value 1 means that a class has only one responsibility (good) and value X means that a class has probably X responsibilities (bad) and should be refactored/split.
There is not any magic here, only common sense. Let’s take a simple example with class Driver. This class has two fields : Car and Brain, and five methods : drive(), goTo(), stop(), getAngry() and drinkCoffee(). Here is the dependency graph between those components. There are three blocks of related components, so LCOM4 = 3, so the class seems to have three different responsibilities and breaks the Single Responsibility Principle.

When it comes to Sonar, things remain pretty simple. A first widget is available within the project dashboard to get a quick insight :

From there, you can click to drill down and view the suspect classes. Knowing the LCOM4 value of a class is a good starting point but definitely not sufficient. Click on the class you are interested in and you will be presented with the block of cohesive methods :

Refactoring can start !
While writing this post, II found out a great post from Stuart Gunter : Assessing the Single Responsibility Principle with LCOM4 with Sonar 2.0. This is a post on “Sonar’s LCOM4 in action” that gives us good feedback on how to improve our algorithm to compute this experimental but valuable metric.


I’m not sure about this, but I think you should take into account methods inherited from an abstract class implemented in a specific class. The design problem, if any, is in the abstract class, not in the specific one. What do you think?
By Telemaco on June 22, 2011 at 6:32 pm
Hello, could you provide a simple java example to be sure to talk about the same thing ? I’d prefer having this discussion on the user Sonar mailing list : http://www.sonarsource.org/support/.
Thanks
Freddy
By Freddy Mallet on June 23, 2011 at 3:39 pm
Hello! But what about Abstract Factory pattern? We have a lot of unrelated methods in factory implementation and each Factory produces itself Product. Of course we will have big LCOM4. Don’t you think so?
By Michael on November 17, 2011 at 3:18 pm
You’re right Michael and that’s a case I’m currently thinking about to automatically remove such false-positives.
By Freddy Mallet on November 20, 2011 at 7:56 pm
Avoiding false-positives in the algorithm is laudable, but I think there will always be times when human decisions on design trump all else. In those cases it will be nice to have annotations or some other mechanism to mark code that has been reviewed and accepted with the given metric rating, LCOM4 or other.
LCOM4 is very useful. Great work!
,chris
By Chris on January 4, 2012 at 9:16 am
Really a good metrics and clearly helps in OOPs design principle. Yes, if Sonar gives less false-positive then its more wonderful.
By Raghu Semburakkiannan on January 9, 2012 at 6:01 am
Hi,
I agree with Telemaco and Michael. The LCOM4 metric is to show you suspect classes, in which the Single Responsibility Principle could be violated.
One pattern that could be taken into account automatically is, that if a class implements abstract methods from a superclass, these methods are taken out of the measurement. (The idea is, that these method are measured as part of the superclass, the derived class just implements a contract that is imposed by the superclass)
As a first step, what is really and badly needed, is a way to take single classes out of the LCOM4 metric, once you have decided that despite the high metric for that class, the design is ok.
Thanks,
Andreas Ebbert-Karroum
By Andreas Ebbert-Karroum on March 19, 2012 at 10:59 am
The referenced article’s link has changed to the following: http://www.g3it.com/blog/technical/java/assessing-the-single-responsibility-principle-with-lcom4-and-sonar-2-0/
By Graham R on October 11, 2012 at 10:19 am
How would you solve the Lack of Cohesion problem in the example class Driver?
By Wolf480pl on October 29, 2012 at 6:53 pm
hi,
I am interested to know how exactly the LCOM4 is calculated. If you could explain w.r.t. the example in the above blog.
By rajeev on February 22, 2013 at 2:06 pm