MVC: Куди подіти бізнес-логіку? [зачинено]


81

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

Я подивився, наприклад, це, і відповідь, яка проголосувала за 45+, говорить, що він радить вкласти бізнес-логіку в модель, що звучить досить логічно.

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

Людина на youtube запитала мене, чи має він рацію, вкладаючи всю логіку у свої моделі, і спочатку я була ні! Тоді я почав думати, що, можливо, він мав рацію !?

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


1
Бізнес-логіка полягає в контролерах. Логіка моделі входить у модель. Логіка моделі - це речі, які стосуються моделі конкретно / лише. Сеттери / геттери / властивості / суматори / видалення тощо
розчавити

1
@crush: Я не згоден. Як я вже читав - "Модельний об'єкт містить дані програми та" ділову логіку "та" Об'єкти контролера пов'язують модель та об'єкти перегляду ".
ChiefTwoPencils

@BobbyDigital - чи можете ви надати посилання на джерело? :)
Andrius Naruševičius

Звичайно, це пояснюється правильним використанням MVC у «Керівництві ранчо великих ботанів», але, на жаль, вам доведеться придбати книгу, щоб підтвердити це.
ChiefTwoPencils

Я скажу, однак, щойно спробувавши підтвердити це в книзі C #, в asp.net бізнес-логіка йде в середній рівень, де верхнім рівнем буде інтерфейс користувача, середнім - контролер, а нижчим - db. Але вони не говорять конкретно / явно про MVC. Це походить від C # для програмістів :)
ChiefTwoPencils

Відповіді:


55

Я вважаю за краще вкладати в модель логіку домену з кількох причин.

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

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


2
Так, мені дуже сподобалось, #2тому що мені було важко ділитися між контролерами самому (довелося використовувати такі методи, як статичний)!
Andrius Naruševičius

Так @ AndriusNaruševičius, не роби цього. Вам слід спробувати ввести свої залежності в контролери, а не покладатися на інші контролери.
Марк Уолш,

Зауважте, що, на мою думку, у цій відповіді йдеться про "доменні моделі" (M-частина класичного шаблону MVC), що не стосується "моделі" ASP.Net MVC (частина шаблону MVVM).
Олексій Левенков

1
Отже ... де ви ставите логіку, яка спирається на кілька моделей?
Каньйон Колоб

