AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Schutzblöcke überflüssig!?

Ein Thema von stahli · begonnen am 30. Sep 2020 · letzter Beitrag vom 1. Okt 2020
Antwort Antwort
Seite 1 von 3  1 23      
Benutzerbild von stahli
stahli

Registriert seit: 26. Nov 2003
Ort: Halle/Saale
4.358 Beiträge
 
Delphi 11 Alexandria
 
#1

AW: Schutzblöcke überflüssig!?

  Alt 30. Sep 2020, 17:47
@Delphi.Narium

Wollen wir anhand Deines Beispiels mal weiter diskutieren?
Die Argumentation finde ich nämlich ganz passend. Vielleicht können wir ja irgendetwas draus ziehen...

Also das Beispiel mit dem Auto passt nicht ganz zu meinem Thema. Im Falle eines Unfalles helfen Gurt und Airbag, die Folgen zu mildern.
Bei der Software kann man die Analogie vielleicht bei einer Fehlerbeseitigung ziehen.
Die Funktion wird abgebrochen, der Speicherbereich wird aufgeräumt, der Anwender erhält eine Nachricht und kann mit einem konsistenten Datenbestand weiter arbeiten.
Soweit alles ok.


Was ich nicht nachvollziehen kann, ist folgendes:

Der wissenschaftliche Beweis, dass man fehlerfreie Software schreiben kann, steht noch aus.

Und solange bleiben bei mir die Schutzblöcke drin.

...

Bei jedem Objekt, dass ich erstelle, besteht die (theoretische) Möglichkeit, dass die Erstellung scheitert. Also muss das abgesichert werden. Und, egal welcher (erwartete oder unerwartete) Fehler auftritt, es spricht nichts dagegen, vorsorglich ein gesichertes Aufräumen zu implementieren.

Am schlechtesten sind die Fehler zu finden, die bei der unstrukturierten Behandlung von Fehlern in der Fehlerbehandlung auftreten, die nur deshalb passieren, weil man an der fehlerverursachenden Stelle vergaß (oder es fahrlässig für überflüssig hielt) für eine geordnete Weiterverarbeitung im Programm zu sorgen.

...

Schutzblöcke gehören da selbstverständlich zu.

Nehmen wir noch ein konkretes Beispiel:

Wir erzeugen zwei Personenobjekte und überweisen einen Betrag.

Delphi-Quellcode:
procedure Überweisung;
begin
  Person1 := TPerson.Create;
  Person1.LoadFromDB;
  Person2 := TPerson.Create;
  Person2.LoadFromDB;
  Person1.Überweise(Person2, 100);
  Person1.SaveToDB;
  Person2.SaveToDB;
  Person1.Free;
  Person2.Free;
end;
Hier können jetzt diverse Probleme auftreten.
Wenn man die zwei Free-Anweisungen jetzt in einen Finally-Block setzt - ohne sonstige Fehlerbehandlung - findest Du weder den Fehler besser noch ist Dein Datenbestand besser geschützt noch erhält der Anwender bessere Fehlerinformationen.
Nur der Speicherplatz der zwei Objekte wird wieder freigegeben. Der Aufrufer der Prozedur Überweisung weiß nichts von dem Fehler und das Programm geht davon aus, dass alles passt.

Ob die Überweisung in der Datenbank realisiert wurde oder nicht, kann Dein Programm nicht nachvollziehen und der Anwender schon gar nicht.

Dass der Speicherplatz der zwei Objekte freigegeben wurde hilft auch niemandem - jedenfalls sehe ich dafür keinen sachlichen Grund.

Noch einmal: Eine Fehlerbehandlung und Benachrichtigung im Sinne "Überweisung ist fehlgeschlagen - bitte wiederholen! Der bisherige Datenbestand wurde nicht beeinträchtigt!" ist völlig korrekt. In dem Zusammenhang natürlich auch die Freigabe der erzeugten Objekte.


Aber alle Objektfreigaben in Schutzblöcke zu kapseln, ohne eine wirkliche Fehlerbehandlung zu realisieren - das halte ich für überflüssig.
Und oft wird ja so argumentiert, dass Objekte immer in Schutzblöcke gehören.

Ich sehe dafür einfach keinen sachlichen Grund.


@freimatz

Wenn man das so gewöhnt ist und machen möchte - ok.
Einen Nutzen sehe ich darin aber nicht (und habe auch noch kein überzeugendes Argument gehört).
Stahli
http://www.StahliSoft.de
---
"Jetzt muss ich seh´n, dass ich kein Denkfehler mach...!?" Dittsche (2004)
  Mit Zitat antworten Zitat
