Чи дизайн, керований доменом, має шаблон SQL?


44

Я занурююся в дизайн, орієнтований на домен (DDD), і хоча я заглиблююсь у нього, є деякі речі, які я не розумію. Як я розумію, головний момент - це розділити Логіку домену (Business Logic) від інфраструктури (БД, файлова система тощо).

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

Зробити ці обчислення в інфраструктурі теж не може, тому що схема DDD дозволяє змінити інфраструктуру, не змінюючи Доменний шар і знаючи, що MongoDB не має тих же можливостей, як, наприклад, SQL Server, цього не може статися.

Це підводний зразок DDD?


34
Хоча SQL розроблений для обробки алгебри реляційних заданих, це не веселий день, коли ви розумієте, що половина вашої ділової логіки похована в безлічі функцій SQL, які важко переробити і ще важче перевірити. Отже, переміщення цього до доменного шару, де він може грати зі своїми друзями, мені здається привабливим. Це викидання є гарним фрагментом технології SQL? Звичайно, але SQL набагато простіше в управлінні, коли ви використовуєте лише SELECT / JOIN.
Джаред Гогуен

30
@JaredGoguen, але це може бути тому, що ваш не експерт SQL, а не завдяки технології
Леонардо Мангано

2
@JimmyJames, що я намагався сказати, це те, що якщо DDD добре реалізований, він дозволяє змінювати шари з мінімальними зусиллями, як, наприклад, перехід з SQL Server на MongoDB. Але якщо у SQL є складні запити, можливо, я не зможу перейти на MongoDB через їх технічні відмінності. Я думаю, що я сказав очевидну річ.
Леонардо Мангано

7
... is like throwing away the SQL technologyТільки тому, що певна технологія може щось зробити, це не означає, що це найкращий вибір. Це анекдотичні докази, але я зустрічав занадто багато підприємств, які використовували для зберігання бізнес-логіки в базі даних і мігрують від неї через тривалі головні головні болі в ремонті. Попрощення, але бази даних призначені для зберігання даних, а мови програмування призначені для перетворення даних. Я б не хотів більше використовувати БД для бізнес-логіки, ніж хотів би спробувати використовувати свій додаток для прямого зберігання даних.
Conor Mancone

8
Сам SQL - прекрасний приклад DDD. Зустрічаючись з організацією пов'язаних даних, люди спочатку вказали мову для цього: SQL. Реалізація насправді не має великого значення. Адміністратору БД не потрібно знати C / C ++ для запиту бази даних. Аналогічно, стикаючись із завданням планування подій, хтось придумав синтаксис CRON (mhdmw) просту модель домену, яка відповідає 99% проблем із плануванням. Основою DDD є не створення класів чи таблиць тощо. Це зрозуміти свою проблему і придумати систему для роботи у вашій проблемній області
slebetman

Відповіді:


39

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

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


13
+1 Хороша відповідь, але ви повинні дати цій концепції її правильну назву - Сегментація команд-запитів.
Майк

6
@Mike Маючи абсолютно різні моделі для читання та письма, більше схожі на CQRS, а не на CQS.
Енді

3
"Модель читання" - це не доменна модель (або її частина)? Я не фахівець з CQRS, але я завжди вважав, що командна модель сильно відрізняється від класичної доменної моделі, але не зчитується. То, може, ви можете навести приклад для цього?
Док Браун

Займав мене занадто довго, щоб зрозуміти, що марка високої продуктивності привертає увагу до друкарської помилки.
VoiceOfUnreason

@DocBrown - ось моя спроба уточнити для вас -> cascadefaliure.vocumsineratio.com/2019/04/…
VoiceOfUnreason

21

Як я розумію, головний момент - це розділити Логіку домену (Business Logic) від інфраструктури (БД, файлова система тощо).

Це є основою непорозуміння: мета DDD - не розділяти речі на жорсткій лінії типу "це на SQL-сервері, тому не повинно бути BL", мета DDD - розділити домени та створити бар'єри між ті, які дозволяють внутрішнім домену бути повністю відокремленими від внутрішніх даних іншого домену та визначати спільні зовнішні між ними.

