.NET Архітектура / шари проекту MVC


11

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

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

Крім того, що складатиме логіку програми на відміну від бізнесу - я здогадуюсь такі речі, як перевірка сеансу / введення користувача?

Так, наприклад, контролер автомобіля може повернути результат дії / перегляду, в якому перераховано десятку найкращих автомобілів, відфільтрованих за типом та найкращими mpg. Так, скажімо, у мене введено ICarRepository"carRepo", що вводиться в контролер (використовуючи шаблон сховища / DI), я фільтрую свої машини за параметром методу дії, наприкладvar cars = carRepo.getCarsByType("hatchback");

Тому я зберігав знання про доступ до даних поза моїм контролером за допомогою сховища, тепер для того, щоб ділова логіка вийшла з контролера за допомогою доменної моделі - var result = new MpgCalculator (машини); - Скажімо, мені потрібен клас калькулятора, оскільки він повинен виконувати додаткову логіку для обчислення найкращої економії палива, більше ніж просто завантаження / фільтрування об'єктів з БД. Отже, тепер у мене є набір даних для відображення, який використовував репозиторій для отримання з рівня доступу до даних, і об'єкт, що стосується домену, для обробки та виконання завдань, пов'язаних з бізнесом, на цих даних.

Чи я тут помиляюся? чи все-таки нам потрібно використовувати шаблон сховища чи я можу просто кодувати проти інтерфейсу, щоб роз'єднати ORM і протестувати? У цій темі, оскільки мої конкретні класи (класи) доступу до даних dbcontext знаходяться в рівні даних, чи повинні визначення інтерфейсу переходити в рівень домен / бізнес, тобто, якщо технологія доступу до даних коли-небудь буде змінена, інші мої шари не будуть виконані?

З того, що я вивчив поки що, моя структура виглядає так:

Інтернет-додаток MVC -> Стандартний інтернет-проект - моделями тут є ViewModels

Доменний / бізнес-рівень -> бізнес-класи, класи / моделі, які контролери можуть використовувати для обробки об'єктів домену із рівня даних, перш ніж переходити до відповідних представлень даних

Необхідна абстракція сховища? -> Я чую багато дискусій з цього приводу, особливо під час використання ORM

Рівень даних -> Класи особи (Автомобіль, Ван, Мотоцикл), DbContext - Бетонний рівень доступу до даних

Відповіді:


26

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

Презентація <---> Бізнес-логіка <---> Доступ до даних

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

MVC (презентація)

У вашому додатку компонент ASP.NET MVC повинен вирішувати трансформацію бізнес-даних для цілей відображення (Моделі), відображення користувальницького інтерфейсу (Перегляди) та такі комунікаційні проблеми, як маршрутизація, автентифікація, авторизація, перевірка запитів, обробка відповідей та як (контролери). Якщо у вас є код, який робить щось інше, він не належить до компонента MVC .

Сховище / ORM (доступ до даних)

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

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

Отже, у вас є ваш презентаційний шар (MVC) та ваш рівень даних (сховище або ORM) ... Все інше - ваш рівень логіки бізнесу (BLL). Тут повинен бути весь ваш код, який визначає, які дані потрібно отримати, або виконує складні розрахунки, або приймає бізнес-рішення. Я зазвичай організую свою бізнес-логіку у вигляді «послуг», до яких мій рівень презентації може закликати виконати потрібну роботу. Усі мої доменні моделі існують тут.

Ваш підхід

Ось тут твій підхід трохи руйнується для мене. Ви описуєте свій контролер MVC як місце, де ви отримаєте дані з сховища, і закликаєте MPGCalculator виконати якусь роботу і т. Д. Я не мав би свого контролера робити цього, а натомість делегував би все це службі в BLL.

Іншими словами, я б не вводив сховище та MPGCalculator в контролер, це покладає на контролер занадто велику відповідальність (він вже обробляє всі контрольні речі, про які я згадував вище). Натомість я мав би службу в обробці BLL з усім цим і передав результати назад контролеру. Потім контролер може перетворити результати на правильну модель і передати їх правильному виду. У контролері немає ніякої ділової логіки, і єдине, що вводиться в контролер, - це відповідні послуги BLL.

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


Привіт Еріку, чудова відповідь - що стосується сховищ, я припускаю, що конкретні класи житимуть у шарі доступу до даних та "ICarRepository" тощо на рівні бізнесу / сервісу? Тоді я можу ввести сервіси в свій контролер, який може містити 1 або більше сховищ залежно від вимог?
Майкл Харпер

@MichaelHarper Так, це звучить як ідеально хороший спосіб робити це.
Ерік Кінг

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

1
@tom Так, у вас є хороший момент. Я думав про просту авторизацію, як у користувача є доступ до цього маршруту , але до нього може бути набагато більше. Частина "набагато більше їй" належить до бізнес-шару.
Ерік Кінг

1
@HunterNelson Якщо ви збираєтеся в перегляд у моделі перегляду, то відображення має відбуватися там, де перегляд, у презентаційному шарі. Не було б сенсу більше ніде.
Ерік Кінг

0

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

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

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


Дякую за відповідь, Вільям 😊 Я б вважав мої бізнес-об’єкти / логіку та доменні об'єкти "моделями", які контролер використовує для обробки дій користувача та моделей перегляду, як перегляд конкретних моделей, які можуть містити групи моделей тощо
Michael Harper
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.