Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

This question already has an answer here:

A co-worker and myself are having a debate on whats best. Both concepts work and work well but is there a general consensus on not making a call to exit?

Whats better?

To call exit within a procedure to avoid doing the rest of the code as in ...

if Staging.Current = nil then exit  

DoSomethingA(FileNameA);  
DoSomethingB(FileNameB);  
Staging.DeleteCurrent;

or to not call exit and instead wrap it in a begin and end

if Staging.Current <> nil then  
begin   
  DoSomethingA(FileNameA);  
  DoSomethingB(FileNameB);  
  Staging.DeleteCurrent;   
end;

Both work. I prefer to use the exit statement since it results in fewer lines of code and looks cleaner to me, but is there any reason or any consensus among programmers to avoid using exit to leave a procedure?

share|improve this question

marked as duplicate by gnat, thorsten müller, MichaelT, Bart van Ingen Schenau, Jalayn Apr 10 '13 at 16:57

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

9  
There will never be a consensus among programmers as long as you ask enough of them. –  Uwe Raabe May 19 '11 at 16:20
1  
@uwe Consensus is often taken to mean a majority. So there's no reason why a consensus could not be reached. –  David Heffernan May 20 '11 at 8:22
    
"There will never be a consensus" .... sorry, but I have to disagree. ;) –  HMcG Mar 5 '13 at 11:05

10 Answers 10

up vote 28 down vote accepted

This is a religious war type of question. For reference the definitive Stack Overflow discussion is here: Should a function have only one return statement?

Many people object to methods that have multiple exit points. They would argue that it makes it harder to reason about a method's behaviour.

On the other hand, others take the point of view that once a method has completed its work it is reasonable for it to quit. Those holding this viewpoint would argue that a C return statement, e.g. return 42 is clear and reasonable anywhere in a function.

I personally feel that there is a clear distinction between code that exits willy nilly from many different points, and code as presented in your question which is known as a guard clause.

One of the great advantages of guard clauses is when you have multiple tests. The code written without guard clauses results in significant indentation which most people agree is to be considered harmful.

It is my perception that the consensus opinion is that guard clauses are better than any alternative.

share|improve this answer
8  
That's the right answer: It really depends on your desires. It's fine if you think it's fine. Me? I like the "Check stuff, and if there's no reason to go on, bail out. Then get on with it" method. But if you are a "one and only one exit point" kind of guy, then don't use Exit. –  Nick Hodges May 19 '11 at 14:35
6  
@stijn your understanding is incorrect it does not raise an exception. If it did it would propagate up the exception handler chain in the call stack. –  David Heffernan May 19 '11 at 17:06
1  
Exactly, the EAbort exception is raised by the procedure Abort found in sysutils.pas - you might have mixed up those. –  Uwe Raabe May 19 '11 at 17:39
1  
I totally agree with the answer. Testing entry conditions can increase readability, what i never would do is using exits on different levels (indentation). This can make reading the code really hard. Of course one can argue, that a function with many levels should be shortened anyway, but i'm sure you have come across of such functions nonetheless... –  martinstoeckli May 19 '11 at 19:57
1  
@stijn: You need to do more research. :) Exit does not raise EAbort. It's no different than return; in C/C++ - in fact, recent versions of Delphi support Exit(ReturnValue); just like C/C++ supports return ReturnValue;. –  Ken White May 19 '11 at 22:18

The only reason (besides your own preferences) for not using exit are programming guidelines. If no such guideline exists feel free to use whatever fits your needs or makes your code look cleaner.

Edit: More recent versions of Delphi allow a call to Exit with a parameter which becomes the result of the function (if it is a function at all). This might lead to some leaner and (subjective view) cleaner code in some cases.

Example:

function IndexOfString(const Value: string; const StringArray: array of string): Integer;
begin
  for I:=Low(StringArray) to High(StringArray) do 
    if Value = StringArray[I] then 
      Exit(I);
  result := -1;
end;

Another approach for this would be:

function IndexOfString(const Value: string; const StringArray: array of string): Integer;
begin
  result := -1;
  for I:=Low(StringArray) to High(StringArray) do 
    if Value = StringArray[I] then begin
      result := I;
      Break;
    end;
end;

Whatever is the better one is more or less a matter of taste.

share|improve this answer
1  
I think this is an over-simplified view of the issue. You can't really mean that programming guidelines would be the only reason to avoid using exit. –  David Heffernan May 19 '11 at 14:46
1  
You are right. What I meant to say was: If you think you, as an experienced programmer, decide to use exit in some case, there can only be some external rules to prohibit you from that. I didn't want to open a door for an overall use of exit in every case. The question was "is there any reason not to use exit" - I understood that as "... to use exit at all". –  Uwe Raabe May 19 '11 at 16:07

