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


13

Я завжди застосовував обмеження на рівні бази даних, крім моїх (ActiveRecord) моделей. Але мені було цікаво, чи справді це потрібно?

Трохи фону

Нещодавно мені довелося провести тестування базового автоматизованого методу генерації часових позначок для моделі. Зазвичай тест створює екземпляр моделі та зберігає її без перевірки. Але є й інші необхідні поля, які не зводяться до нуля при визначенні таблиці, тобто я не можу зберегти екземпляр, навіть якщо пропускаю перевірку ActiveRecord. Тож я думаю, чи варто мені видаляти такі обмеження з самого db, і дозволити ORM їм обробляти?

Можливі переваги, якщо я пропускаю обмеження в db, imo -

  • Може змінювати правило перевірки в моделі, не потребуючи міграції бази даних.
  • Може пропустити перевірку при тестуванні.

Можливий недолік?

Якщо можливо, перевірка ORM завершилася невдачею або її обійти, база даних не перевіряє обмеження.

Що ти думаєш?

EDIT У цьому випадку я використовую рамку Yii , яка генерує модель з бази даних, отже, генеруються і правила бази даних (хоча я завжди можу писати їх і після покоління).


3
Якщо дані у вашій базі даних можуть бути звичайно змінені без використання ORM (інші програми без вашого ORM, або, що ще гірше, прямий доступ db користувачами), перевірка дійсно повинна бути в базі даних.
Мар'ян Венема

Відповіді:


16

Вашим керівним принципом має бути Не Повторюйте себе :

В інженерії програмного забезпечення "Не повторюйте себе" (DRY) - це принцип розробки програмного забезпечення, спрямований на зменшення повторення інформації будь-якого типу, особливо корисного в багаторівневій архітектурі. Принцип DRY вказаний як "Кожен предмет повинен мати єдине, однозначне, авторитетне представлення в системі".

ORM по суті є додатковим шаром (або рівнем, якщо вам зручніше), зручно сидіти між вашою програмою та вашим сховищем даних. Ваші обмеження повинні бути в одному місці, і лише на одному місці, будь то ORM або сховище даних, інакше досить скоро ви закінчите підтримувати різні їх версії. Ти справді не хочеш цього робити.

Однак на практиці більшість напівпристойних ОРМ автоматично генерують велику кількість ваших моделей із вашої схеми даних. Незважаючи на те, що все ще існує дублювання, шанси на пекельне обслуговування мінімальні, оскільки дублюючий код ORM генерується за тією ж схемою щоразу. Ідеально було б не мати дублікату коду, але автоматично створені обмеження - це найкраща справа.

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

Невдачі

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

Обхід ORM для чого-небудь іншого

Також не гарна ідея. Однак це може статися з різних причин:

  1. Спадкові частини програми, створені до введення ORM.

    Це жорстка один, і саме в такій ситуації я маю справу з прямо зараз , тому моїм постійним повтором «підтримуючої пекло». Або ви продовжуєте підтримувати неручні частини ORM, або переписуєте їх для використання ORM. Другий варіант може мати більше сенсу спочатку, але це рішення, яке базується виключно на тому, що саме роблять ті частини вашої програми та наскільки цінним буде повне перезапис у довгостроковій перспективі.

    Спробуйте змінити ключ у погано розробленій таблиці MySQL 2 * 10 ^ 8 рядків (без простоїв), і ви зрозумієте, звідки я родом.

  2. Не застарілі частини програми, яким абсолютно потрібно безпосередньо спілкуватися зі сховищем даних:

    Ще хитріше. ORM - це вигадливі інструменти, і вони піклуються про майже все, але іноді вони просто заважають або навіть є абсолютно марними. Слово (насправді buzzphrase) - невідповідність об'єктно-реляційного імпедансу , просто кажучи, що ORM технічно не може робити все, що робить ваша реляційна база даних, а для деяких речей, які вони роблять, існує суттєвий штраф за продуктивність.

Коментарі

З точки зору цілісності даних обмеження ОБОВ'ЯЗКОВО бути на базі даних, а ОБОВ'ЯЗКОВО бути на додатку. Що робити, якщо доступ до вашої програми через Інтернет та настільні програми, або мобільний додаток, або веб-сервіс? - Луїз Дамім

Тут додавання додаткового шару було б надзвичайно корисним, і якщо ми говоримо про веб-додаток, я б запустив API REST. Надмірно спрощений дизайн для цього було б:

введіть тут опис зображення

ORM буде розташовуватися між API та сховищами даних, і все, що стоїть за API (включаючи його), вважатиметься єдиним об'єктом з різних програм.


Зазвичай ви визначаєте схему у своєму ORM, яка потім відображається в базі даних, щоб у вас був другий рівень впевненості.
Джош К

2
@JoshK Ви кажете другий рівень впевненості, я кажу пекельне обслуговування. Не кажучи, що ти не правий ...
yannis

