Home > Articles > Programming > C/C++

  • Print
  • + Share This
Like this article? We recommend

Reworking an Example in Java Using Metrics

In Five Steps to Better Multi-language Programming Using Metrics: Simplicity in Multi-language Coding: C/C++, Java, Bash, and Python, I review the block of Java code shown in Listing 5.

Listing 5 JBoss Java code example.

public class ExecutionProfiler

{
 @AroundInvoke
 public Object profile(InvocationContext invocation) throws Exception
 {
  long startTimeSnapshot=System.currentTimeMillis();

  System.out.println("Now at the beginning of the interceptor method " +
   invocation.getMethod() + " startTimeSnapshot " + startTimeSnapshot);

  try
  {
   return invocation.proceed();
  }
  finally
  {
   long endTimeSnapshot=System.currentTimeMillis();
   long executionTime=System.currentTimeMillis()-startTimeSnapshot;
   System.out.println("Now at the end of the interceptor method " +
    invocation.getMethod() + " endTimeSnapshot " + endTimeSnapshot);
   System.out.println("Method " + invocation.getMethod()
    + " time taken: " + executionTime + " milliseconds");
  }
 }
}

The code in Listing 5 isn’t too bad. This is another key skill to develop; that is, the ability to read code written by other people. The principal method in Listing 5 is called profile(), which gives a good solid hint about its purpose. An educated guess would suggest that this code serves to provide some timing details for execution profiling. It turns out this guess is correct; the choice of a meaningful name by the original programmer has helped the downstream user (that’s us).

In terms of legibility, the code spacing is a little bit off in lines like these:

long startTimeSnapshot=System.currentTimeMillis()

But we can fix those lines with ease, if we like. Now let’s review the metrics.

Metric

Result in Modified Code (Listing 5)

Variable names that are too short and provide no usage context

No change needed.

Code that provides no context or obvious purpose

No change needed.

Inconsistent spacing

Better. Notice the use of spaces in Listing 5, improving readability.

Inconsistent parameter-type definition

No change needed.

Incomprehensible code

No change needed.

Code that’s too long

No change needed.

No exception handling

Needs attention.

No automatic resource management

No change needed.

External calls that are not contained in separate methods

No change needed.

Inadequate abstraction (need for higher-level code)

Needs attention.

Code that’s difficult or impossible to change

No change needed.

Now that we have a metrics-driven blueprint for refactoring, let’s update the Java code and then review the modified version.

Listing 6 illustrates the Java code after examination with our 11 metrics.

Listing 6 Reworked post-metrics JBoss Java code.

public class ExecutionProfiler
{
 @AroundInvoke
 public Object profile(InvocationContext invocation) throws Exception
 {
  boolean exceptionOccurred = false;
  long startTimeSnapshot = System.currentTimeMillis();

  System.out.println("Now at the beginning of the interceptor method " +
   invocation.getMethod() + " startTimeSnapshot " + startTimeSnapshot);

  try
  {
   return invocation.proceed();
  }
  catch (Exception exc)
  {
   exceptionOccurred = true;
   System.err.println("Exception: " + exc.getMessage());
   // Do something with the exception, cleanup, close files, etc.
  }
  finally
  {
   if(!exceptionOccurred) {
    long endTimeSnapshot = System.currentTimeMillis();
    long executionTime = System.currentTimeMillis() - startTimeSnapshot;
    System.out.println("Now at the end of the interceptor method " +
     invocation.getMethod() + " endTimeSnapshot " + endTimeSnapshot);
    System.out.println("Method " + invocation.getMethod()
      + " time taken: " + executionTime + " milliseconds");
   }
  }
 }
}

The code in Listing 6 is now less brittle than that in Listing 5. This is because the Listing 6 code takes into account any exceptions that might occur. You might also notice that the exception-management approach used in Listing 5 is very common—using a try-finally statement without a catch clause. This technique is often convenient to code, but in my opinion is quite a dangerous omission. Why so?

Well, in any exception scenario, the finally clause will always execute in any case, even if a catch clause runs. If no catch clause is included (as is the case in Listing 5), then the code running in the finally clause may have suffered some serious exception condition. This exception can then leak back into the main code flow. This is such a serious issue that it even has a name: exception leakage. Leaking an exception back into your main application code is not a recipe for success. This is why the exception handler in Listing 6 is superior to that of Listing 5.

  • + Share This
  • 🔖 Save To Your Account