Subjective question. I often use Exit in a sense to check for some initial conditions and exit early if they are not met. My functions often look like this:

begin
  Result := ''; // default return value
  if (<input does not meet conditions>) then
    Exit;

  // continue to do something and return something useful
end;

This makes it a bit more readable for me. But I try not to use Exit from various places in the same function.

share|improve this answer

Personally, I do no think there is any need to avoid the use of exit. It's useful in functions like:

function IsDivideable(const A, B: Integer): Boolean;
begin
  Result := False;

  if (B = 0) then
     exit;

  Result := ((A mod B) = 0);
end;
share|improve this answer
1  
Why would you set Result := False outside the if statement? That appears wasteful and imprecise. –  David Heffernan May 19 '11 at 14:32
    
@David -- to avoid the warning that results. –  Nick Hodges May 19 '11 at 14:34
    
@Nick What warning? When moved inside the if, the compiler can determine that Result is always assigned to. –  David Heffernan May 19 '11 at 14:34
    
@David: Maybe he's on a version before D2009 and can't say Exit(false) yet. –  Mason Wheeler May 19 '11 at 14:57
3  
I use that construct, when the logic of the function is "prove it to me". That is, you start out False, and you have to "prove" your true-ness. –  Nick Hodges May 20 '11 at 3:51

An early exit like this is called a "guard clause". It is not unique to Delphi. Increasingly, it is considered to be good practice.

Advantages:

  • Less lines of code.
  • If is +ve, making it easier to understand.
  • Less nesting = easier to understand.

Disadvantages:

  • If your method allocates resources, it is easy to forget to release them if you don't have a single exit point. For this reason, this style of programming may be more suited to managed languages like C#, but can be used with Delphi as long as you're aware of the issue.

I'm not convinced by arguments that a method should have a single exit point. It has been suggested to me that an early return is just another kind of GOTO. However, the problem with GOTO is that it can take you anywhere, leading to the most horrible mess when it is misused. On the other hand, an early exit from a method always returns you to the caller. What could be neater than that?

share|improve this answer
1  
To the disadvantages I would add that if exit is used as anything but "early exit guard clause"'s, multiple exit points increase complexity and make it less obvious under what conditions code further down a method is executed, because to it may look unconditional as it is not indented... –  Marjan Venema May 19 '11 at 17:34
    
Exit actually raises an EAbort exception, so if you use try/finally correctly, any resources used should get freed appropriately. –  Stijn Sanders May 19 '11 at 19:20
2  
@Stijn: See earlier answers: Exit does not raise EAbort or any other type of exception. You are however correct in that Exit will take you to any surrounding finally blocks, so yes, resource deallocation should not be a problem despite Exit. –  Oliver Giesen May 25 '11 at 7:51

Sometimes Exit might "break" method readability. Kind of like goto would (only "less bad"). I myself prefer conditional blocks, which make very clear the scope of each chunk of code.

share|improve this answer
    
As might be visible after my question edit :) –  daemon_x May 19 '11 at 14:29

I try to not use Exits in code. If you like the code provided, then I'd prefer changing it to be more positive thinking as it typically flows better:

  if Assigned(Staging.Current) then  
  begin   
    DoSomethingA(FileNameA);  
    DoSomethingB(FileNameB);  
    Staging.DeleteCurrent; 
  end;

There's always more than one way of doing something - the deciding factor really is what implementation is the easiest for you and your team to maintain. This is typically defined by writing easier to read and understand code. Burying an exit in the middle of a procedure is generally a bad implementation, on the flip side having a simple one-liner guard code up front would likely fall into the easy to read/understand side for most.

share|improve this answer

I would agree with other posters that Exit in my view reduces readability. However if you are going to use it (and in certain circumstances it does improve readability) formatting is very important. I would change your above to

if Staging.Current = nil then exit

DoSomethingA(FileNameA);
DoSomethingB(FileNameB);
Staging.DeleteCurrent;

The extra line between if and the rest of the statements is important.

share|improve this answer

I'm using Exit when I have a complex condition in the method, and after a while the specs change and you must add some new conditions to code, and it would cost time to rearrange all the conditions. Depends from situation to situation.

But, if the logic is simple, the I prefer to check the stuff and finish the method if everything is ok.

LE: another discussion on this Code Style - Do you prefer to return from a function early or just use an IF statement?

share|improve this answer

I would not consider it as good or bad. Like all answers are showing, it might be hardly depending on the case.

Personally I like the simple "guard condition" with no return value, but I would want to use it in complex functional structure or with class return values.

Maybe some best practices could be extracted from the answers above, and could lead to a simple checklist, when its safe and useful to use "Exit", and also when to better avoid it.

share|improve this answer

Not the answer you're looking for? Browse other questions tagged or ask your own question.