|CIWS metric calculator|
|Written by Peter Perhac|
Chained Invocation Weighted Score (CIWS) is a number calculated for each Java source file and it shows how often are methods invoked on the objects returned from other method calls. Well, actually, what this metric shows would need a bit more thinking about and investigating, which I am more than happy to do, and will do in due course.
Chained invocation is closely related to the Law of Demeter, which I talk about in a different article.
Below, you will find a snapshot of the most CIWS-loaded 18 classes from the JDK source and below that an explanation of how the CIWS score is actually computed.
To understand the values shown in the table, a bit of explaining on my side is needed. The score accumulates as the metric calculator passes through a Java file that's previously been treated by the Code Stripper.
I described chained invocation as `methods invoked on the objects returned from other method calls`. For example:
String trimmedString = myList.get(index).trim();
Calling get() on the myList object returns a String object, and directly on this returned object we invoke the trim() method. So we have chained two method calls together. Length of invocation chain in this case is 1 (one).
The CIWS score will only be updated when the length of the invocation chain is greater than zero - that is only if there are any invocations chained at all. Points that would be added to the score are calculated using the formula:
points = 2^(chainLength - 1)
Say, we started with a CIWS score of 0 (zero) and found a statement like the previous one. Chain length = one, points added to the CIWS score = 2^(1-1) = 2^0 = 1. Let's add that to the score and continue. [CIWS=1].
What about the following example?
String result = new StringBuilder().append("Peter ").append("is ").append("a ").append("good ").append("student.");
Here we have a chain of 5 (five) method invocations. In this particular case, chaining method calls is not a very bad idea. Indeed, you could find similar use of the StringBuilder in many Java applications. Still, let's update the CIWS score: points for this statement = 2^(5-1) = 2^4 = 16. [CIWS = 17]. But what about this piece of code?
String className = objectListKeeper.getObjectList().get(index).getClass().getName();
You may now gasp in horror. Now stop gasping and let's count. Length of chain is 3 (three), which would add four points to the CIWS score [CIWS=21]. Well, that's not too bad, or is it? Statements like this indicate serious design issues. It's generally a bad practice to return collection objects, which is obviously what getObjectList() does. I am not going to dwell too much on this, not going to attempt to provide the best solution to this situation, or make any changes to design. I will only suggest taming the CIWS score:
List myList = objectListKeeper.getObjectList();
First two lines don't chain any method invocations. It's only in the third line that getName() is invoked directly on the Class object returned from the getClass() call. So the chain length is only 1 (one) and this would raise the CIWS score by one point only.
The other two columns shown in the image (re-displayed below) are measures gathered alongside the calculation of the CIWS score.
CIWS-MAX shows the maximum length of chain invocation found in the Java file, which is not to be mistaken for maximum number of points awarded for a single statement, as the column heading may suggest. CIWS-SD shows the standard deviation of invocation chain lengths found in the Java file. This number shows the difference between Java files that use a certain length of invocation chain throughout (e.g. file #3 in the table) from those that generally don't chain invocations but there's one dirty spot where the chain length is rather high (e.g. file #4 in the table).
So, you may see that the CIWS metric could help identifying ugly code, bad design, etc... But it's not good as itis in its current state. We have seen that the usage of chained invocation when building a string using a StringBuilder (or StringBuffer, which is synchronized) is quite understandable and, looking at various Java projects' source, quite often found in various places. Is it fair to add 16 points to the CIWS score for building a string using StringBuilder and only 4 points for the dodgy code in the other example? These issues need to be addressed by further work on the CIWS calculator.
Also, the meaning of the CIWS score needs to be defined more precisely. What does it mean when a Java source file comes out with a CIWS score of 21 (as it did in the example above)? What does it mean that the XPathParser.java file of the JDK1.6 source has a CIWS score of 693? Why should any developer bother trying to keep the metric down? Why should anyone ever investigate what's wrong with the files where the CIWS is greater than some safe value. What is the safe value? How does all of this relate to the LOC size of the code?
I'm on the case.
|Last Updated on Thursday, 03 December 2009 00:28|