Properties und Validierung

Für Fragen von Einsteigern und Programmieranfängern...
Antworten
BitRausch
Beiträge: 50
Registriert: Di 30. Mai 2017, 09:32

Properties und Validierung

Beitrag von BitRausch »

Hallo zusammen,

ich habe eine reine (OOP Anfänger-) Verständnisfrage:

Bei der Umstellung der Records auf Klassen habe ich auch entsprechende Properties für die Felder mit read write gesetzt.
In meinem ursprünglichen Code hatte ich Funktionen/Prozeduren geschrieben um Feldinhalte zu validieren. Z.B. Ob der Feldinhalt eine bestimmte Länge hat oder eine Zahl oder ein Text ist oder ob das Feld leer ist etc...

Was wäre eigentlich der korrekte Weg die Validierung im OOP Kontext umzusetzen?

z.Zt.:

Code: Alles auswählen

 
type
   TSatz : Class(TObject)
   private
      FFeld1 : String;
      FFeld2 : String;
      ...
   public
      property Feld1 : String read FFeld1 write FFeld1;
      property Feld2 : String read FFeld2 write FFeld2;
   ...
  end;
 
 
function isValidFeld1(AFeld : String) : Boolean;
begin
    // Validierung für Feld1
end;
 
function isValidFeld2(AFeld : String) : Boolean;
begin
    // Validierung für Feld2
end;
 
 
wäre das hier der richtige Weg?
 
type
   TSatz : Class(TObject)
   private
      FFeld1 : String;
      FFeld2 : String;
      ...
      function isValid(AFeld : String); override;
   protected
      function SetFeld1(AFeld1 : String);
      function SetFedl2(AFeld2 : String);
   public
      property Feld1 : String read FFeld1 write SetFeld1;
      property Feld2 : String read FFeld2 write SetFeld2;
   ...
  end;
 
 
function TSatz.isValid(AFeld1 : String) : Boolean;
begin
    // Validierung für Feld1 auf Text
end;
 
function TSatz.isValid(AFeld2 : String) : Boolean;
begin
    // Validierung für Feld2 auf Zahl im Text
end;
 
 
function TSatz.isValid(AFeld2 : String) : Boolean;
begin
    // Validierung für Feld2
end;
 
function TSatz.SetFeld1(AFeld1 : String) : String;
begin
   if isValid(AFeld1) then           
     Result := AString
  else
  begin
     InLogSchreiben('Fehler in Feld 1');
     Result :='';
  end;
end
 
function TSatz.SetFeld2(AFeld2 : String) : String;
begin
   if isValid(AFeld2) then    //Zahl im String
     Result := AString
  else
  begin
     InLogSchreiben('Fehler in Feld 2');
     Result :='0';
  end;
end
 
 


Hintergrund der Frage ist auch das ich immer wiederkehrende Validierungen habe für verschiedene Felder...
oder sollten diese Prüfungen außerhalb der Klasse stehen?

Gruß

wp_xyz
Beiträge: 4869
Registriert: Fr 8. Apr 2011, 09:01

Re: Properties und Validierung

Beitrag von wp_xyz »

So kannst du's natürlich machen. Aber ich finde es ungeschickt, in den Settern einen Log-Eintrag zu machen, denn dadurch machst du die Klasse abhängig von einem irgendwie gearteten Logging-Mechanismus. Ich würde stattdessen in den Settern nur die Notbremse ziehen und bei einem ungültigen Eintrag eine Exception erzeugen. Diese kannst du ja weiter außen, z.B. im Eingabe-Formular, abfangen und stattdessen einen Log-Eintrag erzeugen.

BitRausch
Beiträge: 50
Registriert: Di 30. Mai 2017, 09:32

Re: Properties und Validierung

Beitrag von BitRausch »

hmm - "ungeschickt" passt zu meinem Stiel :lol:

Mit Exception meinst Du sowas wie eine Error Variable die ich in der Klasse definiere und bei Fehler setze?

wp_xyz
Beiträge: 4869
Registriert: Fr 8. Apr 2011, 09:01

