Redundant return()

I

Ian Collins

The relevant issue isn't speed, but ease of comprehension. Supporters of
"single exit" claim it's easier to comprehend; my personal experience is
that early-return is easier.

Especially when you see some of the goto spaghetti some single exit
functions end up using!
 
K

Kaz Kylheku

Testing. A large, complex, function is hard to test. More less complex
functions are easier to test. That's why code written test first won't
contain large, complex, functions.

Sure it will. Start with a small well-tested function, and grow it, carefully
testing every increment. You end up with a big function that is supported
by a large number of tests.
 
I

Ian Collins

Sure it will. Start with a small well-tested function, and grow it, carefully
testing every increment. You end up with a big function that is supported
by a large number of tests.

That only happens if you don't refactor as you go. Even if it is well
tested, a big function is still a fragile thing.
 
L

Lanarcam

Le 15/05/2012 22:18, Ian Collins a écrit :
That only happens if you don't refactor as you go. Even if it is well
tested, a big function is still a fragile thing.
IMO, a function, for reasons of maintenance, must be short,
two pages max, and easily understandable. Large chunks of code
should be replaced with calls to functions with meaningful names
and few parameters. It should be easy to understand it at the
first reading without being lost in obscure details and forgetting
the logic of the whole.
 
I

Ian Collins

Le 15/05/2012 22:18, Ian Collins a écrit :
IMO, a function, for reasons of maintenance, must be short,
two pages max, and easily understandable. Large chunks of code
should be replaced with calls to functions with meaningful names
and few parameters. It should be easy to understand it at the
first reading without being lost in obscure details and forgetting
the logic of the whole.

Two *pages*? blimey.
 
B

BartC

James Kuyper said:
On 05/15/2012 03:51 AM, Stefan Ram wrote:


Any decent modern compiler should generate the same code either way, so
if it does run noticeably faster using one approach, then you should get
a better compiler.

The relevant issue isn't speed, but ease of comprehension. Supporters of
"single exit" claim it's easier to comprehend; my personal experience is
that early-return is easier.

Yes. Easier in that there is then a choice.

I can't see the problem with multiple returns. No matter how many returns
there are in one function, the next statement executed will always be the
one falling the original call. That's not much different from 'single exit'.
 
B

BartC

Ian Collins said:
Testing. A large, complex, function is hard to test. More less complex
functions are easier to test.

I don't see that. You're testing inputs and outputs. A function which is
'complex' in the amount of logic it contains, can still have simple
requirements and be straightforward to test.

But one which is arbitrarily broken up into pieces, now needs to have a
meaningful set of specifications drawn up for each part.
That's why code written test first won't contain large, complex,
functions.

That's right; you build a framework of one hundred functions, all initially
empty (or with some stub). They each do ten different things depending on
some parameter. Each of those things is straightforward by itself, but can
be added one by one, function by function. In the end you have 5000
different things split amongst 100 functions.

Your way, there would be 5000 2-line functions. Plus 100 dispatcher
functions. And most of the relationships amongst each group of ten, has
disappeared.
 
I

Ian Collins

I don't see that. You're testing inputs and outputs. A function which is
'complex' in the amount of logic it contains, can still have simple
requirements and be straightforward to test.

But if you change something and break the function, a swag of tests will
fail and you then have to work out why (or back out the edit).
But one which is arbitrarily broken up into pieces, now needs to have a
meaningful set of specifications drawn up for each part.

Who mentioned arbitrarily? The tests *are* the specification.
That's right; you build a framework of one hundred functions, all initially
empty (or with some stub).
No.

They each do ten different things depending on
some parameter. Each of those things is straightforward by itself, but can
be added one by one, function by function. In the end you have 5000
different things split amongst 100 functions.
No.

Your way, there would be 5000 2-line functions. Plus 100 dispatcher
functions.
No.

And most of the relationships amongst each group of ten, has
disappeared.

My typical function size is 10-20 lines.
 
I

Ian Collins

Yes. Easier in that there is then a choice.

I can't see the problem with multiple returns. No matter how many returns
there are in one function, the next statement executed will always be the
one falling the original call. That's not much different from 'single exit'.

Clean-up is always the elephant in the room with multiple returns in C.
Hence the proliferation of goto spaghetti. I for one prefer early
return on precondition tests, but once a function allocates a resource
or changes a state, there should only be one.

Multiple returns are more common (and banning them unnecessary) in
languages that have support for automatic clean-up.

All safety (as in user) focused C coding standards I have seen specify a
single return.
 
J

James Kuyper

Clean-up is always the elephant in the room with multiple returns in C.
Hence the proliferation of goto spaghetti. I for one prefer early
return on precondition tests, but once a function allocates a resource
or changes a state, there should only be one.

I'm in perfect agreement here. If I allocate memory, I normally use the
following structure where possible (there's obviously situations in
which it's NOT possible):

retval = SUCCESS;

p = malloc(count * sizeof *p);
if (p == NULL)
{
// error handling
return ERROR1;
}
else
{
// Normal processing. 'return' prohibited in this block.

if(error condition)
{
// other error handling
retval = ERROR2;
}

free(p);
}

return retval;


I handle fopen() and fclose() similarly, and any other similar book-end
functions (the libraries I use have quite a few book-end pairs).

This approach doesn't scale well when many different resources need to
be managed simultaneously, in which case more complicated approaches are
needed.
 
B

BartC

Ian Collins said:
On 05/16/12 09:59 AM, BartC wrote:

No.

Well, you're right in that you end up with 1000 things not 5000...
My typical function size is 10-20 lines.

My average is around 40 (except for projects where large numbers of small
functions are used deliberately, but are managed semi-automatically, usually
involving tables of function pointers).

That average fits in well with the size of my editor window, around 60
lines.
 
G

Guest

[...] Supporters of
"single exit" claim it's easier to comprehend; my personal experience is
that early-return is easier.

yes but to a certain degree this is a matter of taste.
Clean-up is always the elephant in the room with multiple returns in C.
yes.

Hence the proliferation of goto spaghetti. I for one prefer early
return on precondition tests, but once a function allocates a resource
or changes a state, there should only be one.

yes. Sounds pretty sensible
Multiple returns are more common (and banning them unnecessary) in
languages that have support for automatic clean-up.

yes. With C++ you return or throw whenever you like- if you've RAIIed
 

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,774
Messages
2,569,596
Members
45,143
Latest member
SterlingLa
Top