Наскільки архітектура MVC наскільки тісно пов'язана модель та погляд на контролер?


16

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

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


1
Я не відповім, тому що мій досвід обмежений в архітектурах MVC, але, з усього, про що я чув і говорив з іншими, про M&V тісно пов'язані один з одним, але не C. Це правило, M називає функції C і V часто лише дані пов'язуються з деякою підмножиною М.
Стівен Еверс

8
@SnOrfus: Це точно протилежне тому, що я думав - M&V поєднані з C, але не один з одним.
DeadMG

1
Як стільки відповідей може бути настільки помилковим. Тут читайте версію MS msdn.microsoft.com/en-us/library/ff649643.aspx
Reactgular

Дайте цю статтю прочитати: objectmentor.com/resources/articles/taskmast.pdf
Edward Strange

Відповіді:


15

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

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

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

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

У Rails вам дуже рекомендується підштовхувати доменні об’єкти (ActiveRecord) до перегляду та вірити, що представлення не скористається цим доступом (наприклад, ви не повинні дзвонити customer.save з виду, навіть якщо це буде доступний).

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


1
Модель перегляду - дуже поширена практика, коли справа стосується тестування одиниць. Зазвичай модель автодомену карт домену або об'єкт DTO для моделі перегляду. Потім ви використовуєте свою модель перегляду у поданні. Перегляд моделі легко перевірити, і вона не прив’язана до шару внизу.
CodeART

7

Примітка: Роберт К. Мартін (він же дядько Боб) пояснює це набагато краще і жартівливіше у своїй основній записці « Архітектура втрачених років» . Трохи довгий, але вчить багато хороших концепцій.

tl; dr: Не думайте і не плануйте свою програму з точки зору MVC. Рамка MVC - це лише деталь реалізації.

Найбільш заплутане в MVC - розробники намагаються використовувати всі компоненти, склеєні разом.

Спробуйте думати в умовах програми, а не в рамках.

Ваша програма має мету. Він займає деякі дані, робить дані з даними та повертає деякі дані.