Не думайте «бути в SQL» як бар'єр BL / DL - це не те, що це є. Натомість подумайте про "це кінець внутрішнього домену" як бар'єр.

Кожен домен повинен мати зовнішні інтерфейси API, які дозволяють йому працювати з усіма іншими доменами: у випадку шару зберігання даних він повинен мати дії для читання / запису (CRUD) для даних, що зберігаються. Це означає, що сам по собі SQL не є бар'єром, VIEWа PROCEDUREкомпоненти є. Ви ніколи не повинні читати безпосередньо з таблиці: що є деталлю реалізації DDD говорить нам , що, як зовнішній споживач, ми не повинні турбуватися.

Розглянемо ваш приклад:

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

Це саме те, що повинно бути тоді в SQL, і це не порушення DDD. Це для чого ми зробили DDD . З таким розрахунком у SQL, що стає частиною BL / DL. Що ви могли б зробити , це використовувати окремий вид / збережена процедура / що-у-ви, і тримати бізнес - логіка відокремлена від даних шару, так що ваш зовнішній API. Фактично, ваш рівень даних повинен бути ще одним рівнем домену DDD, де у вашого рівня даних є власні абстракції для роботи з іншими доменними шарами.

Зробити ці обчислення в інфраструктурі теж не може, тому що схема DDD дозволяє змінити інфраструктуру, не змінюючи Доменний шар і знаючи, що MongoDB не має тих же можливостей, як, наприклад, SQL Server, цього не може статися.

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

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

DDD не налаштований, щоб дозволити одночасно замінити MSSQL на MongoDB - це два абсолютно різні інфраструктурні компоненти.

Замість цього давайте скористаємось аналогією для того, що DDD визначає: газові та електричні машини. У обох транспортних засобів є два абсолютно різних способу створення приводу, але вони мають однакові API: включення / вимкнення, дросель / гальмо та колеса для приводу автомобіля. DDD каже, що ми повинні мати можливість замінити двигун (газовий або електричний) в нашому автомобілі. Це не говорить про те, що ми можемо замінити автомобіль на мотоцикл, і це ефективно те, що MSSQL → MongoDB.


1
Дякую за пояснення. Для мене дуже важка тема, кожен має різну точку зору. Єдине, з чим я не згоден - це порівняння між MSSQL (автомобіль) та MongoDB (мотоцикл), для мене правильне порівняння - це два різні двигуни для однієї машини, але це лише думка.
Леонардо Мангано

8
@LeonardoMangano Ага, але це не так. MSSQL - це реляційна база даних, MongoDB - це база даних документів. Так, "база даних" описує і те, і інше, але це приблизно настільки, наскільки це йде. Методи читання / запису абсолютно різні. Замість MongoDB ви можете використовувати Postgre або MySQL як альтернативу, і це було б достовірним порівнянням.
410_Gone

3
"Ніколи не слід читати прямо зі столу ..." Божевілля.
jpmc26

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

@LuciferSam Aye. Це значно полегшує управління розділенням між деталями реалізації та межами домену. Один "об'єкт" у домені може бути представлений 5 таблицями, тому ми використовуємо View для інкапсуляції цього об'єкта.
410_За

18

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

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

Відхилення від архітектурного зразка

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

  • Це правильна модель? (багато разів це буває, але іноді це просто погано підходить)
  • Чи варто відхилятися таким чином?
  • Наскільки я далеко відхилився?

Ви побачите, що деякі архітектурні зразки добре підходять для 80-90% вашої програми, але не стільки для решти бітів. Епізодичне відхилення від встановленого зразка є корисним з міркувань продуктивності чи логістики.

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

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


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

@RobertHarvey, я був у проектах, де використовуваний шаблон був просто невідповідним для програми, через що він не міг певних показників якості. Це, звичайно, не норма, але коли це станеться, у вас важке рішення змінити архітектуру або зберегти код вбудування в додаток. Чим раніше ви зможете визначити погану форму, тим простіше це виправити. Ось чому я завжди включаю цю думку під час оцінки кращих випадків. Поряд із останньою кулею, іноді ви не усвідомлюєте, наскільки це погано підходить, поки не побачите скупчення відхилень.
Берін Лорич

7