Delphi.Narium

Registriert seit: 27. Nov 2017
2.598 Beiträge
 
Delphi 7 Professional
 
#2

AW: Schutzblöcke überflüssig!?

  Alt 30. Sep 2020, 18:26
Hoffentlich hab' ich Dich nicht falsch verstanden.

Deine Argumentation klingt im Moment für mich in etwa so (sehr grob formuliert):

Wenn ich keine vernüftige Fehlerbehandlung habe, kann ich mir im Fehlerfalle auch die Freigabe von Objekten sparen.

Die Prozeduren bei Dir wären bei mir schonmal Funktionen, die im Erfolgsfalle ein True zurückgeben, im Fehlerfalle ein False. Wenn die erste Funktion fehlschlägt, wird die zweite nicht mehr ausgeführt. Welchen Sinn hätte es denn, wenn eine der beiden Personen nicht aus der DB geladen werden könnte, die Überweisung durchzuführen? Und dann das Ergebnis auch noch speichern?

Meiner Meinung nach ist Dein Beispiel schon logisch grob falsch, von daher halte ich anhand eines derartigen Beispiels eine Diskussion über die Sinnhaftigkeit von Schutzblöcken für nicht angebracht.

Oder mal wieder sehr dreist formuliert:

Wer so schlecht programmiert, kann sich auch Schutzblöcke sparen, die machen den Kohl dann auch nicht mehr fett.


Zitat von freimatz:
... aber sie bekommen (zumindest bei mir) dafür Minuspunkte sollten sie sich um einen Job bewerben.
Da würd' ich noch etwas weiter gehen: Hätten bei mir keine Chance, einen Job zu bekommen.

PS:

Das Autothema passt sehr gut.

Du argumentierst
Zitat:
Also das Beispiel mit dem Auto passt nicht ganz zu meinem Thema.
nämlich in der Begründung für das Nichtpassen im Zusammenhang mit Schutzblöcken, durch die Einführung von Schutzblöcken,
Zitat:
Im Falle eines Unfalles helfen Gurt und Airbag, die Folgen zu mildern.
dass es nicht passt.

Durch die Einführung dessen, dessen Nutzen Du bezweifelts, widerlegst Du ein Beispiel für den Sinn dessen, was Du bezweifelts?

Ehrlich gesagt: Auf so eine Diskussion hab' ich keine Lust.
  Mit Zitat antworten Zitat
Benutzerbild von stahli
stahli

Registriert seit: 26. Nov 2003
Ort: Halle/Saale
4.358 Beiträge
 
Delphi 11 Alexandria
 
#3

AW: Schutzblöcke überflüssig!?

  Alt 30. Sep 2020, 18:44
Deine Argumentation klingt im Moment für mich in etwa so (sehr grob formuliert):

Wenn ich keine vernüftige Fehlerbehandlung habe, kann ich mir im Fehlerfalle auch die Freigabe von Objekten sparen.

Die Prozeduren bei Dir wären bei mir schonmal Funktionen, die im Erfolgsfalle ein True zurückgeben, im Fehlerfalle ein False. Wenn die erste Funktion fehlschlägt, wird die zweite nicht mehr ausgeführt. Welchen Sinn hätte es denn, wenn eine der beiden Personen nicht aus der DB geladen werden könnte, die Überweisung durchzuführen? Und dann das Ergebnis auch noch speichern?

Meiner Meinung nach ist Dein Beispiel schon logisch grob falsch, von daher halte ich anhand eines derartigen Beispiels eine Diskussion über die Sinnhaftigkeit von Schutzblöcken für nicht angebracht.

...

Ehrlich gesagt: Auf so eine Diskussion hab' ich keine Lust.
Einmal kurz antworten will ich dennoch.

Wenn man (in möglichen Fehlerfällen) Rückgabewerte nutzt und den Programmablauf entsprechend steuert, ist das völlig in Ordnung (das Beispiel hatte ich ich auch gebracht). Das ist auch nicht der Ansatz, den ich kritisiert habe.

Ohne Fehlerbehandlung ist die Freigabe von Objekten im Fehlerfall nebensächlich - genau das UND NUR DAS meine ich.
Stahli
http://www.StahliSoft.de
---
"Jetzt muss ich seh´n, dass ich kein Denkfehler mach...!?" Dittsche (2004)
  Mit Zitat antworten Zitat
Delphi.Narium

Registriert seit: 27. Nov 2017
2.598 Beiträge
 
Delphi 7 Professional
 
#4

AW: Schutzblöcke überflüssig!?

  Alt 30. Sep 2020, 18:55