1
@Ferrucio Це погане рішення. Ви потрапляєте в "пекло залежностей", де створюєте об'єкти, які покладаються на інші об'єкти, які потрібно створити. Це погане рішення, оскільки непотрібні / невикористані дані передаються без причини. Ви хочете, щоб функції приймали лише те, що їм потрібно для виконання роботи - інакше код стає дуже незрозумілим дуже швидко. Кращим рішенням є створення класів бізнес-логіки, для побудови яких необхідний мінімум (а ще краще - використовувати ін'єкцію залежностей для побудови). Таким чином, вам ніколи не доведеться отримувати кілька непов’язаних об’єктів для здійснення бізнес-логіки.
Каньйон Колоб,

43

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


5
+1 повністю погоджуюсь. Я думав, що мені єдиному подобається зводити відповідальність моделей до мінімуму!
Lee

1
Звичайно, він суть мого контролера входу gist.github.com/markwalsh-liverpool/8fb361a9df0dcf034caf
Марк Уолш

1
Тож якщо ви не вкладаєте свою логіку у свої моделі чи контролери - куди ви її вкладаєте?
niico

1
Як ви передаєте аргументи конструктору контролера? Хіба ініціалізація контролера зазвичай не проводиться за кадром?
Джефф,

1
Я використовую ін’єкцію залежності.
Марк Уолш

23

Бізнес логіка відноситься до проблемної області , і все , що належить до проблемної області йде до моделі в MVC.

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

Ключовим тут є різниця між бізнес-логікою та логікою сантехніки. На мою думку, те, що робить автоматично згенерований Контролер облікових записів, - це в основному сантехніка, а не насправді ділова логіка. Пам’ятайте, що сантехнічна логіка зовсім не обов’язково коротка, тому вам не потрібно встановлювати штучні обмеження (наприклад, „X кількість дзвінків не більше в контролері“).


Я з усім цим погоджуюсь. Однак, я думаю, багато плутанини виникає в тому, як структурувати класи в моделі, особливо з EF. IE: чи використовуєте ви часткові класи та будуєте логіку в різних файлах C #? один файл для EF та один файл для логіки?
S1r-Lanzelot

13

Коли моя команда перейшла на mvc із веб-форм (asp.net), провела багато досліджень і придумала таку структуру. На мою думку, справа не в тому, наскільки велика чи мала програма. Йдеться про підтримку чистоти та чіткості коду.

DALProject

AccountsDAL.cs --- > Calls SP or any ORM if ur using any

BLLProject

AccountsBLL.cs ---> Calls DAL

WebProject

Model
    AccountsModel --- > Contains properties And call BLL
Controllers
    IndexController ---> Calls Models and returns View
Views
    Index

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


13

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

Архітектура N-рівня пов'язана з поділом програми на кілька рівнів. Простим прикладом є те, що програма розділена на рівень презентації, рівень бізнес-логіки та рівень доступу до даних.

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

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

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

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


8

Взагалі кажучи, ділова логіка не повинна знаходитися в жодному з гравців MVC; він повинен споживатися лише вашими діями контролера.

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

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

Абстрагування нашої ділової логіки в самостійну асамблею (або збірки) нам добре допомогло протягом багатьох років. Тоді наша бізнес-логіка може використовуватися практично будь-якою технологією .NET (ASP.NET MVC / API / Core, WPF, Win Forms, WCF, UWP, WF, Console тощо).

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

Логічне проектування нашого середнього рівня таким чином дозволило нам легко досягти цієї фізичної архітектури:

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

Він був написаний на Peasy.NET і добре служив нам протягом багатьох років. Настільки добре, що ми вирішили відкрити його.

Якщо комусь цікаво, як виглядає наш середній рівень, ось зразок бізнес-рівня агностичного клієнта. Він також демонструє споживання його багатьма клієнтами .NET (ASP.NET MVC, Web Api та WPF).

Сподіваюся, це комусь допомагає!


В основному немає необхідності повторно використовувати логіку. Якщо я, скажімо, вирішу використовувати ASP.NET Core MVC для веб-API, я ніколи не захочу використовувати цю бізнес-логіку в WPF або WinForms. Тому що клієнт у будь-якому випадку зв’яжеться із сервером. Розміщувати бізнес-логіку і особливо логіку доступу до бази даних на стороні клієнта - це просто погано.
Конрад,

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

8

Бізнес-логіка не повинна входити у ваші подання моделей або контролери. Повинен бути окремий рівень логіки бізнесу ; єдиною метою цього рівня є обробка вашої бізнес-логіки. Це більше відповідає твердому .

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

А як щодо введення логіки в Моделі?

Це погане рішення.

Ви потрапите в пекло залежності, де об’єкти покладаються на об’єкти. введіть тут опис зображення

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

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

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

Застосовувані принципи чистого кодексу

  1. Класи / функції виконують лише те, що їм потрібно для виконання роботи.
  2. Функції повинні приймати 3 параметри або менше, якщо це можливо
  3. Класи / функції / змінні іменуйте розумно (дотримуйтесь стандартів Microsoft)
  4. Не поєднуйте ділову логіку з переглядом моделі або контролером

Контролери

У своєму контролері ви зможете використовувати ін’єкцію залежностей для введення рівня бізнес-логіки . Переконайтеся, що контролер використовується лише для маршрутизації інформації на рівень бізнес-логіки. Контролер НЕ повинен мати ділової логіки безпосередньо в ньому. Будь-яка перевірка повинна оброблятися IValidatableна Моделі. Будь-яку ділову логіку потрібно направляти в окремий рівень.


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

@MateusFelipe Отже, де ви ставите логіку, яка вимагає декількох моделей (наприклад: Оплата та товар)? Ви створюєте нову модель, яка має Paymentта Productяк змінну екземпляра? Як ви називаєте цей предмет? Якщо модель не використовується у поданні, це вже не модель. Це частина окремого шару. В ідеалі той клас, який ви робите, повинен брати лише те, що йому потрібно, з оплати та товару, щоб зробити свою роботу. Якщо йому потрібні лише productNameі price, він повинен приймати лише ці два параметри, а не весь об'єкт.
Каньйон Колоб

4

Загальна відповідь, яку я маю, полягає в тому, що бізнес-логіка зазвичай поділяється на дві категорії:

Об'єктно-орієнтована бізнес-логіка: отримує змодельовані як об'єкти (у моделі), зазвичай вводяться як сховища.

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

Логіка контролера: Логіка, яка контролює, як команди отримуються та передаються моделям / службам, а потім як ці результати передаються у подання.

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


2

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


1

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

1. Контролер WebApi: Перевага використання контролера webapi полягає в тому, що ви можете надавати їх як послуги пізніше на інші пристрої, завдяки чому ваш код можна використовувати повторно.

2. BAL / Common commonent: Є деякі логіки, які мають специфічне використання і не можуть бути виставлені як API, можуть бути використані в цьому класі.

3. Сховище: Усі запити, пов’язані з базою даних, додаються до сховища. Може існувати загальне сховище, яке реалізовуватиме всі функції (операції CRUD) або конкретні сховища для кожної таблиці. Залежно від операцій, які потрібно виконати.


1

Як писав ahanusa, вам слід розмістити логіку бізнесу в окремій бібліотеці DLL або в окремому каталозі.
Я часто використовую каталог "Логіка" на тому ж рівні "Моделі та контролери", куди я кладу класи, які роблять бізнес-логіку.
Таким чином я даю чистити і моделям, і контролерам.


0

Я знаю, що це питання про MVC, але я думаю, що приклад, який я даю (Веб-API), буде корисним.

Я розробляю свій перший веб-API і повторно використовую бізнес-логіку з інших додатків. Якщо бути конкретним, він походить із зовнішньої бібліотеки DLL, тому мій API використовується просто для «розмови» з рішенням SAP, отримання запитів від PO та надсилання відповідей назад.

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

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

Мені не подобається, коли моя програма (в даному випадку веб-API) тримає бізнес-логіку, я думаю, що таким чином буде втрачено можливість повторного використання.

Я розглядаю свою бізнес-логіку як залежність, яку я ввожу в контролер.

Я зробив багато рефакторингу у застарілій версії, щоб надати рішення Unit Testable, мені довелося створити багато інтерфейсів та впровадити деякі шаблони дизайну в спадщину, щоб надати це рішення.

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

Звичайно, якщо ваш CORE (бізнес) - це ваша програма (API / WebSite) , правила бізнесу будуть впроваджені у ваші класи MVC. Але в майбутньому, якщо ви хочете розробити новий додаток, а деякі ділові правила однакові, я впевнений, що у вас буде багато проблем, просто підтримувати однакову логіку, застосовану в обох додатках.

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