Таким чином, controllerце механізм доставки вашої програми.

  1. Користувач надсилає запит до вашої програми (скажімо, додайте товар у кошик для покупок).
  2. Контролер приймає цей запит (інформація про продукт та інформацію про користувача), він викликає необхідну частину вашої програми, яка буде обробляти цей запит $user->addToCart($product)
  3. Ваша програма ( addToCartфункція userоб'єкта в даному випадку) виконує роботу, яку він повинен був виконати, і повертає відповідь (скажімо success)
  4. Контролер готує відповідь, використовуючи відповідні view: напр. в об'єкті контролера$this->render($cartView('success')

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

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

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

І то Model. Розглядайте це як механізм стійкості.

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

class User {
    //...
    private $id;
    private $shoppingCart;
    //...
}

class Product {
    //...
    private $id;
    //...
}

Коли ви додасте товар у кошик, ви можете додати його product::idдо user::shoppingCart.

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

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


Отже, спочатку напишіть свою програму. Якщо ви програмуєте способом "OO", використовуйте звичайні старі об'єкти мови. Спочатку не думайте з точки зору MVC.


Чудове відео. Спасибі. Я б не погодився з вашим тлумаченням цього. MVC не є деталлю в тому сенсі, який там має дядько Боб. Ви зауважите, що MVC - це архітектурний зразок, схожий на його "Інтерактор / Сутність / Межа", який він встановлює. З іншого боку, будь-яка конкретна система MVC, така як Spring або будь-яка інша, - це дійсно те, що він рекомендує відкласти. Як він пояснює, однак, ці структури називаються "MVC" - це своєрідна бастардизація цього терміна.
Едвард Странд

Так, я писав, що люди думають, що MVCтаке. Ось чому я і писав MVC Framework.
Хакан Деріал

2

Мартін Фаулер добре працює, описуючи парадигму MVC. Ось посилання на його статтю про нього http://martinfowler.com/eaaDev/uiArchs.html

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


1

Ось простий приклад того, як MVC можна використовувати в типовому додатку Java Swing ...

Скажімо, у вас є панель, що містить кнопку та текстове поле. Після натискання кнопки подія запускається, що призводить до певної зміни стану програми. Після того, як зміна стану зареєстрована, TextField стає відключеним.

Тоді це був би типовий підхід, застосований у простому додатку MVC ...

Контролер зареєструється як слухач подій View. При натисканні кнопки сам перегляд не обробляє подію; контролер робить. Контролер є Swing специфічним, оскільки він повинен мати справу з подіями, пов'язаними з Swing.

Контролер отримує це повідомлення і повинен вирішити, хто повинен його обробляти (Вид або модель). Оскільки ця подія змінить стан програми, вона вирішить переслати інформацію Моделі, яка відповідає за логіку даних та програми. Деякі роблять помилку, розміщуючи програмну логіку в контролері, але в OOP, моделі представляють і дані, і поведінку. Прочитайте Мартіна Фаулера про його розуміння.

Повідомлення отримує Модель у відповідному контексті. Тобто, це абсолютно не містить будь-яких посилань на Swing або будь-які інші специфічні посилання на GUI. Це повідомлення говорить Моделі та ТІЛЬКИ моделі. Якщо ви імпортуєте оператори javax.swing у Модель, ви не кодуєте модель правильно.

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

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


0

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

Однак ви не можете уникнути ДЕЯКОЇ залежності. Заняття повинні трохи знати один про одного, інакше вони ніколи не спілкуватимуться.

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

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


Ага - ось чому голоси - я неправильно написав. Я мав на увазі, що контролер має залежності від обох. D'oh!
Меттью Флін

-5

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

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

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

Звичайно, це лише тенденція, яку я спостерігав, і насправді нічого не говорить про якийсь конкретний приклад.

Щоб зрозуміти, що таке MVC, і якими є стосунки зв'язку, ви повинні вивчити, яким чином став MVC. Середовище, в якому було створено MVC, було таким, у якому "віджетів" як елементів форми, з якими можна будувати діалоги, не існувало. "Вид" був коробкою, і він малював речі. Перегляд тексту - це поле, в якому буде намальований текст. Перегляд списку являв собою вікно, в якому буде намальований список. "Контролер" отримував усі події миші та клавіатури з системи користувальницького інтерфейсу, що мали місце в цьому режимі; не було подій "textChanged" або "selectChanged". Контролер буде приймати всі ці події низького рівня та генерувати взаємодію з моделлю. При зміні модель сповістить про свої погляди; ми з тих пір сприймали ці відносини як "спостерігача", і це "

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

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


Для тих, хто думає, що знає краще:

http://www.codeproject.com/Articles/42830/Model-View-Controller-Model-View-Presenter-and-Mod

http://msdn.microsoft.com/en-us/library/ff649643.aspx

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

Але чому нехай факти заважають ...

Стаття, вже розміщена в іншій відповіді, також підтримує мої заяви:

http://martinfowler.com/eaaDev/uiArchs.html

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


4
Це явно неправильно. Модель не повинна залежати від вигляду ніколи! Навіть якщо цей погляд абстрактний або інтерфейс. Модель має бути повністю відірвана від презентації!
Сокіл

3
Відповідь неправильна. Модель не залежить від виду або контролера.
CodeART

2
@ Божевільний Едді Ви сказали: "З мого досвіду, модель, як правило, залежить лише від перегляду, а не від конкретного, часто як спостерігача". У вашій цитованій посилання йдеться: "Однак модель не залежить ні від виду, ні від контролера". Ви навіть читали цитовану статтю? Не схоже на це.
CodeART

2
@ Божевільний Едді: Мені байдуже, що пише хтось на хитрому кодовому проекті. Це жахливий дизайн. Використовувати спостерігача для прослуховування змін - це нормально, але розміщувати презентаційний інтерфейс у доменній моделі - це так неправильно. Цитований код із статті є дефектом у деяких фундаментальних аспектах щодо MVC. Це навіть дозволяє моделі неявно залежати від контролера. Яке лайно.
Сокіл

3
@ Crazy Eddie: lol @ downvote шум. Чи я тебе розлютив?
Сокіл

-7
  • Контролер посилає модель на представлення, і він обробляє подану модель з представлень, однак вона не є щільно пов'язаною з поданням чи моделлю.

Якщо контролер був щільно пов'язаний з поданням, то ми опинимося у світі веб-форм. У вас буде код, прив'язаний до файлу шаблону (застосовно до веб-форм ASP.NET)

Через це контролер не пов'язаний з моделлю чи видом. Це просто механізм обробки запитів та надсилання відповідей.

  • Вид щільно поєднаний з моделлю. Внесіть зміни у свою модель (наприклад, змініть її властивість), і вам доведеться внести зміни у свій погляд.

  • Модель не щільно поєднана з видом. Внесіть зміни в представлення, і це не вплине на модель.

  • Модель нічого не знає про контролер або види, де він може бути використаний. Тому модель не є щільно пов'язана з видом або контролером.

Ще один спосіб подумати над цим:

  • Внесіть зміни в контролер - на перегляд і модель це не вплине

  • Внесіть зміни в модель - вигляд порушиться, коли він спиратиметься на модель

  • Внесіть зміни у вигляд - модель та контролер не вплинуть

Ця нещільна муфта в проектах MVC - це те, що дозволяє легко провести тестування.


1
Це так неправильно, що не смішно. Навіть не варто пояснювати. Просто ігноруйте цю відповідь повністю.
Реакційний

1
@MathewFoscarini Перестань плакати і залишити "правильну відповідь"
CodeART

2
хаха, вся теорія дизайну, що стоїть за MVC, полягає в тому, що вони не залежать один від одного.
Реакційний

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