Чи ORM дозволяють створювати розширені моделі доменів?


21

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

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

Деякі проблеми, які я знайшов:

  • Не вдається переміститися по графіку об'єктів, оскільки збережені процедури просто завантажують мінімальну кількість даних, це означає, що іноді ми маємо подібні об'єкти з різними полями. Один із прикладів: у нас є збережена процедура для отримання всіх даних від клієнта, а інша для отримання інформації облікового запису плюс кілька полів від клієнта.
  • Багато логіки виявляється в допоміжних класах, тому код стає більш структурованим (з сутностями, що використовуються як старі структури С).
  • Більш нудний код лісу, оскільки немає рамки, яка витягує набори результатів із збереженої процедури та розміщує їх у сутності.

Мої запитання:

  • хтось був у подібній ситуації і не погоджувався з підходом до процедури магазину? що ти зробив?
  • Чи є фактична користь від використання збережених процедур? крім дурної точки "ніхто не може видати стіл для крапель".
  • Чи є спосіб створити багатий домен, використовуючи збережені процедури? Я знаю, що існує можливість використання AOP для введення DAO / Repositories в об'єкти, щоб мати можливість переміщатися по об’єктовому графіку. Мені не подобається цей варіант, оскільки він дуже близький до вуду.

Висновок

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

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

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

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

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

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


Невелике оновлення (6.06.2012)

Збережені процедури (принаймні в Oracle) заважають робити щось подібне до постійної доставки з нульовим простоєм, оскільки будь-яка зміна структури таблиць призведе до недійсності процедур і тригерів. Тож під час оновлення БД програма також буде вимкнена. Oracle надає рішення для цієї назви Визначення на основі редакції , але нечисленні DBA, про які я запитував про цю функцію, згадували, що вона мала слабке враження, і вони не вкладають її у виробничу БД.


Ну, очевидно, ви могли б робити те, що робить Hibernate, і використовувати спадщину для генерування динамічного проксі-об’єкта, що дозволяє отримати графік об'єкта. Це надзвичайно гакітно з SP, хоча: D
Макс

Тож я закінчив би переосмислити половину сплячки, без досвіду 10+ років, який має команда зі сплячки :).
Август

1
Будь-яка DBA повинна перешкоджати видаленню певних таблиць певними користувачами. Не має значення, як ви намагаєтеся це зробити.
JeffO

1
Ви можете поглянути на Mybatis - він може забезпечити необхідну функцію. Це менше ОРМ, ніж структура картографування. Ви можете написати SQL, скільки завгодно, і сказати Mybatis, де його розмістити на вашій об'єктній моделі. Він буде обробляти великі об’єктні графіки з декількома запитами, що схоже на ситуацію у вас (безліч тонких зберігаються процедур).
Майкл К

1
@Augusto: Я опинився в подібній ситуації не через використання SP, а через використання власної структури картографування, яка не підтримувала об'єктні зв'язки. Ми витрачали дні на написання коду, який можна було записати за лічені хвилини, використовуючи належну ORM. Я ніколи не вирішував цю проблему.
Кевін Клайн

Відповіді:


16

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


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

1
@Augusto Добре ... ви розробник додатків, тому вам доведеться вирішити, чи є сенс існування певного об'єкта з певними полями, встановленими NULL. Якщо це має сенс (наприклад, для певного завдання), то нехай це буде. Якщо ні, попросіть автора ІП надати більше даних, щоб ви могли створити свої об'єкти.
Яцек Прусія

І додавши до коментаря Яцека - насправді цілком прийнятно викликати 2+ збережених програм, знову ж думайте про них як про два віддалені сервіси, до яких вам потрібно зателефонувати, щоб створити свою модель домену, нічого поганого в цьому немає :-).
Martijn Verburg

@Martijn: На мій досвід, тонкого шару недостатньо. Код відображення може бути значно довшим, ніж основна бізнес-логіка.
Кевін Клайн

@Kevin cline - Добре, поставив "сподіваюсь" у відповідь :-)
Martijn Verburg

5

Чи є фактична користь від використання збережених процедур?

У фінансовому світі (і в місцях, де потрібне дотримання Сарбанса-Окслі ), ви повинні мати можливість аудиту систем, щоб переконатися, що вони роблять те, що їм належить робити. У цих випадках набагато простіше забезпечити відповідність, коли весь доступ до даних здійснюється через збережені процедури. І коли всі спеціальні SQL видаляються, приховувати речі набагато складніше. Для прикладу, чому це було б «доброю справою», я посилаю вас на класичну книгу Кена Томпсона « Роздуми про довіру довіри» .


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

1
Я працюю в публічній компанії, і ми SOX сумісні. Це може бути мої погані знання щодо аудиту, але я не бачу різниці між проведенням аудиту на рівні БД (через збережені програми) або на рівні програми. Кожна програма повинна мати власну схему БД, і ця схема доступна лише з програми, а не поділяється між різними програмами.
Августо

