Płynna walidacja za pomocą metod łańcuchowych w Javie: poprawa czytelności i elastyczności kodu

Podczas tworzenia oprogramowania walidacja danych jest kluczowym aspektem zapewniającym integralność i niezawodność systemu. Weryfikacja danych wprowadzanych przez użytkownika, żądań interfejsu API lub innych danych przepływających przez system jest niezbędna, aby zapobiec błędom, naruszeniom danych i innym nieoczekiwanym zachowaniom. Jednym z powszechnych podejść do implementacji walidacji danych jest użycie interfejsu Validator, który definiuje kontrakt do walidacji różnych typów danych.
W Javie implementacja logiki walidacji może czasem stać się skomplikowana i trudna w zarządzaniu, zwłaszcza w przypadku wielu reguł walidacji. Jednak użycie metod łańcuchowych w interfejsie Validatora może znacznie uprościć ten proces, czyniąc kod bardziej czytelnym, wielokrotnego użytku i łatwiejszym w utrzymaniu.
W tym poście na blogu zbadamy, jak dodać metody łańcuchowe do interfejsu Validator i wykorzystać je do stworzenia solidnej i elastycznej logiki walidacji. Udostępnimy również przykład kodu, aby zademonstrować tę koncepcję.
Dlaczego metody łańcuchowe?
Tradycyjne podejście do korzystania z Validator
interfejsu często polega na wywoływaniu wielu metod sprawdzania poprawności jedna po drugiej, co może skutkować zagnieżdżonymi instrukcjami if-else i utrudniać odczytywanie i konserwację kodu. Dodając metody łańcuchowe do interfejsu Validator, możemy wykorzystać płynny interfejs, który pozwala na bardziej zwięzły i wyrazisty sposób pisania logiki walidacji.
Tworzenie interfejsu walidatora
Zacznijmy od stworzenia interfejsu Validator
, który posłuży jako podstawa dla naszych metod łączenia. Interfejs walidatora będzie miał ogólny typ T, reprezentujący typ danych do walidacji, i będzie definiował pojedynczą metodę walidacji, która pobiera obiekt typu T
i zwraca ValidationResult
obiekt, wskazując, czy walidacja zakończyła się pomyślnie, czy nie.
@FunctionalInterface
public interface Validator<T> {
ValidationResult validate(T t);
}
public class ValidationResult {
private final boolean isValid;
private final String message;
public ValidationResult(boolean isValid, String message) {
this.isValid = isValid;
this.message = message;
}
public boolean isValid() {
return isValid;
}
public String getMessage() {
return message;
}
}
Następnie dodamy do interfejsu trzy metody tworzenia łańcuchów Validator
: and
, or
, i negate
.
Metoda and
przyjmuje inny Validator
jako parametr i zwraca nowy Validator, który wykonuje obie walidacje. Jeśli któraś z walidacji nie powiedzie się, nowy Validator zwróci wynik walidacji zakończony niepowodzeniem.
default Validator<T> and(Validator<? super T> other) {
return obj -> {
ValidationResult result = this.validate(obj);
return !result.isValid() ? result : other.validate(obj);
};
}
default Validator<T> or(Validator<? super T> other) {
return obj -> {
ValidationResult result = this.validate(obj);
return result.isValid() ? result : other.validate(obj);
};
}
default Validator<T> negate() {
return obj -> {
ValidationResult result = this.validate(obj);
return new ValidationResult(!result.isValid(), result.getMessage());
};
}
Zobaczmy teraz, jak możemy użyć metod łączenia, aby utworzyć połączony moduł sprawdzania poprawności, który weryfikuje zarówno adres e-mail, jak i imię i nazwisko. Jako przykłady użyjemy dwóch prostych walidatorów do sprawdzania poprawności adresu e-mail i nazwiska.
Validator<String> emailValidator = str -> {
if (str == null || !str.matches("[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}")) {
return new ValidationResult(false, "Email is not valid");
}
return new ValidationResult(true, "");
};
Validator<String> nameValidator = str -> {
if (str == null || str.trim().isEmpty()) {
return new ValidationResult(false, "Name cannot be empty");
}
return new ValidationResult(true, "");
};
Validator<String> combinedValidator = emailValidator.and(nameValidator);
ValidationResult result = combinedValidator.validate("[email protected]");
Na koniec nazwaliśmy validate
metodę na combinedValidator
przykładowym wejściu e-mail „ [email protected] ”. Metoda validate
zwraca ValidationResult
obiekt wskazujący, czy walidacja przebiegła pomyślnie, czy nie. W tym przykładzie, ponieważ adres e-mail jest prawidłowy, a nazwa nie jest pusta, pole isValid
obiektu result
będzie miało true
postać , co oznacza pomyślną weryfikację, a getMessage
metoda zwróci pusty ciąg jako komunikat weryfikacyjny.
Możesz dalej dostosowywać i łączyć ze sobą wiele Validatorów, aby stworzyć bardziej złożoną logikę walidacji zgodnie z własnymi wymaganiami. Metody łańcuchowe w interfejsie Validator zapewniają elastyczny i wyrazisty sposób budowania solidnej i łatwej w utrzymaniu logiki sprawdzania poprawności w Javie.
Zalety metod łańcuchowych
Podejście polegające na dodawaniu metod łańcuchowych do interfejsu Validator ma kilka zalet:
Hermetyzacja : Logika sprawdzania poprawności jest zawarta w interfejsie Validatora i jego implementacjach. Sprzyja to lepszemu rozdzielaniu problemów i ułatwia zmianę logiki sprawdzania poprawności bez wpływu na resztę kodu.
Wielokrotne użycie : interfejs Validator i jego implementacje mogą być ponownie wykorzystywane w różnych częściach bazy kodu, zmniejszając powielanie kodu i promując spójność logiki walidacji. Może to zaoszczędzić czas i wysiłek związany z programowaniem.
Komponowalność : metody łańcuchowe umożliwiają łatwe tworzenie mniejszych, prostszych walidatorów w celu wyrażenia złożonych reguł walidacji w zwięzły i czytelny sposób. Ułatwia to zrozumienie i obsługę logiki sprawdzania poprawności.
Elastyczność : metody łańcuchowe zapewniają elastyczny sposób łączenia walidatorów na różne sposoby, aby spełnić specyficzne potrzeby konkretnego przypadku użycia. Pozwala to na dynamiczną i elastyczną logikę walidacji, która może ewoluować w czasie.
Testowalność : Hermetyzacja i możliwość ponownego użycia interfejsu Validator i jego implementacji ułatwiają pisanie testów jednostkowych dla logiki walidacji. Metody łańcuchowe pozwalają również na dokładniejsze testowanie logiki walidacji, zapewniając solidność i niezawodność.
Wniosek
Podsumowując, włączenie wzorca projektowego wykorzystującego metody łańcuchowe w interfejsie Validatora może znacznie zwiększyć skuteczność walidacji kodu. Takie podejście promuje enkapsulację, możliwość ponownego użycia, kompozycję, elastyczność i testowalność, co skutkuje bardziej niezawodnym i łatwiejszym w utrzymaniu kodem. Łącząc ze sobą metody sprawdzania poprawności, możemy zmniejszyć złożoność logiki sprawdzania poprawności kodu i uczynić go bardziej zwięzłym i czytelnym. Pomaga to nie tylko wcześnie wykryć błędy i spełnić wymagania, ale także poprawia organizację kodu i promuje praktyki tworzenia oprogramowania wysokiej jakości. Przyjmijmy więc ten wzorzec projektowy w naszych wysiłkach związanych z walidacją kodu, aby stworzyć niezawodne i niezawodne oprogramowanie.
Szczęśliwego kodowania!