Скільки логіки бізнесу має застосовувати база даних?


107

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

Який із цих підходів загалом кращий?

Плюси впровадження бізнес-логіки в БД, про які я можу придумати, є:

  • Централізація ділової логіки;
  • Незалежність типу програми, мови програмування, ОС тощо;
  • Бази даних менш схильні до міграції технологій або великих реконструкцій (AFAIK);
  • Не потрібно переробляти міграцію технологій додатків (наприклад: .NET на Java, Perl на Python тощо).

Мінуси:

  • SQL є менш продуктивним і складнішим для програмування ділової логіки, через відсутність бібліотек та мовних конструкцій найбільш пропонованих мов, орієнтованих на додатки;
  • Складніше (якщо взагалі можливо) використання коду через бібліотеки;
  • Менш продуктивні ІДЕ.

Примітка. Бази даних, про які я говорю, - це реляційні, популярні бази даних, такі як SQL Server, Oracle, MySql тощо.

Дякую!


3
Ви можете знайти відповідь на це питання корисною.
Blrfl

7
Цей аргумент уже обговорювався вичерпно . Що ще ми могли б змістовно додати до розмови тут?
Роберт Харві

2
@gnat: Навіть близько.
Роберт Харві


7
Подумайте, що база даних далеко не переживе вашу програму. База даних може навіть переживати мову, на якій ви пишете свою заявку. Самі дані зазвичай є бізнесом, і база даних повинна мати можливість захищати цілісність даних, які вона містить. У цьому сенсі кожне зовнішнє ключове обмеження - це, чесно кажучи, реалізація бізнес-правила. Якщо ви не позбудетесь усіх реляційних обмежень у вашій реляційній базі даних, ви справді не можете повністю вивести бізнес-логіку з бази даних.
Крейг

Відповіді:


82

Бізнес-логіка не входить у базу даних

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

Бази даних дійсно добре виконують деякі речі:

  1. Вони зберігають і отримують дані
  2. Вони встановлюють та застосовують відносини між різними суб'єктами даних
  3. Вони надають засоби для запиту даних для відповідей
  4. Вони забезпечують оптимізацію продуктивності.
  5. Вони забезпечують контроль доступу

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

І звичайно, можуть бути речі, які виконуються в базі даних для продуктивності та інших причин:

  1. Закриття бухгалтерського періоду
  2. Кількість хрускіт
  3. Нічні серійні процеси
  4. Збій

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

Зберігаються процедури скрізь

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

Але чим ви ризикуєте?

  1. Блокування провайдера
  2. Потреба в розробниках із спеціальними наборами навичок
  3. Загальні засоби програмування Спартана
  4. Надзвичайно щільна програмна муфта
  5. Немає розлуки проблем

І звичайно, якщо вам потрібен веб-сервіс (який, мабуть, все-таки це заголовок), вам все одно доведеться будувати це.

То яка типова практика?

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

Наскільки добре це працює? Дуже добре, і набагато швидше, ніж написання збережених процедур та поглядів. Це, як правило, охоплює близько 80% ваших потреб доступу до даних, переважно CRUD. Що покриває інші 20%? Ви здогадалися: збережені процедури, які підтримують всі основні ORM.

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


3
Дякую за чудову відповідь, @Robert Harvey. Але я думав про аргумент "фіксація постачальника": якщо не використовувати певну технологію (скажімо, стек .NET або Java) для створення додатків і блокування постачальника? Або є переваги вкладеного в додаток блокування постачальника стеків порівняно з БД?
Рафаель

3
@RobertHarvey, Але частина логіки програми, що знаходиться у .NET, все ще зафіксована у .NET. Те саме стосується PHP та Java.
Печер'є

2
@Pacerier: За допомогою постачальника, я маю на увазі постачальника бази даних. Насправді, база даних (і стек програмування) рідко замінюються.
Роберт Харві

2
@kai: Ну, у вас це не може бути обома способами. Або ви користуєтеся заглушками та макетами, і живете з тим, що тест є штучним, або ви пишете тест, який реалістичний, і живете з невеликою затримкою. Я сумніваюся, що ваш компроміс становить 10 хвилин проти 30 секунд.
Роберт Харві

3
Можливо, пізно, але я вважаю, що збережені процедури, що реалізують бізнес-логіку, належать до рівня бізнес-логіки, а не до рівня даних. Вони є своєрідним окремим язиком, не потребуючи ORM.
Параліфе

16

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

Я заперечую ваші плюси і мінуси.

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

select <whatever>
from group g
where fn_invoker_has_access_to_group(g.group_id)

Проблема такого підходу полягає в тому, що він, як правило, (можуть бути випадки, коли це помилково), примушує базу даних виконувати вашу функцію N разів, один раз у ряд. Іноді ця функція дорога. Деякі бази підтримують індекси функцій. Але ви не можете індексувати кожну можливу функцію проти кожного можливого введення. Або ти можеш?

Поширеним рішенням вищезазначеної проблеми є вилучення логіки з функції та об'єднання її в запит. Тепер ви порушили інкапсуляцію та дублювали логіку.

