Offenes Webinar „Fließende Validierung als Datenvalidierungswerkzeug“



Hallo nochmal! Im Rahmen des Starts des C # Developer- Kurses haben wir eine traditionelle offene Lektion über das Fluent Validation- Tool abgehalten. Während des Webinars untersuchten wir anhand eines Beispiels zur Überprüfung der Richtigkeit des Ausfüllens von Kundendaten, wie eine Reihe von Wenns beseitigt werden können, untersuchten die interne Implementierung der Bibliothek und wie der Fluent Interface-Ansatz in die Praxis umgesetzt werden kann. Das Webinar wurde von Alexei Yagur , Teamleiter bei YouDo, moderiert.



Warum ist eine Validierung erforderlich?


Wikipedia sagt uns, dass die Validierung (von lat. Validus „gesund, stark, stark“) ein Beweis dafür ist, dass die Anforderungen eines bestimmten Benutzers, Produkts, einer bestimmten Dienstleistung oder eines bestimmten Systems erfüllt sind. Die Validierung erfolgt in der Regel nach Bedarf, wobei sowohl eine Analyse der festgelegten Verwendungsbedingungen als auch eine Bewertung der Konformität der Produkteigenschaften mit den bestehenden Anforderungen vorausgesetzt wird. Das Ergebnis der Validierung ist die Schlussfolgerung über die Möglichkeit, das Produkt für bestimmte Bedingungen zu verwenden.

In Bezug auf das Tool zur fließenden Validierung können wir aufgrund seines Wissens:

  • Zeit sparen bei der Lösung von Aufgaben im Zusammenhang mit der Datenvalidierung;
  • verstreute hausgemachte Schecks auf ein einziges Formular zu bringen;
  • Zeigen Sie Ihren Kollegen Ihr Wissen über die Kaffeevalidierung :)

Aber das ist alles Theorie, lasst uns besser mit der Praxis beginnen.

Validierung von Fallstudien: Interaktiv


Die praktische Implementierung der Validierung in C # lautet also wie folgt:



Wir haben eine Klasse Kunde, die die einfachsten Felder hat: Vorname - Name, Nachname - Nachname, Alter - Alter. Und es gibt eine bestimmte CustomerManager-Klasse, die, wie wir sehen, einen neuen Benutzer (Käufer) im CustomerRepository speichert und der Konsole Informationen anzeigt, die der Kunde erfolgreich hinzugefügt hat.

Versuchen wir, einen Benutzer und einen Manager hinzuzufügen, der den Benutzer verwaltet:

void Main() { var customer = new Customer { FirstName = " ", LastName = "", Age = 57, }; var manager = new CustomerManager(); manager.Add(customer); } 

Das Ergebnis der Ausführung ist die Ausgabe des folgenden Textes in der Konsole:

.

Wie Sie sehen können, soweit so gut. Aber was passiert, wenn plötzlich "verdorbene" Daten in unserer Datenbank erscheinen? Zum Beispiel, wenn in den Feldern falsche Informationen eingegeben werden (Telefonnummer anstelle von Name, Alter mit Minuszeichen usw.):

 { FirstName = "+79123456789", LastName = "valde@mar.ru", Age = -14, }; 

Als Ergebnis werden wir sehen, dass ein benutzerdefiniertes Messgerät mit einem unverständlichen Datensatz ebenfalls hinzugefügt wird:

+79123456789 valde@mar.ru .

Natürlich möchten wir solche Daten nicht in unserem Repository haben. Wie schützen wir uns? Am einfachsten ist es, einen Fehler zurückzugeben, wenn beispielsweise nicht alle Zeichen - Buchstaben - vorhanden sind. Dazu legen wir die Bedingung für FirstName mit if fest. Wenn die Bedingung nicht erfüllt ist, stoppen wir die Funktion mit return und zeigen die Meldung „Error in name“ auf der Konsole an. Wir machen das gleiche mit Nachname. In Bezug auf das Alter überprüfen wir hier den Zahlenbereich, zum Beispiel:

if (customer.Age < 14 || customer.Age > 180)

Nehmen wir nun an, wir müssen zusätzliche Felder für den Käufer hinzufügen , z. B. ein Telefon. Wir validieren das Telefon unter der Bedingung, dass die eingegebenen Werte mit "+79" beginnen und nur Zahlen enthalten müssen. All dies an sich wird ein ziemlich umständliches Design sein, aber wenn wir mehr E-Mail hinzufügen wollen?

Wie auch immer, nachdem wir die obigen Operationen ausgeführt haben, erhalten wir eine Reihe von Wenns und ein großes Codeblatt . Für einen externen Entwickler wird es nicht einfach sein, solchen Code zu verstehen. Was tun?

