Relational Cohesion of a Package

Relational Cohesion measures how well a package p hangs together.

That is, for each type in p we measure how many types within p it depends on, and we take the average. To cater for the case that there is only one type in the package (and then obviously the package is quite cohesive!) we add 1 to the resulting average. The recommended range for this metric is between 1.5 and 4.0: too low a cohesion indicates that the package is a "kitchen sink" containing too many unrelated types. On the other hand, a cohesion that is too high indicates a package that is too complex, with too many internal dependencies.

Pre-packaged Queries

Query name = "Semmle/Metrics/Packages/Cohesion/High cohesion packages"

Reports packages that have relational cohesion greater than 4, in decreasing order, as a bar chart.

from MetricPackage p, float c
where p.fromSource() and c = p.relationalCohesion() and c > 4
select p, c order by c desc
Query name = "Semmle/Metrics/Packages/Cohesion/Low cohesion packages"

Reports packages with relational cohesion below 1.5, in increasing order, as a bar chart.

from MetricPackage p, float c
where p.fromSource() and c = p.relationalCohesion() and c < 1.5
select p, c order by c

.QL Source of Metric

This metric is defined in MetricPackage:

     float countDependencies(RefType t) {
          t.getPackage()=this and
          result = count(RefType s |
                                s.getPackage()=this
                                and
                                depends(t,s))
     }

     float relationalCohesion() {
        result = 1+ avg(RefType t |
                        t.getPackage() = this |
                        this.countDependencies(t))
     }

Variations

Our definition above agrees with most other metrics tools such as NDepend. Some modelling tools, for instance those of Objecteering, compute this metric not by counting types, but by counting the different ways one type depends on another. By contrast, the above definition only counts the number of other types one type depends on.

The above definition has been written so that it is easy to override the way in which dependencies are counted. A special version of the depends(s,t) predicate not only records the existence of dependencies between types t and s, but also the reason why t depends on s (as a string), and a position that identifies that reason (such as a method call). (For a full definition of depends, please refer to the documentation of afferent coupling, which spells it out in detail.) Using this special version of depends, we override our previous definition to count the number of reasons for dependencies rather than just the dependencies themselves.

class MyMetricPackage extends MetricPackage {
   float countDependencies(RefType t) {
     t.getPackage()=this and
     result = count(Reason r |
                    exists(RefType s |
                      s.getPackage()=this and
                      depends(t,s,_,r)))
   }
}

References

Robert C. Martin. OO Design Quality Metrics. October 24, 1994.

Robert C. Martin. Agile Software Development, Principles, Patterns and Practices. Addison Wesley, 2002.

Objecteering. Class Category Relational Cohesion (CCRC) , 2007.

SDMetrics. Package metrics , 2007.

Patrick Smacchia. Relational Cohesion , 2007.

Digg!Reddit!Del.icio.us!Facebook!Slashdot!Technorati!StumbleUpon!Ma.gnolia!

Comments
Only registered users can write comments!
 
< Prev   Next >