Monday, May 30, 2005

Important Metrics

"Decades of evidence say that routines of such length are no more error prone than shorter routines...issues such as the routine's cohesion, depth of nesting, number of variables, number of decision points, number of comments needed to explain the routine and other complexity related considerations dictate the length of the routine rather than imposing a length restriction per se."

From Code Complete (2nd Edition) pp173-174

Empirical Analysis of CK Metrics for Object-Oriented Design Complexity: Implications for Software Defects More significant metrics seem to be:
* DIT - Depth of Inheritance Tree (the deeper the worse/the more clumped together the better).
* NOC - Number of child classes (more the better - reuse leads to better quality).
* NOM - Number of methods per class (the less the better).
* NOV - Number of variables (the fewer the better).

Good summary of defects to metrics on page 3 here.

An Empirical Comparison of Modularity of Procedural and Object-oriented Software Average of 7.5 lines of code per method in Java.

"This design flaw, is one of the "smells" presented in [7]. It refers
to classes that define data fields and almost no methods except some
accessor methods for the data fields."

Data objects and code smells:
* Detecting Design Flaws via Metrics in Object-Oriented Systems
* Detection Strategies: Metrics-Based Rules for Detecting Design Flaws

Penned Papers on Pair Programming

Extreme Programming: First Results from a Controlled Case Study "Results shows that while the first release is a learning effort for all stakeholders, the second release shows clear improvement in many regards. The estimation accuracy is improved by 26% and productivity was increased by 12 locs/hour. Yet, the post-release defect rate remained low, i.e., 2.1 defects/KLoc."

Has a nice graph of effort in XP projects here (page 5).

The Costs and Benefits of Pair Programming "Significantly, the resulting code has about 15% fewer defects". Also shows that the same functionality is implemented in up to 25% less code.

Thursday, May 19, 2005

Failing Tests

Four approaches to writing a test that expects an exception to occur:

  • Approach 1:
    public void failGetter() throws IllegalArgumentException { 
    new Foo(null).getMember();
    }

  • Approach 2:
    public void testGetter2() { 
    String msg = ThrowAssert.assertThrows(IllegalArgumentException.class, new Block() {
    public void call() throws Exception {
    new Foo(null).getMember();
    }
    });
    }

  • Approach 3:
    public void testGetter3() { 
    Foo foo = new Foo(null);
    String msg = ThrowAssert.assertThrows(IllegalArgumentException.class, foo,
    new CallSpec("getMember", new Class[]{}, new Object[] {null}));
    }

  • Approach 4:
    public void testGetter4() { 
    try {
    new Foo(null).getMember();
    fail("Expected NPE");
    } catch (NullPointerException npe) {
    // We expect this to happen.
    } catch (Exception e) {
    fail("Wrong exception thrown");
    }
    }


I generally prefer Approach 2 because it is more extensible, use it when:

  • There are multiple assertions to be checked and complicated calling is expected.

  • Multiple exceptions are thrown, you can ignore any exception including checked exceptions.

  • Assertions need to be made on the message from the thrown exception.

  • There needs to be an opposing assertion - a test that it doesn't throw an exception (assertPasses).

  • Variables can be made final.


Approach 1 can be used when the intent and code can be expressed on one line and only one exception is expected. It also requires there to be a bit of code in a test base class although it is inconsistent with the usual "textXXX" method names used for test code.

Friday, May 06, 2005

Mutating to Immutable

RFE: Add Immutable types to Java "This proposal is to add an interface to mark a class as immutable (note immutability on a per class basis not a per object basis) and to add immutable and companion mutable classes plus two helper interfaces for conversion to/from immutable and mutable."

Some comments: "...== should map to a.equals(b), as they both must have the same samantics for an immutable class. Remember Immutable objects may not be cloned or copy constructed and implementation details like hash-consing (and pass by reference or pass by value) should be invisible to the programmer."

Near the bottom is a link to PEC - Pattern Enforcing Compiler, "A pattern enforcing compiler™ (PEC™) allows classes to be marked as having a given design pattern, e.g. Singleton. The PEC™ then checks that the marked class conforms to the pattern and issues an error message if it does not, thus the pattern checking is much like type checking. The PECs™ downloadable from this site require no new syntax and therefore they can be used with existing: editors, IDEs, pretty printers, etc. The downloadable PECs™ are extensible and therefore as well as using the supplied patterns a programmer can write their own patterns and have the PEC™ enforce these."

It comes with some existing code knitting patterns such as: Immutable, Value, and Multiple Dispatch.