Goto und Verwandte
-
Hallo,
ich weiß, dass man, wenn die Sprache es anbietet, goto nicht verwenden sollte. Sagt einem ja jeder.
Aber wie sieht es mit anderen "skip"-Befehlen aus? Also Überspringen eines Schleifendurchlaufs (continue, skip), Abbrechen einer Schleife (break), Abbrechen einer Funktion (return) etc.
Mein Informatikleher meint, die wären genauso böse. Ich sehe an ihnen aber nicht viel verwerfliches, außer, wenn man dadurch vergisst Arbeitsspeicher freizugeben oder ähnliches.
Wie ist es nun?
-
Ich sehe nichts "böses" daran.
-
Mein Informatikleher meint, die wären genauso böse.
Hat er dafür auch eine Begründung?
In der strukturierten Programmierung besteht ein Programm aus ineinander geschachtelten Kontrollstrukturen (if/switch/while/for/do-while/Anweisungsblöcke in C). Man kann den Programmablauf mehr oder weniger verstehen, indem man sich diese Verschachtelungen anguckt. goto geht daran völlig vorbei, man kann beliebig aus diesen Strukturen raus und in andere rein springen, so dass man das Programm nicht mehr verstehen kann, ohne jedes einzelne goto nachzuverfolgen. Das nennt sich auch Spaghetti-Code, und das ist das eigentliche Problem an goto. Die anderen Sprunganweisungen halten sich aber an die Kontrollstrukturen. Falls sie böse sein sollten (Ansichtssache, in der streng orthodoxen Lehre dürfen Blöcke nur einen Eingang und einen Ausgang haben), dann jedenfalls nicht "genauso" wie goto, sondern anders.
-
Es gibt schon Gründe, warum man break und continue als "böse" betrachten kann. Kannst mal im Touch of Class - pdf Version auf Seite 196 unter "goto puts on a mask" lesen, warum mein Professor vom letzten Semester break und continue nicht in Eiffel implementiert hat.
Ich finde die Argumente von Meyer (dem Autor) berechtigt. Aus meiner Sicht aber auch etwas zu puristisch gedacht (wie mit so einigem in Eiffel).
-
icarus2 schrieb:
Ich finde die Argumente von Meyer (dem Autor) berechtigt. Aus meiner Sicht aber auch etwas zu puristisch gedacht (wie mit so einigem in Eiffel).
Seh ich auch so. Was nervt ist die teils unsachliche Argumentation. Das, was er am Ende über das Problem mit den Schleifennachbedingungen/-invarianten sagt, ist durchaus nachvollziehbar, aber bis er dahin gekommen ist, hat er schon dreimal die Leier mit "wie goto, also böse" gebracht. Damit verharmlost er goto sogar indirekt.
-
Not for publication
Important: this text is in draft form and is reserved for the use of
students in the ETH Zurich “Introduction to Programming” course
(37-001),Winter semester 2003, as well as for members of the “Touch
of Class” mailing list. Do not copy it other than for personal use, or
distribute it without the author’s permission.
-
Die Rangfolge des Bösen, um den Ablauf in einer Schleife zu verändern:
- Schleifenindex verfummeln
- goto
- künstliche Abbruchvariable
- if um den ganzen Körper
- break
- continue
- return
break ist erstaunlich selten nötig und return kann oft sinnvoll genommen werden. Aber wenn man das noch nicht drauf hat, sind die Tricks, die man anstellt, um break zu vermeiden, wenn break verboten ist, einfach schrecklich. Schritte in Richtung des Bösen.
-
@Zeus: Das ist als ob man einen offenen Koffer voller Geldscheine in eine dunkle Gasse stellt, daneben ein Papierschild anbringt "nichts entnehmen" und sich am nächsten Tag wundert, dass der Koffer leer ist.
MfG SideWinder
-
Wurstinator schrieb:
außer, wenn man dadurch vergisst Arbeitsspeicher freizugeben oder ähnliches.
Das ist der Punkt. Faßt man seine Objekte mit using an oder denkt an finally-Blöcke oder schreibt C++, dann darf man frei returnen. Die meisten alten Sprachen haben sowas nicht. Da sollte man diesbezüglich sehr ängstlich sein und man war es ja auch vor 30 Jahren.
-
SideWinder schrieb:
@Zeus: Das ist als ob man einen offenen Koffer voller Geldscheine in eine dunkle Gasse stellt, daneben ein Papierschild anbringt "nichts entnehmen" und sich am nächsten Tag wundert, dass der Koffer leer ist.
MfG SideWinder
Endlich bin ich reich.
-
@ Bashar: Wie du sagtest, meint er, Blöcke haben nur einen Eingang und Ausgang. Laut ihm wird der Code unübersichtlich, wenn man so "herumspringt".
@ icarus2: Joa, ist ja das, was Bashar auch gesagt hat.
@ volkard: Vielleicht bin ich ja einfach ein schlechter Programmierer, aber in Ruby hab ich break schon ab und zu benutzt. Öfter als continue :p
Was meinst du mit "fasst man seine Objekte mit using an"? Und finally ist doch für Exceptions, wenn ich mich recht erinnere?
-
@ icarus2: Joa, ist ja das, was Bashar auch gesagt hat.
[/quote]
Das meiste schon. Aber du hast offenbar das "Loop postcondition principle" überlesen oder nicht verstanden was damit gemeint ist. Ich finde das ein gutes Argument.*Edit
Wurstinator schrieb:
Und finally ist doch für Exceptions, wenn ich mich recht erinnere?
Finally ist einfach ein Codestück, das immer ausgeführt wird nach Verlassen des umschliessenden Blocks (des scopes oder wie man das auch immer formulieren will). Finally wird also immer ausgeführt, egal wie der Block verlassen wird. Ist nützlich für Aufräumarbeiten und um Garantien geben zu können, dass etwas ausgeführt wird, bevor ein Block (z.B. eine Funktion) verlassen wird. In C++ gibt es bekanntlich kein finally. Da löst man es über RAII.
-
Wurstinator schrieb:
@ Bashar: Wie du sagtest, meint er, Blöcke haben nur einen Eingang und Ausgang. Laut ihm wird der Code unübersichtlich, wenn man so "herumspringt".
Ja, das ist die alte Schule. Wo es die ganzen tollen Features die wir heute haben noch nicht gab. Damals hat das Sinn gemacht. Single Entry/Single Exit.
Heute ist das halt komplett ueberholt.
Vielleicht bin ich ja einfach ein schlechter Programmierer, aber in Ruby hab ich break schon ab und zu benutzt. Öfter als continue :p
Ich wuerde darauf tippen das deine Funktionen generell laenger als 10 Zeilen sind. Stimmt das?
-
Naja, vor allem in C ist goto für CleanUp Code doch durchaus schön anwendbar.
Verstehe den Rummel darum nicht, wenn mans nicht missbraucht ist es ein akzeptables Sprachfeature.
-
@Ethon:
Genau. In C finde ich es schon fast plem strikt aufgoto
zu verzichten.In den letzten Jahren hab ich in C++ aber kein
goto
mehr geschrieben. Bin nichtmal wirklich in Versuchung gekommen. OK, vielleicht ein paar wenige Stellen wo ich aus ner verschachtelten Schleife raus wollte, aber die liessen sich alle leicht aufreturn
umstellen, ohne dadurch unübersichtlicher zu werden.
-
Ist wohl mal wieder eine sehr emotional geprägte Fragestellung!
Die ersten BASIC-Interpreter kannten als Kontrollstruktur nur goto. In FORTRAN war continue absolutes Muss. Die WinApi-Programmierung mit C erfordert den Einsatz von break bei switch.
Sei beruhigt trotz anderer Meinungen. Selbst das zurecht verpönte goto kann noch seine Berechtigung haben. Ich selbst steige aus komplizierten Iterationen auch schon einmal mit goto ans Funktionsende aus, weil es übersichtlich ist. Funktionen sind bei mir meist klar definierte Blöcke mit Eingabe-Verarbeitung-Ausgabe (EVA).
-
berniebutt schrieb:
Die WinApi-Programmierung mit C erfordert den Einsatz von break bei switch.
Man muss auf Windows break und switch verwenden? Wie will das OS das denn überprüfen?
-
@ icarus2: Okay, ich habs beim ersten Lesen mehr überflogen. Jetzt hab ichs verstanden
@ Shade of Mine: Nicht generell. Aber ich stelle mich absichtlich gegen Regeln, die besagen, dass Funktionen nur so und so lang sein dürfen. Für mich hört eine Funktion dann auf, wenn es Sinn macht
Danke für all die Antworten
-
berniebutt schrieb:
Funktionen sind bei mir meist klar definierte Blöcke mit Eingabe-Verarbeitung-Ausgabe (EVA).
Haha. Auch ein Paradigma, das vor 20 Jahren schon 20 Jahre alt war.
Eine Stilsünde zieht die andere nach sich.
-
volkard schrieb:
berniebutt schrieb:
Funktionen sind bei mir meist klar definierte Blöcke mit Eingabe-Verarbeitung-Ausgabe (EVA).
Haha. Auch ein Paradigma, das vor 20 Jahren schon 20 Jahre alt war.
Eine Stilsünde zieht die andere nach sich.Gibts Funktionen ohne EVA? Was machen die? Wobei ich A jetzt als return oder Hardwareausgabe sehe.