Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Break schlechter Programmierstil? (https://www.delphipraxis.net/13121-break-schlechter-programmierstil.html)

mirage228 11. Dez 2003 12:35


Break schlechter Programmierstil?
 
Hallo,

in der heutigen Informatikstunde haben wollten wir einen spezifischen Wert aus einem Array suchen.
Unser Lehrer nutzte hierzu eine WHILE schleife. Ich schlug hierrauf vor, das mit einer FOR schleife und einem Break; nach dem Finden des Wertes (bzw. des indexes) die schleife zu verlassen. Er meinte daraufhin, dass man das so nicht machen könne(oder solle), da Break "extrem schlechter" Programmierstil sei.

Nun meine Frage: Ist da tatsächlich was dran? War die Benutzung von Break unter TurboPascal nun anders, sodass mein Lehrer das Break als schlechten Stil bezeichnet?

mfG
mirage228

Tyrael Y. 11. Dez 2003 12:37

Re: Break schlechter Programmierstil?
 
lol,

ich benutze Break nicht oft, aber ich benutze es und finde es nicht als
schlechten Programierstil

genauso exit, wobei ich exit wichtiger finde


Gruß

Dagon 11. Dez 2003 12:43

Re: Break schlechter Programmierstil?
 
Es ist schon so, das es nicht gerade zu einem guten Programmierstil gehört. Manchmal ermöglicht es aber eine übersichtlichere Konstruktion.

Sanchez 11. Dez 2003 12:51

Re: Break schlechter Programmierstil?
 
Ich benutze break eigentlich regelmäßig in der Form, wie es Mirage beschrieben hat.
Ich hatte dabei nicht das Gefühl, dass diese Konstruktionen meinen Programmierstil runterziehen. Da gibts schlimmere Sachen, die mich ärgern, wenn ich später mal was modifiziere.

Pseudemys Nelsoni 11. Dez 2003 12:52

Re: Break schlechter Programmierstil?
 
ka wieso das schlecht sein sollte, würde doch nur zeit kosten wenn man es nicht benutzt und die schleife ganz durchlaufen lässt ohne das es noch nötig ist

Phoenix 11. Dez 2003 12:56

Re: Break schlechter Programmierstil?
 
Ob schlechter oder guter Stil liegt in so einem Fall auch immer daran, wofür man ein bestimmtes Konstrukt verwendet.

Würdest Du, wenn Du einen Countdown brauchst, eine normale Uhr nehmen und an der Stelle wo 0 sein soll einen Nagel ins Zifferblatt hauen um den Zeiger zu stoppen (break), oder gleich eine Sanduhr nehmen und nur so viel Sand einfüllen wie Du für den Countdown brauchst (while)?

Eine For-Schleife ist nunmal dann das richtige Werkzeug, wenn Du für jedes (for each, wie es auch ab und zu woanders heisst) Element in der Schleife etwas bestimmtes tun willst.

Man sucht aber nicht für jedes Element, sondern solange wie man es noch nicht gefunden hat. Deshalb ist bei einer sequentiellen Suche nunmal eine while - Schleife die richtige.

Von daher würde ich Deinem Lehrer da in jedem Fall zustimmen: For / break für eine Suche ist schlechter Stil.

Sanchez 11. Dez 2003 13:01

Re: Break schlechter Programmierstil?
 
Ich finds einfach einfacher, wenn ich

Delphi-Quellcode:
  for i:=0 to Count - 1 do begin
    if gefunden then begin
      MachWasDraus;
      break;
    end;
  end;
schreibe als

Delphi-Quellcode:
  while NichtGefunden and (i < Count) do begin
    if Gefunden then begin
      NichtGefunden := false;
      MachWasDraus;
      i := i + 1;
    end;
  end;
zu schreiben. Wenns irgendeine plausible Erklärung gibt, while zu verwenden nehm ich halt while

Phoenix 11. Dez 2003 13:07

Re: Break schlechter Programmierstil?
 
Hrm..

Scheint, als hättest Du da was nicht ganz 100% optimiert :)
Also wenn man das richtig macht sieht das so aus:
Delphi-Quellcode:
while not gefunden do
   Suche;

