Ich habe gehört, dass einige "Breaks" keine schlechte Übung sind. Was ist mit diesem?

8

Ich habe oft gehört, dass die Verwendung von break s in Java als schlechte Übung gilt, aber nachdem ich einige Threads auf Stack Overflow gelesen habe, habe ich etwas anderes gesehen. Viele sagen, dass es in bestimmten Fällen akzeptabel ist.

Ich bin etwas verwirrt darüber, was in diesem Fall schlecht ist / ist.

Für Project Euler : Problem 7, ich habe den folgenden Code erstellt. Die Herausforderung bestand darin, die 10001. Primzahl zu finden.

%Vor%

Dies liefert die korrekte Antwort (in 21ms), aber übersehe ich eine ernste Warnung? Es ist 100% möglich, eine While-Schleife ohne Pause zu erstellen, aber ich finde, dass dies ein wenig einfacher zu folgen ist.

Benutzt ich die break; schlechte Übung? Ich weiß, dass es immer einen Weg gibt, einen zu benutzen, aber ist es wirklich so schlimm hier?

Vielen Dank

Justian

BEARBEITEN

Hier ist mein isPrime () Code. Ich könnte das auch optimieren, während ich dabei bin.

%Vor%     
Justian Meyer 30.07.2010, 16:09
quelle

9 Antworten

15

In diesem Fall sieht es für mich so aus, als ob es einfacher wäre, die Bedingung while zu ändern:

%Vor%

Das ist normalerweise der Fall, wenn eine while(true) Schleife mit

endet %Vor%

... obwohl Sie prüfen müssen, ob etwas anderes im Schleifenkörper ein continue ausführt.

Alternativ könnten Sie es leicht umstrukturieren:

%Vor%

Dann wird current die Antwort am Ende sein.

Im Allgemeinen bevorzuge ich eine for -Schleife über eine while-Schleife, wenn Sie versuchen, eine bestimmte Anzahl von Malen zu tun. In diesem Fall ist das "Etwas" "finde die nächste Primzahl".

Es gibt verschiedene Dogmen in der Programmierung, von denen ich glaube, dass sie zu weit gefasst sind - einschließlich "eines Ausgangspunkts für eine Methode" und "keine Pause verwenden". Schreibe den Code so gut wie möglich. Wenn du dir Code anschaust und merkst, dass es nicht offensichtlich ist, was los ist, versuche, andere Wege zu finden, ihn zu strukturieren. Manchmal ist es ein Fall, eine Schleife zu ändern; manchmal extrahiert es eine Methode; manchmal invertiert es eine Logik (gehe zuerst mit einem negativen Zweig um, wähle möglicherweise früh und bearbeite dann den Normalfall).

    
Jon Skeet 30.07.2010, 16:12
quelle
22

Ich bin mir nicht sicher, ob Pausen im Allgemeinen eine schlechte Übung sind, aber ich denke, dass dies eine ist.

Es ist ein bisschen albern, weil es unnötig ist. Ihr while (true) ... break entspricht vollständig:

%Vor%

aber viel weniger intuitiv.

Wenn Sie sich an den kanonischen Weg zur Darstellung von Dingen halten, bedeutet das weniger Rechenaufwand für Ihre Leser, macht Ihren Code verständlicher, einfacher zu pflegen und letztendlich robuster.

Bearbeiten (als Antwort auf einen Kommentar): Sie haben Recht, dass es immer einen Weg gibt, einen zu verwenden, aber die Regel (wenn Sie einen wollen) ist relativ einfach: Schreiben Sie, was am besten lesbar ist. In dem Fall, dass Sie gepostet haben, ist dies nicht der lesbarste, da die Alternative, die ich gab, die kanonische Art ist, dies zu repräsentieren. In einigen Fällen, zum Beispiel durch eine Sammlung, bis Sie einen bestimmten passenden Kandidaten gefunden haben, ist die Verwendung von break wahrscheinlich der beste Weg, dieses Muster darzustellen.

