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.