Де перевірити правила доменної моделі, які залежать від вмісту бази даних?


10

Я працюю над системою, яка дозволяє адміністраторам визначати форми, які містять поля. Визначені форми потім використовуються для введення даних у систему. Іноді Форми заповнюються людиною через GUI, іноді Форма заповнюється на основі значень, повідомлених іншою системою.

Для кожного поля адміністратор може визначити правило перевірки, яке обмежує допустимі значення для поля. Правила перевірки можуть бути будь-якими, від "значення, введене в поле повинно бути істинним або помилковим", до "значення, введене в поле, повинно існувати у колонці таблиці таблиці В в базі даних". Адміністратор може в будь-який час змінити Правило перевірки поля.

У цьому сценарії, що, на вашу думку, є найбільш підходящим місцем для перевірки правильності заповнення кожного поля? На даний момент маю на увазі два основні підходи:

Варіант №1: Підтвердити модель домену

Кожен об'єкт Field містив би правило перевірки, визначене адміністратором. Об'єкти поля також мали б посилання на IValidator. Коли робиться спроба встановити значення поля, поле передасть задане значення та правило перевірки IValidator. Якщо задане значення недійсне, ValidationException буде викинуто і відповідним чином обробляється в GUI / інтерфейсі для іншої системи.

Плюси:

  • Сильний захист від випадково присвоєних полів значень, що порушують Правило перевірки

Мінуси:

  • Шар доступу до даних повинен бути в змозі обійти валідацію та побудувати поля, що порушують поточне правило перевірки. Незважаючи на те, що адміністратор змінив Правило перевірки для поля, нам все-таки потрібно мати можливість будувати об’єкти поля на основі старих даних, наприклад, під час надання форми, заповненої років тому. Це потенційно може бути вирішено, зберігаючи поточне правило перевірки, коли ми зберігаємо поле.

  • У цій конструкції модель Field має непряме посилання на рівень / сховище доступу до даних через IValidator. Введення послуг / репозиторіїв до доменних моделей, здається, зазвичай нахмуриться .

Варіант №2: перевірка в сервісі

Постарайтеся переконатися, що всі спроби встановити значення поля проходять через службу, яка забезпечує виконання правила перевірки. Якщо правило перевірки порушено, киньте ValidationException.

Звичайно, рівень доступу до даних не використовував би Сервіс під час створення об'єктів Field, які раніше зберігалися в БД.

Плюси:

  • Не порушує мислення "не вводьте служби / сховища у ваші доменні моделі".

  • Не потрібно зберігати поточне правило перевірки під час збереження поля. Служба може просто знайти поточне правило перевірки для поля; при перегляді даних історії значення Поля не буде змінено.

Мінуси:

  • Ніякої гарантії, що вся логіка, яка повинна використовувати Сервіс для встановлення значення поля, насправді так і робить. Я бачу це як головний недолік; все, що, здається, береться за те, щоб хтось написав "thisField.setValue (thatField.getValue ())", і Правило перевірки цього FiFi може бути порушено, без того, щоб хтось мудріший. Це потенційно може бути зменшене, гарантуючи, що значення поля збігається з правилом перевірки, коли рівень доступу до даних збирається зберігати поле.

В даний час я віддаю перевагу варіанту №1 над варіантом №2, головним чином тому, що я сприймаю це як ділову логіку і вважаю, що варіант №2 створює більший ризик введення поганих даних у систему. Який варіант ви віддаєте перевагу, чи є інший дизайн, який краще відповідає цьому сценарію, ніж два описані варіанти?

Редагування (Складність перевірок)

Випадки перевірки, що з’явилися зараз, відносно прості; Значення поля повинно бути, наприклад, числовим, датою, датою з часом або бути наявним значенням у стовпці бази даних. Однак я підозрюю, що складність з часом поступово збільшуватиметься. Наприклад, рішення для перевірки потрібно будувати з урахуванням інтернаціоналізації - такі речі, як Дати, можуть бути введені в синтаксис, характерний для локальної мови.

Наразі я вирішив перейти до Варіанту №1, намагаючись подбати про те, щоб не покласти занадто багато обов'язків до Доменної моделі. Особи, які стикаються з подібною ситуацією, можуть також захотіти перевірити відповідні питання Валідація та авторизація у багатошаровій архітектурі та перевірка введення даних - Де? Скільки? .


Створення моделі чудово працює з усіма перевірами. Але коли ви хочете відредагувати або переглянути форму, перевірка також починається. Це викидає винятки для полів, які порожні або мають недійсні значення - можливо, змінені в db або завантажені з Excel. Очікуване рішення полягає в тому, щоб дозволити форму відображатися під час оновлення, щоб адміністратор міг виправити ці поля.
fasmispe tunmise

Відповіді:


4

Наскільки складні перевірки? Часто для перевірки потрібна точна оцінка комбінації полів або правил бізнесу, які покладаються на поля.

Чим складніші перевірки, тим важчий і менш ефективний варіант №2.

Звичайно, рівень даних може викликати послугу перевірки на постійний час. Це може допомогти дивній ситуації, коли дані знаходяться в недійсному стані через зміну правил.

Інший пункт, про який варто коментувати, - це можливість зміни правил перевірки без циклу qa. Але це тема для іншої теми.

Враховуючи інформацію, описану вище, варіант 1 видається найбільш гнучким, якщо ви дотримуєтесь дисципліни, розділяючи валідацію та наполегливість.


0

Можливо, вам не вистачає шару. Не знаючи деталей вашої програми (реквізити, архітектура тощо), я б зробив щось на зразок Клієнта (хто б це не було) -> Служба застосунків -> Доменна модель

Службовому рівню додатків дозволяється взаємодіяти з сховищем та доменною моделлю, що містить бізнес-логіку. Таким чином, ви можете мати щось на кшталт:

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

Якщо у вас є стосунки між Field і його FieldRules і використовуєте ORM, як Hibernate в Java, ви тільки зробите:

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

Тому що ORM запитує та інстанціює графік об'єктів, про який ви запитуєте.

Щодо сумнівів у тому, що хтось може зробити

thisField.setValue (thatField.getValue ()) "та Правило перевірки цьогоField можуть бути порушені, без того, щоб хтось мудріший

Хтось також міг написати: FieldRule alwaysReturnTrueRule = новий FieldRule {isValid (newValue) {return true; }} field.updateValue ("uncontValue", alwaysReturnTrueRule) Це незрозумілий приклад, але те, що їм потрібно сказати, це те, що ніщо не захищає вас від поганого використання коду. Можливо, хороша документація та спілкування віч-на-віч. Я думаю, що ніщо не захищає вас від поганого використання коду.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.