December 8, 2006

Cohesion, Tracing, Exceptions

When I was discussing some major issues with one of the engineers in my project, we had to investigate some existing code in order to check for the feasibility of several options.

I was shocked when I saw the implementation of one method, which was obviously the one to be enhanced for our purposes. I'll give you a short statistics on the method:

  • appropriate method-name
  • method-length: more than 2 pages
  • depth of nested conditionals: 4
  • location of the method's implementation of its main purpose: in depth 4 in an else-branch almost at the end of the method-body
  • cohesion:?

There was no tracing throughout the method's code, and due to the inappropriate exception-handling there's no chance to figure out, what happened in case of any problem with this method:


   try {
      // very long implementation
      // spread on multiple branches
      // with various assumptions
      // about 100 lines of code
      // without tracing which branch was executed
   } catch (Exception e) {
      throw new SpecialPurposeException( "some arbitrary text" );
   }

There are always discussions about the need for tracing. Personally, I prefer static program or trace analysis over debugging. Also, usually I write very few trace statements in my code, because most often they're not necessary to figure out what happened. The stack trace should easily document the execution path.

To achieve that, it's necessary to separate concerns and to write single purpose methods (on one level of abstraction). For example, the refactoring of that one very overloaded unfocussed method, that almost accidently provided it's service at the end in an else branch, came up with a 7 line method like this:


   if ( <method-precondition met> ) {
      executeTheMethodImplementationThatsNowInANewlyCreatedPrivateMethod();
   } else if ( <wasAlreadyExecuted>) {
      handleAlreadyExecuted();
   } else {
      handleTheCondition();
   }

If an exception occurs in this implementation it will be easy to find the cause, if

  • the called methods are implemented in a similar way

  • exceptions are thrown instead of being swallowed

  • preconditions are checked

I was surprised that the former code existed for quite a while, although it has already caused some trouble before and was investigated by some engineers without being refactored. Due to that, I ordered a copy of Code Complete immediately. I strongly recommend this book for every developer.

Posted by Phillip Ghadir at December 8, 2006 8:38 AM