Cyclic Package Dependencies

Strictly speaking not a metric, this set of definitions and queries provides a means for identifying cycles in dependencies between packages, and for exploring them in depth.

One package p depends on another package q if p contains a type s that depends on a type t in q.

For a detailed discussion of the notion of dependencies between types, please consult the discussion of afferent coupling.

Pre-packaged Queries

Name of query = "Semmle/Metrics/Packages/Coupling/Determine packages that cyclically depend on one another"

This reports strongly connected components in the dependency graph of packages. For each such component, it reports a representative element (the package with the lexicographically minimal name) and the size of the component. Underneath this initial description in the tree view, you will find a list of all the elements of a component.

from MetricPackage p
where p.getCycleSize() > 1 and p.isRepresentative()
select "SCC of size " + p.getCycleSize().toString() + " for " + p.getName() as s,
               p.getACycleMember()
order by s desc

    
Query name = "Semmle/Metrics/Packages/Coupling/Cyclic packages with exploration"

While the above query is useful in identifying the existence of cycles between packages, it is sometimes hard to get at the cause of such cycles. The query below helps to drill down into such cases: it reports the cycles, but then for each cycle member, it lists the dependencies on other packages. Furthermore, for each such pair, it gives an explanation of the reasons why the first package depends on the second, both in words (as a string), and as a location you can click on to take you to the relevant source location.

from MetricPackage p,  // representative of cycle 
     MetricPackage q1, // cycle member
     MetricPackage q2, // another cycle member
     RefType s,        // a type in q1
     RefType t,        // a type in q2
     string reason,    // why s depends on t
     Reason click      // locatable for inspecting the reason
where p.fromSource() and q1.fromSource() and q2.fromSource() and
      p.isRepresentative() and 
      q1 = p.getACycleMember() and
      q2 = p.getACycleMember() and
      q1 != q2 and
      s = q1.getARefType() and
      t = q2.getARefType() and
      depends(s,t,reason,click)
select "SCC of size " + p.getCycleSize().toString() + 
              " for " + p.getName() as name,
       q1,q2,
       "explanation", // show why q1 depends on q2
       q1,s,          // q1 contains a type s
       q2,t,          // that depends on t in q2
       reason,click   // report reason
order by name desc

.QL Source

The auxiliary methods for finding cycles and for exploring them are defined in MetricPackage:

    MetricPackage getACycleMember() {
        result.getADependency*() = this
        and
        this.getADependency*() = result
    }

    int getCycleSize() {
        result = count(this.getACycleMember())
    }

    predicate isRepresentative() {
        this.getName() = min(MetricPackage p | 
                             p = this.getACycleMember() | 
                             p.getName())
    }

References

Chris Chedgey. Emergent Package Design: cyclic package dependencies . About: Focus on Java, 2007.

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

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

Glen Wilcox. Managing your dependencies with JDepend . O'Reilly OnJava.com, 2004.

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

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