Gdzie sprawdzić poprawność reguł modelu domeny, które zależą od zawartości bazy danych?


10

Pracuję nad systemem, który pozwala administratorom definiować formularze zawierające pola. Zdefiniowane formularze są następnie wykorzystywane do wprowadzania danych do systemu. Czasami Formularze są wypełniane przez człowieka za pomocą GUI, czasami Formularz jest wypełniany na podstawie wartości zgłoszonych przez inny system.

Dla każdego pola administrator może zdefiniować regułę walidacji, która ogranicza dozwolone wartości pola. Reguły sprawdzania poprawności mogą być dowolne, od „wartość wprowadzona w polu musi być Prawda lub Fałsz” do „wartość wprowadzona w polu musi istnieć w kolumnie A tabeli B w bazie danych”. Administrator może w dowolnym momencie zmienić regułę walidacji dla pola.

W tym scenariuszu, co Twoim zdaniem jest najbardziej odpowiednim miejscem do sprawdzenia, czy każde pole jest poprawnie wypełnione? Mam na myśli dwa główne podejścia:

Opcja nr 1: Sprawdź poprawność w modelu domeny

Każdy obiekt pola zawierałby regułę walidacji określoną przez administratora. Obiekty Field również będą miały odniesienie do IValidatora. Gdy podejmowana jest próba ustawienia wartości pola, pole przekazuje podaną wartość i regułę walidacji do IValidatora. Jeśli podana wartość nie jest poprawna, wyjątek ValidationException zostanie zgłoszony i odpowiednio obsłużony w interfejsie GUI / interfejsie do drugiego systemu.

Plusy:

  • Silna ochrona przed przypadkowym przypisaniem wartościom pól, które naruszają zasadę walidacji

Cons:

  • Warstwa dostępu do danych musi być w stanie ominąć sprawdzanie poprawności i konstruować pola, które naruszają bieżącą regułę sprawdzania poprawności. Pomimo zmiany przez administratora reguły walidacji dla pola, nadal musimy być w stanie konstruować obiekty pola na podstawie starych danych, np. Podczas renderowania formularza wypełnionego lata temu. Można to potencjalnie rozwiązać, przechowując bieżącą regułę walidacji za każdym razem, gdy przechowujemy pole.

  • W tym projekcie model Field ma pośrednie łącze do warstwy / repozytorium dostępu do danych za pośrednictwem IValidatora. Zastrzyki usług / repozytoriów modelom domen wydają się być w zasadzie niezadowolone .

Opcja nr 2: Sprawdź poprawność usługi

Spróbuj upewnić się, że wszystkie próby ustawienia wartości pola przechodzą przez usługę, która zapewnia utrzymanie reguły walidacji. Jeśli zasada walidacji zostanie naruszona, należy zgłosić wyjątek ValidationException.

Oczywiście warstwa dostępu do danych nie używałaby usługi podczas tworzenia obiektów pola, które wcześniej były utrwalane w bazie danych.

Plusy:

  • Nie narusza myślenia „nie wstrzykiwać usług / repozytoriów do modeli domen”.

  • Nie trzeba utrzymywać bieżącej reguły sprawdzania poprawności podczas utrwalania pola. Usługa może po prostu wyszukać bieżącą regułę walidacji dla pola; podczas przeglądania danych historycznych wartość pola nie ulegnie zmianie.

Cons:

  • Nie ma gwarancji, że cała logika, która powinna korzystać z Usługi w celu ustawienia wartości Pola, faktycznie to robi. Widzę to jako poważną wadę; zdaje się, że wystarczy ktoś piszący „thisField.setValue (thatField.getValue ())”, a Reguła Walidacji thisField może zostać naruszona bez mądrzejszego podejścia. Można to potencjalnie złagodzić, zapewniając zgodność wartości pola z regułą sprawdzania poprawności, gdy warstwa dostępu do danych ma zamiar utrwalić pole.

Obecnie wolę opcję 1 niż opcję 2, głównie dlatego, że postrzegam to jako logikę biznesową i uważam, że opcja 2 stwarza większe ryzyko wprowadzenia złych danych do systemu. Którą opcję preferujesz, czy jest inny projekt, który lepiej pasuje do tego scenariusza niż dwie opisane opcje?

Edycja (złożoność walidacji)

