1

I'm writing a method along these lines:

if (hasFoo()) {
   return calculateFoo();
} else if (hasBar()) {
   return calculateBar();
} else {
   return calculateBaz();
}

The getters are rather expensive and the has...() checks would either duplicate a lot of the logic or just have to reuse the getters. I could have the has...() methods store the result of the get...() in a field and make the getter lazy, but it would be nice for has...() not to have any side effects. I could write this with nested try{} catch{} blocks, but that doesn't look elegant. seems like there should be a better solution to this...

EDIT: changed get...() to calculate...() to make it clear that they're expensive.

Christian Rau
  • 43,206
  • 10
  • 106
  • 177
seminolas
  • 397
  • 6
  • 14
  • So, what is your question then? – adarshr Nov 28 '11 at 10:54
  • http://stackoverflow.com/questions/36707/should-a-function-have-only-one-return-statement – Bart Kiers Nov 28 '11 at 10:55
  • have getFoo() return null if it does not have Foo? – janzi Nov 28 '11 at 10:57
  • your question title appears to be completely wrong - there's nothing here about multiple returns. – Alnitak Nov 28 '11 at 10:59
  • If your `hasXXX()` functions are almost as complicated or as expensive as your `getXXX()` functions then you're doing it wrong. You need to show an example of how a `has()` and a `get()` overlap to see how they might be refactored. – Alnitak Nov 28 '11 at 11:02

8 Answers8

4
int result = 0;

if (hasFoo()) {
   result = getFoo();
} else if (hasBar()) {
   result = getBar();
} else {
   result = getBaz();
}

return result;

is the idiom I prefer to use - makes it far easier to inspect variable values while debugging.

mcfinnigan
  • 10,367
  • 30
  • 28
2

I see nothing wrong in doing

Object fooBarBaz = null;

if (hasFoo()) {
   foo = getFoo();
} else if (hasBar()) {
   fooBarBaz = getBar();
} else {
   fooBarBaz = getBaz();
}

return fooBarBaz;
adarshr
  • 57,189
  • 21
  • 133
  • 158
0

EDIT: If I'm interpreting your comments correctly, it sounds like you actually want something like:

Result result = calculateFoo();
if (result != null) {
    return result;
}
result = calculateBar();
if (result != null) {
    return result;
}
return calculateBaz();

... where each of the calculate methods returns null if the corresponding has method returns false. Now if null is a valid "real" return value, you could always wrap the result so that calculateFoo returns a value which can basically say, "Yes, I've got a valid value and it's X" or "no, I haven't got a valid value" (a "maybe" type).


Original answer

I would keep your code exactly as it is. I see no problems with having multiple return statements when that's the clearest approach - and in this case I believe it is.

You're making it clear that once you've reached each of the "leaf" parts, you know exactly what the return value is, and the only other code which should be executed before leaving the method is any clean-up code in finally blocks.

Having a single exit point makes sense in languages which don't have try/finally or GC (where you really want to make sure you do all the cleanup in a single place) but in Java, I think returning when you know the result states your intention more clearly than using a separate local variable.

Having said that, another alternative to consider is using the conditional operator, laying out your code so it's obviously going through a series of tests and returning as soon as it finds the first "match":

return hasFoo() ? getFoo()
     : hasBar() ? getBar()
     : getBaz();

The disadvantage is that this pattern looks a little odd the first time you see it - but once you get used to it, I find it a really neat way of encoding this sort of logic.

Jon Skeet
  • 1,261,211
  • 792
  • 8,724
  • 8,929
  • I think the calling code looks fine as is, but how do I structure the rest of the methods? consider that each of the `get...()` is actually an expensive `calculate...()` and the answer to `has...()` is only clear after going through most of the same logic. – seminolas Nov 28 '11 at 11:07
  • that's probably why my question is so vague - I like the calling code, but don't know if I can make the rest of the code reasonable for it. Otherwise, is there a better pattern to use? – seminolas Nov 28 '11 at 11:09
  • @huppy_doodoo: I'm afraid *because* your question is so vague, it's hard to understand exactly what you're asking - especially as your question title *appears* to be about having multiple returns in the method, which now sounds as if it's irrelevant... – Jon Skeet Nov 28 '11 at 11:16
  • @huppy_doodoo: See my edited answer (at the top) - is that what you're after? – Jon Skeet Nov 28 '11 at 11:31
  • @Alnitak: No, I don't think so. Your suggestion requires two calls; mine requires *one* call per method of calculation, with the return value indicating success/failure *and* the success value. I find this neater, as requiring that methods are called in a certain order is fragile. – Jon Skeet Nov 28 '11 at 12:00
0

I prefer it this way:

