Ja pierwszy raz widzę bibliotekę, której podaje się gotowy złożony i potencjalnie niespójny obiekt do walidacji, zamiast konstruowania obiektu po sprawdzeniu poprawności.
Tyle, że to nie jest obiekt w sensie OOP. To jest DTO, czyli po prostu rekord, taki prosty pojemnik na dane.
Może to dlatego, że kodzę w Scali :)
Może. Ale w Javie chyba DTO widziałeś? I chyba nawet Spring potrafi zrobić takie DTO z danych, które w HTTP reqeście przyszły.
Z drugiej strony popatrzyłem na biblioteki do czytania CSV w Javie i dwa pierwsze wyniki z Google pokazały twory, które aczkolwiek potrafią deserializować do fasolek, to jednak wspierają też czytanie wierszy do kolekcji stringów. Widzę, że podejście stringly typed
wciąż trzyma się mocno.
Trzeba było od razu napisać, że FluentValidation jest tak sztywny, że nadaje się tylko do sztywnych DTOsów.
A vavr jest tak sztywny, że nawet messageboxa nie potrafi narysować na ekranie, do tego nie generuje SQL. :P
To jest oczywiste, że biblioteka robi to, do czego jest przeznaczona, a nie coś innego i przy okazji wszystko pozostałe.
- DTO zawiera same nieprzekonwertowane Stringi. Zaletą jest to, że jego stworzenie zawsze się powiedzie
To jest tak smutne, że powinni ten pomysł zekranizować, kobiety lubią wyciskacze łez, więc ruch przed walentynkami byłby spory.
- DTO zawiera inta, floata, BigDecimala, etc Zaletą jest to, że konwersja danych jest w jednym miejscu. Wadą jest to, że błędy mogą się pojawić w dwóch momentach - jeden to moment deserializacji danych do DTO, drugi to moment walidacji za pomocą FluentValidate. Dowolny błąd deserializacji danych pozbawi nas możliwości raportowania o np błędach z walidatora, a więc lipa. Np użytkownik w polu rok wpisze 1600, a w polu bilans konta wpisze "ala ma kota". Zobaczy tylko jeden błąd - nie udało się zdeserializować DTO, bo "ala ma kota" nie jest liczbą. Nie ma DTO, nie ma walidacji DTO, więc nie ma też komunikatu, że 1600 nie jest akceptowalnym rokiem urodzenia.
To już zależy od tego jak zaimplementowana jest deserializacja. Może np. zwracać własną listę błędów, albo wstawiać domyślną wartość oznaczającą błąd, którą następnie walidator wykryje i zwróci swój error.
Przy użyciu Validate z vavr.io nie ma takich dylematów - walidacja odbywa się w tym samym kroku co wyciąganie danych i konwersja ich typów. Dowolny błąd skutkuje dołączeniem go do listy błędów, nie rozwala procesu walidacji jako całości.
Mnie osobiście nie bardzo podoba się takie łączenie odpowiedzialności. Oddzielny walidator ma tę zaletę, że zadziała na DTO pochodzących z dowolnego źródła, więc może być łatwo reużywany.
Przy założeniu, że struktura jest sztywna to FluentValidation wystarczy. Jeśli jednak np na wejściu mam XMLa z danymi kontraktu walutowego, a na wyjściu chcę dostać zwalidowaną podklasę klasy Trade (możliwe podklasy to np CDS, IRS, Future, Option, etc - mają różne zestawy pól) to muszę XMLa walidować krok po kroku i na podstawie części zwalidowanych danych (np nagłówka) decydować które dane w następnego kolejności walidować i które obiekty (tzn której podklasy) konstruować. FluentValidation tego nie ogarnie.
Owszem, nie ogarnie. Bo jak nazwa wskazuje służy do walidacji, nie deserializacji. Jeśli mamy sytuację, w której potrzebujemy własnego deserializatora, to można od razu go wyposażyć także w walidację. Jeśli dane są proste i istnieją wbudowanych deserializatorów do nich, to pisanie własnego nie ma sensu.