The Register® — Biting the hand that feeds IT

Feeds

Bloody code!

It's amazing how some good practices limp on for decades beyond their expiration date. I still encounter people who insist that a method should have only one point of return - as if we're all still littering our code with GOTOs, and the concept of a "black-box" function was never invented. The way these same people go on about …

This topic is closed for new posts.

Page:

Re "Challenge" by Juha-Matti Myllylä - Correction

I'm sorry, but your code was so badly presented that I missed its program flow! I now see it is....

for ( int x = 0; x < UNIVERSE_X_SIZE; x++ )

for ( int y = 0; y < UNIVERSE_Y_SIZE; y++ )

for ( int z = 0; z < UNIVERSE_Z_SIZE; z++ )

if ( aUniverse->FindObjectAt( aId, x, y, z )

return rlCoordinate( x, y, z );

Well, firstly, you shouldn't be using "for" loops (with specific start and end points) and then knackering up the program flow by breaking out of the loops like this. You should use "while" or "do" loops as appropriate and break out of them cleanly.

My goodness, you really ARE sloppy, aren't you? I bet your workmates love you!!

Anonymous Coward
Anonymous Coward

Of course there is those of use that use the single assignment method

Perhaps I've spent too many years in Smalltalk, Lisp, functional languages, &c. Other than the the return statement itself, I don't like to have if-then-else in my code myself (i.e. "return ( cond ) ? x : y;").

Most of the time I have to use imperative languages, hopefully OO languages like Java, CLOS, Smalltalk, &c. So I'm not a true functional developer.

Anyway, the way I think of it, multiple return statements is a sign of messy thinking. I've used it plenty of times. Sooner or later, you have to shoot the engineers and ship the code.

It will cost more next year, but you start generating returns to keep you alive until next year.

david

Pirate

multiple returns == Coding by Exception

As a reviewer, I'll generally allow an if-else block at the end for returns. Beyond that, I take a very dim view.

Here is why. For any given solution, there are a finite number of rules, and an infinite number of exceptions.

When you start doing extensive data checking, you must consider first whether it's your business to know what information you're handling. If you're a typical Object-Obfucated programmer, you'll have 80%+ of your code checking what it isn't (and what to do). You'll also be sure and include the sanity checks in every class in your 12-layer chain of inheritance.

Now, the constant of gravity changes, or the customer wants another argument in the API. And at that moment, you will be cursed with 3 eternities in maintenance hell for your transgression. Of course, your tester will already have cursed your name to 20 lifetimes on helldesk duty in that case... Of course, the jobu who did it originally has probably spread the love to 10 other places, or writing a book.

This is programming, and not law. Just because there's prior precedent doesn't make it right. Just because you can, doesn't mean you should.

The Tao of programming states if you're going to make bugs, make them obvious. After all, a tarantula is easier to find than a flea, and not nearly as deadly.

Single exit point facilitates classic debugging

I remember that years ago when I was less experienced (and depended more on debugging), single exit points in C and Pascal made life a lot easier.

Imagine you're debugging a long routine, proceeding by alternating between setting breakpoints and running, and you get optimistic and set a breakpoint too far down and when you run, you get bounced out of the routine by one of various possible multiple exit points. This is a major bummer if there is significant setup time for the debug session. I finally started using single exit points whenever possible and then just put a breakpoint at the last line of code in the routine, secure in the knowledge that 1) I would get there, and 2) I would still be able to examine the routine's variables because an extra return hadn't returned to a different scope.

Of course, nonlocal returns like the old C jump and modern exception throwing can be very useful, but I prefer to use them for real exceptions and not normal processing. I usually try to structure my code so that I get to the bottom of a routine by essentially tracing a single path in a Nassi-Schneiderman chart. This means no if's without else's so that empty then or else clauses stick out during code reading. If code inspection turns up an empty clause that really shouldn't be empty, then the method has aided in design completion as well as debugging. The downside is that the nesting corresponding to a Nassi-Schneiderman chart can get deep quickly, but I prefer the structural clarity and we've got scrolling GUIs anyway nowadays.

I have this prejudice because early in my career I noticed that elseless if's often corresponded to a failure to complete a design that implied a real else case. I also never did that much assembler, so early exits and other common assembler usages never made their way into my high-level coding habits.

That's why I'm pretty much in the single-entry-single-exit camp, averse to elseless if's and very tolerant of nesting. I don't mind dealing with other code structures, though, as long as they are consistent and the programmer has accounted for all the cases somehow.

@Rich (re "Challenge" by Juha-Matti Myllylä )

I suspect you have somewhat missed the point in this example. The early return from the function is an optimisation. Once you've determined the result of a function, it is most efficient to exit the function immediately. Why bother continuing the iterations?

If UNIVERSE_[X|Y|Z]_SIZE were say, 20 trillion, and the locations of the target points were uniformly distributed, you'd be spunking a approximately 45 bajillion iterations just to avoid the ignomy of having 2 return points from your function.

This is a perfect example of why early return from a function is sometimes safe and desirable.

Happy

Programming in Assembler

25 years ago I believed in the single point of exit thing. But we were programming in assembler on a 6800 using a very primitive debugger. Trying to find out what value a subroutine was returning required looking on the stack just before the final "return" statement was hit. So setting such a breakpoint was easy if subroutines had but one return statement, and progressively more leg-work as more exit points were added.

Fortunately we're not programming with sticks and stones and 300 baud modems any more, so I've thrown off such shackles and now litter return statements wildly where ever they make sense.

spinlock1977.wordpress.com

Stop

Having recently dealt with

The work product of a recently converted COBOL programmer, I can say with complete confidence, this writer has no clue what they're talking about.

Multiple exit points are debug hell. They are a major source of obscurity. They require substantial knowledge transfer between developers to understand. They make future development more difficult. They make porting between client and service paradigms EXTREMELY difficult.

Single exit point here.

"pro-guard clauses" vs "anti-single exit point"

It's much easier to argue the case for guard clauses than to argue outright against single exit points. It's possible that different domains or designs impose constrains on code structure. But guard clauses are a solidly justified, discrete case/pattern for using multiple exit points.

Thumb Down

Single exit rules!

Comments "Can't agree with you" and "Single exit point facilitates classic debugging" have it spot on!

The only thing I'd add is -- read your MISRA:

Rule 82 (advisory): A function should have a single point of exit.

However, if you're a pie eater and don't care about safe code -- just disregard everything and do whatever you want. It's not worth the effort trying to convince you, you're a lost cause.

This post has been deleted by its author

Anonymous Coward
Thumb Down

crock of s**t

it is better to have only one exit, it doesn't make an difference to execution and any one that thinks it does clearly doesn't understand how code works.

Your CODE is not executed, it is just better for the compiler if you write neat code, so that the optimiser can create efficent bite code.

I've heard it said that exits prevent the rest of the function loading, what a load of rubbish that is. I've not heard any good reason why exiting sooner is better, just a load of lies by people that can't code.

If you can't leave your exit unitill the last line, then you can't code and you can't do boolean logic. Its that simple.

I have not writen a procedure in 20 years with more then one exit.

Its simply true that if your dealing with a million lines of code with exit points all over the place it will be harder to debug. If you code follows a single execution path, its easier to follow, it just a cock of s**t that it makes spaghetti code, the opersit is true. How can a single path be spaghetti, code that exits all over the place is always harder to follow unless you only ever write 10 line procs? In which case it doesn't matter as you can always see the mess any way.

Anonymous Coward
Anonymous Coward

Interview Question

boolean shouldHireThisPerson(Programmer p) {

if ( p.thinksYouMustHaveOnlyOneExitPoint() ) {

return false;

}

else if ( p.thinksYouMustHaveMultipleExitPoints() ) {

return false;

}

else {

// doesn't give a crap

return true;

}

}

</pre>

Anonymous Coward
Anonymous Coward

Avoid control booleans

A good example of how trying to avoid multiple exit points makes code more complicated is the 'avoid control booleans' rule, that is, don't create boolean variables inside the function that control the flow of execution - it's much harder to understand the code. A novice approach to creating only one exit point typically ends up with a control boolean:

static bool Foo ()

{

boolean bDidFoo = false;

if (some condition)

{

do something

bDidFoo = true;

}

return bDidFoo;

}

is obviously harder to read than the multiple exit-point equivalent. But I agree that there's no such thing as a hard-and-fast rule for this, or indeed anything.

Boffin

It's a question of IF

I agree completely with Mark Rendle who I think is agreeing with someone else.

The whole aim is to reduce complexity of a function. The biggest factor in complexity is not the number of exit points - but the structure of the IF statements.

Early bailouts are usually based on simple tests - that's why they are effective and easy to understand.

Complicated if statements should be avoided at all cost. If a single exit point comes at the cost of repetition of IF statements in a function then it instantly becomes harder to read.

When I read code, I stop to evaluate the IF statements exactly, in my mind - when the read normal statements, I subconsciously read them as pseudo-code.

Dead Vulture

I totally agree with you on everything you have said

some of the commentators here need to wise up

Linux

messy code

Surely messy, undocumented code is the issue itself, and how many exit-points/gotos/etc isn't relevant in anyway?

Consistency and readability should be paramount. Coding guidelines should aid developers to work as a team, not force them to produce hideous code when they come up against an odd situation.

Equally, if you've got bad coders working on your team, thats another issue that should be solved at the source, not solved by chaining all your programmers up.

As the old saying goes "Garbage in, Garbage out". You should try to solve the original problem if possible, rather than just applying a quick fix.

This post has been deleted by a moderator

Page:

This topic is closed for new posts.