Задана логіка маніпулювання, якою добре користується SQL, без проблем може інтегруватися з DDD.

Скажімо, наприклад, мені потрібно знати деяку сукупну величину, загальну кількість продуктів за видами. Легко запускати в sql, але повільно, якщо я завантажую кожен продукт в пам'ять і додаю їх усі.

Я просто представляю новий об’єкт Домену,

ProductInventory
{
    ProductType
    TotalCount
    DateTimeTaken
}

і метод у моєму сховищі

ProductRepository
{
    List<ProductInventory> TakeInventory(DateTime asOfDate) {...}
}

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


Ну, поки що пригадую. Репозиторії також повинні отримуватись Queryяк параметри. repository.find(query);. Я читав те саме, але з Specs. That opens a door to leave Query` як абстракцію та QueryImplабо реалізацію конкретного запиту до інфраструктурного рівня.
Лаїв

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

I know some people do thatдеякі люди - основні та його основи. SpringFramework має багато цього :-). У будь-якому разі, як підказав @VoiceOfUnreason, ключовим моментом навколо DDD є збереження послідовності записів. Я не впевнений у тому, щоб змусити дизайн доменних моделей, єдиною метою яких є запити чи параметризація запитів. До цього можна звернутись із сфери даних із структурами даних (pocos, pojos, dtos, картографічні рядки тощо).
Лаїв

Очевидно, нам потрібна якась допитливість, щоб допомогти людям повернутися до здорового стану. Але я дотримуюсь своїх гармат. Часткове опромінення рівня даних є прийнятним, коли воно об'єктивно сприяє кращому застосуванню, де суб'єктивним є те, що є чи ні "Об'єкт домену"
Ewan

1
@LeonardoMangano залежить від вашої заявки та реалізації. Головне усвідомити, що ви можете переосмислити свій Домен, щоб зробити його практичним.
Еван

3

Один з можливих способів вирішити цю дилему - це думати про SQL як про мову монтажу: ви рідко, якщо взагалі кодуєте його безпосередньо, але там, де важлива робота, вам потрібно мати можливість зрозуміти код, створений вашим C / C ++ / Golang / Rust компілятор і, можливо, навіть написати мініатюрний фрагмент в зборі, якщо ви не можете змінити код на мові високого рівня, щоб створити потрібний код машини.

Аналогічно, у царині баз даних і SQL різні бібліотеки SQL (деякими з яких є ORM ), наприклад SQLAlchemy та Django ORM для Python, LINQ для .NET, забезпечують абстракції вищого рівня, але використовують генерований код SQL там, де це можливо для досягнення продуктивності. Вони також забезпечують певну портативність щодо використовуваної БД, можливо, мають різну продуктивність, наприклад, на Postgres та MySQL, завдяки деяким операціям, що використовують деякі більш оптимальні для конкретного DB-SQL.

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

PS Я б скоріше прокоментував це, але не маю достатньої репутації для цього.


2

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

Як зауважує Джаред Гогуен у коментарях, перевірити та перевірити SQL може бути дуже важко. Основними чинниками, які призводять до цього, є те, що він не може (загалом) розкладатися на компоненти. На практиці складний запит повинен розглядатися в тото. Ще одним складним фактором є те, що поведінка та коректність SQL сильно залежать від структури та вмісту ваших даних. Це означає, що тестування всіх можливих сценаріїв (або навіть визначення того, що вони є) часто нездійсненно або неможливо. Рефакторинг SQL та зміна структури бази даних також є проблематичним.

Інший великий фактор, який призвів до відходу від SQL, - це реляційні бази даних, як правило, масштабуються вертикально. Наприклад, коли ви будуєте складні обчислення в SQL для запуску в SQL Server, вони збираються виконати в базі даних. Це означає, що вся ця робота використовує ресурси бази даних. Чим більше ви робите в SQL, тим більше ресурсів вашій базі буде потрібно як з точки зору пам'яті, так і з процесора. Це часто менш ефективно робити в інших системах, але практично немає обмеження в кількості додаткових машин, які ви можете додати до такого рішення. Цей підхід є менш дорогим та більш стійким до відмов, ніж створення сервера баз даних монстрів.

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


Хіба не альтернатива базі даних монстрів, просто жахлива кількість та різноманітність допоміжних систем? Яку стійкість мають допоміжні системи, якщо всі вони вибиваються з основної системи? І якщо виправданням є просто технологічне обмеження основної системи, то це часто буде передчасною оптимізацією для більшості бізнес-систем. Загалом, SQL можна писати роз'єднано, якщо це вважається необхідним.
Стів

@Steve Я думаю, що тут ви помилилися, припускаючи, що повинна існувати єдина основна система, від якої оточують інші.
JimmyJames

@Steve Щоб навести приклад, ви можете замінити всю систему системних баз даних однією базою даних без SQL (я не кажу, що це завжди правильний вибір, просто це можна зробити.) Цю базу даних потім можна зберігати в багатьох системи, навіть географічні регіони. Така БД не є допоміжною, це оптова заміна SQL БД.
JimmyJames

@JimmyJames, погодився, але коли немає основної системи, яка може створювати власні проблеми аналізу залежностей та збереження узгодженості даних. Ось причина в першу чергу монолітів - вони створюють певний вид простоти, а отже, певного виду ефективності аналізу та обслуговування. Немонолітні рішення просто обмінюються одними проблемами або витратами на інші.
Стів

@jmoreno Кидаючи ресурси на щось, аби прокинутись разом із цим, це не те, що я б назвав гарною інженерією: "для того, щоб обробляти величезний об'єм даних на сайті, і працює 9000 примірників, що зберігаються, щоб не відставати від кількості транзакцій база даних повинна обслуговуватися. " Ви вважаєте, що вартість вашої конструкції чи ви вважаєте, що хтось виділить гроші, щоб зробити ваші особисті переваги працездатними?
JimmyJames

2

Це підводний зразок DDD?

Дозвольте спочатку вияснити кілька помилок.

DDD не є зразком. І це насправді не призначає шаблонів.

У передмові до книги про DDD Еріка Евана зазначено:

Провідні розробники програмного забезпечення визнали моделювання домену та дизайн домен як найважливіші теми протягом принаймні 20 років, але напрочуд мало написано про те, що потрібно зробити або як це зробити. Хоча вона ніколи не була сформульована чітко, філософія виникла як недолік у спільноті об'єктів, філософію, яку я називаю дизайном, керованим доменом.

[...]

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

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

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

Інша річ, яку слід пам’ятати, - це те, що доменна модель - це не її реалізація OO, яку можна знайти у вашій системі - це лише один із способів її виразити або висловити якусь частину. Модель домену - це те, як ви думаєте про проблему, яку ви намагаєтеся вирішити за допомогою програмного забезпечення. Це те, як ти розумієш і сприймаєш речі, як ти говориш про них. Це концептуально . Але не в якомусь невиразному сенсі. Він глибокий і вишуканий, і є результатом наполегливої ​​праці та збору знань. Він доопрацьовується і, ймовірно, розвивається з часом, і він передбачає міркування щодо впровадження (деякі з яких можуть стримувати модель). Її слід поділити всім членам команди (та залучені експерти домену), і він повинен визначати, як ви реалізуєте систему, щоб система уважно відображала її.

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

Мене цікавить, що відбувається, коли у мене дуже складні запити [...]?

Ну, загалом, тут є два сценарії.

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

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


0

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

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

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

Чи вбудували б ви генератор PDF в драйвер принтера або додали тригер, який буде друкувати сторінку журналу для кожного замовлення на продаж, надрукованого з нашого принтера?

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

У 70-х - 90-х базах даних SQL були ефективними, зараз? - Не впевнений, що в деяких сценаріях асинхронний запит даних повертає потрібні дані швидше, ніж багаторазове приєднання до SQL-запиту.

SQL не був розроблений для складних запитів, він був розроблений для ефективного зберігання даних, а потім надання інтерфейсу / мови для запиту збережених даних.

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


1
Але я продовжую думати, що SQL набагато краще для заданих обчислень, ніж будь-яка інша мова. З моєї точки зору. ваш приклад перевернутий, використовуючи C # для дуже складних операцій з набором з мільйонами рядків і приєднань, використовуючи неправильний інструмент, але я можу помилитися.
Леонардо Мангано

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