Zitat von stahli:
Ohne Fehlerbehandlung ist die Freigabe von Objekten im Fehlerfall nebensächlich - genau das UND NUR DAS meine ich.
deckt sich mit dem
Zitat von Delphi.Narium:
Wer so schlecht programmiert, kann sich auch Schutzblöcke sparen, die machen den Kohl dann auch nicht mehr fett.
Aber ehrlich: Ist eine Diskussion darüber, ob man bei schlechter bzw. fehlerhafter Programmierung Schutzblöcke nutzen soll oder nicht, wirklich zielführend?
  Mit Zitat antworten Zitat
Benutzerbild von jaenicke
jaenicke

Registriert seit: 10. Jun 2003
Ort: Berlin
10.055 Beiträge
 
Delphi 12 Athens
 
#5

AW: Schutzblöcke überflüssig!?

  Alt 30. Sep 2020, 19:36
Hier können jetzt diverse Probleme auftreten.
Wenn man die zwei Free-Anweisungen jetzt in einen Finally-Block setzt - ohne sonstige Fehlerbehandlung - findest Du weder den Fehler besser noch ist Dein Datenbestand besser geschützt noch erhält der Anwender bessere Fehlerinformationen.
Nur der Speicherplatz der zwei Objekte wird wieder freigegeben. Der Aufrufer der Prozedur Überweisung weiß nichts von dem Fehler und das Programm geht davon aus, dass alles passt.
Doch, denn es geht ja um den Fall, dass eine Exception ausgelöst wird, so dass die Freigabe des Objekts übersprungen würde, weil man bei der Exception heraus springt. Dann kann die Exception zwar abgefangen werden, aber der Speicher wird nicht freigegeben.

Und nun nehmen wir mal an der Code wird in einem Programm immer wieder aufgerufen, das länger läuft, z.B. ein Webservice... da ist dann irgendwann trotz sauberer Behandlung der Exceptions der Speicher voll.

Wenn es nur um wenige Aufrufe geht, merkt man in der Tat nicht viel davon. Aber das Programm benutzt eben mehr Speicher als nötig.

Noch schlechter wird es, wenn man in dem Objekt ein Handle auf eine Datei offen hat oder ähnliches, so dass die Datei dann gesperrt bleibt bis das Programm beendet wird.

Und damit man das nicht immer neu bewerten muss, macht es Sinn einfach immer eine korrekte Behandlung solcher potentiellen Probleme einzubauen. Denn sonst müsstest du ja bei jeder Änderung schauen, ob deine Prozedur nicht irgendwo aufgerufen wird, wo dann eine Behandlung nötig wird...

Davon abgesehen bringt ein Ressourcenschutzblock nur etwas, wenn er auch korrekt aufgebaut ist (Konstruktoraufruf vor dem try, sonst springt man bei einer Exception im Konstruktor auch in das finally obwohl die Variable noch gar nicht zugewiesen ist und dann knallt es ggf. dort erneut):
Delphi-Quellcode:
procedure Run;
begin
  obj1 := TObject.Create;
  try
    Beep;
    obj2 := TObject.Create;
    try
      obj3 := TObject.Create;
      try
        Beep;
      finally
        obj3.Free;
      end;
    finally
      obj2.Free;
    end;
  finally
    obj1.Free;
  end;
end;

try
  Run;
except
  on E: Exception do
  begin
    WriteLog(E);
    UserDialog(Format('Interner Fehler: %s - %s', [E.ClassName, E.Message]));
  end;
end;
Sebastian Jänicke
AppCentral
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.555 Beiträge
 
Delphi 12 Athens
 
#6

AW: Schutzblöcke überflüssig!?

  Alt 30. Sep 2020, 20:03
Konstruktoraufruf vor dem try, sonst springt man bei einer Exception im Konstruktor auch in das finally obwohl die Variable noch gar nicht zugewiesen ist und dann knallt es ggf. dort erneut
Man könnte jetzt zwar denken
"ist doch nicht so schlimm, wenn es nochmal knallt ... der Nutzer bekommt ja dennoch nur einen Fehler zu sehen"
aber das stimmt nicht, denn er und ein eventuelles Logging bekommt nur den letzten Fehler zu sehen und die "eigentliche" Fehlermeldung und Position ist dann weg, was echt blöd für die Fehlersuche ist.
Das ist genauso schlimm, wie wenn man im Except den Fehler abfängt und den Fehlertext durch einen sinnlosen und nichtssagenden Text ersetzt.

