The NPath complexity of your code is exactly the number of unit tests required to get complete coverage of it. Complexian exists to measure the NPath complexity of your code and to warn you when it gets too high. Keeping the number low means that you can cover many more of the paths through your system with unit tests. That can save valuable time and money as projects get bigger and go for longer periods of time.
Fortunately, when your complexity gets too high, it’s usually skewed dramatically by a few poorly designed classes and method in your system. The best thing to do is to focus some refactoring effort just on those classes. You can get dramatic bang for buck as a result of that focussed effort. Complexian can tell you exactly where to find the code you should be working on.
Download: complexian-0.14.1.zip MD5
Using Complexian from the command line
Execute a command as follows, and pass a parameter to the command telling it the name of the directory containing your source files. Complexian will find them all from that point. No extra jars are needed.
java -jar complexian-0.14.1.jar [options] Options: -type=[cyclomatic|npath] [-threshold=<threshold>] [-includes=<inclusion-filter> ...] [-excludes=<exclusion-filter> ...] [<dir> ...] -type - The type of complexity check to run. Can be "cyclomatic" or "npath". -threshold - Report on methods exceeding a complexity of this threshold (default 100). -includes - Include files matching the specified pattern. -excludes - Exclude files matching the specified pattern. <inclusion-filter> - An Ant style pattern to include files from. eg. "src/java/**/*" <exclusion-filter> - An Ant style pattern to exclude files with. eg. "**/*Test.java" <dir> - A directory to include all files from. Equivalent to "-includes=<dir>/**/*"
Using Complexian from Ant
Complexian can be run as an Ant task against an arbitrary set of files as specified by nested FileSets. By default, output is in plain text using the default Ant logger, but this can be overridden using nested formatters. Complexity types, thresholds and failure properties are managed using attributes of the task.
|type||The type of complexity check to use. Can be npath or cyclomatic.||Yes|
|threshold||The threshold over which to start reporting on complex methods.||No; defaults to 100.|
|failOnViolation||If true, the build will fail if a method exceeds the threshold.||No; defaults to false.|
|failureProperty||The name of the property to set in the event of a failue.||No|
Nested filesets are used to control which files should be run against Complexian.
The results of Complexian can be printed in different formats. Output can optionally be sent to a file, if the toFile parameter is used. There are two formatters available. The plain formatter prints text output, and the xml formatter prints XML output. If no formatter is specified, output will formatted in the plain style and written to the Ant logger.
|type||The type of formatter to use. Can be plain or xml.||No; defaults to plain.|
|toFile||The name of a file to write the output to.||No.|
<target name="complexian"> <taskdef resource="complexiantask.properties" classpath="lib/complexian-0.14.1.jar"/> <complexian type="npath"> <fileset dir="src" includes="**/*.java"/> </complexian> </target>
Checks the NPath complexity of all methods in .java files under the src directory. A default threshold of 100 will be used, and output will be written to the default Ant logger. The build will not fail if a method exceeds the threshold.
<target name="complexian"> <taskdef resource="complexiantask.properties" classpath="lib/complexian-0.14.1.jar"/> <complexian type="cyclomatic" failOnViolation="true" threshold="10"> <fileset dir="src" includes="**/*.java"/> <formatter type="plain"/> <formatter type="xml" toFile="build/complexian-output.xml"/> </complexian> </target>
Checks the Cyclomatic complexity of all methods in .java files under the src directory. A threshold of 10 will be used, and output will be written both in plain format to the default Ant logger, and in XML format to the file build/complexian-output.xml. The build will fail if a method exceeds the threshold.
When you run Complexian against your code base, you get some output like the sample below. This has been taken from a run against SiteMesh.
Any methods that exceed the complexity threshold are listed in order, with the biggest culprits coming last so that you can clearly see them after Complexian has finished running. A summary of the project is given at the end, telling you the total complexity of the system, and how much of that is attributable to the methods which violated your threshold.
Complexity Analyser 0.14.1 - http://www.martyandrews.net/resources/complexian.html Copyright (c) 2007 Cogent Consulting Pty. Ltd. All rights reserved. Complexian will be free for use until at least the first major release. Method complexity of 530 found in /Users/marty/Products/sitemesh-2.3/src/java/com/opensymphony/module/sitemesh/taglib/page/ApplyDecoratorTag.java:142 Method complexity of 11456640 found in /Users/marty/Products/sitemesh-2.3/src/java/com/opensymphony/module/sitemesh/mapper/PathMapper.java:98 Method complexity of 29997703933 found in /Users/marty/Products/sitemesh-2.3/src/java/com/opensymphony/module/sitemesh/parser/FastPageParser.java:98 The maximum threshold for method complexity is 100. Of the 599 methods in the system, 3 of them have exceeded the complexity threshold. The total complexity of the system is: 30009162608. These methods account for a complexity of: 30009161103. These methods account for 99.99% of the total complexity of the system. Processing time: 0.248sec
Can’t I do this with Checkstyle?
Checkstyle does have support for checking NPath complexity built in. Here’s a few reasons that you might prefer to use Complexian:
- Its significantly faster. Complexian can check the 1.2 million shared lines of code in JDK1.5 in under 15 seconds.
- Output is ordered so you see the “worst” offenders more obviously.
- You get summary of the total system, and how offensive the violations are in relation to it.
- Checkstyle has an overflow bug in it, so you don’t get the real story. (we’ve submitted a patch though, so this will go away eventually).
The most important reason for is that complexity is treated like a second class citizen when its bundled in with other checkstyle checks. Too many times have we seen either the specific check turned off, or checkstyle itself turned off because developers didn’t like some formatting rule.
Its important enough to us that we want that decision to be much more obvious, and treated with more consideration. If producing a tool that deals with the issue directly helps to highlight it, then we’re happy with the outcome.