Sind "while (true)" - Schleifen so schlecht? [geschlossen]

218

Ich programmiere seit einigen Jahren in Java, bin aber erst kürzlich zur Schule zurückgekehrt, um einen formalen Abschluss zu machen. Ich war ziemlich überrascht zu erfahren, dass ich bei meiner letzten Aufgabe Punkte verloren habe, weil ich eine Schleife wie die folgende verwendet habe.

do{
     //get some input.
     //if the input meets my conditions, break;
     //Otherwise ask again.
} while(true)

Für meinen Test suche ich nur nach Konsoleneingaben, aber mir wurde gesagt, dass von dieser Art von Schleife abgeraten wird, da die Verwendung breakähnlich ist goto, wir tun es einfach nicht.

Ich verstehe die Fallstricke gotound seinen Java-Cousin voll und ganz break:labelund habe den guten Sinn, sie nicht zu benutzen. Mir ist auch klar, dass ein vollständigeres Programm ein anderes Mittel zur Flucht bieten würde, zum Beispiel um das Programm zu beenden, aber das war kein Grund, den mein Professor angeführt hat, also ...

Was ist los mit do-while(true)?

JHarnach
quelle
23
Fragen Sie Ihren Lehrer, solche Sachen sind ziemlich subjektiv.
Chris Eberle
18
Ich fand diesen Artikel hilfreich, um zu verstehen, was an goto schädlich ist . Der Vergleich mit breakist wahrscheinlich gut gemeint, wird aber tatsächlich missverstanden. Vielleicht können Sie Ihren Professor darüber unterrichten;) Nach meiner Erfahrung wissen Professoren nicht viel über das Handwerk des Programmierens.
Magnus Hoff
100
Das einzig wirklich unbestreitbare Schlechte daran ist meiner Meinung nach die Tatsache, dass do {} while (true)äquivalent zu while(true) {}und letztere bei weitem die konventionellere Form und viel klarer ist.
Voo
11
Wenn jemand die einfache Ausdruckskraft von nicht schätzt break, sollte er versuchen, in einer Sprache ohne sie zu programmieren. Es dauert nicht zu viele Schleifen, bis Sie es wünschen!
Steven
16
Ich bin mit dem Hausaufgaben-Tag nicht einverstanden.
aaaa bbbb

Antworten:

220

Ich würde nicht sagen, dass es schlecht ist - aber genauso würde ich normalerweise zumindest nach einer Alternative suchen.

In Situationen, in denen es das erste ist, was ich schreibe, versuche ich fast immer, es zumindest in etwas Klareres umzugestalten. Manchmal kann nicht geholfen werden (oder die Alternative besteht darin, eine boolVariable zu haben , die nichts Sinnvolles tut, als das Ende der Schleife anzugeben, weniger klar als eine breakAnweisung), aber es lohnt sich zumindest, es zu versuchen.

breakBetrachten Sie als Beispiel dafür, wo die Verwendung klarer ist als eine Flagge:

while (true)
{
    doStuffNeededAtStartOfLoop();
    int input = getSomeInput();
    if (testCondition(input))
    {
        break;
    }
    actOnInput(input);
}

Jetzt zwingen wir es, eine Flagge zu verwenden:

boolean running = true;
while (running)
{
    doStuffNeededAtStartOfLoop();
    int input = getSomeInput();
    if (testCondition(input))
    {
        running = false;
    }
    else
    {
        actOnInput(input);
    }
}

Ich halte letzteres für komplizierter zu lesen: Es hat einen zusätzlichen elseBlock, der actOnInputist stärker eingerückt, und wenn Sie herausfinden möchten, was bei der testConditionRückgabe passiert true, müssen Sie den Rest des Blocks sorgfältig durchsehen, um dies dort zu überprüfen ist nicht etwas nach dem elseBlock, das auftreten würde, ob runninggesetzt wurde falseoder nicht.

Die breakAnweisung kommuniziert die Absicht klarer und lässt den Rest des Blocks mit dem fortfahren, was er tun muss, ohne sich um frühere Bedingungen sorgen zu müssen.

