Discussion about only having one exit point in a function?

Member
Posts: 257
Joined: 2004.06
Post: #1
Did someone post something about it better to have only one exit point in a function, such that even using "goto" was a good idea? I remember reading something about that here but I can't for the life of me find it now, even by searching the forum.

The brains and fingers behind Malarkey Software (plus caretaker of the world's two brattiest felines).
Quote this message in a reply
Luminary
Posts: 5,143
Joined: 2002.04
Post: #2
I hope not, 'cos it ain't Smile
Quote this message in a reply
Member
Posts: 92
Joined: 2002.04
Post: #3
One entry point and one exit point is good object oriented programming.

Using goto is even frowned upon in cobal programming which used to use it a lot.

Justin "LordFire" Baldock
Quote this message in a reply
Moderator
Posts: 522
Joined: 2002.04
Post: #4
This code from the default Carbon project template is pretty clean, though, and uses gotos:

PHP Code:
int main(int argccharargv[])
{
    
IBNibRef         nibRef;
    
WindowRef         window;
    
    
OSStatus        err;

    
// Create a Nib reference passing the name of the nib file (without the .nib extension)
    // CreateNibReference only searches into the application bundle.
    
err CreateNibReference(CFSTR("main"), &nibRef);
    
require_noerrerrCantGetNibRef );
    
    
// Once the nib reference is created, set the menu bar. "MainMenu" is the name of the menu bar
    // object. This name is set in InterfaceBuilder when the nib is created.
    
err SetMenuBarFromNib(nibRefCFSTR("MenuBar"));
    
require_noerrerrCantSetMenuBar );
    
    
// Then create a window. "MainWindow" is the name of the window object. This name is set in 
    // InterfaceBuilder when the nib is created.
    
err CreateWindowFromNib(nibRefCFSTR("MainWindow"), &window);
    
require_noerrerrCantCreateWindow );

    
// We don't need the nib reference anymore.
    
DisposeNibReference(nibRef);
    
    
// The window was created hidden so show it.
    
ShowWindowwindow );
    
    
// Call the event loop
    
RunApplicationEventLoop();

CantCreateWindow:
CantSetMenuBar:
CantGetNibRef:
    return 
err;



It looks like voodoo until you check out the macros:
PHP Code:
*/
#if DEBUG_ASSERT_PRODUCTION_CODE
   #define require_noerr(errorCode, exceptionLabel)                           \
      
do                                                                      \
      {                                                                       \
          if ( 
!= (errorCode) )                                             \
          {                                                                   \
              goto 
exceptionLabel;                                            \
          }                                                                   \
      } while ( 
)
#else
   #define require_noerr(errorCode, exceptionLabel)                           \
      
do                                                                      \
      {                                                                       \
          
int evalOnceErrorCode = (errorCode);                                \
          if ( 
!= evalOnceErrorCode )                                       \
          {                                                                   \
              
DEBUG_ASSERT_MESSAGE(                                           \
                  
DEBUG_ASSERT_COMPONENT_NAME_STRING,                         \
                  
#errorCode " == 0 ",                                        \
                  #exceptionLabel,                                            \
                  
0,                                                          \
                  
__FILE__,                                                   \
                  
__LINE__,                                                   \
                  
evalOnceErrorCode);                                         \
              goto 
exceptionLabel;                                            \
          }                                                                   \
      } while ( 
)
#endif 


Not too shabby I think.

-Jon
Quote this message in a reply
Moderator
Posts: 771
Joined: 2003.04
Post: #5
goto's are evil, and return statements at various places in a function could be considered "special goto's". I use them all the time and they never caused any problems (the returns, not the goto's - I've never used a goto in my life. OK, I have, but it was assembler Wink )

BTW, it doesn't have anything to do with OOP, it is a basic structured programming rule.
Quote this message in a reply
Moderator
Posts: 771
Joined: 2003.04
Post: #6
aarku Wrote:This code from the default Carbon project template is pretty clean, though, and uses gotos:

PHP Code:
code 


Not too shabby I think.

-Jon

