void methods and "return"

S

Scott Steiner

hi,

void methods cannot return values, however, i noticed that i can still
use "return" without any value to exit a method like this:

public void myMethod(int arg0)
{
if (arg0 == 0) return;
...
}

question: is the above ok or will i get errors with other java versions.
i'm using jre1.4.1_02 in eclipse.

thx!
 
C

Chris Uppal

Scott said:
void methods cannot return values, however, i noticed that i can still
use "return" without any value to exit a method
[...]
question: is the above ok or will i get errors with other java versions.

That's perfectly OK. Java has always worked that way, and almost certainly
always will.

-- chris
 
A

Arnaud Berger

Hi,

This is a "correct" way of finishing a method.
Correct means this is and will be part of the specs I guess.

However, note that in some cases (large methods, multiple loops) it is
tricky to see these return statements which shortcuts the rest of the
method.

Regards,

Arnaud
 
P

P.Hill

Scott said:
public void myMethod(int arg0)
{
if (arg0 == 0) return;
...
}

question: is the above ok or will i get errors with other java versions.

The return key word could be read as meaing "return to where ever the
code is that called this method" and not a statement to send something
back to the caller. As you demonstrated, it has uses
for simple things like guard conditions, but it is also worth
repeating the warning from Arnaud that too many of these or hiding
returns in long routine is often poor style. Fewer returns is better
than more returns, one is the cleanest way to write, but don't go out of
your way to make one and only one.

-Paul
 
C

Chris Uppal

P.Hill said:
it is also worth
repeating the warning from Arnaud that too many of these or hiding
returns in long routine is often poor style. Fewer returns is better
than more returns, one is the cleanest way to write, but don't go out of
your way to make one and only one.

