Жирна модель / тонкий контролер проти сервісного рівня [закрито]


83

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

Нещодавно ми почали працювати над проектами MVC 3, і ми обговорили, куди подіти яку логіку. Я зіткнувся з тонкою архітектурою Controller / FAT Model і мені було цікаво, як укладеться рівень обслуговування

Варіант 1 - Модельні розмови зі службами

Контролер тонкий, викликає методи на моделях. Моделі "знають", як завантажувати себе з БД і спілкуватися зі сховищами чи службами. Наприклад, customerModel має метод Load (id) і завантажує клієнта та деякі дочірні об'єкти, такі як GetContracts ().

Варіант 2 - Контролер звертається до служб

Контролер просить Служби отримати об'єкти моделі. Логіка завантаження / зберігання тощо знаходиться в сервісному рівні. Модель є чисто суттєвою моделлю лише з даними.

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

Дякуємо за всі поради та посилання на хороші ресурси.

Відповіді:


94

Все це залежить від намірів та вимог вашої заявки.

Тим не менш, ось моя пропозиція щодо веб-програм "середнього масштабу" (не місцевого ресторану та не Twitter / Facebook).

  1. Lean Domain Modeling

    Сушіть об'єкти стилю POCO, бажано не знаючи архітектури MVC вашого веб-додатку, щоб залишатися якомога вільнішим від вашої конкретної реалізації. Можливо, навіть бібліотека класів, що перепаковується для використання у зовнішній програмі, скажімо REST API через веб-службу WCF ).

    "Модель" у MVC найточніше означає модель, про яку знає Контролер, а отже модель, призначену для Перегляду .

    У менших (часто навчальних) програмах моделі сутності вашого "Рівня моделі додатка / домену" часто є однаковими екземплярами об'єктів, які контролер передає до подання.

    У великих додатках розробники часто використовують принципи архітектури MVVM і починають використовувати окремі об'єкти View Model. Контролери часто звертаються до служб середнього рівня, які працюють з невидимими сутностями нижче. У цьому випадку M в MVC найбільш точно означає модель перегляду.

  2. Міцний рівень обслуговування

    Це не означає ожиріння логіки, а добре написані одноцільові послуги. Хоча кодування вашої бізнес-логіки в послугах поза моделлю є трохи більш "процедурним", ніж чисте "ООП", воно дуже допомагає при вільному з'єднанні, тестуванні та гнучкому розгортанні (наприклад, розгортання n-рівня).

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

  3. Пісні контролери

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

    1. Служби дзвінка, які взаємодіють із моделями сутності / домену

    2. Підготуйте модель вигляду для відповідного вигляду.

    Навіть автентифіковані / уповноважені дії контролера виконуються за допомогою введених служб / атрибутів.


EDIT 1:

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

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

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


РЕДАКТУВАТИ 2:

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


EDIT 3:

Я хотів зазначити, що це пояснення та поради стосуються контексту архітектури MVC на стороні сервера, як ASP.Net, а не таких платформ, як Knockout або Backbone.


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

2
@Lester Я редагував, щоб це прояснити. 95% випадків шахти теж не роблять, ідея полягає в тому, що служби роблять це. У невеликих додатках це може бути надмірним, але це хороша практика для всіх і набагато простіше підтримувати за допомогою контейнера IoC
one.beat.consumer

1
+1 @ one.beat.consumer: це той самий підхід, який я застосовую до своїх проектів ... іноді занадто пуристичне ставлення до правил призводить до надскладних рішень, і ви можете отримати більше переваг від перевіреного в реальному світі рішення, яке не ідеально дотримується зразків GOF
themarcuz

7
Модель @ivowiblo у MVC - це будь-яка модель даних, яку ваш контролер готує та передає до подання. Ось чому ваша „модель програми” (модель домену, рівень моделі, що б ви не позначили) може абсолютно не знати про бібліотеки MVC, навіть існувати поза вашим рішенням в окремо розподіленій системі. У MVC запит просто направляється на контролер. Контролер збирає модель подання (дані для рівня презентації). Якщо ця модель такої ж , проілюстрований об'єкт , який ви використовували у вашому механіці наполегливості, поганий практиці , може бути, але це буде дозволено, тобто не виняткове визначення.
one.beat.consumer

2
+1 для Майте на увазі "Модель" у MVC найточніше означає модель, про яку знає Контролер, а отже модель, призначену для Перегляду.
Luiz Damim

16

Вам потрібно знати трохи більше про MVC, перш ніж ми продовжимо обговорювати, куди все покласти. Добре, якщо ви хочете слідувати шаблону. В іншому випадку ви можете перестати читати зараз.

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

MVC

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

Контролер Контролер - це клей. Він бере інформацію з Моделі та адаптує її до подання та навпаки.

Перегляд Перегляд повинен відображати лише те, що бачить користувач.

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

Відповідь

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

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

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

Зверніть увагу, що рівень обслуговування може не знадобитися. Ви можете зателефонувати OR / M безпосередньо з контролерів. Але якщо ви виявили дублювання коду або отримання контролерів жиру, просто перемістіть логіку на сервісний рівень. Ці зміни не вплинуть ні на що, крім контролера, оскільки ви використовуєте належні моделі перегляду.


3
Я хотів би, щоб ASP.NET MVC був названий ASP.NET ModelView View Controller. Це було б жахливе ім'я, але принаймні воно передало б його справжнє значення :)
Hector Correa

Навіть після використання ASP.NET MVC мені зайняв деякий час, щоб зрозуміти, що модель не означає модель перегляду.
Лестер

@ one.beat.consumer: Моя думка щодо Моделі полягала в тому, що вона може бути будь-якою. Це просто шар там. Створіть його так, як він підходить для програми. Я висловлююсь так, оскільки багато хто вважає, що Модель в ASP.NET MVC є Моделью Перегляду або що ВМ і Модель однакові.
jgauffin

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

2
Тут важлива семантика @jgauffin - у MVC "модель" не означає "модельний шар"; це тільки означає , зразковий об'єкт , придатний для контролера , щоб перейти до View . У значних додатках архітектура MVC часто навіть не знає про рівень моделі / даних або про те, що ви вирішили назвати. Моя відредагована відповідь намагається пояснити цю плутанину ... головним чином, коли додатків мало, часто немає потреби в додатковому розділенні моделі Model і View, тому люди, як правило, розмічають свої моделі і дозволяють контролерам використовувати сховище тощо. повнорозмірні програми, це рідко трапляється.
one.beat.consumer

0

Варіант 1: Можна подумати, що модель == послуга. Модель також Є діловим рівнем.

Варіант 2 - це анти-шаблон Анемічної моделі домену. http://en.wikipedia.org/wiki/Anemic_domain_model


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

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

0

Варіант 2 - це те, що описується як архітектура Fat Stupid Ugly Controllers ( Посилання на автора цього виразу ). Це рішення, як правило, суперечить духу MVC, оскільки воно порушує розділення проблем.


1
public ActionResult FetchApple() { return View(_groceryService.GetApple("Granny Smith")); }досить худий, якщо ви запитаєте мене.
one.beat.consumer

4
Моє прочитання цієї статті FSUC не відповідає варіанту 2 вище. Приклад, наведений автором FSUC, не показує використання сервісного рівня, де інкапсульована вся ця логіка впорядкування. Натомість це показує, що контролер завантажений бізнес-логікою. І багаторазове використання бізнес-логіки внаслідок перебування в контролері втрачено.
Marvo
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.