Anschließen der fließenden Validierung


LINQPad bietet die Möglichkeit, die Fluent Validation-Bibliothek zu verbinden, was wir auch tun . Zusätzlich erstellen wir eine weitere Klasse CustomerValidator, die ein Validator sein wird. Dementsprechend schreiben wir alle notwendigen Regeln vor. Wir nehmen zusätzliche Anpassungen vor und entfernen die zahlreichen Wenns, da sie nicht mehr benötigt werden.

Infolgedessen sieht unser endgültiger Code folgendermaßen aus:

 void Main() { var customer = new Customer { FirstName = "Alex2", LastName = "Petrov1", Age = 10, Phone = "+791234567893", Email = "adsf@fadsf3.com" }; var manager = new CustomerManager(); manager.Add(customer); } class Customer { public string FirstName { get; set; } public string LastName { get; set; } public int Age { get; set; } public string Phone { get; set; } public string Email { get; set; } } class CustomerManager { CustomerRepository _repository; CustomerValidator _validator; public CustomerManager() { _repository = new CustomerRepository(); _validator = new CustomerValidator(); } public void Add(Customer customer) { if (!ValidateCustomer(customer)) { return; } _repository.Add(customer); Console.WriteLine($" {customer.FirstName} {customer.LastName}  ."); } private bool ValidateCustomer(Customer customer) { var result = _validator.Validate(customer); if (result.IsValid) { return true; } foreach(var error in result.Errors) { Console.WriteLine(error.ErrorMessage); } return false; } } class CustomerValidator : AbstractValidator<Customer> { public CustomerValidator() { var msg = "   {PropertyName}:  {PropertyValue}"; RuleFor(c => c.FirstName) .Must(c => c.All(Char.IsLetter)).WithMessage(msg); RuleFor(c => c.LastName) .Must(c => c.All(Char.IsLetter)).WithMessage(msg); RuleFor(c => c.Age) .GreaterThan(14).WithMessage(msg) .LessThan(180).WithMessage(msg); RuleFor(c => c.Phone) .Must(IsPhoneValid).WithMessage(msg) .Length(12).WithMessage("    {MinLength}  {MaxLength}.  : {TotalLength}"); RuleFor(c => c.Email) .NotNull().WithMessage(msg) .EmailAddress(); } private bool IsPhoneValid(string phone) { return !(!phone.StartsWith("+79") || !phone.Substring(1).All(c => Char.IsDigit(c))); } } class CustomerRepository { Random _random; public CustomerRepository() { _random = new Random(); } public void Add(Customer customer) { var sleepInSeconds = _random.Next(2, 7); Thread.Sleep(1000 * sleepInSeconds); } } 

Und ein bisschen mehr Theorie


Ich möchte ein paar Worte zur fließenden Validierung hinzufügen. Dieses Tool wird aufgrund der "Fluid" -Schnittstelle so genannt. Wieder sagt uns Wikipedia , dass eine flüssige Schnittstelle eine Möglichkeit ist, eine objektorientierte API zu implementieren, um die Lesbarkeit des Quellcodes des Programms zu verbessern. Die Definition enthält, wie wir sehen, viele schöne und lange Wörter, was nicht immer klar ist. Aber wir können anders sagen:
"Eine flüssige Schnittstelle ist eine Möglichkeit, eine objektorientierte API zu implementieren, in der Methoden dieselbe Schnittstelle zurückgeben, auf der sie aufgerufen wurden."
Alexey Yagur
Die Bibliothek selbst enthält die folgenden Komponenten :

  1. Die Grundlogik . Hier ist ein Link zu GitHub, wo Sie die Hauptlogik sehen können.
  2. Hilfslogik . FluentValidation.ValidatorAttribute ist für diese Logik verantwortlich.
  3. Kontextsensitiver Teil . Siehe FluentValidation.AspNetCore , FluentValidation.Mvc5 und FluentValidation.WebApi .
  4. Tests . Dementsprechend sind wir an FluentValidation.Tests.AspNetCore , FluentValidation.Tests.Mvc5 , FluentValidation.Tests.WebApi und FluentValidation.Tests interessiert .

Das ist alles, Schritt für Schritt, um Code zu schreiben, siehe Video . Darüber hinaus könnten Sie an zusätzlichen interaktiven Themen zum Thema "Variablen in Fehlertexten" interessiert sein, die der Lehrer gegen Ende des Webinars abhielt.

Wir sehen uns beim C # Developer Course!

Source: https://habr.com/ru/post/de472604/


All Articles