Machwas;
Delphi-Quellcode:
for i := 0 to Count - 1 do
begin
   Suche;
   if gefunden then
      break;
end;

Machwas;
Und was ist nun besser?

Pseudemys Nelsoni 11. Dez 2003 13:11

Re: Break schlechter Programmierstil?
 
Zitat:

while not gefunden do
Suche;
ist das nicht ne endlosschleife? oder wird "gefunden" irgendwann auf true gesetzt?

mirage228 11. Dez 2003 13:13

Re: Break schlechter Programmierstil?
 
Phoenix, wenn das element nicht gefunden wurde, ergibt das obere gnadenlos eine endlosschleife :-D

wir hatten das so gemacht, dass wir das ergebins erstmal auf 0 (ausserhalb des arrays) setzen und die while schleife maximal bis zu CONST n = 10000 (so lang ist der Array) laufen lassen.

mfG
mirage228

Phoenix 11. Dez 2003 13:16

Re: Break schlechter Programmierstil?
 
In Suche wird gefunden auf true gestellt, wenn das Element gefunden wurde.
Alternativ kann man hier auch einen Counter mitführen der halt auch true zurückgibt wenn man am Ende der Elementliste ist.

Allerdings ist die von Sanchez ist immer eine Endlosschleife:

Zitat:

Zitat von Sanchez
Delphi-Quellcode:
  while NichtGefunden and (i < Count) do begin
    if Gefunden then begin
      NichtGefunden := false;
      MachWasDraus;
      i := i + 1;
    end;
  end;

Schliesslich macht die nix. Noch nichtmal den Counter erhöhen :)

Sanchez 11. Dez 2003 13:22

Re: Break schlechter Programmierstil?
 
Meine Version ist keine Endlosschleife.
Count ist die Anzahl der Elemente (z.B. length(Array) oder stringliste.count) und i ist der Zähler.
i wird in jedem Schleifendurchgang um eins erhöht

Phoenix 11. Dez 2003 13:31

Re: Break schlechter Programmierstil?
 
Negativ, Dein Zähler wird nur um eins erhöht, wenn das Element das richtige ist:
Delphi-Quellcode:
if Gefunden then begin
      NichtGefunden := false;
      MachWasDraus;
      i := i + 1;      // <-- hier, nur im if gefunden then... block
    end;
Will heissen: wenn nicht zufällig das erste Element schon das gesuchte ist bleibt er für immer darauf stehen.

Sanchez 11. Dez 2003 13:32

Re: Break schlechter Programmierstil?
 
:oops: das muss ich wohl übersehen haben. Aber das diente sowieso nur zur Veranschaulichung und hat nie einen Kompiler zu gesicht bekommen :mrgreen:

jbg 11. Dez 2003 15:04

Re: Break schlechter Programmierstil?
 
Bei so einfachen Beispielen ist die Benutzung von Break sicher nicht begründet. Das break ist eher für eine Schleife, in der mehr als nur eine Anweisung steht gedacht, wobei die restlichen Anweisungen bei einer bestimmten Bedingung nicht mehr ausgeführt und die Schleife verlassen werden soll.