Ще одна проблема, яку я бачу, - це виклик збережених процедур у циклі, оскільки немає способу приєднати чи перетинати збережені набори результатів proc.

declare some_cursor
while some_cursor has rows
    exec some_other_proc
end

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

Взагалі я вважаю, що бази даних погано:

  1. Обчислення
  2. Ітерація (вони оптимізовані для заданих операцій)
  3. Балансування навантаження
  4. Розбір

Бази даних добре:

  1. Блокування та розблокування
  2. Ведення даних та їх взаємозв'язок
  3. Забезпечення доброчесності

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

Ви правдиві, що це відокремлює вашу ділову логіку від мови програмування вашої програми, але я не бачу, чому це є перевагою. Якщо у вас є програма Java, то у вас є програма Java. Перетворення купи Java-коду в збережені процедури не змінює факту наявності програми Java.

Моя перевага - тримати код бази даних, орієнтований на стійкість. Як створити новий віджет? Ви повинні вставити в 3 таблиці, і вони повинні бути транзакцією. Це належить до збереженої процедури.

Визначення того, що можна зробити з віджетом, і правила бізнесу щодо пошуку віджетів належить до вашої програми.


8
На SQL-сервері в циклі потрібно викликати лише погано написані sps, ви можете пересилати їм набори даних у параметрі та робити процес на основі набору.
HLGEM

2
SQL Server генеруватиме неоптимальний план запитів, коли в пункті WHERE є UDF.
Джим Г.

7
Схоже, що у вашій продуктивності проблема не є виною логіки в базі даних проти програми .. вона просто погано написана та архітектована. Ця проблема піде за вами у світі ORM так само. ORM можуть бути справжнім головним болем поза операціями CRUD. Якщо у вашій системі важкі дані, тип звітування, будьте обережні.
сам урожай

Це правда. Більшість проблем із продуктивністю пов'язані з погано написаним кодом та надмірно складною архітектурою. Але я все-таки вважаю, що ми внесли неправильний тип роботи в наші бази даних. Якнайбільше кодування в базу даних змусило нас робити речі, в яких база даних не є доброю.
Брендон

1
Цей приклад є навіть аргументом для розміщення в БД основних частин бізнес-логіки: щоб уникнути ітеративного підходу (коду чи циклу курсору замість виразів на основі набору), як чума. Програмісти, як правило, обробляють набори об'єктів в ітераційному порядку (цикл, траверса), що, ймовірно, призводить до зайвих навантажень або проблеми SELECT N + 1 для багатьох переходів із одного запиту. Використовуючи вирази, засновані на SQL або мові (наприклад, LINQ), вони будуть змушені використовувати на основі набору підхід, коли це можливо.
Ерік Харт

10

Я працював у двох різних компаніях, які мали різний погляд на цю тему.

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

В іншому випадку я думаю, що логіка програми завжди повинна бути в самому програмному забезпеченні. Чому? Тому що програма повинна бути перевірена, і я не думаю, що існує простий спосіб відстежити збережену процедуру. Не забувайте, що програма, яка не перевірена, - це погана програма.

Тому використовуйте Збережену процедуру з обережністю, коли це потрібно.


3
Збережені процедури проходять перевірку. Дивіться тут деякі методи.
Роберт Харві

4
afaik, одиничний тест ніколи не використовує базу даних або файл. Таким чином, технічно "одиничне тестування" збережена процедура не є одиничним тестуванням, і це буде повільно, як пекло. Набір тестових одиниць повинен бути запущений за кілька секунд (а може, і хвилин із дуже великим застосуванням) у будь-який час розвитку.
Кот Жан-Франсуа

1
В ОП говорили про "бізнес-логіку", а бізнес-логіку слід перевірити. Помістивши його в збережену процедуру, ви змішуєте його з запитом до бази даних, який уповільнює весь процес. Як я вже говорив, ви можете використовувати процедуру зберігання (це не злочин), але це розмиває межу між логікою бізнесу та шаром бази даних, що погано. Використовуйте це обережно :)
Jean-François Côté

1
Якщо ви створюєте db та необхідні об'єкти, sp, тестуєте, а потім згортаєте, це одиничний тест. Це випробовує одиницю роботи.
Тоні Хопкінсон

2
Чи не розвінчали міф про підвищення продуктивності із збереженими процедурами?
JeffO

9

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

Як ви зазначали, T-SQL (або його еквівалент в інших популярних RDBMS) не є найкращим місцем для кодування складної бізнес-логіки.

Я намагаюся побудувати досить пристойну модель даних, використовую функції бази даних, щоб захистити мої припущення щодо цієї моделі (тобто, FKs та обмеження), і використовую коди бази даних порядно. Код бази даних корисний, коли вам потрібно щось (тобто сума), що база даних дуже добре робить і може позбавити вас від переміщення мільйонів записів по дроту, коли вони вам не потрібні.


