Чи справді потрібен "C" у MVC?


37

Я розумію роль моделі та подання у моделі Model-View-Controller, але мені важко зрозуміти, чому потрібен контролер.

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

Це просто окремий клас, який має всі функції, які будуть викликатися, коли ви, скажімо, натискаєте на плитку? Чому б просто не виконати всю логіку моделі на самому погляді?


1
Особисто я цим займаюся . Можуть бути випадки, коли альтернативи MVC немає, але я не можу витримати її.
Майк Данлаве

10
Три слова ... "Розмежування турботи".
Travis J

4
Практично всі програми Windows раніше .net використовували Doc-View без контролера. Здається, це було досить успішно.
Мартін Бекетт

Мартін, un (змінити) здатні моноліти.
Незалежна

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

Відповіді:


4

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

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


36
"Використовуючи ваш приклад, Контролер буде тим, що вирішило, що було законним кроком чи ні". Це поганий приклад: (така логіка має бути і в моделі; інакше ваша логіка розділена між контролером та моделлю.
Дім

6
@Dime - модель не повинна містити жодної логіки. Контролер буде єдиною логікою утримування, отже, "керуючим".
Травіс J

34
@TravisJ Не дуже згоден. Контроль не означає знати, як робити роботу. Йдеться про контроль над тими об’єктами, які роблять. Отже, логіка виконання роботи буде в моделі, і контролер контролює, яку модель використовувати для виконання необхідних вимог дії тощо. Занадто багато логіки в контролерах, на мій погляд, буде рецептом для блокування контролера ...
dreza

25
Вся справа в ООП полягає в тому, щоб згуртовані біти даних і поведінки зберігалися разом і констатувалися внутрішньо. "Модель" моделює поведінку та дані.
Мисько

12
-1 Контролер не повинен містити бізнес-логіку. Модель - це «додаток», вона містить дані та має підпрограми для дзвінка для всього, що може трапитися в додатку; не обов'язково все в одному файлі чи класі. Погляд візуалізує стан моделі. Контролер мостить модель / вигляд та реальний світ / вхід. Хочете "опублікувати" додаток як веб-додаток? Просто потрібен контролер, який обробляє HTTP та відповідний перегляд на основі HTML. Хочете інтерфейс командного рядка до вашої програми? Просто потрібен відповідний контролер і перегляд. Модель, бізнес-логіка, ніколи не змінюється в цих випадках.
декад

39

Чому б просто не виконати всю логіку моделі на самому погляді?

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

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

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

  • Ви можете змінити модель або вигляд, не змінюючи іншої. Можливо, вам доведеться оновити контролер при зміні будь-якого, але певним чином це є частиною переваги: ​​частини програми, які, швидше за все, змінюються, зосереджені в контролері.

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

  • Легко писати тести як для моделі, так і для перегляду, щоб переконатися, що вони працюють так, як слід.

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


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

Проблема з усіма відповідями полягає в тому, що існує стільки тлумачень MVC, скільки людей, які публікують публікації. І перераховані вище переваги стосуються лише однієї конкретної інтерпретації MVC. Якщо потрібно вкласти більшу частину логіки в контролер (або модель) і мати перегляд виклику / ініціювати виклики конкретного методу на контролері, то це робить комбінований контролер / модель автономним і дуже багаторазовим. Здебільшого це необхідний новий погляд. У мене ніколи не було потреби повторно використовувати вид. Навіть з вашим прикладом RSS можна легко обробляти новий перегляд, який використовує ваш старий із шаром RSS посеред.
Данк

2
@Dunk: важливо відокремити бізнес-логіку від користувальницького інтерфейсу, щоб бізнес-логіку можна було перевірити безпосередньо.
Кевін Клайн

@Kevin: Я повністю згоден, бізнес-логіка не належить до інтерфейсу користувача. Однак контролеру не потрібно входити в інтерфейс користувача. Це те, що я маю на увазі під багатьма визначеннями. За визначенням однієї особи, контролер обробляє кнопку, а інша людина вважає це частиною погляду. Якщо представлення знає, як перетворити дії оператора (тобто натискання кнопок / вибір елементів) на запити додатків, тоді Контролер / Модель стає дуже багаторазовим для використання майже з будь-яким інтерфейсом користувача, який може включати інтерфейси GUI, консолі або мережі.
Данк

1
@Dunk: Я думаю, ви можете називати все, що вам подобається, "контролером", але в архітектурі MVC контролер залежить і тому є частиною інтерфейсу користувача.
Кевін Клайн

7

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

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

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

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

Це все, що ви насправді повинні турбуватися.


3
Клей, клей, мені подобається це визначення, воно так правильне: всю модель слід охрестити MVG, і люди перестануть брязкати головою в пошуках елегантності, де їх не знайти.
ZJR

1
+1 для "клею"; це також означає, що саме та частина, яка найкраще підходить для роботи на мові сценаріїв (оскільки вони, як правило, переважають при склеюванні).
Стипендіати доналу

@DonalFellows Мені подобається, що багато думав. Щось, що "склеює" 2 різні сукупності разом, потребує великої гнучкості, яка сприяє слабо набраному мовам сценарію (тобто JavaScript)
Zack Macomber

4

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

  • Мене запитали, чи можна перенести шахову фігуру (вид) на х. Чи
    дозволено це ? Я не впевнений, але я знаю, де і кого запитати (модель).
  • Щось попросив мене зберегти свої дані. Як чорт мені це робити? Я знаю, де хоч і запитати! Як ми зберігаємо дані або де вони зберігаються, я поняття не маю, але цей клас репозиторію повинен знати. Я відправлю це, і нехай він вирішить це.
  • Я повинен показати поточну позицію шахової фігури користувачеві, на яку модель переїхала. не впевнений, чи хочу я показати твір як зелений чи жовтий? Ба, хто дбає, я знаю, що існує думка, яка може впоратися з цим, тому я передаю їм дані, і вони можуть вирішити, як це буде показано.

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

Що і де => Контролер Як і коли => Моделі та види

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


2

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

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


2

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

У GWT ви отримуєте більш чистий поділ з MVP. Немає жодної ділової логіки (якщо це зроблено правильно). Ведучий виступає в ролі контролера, і погляд не знає моделі. Дані моделі просто передаються на вигляд.


1

Перегляд документів (тобто перегляд моделі) є стандартною моделлю для більшості додатків Windows, написаних на MFC, тому він повинен працювати у багатьох випадках.


1

Я розумію роль моделі та подання у моделі Model-View-Controller, але мені важко зрозуміти, чому потрібен контролер.

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

Подумайте, якщо ви хочете зробити свою шахову програму незрячою, замініть уявлення на звукову версію та контролер, який працює з клавіатурою. Скажімо, ви хочете додати ігри поштою, додати контролер, який приймає текст. Чиста версія гри? Контролер, який приймає команди від сокета, зробив би цю роботу. Додайте до нього приємний 3d візуалізацію, новий класний вигляд. Нульова модель змінює необхідні Шахи як і раніше шахи.

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


0

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

IMO має бути API (бекенд) та додаток, який використовує API (frontend). Я думаю, ви можете зателефонувати GET-запиту контролеру (який просто називає бекенд-api) та html-огляді, але я зазвичай не чую, як люди говорять про вид як про чистий html, ні про модель, що не є API API.

У IMO все повинно бути надійним API. Насправді їм не потрібно бути надійними (як у чистому та добре побудованому), але внутрішні внутрішні записи повинні залишатися приватними, а додаток / фронт / поза api ніколи не повинен отримувати зв'язок із базою даних, а також не мати змоги робити необроблені запити.

Тепер, якщо ваш код / ​​дизайн передбачає клеїти його штрафом. Якщо у вашій шаховій грі є якась розмітка, яку ви можете відредагувати до графічного інтерфейсу, gui збирає координати / вхід і викликає MovePiece (srcPosition, dstPostion) (який може повернути буль або перерахунок, щоб сказати, чи це дійсний хід чи ні ) і добре, з усією логікою, що знаходиться в моделі, тоді обов'язково називайте це MVC. Однак я б все-таки організовував речі за класами та API і переконуюсь, що в них немає класу мийки, який би все не торкався (ані API, щоб знати про все).


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

0

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

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

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

Контролер реагує на події та контролює те, що є в моделі та, отже, що на екрані / Перегляд.

Трохи відступивши назад, ви можете уявити весь браузер як Вид і сервер як Контролер, а дані - як Модель. Коли користувач натискає кнопку у веб-переглядачі подія, яку він надіслав на сервер (контролер), він збирає ресурси як HTML-сторінку (модель) і повертає її назад до браузера для відображення (Перегляд)

Внизу на сервері, будь то asp, php чи java, "код" (Controller) отримує подію натискання та запитує базу даних чи сховище документів (Model) та створює HTML. З точки зору сервера результатом усіх його дій є Вид (HTML) його базового сховища даних (Модель). Але з точки зору клієнта результатом його запиту на сервер є його Модель (HTML)

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


-2

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

книга про чотири групи:

Шаблони дизайну в MVC Smalltalk

Тріада класів Model / View / Controller (MVC) [KP88] використовується для побудови інтерфейсів користувача у Smalltalk-80. Перегляд моделей дизайну всередині MVC повинен допомогти вам зрозуміти, що ми маємо на увазі під поняттям «візерунок».

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

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

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

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

Ще одна особливість MVC полягає в тому, що представлення даних можуть вкладатись. Наприклад, контрольна панель кнопок може бути реалізована як складний вид, що містить вкладені подання кнопок. Інтерфейс користувача для інспектора об’єктів може складатися з вкладених представлень, які можуть бути використані повторно в налагоджувачі. MVC підтримує вкладені представлення з класом CompositeView, підкласом View. Об'єкти CompositeView діють так само, як і об'єкти View; складений вигляд можна використовувати скрізь, де подання можна використовувати, але воно також містить і керує вкладеними поданнями.

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

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

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

Зв'язок View-Controller є прикладом схеми проектування стратегії (315). Стратегія - це об'єкт, який представляє алгоритм. Це корисно, коли ви хочете замінити алгоритм статично чи динамічно, коли у вас є багато варіантів алгоритму або коли алгоритм має складні структури даних, які ви хочете інкапсулювати.

MVC використовує інші шаблони дизайну, такі як Фабричний метод (107), щоб вказати клас контролера за замовчуванням для подання та Декоратор (175), щоб додати прокручування до подання. Але основні взаємозв'язки в MVC задаються моделями проектування спостерігачів, композитів та стратегій.


1
Схоже, весь цей пост мінус перші два абзаци взяті дослівно від Design Patterns . Я відформатував цей розділ як цитату, щоб читачі зрозуміли це - будь ласка, редагуйте, якщо я цитував ваші власні абзаци.
Калеб

1
Я повинен не погодитися з вашою думкою, що "контролер закінчується спагетірованним у погляді". Можливо, це залежить від платформи та основи, яку ви використовуєте, але це набагато частіше в програмах Cocoa та Cocoa Touch, щоб створити відповідні контролери, ніж опускати їх. Якщо програміст Objective-C відмовиться від однієї з категорій, це майже певна модель, яка страждає.
Калеб

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