Przypadki walidacji, które pojawiły się na razie, są stosunkowo proste; wartość pola musi być np. numeryczna, data, data z czasem lub być wartością istniejącą w kolumnie bazy danych. Podejrzewam jednak, że z czasem złożoność stopniowo wzrasta. Na przykład rozwiązanie do sprawdzania poprawności musi być budowane z myślą o internacjonalizacji - takie rzeczy jak Daty mogą być wprowadzane w składni specyficznej dla ustawień regionalnych.

Zdecydowałem się na razie przejść do Opcji nr 1, starając się nie przypisywać zbyt wielu obowiązków modelowi domeny. Osoby stojące w podobnej sytuacji mogą również chcieć zapoznać się z pokrewnymi pytaniami Sprawdzanie poprawności i autoryzacja w architekturze warstwowej oraz sprawdzanie poprawności wprowadzania danych - gdzie? Ile? .


Tworzenie modelu działa doskonale ze wszystkimi walidacjami. Ale gdy chcesz edytować lub wyświetlić formularz, rozpoczyna się także sprawdzanie poprawności. Zgłasza to wyjątek dla pól, które są puste lub mają nieprawidłowe wartości - być może zmienione w db lub załadowane z Excela. Oczekiwanym rozwiązaniem jest umożliwienie wyświetlenia formularza po aktualizacji, aby administrator mógł poprawić te pola.
tunmise fasipe

Odpowiedzi:


4

Jak złożone są walidacje? Często sprawdzanie poprawności wymaga kombinacji pól i / lub reguł biznesowych, które opierają się na polach w celu ich dokładnej oceny.

Im bardziej złożona jest walidacja, tym trudniejsza i mniej wydajna jest opcja nr 2.

Oczywiście warstwa danych może wywoływać usługę sprawdzania poprawności w czasie trwałości. Może to pomóc w nieparzystej sytuacji, w której dane są w nieprawidłowym stanie z powodu zmiany reguł.

Kolejną rzeczą wartą skomentowania jest możliwość zmiany reguł sprawdzania poprawności bez pewnego rodzaju cyklu qa. Ale to temat na inny wątek.

Biorąc pod uwagę powyższe informacje, opcja 1 wydaje się najbardziej elastyczna, zakładając utrzymanie dyscypliny, oddzielenie walidacji i wytrwałości.


0

Może brakuje Ci warstwy. Bez znajomości szczegółów twojej aplikacji (wymagania, architektura itp.) Zrobiłbym coś takiego jak Klient (kimkolwiek to będzie) -> Usługa aplikacji -> Model domeny

Warstwa usługi aplikacji może wchodzić w interakcje z repozytorium i modelem domeny zawierającym logikę biznesową. Możesz mieć coś takiego:

FieldUpdateService >> updateField(fieldId, newValue)
  List<FieldRule> rules = this.rulesRepository.findRulesFor(fieldId)
  Field field = this.fieldRepository.find(fieldId)
  try 
    field.updateValue(rules,newValue)
    fieldRepository.save(field)
  catch 
    // manage error

Jeśli masz relację między polem a jego regułami pola i używasz ORM, takiej jak Hibernacja w Javie, wykonasz tylko:

FieldUpdateService >> updateField(fieldId, newValue)
  Field field = this.fieldRepository.find(fieldId)
  try 
    field.updateValue(newValue)
    fieldRepository.save(field)
  catch 
    // manage error

Field >> updateValue(newValue)
  for rule in rules
     if !rule.isValid(newValue)
        throw ValueNotAllowedException
  this.value = newvalue

Ponieważ zapytanie ORM tworzy instancję wykresu obiektów, o które prosisz.

Jeśli chodzi o wątpliwości co do tego, że ktoś może to zrobić

thisField.setValue (thatField.getValue ()) ”i Reguła sprawdzania poprawności thisField mogą zostać naruszone bez wiedzy użytkownika

Ktoś też mógłby napisać: FieldRule alwaysReturnTrueRule = new FieldRule {isValid (newValue) {return true; }} field.updateValue („uncheckedValue”, alwaysReturnTrueRule) Jest to niejasny przykład, ale sugeruję, że nic nie chroni przed złym użyciem kodu. Być może dobra dokumentacja i komunikacja osobiście. Myślę, że nic nie chroni przed złym użyciem kodu.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.