Und da die Vairale nicht initialisiert ist, kann sie sonstwo hinzeigen,
wodurch dann das Free nochmal richtig was im Speicher zerstören kann, und somit die Funktion seines Programm dann richtig schädigen würde.
Ein Therapeut entspricht 1024 Gigapeut.
  Mit Zitat antworten Zitat
Benutzerbild von stahli
stahli

Registriert seit: 26. Nov 2003
Ort: Halle/Saale
4.358 Beiträge
 
Delphi 11 Alexandria
 
#7

AW: Schutzblöcke überflüssig!?

  Alt 30. Sep 2020, 20:16
Ja, danke Sebastian.

Deinen Text kann ich nachvollziehen und da gehe ich auch weitestgehend mit.
Dein Beispiel ist grundsätzlich auch in Ordnung, da Du eine Exception auswertest und darauf reagierst.

Oft sieht man aber Beispiele wie Dein "Run" alleinstehend, wo die Objekte wieder freigegeben werden und keine Fehlerbehandlung ersichtlich ist.
Das finde ich dann halt unsinnig.


Folgenden Punkt Deiner Ausführungen sehe ich aber dann doch anders:

Und damit man das nicht immer neu bewerten muss, macht es Sinn einfach immer eine korrekte Behandlung solcher potentiellen Probleme einzubauen. Denn sonst müsstest du ja bei jeder Änderung schauen, ob deine Prozedur nicht irgendwo aufgerufen wird, wo dann eine Behandlung nötig wird...
Ich finde den Ansatz sinnvoller, mich dabei auf die potenziell problematischen Stellen zu beschränken.
Entweder weiß ich von vorn herein, dass an bestimmten Stellen ein Exception-Problem auftreten kann, das berücksichtigt werden muss oder ich merke es bei der Entwicklung bzw. in einer Testphase.
Wenn ich 1000 Stellen im Code mit Schutzblöcken absichere und nur eine ein wirkliches Risiko beinhaltet, dann finde ich den Aufwand einfach nicht zu rechtfertigen (zumal der Code auch schlechter wartbar wird).

Wenn das mögliche Problem in Deinem Beispiel nicht vermeidbar ist (z.B. Netzkabel gezogen) und Deine Exceptionbehandlung das Problem vollständig löst, so dass das Programm korrekt mit konsistenten Daten weiter arbeitet, dann ist die Lösung absolut sinnvoll.
Eine Datenbereinigung ist dort jedoch auch nicht skizziert, sondern nur ein Log und eine Infobox.

Wenn KEINE ausdrückliche Datenbereinigung erfolgt, dann muss vor einer Fortsetzung der Arbeit erst mal der Datenbestand gesichert/geprüft und der Fehler in der Software schnell bereinigt werden.
In dem Moment komme ich wieder zu dem Schluss, dass die finallys in dem Run völlig verzichtbar sind:

Dein Code wäre dann m.E. gleichwertig zu folgendem:

Delphi-Quellcode:
procedure Run;
begin
  obj1 := TObject.Create;
  Beep;
  obj2 := TObject.Create;
  obj3 := TObject.Create;
  Beep;
  obj3.Free;
  obj2.Free;
  obj1.Free;
end;

try
  Run;
except
  on E: Exception do
  begin
    // VollständigeDatenprüfungUndBereinigung;
    WriteLog(E);
    UserDialog(Format('Interner Fehler: %s - %s', [E.ClassName, E.Message]));
  end;
end;
Hier mal angenommen, der Fehler wäre nicht komplett ausgebügelt und der Datenbestand möglicherweise inkonsistent.
In beiden Fällen erhalten wir eine Info und einen Log aber wir wüssten nicht, was nun mit den Daten ist.
Der Fehler müsste bereinigt werden und das Programm ein Update erhalten.
Eine Weiterarbeit wäre dem Anwender nicht zu empfehlen, weil wir nichts über den Datenbestand sagen können.
Die verkürzte Run-Prozedur hätte keine wirklichen Nachteile gegenüber Deiner. Ok, da dümpeln noch 1 - 3 Speicherbereiche im Speicher rum, aber das Programm muss ja sowiso beendet werden.

Wenn da natürlich die VollständigeDatenprüfungUndBereinigung eingebaut wäre, dann wäre Deine Lösung perfekt und absolut richtig.


Fazit:
- Exceptionbehandlung mit Datenbereinigung -> Object.Free im Finally sinnvoll
- keine Exceptionbehandlung mit vollständiger Datenbereinigung -> Object.Free im Finally nicht hilfreich

Und vollständige Datenbereinigung bei möglichen Fehlern kann man nur bei erwarteten bzw. denkbaren Fehlern durchführen.
Stahli
http://www.StahliSoft.de
---
"Jetzt muss ich seh´n, dass ich kein Denkfehler mach...!?" Dittsche (2004)