Beachten Sie, dass dies genau das gleiche Argument ist, das Benutzer für mehrere return-Anweisungen in einer Methode haben. Wenn ich beispielsweise das Ergebnis einer Methode in den ersten Zeilen berechnen kann (z. B. weil eine Eingabe null oder leer oder null ist), finde ich es klarer, diese Antwort direkt zurückzugeben, als eine Variable zum Speichern des Ergebnisses zu haben , dann ein ganzer Block anderen Codes und schließlich eine returnAnweisung.

Jon Skeet
quelle
3
Ich bin damit einverstanden, dass es nicht das erste Tool ist, nach dem ich greife, aber es schien das Problem so sauber zu lösen, und ich mag sauberen Code.
JHarnach
3
@ X-Zero: Ja, manchmal. Wenn Sie die "Pause" in eine "Rückkehr" verwandeln können, ist das oft gut ... obwohl Sie möglicherweise immer noch mit einemwhile (true)
Jon Skeet
21
@trutheality: Ich bevorzuge jedoch, dass der größte Teil meines Codes so unaufmerksam wie möglich ist. Und eine Bedingung mit einer zusammengesetzten Zuordnung fühlt sich für mich komplizierter an.
Jon Skeet
3
@Vince: Ja, und das ist großartig, wenn Sie die Bedingung zu Beginn der Schleife leicht ausdrücken können . Aber manchmal kann man nicht - und das ist die Situation, über die wir sprechen. Bitte beachten Sie die ersten Sätze meiner Antwort.
Jon Skeet
6
@Ismail: Ich hoffe nicht. Beiträge sollten ausschließlich nach ihrem Inhalt beurteilt werden, nicht nach dem Autor. Heck, ich würde sogar einen Eric Lippert-Beitrag ablehnen, wenn ich der Meinung wäre, dass er ungenau / nicht hilfreich ist. Das ist aber noch nicht passiert :)
Jon Skeet
100

AFAIK eigentlich nichts. Lehrer sind nur allergisch gegen goto, weil sie irgendwo gehört haben, dass es wirklich schlimm ist. Sonst würdest du einfach schreiben:

bool guard = true;
do
{
   getInput();
   if (something)
     guard = false;
} while (guard)

Welches ist fast das gleiche.

Vielleicht ist dies sauberer (weil alle Schleifeninformationen oben im Block enthalten sind):

for (bool endLoop = false; !endLoop;)
{

}
El Marcel
quelle
4
Ich mag Ihre Vorschläge, da die Beendigungsbedingung viel sichtbarer ist. Das heißt, wenn Sie den Code lesen, werden Sie schneller verstehen, was er zu tun versucht. Ich würde niemals eine Endlosschleife verwenden, sondern Ihre beiden Versionen häufig verwenden.
Schlitten
4
Der Konsens ist, dass eine Flagge besser ist als zu brechen, weil sie Absicht ausdrückt? Ich kann sehen, dass das von Vorteil ist. Alle soliden Antworten, aber ich werde dies als akzeptiert markieren.
JHarnach
20
Beide leiden immer noch darunter, dass der Rest der Schleife (zumindest in einigen Situationen) verschmutzt ist, indem sie weiter bis zum Ende des Schleifenkörpers gehen müssen, selbst wenn Sie wissen, dass Sie brechen . Ich werde ein Beispiel in meine Antwort setzen ...
Jon Skeet
8
Ich mag Jon Skeets Antwort besser. Auch während (wahr) {} ist VIEL besser als {} während (wahr)
aaaa bbbb
1
Ich hasse es, dass Dijkstra jemals diesen GoTo-Artikel geschrieben hat. Während GoTo sicherlich oft missbraucht wurde, heißt das nicht, dass Sie es niemals verwenden sollten. Außerdem sind Exit For, Break, Exit While und Try / Catch nur spezielle Formen von Goto. Gotos können Code oft lesbarer machen. Und ja, ich bin mir bewusst, dass alles ohne Springen möglich ist. Das heißt nicht, dass es sollte.
Kibbee
39