Es wäre schwierig (und ich würde argumentieren, vergeblich), zu versuchen, sich mit festen Regeln darüber zu befassen, wann break verwendet werden soll und wann man Variablen herausziehen und stattdessen Konditionale verwenden soll. Oft ist es einfach zu sagen, was die einfachste Option ist, aber nicht immer. Dies ist eines der Beispiele, wo Erfahrung wirklich zählt - je mehr guten / schlechten Code du gelesen und selbst geschrieben hast, desto größer deine persönliche Bibliothek an guten und schlechten Beispielen und desto einfacher wird es für dich sein zu sagen, was das "Beste" ist "* Möglichkeit, ein gegebenes Konzept darzustellen.

* Natürlich ist es subjektiv!

    
Andrzej Doyle 30.07.2010 16:11
quelle
3

Es gibt ein paar Bedingungen, wenn es sinnvoll ist, eine Pause zu machen. Eine ist, wenn Sie N.5-Loops ausführen müssen - d. H., Sie werden die Schleife einige Male ausführen, aber das letzte Mal werden Sie immer irgendwo in der Mitte des Loop-Körpers ausgeführt. Sie können vermeiden, in diesem Fall eine Pause zu verwenden, aber dies verschleiert oft den Code oder führt zu einer Duplizierung. Zum Beispiel:

%Vor%

kann wie folgt aussehen:

%Vor%

oder:

%Vor%

Keine davon ist notwendigerweise eine wesentliche Verbesserung. Ein anderer Umstand, unter dem eine Pause sinnvoll sein kann, ist einfach ein Fehler. Wenn Sie beispielsweise N Dateien zur Verarbeitung übergeben haben, kann es sinnvoll sein, die Schleife zu verlassen, wenn eine der Dateien nicht geöffnet werden kann. Nichtsdestoweniger, wenn es überhaupt sinnvoll ist , ist es eindeutig besser, die Bedingung zu haben, unter der Sie die Schleife verlassen, die explizit in der Bedingung der Schleife angegeben ist.

    
Jerry Coffin 30.07.2010 16:25
quelle
2

Wenn du ohne Pause davonkommen kannst, dann tu es.

tue

%Vor%     
hvgotcodes 30.07.2010 16:12
quelle
2

Dafür wurde / while erfunden:

%Vor%

Es ist das while(true) -Bit, das ich schlecht finde, was natürlich zu break führt.

    
sje397 30.07.2010 16:14
quelle
2

Nicht sehr verschieden von allem, was vorher gesagt wurde, aber von der Lesbarkeit, dem transparenten logischen Standpunkt würde ich empfehlen

%Vor%

ich bin die Antwort.

    
aepryus 30.07.2010 19:45
quelle
0

Wenn es nur eine Bedingung gibt, unter der eine Schleife beendet werden kann, und vor der Überprüfung der Bedingung nicht viel Code ausgeführt werden muss und nicht viel Code ausgeführt werden muss Überprüfen Sie die Bedingung, setzen Sie die Bedingung in die Schleife.

Ich denke, es gibt sicherlich Anwendungen für ein "do {} while (1);" Schleife. Unter ihnen:

  1. Im Loop-Continue-Fall muss die primäre Bedingung genügend Code haben, bevor und nachdem überprüft wird, dass das Einfügen des Codes in die Bedingung selbst bestenfalls peinlich wäre.
  2. Die Schleife hat mehrere Exit-Bedingungen, und die Exit-Bedingung, die logisch am oberen oder unteren Ende der Schleife stehen würde, würde speziellen Code zur Ausführung erfordern, der für andere Exit-Bedingungen nicht ausgeführt werden sollte.

Manche Leute benutzen gerne Flags, um Ausgangsbedingungen zu unterscheiden. Ich neige dazu, solche Flags als eine Bemühung zu betrachten, die Codierungsstrukturen zu vermeiden, die tatsächlich die Aktion des Programms am besten verkörpern.

Wenn man sich keine Gedanken über die Geschwindigkeit macht, kann man vermeiden, jemals irgendeine Form von goto , vorzeitigem Beenden return zu verwenden, oder für mehrere Zwecke während - und das mit einer einfachen Bedingung. Schreiben Sie einfach das gesamte Programm als Zustandsmaschine:

%Vor%

Es gibt Zeiten, in denen ein solches Codieren nützlich ist (insbesondere wenn das "while" aus der Routine do_whatever () in eine Schleife gezogen werden kann, die mehrere ähnlich codierte Routinen "simultan" ausführt). Und es ist nie nötig, etwas wie ein "Goto" zu verwenden. Aber zur besseren Lesbarkeit sind strukturierte Programmierkonstrukte viel netter.

Meiner Meinung nach ist das Ersetzen eines strukturierten Codes durch unstrukturierten Code ein Flag, um eine Schleife zu beenden und dann einen von mehreren Codeteilen auszuwählen, die basierend auf der Beendigungsursache ausgeführt werden. Wenn ich innerhalb einer Schleife schreibe, schreibe ich

%Vor%

Es ist sofort (und lokal) klar, dass der Grund, warum ich ein neues Objekt erstelle, darin liegt, dass mein Index die Anzahl der Elemente überschritten hat und ich keine redundante Bedingung testen muss. Wenn ich stattdessen eine Schleife mache, bis ich etwas gefunden habe oder keine Elemente mehr habe, dann muss ich entweder eine Bedingung nach der Schleife redundant testen oder jeder Schleifeniteration einen Flag-Test hinzufügen.

    
supercat 30.07.2010 16:58
quelle
0

Wie andere bemerkt haben, ist das Beispiel, das Sie angegeben haben, ein schlechtes, weil Sie den Test einfach in den WHILE verschieben können.

Die Fälle, in denen ich eine Pause benutze, sind wenn ich eine Schleife habe, in der ich etwas verarbeiten muss, bevor ich weiß, dass dies das letzte Mal ist. Zum Beispiel:

%Vor%

Dieses Beispiel ist nur leicht erfunden: Ich stoße oft auf Probleme, wenn ich Daten aus einer Datei oder einer anderen Quelle lese, diese Daten irgendwie parse und erst dann weiß, dass ich das Ende erreicht habe, an dem ich interessiert bin Verarbeitung jetzt.

Sie könnten natürlich eine Funktion schreiben, die die Zeile liest und das Parsen benötigt, wie:

%Vor%

Aber dann haben Sie möglicherweise das Problem, dass sowohl die Funktion als auch der Körper der Schleife Zugriff auf die gelesenen Daten benötigen, und die Funktion muss einen booleschen Wert für die Regelkreisverarbeitung zurückgeben, so dass sie die Daten nicht zurückgeben kann Um die Daten für den Schleifenkörper verfügbar zu machen, muss die Funktion in ein für beide Seiten zugängliches Feld geworfen werden, das dann verdeckt, woher die Schleife ihre Daten bezieht.

    
Jay 30.07.2010 16:59
quelle
0

Diese Lösung ist ziemlich schnell:

%Vor%

Anmerkungen:

  • isqrt (n) ist floor (sqrt (n)). Dies vermeidet Gleitkommaoperationen, die wir sowieso nicht brauchen. Algorithmus von Ссылка .
  • nPrimes führt eine Liste der Primzahlen. Dies ermöglicht es Ihnen, nur Prim Divisors zu testen, was die große Mehrheit dieser kostspieligen Mod-Operationen ausschließt.
  • Selbst die Primzahlen werden nur bis Isqrt (n) getestet.
  • Das ist ein hässliches Goto, aber C hat nicht weiter benannt, und eine Flag-Variable wäre eine totale Zeitverschwendung gewesen.
  • Das primes-Array wird mit 2 initialisiert und es werden nur ungerade Zahlen von 3 geprüft. Die Entfernung von Vielfachen von 3 ist in ähnlicher Weise möglich, aber nicht von trivialer Komplexität.
  • Der isqrt-Aufruf könnte eliminiert werden, indem eine Tabelle mit Quadraten von Primzahlen gehalten wird. Das ist mit ziemlicher Sicherheit ein Overkill, aber Sie können, wenn Sie wollen.
  • Auf meiner nicht-neuen Maschine läuft das im Handumdrehen.
Thom Smith 31.07.2010 18:03
quelle

Tags und Links