I think this is /completely/ the wrong way around, and is very bad advice (or
it would be if you hadn't added that last clause).

If a method is so long that embedded returns are not easy to spot, then that is
the fault of the method, not of the returns. And the method is clearly is dire
need of either refectoring into smaller methods (the ideal[*]) or at minimum
re-writing to make its structure clearer.

Attempting to reduce the number of embedded returns is a sure-fire way of
producing an unreadable mess.

-- chris

([*] not always feasible for intrinsically complicated algorithms -- but such
cases crop up extremely rarely in my experience)
 
P

P.Hill

Chris said:
I think this is /completely/ the wrong way around, and is very bad advice (or
it would be if you hadn't added that last clause).

I don't see were what I said conflicts with you. I think you are
assuming something I am not.
If a method is so long that embedded returns are not easy to spot, then that is
the fault of the method, not of the returns.

I agree! Who said it as the fault of the returns? Many returns is a
"smell", too many and the code stinks as we like to say in the world of
refactoring.

I don't understand how you read into my post that good ways to
reduce the number of returns would not include:
"refactoring", "make its structure clearer".

I was not trying to state an all encompassing approach to
making more readable code and keeping the number of returns
to an unstandable minimum. I was just stating a rule of thumb
that fewer is better.

I guess what I didn't mention was any rules that would be
in tension with fewer is better, yet I did mention
guard conditions.
Attempting to reduce the number of embedded returns is a sure-fire
way of producing an unreadable mess.

Fewer embedded returns is very often clearer.
Somehow you were assuming something that limited my approach
which I don't believe I stated.

-Paul
 
C

Chris Uppal

P.Hill said:
I don't see were what I said conflicts with you. I think you are
assuming something I am not.

Perhaps. The way I understood what you were saying was that embedded returns
are Not A Good Thing (and your points below reinforce that impression).
Whether or not that is actually a reasonable interpretation of your own
position, it is a view that I disagree with strongly. I consider it a mistake
to encourage people to avoid embedded returns.

I agree! Who said it as the fault of the returns? Many returns is a
"smell", too many and the code stinks as we like to say in the world of
refactoring.

And so is many semi-colons a "smell". In exactly the same sense, and with
exactly the same justification, yet I don't here anyone saying "more than one
semi-colon indicates poor style" (or any weaker version of the same
observation).

I don't understand how you read into my post that good ways to
reduce the number of returns would not include:
"refactoring", "make its structure clearer".

What I read into your post was that reducing returns could be seen as an end in
itself. And that is /precisely/ what I disagree with.

I was not trying to state an all encompassing approach to
making more readable code and keeping the number of returns
to an unstandable minimum. I was just stating a rule of thumb
that fewer is better.

If I had to make a rule of thumb on this particular issue, then I'd say that
more early returns is better than fewer. I.e. I'd like to see people actively
looking for chances to code algorithms in such a way that early returns can be
used to prune the problem space, and hence the complexity of the expression.

Still, I don't really expect that we'd disagree about any particular code. I
just take exception to any advice that is likely to encourage beginners (or
others) to try to avoid early returns -- I've worked with far too much really
crap code that has been produced with such a prejudice in mind.

-- chris
 
P

P.Hill

Chris said:
What I read into your post was that reducing returns could be seen as an end in
itself. And that is /precisely/ what I disagree with.

Okay, I think I see the confusion.
It's more of a way to stimilute criticism of code
to ask the question: would it be clearer to have fewer?
Just like asking would it be clearer to introduce an extra class.
I probably overstated the idea in the way I mentioned one return.
I should not have given value to just one when I meant:
Fewer is better, anyone can understand when there is only one, but don't
go out of your way to make your method have just one when two or three
oftens make the code very readable.
If I had to make a rule of thumb on this particular issue, then I'd say that
more early returns is better than fewer. I.e. I'd like to see people actively
looking for chances to code algorithms in such a way that early returns can be
used to prune the problem space, and hence the complexity of the expression.

This method of cleaning up code can often be combined with refactoring
into new methods, such that a small number of ways (two or three) to
break out of tricky bit of logic can all occur in one method reducing
the higher level to something akin to a series of simple tests.
I consider it a mistake to encourage people to avoid embedded returns.

Sorry, just saying more early returns makes better code I would
not good beginner advice either. Certainly, setting lots of flags to
carry around just to make the code fall through to its final line makes
for really poor code, but open season on returns anywhere is not without
its pitfalls. You already mentioned, more than a handfull and it's time
to consider some cleaning, but other rules might be worth stating like:
lots of simple guard conditions makes for more readable code than
appearances of multiple returns in various places. Where guard
condition is defined as: an as simple as possible conditional that may
result in a return at the highest level of code, less of a surprise and
hence more readbale when they occur near the top of a routine.
And so is many semi-colons a "smell". In exactly the same sense, and
with exactly the same justification, yet I don't here anyone saying
"more than one semi-colon indicates poor style" (or any weaker version
of the same observation).

Apparently you haven't hung out with old smalltalk developers or XP
refactoring folks heavely influenced by smalltalk style. "smalltalk
style" usually results in really small routines on the order of
a few lines including loop definitions and conditions which don't have
semicolons. I would consider that a weaker version of a one-semi
observation.

While a style of keeping things to a reasonable handful might result in:

Foo foo( Bar1 b1, Bar2 b2 ) {
if ( b2 == null || b1 == null ) {
throw new IllegalArgumentException( ... );
}
if ( !b2.fooable() || !b1.fooable() ) return null;

for ( ... } {
if ( ... ) {
blah...;
blah...;
if ( ... ) return firstFoo;
}
}

for ( ... ) {
if ( ... ) {
return secondFoo;
}
}

if ( finalTest( ... ) ) {
return goodFoo;
}
return sorryNothingBetterFoo;
}

Hmm, a simple handful yes. No attempt to carry around
extra flags to fall to the bottom, but no smalltalk influenced
developer would stand for not refactoring that to a set of
2 or 3, 2 return methods.

Foo foo( Bar1 b1, Bar2 b2 ) {
if ( b2 == null || b1 == null ) {
throw new IllegalArgumentException( ... );
}
if ( !b2.fooable() || !b1.fooable() ) return null;

Foo result = searchForFirst(...);
if ( result != null ) return result;

result = searchForSecond(...);
if ( result != null ) return result;

result = findFinal( ... );

return result;
}

And just to be slightly annoying, I see little wrong with
a one return version.

Foo foo( Bar1 b1, Bar2 b2 ) {
if ( b2 == null || b1 == null ) {
throw new IllegalArgumentException( ... );
}
Foo result = NothingBetterFoo();
if ( b2.fooable() && b1.fooable() ) {
result = searchForFirst(...);
if ( result == null ) {
result = searchForSecond(...);
if ( result == null ) {
result = findFinal( ... );
}
}
}
return result;
}

Of course this one return case is often not
what often happens (despite the theory that it could),
but is the result of my simplified example.

When I say "little wrong", I mean that
if I came across this code I would not
feel compelled to refactor by straigtening it out.
But if a new case came up, the indent depth is
starting to get smelly.

By the way "poor style" does not equal "smelly".
Smelly is a scale, poor style sounds more like
a boolean. Even when to refactor duplication
can be viewed as sliding scale
Duplication Refactoring Threshold see
http://c2.com/cgi/wiki?DuplicationRefactoringThreshold
I've worked with far too much really
crap code that has been produced with such
a prejudice in mind.

Hmm, my exerpiance may be different. The real
crap I've seen usually doing too much in one
routine (or class). I'm not sure I ever saw anyone
try to keep religiously to one and only one return
such that it was the only reason for bad code,
but I could believe such orthodox attitudes
exist.

cheers,
-Paul


-Paul
 
C

Chris Uppal

P.Hill wrote:

[I've snipped most of your post since it seems we've reached something of a
concensus; the rest of tihs is just a few observations]
[...] but other rules might be worth stating like:
lots of simple guard conditions makes for more readable code than
appearances of multiple returns in various places. Where guard
condition is defined as: an as simple as possible conditional that may
result in a return at the highest level of code, less of a surprise and
hence more readbale when they occur near the top of a routine.

Yes, this is where I would want to put the emphasis if I were attempting to
compose rules-of-thumb for clean code. What matters is the amount and
complexity of the conditional code, not whether it contains returns. Something
like:

a) Conditions with code on both branches,
if (..) { ... } else { ... }
are worse than conditions with only one branch.