Douglas Crockford hatte eine Bemerkung darüber, wie er wünschte, JavaScript würde eine loopStruktur enthalten:

loop
{
  ...code...
}

Und ich denke nicht, dass Java schlechter wäre, wenn man einloop Struktur .

An while(true)Schleifen ist an sich nichts auszusetzen , aber es gibt sie eine Tendenz für die Lehrer , sie zu entmutigen. Aus der Sicht des Unterrichts ist es sehr einfach, dass Schüler Endlosschleifen erstellen und nicht verstehen, warum die Schleife nie entkommen wird.

Was sie jedoch selten erwähnen, ist, dass alle Schleifenmechanismen mit repliziert werden könnenwhile(true) Schleifen werden können.

while( a() )
{
  fn();
}

ist das gleiche wie

loop
{
  if ( !a() ) break;
  fn();
}

und

do
{
  fn();
} while( a() );

ist das gleiche wie:

loop
{
  fn();
  if ( !a() ) break;
}

und

for ( a(); b(); c() )
{
  fn();
}

ist das gleiche wie:

a();
loop
{
  if ( !b() ) break;
  fn();
  c();
}

Solange Sie Ihre Schleifen so einrichten können, dass sie funktionieren, ist das von Ihnen ausgewählte Konstrukt unwichtig. Wenn es passiert , in einer passen forSchleife, verwenden Sie einfor Schleife.

Ein letzter Teil: Halten Sie Ihre Loops einfach. Wenn bei jeder Iteration viele Funktionen erforderlich sind, fügen Sie diese in eine Funktion ein. Sie können es jederzeit optimieren, nachdem es funktioniert hat.

