Rich Web Experience

JSFOne

Private Events

Blogs

View all Blogs >>
  • Andrew Glover

    Co-author of "Continuous Integration"

    Enjoy the reading, baby: Continuous Integr more»

  • Michael Nygard

    Agile technology leader and dynamicist

    If large amounts of dirty data are actually valuable, how do you go about collecting it? Who's in the best position to amass huge piles? more»

  • Keith Donald

    Lead of Spring Web and Creator of Spring Web Flow

    I am pleased to announce that Developing Rich Web Applications with Spring, a three-day bootcamp lead by SpringSource engineers on web... more»

  • Mike Levin

    Software Developer specializing in Web2.0 websites

    “ align=“left” Del.icio.us is one more»

  • Matt Raible

    Creator of AppFuse and author of Spring Live

    Last Thursday, Kevin Brown visited LinkedIn's Mountain View office to do a presentation on Shindig, more»

  • Ted Neward

    Enterprise, Virtual Machine and Language Wonk

    If you've peeked at my blog site in the last twenty minutes or so, you've probably noticed some churn in the template in the upper-left... more»

  • Neal Ford

    Application Architect at ThoughtWorks, Inc.

    OK, it's finally here. I g more»

  • Richard Monson-Haefel

    VP of Developer Relations, Curl Inc.

    more»

  • Nathaniel Schutta

    Author, speaker, software engineer focused on user interface design.

    I don’t get to go to quite as many conferences as I’d like but luckily more and more organizers are putting talks on-line or... more»

  • Alex Miller

    Sr. Engineer with Terracotta Inc.

    I’m just starting to build out an app that uses Hibernate. I started with Hibernate mapping files but switched over to using JPA... more»

  • Pramod Sadalage

    Co-author of "Refactoring Databases:Evolutionary Database Development"

    When creating a Foreign Key constraint on the database as shown below ALTER TABLE BOOK ADD (CONSTRAINT FK_BOOK_ more»

  • Guillaume LaForge

    Groovy Spec Lead & Project Manager

    more»

  • Pratik Patel

    Software Architect

    I've been (very) slowly hacking away at new-and-improved Dojo plugin for Grails. I've found that Dojo, not Grails, has been my bottleneck -... more»

  • Graeme Rocher

    Project Lead of the Grails Project & CTO of G2One

    Apologies for not posting as frequently recently, I've been hard at work on the second edition of "The Definitive Guide to Grails" and also... more»

  • Jeff Brown

    G2One Director Of North American Operations - Groovy and Grails Developer

    G2One have announced our G roovy/Grails No more»

  • Jared Richardson

    Agile coach and co-author of Ship It

    Ouch. I feel guilty. The Joy of Tech on 3G iPhones more»

  • Ryan Shriver

    Business and Technology Consulting

    more»

  • Venkat Subramaniam

    Founder of Agile Developer, Inc.

    I have been waiting for this book since I saw my friend Neal more»

  • Jason Rudolph

    Author of Getting Started with Grails

    As of 8:55 EDT, there’s no direct link to the store just yet, but you can “hack” your way in. Just search the iTunes st more»

  • Howard Lewis Ship

    Creator of Tapestry and HiveMind

    I'll be flying into Cambridge, UK for a week of Tapestry training. I'll be there from Sunday through Thursday night before returning to... more»

  • Erik Doernenburg

    Principal Consultant @ Thoughtworks

    For a few releases the Apple development tools have included OCUnit and many developers have now started to write unit tests. There are lots... more»

  • Brian Pontarelli

    Brian Pontarelli - founder of Inversoft

    Found a good shortcut for getting access to hidden folders in OS X file dialogs and the Finder. It requires some typing and it doesn’t... more»

  • Vladimir Vivien

    Software Engineer / Consultant

    Judging from the list of features that will be included in NetBeans 6.5, more»

  • David Bock

    Principal Consultant, CodeSherpas Inc.

    I just spent this weekend speaking at the Ag ile IT Exchange conference i more»

  • Scott Leberknight

    Chief Architect at Near Infinity

    I ran into a situation the other day with Groovy that baffled me at first. Let's create a range from 0.0 to 10.0 and then use it to check if... more»

  • Kirk Knoernschild

    Software Developer & Mentor

    I’ve published a summary of the OSGi survey results on the APS blog more»

  • Stuart Halloway

    CEO of Relevance

    I was talking to Tim the other day about auditing Rails projects, a more»

  • Brian Goetz

    Author of Java Concurrency in Practice

    This surprised the heck out of me.�� We recently finished a new TV room down in the basement.�� We have a 50″ plasma TV, mounted on the... more»

  • Jason Harwig

    Senior Software Engineer at Near Infinity

    I was reading a blog entry at more»

  • Craig Walls

    Author of Spring in Action

    For quite some time I've been pondering OSGi and how it fits into enterprise Java. And that interest has been magnified over the past month... more»

  • Pete Behrens

    Organizational Agility Coach

    Marti nig & Associates Methods & Tools group recentl more»

  • Joseph Nusairat

    Author of Beginning JBoss Seam & Co-Author of Beginning Groovy & Grails

    Today is the first day of JBoss World, I survived the first three presentations and waiting for the keynote to be  complete to d more»

  • John Heintz

    Principal Consultant with New Aspects of Software

    This post is to mostly keep track of the numerous blog threads going on about IDLs and schemas for REST. I find myself with more to say that... more»

  • Brian Sam-Bodden

    Java author, Ruby geek and Open Source Advocate

    In this installment we are going to build the Dashboard page of the Tempo application. T more»

  • Mark Fisher

    Spring Integration Lead

    In my recent post, I had mentio more»

  • Ron Bodkin

    Chief Software Architect, Quantcast

    I'm looking forward to speaking at The Rich Web Experience conference in San Jose next month. The event runs from September 7th through 9th.... more»

  • Mark Goodwin

    Web Application Security Specialist

    We've already looked at one of the two big problems posed by anti DNS pinning on Java applets; because there's rebinding on the applet and... more»

  • Scott Davis

    Author of "Groovy Recipes" & TDD Expert

    Every time I see a live show at the Denver Botanic more»

  • Romain Guy

    Java User Interface expert.

    more»

  • Ramnivas Laddad

    Author of AspectJ in Action, Principal at SpringSource

    InfoQ.com has published my AOP myths and realities talk recorded at a No Fluff Just Stuff conference. InfoQ.com founded by Floyd Marine more»

  • David Geary

    Author of Graphic Java and co-author of Core JSF

    The 2006 NFJS tour kicked off t more»

  • Jason Hunter

    Author of Java Servlet Programming

    I just posted the JDOM 1.1 release for download. This release includes about 20 improvements and bug fixes. more»

  • Kito Mann

    Editor-in-chief of JSF Central and the author of JSF in Action

    In this three-part series, author and Java™ developer Andrei Cioroianu shows you how to automatically save form data in a Java Web... more»


Unambiguously analyzing metrics

Posted by: Andrew Glover on 03/19/2008

Software metrics are objective measurements of particular aspects of code– for instance, Cyclomatic complexity measures complexity without any regard for why code contains a certain number of paths. For metrics to be useful, baby, they must be applied subjectively. In the case of complexity, there may be circumstances that warrant such code (although, I’ve yet to find complex code that still can’t benefit from refactoring). I’ve also found that, on the whole, metrics are more copasetic when combined with other metrics and trended– for instance, complexity alone is somewhat interesting, but pairing complexity with code coverage paints a much more detailed metric that bears understanding. High complexity with low coverage is clearly more risky than the same complexity with high code coverage– even the CRAP metric holds this relationship.

One particular hip metric that I find helpful is the ratio of copy and pasted code within a code base as unknown copy and pasted code will haunt you, man. For instance, copy and pasted code replicates bugs and poorly coded algorithms to name a few nefarious aspects; consequently, understanding what code has been replicated can help teams refactor offending code. Having run various copy and paste analyzers on more code bases than I care to admit, (and because it’s my bag) I’ve found that all code bases have a certain level of offending code that triggers a copy and paste detection. One particular tool, CPD, is nice enough to create a report containing the offending code like so:

<duplication lines="7" tokens="53">
 <file line="36" path="cbd4/blackjack/src/com/stelligent/blackjack/Hand.java"/>
 <file line="42" path="cbd4/blackjack/src/com/stelligent/blackjack/Hand.java"/>
 <file line="48" path="cbd4/blackjack/src/com/stelligent/blackjack/Hand.java"/>
 <codefragment>
 <![CDATA[
    } else if (first.equals("Jack")) {
      if(!second.equals("King") && !second.equals("Queen") && !second.equals("Jack")){
         return Integer.parseInt(second) + 10;
     } else {
      return 20;
    }
   }else if(first.equals("9")){
]]>
</codefragment>
</duplication>

As you can see, CPD reports the total number of lines of copy and pasted code and where that bogue code can be found. This data is certainly helpful; however, it doesn’t paint the entire story– while 7 lines doesn’t seem like all that much code, you’d probably reconsider if it were 7 lines of code in a 30 line code base or more realistically– 700 lines in a few thousand line code base. Therein lies the catch– CPD’s data is really only helpful when viewed on the whole (or a ratio– that is, total lines of copy and pasted code over total lines of code). Unfortunately, CPD doesn’t report the total lines of code scanned– only the total lines of copy and pasted code. For instance, in this sample code base, there were 9 suspected copy and pasted code fragments totaling about 120 lines of code (or CPLOC).

Luckily, there’s another handy tool which reports the total lines of code (or LOC) in a code base– JavaNCSS. Running JavaNCSS yielded a value of about 610 LOC; therefore the ratio of copy and pasted code is CPLOC/LOC or 120/610, which is roughly 20%.

20% CPLOC is probably a bad thing– at a minimum is is worth knowing about. 20% today might not be too important to know, but knowing that it increased to 25% next week would be an indication that things are degrading– likewise, seeing a value decrease over time indicates the code base is actively being improved. Yet, how can teams possibly monitor this trippin’ data?

Reports are hip, but in truth, reports by tools like CPD are essentially read once– the first time they are generated. After that, it’s anyone’s guess when someone will actively read the report again. Hence, I find it particularly helpful to essentially throw the report out and let the build itself proactively tell me when a particular metric gets out of hand. This essentially means that my build has to monitor a particular metric– and in the case of the CPLOC ratio, my build has to gather data from two sources– JavaNCSS’s report and CPD’s.

Fortunately, this is easy with Groovy– if your instance, you are using Ant for builds, you can first generate the two reports as follows:

<target name="cpd">
 <mkdir dir="target/reports"/>
 <taskdef name="cpd" classname="net.sourceforge.pmd.cpd.CPDTask"
   classpathref="classpath"/>
 <cpd minimumTokenCount="10" outputFile="target/reports/cpd.xml" format="xml">
  <fileset dir="src">
   <include name="**/*.java"/>
  </fileset>
 </cpd>
</target>

The code above generates a CPD XML report from all the code in a src directory and the following code creates a JavaNCSS report from the same code base:

<target name="javancss">
 <taskdef name="javancss" classname="javancss.JavancssAntTask"
   classpathref="classpath" />
 <javancss srcdir="src" generateReport="true"
   abortOnFail="true" ccnPerFuncMax="100"
   outputfile="target/reports/javancss_metrics.xml" format="xml" />
</target>

The only high-level step left to do is to put the two metrics together; however, this step actually takes a few sub-steps, baby. For instance, obtaining the total lines of CPLOC requires iterating over a collection of duplication elements in the CPD xml file. Consequently, the following steps detail the effort required to obtain this metric:

  • parse the JavaNCSS xml report and obtain the total LOC
  • parse the CPD xml report and obtain the total CPLOC
  • divide the two and compare the result to some threshold
  • if the threshold is exceeded, fail the build

Groovy, by the way, is particularly well suited for such a task (as if you didn’t know that, man?)– parsing XML with Groovy is practically effortless– like disco dancing, eh? For instance, obtaining the total LOC from JavaNCSS’s xml file is as easy as

int ncss = Integer.parseInt(jncssroot.packages.total.ncss.text())

Note, I’m coercing integer values as I’d like to divide (and round) my result– if I don’t explicitly specify int’s I’ll be left with String division, which doesn’t work so well.

Parsing CPD’s xml document is slightly more complex– slightly in that it takes 3 times as much code:

def cpdtot = 0
cpdroot.duplication.each { elem ->
 cpdtot += Integer.parseInt(elem.@lines.text())
}

Again, parsing an XML document yields String values; accordingly, I need to use Integer’s parseInt method.

Next, all I need to do is divide the two and, in my case, I’m aggressively rounding up via Java’s ceiling call as follows:

def ratio = Math.ceil((cpdtot / ncss) * 100)

Multiplying the result by 100 gives me a percentage value, of course, and lastly, I compare that to a threshold value:

if(ratio > Double.parseDouble(properties.cpd_threshold)){
  ant.fail(message:
   "cut and paste ratio was greater than ${properties.cpd_threshold}%, it was ${ratio}%")
}

Puttin’ it all together, baby, yields a groovy Ant script with a hip target:

<target name="cpd-threshold" depends="metrics">
 <groovy>
 def jncssroot = new XmlSlurper().parse("target/reports/javancss_metrics.xml")
 int ncss = Integer.parseInt(jncssroot.packages.total.ncss.text())

 def cpdroot = new XmlSlurper().parse("target/reports/cpd.xml")

 def cpdtot = 0
 cpdroot.duplication.each { elem ->
  cpdtot += Integer.parseInt(elem.@lines.text())
 }

 def ratio = Math.ceil((cpdtot / ncss) * 100)

 if(ratio > Double.parseDouble(properties.cpd_threshold)){
  ant.fail(message:
   "cut and paste ratio was greater than ${properties.cpd_threshold}%, it was ${ratio}%")
 }
 </groovy>
</target>

Reports are hip, but they are usually only read once– the first time they are generated. Rather than waiting to find out that there’s a problem, proactively analyzing a hip metric (such CPLOC/LOC) enables rapid feedback and rapid corrections– is that unambiguous or what?

I also blog at testearly.com | My company is hiring gurus


be the first to rate this blog

About Andrew Glover

Andrew Glover is the President of Stelligent Incorporated, which helps companies address software quality with effective developer testing strategies and continuous integration techniques that enable teams to monitor code quality early and often.

Andrew was the founder of Vanward Technologies, which was acquired by JNetDirect in 2005. He is the co-author of Addison Wesley's "Continuous Integration", Manning's "Groovy in Action" and "Java Testing Patterns". He is an author for multiple online publications including IBM's developerWorks and Oreilly's ONJava and ONLamp portals. He actively blogs about software quality at thediscoblog.com and testearly.com.

More About Andrew »