Geändert von stahli (30. Sep 2020 um 20:27 Uhr)
  Mit Zitat antworten Zitat
freimatz

Registriert seit: 20. Mai 2010
1.513 Beiträge
 
Delphi 11 Alexandria
 
#8

AW: Schutzblöcke überflüssig!?

  Alt 30. Sep 2020, 20:53
Entweder weiß ich von vorn herein, dass an bestimmten Stellen ein Exception-Problem auftreten kann, das berücksichtigt werden muss oder ich merke es bei der Entwicklung bzw. in einer Testphase.
Da fallen mir nun wirklich nur ironische Kommentare ein.

Wenn ich 1000 Stellen im Code mit Schutzblöcken absichere und nur eine ein wirkliches Risiko beinhaltet, dann finde ich den Aufwand einfach nicht zu rechtfertigen (zumal der Code auch schlechter wartbar wird).
Wenn dem so wäre ja. Aber es ist nicht so. Es sind nicht 1000.
Ein Block ist in 5 Sekunden gemacht. Die Fehler oder Memory-Leak suchen, weil irgendein so ein mal gemeint hat auf einem Block verzichten zu können oder es vergessen hat, dauert teilweise Tage.
  Mit Zitat antworten Zitat
Delphi.Narium

Registriert seit: 27. Nov 2017
2.598 Beiträge
 
Delphi 7 Professional
 
#9

AW: Schutzblöcke überflüssig!?

  Alt 30. Sep 2020, 21:13
Entweder weiß ich von vorn herein, dass an bestimmten Stellen ein Exception-Problem auftreten kann, das berücksichtigt werden muss oder ich merke es bei der Entwicklung bzw. in einer Testphase.
Da fallen mir nun wirklich nur ironische Kommentare ein.
Habe schon viele Tester erlebt, richtig gute, die fanden Logikfehler durch passende Testdaten, auf die weder die Analysten noch die Entwickler je kamen.

Aber das die irgendwann mal ein Speicherleck gefunden haben, hab' ich nie erlebt.
  Mit Zitat antworten Zitat
Benutzerbild von stahli
stahli

Registriert seit: 26. Nov 2003
Ort: Halle/Saale
4.358 Beiträge
 
Delphi 11 Alexandria
 
#10

AW: Schutzblöcke überflüssig!?

  Alt 30. Sep 2020, 21:29
Da fallen mir nun wirklich nur ironische Kommentare ein.
Bitte bleib sachlich.

Wenn man z.B. mit Netzwerkverbindungen arbeitet muss man immer mit Abbrüchen rechnen und darauf reagieren.
An anderen Stellen wird aber doch mit getesteten Klassen und Bedingungen gearbeitet, wo keine Exceptions zu erwarten sind.
Wenn irgendwann doch Probleme erkannt werden, muss man eben doch nachbessern.

Das gehört für mich zu ordentlichen Tests.


Ein Block ist in 5 Sekunden gemacht. Die Fehler oder Memory-Leak suchen, weil irgendein so ein mal gemeint hat auf einem Block verzichten zu können oder es vergessen hat, dauert teilweise Tage.
Ich sage ja nicht, dass Speicher nicht freigegeben werden soll. Im Falle dass "ES KNALLT" (man also einen schwerwiegenden Fehler hat, das Programm nicht mehr sauber funktioniert und beendet werden sollte und die (gespeicherten) Daten möglicherweise sogar kaputt sind) ist es wurscht, ob vor dem Crash Speicher von 3 Objekten freigegeben wurde oder nicht.
Wenn es ordentlich gerumst hat wirst Du bestimmt nicht schauen, ob der Speicher zuvor korrekt aufgeräumt wurde.
Du musst den Fehler finden und das Programm sowie die Daten bereinigen.

Wenn das Programm korrekt läuft, werden alle Free ausgeführt und es gibt kein Speicherleck.
Nur wenn es unerwartet Knallt, würde ein solches entstehen - aber dann hat man sowieso deutlich größere Probleme.
Mit einer Problemlösung ist auch das Speicherleck automatisch wieder vom Tisch.


Ich verstehe nicht, dass Du (weitestgehenden) Verzicht auf Schutzblöcke mit Gleichgültigkeit gegenüber Speicherlecks gleichsetzt.
Das hat doch gar nichts miteinander zu tun.
Stahli
http://www.StahliSoft.de
---
"Jetzt muss ich seh´n, dass ich kein Denkfehler mach...!?" Dittsche (2004)
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 3  1 23      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 01:47 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