Re: Properties und Validierung

Beitrag von wp_xyz »

BitRausch hat geschrieben:Mit Exception meinst Du sowas wie eine Error Variable die ich in der Klasse definiere und bei Fehler setze?

Nein, das ist ein in die Sprache eingebauter Fehlerbehandlungsmechanismus: z.B. https://de.wikibooks.org/wiki/Programmi ... Exceptions

Da bei einer Exception aber immer das Programm angehalten wird, wenn es in der IDE läuft, finde ich Exceptions nur als Notbremse sinnvoll. Um einfache Eingabefehler z.B. in einem Formular abzufangen, würde ich, anders als oben geschrieben, die Prüfung ins Formular verlagern und dort auch unmittelbar reagieren.

Code: Alles auswählen

function TSatz.IsValid(AFeld: String; out AMsg: String): Boolean;
begin
  if AFeld = '' then begin
    AMsg := 'Leereingabe nicht erlaubt.';
    Result := false;
  end else
    Result := true;
end;
 
procedure TSatz.SetFeld1(AValue: String);
// Nur für den Fall, dass sich hier ein falscher Wert einmogeln würde
var
  msg: String;
begin
  if not IsValid(AValue, msg) then
    raise Exception.Create('Fehler in TSatz.Feld1: '+ msg);
  FFeld1 := AValue;
end;
 
procedure TEingabeFormular.OKButtonClick(Sender: TObject);
var
  msg: String;
begin
  if not Satz.IsValid(Edit1.Text, msg) then begin
    Edit1.SetFocus;
    ShowMessage('Fehler: ' + msg);
    Modalresult := mrNone;   // das verhindert das Schließen des Formulars.
  end;
end;
 
procedure TEingabeFormular.Speichern;
begin
  Satz.Feld1 := Edit1.Text
  // Falls Edit1.Text leer ist, wird hier eine Exception ausgelöst:
  // --> Es wird die Meldung der Exception angezeigt, und der folgende Code wird nicht ausgeführt
  Satz.Feld2 := ...
  Satz.Save;
 
  // Falls du mit dem Text der Meldung nicht einverstanden bist, kannst du auch mit try-except the Exception abfangen.
  // Statt obigem Code wäre das dann:
  try
    Satz.Feld1 := Edit1.Text;
    Satz.Feld2 := ...
    Satz.Save;
  except
    on E:Exception do ShowMessage('Die Eingabe kann nicht gespeichert werden: ' + E.Message);
  end;
end;
 

BitRausch
Beiträge: 50
Registriert: Di 30. Mai 2017, 09:32

Re: Properties und Validierung

Beitrag von BitRausch »

Ahh :idea: - ok - das habe ich verstanden. Das man selbst Exceptions generieren kann kannte ich so noch nicht...

Ich denke das dieser Abschnitt meinen Anforderungen am nächsten kommt.

Code: Alles auswählen

 
procedure TSatz.SetFeld1(AValue: String);
// Nur für den Fall, dass sich hier ein falscher Wert einmogeln würde
var
  msg: String;
begin
  if not IsValid(AValue, msg) then
    raise Exception.Create('Fehler in TSatz.Feld1: '+ msg);
  FFeld1 := AValue;
end;
 


Der Grund ist das ich so gut wie keine Eingabevalidierung habe da die Felder aus einer CSV Datei gelesen werden und schon beim einlesen geprüft werden und bei Fehler eine entsprechende Fehlermeldung in einer Logdatei geschrieben werden.
Je nach Fehlersituation wird das weitere einlesen der Datensätze abgebrochen (z.B. wenn der Datensatz nicht vollständig ist) oder es werden "nur" Meldungen ins Log geschrieben..
Zur Zeit habe ich (sehr Old-School) globale Variablen für Fehler definiert die ich im Programm setze bzw. abfrage...
Auf jeden Fall werde ich ich mal das Thema Exceptions noch mal sehr genau anschauen...

Vielen Dank wp_xyz!! :D

Antworten