Versuche mal folgenden Code ohne Break (und natürlich ohne goto) zu realisieren. Welcher der beiden Codes wird leichter zu lesen sein?
Delphi-Quellcode:
    while (i < lCount) or (ri < rCount) do begin
      if i < lCount then l := FLocalFL.Items[Integer(lList.Objects[i])]
       else begin
        // alle restlichen Remote-Dateien in die Delete-Listen
        while ri < rCount do begin
          if FRemoteFL.Items[Integer(rList.Objects[ri])].IsDir
           then delDirs.AddObject('-d' + rList[ri], rList.Objects[ri])
           else delFiles.AddObject('-f' + rList[ri], rList.Objects[ri]);
          inc(ri);
        end;
        break; // und raus
      end;
      if ri < rCount then rl := FRemoteFL.Items[Integer(rList.Objects[ri])]
       else begin
         // alle restlichen Local-Dateien in die Add-Listen
         while i < lCount do begin
           if FLocalFL.Items[Integer(lList.Objects[i])].IsDir
            then addDirs.AddObject('+d' + lList[i], lList.Objects[i])
            else addFiles.AddObject('+f' + lList[i], lList.Objects[i]);
           inc(i);
         end;
         break; // und raus
      end;

      if not DoCompare(l.Name, rl.Name) then begin
        // Datei suchen
         x := ri;
         while (x < rCount) and (not DoCompare(rList[x], l.Name)) do inc(x);
         if x = rCount then begin
           // nicht gefunden

          // Datei/Ordner hinzufügen
            if l.IsDir then addDirs.AddObject('+d' + l.Name, lList.Objects[i])
             else addFiles.AddObject('+f' + l.Name, lList.Objects[i]); // neue Datei // LocalIndex

            dec(ri); // und ri am Ende nicht erhöhen
          end else begin
           // gefunden

           // Alle dazwischenliegenden Dateien löschen
           while ri < x do begin
             if FRemoteFL.Items[Integer(rList.Objects[ri])].IsDir
              then delDirs.AddObject('-d' + rList[ri], rList.Objects[ri])
              else delFiles.AddObject('-f' + rList[ri], rList.Objects[ri]);
             inc(ri);
           end;
          // Daten holen
           rl := FRemoteFL.Items[Integer(rList.Objects[ri])];
         end;
      end;

      if DoCompare(l.Name, rl.Name) then begin
         if l.IsDir and rl.IsDir then begin end // Verzeichnisse nicht überprüfen
          else if l.IsDir <> rl.IsDir then begin
            if rl.IsDir then begin
              // eine Datei ist ein remote Verzeichnis ??? -> remote Verzeichnis mit Subdirs löschen.
               delDirs.AddObject('-d' + rl.Name, rList.Objects[ri]); // RemoteIndex
               dir := rl.Name + '/';
               len := length(dir);
               inc(ri);
              // Unterordner löschen
               while (ri < rCount) do begin
                 rl := FRemoteFL.Items[Integer(rList.Objects[ri])];
                 if DoCompare(copy(rl.Name, 1, len), dir) then begin
                    if rl.IsDir
                     then delDirs.AddObject('-d' + rl.Name, rList.Objects[ri])
                     else delFiles.AddObject('-f' + rl.Name, rList.Objects[ri]); // RemoteIndex
                 end else break;
                 inc(ri);
               end;
               dec(ri);
              // und die Datei hinzufügen
               addFiles.AddObject('+f' + l.Name, lList.Objects[i]); // LocalIndex
             end else begin
              // ein Verzeichnis ist eine remote Datei ??? -> remote Datei löschen
               delFiles.AddObject('-f' + rl.Name, rList.Objects[ri]); // RemoteIndex
              // und das Verzeichnis hinzufügen
               addDirs.AddObject('+d' + l.Name, lList.Objects[i]); // LocalIndex
            end;
          end else begin
          // nur Dateien hier:
           update := False;
           if (FUpdateDate) then begin
              update := ((not FUpdateOnlyNewerDate) and
                         (l.LastWriteTime <> rl.LastWriteTime))
                         or
                        ((FUpdateOnlyNewerDate) and
                         (l.LastWriteTime > rl.LastWriteTime));
           end;
           if (FUpdateSize) and (l.Size <> rl.Size) then update := True;

           if update then
              updFiles.AddObject('*f' + l.Name, lList.Objects[i]); // LocalIndex
         end; // if
      end; // if

      inc(i);
      inc(ri);
    end; // while

Robert Marquardt 11. Dez 2003 15:35

Re: Break schlechter Programmierstil?
 
Break ist nicht per se schlecht. In C z. B. sind die for und while Schleife sehr eng verwandt und Break ist dort voellig normal.
In Delphi ist die for Schleife konzeptionell deutlich anders als die while Schleife.
Man sollte mit dem Break sparsam umgehen. Da es aber vorhanden ist, kann sein Gebrauch auch nicht falsch sein.
Wichtig ist das man nicht zu Exit greift wenn Break reicht. Das macht die Programme leichter wartbar.
Besonders haesslich finde ich es wenn man zum exzessiven Exit Stil greift und in kurzen Methoden erst mal alle Bedingungen mit Exit abweist. Das ist schwer verstaendlich.

Phoenix 11. Dez 2003 15:47

Re: Break schlechter Programmierstil?
 
Zitat:

Zitat von jbg
Bei so einfachen Beispielen ist die Benutzung von Break sicher nicht begründet. Das break ist eher für eine Schleife, in der mehr als nur eine Anweisung steht gedacht, wobei die restlichen Anweisungen bei einer bestimmten Bedingung nicht mehr ausgeführt und die Schleife verlassen werden soll.

Auch Du hattest keine for - Schleifen mit break abgebrochen. ;-)
Es mag vereinzelt tatsächlich Situationen geben, in denen man aus einer for - Schleife mit break aussteigen muss, aber solche Situationen sind recht selten.

Fast noch seltener sind solche Dinge in einer while - Schleife, da man hier ja die break-bedingung meist noch in die Schleifenbedingung packen kann. Wie gesehen geht das aber auch nicht immer, deswegen braucht man schon solche Abbrüche. Sonst gäbe es das break ja auch nicht.

Was das exit angeht:
gerade bei Sonderbedingungen ist es schon nützlich.

Delphi-Quellcode:
begin
   TuWas;
end;

procedure TuWas;
begin
   // nix zu tun
   if Status in [Sonderfall1, Sonderfall2] then
      exit;

   JetztTuWirklichWas;
end;
Das sollte natürlich nicht in jeder Methode stehen, aber ab und an kann das einem das Leben ganz schön vereinfachen.

Das is allemal besser, als an zig einzelnen Stellen in denen die Methode aufgerufen wird jedesmal eine Abprüfung einzubauen, um den Aufruf zu verhindern.

Robert Marquardt 11. Dez 2003 18:37

Re: Break schlechter Programmierstil?
 
Phoenix, dein Beispiel fuer Exit ist genau das was man nicht tun soll.
In so einer kurzen Funktion ist ein positives if leichter verstaendlich als ein Abweisen mit einer negativen Bedingung.

SirThornberry 11. Dez 2003 18:53

Re: Break schlechter Programmierstil?
 
Wenn das schlechter programmierstil ist mit "break" dann schließ ich daraus das die Jedi-Programmierer schlechte Programmierer sind bzw. einen schlechten Stil haben weil das darin vorkommt.

Da steht in einem beispiel zum beispiel

Delphi-Quellcode:
  if not OpenDialog1.execute then exit; //exit entspricht ja break nur das es nicht für schleifen ist
wobei

Delphi-Quellcode:
  if OpenDialog1.execute then
  begin
    [..]
  end;
viel schöner ist. Find das zwar selbst mit den breaks und exits nicht so schon aber manchmal lässt sichs einfach nicht vermeiden oder es macht ungerechtfertigt viel aufwand es anders zu schreiben was einen dann niemand bezahlen würde...

Robert Marquardt 11. Dez 2003 19:00

Re: Break schlechter Programmierstil?
 
Da hast du ganz recht das die JVCL viel schlechten Code enthaelt.
Ich beschaeftige mich ja auch damit das auszumerzen.
16 Megabyte Sourcen umzugraben dauert aber seine Zeit.
Im Augenblick zentralisiere ich die resourcestrings, dann geht es wieder mit
der Ueberarbeitung des Stils weiter.

Wenn du es bei kurzen Funktionen gleich richtig machst dann dauert es auch nicht laenger als die schlechte Version und beide werden gleich bezahlt.

Duffy 11. Dez 2003 19:13

Re: Break schlechter Programmierstil?
 
Hallo mirage228,
ja, ich dachte immer ein sauberes BASIC "GOTO" sei ein schlechter Programmierstil, weil es Spagetti Code erlaubt. "Break" und "Continue" hingegen erlauben dagegen ein sauberes Verlassen einer "for" oder "while" Schleife und der Compiler streikt, wenn sie außerhalb definierter Befehle verwendet werden.

Na ja, wie dem auch sei, die Entwickler und dein Lehrer werden sich was mit ihrem Handeln und Aussagen gedacht haben.

bye
Claus

Tonic1024 12. Dez 2003 07:40

Re: Break schlechter Programmierstil?
 
Moin...

Ein Argument (vielleicht ist es ja auch keins) fehlt mir hier eigentlich noch...

Ist es nicht so, dass For-Schleifen in Pascal wesentlich performanter sind als While-Schleifen? Berichtigt mich ruhig... Bin immer bereit was zu lernen!

Wenn ich also aus einer langen Liste, Array, etc. das passende Gegenstück raussuchen soll (Klassischer Fall: ID und Bezeichnung) dann mache ich das mit einer For-Schleife aufgrund des definierten Endes im Fehlerfall (Länge des Arrays). Nun ist es aber völliger Unsinn wenn der entsprechende Eintrag gefunden wurde, die Schleife weiterlaufen zu lassen.

Wenn ich das mit einer While-Schleife realisiere muss ich Die Schleife verlassen bei "Found OR End of Array". der Code dafür ist wahrscheinlich länger und nicht so übersichtlich wie bei der For-Schleife...

Aber es ist wohl auch so, dass jeder seinen eigenen Style finden muss und dann versuchen sollte, dass auch andere ihn verstehen.

Bis denne...

[EDIT] Ausserdem sind Lehrer - Informatiklehrer bilden da keine Ausnahme - oft ziemlich rechthaberisch. Egal wie offensichtlich ihr Irrtum ist. Unabhängig von der "Break"-Frage jetzt [/EDIT]

Robert Marquardt 12. Dez 2003 10:17

Re: Break schlechter Programmierstil?
 
Eine for-Schleife ist performanter als eine while-Schleife, da die Endebedingung nur einmal ausgewertet wird.

nailor 12. Dez 2003 17:05

Re: Break schlechter Programmierstil?
 
Zitat:

Zitat von Tonic1024
[EDIT] Ausserdem sind Lehrer - Informatiklehrer bilden da keine Ausnahme - oft ziemlich rechthaberisch. Egal wie offensichtlich ihr Irrtum ist. Unabhängig von der "Break"-Frage jetzt [/EDIT]

lol. stimmt aber im Wesentlichen!

Ich finde for mit break manchmal übersichtlicher, manchmal while. Dann sollte man die übersichtlichere Variante nehmen. Wobei "übersichtlicher" subjektiv sein kann, aber darüber lässt sich streiten.

Manchmal ist auch die eine Lösung viel einfacher zu tippen. Dann soll man halt die nehmen, die einem grade einfällt und nicht die Zeit damit verschwenden, wie die ander Lösung aussähe!

Bei "inner loops" bei nem zeitintensiven Alogo, der die Abbruchbedingung nur selten erfüllt, ist aber die for-Schleife aus Performance-Gründen vorzuziehen. Da hab ich lieber nicht so leserlichen Code, der dafür (im Extremfall) bis zu doppelt so schnell ist.

Die while-Schleifen sind der Wink mit dem Zaunpfahl, wenn man den Code nicht kennt, und sich fragt, ob jetzt z.B. das ganze Array durchgegangen wird. Aber eine for Schleife tuts auch und ist nicht unbedingt schlechter!


Alle Zeitangaben in WEZ +1. Es ist jetzt 21:23 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz