Is it "bad practice" to effectively cache the result of executing expensive stateless checking code by returning a null in the case of a "no problem found"? The upside is minimal code and no class/code bloat.
This is illustrated by this code:
public static String getErrorMessage(SomeState x) {
// do some "expensive" processing with "x"
if (someProblem)
return "Some problem";
if (someOtherProblem)
return "Some other problem";
return null; // no error message means "all OK"
}
And the calling code:
String message = getErrorMessage(something);
if (message != null) {
display(message);
return;
}
// proceed
This pattern avoids having to repeat executing the expensive code twice by returning null to mean "there's no error message, because there's no error". And there's no extra "low value" classes/code.
The obvious alternatives are A) to separate out the concerns of checking and message creation:
public static boolean isOK(SomeState x) {
// do some "expensive" processing with "x"
return thereIsNoProblem;
}
public static String getErrorMessage(SomeState x) {
// do some "expensive" processing with "x"
if (someProblem)
return "Some problem";
if (someOtherProblem)
return "Some other problem";
}
And the calling code:
if (!isOK(something)) {
display(getErrorMessage(something)); // expensive code called a second time here
return;
}
// proceed
which executes the expensive code once to determine if there's a problem, and again to determine what the problem is, or B) to return a "result" object that has a boolean field to answer the "if" part and a String field to answer the "message" part, eg
class MyResult { // like a struct in C
boolean ok;
String message;
// accessor methods omitted
}
public static MyResult verify(SomeState x) { ...}
And the calling code:
MyResult result = verify(something);
if (!result.ok) { // spare me the lecture on accessors - this is illustrative only
display(result.message);
return;
}
which creates class bloat and is a little clumsy IMHO.
Is it "bad" to "overload" the return value in this way?
It is certainly "neater" than all the alternatives I can think of.
I would use:
Then:
And:
Alternatively, you could have it throw a checked exception.
Then: