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
source to share
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"));
source to share
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.
source to share
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);
}
source to share
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.
source to share
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!
source to share
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);
source to share