juan_gandhi: (Default)
Juan-Carlos Gandhi ([personal profile] juan_gandhi) wrote2010-03-07 08:07 pm

the brief history of single exit

Many many years ago people were writing their code mostly in Fortran, but also in PL/I. They were told by their teachers not to use too many functions or subroutines, because each call and return is very expensive, compared to plain goto statement.

So the brave programmers managed to write functions or subroutines several thousand lines long; these people were considered smart and very important, compared to the junior kind who only could write a hundred or two lines in one function or subroutine.

Then something bad started happening: the code did not work. Or it did work until you start changing it. As a result, two pрilosophies were born:
1. Do not change anything;
2. Write structured code.

Structured programming consisted of using functions of reasonable sizes with reasonable structures. No jumps into the middle of a loop, no jumps out of looзs into another loop or into a conditional statement; no exits out of the middle of your subroutine.

Then, later, it was discovered that it is just goto statement that should be blamed. So people started setting limitations, depending on their taste and creativity.

- do not goto inside another subroutine;
- do not goto ito a loop or a condition;
- do not goto upstream.

The idea of totally abandoning goto was considered too extremist: how else can we make sure that we have only one exit out of a subroutine or a function?

Well then, why do we need just one exit? There were two reasons:
- it was really hard to set breakpoints on all the exits scattered over half a thousand lines;
- how about releasing resources, like closing files, etc?

So it was decided, more or less unanimously, that we have to a) maintain some kind of "response" or "result" code, and b) goto the bottom of our subroutine and exit from there, using the "result code" to decide whether we should do something to close up our activity.

Since later goto was more and more discouraged (although you can find a goto in Java libraries source code), the kosher solution was suggested that was keeping some kind of integer shitLevel flag; everywhere in your code you are supposed to check the level, and if it is close to the fan, you should proceed without doing anything.

This ideology penetrated into Pascal, C, C++, and, later, Java. And only later people started thinking about structuring their code better.

Like making it smaller.

Besides, some languages have finally block that can be used to neatly close all the streams that may remain open.

These two changes, much smaller code and finally block make "single exit" ideology meaningless. Why does one need a specific variable to pass around if we can just return it? If the whole method is half a screen, is it really hard to find other exit points? Is not it safer to use finally that will release your resources in any case, as opposed to that bottom of the method that may never be reached. Just look at this:
   public final static void doit() {
        try {
            throw new NullPointerException("npe");
        } finally {
            System.out.println("Finally!");
        }
    }

Here is basically the same argument, specifically for Java.

[identity profile] itman.livejournal.com 2010-03-08 04:26 am (UTC)(link)
Well, throwing an exception is in many cases an equivalent of a goto statement outside the block.

[identity profile] ivan-gandhi.livejournal.com 2010-03-08 04:32 am (UTC)(link)
No way. When you throw, you do not know who catches it.

[identity profile] itman.livejournal.com 2010-03-08 05:11 am (UTC)(link)
This is the difference, but still there is some resemblance.

[identity profile] spamsink.livejournal.com 2010-03-08 10:21 am (UTC)(link)
Remember INTERCAL's "come from"?

[identity profile] aruslan.livejournal.com 2010-03-08 04:52 am (UTC)(link)
Assuming you are talking about a dynamic non-local goto ("safe longjmp") - yes.
However, dynamic non-local goto is essentially a continuation, so OP's point is valid.

The usual local goto with the statically known set of valid jump targets is NOT equivalent to throwing an exception.
Speicifically, because the jump target (catch) is unknown == undecidable.

[identity profile] itman.livejournal.com 2010-03-08 05:12 am (UTC)(link)
Ok, it is not equivalent, but is somewhat similar.

[identity profile] aruslan.livejournal.com 2010-03-08 05:32 am (UTC)(link)
Sure it's similar: all continuations are trivially similar.
However, to enforce "one exit" rule you'd have to catch all exceptions and somehow rethrow them.

Letter of the "law" is satisfied at the expense of its spirit.
This is so sadly frequent consequence of any mechanical approach.

[identity profile] aruslan.livejournal.com 2010-03-08 05:41 am (UTC)(link)
If a language has expressive means of deconstruction and composition - you don't need "the rule", as it would be naturally enforced by readability.

If it's not expressive enough, you don't need the rule as it wouldn't be honored anyway: readability matters.

the brief history of single exit

[identity profile] yatur.livejournal.com 2010-03-08 06:51 pm (UTC)(link)
TIt is quite simple really. As circumstances change, so do our principles and practices. The computers used to be slow and expensive, and people tended to write complex but efficient code. Today computers are fast and cheap (compared to programmers), so simplicity is more important than efficiency 99,9% of the time.

Simplicity means shorter methods -> single exit is no longer really important. In a 15 line method it does not really matter.

[identity profile] vaggie.livejournal.com 2010-03-08 10:51 pm (UTC)(link)
ну наконец то! а то терзало меня смутное чувство..

[identity profile] sab123.livejournal.com 2010-03-09 10:18 pm (UTC)(link)
Java needs destructors that are called on block exit, like in C++. They don't have to actually destroy the object, just free any expensive resources and put in into a dormant state. Closing everything manually is a pain.

[identity profile] andreyoid.livejournal.com 2010-03-10 12:03 pm (UTC)(link)
For sure. Those infinit try-finally, the requirements to declare variables before try, set them to null are crazy! You may also look through my record about mobile java. There are even more surprises.

[identity profile] andreyoid.livejournal.com 2010-03-10 12:12 pm (UTC)(link)
I want to comment the ideology of single return point.

It is actually meaningless in Java and in C++.

And I think that is wrong to say that the function
may contain hundred of strings.
Actually, it needs refactoring.
I think in manner of Martin Fowler-
want comment? make a function!

My main point against single return is that
people begin to write the code with a lot if-else,
if-else, if-else.

It is simpler to write
if(wrongArgument) { throw ... }
if(dontWork) { return .. }
if(alreadyDone) { return .. }
I.e. return as earlier as possible.

The exceptions are also a kind of return...
So the ideology of single return implicitly disables
the use of exceptions.