Де “рівень бізнес-логіки” вписується в програму MVC?


86

По-перше, перш ніж хтось кричав дурнем, мені було важко сформулювати це в простому заголовку. Інший заголовок міг би бути "Яка різниця між моделлю домену та моделлю MVC?" або "Що таке модель?"

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

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

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

Як би ви відокремили послуги ASP.NET (постачальник членства, постачальник ролей тощо) від моделі? Або ти хотів би взагалі?

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

Хтось хоче пролити світло на це питання?


1
Ось чому вам слід задати чотири окремі запитання.
Джон Фаррелл,

3
Ключове слово "майже". Це насправді одне і те ж питання, можливо, підзапитання використані для ілюстрації основного питання.
Ерік Функенбуш

3
Модель - Вид - Контролер. Це репосирори / BL View? Ні. Це контролер? Ні. Що залишилось :)? Це MVC, а не MSVC, не MRVC, не MBLVC. Є всього три шари. Отже, сховище є частиною моделі, BL є частиною моделі. І ви можете зробити додаткове розділення, але це робиться всередині шару моделі.
LukLed

3
@LukeLed, @bslm - Не дуже. MVC не говорить, що не може бути інших шарів, з якими взаємодіє контролер або модель.
Джон Фаррелл,

3
@LukLed - Не згоден - MVC - це просто шаблон презентаційного шару. Це не впливає на структуру ваших інших шарів, таких як BLL та DAL.
Cory House,

Відповіді:


69

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

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

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

Справа в тому, що я працюю з кредитними картками - я повинен вимагати cvv під час обробки платежу, але я не можу зберігати cvv (це штраф у розмірі 50 000 доларів США). Але я також хочу, щоб ви могли редагувати свою кредитну картку - зміну адреси, імені чи терміну дії. Але ви не збираєтеся давати мені номер або cvv під час редагування, і я, звичайно, не збираюся розміщувати номер вашої кредитної картки простим текстом на сторінці. У моєму домені є ці значення, необхідні для збереження нової кредитної картки, оскільки ви надаєте їх мені, але моя модель редагування навіть не включає номер картки або cvv.

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

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

<% if (!String.IsNullOrEmpty(Model.SomeObject.SomeProperty) && 
    Model.SomeObject.SomeInt == 3 && ...) { %>

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


Приблизно дзеркало того, що я маю в нашому корпоративному додатку MVC. Архітектура N-Tier. Додаток MVC взаємодіє лише з бізнес-об'єктами та послугами в N-Tier зонах.
Ed DeGagne

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

1
@Josh, було б корисно, якщо б ви могли показати знімок екрану вашого зразкового проекту?
shaijut

@Josh що, якщо ваш проект не має бази даних. Він взаємодіє зі посиланнями на послуги. Усі класи доменів та методи походять з цих посилань. Чи підходить цей сценарій для шаруватої структури?
user6395764

17

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

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

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

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

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

Для широко поширеної парадигми моделі анемічних даних (як доброї, так і поганої) модель буде одночасно і сервісним рівнем, і вашими об’єктами даних.


Чудовий момент! Одне зауваження: там така ж каша з Послугами. Принаймні послугами можуть бути Служби додатків та Домени. Служба додатків - це лише тонка обгортка, яка збирає інформацію зі сховищ тощо. Служба доменів надає ділову логіку, тобто використовує комбінацію моделей доменів або просто речі, які не завжди вкладаються в модель домену.
Artru

а якщо ваш проект не має бази даних. Він взаємодіє зі посиланнями на послуги. Усі класи доменів та методи походять з цих посилань. Чи підходить цей сценарій для шаруватої структури?
user6395764

3

На мою думку,

Модель -

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

Бізнес-логіка -

Його слід розмістити на рівні «Доменні послуги», це взагалі окремий шар. Крім того, додамо ще один шар сюди "Служби програм".

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

Отже, контролер запитає Службу додатків про модель, і потік буде йти як

    Controller->Application Services(using domain services)->Model

2

Шаблон MVC та структура Asp.net не робить різниці щодо того, якою має бути Модель.

Власні приклади MS включають класи стійкості в моделі. Ваше питання про членство в моделі. Це залежить. Чи належать заняття у вашій моделі чимось? Чи існує зв’язок між тим, хто входить і які дані відображаються? Чи існує фільтрація частини даних системи дозволів, яку можна редагувати? Хто останній раз оновлював або редагував об’єкт, який є частиною вашого домену, як це вимагає хтось інший, щоб побачити його чи щось для внутрішньої підтримки?

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

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

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

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