![]() |
sicherere Klassen?
Zuersteinmal: diese Idee hab ich mir quasi vom .Free abgeguckt :nerd:
Spricht eigentlich etwas dagegen Klasseninstanzen, welche auf NIL stehen, teilweise auch mal mit zu behandeln und das Programm nicht immer gleich in Exceptions laufen zu lassen? Zitat:
wo man z.B. N:=XML.Node[...].Node[...]; aufrufen könnte und wenn nun das erste Node nicht existiert und auch kein xoNodeAutoCreate definiert ist, dann würde dort NIL zurückgegeben und somit eine Exception ausgelöst. Wenn jetzt das NIL aber mindestens bei "wichtigen" Leseoperationen ausgewertet würde, dann käme hierbei nicht zu einer Exception. Nun die Frage: Wäre soein Verhalten hinnehmbar, oder sollte man es lieber beim alten/normalen Verhalten (mit Exception) belassen? (es geht hier um billige Objekte und nicht um Interfaces oder so) |
Re: sicherere Klassen?
Eine erste Sicherheitsmassnahme wäre:
Delphi-Quellcode:
Die Assertion gibt einen wichtigen Hinweis zur Fehlersuche;
function TXMLNode.Irgendwas:TDatentyp;
begin Assert(Assigned(self), 'TXMLNode.Irgendwas'); ... end; auch dann wenn kein Debugger verfügbar ist. Man kann auch dafür sorgen, dass es keine NIL-Objekte gibt indem man immer eine Instanz erzeugt. Jedes grössere Programm braucht eine Log-Ausgabe, die aber abschaltbar sein sollte. Im ganzen Programm finden sich dann solche Zeilen:
Delphi-Quellcode:
Anstatt nun überall zu prüfen, ob es das LogObjekt gibt, erzeugt man
if Assigned(LogObj) then
LogObj.WriteMessage('irgendwas'); grundsätzlich ein LogObjekt einer speziellen Klasse. Es gibt dann die Klasse TCustomLogger und davon abgeleitet TFileLogger und TNullLogger.
Delphi-Quellcode:
Jetzt kann man gefahrlos alle Methoden des LogObjekts aufrufen,
if ParamStr(1)='/nolog' then
LogObj := TNullLogger.Create else LogObj := TFileLogger.Create(dateiname_logfile); weil sichergestellt ist, dass immer ein gültiges Objekt erzeugt wurde. Dieses ![]() sich auch auf XMLNode Objekte übertragen. |
Re: sicherere Klassen?
Sowas wie mit dem Null-Objekt wollte ich nicht einführen, denn dann geht sowas wie Assigned (beim Anwender) nicht mehr.
Aber das mit den Assertions werde ich zumindestens implementieren und die Properties ohne Getter werde ich nur im Fall von aktiven Assertions umleiten. :) |
Re: sicherere Klassen?
Die Frage ist ja, was erwartet man, wenn man auf ein Element zugreift, welches es garnicht gibt?
Bei deinem Beispiel zumindest würde ja eigentlich schon beim Getter der Property Nodes ein Index out of bounds erwarten, wenn ich dort auf eine Node zugreifen möchte, die es nicht gibt. Wird über eine anderen Parameter darauf zugegriffen (hab deine Xml Implementierung nicht im Kopf) müsste man sich fragen: gibt es use cases, wo ich als Ergebnis nil zurückbekommen möchte (mit der Aussage, die node gibt es nicht) oder einen Fehler und ich muss vorher überprüfen, ob es eine bestimmte Node gibt. Wenn du allerdings eine Implementierung wie bei TObject.Free benutzt, kann es sein, dass sich die Fehler nur verschieben, Beispiel:
Delphi-Quellcode:
Angenommen der Setter von Value hat so einen Mechanismus, dann gibt es hier keine Zugriffverletzung, aber es wird einfach nix gemacht und an einer anderen Stelle krachts evtl oder es gibt einen Datenverlust.
N:=XML.Node[...].Node[...];
N.Value := 'my new node'; |
Re: sicherere Klassen?
Wenn ich jetzt das NIL beachte und bei Lesezugriffen entsprechend behandle, dann würde hier
N:=XML.Node[...].Node[...]; (den ersten Node gibt es schon nicht) das NIL durch das zweite Node durchgereicht und man könnte sowas machen
Delphi-Quellcode:
es würde also praktisch diesem entsprechen
N := XML.Node['...'].Node['...'];
if not Assigned(N) then ERROR;
Delphi-Quellcode:
N := XML.Node['...\...'];
if not Assigned(N) then ERROR; Gut, jetzt hatte ich mich erstmal entschieden intern Asserts einzuführen und wenn sozusagen das zweite Node aufgerufen würde, dann wäre dort ja vom Ersten das NIL als eingang und würde dann eine EAssert auslösen, wenn assertions aktiviert sind, ansonsten würde sich dann eventuell irgendeine Folgeexteption bemerkbar machen ... meißt wohl "Zugriffverlezung bei Ardresse $000000xx" oder so. Statt dem NIL als Result immer gleich mit einer Exception um mich zu werfen halte ich nun auch nicht immer für sonderlich angebracht. :gruebel: |
Re: sicherere Klassen?
Ich formuliere es mal ein wenig provokant, weil ich es selber bei selbgeschriebenen Komponenten so handhabe.
Bei Settern prüfen ich die übergebenen Werte nur auf formale Korrektheit und werfe ggf. mit Fehlern um mich. Wenn ein Getter oder Setter auf nich initialisierte Properties zugreifen soll, dann lasse ich es ruhig krachen. Es ist nich mein Job, die Faulheit/Schlampigkeit des anderen Programmierers abzufangen. 8-) Abgesehen davon erwarte ich von Programmierern, dass sie ihre Sachen testen, bevor sie sie auf die Menschheit loslassen. Und spätestens beim testen sollten solche Schludrigkeiten auffallen. |
Re: sicherere Klassen?
Das sehe ich ähnlich. Die Kunst ist allerdings, die Fehlermeldungen so zu formulieren, dass sie auch auf den tatsächlichen Fehler hindeuten. Ich sehe öfter mal so etwas(fiktives Beispiel):
Delphi-Quellcode:
Das finde ich nicht sonderlich informativ, gerade wenn das an mehreren Stellen so gehandhabt wird.
try
DoSomething; except MessageBox(0,'Something went wrong',nil,0); end; |
Alle Zeitangaben in WEZ +1. Es ist jetzt 14:52 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