2
Використання бази даних як "завищеного" зберігання ключів / цінностей - цілком вірний прийом, про що свідчать легіони практикуючих NoSQL.
Роберт Харві

1
@RobertHarvey Ви, очевидно, правильні, але якимось чином мої кишки продовжують наполягати на тому, що повинно бути простіше / дешевше / швидше рішення, ніж база даних, якщо все, що вам потрібно, - це зберігання ключів / цінностей. Мені потрібно дізнатися більше про NoSQL.
Dan Pichelman

2
Я не бачу використання збережених процедур як ліки для погано розробленої бази даних.
JeffO

2
@RobertHarvey, я прочитав "завищений ключ / магазин цінностей" буквально. Якщо користуватися ліцензією Oracle або SQL Server на щось подібне, коли є такі варіанти, як MongoDB, доступні безкоштовно, схоже, витрачаючи гроші.
Рафаель

@Raphael Або ви могли б використовувати PostgreSQL 😉
Демі

9

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

http://en.wikipedia.org/wiki/Set_operations_(SQL)

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

Хоча це не важкі і швидкі правила, це хороший вихідний пункт.


6

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

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


3

Через кілька років питання залишається важливим ...

Просте правило для мене: якщо це логічне обмеження або всюдисущий вираз (одне висловлювання), помістіть його в базу даних (так, зовнішні ключі та обмеження перевірки - це також бізнес-логіка!). Якщо це процедурно, містять петлі та умовні гілки (і насправді їх неможливо змінити на вираз), введіть їх у код.

Уникайте баз даних сміття

Спроби помістити справді всю ділову логіку в код програми, ймовірно, перероджують (реляційну) базу даних у смітник, де реляційний дизайн здебільшого повністю опущений, де дані можуть мати будь-який непослідовний стан, а нормалізація відсутня (часто в основному XML, JSON , CSV тощо, кошики для сміття).

Така логіка лише для додатків, мабуть, є однією з головних причин підйому NoSQL - звичайно з недоліком того, що додаток повинен піклуватися про всю логіку, що вбудовується в реляційну БД протягом десятиліть. Однак бази даних NoSQL більше підходять для такого типу обробки даних, наприклад, документи з даними підтримують неявну "реляційну цілісність" всередині себе. Для реляційних БД це просто зловживання, викликаючи все більше проблем.

Вирази (на основі набору) замість процесуального коду

У кращому випадку кожен запит даних або операцію слід кодувати як вираз, а не процедурний код. Відмінною підтримкою цього є те, коли мови програмування підтримують вирази, такі як LINQ у світі .NET (на жаль, наразі лише запити, ніяких маніпуляцій). Що стосується реляційних БД, то вчили давно віддавати перевагу виразам операторів SQL над процедурними петлями курсору. Таким чином, БД може оптимізувати, робити операцію паралельно чи будь-що, що може бути корисним.

Використовуйте механізми цілісності даних БД

Якщо мова йде про RDBMS з обмеженнями зовнішнього ключа та перевірки, обчислені стовпці, можливо, тригери та перегляди, це місце для зберігання основної логіки бізнесу в базі даних. Правильна нормалізація допомагає зберегти цілісність даних, забезпечити унікальний і чіткий примірник даних. Навіть якщо вам доведеться дублювати його в коді та БД, ці основні механізми цілісності даних не слід опускати!

Збережені процедури?

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

Хоча сторона програми, включаючи створений ORM, SQL, більше не знаходиться в базі даних, на відміну від збережених процедур, я все ще вважаю це кодом бази даних. Оскільки він все ще вимагає знань про SQL та базу даних (за винятком найпростішої CRUD), і при правильному застосуванні працює значно відрізняється від процедурного коду, який зазвичай створюється мовами програмування, такими як C # або Java.


2

Це дійсно залежить від бізнесу, його культури та спадщини. Технічні міркування осторонь (вони висвітлювались з обох сторін), наведені відповіді говорять про те, що це зводиться до того, звідки люди приїжджають. У деяких організаціях дані є короткими, а DBA - потужна цифра. Це ваше типове централізоване середовище, центр обробки даних, до якого додається купа терміналів. Перевага в цьому типі середовища очевидна. Робочий стіл може кардинально змінюватися багато разів, перш ніж щось змінити в центрі обробки даних, і між ними буде мало.

Іншим кінцем спектру є чиста 3-ярусна архітектура. А може бути багаторівневим у веб-бізнесі. Ви, ймовірно, почуєте тут іншу історію. DBA, якщо такий є, буде просто супутником, який виконує деякі адміністративні завдання.

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

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


2

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

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

У цьому прикладі бізнес-логіка може перевірити баланс перед тим, як вимагати передачі, або просто викликати збережену процедуру для передачі та повідомити про помилку. ІМХО, в цьому прикладі бізнес-логіка повинна попередньо перевірити наявність достатньої кількості коштів та наявність цільового рахунку і лише потім викликати переказні кошти. Якщо інший дебет відбудеться між початковими етапами та збереженим викликом Proc, лише тоді повернеться помилка.


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