b) Two-branched conditions that are symmetrical are better than ones that are
not. By "symmetrical" I mean that both the branches do the same thing (but in
different ways) so that one can think of the whole compound statement as doing
just a single (conceptual) operation. E.g.
if (condition) { var = 'green'; status = OK; } else { var = 'red'; status =
ERROR; }
is symmetrical.

c) Conditions with complicated code on the branch,
if (..) { ... something complicated ... }
is less clear than conditional execution of simple code (e.g a return is
simple). This is over and above the inherent inclarity of the '... something
complicated ...'. I.e. the condition multiplies the undesirable effect of the
complexity it guards, it does not merely add to it.

d) Conditions with complicated code on both branches are horrible.

e) Complicated code is "defined" recursively by these "rules", so conditional
code inside conditional code is not good.


Apparently you haven't hung out with old smalltalk developers or XP
refactoring folks heavely influenced by smalltalk style. "smalltalk
style" usually results in really small routines on the order of
a few lines including loop definitions and conditions which don't have
semicolons. I would consider that a weaker version of a one-semi
observation.

<chuckle/> I /am/ an old Smalltalk developer -- at least I've been programming
Smalltalk as my language-of-choice for several years now. And I do indeed
write very short methods in that language -- /much/ shorter than I think is
feasible in Java.

Since (as you may know) Smalltalk uses a '.' as its statement
separator/terminator, one could describe over-long methods as suffering from
period-pains...

And just to be slightly annoying, I see little wrong with
a one return version.

Foo foo( Bar1 b1, Bar2 b2 ) {
if ( b2 == null || b1 == null ) {
throw new IllegalArgumentException( ... );
}
Foo result = NothingBetterFoo();
if ( b2.fooable() && b1.fooable() ) {
result = searchForFirst(...);
if ( result == null ) {
result = searchForSecond(...);
if ( result == null ) {
result = findFinal( ... );
}
}
}
return result;
}
[...]

When I say "little wrong", I mean that
if I came across this code I would not
feel compelled to refactor by straigtening it out.

I probably wouldn't refactor it either -- unless I were making changes
anyway -- but I find that formulation significantly harder to follow than the
version with embedded returns[*]. In fact one reason why I wouldn't
"spontaneously" reformulate it (assuming I was in an environment where such
changes were acceptable at all) is that it would take some thought to be sure
that the cleaner version really did have the same effect as the code it was
replacing.

-- chris

([*] not helped by the use of K&R-style layout)
 
D

Dale King

Scott said:
hi,

void methods cannot return values, however, i noticed that i can still
use "return" without any value to exit a method like this:

public void myMethod(int arg0)
{
if (arg0 == 0) return;
...
}

question: is the above ok or will i get errors with other java versions.
i'm using jre1.4.1_02 in eclipse.

While it is certainly correct I would usually code it as:

public void myMethod(int arg0)
{
if( arg0 != 0 )
{
...
}
}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top