I'd rather put returns all over the place Wink
Seriously, goto's and macros? Wacko Crazy Apple programmers!
Quote this message in a reply
Moderator
Posts: 592
Joined: 2002.12
Post: #7
The reason for having just a single return is that it is easier to follow the flow of the code.

It also helps to prevent unexpected results if the code drops out at the wrong place if there is exception handling in place.

Both of these points have a greater impact if you are not the only developer working on the code.
Quote this message in a reply
Moderator
Posts: 384
Joined: 2002.08
Post: #8
I discussed this with a coding architect at the company I worked at this summer. I had always been of the idea "one exit point, that's it." The architect, who has been coding (very well, might I add) for probably as long as I've been alive, said the driving reason for one exit point was debugging - it would be easy to see the problem even if the debugger could only spit out the program state at the end of a procedure/function call.

Since most debuggers nowadays can easily step through code and are very advanced, the exit point can easily be traced. So not so bad to do, at least in that architect's opinion. I still use a single exit point myself, overall.

KB Productions, Car Care for iPhone/iPod Touch
@karlbecker_com
All too often, art is simply the loss of practicality.
Quote this message in a reply
Member
Posts: 114
Joined: 2005.03
Post: #9
What would be a good alternative to goto and multiple exit points (especially the latter)? To me, it looks like you could use only complicated if-structures, and this can make things a lot harder to understand in various situations.
Quote this message in a reply
Member
Posts: 198
Joined: 2005.01
Post: #10
From discussions in my OS class a few years back, the main motivation for single exit now is threads. Lot harder to deal with stuff like locking if your function can bail randomly in the middle.

'Course exceptions can make that happen anyway, which is one nice thing about RAII...

One of my co-workers says (and I've just about come around to his perspective) that the gotos-as-error-handling is just laziness. It's a sign you should be breaking it up into more functions.

Cryptic Allusion Games / Cryptic Allusion, LLC
http://www.cagames.com/
Quote this message in a reply
Member
Posts: 131
Joined: 2004.10
Post: #11
A bit off topic...

One question with the Apple code. Is there any reason for wrapping the code in a do {...} while(0); loop when all that really is needed is just creating a scope and ending it a la {...}?

Just curious.
Quote this message in a reply
Sage
Posts: 1,482
Joined: 2002.09
Post: #12
Because it's a macro. If you want to create variables or other nonsense you need it to be in a block.
Quote this message in a reply
Member
Posts: 131
Joined: 2004.10
Post: #13
Skorche Wrote:Because it's a macro. If you want to create variables or other nonsense you need it to be in a block.
Maybe I wasn't clear...

Apple's code.
Code:
#define require_noerr(errorCode, exceptionLabel) \
   do { \
      if (0 != (errorCode)) { \
         goto exceptionLabel; \
      } \
   } while(0)
What I'm asking.
Code:
#define require_noerr(errorCode, exceptionLabel) \
   { \
      if (0 != (errorCode)) { \
         goto exceptionLabel; \
      } \
   }
Why have the do and while(0) when you can do without? I suspect the compiler will optimize it out anyway but maybe not.
Quote this message in a reply
Luminary
Posts: 5,143
Joined: 2002.04
Post: #14
I think that some older compilers don't accept random blocks in the middle of nowhere, and the do { ... } while (0); mentality has stuck. It could also be so that the semicolon at the end of the statement is necessary, rather than being an empty statement.
Quote this message in a reply
DoG
Moderator
Posts: 869
Joined: 2003.01
Post: #15
I don't really see multiple exit points as bad in simple and math functions. Of course, if you instantiate and rip apart a lot of state info in your function, its not so neat. But then your function is bloated and you should refactor anyway.
Quote this message in a reply
Post Reply 

Possibly Related Threads...
Thread: Author Replies: Views: Last Post
  Proper Way to Exit an NSThread AnotherJake 3 6,259 Jun 6, 2006 11:14 PM
Last Post: AnotherJake
  "Command /.../jam failed with exit code 1"- huh? Joseph Duchesne 2 5,767 Mar 29, 2006 09:32 AM
Last Post: socksy