Gibt es eine Best Practice-Methode zur Validierung von Benutzereingaben ?
Tatsächliches Problem:
Ein Benutzer gibt bestimmte Eingaben in einem Fenster. Wenn er mit diesen Eingaben fertig ist, kann er auf "Erstellen" klicken. Nun sollte eine Popup-Nachricht mit allen ungültigen Eingaben angezeigt werden. Wenn keine ungültige Eingabe, dann einfach weiter.
Ich könnte das leicht in der Form-Klasse machen. Aber ich erinnere mich an eine Best-Practice-Methode zur Validierung der Eingabe in den Eigenschaften des Sets. Problem ist, dass ich bereits eine Instanz dieser Klasse erstellt habe (oder sonst, kann keine Eigenschaften festlegen;)) wenn ich diesen Weg validiere. Das sollte nicht passieren, es darf keine Instanz der Klasse erstellt werden, es sei denn, die Eingabe ist gültig.
Ich wollte eine ErrorMessages-Klasse erstellen, die eine Liste enthält, in die ich alle errorMessages schreiben kann. Jedes Mal, wenn eine ungültige Eingabe erfolgt, wird eine neue Nachricht zur Liste errorMessages hinzugefügt. Wenn der Benutzer auf "Erstellen" klickt, werden alle Nachrichten in der Liste angezeigt. Ist das ein guter Umgang mit den Dingen?
Gibt es einen Best-Practice-Weg? Irgendwelche Entwurfsmuster, die eine solche Lösung bieten?
Bearbeiten: Dies ist eine Schulaufgabe. Also mit unlogischen Anforderungen. Ich muss alle ungültigen Eingaben anzeigen, wenn ich auf "Erstellen" klicke. Ich würde das gerne aus der Form Klasse heraus machen. (Die Validierung funktioniert also auch ohne GUI, ich habe noch nicht einmal die GUI erstellt). Stellen Sie zuerst sicher, dass meine Funktionalität korrekt funktioniert;). Ich möchte meinen Code sauber, abstrakt und OOP behalten. Also, wie soll ich meine Fehlermeldungen zeigen?
Ich wollte eine ErrorMessages-Klasse erstellen, die eine Liste enthält, in die ich alle errorMessages schreiben kann. Jedes Mal, wenn eine ungültige Eingabe erfolgt, wird eine neue Nachricht zur Liste errorMessages hinzugefügt. Wenn der Benutzer auf "Erstellen" klickt, werden alle Nachrichten in der Liste angezeigt. Ist das ein guter Umgang mit den Dingen?
Ich denke, subjektiv wäre es besser, sofortige Rückmeldung zu geben, dass der vom Benutzer eingegebene Wert ungültig ist. Auf diese Weise können sie sofort zurückgehen und es reparieren.
Ich meine, darüber nachdenken. Der Ansatz, den Sie vorschlagen, würde ihnen buchstäblich eine riesige Liste von Problemen am Ende geben, die nicht sehr benutzerfreundlich ist. Außerdem, wie werden sie sich an all diese Probleme erinnern, um zurückgehen zu können und sie einzeln zu reparieren? (Hinweis: Sie sind nicht.)
Stattdessen empfehle ich, die ErrorProvider
-Klasse zu verwenden Zeigen Sie alle Fehler direkt neben dem entsprechenden Steuerelement an. Ich habe in meiner Antwort ein wenig mehr über diesen Ansatz gesprochen. hier und hier .
Natürlich müssen Sie nach der endgültigen Einreichung (durch Klicken auf die Schaltfläche "OK / Senden") sicherstellen, dass alle Eingaben gültig sind. Dies ist jedoch nur ein einfacher Fall, bei dem nach Fehlern gesucht wird.
Ich könnte das leicht in der Form-Klasse machen. Aber ich erinnere mich an eine Best-Practice-Methode zur Validierung der Eingabe in den Eigenschaften des Sets.
Ja, die Idee hier ist Kapselung . Die Form-Klasse sollte nur über Formular-Kram wissen. Es sollte nicht erforderlich sein, zu wissen, welche Art von Eingabe für alle Ihre verschiedenen Steuerelemente gültig ist / ist.
Stattdessen sollte diese Validierungslogik an einer anderen Stelle platziert werden, z. B. in einer Klasse, die Ihre Daten speichert. Diese Klasse würde öffentliche Eigenschaften bereitstellen, um die Daten abzurufen und festzulegen, und innerhalb der Setter-Methode würde sie die Daten überprüfen.
Das bedeutet, dass Ihr Formular nur eine Setter-Methode für Ihre Datenklasse aufrufen muss. Das Formular muss nichts darüber wissen, wie die Daten validiert werden, oder auch was die Daten bedeuten, da die Datenklasse das alles behandelt.
Das sollte nicht passieren, keine Instanz der Klasse kann erstellt werden, wenn die Eingabe nicht gültig ist.
Wenn dies tatsächlich der Fall ist, müssen Sie einen -Konstruktor für die Klasse bereitstellen, die alle benötigten Daten als Parameter akzeptiert. Der Rumpf des Konstruktors validiert dann die angegebenen Daten und löst eine Ausnahme aus, wenn eine davon ungültig ist. Die Ausnahme verhindert, dass die Klasse erstellt wird, und stellt sicher, dass keine Instanz einer Klasse existiert, die ungültige Daten enthält.
Solch eine Klasse hätte wahrscheinlich keine Setter-Methoden bei allen - nur getters.
Dies ist jedoch eine ungewöhnliche Anforderung in der C # -Welt (wie üblich in C ++). Im Allgemeinen funktioniert es gut, wenn Sie Ihren Validierungscode innerhalb der Setter platzieren.
Meine Eigenschaften haben einige private Setter. Sie werden also nur im Konstruktor meiner Datenklasse festgelegt. Das Problem ist jetzt, dass dies meine Validierung nicht einfach zu machen scheint
Warum würde das etwas ändern? Sie übernehmen weiterhin die Validierung innerhalb der privaten Setter. Wenn die Validierung fehlschlägt, werfen Sie eine Ausnahme aus. Da der Konstruktor die Ausnahme nicht behandelt, wird der Code, der versucht hat, das Objekt zu instanziieren, aus dieser Methode herausgesprudelt. Wenn dieser Code die Ausnahme behandeln möchte (z. B. um dem Benutzer eine Fehlermeldung anzuzeigen), kann er dies tun.
Zugegeben, das Auslösen einer Ausnahme im Falle einer ungültigen Eingabe ist nicht unbedingt eine "Best Practice". Der Grund ist, dass Ausnahmen in der Regel für unerwartete Bedingungen reserviert werden sollten, und Benutzer, die versauen und Ihnen ungültige Daten liefern, sind zu erwarten. Jedoch:
Dies ist eine einfache Anforderung, wird aber manchmal diskutiert. Dies ist mein "aktueller" Ansatz, wie man mit der Validierung umgehen kann. Ich habe diesen Ansatz noch nicht verwendet, und das ist nur ein Konzept. Dieser Ansatz muss weiterentwickelt werden.
Erstellen Sie zuerst eine benutzerdefinierte Validierungsattribute
%Vor%Zweitens, erstellen Sie einen benutzerdefinierten Fehlerhandler / Nachricht
%Vor%Erstellen Sie dann einen Validator
%Vor%Um es zu verwenden, können Sie Folgendes tun:
%Vor%Um den Validator aufzurufen
%Vor%Was ist der Vorteil:
Der Nachteil:
Siehe die ErrorProvider
-Klasse (Dokumentation hier ). Es bietet eine Reihe von standardmäßigen visuellen Indikatoren, die an die meisten standardmäßigen WinForms-Steuerelemente angehängt werden können.
Es gibt mehrere mögliche Ansätze:
Wenn der Benutzer einen Wert eingibt, wird dieser während der Eingabe überprüft ( TextChanged
) und sofort validiert. Erzeuge Instanz einer neuen Klasse, rufe property / method auf, was string
akzeptieren soll und gebe bool
zurück (oder throw Exception
im Falle einer Eigenschaft), auf false
- zeichne spezielle Fehlerbedingung (rote Beschriftung neben Textfeld) , etwas blinkend, ErrorProvider
oder was immer Sie tun können, was dem Benutzer "falsch!" sagen sollte.)
Diesen benutze ich gerne, aber ein bisschen anders, normalerweise überprüfe ich nur Type
und versuche dann einfach, es direkt im Formular zu parsen. Es ist möglich, mehr zu abstrahieren, wenn die Form mit den string
arbeitet und alle Formatierungen und Validierungen in der Klasse (Property Setter) stattfinden. Oder Sie können das Formular mit zusätzlichen Informationen versehen (mithilfe von Abfragemethoden oder -attributen), um eine sofortige Validierung durchführen zu können, ohne dass die Klasse instanziiert oder Setter verwendet werden müssen. Als Beispiel kann double factor
Eigenschaft im Formular (oder sogar Steuerelement) identifiziert werden, um 'double.Parse and you can have attribute
DefaultValue which can be used to display to the user value in the different way when it's different from default (like it is done by
PropertyGrid' auszuführen.)
Wenn der Benutzer die Eingabe beendet hat, validiert (indem er versucht, den Wert festzulegen und eine Ausnahme abzufangen), wenn der Benutzer nicht "verlassen" oder "fortfahren" kann, bis er ESC drückt (um die Änderungen rückgängig zu machen) oder um seine Eingabe zu bestätigen .
Diesen mag ich nicht. Die Idee, den Benutzer zu halten, ärgert mich (und den Benutzer von). Außerdem ist es schwierig Cross Checks zu implementieren (wie wenn Sie Min
und Max
Werte haben, dann wird der Benutzer dazu gedrängt "zuerst" zu erhöhen, andernfalls wird die Ungültigkeitsprüfung fehlschlagen).
Das bedeutet nur, dass der Benutzer alles eingeben und nur validieren kann, wenn er auf "Ok" klickt.
Ich denke, das Kombinieren der "Ok" -Schaltfläche und die interaktive sofortige Validierung ist für den Benutzer das Beste. Da der Benutzer weiß, wo er einen Fehler gemacht hat, kann er trotzdem blättern und bekommt nur einen "Klaps" von der Bestätigung nachdem er auf "OK" geklickt hat (bei diesem Schritt kann man ihm einfach zuerst Fehler anzeigen, nicht notwendig) um sie alle zu zeigen.)
Fehlermeldungen können von Setter im altmodischen LastError
Weg oder als Text im Exception
bereitgestellt werden.