zzzzBov
quelle
2
+1: Es gibt zusätzliche Komplexitäten mit forSchleifen, wenn continueAnweisungen beteiligt sind, aber sie sind keine wesentliche Erweiterung.
Donal Fellows
Normalerweise verwende ich eine for-Schleife, wenn es eine Sequenz gibt, über die ich laufen möchte, und eine while-Schleife, wenn es eine Bedingung gibt, die ich erfüllen möchte. Dadurch bleibt der Code imo besser lesbar.
Dascandy
4
Schreibt niemand for (;;) {mehr? (Ausgesprochen "für immer"). Dies war früher sehr beliebt.
Dawood ibn Kareem
16

Bereits 1967 schrieb Edgar Dijkstra in einem Fachmagazin einen Artikel darüber, warum goto aus Hochsprachen entfernt werden sollte, um die Codequalität zu verbessern. Daraus entstand ein ganzes Programmierparadigma namens "strukturierte Programmierung", obwohl sicherlich nicht alle zustimmen, dass goto automatisch schlechten Code bedeutet.

Der Kern der strukturierten Programmierung besteht im Wesentlichen darin, dass die Struktur des Codes seinen Fluss bestimmen sollte, anstatt Gotos oder Unterbrechungen zu haben, oder den Fluss weiterhin bestimmt, wo immer dies möglich ist. In ähnlicher Weise wird in diesem Paradigma auch davon abgeraten, mehrere Eintritts- und Austrittspunkte zu einer Schleife oder Funktion zu haben.

Offensichtlich ist dies nicht das einzige Programmierparadigma, aber oft kann es leicht auf andere Paradigmen wie die objektorientierte Programmierung (ala Java) angewendet werden.

Ihre Lehrer wurden wahrscheinlich unterrichtet und versuchen, Ihrer Klasse beizubringen, dass wir "Spaghetti-Code" am besten vermeiden, indem wir sicherstellen, dass unser Code strukturiert ist und die implizierten Regeln der strukturierten Programmierung befolgen.

Während bei einer Implementierung, die break verwendet, nichts von Natur aus "falsch" ist, halten es einige für wesentlich einfacher, Code zu lesen, bei dem die Bedingung für die Schleife explizit in der while () - Bedingung angegeben ist, und eliminieren einige Möglichkeiten, übermäßig knifflig zu sein. Es gibt definitiv Fallstricke bei der Verwendung einer (wahren) while-Bedingung, die von unerfahrenen Programmierern häufig im Code auftaucht, z. B. das Risiko, versehentlich eine Endlosschleife zu erstellen oder Code zu erstellen, der schwer zu lesen oder unnötig verwirrend ist.

Ironischerweise ist die Ausnahmebehandlung ein Bereich, in dem Abweichungen von der strukturierten Programmierung sicherlich auftreten und zu erwarten sind, wenn Sie weiter in die Programmierung in Java einsteigen.

Es ist auch möglich, dass Ihr Kursleiter von Ihnen erwartet hat, dass Sie nachweisen, dass Sie in der Lage sind, eine bestimmte Schleifenstruktur oder Syntax zu verwenden, die in diesem Kapitel oder in dieser Lektion Ihres Textes vermittelt wird, und obwohl der von Ihnen geschriebene Code funktional äquivalent ist, haben Sie dies möglicherweise nicht demonstriert besondere Fähigkeit, die Sie in dieser Lektion lernen sollten.

Jessica Brown
quelle
2
Hier ist Edsger Dijkstras Artikel . Es ist eine gute Lektüre.
Roy Prins
14

Die übliche Java-Konvention zum Lesen von Eingaben lautet:

import java.io.*;
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String strLine;

while ((strLine = br.readLine()) != null) {
  // do something with the line
}

Und die übliche C ++ - Konvention zum Lesen von Eingaben lautet:

#include <iostream>
#include <string>
std::string data;
while(std::readline(std::cin, data)) {
  // do something with the line
}

Und in C ist es

#include <stdio.h>
char* buffer = NULL;
size_t buffer_size;
size_t size_read;
while( (size_read = getline(&buffer, &buffer_size, stdin)) != -1 ){
  // do something with the line
}
free(buffer);

oder wenn Sie überzeugt sind, dass Sie wissen, wie lang die längste Textzeile in Ihrer Datei ist, können Sie dies tun

#include <stdio.h>
char buffer[BUF_SIZE];
while (fgets(buffer, BUF_SIZE, stdin)) {
  //do something with the line
}

Wenn Sie testen, ob Ihr Benutzer einen quitBefehl eingegeben hat , können Sie diese drei Schleifenstrukturen problemlos erweitern. Ich mache es in Java für Sie:

import java.io.*;
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String line;

while ((line = br.readLine()) != null  && !line.equals("quit") ) {
  // do something with the line
}

Während es sicherlich Fälle gibt, in denen dies gerechtfertigt ist breakoder gotogerechtfertigt ist, sollten Sie, wenn Sie nur Zeile für Zeile aus einer Datei oder der Konsole lesen, keine while (true)Schleife benötigen , um dies zu erreichen - Ihre Programmiersprache hat Sie bereits versorgt mit einer geeigneten Redewendung für die Verwendung des Eingabebefehls als Schleifenbedingung.

Ken Bloom
quelle
Wenn Sie while (true)anstelle einer dieser herkömmlichen Eingabeschleifen eine Schleife verwenden, vergessen Sie möglicherweise, nach dem Ende der Datei zu suchen.
Ken Bloom
3
Sie erreichen dies effektiv, indem Sie den ersten Teil der Schleife in die whileBedingung einfügen. In der endgültigen Java-Bedingung wird es bereits ziemlich heftig, und wenn Sie umfangreiche Manipulationen vornehmen müssen, um zu entscheiden, ob Sie fortfahren möchten oder nicht, kann es ziemlich lange dauern. Sie könnten es in eine separate Funktion aufteilen, und das könnte am besten sein. Aber wenn Sie es in einer Funktion haben möchten und nicht triviale Arbeit zu erledigen ist, bevor Sie entscheiden, ob Sie fortfahren möchten, ist dies while(true)möglicherweise am besten.
Poolie
@poolie: Dann ist es wahrscheinlich am besten, den Lesebefehl als Schleifenbedingung (die nach EOF sucht) zu verwenden und als break-Anweisungen nach Ihren anderen Bedingungen innerhalb der Schleife zu suchen.
Ken Bloom
1
Für das, was es wert ist, gets()ist keine übliche Konvention. Es ist sehr förderlich, Überläufe zu puffern. fgets(buffer, BUFFER_SIZE, file)ist viel mehr wie Standardpraxis.
Dave
@ Dave: Ich habe jetzt die zu verwendende Antwort bearbeitet fgets.
Ken Bloom
12

Es ist keine so schreckliche Sache, aber Sie müssen andere Entwickler beim Codieren berücksichtigen. Auch in der Schule.

Ihre Mitentwickler sollten in der Lage sein, die Exit-Klausel für Ihre Schleife in der Schleifendeklaration zu sehen. Das hast du nicht gemacht. Sie haben die Exit-Klausel in der Mitte der Schleife versteckt, um mehr Arbeit für jemanden zu machen, der mitkommt und versucht, Ihren Code zu verstehen. Dies ist der gleiche Grund, warum Dinge wie "Pause" vermieden werden.

Davon abgesehen werden Sie solche Dinge immer noch in einer Menge Code in der realen Welt sehen.

rfeak
quelle
4
Wenn die Schleife mit beginnt, ist while (true)es ziemlich offensichtlich, dass es ein breakoder returnin ihr geben wird oder dass es für immer laufen wird. Unkompliziert zu sein ist wichtig, aber an while(true)sich nicht besonders schlecht. Variablen mit komplexen Invarianten über Schleifeniterationen hinweg wären ein Beispiel für etwas, das viel mehr Angst verursacht.
Poolie
4
Versuchen Sie, bei einer Suche drei Ebenen tief zu gehen und dann irgendwie auszubrechen. Der Code wird viel schlechter, wenn Sie nicht einfach von diesem Punkt zurückkehren.
Dascandy
11

Es ist deine Waffe, deine Kugel und dein Fuß ...

Es ist schlecht, weil Sie um Ärger bitten. Sie oder eines der anderen Poster auf dieser Seite haben keine Beispiele für kurze / einfache while-Schleifen.

Das Problem wird zu einem sehr zufälligen Zeitpunkt in der Zukunft beginnen. Dies kann durch einen anderen Programmierer verursacht werden. Dies kann die Person sein, die die Software installiert. Es könnte der Endbenutzer sein.

Warum? Ich musste herausfinden, warum eine 700K LOC-App allmählich 100% der CPU-Zeit verbrennt, bis jede CPU gesättigt ist. Es war eine erstaunliche while (wahre) Schleife. Es war groß und böse, aber es lief darauf hinaus:

x = read_value_from_database()
while (true) 
 if (x == 1)
  ...
  break;
 else if (x ==2)
  ...
  break;
and lots more else if conditions
}

Es gab keinen letzten Zweig. Wenn der Wert nicht mit einer if-Bedingung übereinstimmte, lief die Schleife bis zum Ende der Zeit weiter.

Natürlich beschuldigte der Programmierer die Endbenutzer, keinen vom Programmierer erwarteten Wert ausgewählt zu haben. (Ich habe dann alle Instanzen von while (true) im Code entfernt.)

IMHO ist es keine gute defensive Programmierung, Konstrukte wie while (true) zu verwenden. Es wird zurückkommen, um dich zu verfolgen.

(Aber ich erinnere mich an die Bewertung von Professoren, wenn wir nicht jede Zeile kommentiert haben, auch nicht für i ++;)

jqa
quelle
3
+1 für den Kommentar zur defensiven Programmierung.
JHarnach
3
In Ihrem Beispiel ist der Code nicht wegen der Wahl der while (true) dumm, sondern wegen der Idee, eine Schleife um den Code zu setzen.
Florian F
Was war der Sinn dieser Schleife? :)
Juzzlin
6

Es ist in dem Sinne schlecht, dass strukturierte Programmierkonstrukte (den etwas unstrukturierten) Anweisungen zum Brechen und Fortfahren vorgezogen werden. Im Vergleich dazu werden sie nach diesem Prinzip dem "Gehe zu" vorgezogen.

Ich würde immer empfehlen, Ihren Code so strukturiert wie möglich zu gestalten ... obwohl Jon Skeet darauf hinweist, sollten Sie ihn nicht strukturierter gestalten!

Patrick87
quelle
5

Nach meiner Erfahrung haben Schleifen in den meisten Fällen die "Hauptbedingung", um fortzufahren. Dies ist die Bedingung, in die der while () - Operator selbst geschrieben werden sollte. Alle anderen Bedingungen, die die Schleife unterbrechen können, sind sekundär, nicht so wichtig usw. Sie können als zusätzliche if() {break}Anweisungen geschrieben werden.

while(true) ist oft verwirrend und weniger lesbar.

Ich denke, dass diese Regeln nicht 100% der Fälle abdecken, sondern wahrscheinlich nur 98%.

AlexR
quelle
Gut gesagt. Es ist wie eine for-Schleife mit: while (true) {i ++; ...}. Sie vergraben die Schleifenbedingung innerhalb der Schleife und nicht in der 'Signatur'.
LegendLength
3

Obwohl dies nicht unbedingt eine Antwort darauf ist, warum man es nicht verwendet while (true), habe ich immer diese komische und begleitende Aussage des Autors gefunden eine prägnante Erklärung, warum man es tut, anstatt es zu tun.

In Bezug auf Ihre Frage: Es gibt kein inhärentes Problem mit

while(true) {
   do_stuff();
   if(exit_time) {
      break;
   }
}

... wenn Sie wissen, was Sie tun und sicherstellen, dass dies exit_timeirgendwann ausgewertet wirdtrue .

Lehrer raten von der Verwendung ab, while(true)da es eine einfache Möglichkeit ist, einen kritischen Fehler zu machen, bis Sie genau wissen, was Sie tun.

Shadur
quelle
Ich denke Einstellung exit_time = false; while(!exit_time) { execute_stuff(); }und do { execute_stuff(); } while(! exit_time );sind beide viel klarer als ein if( condition ) { break; }am Ende einer Schleife mit einem while(true). Unterbrechungen sind Kurzschlüsse zu Schleifen - vollkommen in Ordnung, wenn sie als Kurzschluss in der Mitte einer Schleife verwendet werden. Sie sollten jedoch nur eine Bedingung in der while-Anweisung als eine Unterbrechung am Ende einer Schleife bewerten.
Dr. Jimbob
In Bezug auf diesen Comic: Während do-while nicht alles kann, während kann, ist do-while manchmal besser, was do-while auch tun kann, während while auch kann.
Theraot
3

Sie können einfach ein Boolesches Flag verwenden, um anzugeben, wann die while-Schleife beendet werden soll. Breakund go towaren Gründe dafür, dass Software zu schwer zu warten ist - die Software-Krise (tm) - und sollten vermieden werden und können es auch leicht sein.

Es ist eine Frage, ob Sie pragmatisch sind oder nicht. Pragmatische Programmierer könnten in dieser einfachen Situation nur break verwenden.

Aber es ist gut, die Gewohnheit zu bekommen, sie nicht zu verwenden, sonst könnten Sie sie in ungeeigneten Situationen aus dem Habbit heraus verwenden, wie in komplizierten verschachtelten Schleifen, in denen die Lesbarkeit und Wartbarkeit Ihres Codes durch die Verwendung schwieriger wird break.

