Re: small java exercise
Stefan Ram wrote:
Patricia Shanahan <pats@acm.org> writes:
In this case, I am not so much giving advice as asking for
insight. Are there advantages in Java to pushing for single
exit that outweigh the cost of making the code more
complicated, for example by requiring a "retVal"? If so, what
are they?
The usual benefits of ?structured programming?.
- With a single exit at the end, if I would want to add a
call to be done once before the method exits, I would add
it in front of this exit point. Otherwise, one would need
to find all exit points and add this call in front of
each one.
My question is specific to Java, so I could wrap the multi-exit code in
a try-finally and do the call in the finally block. This used to be one
of the most convincing arguments, but I'm not sure it still applies.
- A kind of ?referential transparency? of blocks. By this
(ignoring parameters and return values for simplicity),
a methode declaration
m(){ ... { ... } ... }
can always be refactored to
m1(){ ... } // = the ?{ ... }? block from above
m(){ ... m1(); ... }
Thus, a block can always be replaced by a call to this
block after it has been given a name by a method
declaration.
Not always, in Java, given the lack of call-by-reference:
m(){int x=0; int y = 0; ... { ... x = 5; y = 20; ... } ... }
cannot be refactored as above without changing the handling of x and y.
Passing them as parameters does not get the changed values back to the
surrounding block.
And one of the standard techniques for obtaining a single exit function
involves using an extra outer block variable, modified at each logical
exit point, to represent the return value.
This is not possible anymore, when this block contains
an exit (?return?).
- Improved readability. In
{ ...
{ ... }
f();
... }
I know that ?f();? will be executed whenever the whole
block is executed if the block is written according to
structured programming rules. I do not have to analyze the
inner block to make this assertion. When jump-statements,
like ?return;? are allowed, one can not make such
assertions with the same ease.
I'm not convinced the single exit rule does always aid readability. In
some cases, for example, I think getting one or two special cases
completely out of the way before starting the main work leads to more
readable code. It makes it easier to be sure that nothing else in the
method needs to handle the special cases, and that the special case
decision will not be overridden later on.
This is especially the case for recursive methods.
int factorial(int n){
if(n < 0){
throw something;
}
if(n == 0){
return 1;
}
return n * factorial(n-1);
}
int factorial(int n){
int fact;
if(n < 0){
throw something;
}
if(n == 0){
fact = 1;
}else{
fact = n * factorial(n-1);
}
return fact;
}
I think the multi-exit version makes it easier to identify the base case
and be sure its handling is non-recursive.
Note that I am not denying the existence of many methods for which the
single exit version will be the most readable version, and should be
used. I just feel that there are cases in which multiple exit is clearer
than single exit, and that multiple exit should be used in those cases.
Possibly the difference is whether it is more important to be sure some
code is always executed, or to be sure some code is not executed in
particular cases.
Patricia