if (hasFoo()) {
    return calculateFoo();
}

if (hasBar()) {
    return calculateBar();
}

return calculateBaz();

All a matter of taste and convention.

CKuck
  • 704
  • 5
  • 18
0

I am not sure if this is your case, but I would try to fully refactor the code. Currently, as far as I understand, your code looks something like this (example):

boolean hasFoo() {
    DataObject do = getSomeDataSource().getSomeDataObject();
    if (do.getF() != null && do.getO() != null) {
        return true;
    } else {
        return false;
    }
}

Foo getFoo() {
    DataObject do = getSomeDataSource().getSomeDataObject();
    Foo result = new Foo(do.getF(), do.getO());
    return result;
}

Basically what happens here is that the same code is used to check if Foo can be returned and to construct the Foo itself too. And I would refactor it to this:

/**
* @returns instance of Foo or null if Foo is not found
*/
Foo getFoo() {
    DataObject do = getSomeDataSource().getSomeDataObject();
    F f = do.getF();
    if (f == null) {
        return null; //Foo can not be created
    }
    O o = do.getO();
    if (o == null) {
        return null; //Foo can not be created
    }

    return new Foo(f,o);
}

Now your original code would become similar to this:

Result r;

r = getFoo();
if (r == null) {
    r = getBoo();
}
if (r == null) {
    r = getDoo();
}
return r;
bezmax
  • 23,632
  • 10
  • 46
  • 84
0

This is not an "is it OK to do multiple returns" problem - your multiple returns are fine.

This is a refactoring and/or state storage problem.

If you have:

bool hasXXX() {
    // do lots of stuff
    ...

    return has_xxx;
}

and

double calculateXXX() {
    // do the same lots of stuff
    ...

    // do some more stuff
    ...

    return xxx;
}

then the complexity of the problem depends on whether the hasXXX() calculation produces lots of intermediate values that are necessary for calculateXXX().

You likely need something like:

bool checked_xxx = false;
double xxx_state;

bool hasXXX() {
   // do expensive stuff
   ...

   // save temporary state variables
   xxx_state = ... 

   // remember that we've been here
   checked_xxx = true;

   // send back the required value
   return has_xxx;
}

double calculateXXX() {
    // make sure that hasXXX was called, and is valid
    if (!checked_xxx && !hasXXX()) {
        // should never happen - you called calculateXXX when hasXXX() == false
        throw new RuntimeException("precondition failed");
    }

    // use the previously calculated temporary state variables
    ...

    // send back the final result
    return xxx;
}
Alnitak
  • 313,276
  • 69
  • 379
  • 466
0

Instead of doing hasXXX() and calculateXXX() you could factor those calculations out to separate objects eg

public interface CalculationModel {
    Object calculate();
}

public class FooCalculationModel implements CalculationModel {
    @Override
    public Object calculate() {
        // Perform Foo calculations
        return result;
    }
}

and your if-statement can then be replaced with:

return getCalculationModel().calculate();

You will need some way of deciding the CalculationModel of course, but this would then replace the hasFoo(), hasBar() etc methods.

Mark Rotteveel
  • 82,132
  • 136
  • 114
  • 158
-1

you could do something like this :

Object bar;
if ((bar = getFoo()) != null) {
  return bar;
} else if ((bar = getBoo()) != null) {
  return bar;
} else {
  return getBaz()
}

this way you only need to call the get methods, but not the has ones

EDIT

this is the same in a more readable format that also elminates the need to call the has methods

Object bar = getFoo()

if (bar == null) {
  bar = getBoo()
}

if (bar == null) {
  bar = getBaz()
}

return bar;
Peter Szanto
  • 6,723
  • 2
  • 43
  • 50
  • somebody once told me it's a bad practice to assign and check on one line, although it looks nice. – seminolas Nov 28 '11 at 11:12
  • This looks scary, I wouldn't like to see code like this in my projects. – bezmax Nov 28 '11 at 11:13
  • @huppy_doodoo: In huge projects lots of people tend to make changes to the same code, or debug it. Each place you try making "shorter" (like in this answer), eventually leads to 20-30 more seconds for a "new guy" to understand what this line actually does. Which also leads to lots of errors in the future. That's why you shouldn't do this shortening stuff in most cases. There are still some reasonable places where you can use them, but only because every programmer seen it millions of times and knows exactly what they do. For example: `while ((line = file.readLine()) != null)`. – bezmax Nov 28 '11 at 11:22
  • @Max personally I never do it either, for the same reason as you said, but the requester asked for a solution that eliminates the need of the has methods. The same could be achieved by moving the assignments before the conditions and check NULL only in the conditions. – Peter Szanto Nov 28 '11 at 11:47