зламане посилання ...
Alex R

@AlexR, стаціонарне посилання
Tangurena

2

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

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

Я був у ситуаціях, коли ми повністю використовували SP, DB надав API даних, і ми його використовували. Цей конкретний додаток був дуже масштабним і працював напрочуд добре. Після цього я нічого поганого не сказав про СП!

Є ще одна перевага - DBA записуватимуть усі ваші SQL-запити і з радістю оброблять усі реляційні ієрархії в БД, тому вам не доведеться цього робити.


3
gbjbaanb, більшість сказаного стосується старих баз даних. Більшість нових баз даних досить часто перекомпілюють запити, щоб вирішити, які нові оптимізації використовувати (навіть якщо вони зберігаються у виробництві). Я погоджуюся з тим, що ви сказали про використання БД як зовнішньої системи, але я також бачу, що це дуже багато роботи, оскільки додаток володіє базою даних, і обидва повинні бути синхронізовані якомога більше. Наприклад, з називанням таблиці / класів та полів / стовпців. Крім того, підхід до дозволу DBA писати процедури швидше нагадує розробку силосів, а не створення мультидисциплінарної команди.
Август

7
SP не завжди завжди ефективніші, і я думаю, що передача SQL DBA - це поганий шлях. Як експерт по домену, розробник повинен знати, які дані вони хочуть отримати і як їх отримати
Martijn Verburg

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

1
@Augusto the approach of letting the DBAs write the procedures smells like development silos+100 інтернетів вам за цей дорогоцінний камінь істини. Я завжди розглядав це як випадок, коли доступ до даних контролювався за допомогою збережених процедур.
maple_shaft

1
@maple_shaft: чому, не вважаються DBA, які пишуть SP, частиною команди розробників? Там, де це працює, вони є спеціалізованими кодерами, які добре знають цей аспект системи, набагато краще, ніж більшість розробників загального призначення. Це може бути проблемою, що спричинила популярність ORM. Я маю на увазі, що ніхто б не замислювався над тим, щоб дизайнер займався графічним інтерфейсом, то чому ж ненависть архітектора даних робить схему?
gbjbaanb

2

Часто трапляється те, що розробники неправильно використовують свої об'єкти ORM як свої доменні моделі.

Це неправильно, і пов'язує ваш домен безпосередньо зі схемою БД.

Що насправді повинно мати окремі моделі доменів настільки багаті, як вам подобається, та використовуйте шар ORM окремо.

Це означає, що вам буде потрібно картування між кожним набором об'єктів.


1
Це гарна ідея, але для менших проектів вона справді починає відчувати себе надмірною. Цей підхід також вимагає рівня перекладу між стійким шаром ORM та моделлю домену.
maple_shaft

@maple_shaft погодився, і саме це я мав на увазі під «картографуванням» :-)
ozz

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

@Augusto Я теж це зробив! і, як каже maple_shaft, це добре для невеликих додатків у стилі CRUD, але існує багато проблем, як з'ясовує ОП. Одним із прикладів може бути те, де у вас є багато-багато таблиць з картографуванням, наприклад: StudentClasses, що позначає студентів на їхні класи та просто містить StudentID та classID, вам не обов'язково хотіти відображати це у вашому домені. Це просто швидкий приклад із верхнього мого голови.
ozz

2
@Ozz: Ваш коментар, здається, суперечить самій ідеї ORM. ORM не "прив'язує ваш домен безпосередньо до вашої схеми БД". ORM відображає ваш домен у схемі DB без необхідності окремого шару DAO. У цьому вся суть ОРМ. І більшість ORM-файлів обробляють багато-багато-багато відображень просто без необхідної моделі домену для таблиці відображення.
Кевін Клайн

1

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


Зараз ми використовуємо картографічні дані, але проблема полягає в тому, що вони зберігають документи повертають мінімальний набір даних, що іноді недостатньо для заповнення об'єкта (можливо, ми повинні дозволити збереженим процедурам повернути більше інформації). Наприклад, один магазин Pro може повернути електронну пошту користувача, ім'я та прізвище; а інший додає userid та адресу. Оскільки дані різні, ми використовуємо різні об’єкти для зберігання даних, це означає, що у нас є різні класи "Користувач". Я намагаюся тут не використовувати спадщину, тому що думаю, що це неправильне використання.
Августо

@Augusto: Інтерфейси?
Відновити Крамію Моніку

@Karmii, я не думаю, що тут допомагають інтерфейси, оскільки нам тоді потрібно було б дублювати логіку в різних класах. Або ми можемо використовувати інтерфейси, а потім делегувати обробку на хелперний клас, але це насправді не OO :(.
Августо

1
@Augusto Я не розумію проблеми: "збережені програми повертають мінімальний набір даних, чого іноді недостатньо для заповнення об'єкта". Отже, ви змінюєте проросток або створюєте інший, а потім дозволяєте картографію даних робити відображення
NimChimpsky
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.