Walidacja danych w wzorcu MVP - jak i gdzie?

0

Piszę aplikacją WinForms i pierwszy raz staram się użyć wzorca MVP, mam podzielony projekt na 3 podprojekty: Model, Presenter i View. W modelu trzymam klasy, które odpowiadają encją w bazie danych oraz logikę biznesową. Teraz pytanie o walidację, wydaje mi się, że powinna być ona również w Modelu, dobrze myślę? Pytanie numer dwa, jak najlepiej zaprojektować walidację, myślałem o statycznej klasie ValidationUtilities, która miała by takie funkcje jak: IsValidUsername(), IsValidPassword(), IsValidPersonalNumber(), itp., które rzucają wyjątkiem jeżeli walidacja się nie powiedzie. Czy to dobre podejście?

`zamiana znaczników na ``` - @furious programming

1

Tak, walidacja biznesowa powinna jest częścią Domeny czyli Modelu.
Ale jedna klasa do walidacji wszystkich możliwych encji będzie złamaniem zasady SRP. Na początku może to będzie fajne, ale szybko zrobi się z tego God Object na milion linijek.

Moim zdaniem każda encja powinna mieć swój własny walidator (albo klika). Polecam zapoznać się z biblioteką FluentValidation.

0

@somekind dzięki za rozjaśnienie tematu, zapoznaje się z biblioteką FluentValidation jak poleciłeś. Teraz nasuwa mi się kolejne pytanie: kiedy dane powinny być sprawdzane? Tylko przed zapisem do bazy danych czy nawet kiedy tylko odpytuje bazę? Dajmy na to, że mam funkcję:

bool IsUserInRole(string username, Role role)

czy przed sprawdzeniem powinienem sprawdzić poprawność username i rzucić wyjątkiem(?), czy po prostu zwrócić **false ** jeżeli taki użytkownik o podanej nazwie, nawet błędnej, nie istnieje. Jeżeli sprawdzać poprawność to tworzyć osobną klase:

UsernameValidator : AbstractValidator<string>

czy może inaczej?

0

Ja bym najpierw sprawdził czy nazwa podana przez użytkownika jest prawidłowa, a dopiero potem czy jest już wykorzystana.

0

Ok, także zrobię jak mówisz. Mam jeszcze jedno pytanie, czy taka walidacja danych ma sens:

public class UserInformationValidator : AbstractValidator<UserInformation>
    {
        public UserInformationValidator()
        {
            RuleFor(x => x.FirstName).NotEmpty().Matches(namePattern).WithName("Imię pierwsze");
            RuleFor(x => x.MiddleName).NotEmpty().Matches(namePattern).WithName("Imię drugie").When(x => x.MiddleName != null);
            RuleFor(x => x.Surname).NotEmpty().Matches(surnamePattern).WithName("Nazwisko");
            RuleFor(x => x.FamilyName).NotEmpty().Matches(surnamePattern).WithName("Nazwisko rodowe");
            RuleFor(x => x.DateOfBirth).NotEmpty().WithName("Data urodzenia");
            RuleFor(x => x.PlaceOfBirth).NotEmpty().Matches(cityPattern).WithName("Miejsce urodzenia");
            RuleFor(x => x.PersonalNumber).NotEmpty().Matches(personalNumberPattern).WithName("Numer PESEL");
            RuleFor(x => x.Address).NotEmpty().Matches(addressPattern).WithName("Adres zamieszkania");
            RuleFor(x => x.City).NotEmpty().Matches(cityPattern).WithName("Miejscowość");
            RuleFor(x => x.ZipCode).NotEmpty().Matches(zipCodePattern).WithName("Kod pocztowy");
        }

        private readonly string namePattern = @"^[A-ZŁŚŻ][a-ząćęłńóśżź]{2,30}$";
        private readonly string surnamePattern = @"^[A-ZŁŚŻ][a-ząćęłńóśżź]{2,30}(-[A-ZŁŚŻ][a-ząćęłńóśżź]{2,30})?$";
        private readonly string personalNumberPattern = @"^\d{11}$";
        private readonly string addressPattern = @"^[\w\sąćęłńóśżźĄĆĘŁŃÓŚŻŹ.\\\/-]{3,}$";
        private readonly string cityPattern = @"^[A-ZĆŁŚŻ][a-ząćęłńóśżź]{2,30}([- ][A-ZĆŁŚŻ][a-ząćęłńóśżź]{2,30})?$";
        private readonly string zipCodePattern = @"^\d{2}-\d{3}$"; 

Przykładowo czy ograniczanie znaków dla adresu, imienia, nazwiska itp ma sens?

0

I co nikt nic nie poradzi? Zastanawiam się czy to ma sens, czy jest jakiś lepszy sposób na walidację ulic, imion, nazwisk niż takie regexy? Jak to się robi w praktyce w prawdziwej pracy?

0

To jest walidacja danych wprowadzanych przez użytkownika, nie sądzę, aby był sens powielania jej na poziomie encji.

0

@somekind bardziej mi chodziło o to czy taka walidacja sama w sobie jest ok, przy użyciu regexów. Zastanawiam się czy w praktyce robi się takie szczegółowe sprawdzenia jak np czy imie zaczyna się od litery A-XŁŚŻ, czy sprawdza się po prostu czy imie nie jest puste i to wystarczy? Albo czy np ogranicza się możliwe znaki co do ulicy, itp.

Walidacji nie będę powielał, implementuje ją tylko na poziomie Modelu, który będzie rzucał wyjątkami do kontrolera w przypadku nie powodzenia.

`zamiana znacznika na ``` - @furious programming

0
Wielki Mleczarz napisał(a):

@somekind bardziej mi chodziło o to czy taka walidacja sama w sobie jest ok, przy użyciu regexów. Zastanawiam się czy w praktyce robi się takie szczegółowe sprawdzenia jak np czy imie zaczyna się od litery A-XŁŚŻ, czy sprawdza się po prostu czy imie nie jest puste i to wystarczy?

Nie spotkałem się nigdy z tak szczegółową walidacją. Moim zdaniem jakakolwiek zawartość jest prawidłowa. Jeśli ktoś twierdzi, że ma na imię "A" albo "Piotrek13cm", to takie wartości powinno się móc wprowadzić.

Walidacji nie będę powielał, implementuje ją tylko na poziomie Modelu, który będzie rzucał wyjątkami do kontrolera w przypadku nie powodzenia.

Walidacja danych wprowadzonych przez użytkownika nie powinna opuścić warstwy prezentacji, ją może zrobić Prezenter albo nawet Widok (w sensie kontrolki GUI), na podstawie reguł zdefiniowanych we ViewModelu.

Model powinien zawierać logikę biznesową, np. to, że użytkownik nie może kupić więcej niż 3 produktów, jeśli na koncie masz mniej niż 100zł. Weryfikacja danych od użytkownika w Modelu jest zbyt późna.

1 użytkowników online, w tym zalogowanych: 0, gości: 1