Method refactoring that calls other methods that throws an exception

I have several (more than 20) methods ( getXXX()

) that can throw exception (a NotCalculatedException

) when they are called.

In another method, I need to access the results given by these methods. At the moment I have terrible code that looks like this:

public void myMethod() {
    StringBuffer sb = new StringBuffer();
    // Get 'foo' result...
    sb.append("foo = ");
    try {
        sb.append(getFoo());
    } catch (NotCalculatedException nce) {
        sb.append("not calculated.");
    }
    // Get 'bar' result...
    sb.append("\nbar = ");
    try {
        sb.append(getBar());
    } catch (NotCalculatedException nce) {
        sb.append("not calculated.");
    }
    ...
}

      

Without changing the methodsgetXXX

(so they should keep their own throws NotCalculatedException

), how would you refactor / simplify myMethod()

to make it look better?

Please note that this project is still using Java 1.4 :(


EDIT

I cannot put all the methods getXXX()

in a block try { ... }

, since the StringBuffer will be incomplete if one method is chosen NotCalculatedException

.

public void myMethod() {
    StringBuffer sb = new StringBuffer();
    try {
        sb.append("foo = ");
        sb.append(getFoo());
        sb.append("\nbar = ");
        sb.append(getBar());
    } catch (NotCalculatedException nce) {
        sb.append("not calculated.");
    }
    ...
}

      

In other words, if it getFoo()

throws out a NotCalculatedException

, I want to have an output like this:

foo = not calculated
bar = xxx
...

      

If I put everything in one try { ... }

, I have this output, which I don't want to receive:

foo = not calculated

      

+2


source to share


7 replies


I don't think you should be using NotCalculatedException to manipulate logic.

But I have several ideas about this.



  • You need another getter method

    sb.append (this.getFoo ("not evaluated"));

  • Create hasValue method

    sb.append (hasFoo ()? this.getFoo (): "not evaluated");

  • Create a generic getter method

    sb.append (this.getValueByName ("Foo"));

+2


source


For each, getXXX

you can add getXXXOrDefault()

which wraps the exception, returns a value, getXXX

or "not evaluated".

public void myMethod() {    
        StringBuffer sb = new StringBuffer();    
        // Get 'foo' result...    
        sb.append("foo = ");
        sb.append(getFooOrDefault());
        // Get 'bar' result...    
        sb.append("\nbar = ");
        sb.append(getBarOrDefault());
        // ...
}

public Object getFooOrDefault() {
        try {
                return getFoo();
        } catch() {
                return "not calculated.";
        }
}

      

Or ... Use Reflection



public Object getValueOrDefault(String methodName) {
        try {
                // 1 . Find methodName
                // 2 . Invoke methodName 
        } catch() {
                return "not calculated.";
        }
}

      

But I think I still prefer the first option.

+1


source


My suggestion is more code, but improved readability for myMethod:

public void myMethod() {
    StringBuilder resultBilder = new StringBuilder();

    resultBuilder.append("foo=");
    appendFooResult(resultBuilder);
    resultBuilder.append("\nbar=");
    appendBarResult(resultBuilder);

    ...
}

private void appendFooResult(StringBuilder builder) {
    String fooResult = null;
    try {
        fooResult = getFoo();
    } catch (NotCalculatedException nce) {
        fooResult = "not calculated.";
    }
    builder.append(fooResult);
}

private void appendBarResult(StringBuilder builder) {
    String barResult = null;
    try {
        barResult = getBar();
    } catch (NotCalculatedException nce) {
        barResult = "not calculated.";
    }
    builder.append(barResult);
}

      

+1


source


I think you should leave your code as it is. It's verbose, but it's very easy to tell what he is doing and he is behaving correctly.

+1


source


In an array, you can store "foo", "bar", etc. Loop around them, print each one and then use reflection to find / call the corresponding getFoo (), getBar (). Not good, I confess.

See Method for more information .

EDIT: Alternatively, use AspectJ to surround each getXXX () method for that object and catch the exception.

0


source


You can use the Execute Around idiom. Unfortunately, Java's syntax is verbose, so it's not a big win in simple cases. Assuming that NotCalculatedException

is a fuzzy exception.

appendThing(sb, "foo = ", new GetValue() { public Object get() {
     return getFoo();
}});
appendThing(sb, "bar = ", new GetValue() { public Object get() {
     return getBar();
}});

      

Another ugly method would combine a loop and a switch:

int property = 0;
lp: for (;;) {
    String name = null; // Ugh.
    try { 
        final Object value;
        switch (property) {
            case 0: name= "foo"; value = getFoo(); break;
            case 1: name= "bar"; value = getBar(); break;
            default: break lp;
        }
        ++property;
        sb.append(name).append(" = ").append(value).append('\n');
    } catch (NotCalculatedException exc) {
        sb.append(name).append(" = ").append("not calculated.\n");
    }
}

      

In addition, you have an enum and a switch for each parameter. Just don't use reflection!

0


source


It looks like Java doesn't have delegates out of the box like C #, however Google showed me that there are ways to throw my own , so there might be something to try ..

public static PrintProperty(JavaDelegateWithAName del, StringBuilder collector)
{
  try
  {
    collector.append( del.Name+ " = " );
    collector.append( del.Target.Invoke() );
  }
  catch(NotCalculatedException nce) 
  { collector.append("NotCalculated"); }
}

      

... main

foreach(JavaDelegateWithAName entry in collectionOfNamedJavaDelegates)
  SomeUtilityClass.PrintProperty(entry, sb);

      

0


source







All Articles