Daniel Leschkowski
quelle
8
Weil das Halten einer booleschen Flagge meiner Erfahrung nach wahrscheinlich nicht klarer und möglicherweise weniger klar ist?
Jon Skeet
3
@ Jon Skeet Nun, es ist eine Frage des Gehens mit einem guten Habbit oder des Trainings eines schlechten mit Pause. Ein Bool namens "Running" ist dir nicht klar? Es ist offensichtlich, leicht zu debuggen und wie ich bereits erwähnt habe, ist ein guter Habbit eine gute Sache, die man behalten sollte. Wo ist das Problem?
Daniel Leschkowski
4
Ein Bool namens running, bei dem ich eine if (running)innerhalb der Schleife haben muss, um den gesamten Rest des Codes einzurücken, wenn ich nur die Schleife verlassen möchte, ist mir definitiv weniger klar als eine einfache break-Anweisung, die genau angibt , was ich tun möchte. Sie scheinen zu erwägen, Pause axiomatisch als schlechte Angewohnheit zu verwenden - ich sehe das nicht als solche.
Jon Skeet
2
Warum sollten Sie ein if (running) innerhalb der Schleife haben? Wie bei break am Ende der Schleife prüfen Sie, ob Sie das Flag ausbrechen und umdrehen möchten, anstatt break zu verwenden, und verwenden Sie das Flag in while (running) anstelle von while (true). Ich verstehe Ihren Standpunkt nicht ernst. Ich würde zustimmen, dass ein pragmatischer Programmierer in bestimmten Situationen eine Pause verwenden könnte, aber ich verstehe die Kommentare, die Sie unter meinem Vorschlag abgegeben haben, wirklich nicht
Daniel Leschkowski
3
Sie gehen davon aus, dass Sie innerhalb der Schleife nichts tun müssen, nachdem Sie festgelegt haben, ob Sie das Programm beenden möchten oder nicht. Zum Beispiel muss er in der Situation des OP um mehr Input bitten, wenn er nicht aufgibt.
Jon Skeet
3

Vielleicht habe ich Pech. Oder vielleicht fehlt mir einfach eine Erfahrung. Aber jedes Mal, wenn ich mich erinnere, while(true)dass breakes darum ging , drinnen zu sein, war es möglich, den Code zu verbessern, indem die Extraktionsmethode auf while-Block angewendet wurde , wodurch das while(true)aber (zufällig?) Alle breaks in returns transformierte .

Nach meiner Erfahrung while(true)ohne Pausen (dh mit Rückschlägen oder Würfen) sind sie recht bequem und leicht zu verstehen.


  void handleInput() {
      while (true) {
          final Input input = getSomeInput();
          if (input == null) {
              throw new BadInputException("can't handle null input");
          }
          if (input.isPoisonPill()) {
              return;
          }
          doSomething(input);
      }
  }
Mücke
quelle
3

Ich denke, dass es ja ziemlich schlecht ist ... oder zumindest für viele Entwickler. Es ist symptomatisch für Entwickler, die nicht über ihre Schleifenbedingungen nachdenken. Folglich ist es fehleranfällig.

Griff Sob Becker
quelle
2

Es gibt kein großes Problem mit while(true)mit breakAussagen, denken einige können jedoch seine leicht die Lesbarkeit des Codes senkt. Versuchen Sie, Variablen aussagekräftige Namen zu geben und Ausdrücke an der richtigen Stelle auszuwerten.

Für Ihr Beispiel scheint es viel klarer zu sein, etwas zu tun wie:

do {
   input = get_input();
   valid = check_input_validity(input);    
} while(! valid)

Dies gilt insbesondere dann, wenn die do while-Schleife lang wird - Sie wissen genau, wo überprüft wird, ob eine zusätzliche Iteration stattfindet. Alle Variablen / Funktionen haben auf der Abstraktionsebene entsprechende Namen. Die while(true)Aussage besagt, dass die Verarbeitung nicht an dem Ort erfolgt, an dem Sie gedacht haben.

Vielleicht möchten Sie beim zweiten Mal durch die Schleife eine andere Ausgabe. Etwas wie

input = get_input();
while(input_is_not_valid(input)) {
    disp_msg_invalid_input();
    input = get_input();
}

scheint mir dann lesbarer zu sein

do {
    input = get_input();
    if (input_is_valid(input)) {
        break;
    }
    disp_msg_invalid_input();
} while(true);