Має сенс. Зараз я слідую за цим маршрутом. Спасибі!
на

1
Після того, як ви пройдете повз точку, коли один або два розробники займаються кодом і роботою бази даних, це стає необхідним злом. Якщо ви використовуєте хороший ORM, він генерує міграцію і для вас. Коли ви зробите до того, що маєте спеціальну DBA, це не обійдеться, вони не дозволять таблицям плавати навколо без обмежень. Простий спосіб запобігти реєстрації людей без електронного листа - це обмеження рівня пам’яті.
Джош К

1
З точки зору цілісності даних обмеження ОБОВ'ЯЗКОВО бути на базі даних, а ОБОВ'ЯЗКОВО бути на додатку. Що робити, якщо доступ до вашої програми через Інтернет та настільні програми, або мобільний додаток, або веб-сервіс?
Луїз Дамім

20

На це насправді дуже важко відповісти, і я вважав, що це дуже суперечлива тема.

Як зазначив у своїй відповіді Янніс Різос, наявність логіки обмеження як у базі даних, так і в шарі ORM , здавалося б, порушує DRY, що "може призвести до кошмарів технічного обслуговування, поганого факторингу та логічних суперечностей".

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

  1. Оновлення БД вручну (вони, здається, трапляються у кожної компанії)

  2. Оновлення БД з іншої системи, яка не завжди може легко поділяти логіку обмеження ORM (колишній сценарій Perl, який виконує звичайні завдання, коли рівень ORM реалізований в режимі глибокого сну та використовується додатком Java для щоденної діяльності)

Це дозволить вам лише додати логіку обмеження до БД та видалити зі свого рівня ORM , щоб уникнути порушення DRY. Однак це може призвести до випадків, коли код програми не може успішно захопити фактичну проблему та передати користувачеві (хоча, як розробник налагоджує проблему, ви, швидше за все, можете). Це може бути прийнятним для деяких проектів.

Ваш останній варіант - автоматизувати створення обмежень в ОРМ (та будь-якій іншій системі) з обмежень БД (або, справді ... навпаки). Хоча в кінцевому підсумку ви отримаєте дві або більше реалізації обмежень, це не буде порушенням принципу DRY, як описано в «Прагматичному програмісті», оскільки вони рекомендують використовувати генерацію коду, щоб уникнути порушення DRY. Звичайно, це не так просто, оскільки, наприклад, кожна зміна обмеження в БД може змусити перевстановити і перевстановити всі ваші програми, які використовують його (не тривіально для автоматизації).

Дійсно, це доведеться оцінювати в кожному конкретному випадку . Я можу вам сказати, що до цього часу мене зустрічали порожні погляди, коли я пропоную, щоб логіка обмеження не повторювалася.


2
Щойно вийшов з роботи і думав розширити свою відповідь, щоб бути більш-менш тим, що ви тільки що опублікували. Гарна відповідь!
янніс

3

Я б точно додав обмеження в базу даних як мій варіант за замовчуванням. Це тому, що для підприємства дані є короткими, а якість даних є першорядною. @Yannis Rizos виніс на дискусію принцип DRY. Ну інший принцип - оборона в глибині. Для даних я б використовував цей принцип.

Я працював на реальних підприємствах, де БД має дані, створені 30 років тому. До нього доступ і досі доступний додаток COBOL, а тепер додаток .Net. Через 10 років це може бути додаток продавця, хто знає. Відбулося злиття, і мільйони рядків даних були перетворені та перенесені з іншої компанії в цю базу даних за допомогою SQL. Жоден ORM не може цього зробити. Підсумковий рядок - Дані залишаються, змінюються програми, змінюються способи генерування даних. То чому б не знизити ймовірність пошкодження даних?


2

Я думаю, ви в певній мірі ви обидва.

  • Основні обмеження повинні існувати в ORM - мови програмування набагато гнучкіші, їх легше перевірити і легше налаштувати, коли вимоги змінюються; не потрібно турбуватися про виправлення DDL принаймні. І ти, як правило, уникаєш складної перевірки проблем регресії даних.

  • Деякі дуже важкі та швидкі обмеження також повинні міститись у базі даних. Наприклад, я не кажу про неіснуючі імена. Я говорю про такі речі, як референтна цілісність або вимагають якихось абсолютно важливих ідентифікаторів. Структурні вимоги, тому ваш код не повинен мати справу з "що робити, якщо у Замовлення немає товару".


1

База даних - ІМО - єдине місце, де DRY може бути порушена, тому що якщо щось обходить ваш ORM і має погані дані, це все. Гра завершена. Корумповані дані - це вбивчий удар.


Лише база даних? Я можу придумати багато випадків, коли поведінка, пов'язана з даними, повинна існувати на декількох шарах (логічних або фізичних), навіть якщо дані взагалі не зберігаються. Іноді можливо мати єдиний вихідний код і зменшити "дублювання" розгорнутого DLL.
mike30
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.