Wiederum sind beide mit einem trivialen Beispiel gut lesbar; Wenn die Schleife jedoch sehr groß oder tief verschachtelt wurde (was bedeutet, dass Sie sie wahrscheinlich bereits überarbeitet haben sollten), ist der erste Stil möglicherweise etwas klarer.

Dr. Jimbob
quelle
1

Ich verwende in vielen meiner Funktionen etwas Ähnliches, aber mit entgegengesetzter Logik.

DWORD dwError = ERROR_SUCCESS;

do
{
    if ( (dwError = SomeFunction()) != ERROR_SUCCESS )
    {
         /* handle error */
         continue;
    }

    if ( (dwError = SomeOtherFunction()) != ERROR_SUCCESS )
    {
         /* handle error */
         continue;
    }
}
while ( 0 );

if ( dwError != ERROR_SUCCESS )
{
    /* resource cleanup */
}
Jim Fell
quelle
1

Es ist eher eine ästhetische Sache, viel einfacher zu lesender Code, bei dem Sie explizit wissen, warum die Schleife direkt in der Deklaration der Schleife stoppt.

Petey B.
quelle
1

Ich würde sagen, dass der Grund dafür, dass dies keine gute Idee ist, im Allgemeinen darin besteht, dass Sie das Konstrukt nicht in vollem Umfang nutzen. Außerdem neige ich dazu zu denken, dass es vielen Programmierlehrern nicht gefällt, wenn ihre Schüler mit "Gepäck" hereinkommen. Damit meine ich, dass sie gerne den primären Einfluss auf den Programmierstil ihrer Schüler haben. Vielleicht ist das nur ein kleiner Ärger des Ausbilders.

Paul
quelle
1

Für mich ist das Problem die Lesbarkeit.

Eine while-Anweisung mit einer wahren Bedingung sagt nichts über die Schleife aus. Es macht die Aufgabe, es zu verstehen, viel schwieriger.

Was wäre aus diesen beiden Ausschnitten leichter zu verstehen?

do {
  // Imagine a nice chunk of code here
} while(true);

do {
  // Imagine a nice chunk of code here
} while(price < priceAllowedForDiscount);
Vince Panuccio
quelle
0

Ich denke, wenn Sie Ihrem Lehrer eine Pause geben, brechen Sie einen Ast eines Baumes, um die Früchte zu erhalten. Verwenden Sie einige andere Tricks (beugen Sie den Ast), damit Sie die Früchte bekommen und der Ast noch lebt. :)

Bimal Sharma
quelle
0

1) Mit a ist nichts falsch do -while(true)

2) Dein Lehrer ist falsch.

NSFS !!:

3) Die meisten Lehrer sind Lehrer und keine Programmierer.

Pacerier
quelle
@Connell warte bis dein Lehrer das hört!
Pacerier
1
Ich bin Autodidakt an der Programmierfront. Alles, woran ich messen muss, ist mein IT-Lehrer in der Sekundarschule, der uns beigebracht hat, Websites mit Dreamweaver so zu erstellen, dass ALLES ein absolut positionierter Div war ...
Connell
@Connell bis mein Beitrag, um Ihre Zustimmung zu zeigen
Pacerier
2
"Wer nicht kann, lehrt." - Das ist eine ziemlich große Verallgemeinerung, findest du nicht? Sollten Ärzte, Ingenieure, Piloten usw. Autodidakten sein, da ihre Ausbilder Ihrer Meinung nach inkompetent sind?
Filip-Fku
@ filip-fku wow wow ~ cool es cool es!
Pacerier
0

Es kann schlecht sein, wenn Ihre Schleife in einem Hintergrundthread ausgeführt wird. Wenn Sie also Ihre Anwendung durch Beenden eines UI-Threads schließen, wird dieser Code weiterhin ausgeführt. Wie andere bereits sagten, sollten Sie immer eine Art Scheck verwenden, um eine Möglichkeit zur Stornierung bereitzustellen.

Dmitry
quelle