Что такое MVC, на самом деле?


202

Как серьезный программист, как вы отвечаете на вопрос, что такое MVC?

На мой взгляд, MVC - это своего рода туманная тема, и поэтому, если ваша аудитория - ученик, вы можете описать ее в общих терминах, которые вряд ли будут противоречивыми.

Однако, если вы разговариваете с хорошо осведомленной аудиторией, особенно с интервьюером, мне трудно думать о направлении, которое не рискует реакцией «ну, это не правильно! ...». У нас у всех разный реальный опыт, и я не встречал один и тот же шаблон реализации MVC дважды.

В частности, по-видимому, существуют разногласия в отношении строгости, определения компонентов, разделения частей (какая часть подходит, где) и т. Д.

Итак, как мне объяснить MVC таким образом, чтобы он был правильным, кратким и неоспоримым?


4
Примечание: если вы работаете в ASP.NET, MVC имеет второе, не туманное значение: ASP.NET MVC
Брайан

MVC был объяснен здесь хорошо codespeaker.com/blogs/...
smzapp

Ответы:


156

MVC - это программная архитектура - структура системы, которая отделяет логику домена / приложения / бизнеса (что вы предпочитаете) от остальной части пользовательского интерфейса. Это делается путем разделения приложения на три части: модель, представление и контроллер.

Модель управляет фундаментальным поведением и данными приложения. Он может отвечать на запросы о предоставлении информации, отвечать на инструкции по изменению состояния своей информации и даже уведомлять наблюдателей в управляемых событиями системах при изменении информации. Это может быть база данных или любое количество структур данных или систем хранения. Короче говоря, это данные и управление данными приложения.

Представление эффективно предоставляет элемент пользовательского интерфейса приложения. Он отобразит данные из модели в форму, подходящую для пользовательского интерфейса.

Контроллер получает пользовательский ввод и выполняет вызовы к модельным объектам и представлению для выполнения соответствующих действий.

В целом, эти три компонента работают вместе, чтобы создать три основных компонента MVC.


7
+1 Я действительно предпочитаю думать о MVC как об архитектуре из трех (или более) шаблонов, а не как шаблон проектирования. Канонической реализации нет, просто она не так мала, и все реализации будут иметь гораздо больше, чем подразумеваемые основные компоненты.
Яннис

51
Хотя в этом ответе содержится 21 ответ, я нахожу предложение «Это может быть база данных или любое количество структур данных или систем хранения. (Tl; dr: это данные и управление данными приложения)» ужасно. Модель - это логика чистого бизнеса / предметной области. И это может и должно быть намного больше, чем управление данными приложения. Я также различаю доменную логику и логику приложения. Контроллер никогда не должен содержать бизнес / доменную логику или напрямую общаться с базой данных.
Сокол

9
Я не могу не согласиться с этим ответом просто потому, что он утверждает, что mvc является рациональным вне уровня представления. Остальная часть ответа в порядке. MVC должен начинаться и заканчиваться на уровне презентации и абсолютно не должен содержать вашу бизнес-логику и репозиторий. Это эффективно помещает все ваше приложение на уровень представления и не дает доступ к API, который позволил бы получить прямой доступ к вашей бизнес-логике или чистым данным, не ориентируясь на исходное приложение. Это не открыто для расширяемости, просмотр моделей приближает вас, но вам все еще не хватает слабой связи
Джимми Хоффа

6
@Jimmy: Во многих конструкциях MVC модели можно повторно использовать в API, поскольку они не зависят от пользовательского интерфейса - об этом заботится разделение между представлением и моделью. Но это, конечно, зависит от того, как вы решите определить «модель». Если вы собираетесь судить о MVC, вам следует сначала объяснить, какую интерпретацию MVC вы используете.
Оуэн С.

5
@ Яннис: Это просто напрашивается вопрос: что такое архитектура шаблонов? Почему бы вам не назвать это просто другой шаблон дизайна? Само определение шаблона проектирования в GoF (и Александре) ясно показывает, что шаблоны не должны предписывать одну каноническую реализацию (хотя популярность обеих книг несколько подрывает это представление).
Оуэн С.

136

аналогия

Я объяснил MVC моему папе так:

MVC (Модель, Представление, Контроллер) - это шаблон для организации кода в приложении для улучшения удобства сопровождения.

Представьте себе фотографа с его камерой в студии. Клиент просит его сфотографировать коробку.

Коробка - это модель , фотограф - это контроллер, а камера - это вид .

Поскольку коробка не знает о камере или фотографе, она полностью независима. Такое разделение позволяет фотографу обойти рамку и направить камеру под любым углом, чтобы получить желаемый снимок / вид.

Не-MVC архитектуры, как правило, тесно связаны друг с другом. Если бы коробка, контроллер и камера были одним и тем же объектом, то нам пришлось бы разбирать и затем заново собирать и коробку, и камеру каждый раз, когда мы хотели получить новый вид. Кроме того, фотографировать - это все равно, что делать селфи, а это не всегда легко.


Детальное объяснение

Только после прочтения следующего вопроса / ответа из списка рассылки я почувствовал, что понял MVC. Цитата: https://mail.python.org/pipermail/python-list/2006-January/394968.html

бваха написал:

Автор ссылается на mvctree.py в wxPython как пример дизайна MVC. Однако я все еще слишком зелен, поэтому нахожу этот конкретный пример слишком сложным и не понимаю разделения, которое рекомендует автор.

MVC это все о разделении интересов.

Модель отвечает за управление данными программы (как частными, так и клиентскими данными). View / Controller отвечает за обеспечение внешнего мира средствами взаимодействия с данными клиента программы.

Модель предоставляет внутренний интерфейс (API), позволяющий взаимодействовать с ней другим частям программы. View / Controller предоставляет внешний интерфейс (GUI / CLI / веб-форма / высокоуровневый IPC / и т. Д.), Который позволяет всем программам взаимодействовать с ним.

Модель отвечает за поддержание целостности данных программы, потому что, если она будет повреждена, игра для всех закончена. View / Controller отвечает за поддержание целостности пользовательского интерфейса, следя за тем, чтобы все текстовые представления отображали актуальные значения, отключая пункты меню, которые не относятся к текущему фокусу, и т. Д.

Модель не содержит кода вида / контроллера; нет классов графического интерфейса, нет кода для размещения диалоговых окон или получения пользовательского ввода. Вид / Контроллер не содержит кода модели; нет кода для проверки URL-адресов или выполнения запросов SQL, а также нет исходного состояния: любые данные, хранящиеся в виджетах, предназначены только для отображения и являются просто отражением истинных данных, хранящихся в модели.

Итак, вот проверка истинного дизайна MVC: программа должна быть полностью функциональной, даже если к ней не подключен View / Controller. ОК, у внешнего мира будут проблемы с взаимодействием с ним в этой форме, но, пока кто-то знает соответствующие заклинания Model API, программа будет хранить и манипулировать данными как обычно.

Почему это возможно? Ответ прост: все благодаря слабой связи между слоями Model и View / Controller. Тем не менее, это не полная история. Что ключ ко всему шаблону MVC является направлением , в котором те соединения идут: ВСЕ инструкции поток из Вида / контроллера к модели. Модель НИКОГДА не говорит View / Controller, что делать.

Почему? Потому что в MVC, хотя View / Controller разрешено немного знать о Модели (в частности, API Модели), но Model не разрешается вообще ничего знать о View / Controller.

Почему? Потому что MVC - это создание четкого разделения интересов.

Почему? Чтобы помочь предотвратить сложность программы, выходящую из-под контроля и скрывающую вас, разработчика, под ней. Чем больше программа, тем больше число компонентов в этой программе. И чем больше связей существует между этими компонентами, тем сложнее разработчикам поддерживать / расширять / заменять отдельные компоненты или даже просто следить за работой всей системы. Задайте себе вопрос: при взгляде на диаграмму структуры программы, вы бы предпочли увидеть дерево или кошачью колыбель? Шаблон MVC позволяет избежать последнего путем запрета круговых соединений: B может подключаться к A, но A не может подключаться к B. В этом случае A - это модель, а B - представление / контроллер.

Кстати, если вы сообразительны, вы заметите проблему с только что описанным «односторонним» ограничением: как Модель может информировать View / Controller об изменениях в пользовательских данных Модели, когда Модель даже не имеет права знаете, что View / Controller, не говоря уже о том, чтобы отправлять на него сообщения? Но не волнуйтесь: есть решение для этого, и оно довольно опрятное, даже если на первый взгляд оно кажется довольно окольным. Мы вернемся к этому через минуту.

Таким образом, в практическом плане объект View / Controller может через API модели: 1. сказать модели делать что-либо (выполнить команды) и 2. сказать модели дать ей вещи (вернуть данные). Слой View / Controller передает инструкции на слой Model и извлекает информацию из слоя Model.

И вот где ваш первый пример MyCoolListControl идет не так, потому что API для этого класса требует , чтобы информация толкнул в нее, так что вы вернулись к тому , двухстороннюю связь между слоями, нарушение правил MVC и демпинг вас обратно в архитектура кошачьей колыбели, которую вы [предположительно] пытались избежать в первую очередь.

Вместо этого класс MyCoolListControl должен идти с потоком, извлекая необходимые данные из слоя ниже, когда это необходимо. В случае виджета списка это обычно означает запрос количества значений, а затем запрос каждого из этих элементов по очереди, потому что это самый простой и самый простой способ сделать это и, следовательно, свести к минимуму связь. И если виджет хочет, скажем, представить эти значения пользователю в хорошем алфавитном порядке, то это его перогатив; и его ответственность, конечно.

Теперь, последняя загадка, как я уже упоминал ранее: как вы синхронизируете отображение интерфейса пользователя с состоянием модели в системе на основе MVC?

Вот проблема: многие объекты View имеют состояние, например, флажок может быть отмечен или не отмечен, текстовое поле может содержать некоторый редактируемый текст. Однако MVC требует, чтобы все пользовательские данные были сохранены на уровне модели, поэтому любые данные, хранящиеся в других слоях для целей отображения (состояние флажка, текущий текст текстового поля), должны, следовательно, быть вспомогательной копией этих первичных данных модели. Но если состояние модели изменится, копия этого состояния в представлении больше не будет точной и нуждается в обновлении.

Но как? Шаблон MVC не позволяет модели помещать свежую копию этой информации в слой просмотра. Черт возьми, он даже не позволяет модели отправлять View сообщение о том, что его состояние изменилось.

Ну, почти. Хорошо, слою модели не разрешено напрямую общаться с другими уровнями, поскольку для этого потребуется, чтобы он что-то знал об этих слоях, а правила MVC препятствуют этому. Тем не менее, если дерево падает в лесу и его никто не слышит, издается ли оно?

Ответ, вы видите, состоит в том, чтобы настроить систему уведомлений, предоставляя слою Model место, где он может никому не сообщать, в частности, что он только что сделал что-то интересное. Затем другие слои могут публиковать слушателей с помощью этой системы уведомлений для прослушивания тех объявлений, которые им действительно интересны. Слой модели не должен ничего знать о том, кто слушает (или даже если кто-то вообще слушает!); он просто публикует объявление, а затем забывает об этом. И если кто-то услышит это объявление и захочет что-то сделать потом - например, запросить у модели какие-то новые данные, чтобы она могла обновить свой экранный дисплей - тогда замечательно. Модель просто перечисляет, какие уведомления она отправляет как часть своего определения API; и то, что кто-то еще делает с этим знанием, зависит от них.

MVC сохранился, и все счастливы. Ваша прикладная среда вполне может обеспечить встроенную систему уведомлений, или вы можете написать свою собственную, если нет (см. «Шаблон наблюдателя»).

...

Во всяком случае, надеюсь, что это помогает. Как только вы поймете мотивы, стоящие за MVC, причины, по которым все делается так, как они есть, начинают иметь смысл, даже когда - на первый взгляд - они кажутся более сложными, чем необходимо.

Ура,

имеет


Что касается MVVM и MVCS, я слышал ваш ответ MVC от softwareengineering.stackexchange.com/questions/184396/…
dengApro

86

MVC - это в основном модное слово.

Раньше его считали шаблоном, но его первоначальное определение 1979 года было тупым, переданным, неправильно истолкованным, вырванным из оригинального контекста. Он был плохо переопределен до такой степени, что начинает напоминать религию, и хотя это, безусловно, помогает его культовым грузчикам защищать его, его имя больше не ассоциируется с твердым набором руководящих принципов . Как таковой, он не может больше рассматриваться как образец.

MVC никогда не предназначался для описания веб-приложений.
Ни современные операционные системы, ни языки.
(некоторые из них фактически сделали определение 1979 года излишним)

Это было сделано для. И это не сработало.

Теперь мы имеем дело с непристойным гибридом web-mvc, который с его ужасным статусом модных слов, плохим определением и полуграмотными программистами в качестве целевой демографии делает действительно плохую рекламу шаблонам программного обеспечения в целом.

Таким образом, MVC стал разделением интересов для людей, которые на самом деле не хотят слишком много думать об этом.

  • Модель данных обрабатывается одним способом,
  • вид в другой,
  • остальное просто называют «контроллером» и оставляют на усмотрение читателя.

Веб-сайты / веб-приложения в 90-х не использовались для разделения задач.

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

Веб-технологии, такие как ASP, JSP и PHP, позволяют слишком легко смешивать представления о проблемах с данными и приложениями. Вновь прибывшие на поле обычно испускают неразборчивый код грязных шаров, как в те старые времена.

Таким образом, все большее число людей начали повторять «использовать MVC» в бесконечных циклах на форумах поддержки. Число людей расширилось до уровня менеджеров и маркетологов (для некоторых этот термин уже был знаком с тех времен в программировании на графическом интерфейсе, в которых шаблон имел смысл), и это стало чудовищем модного слова, с которым мы сейчас сталкиваемся ,

Это здравый смысл , а не методология .
Это отправная точка , а не решение .
Это все равно, что говорить людям дышать воздухом или делать хруст , а не лекарство от рака .


22
Это, конечно , не в основном модное слово. Это правда, что MVC имеет тенденцию быть более распространенным и менее отчетливым, чем другие шаблоны проектирования, поэтому вы можете думать о нем как об организационном принципе или парадигме. Но как бы вы это ни называли, это фундаментальная концепция в ряде очень успешных объектно-ориентированных сред. Притворяться, что это просто модное слово, то есть модная фраза, которая ничего не значит, значит оказать плохую услугу ОП.
Калеб

23
It's a fancy word for pre-existing concepts that didn't really need one.И какой шаблон дизайна / архитектура не подходит под это описание?
Яннис

8
+1 Честно говоря, большая часть этих вещей очевидна, если вы овладеете основами (сплоченность, связь, читаемость, ортогональность и т. Д.) И объедините это с возможностями современных языков.
Лориан

12
The data model is handled one way, the view in another, the rest is just named "controller"+1
c69

33
-1. Я бы хотел -10 за все идиотские +1 комментарии. Каким образом все это "очевидно", учитывая основные принципы сцепления и сплоченности? Существует множество архитектур пользовательского интерфейса, включая MVC, MVP, MVVM, Forms и модель Smalltalk. Некоторые компании также доводят архитектуру составных приложений до крайности, например, в WS-CAF. Сказать, что «здравый смысл» автоматически приводит вас к тому, что MVC содержит столько же воды, сколько так называемое доказательство Бога Декартом. Это, очевидно, то, что вы знаете, но ваш ответ демонстрирует либо незнание других методов, либо неспособность расширить свой кругозор.
Aaronaught

39

Лучший способ определить это - обратиться к оригинальным работам Трюгве Реенскауг , который изобрел его: http://heim.ifi.uio.no/~trygver/themes/mvc/mvc-index.html.

Этот документ, в частности, обычно считается текстом определения: http://heim.ifi.uio.no/~trygver/1979/mvc-2/1979-12-MVC.pdf

МОДЕЛИ

Модели представляют знания. Модель может быть одним объектом (довольно неинтересным) или структурой объектов ...

Должно быть взаимно-однозначное соответствие между моделью и ее частями, с одной стороны, и представляемым миром, воспринимаемым владельцем модели, с другой стороны. Поэтому узлы модели должны представлять идентифицируемую часть проблемы.

Все узлы модели должны находиться на одном и том же уровне проблемы, поэтому смешивать проблемно-ориентированные узлы (например, встречи в календаре) с деталями реализации (например, абзацами) очень сложно и считается плохой формой.

ПРОСМОТРЫ

Представление - это (визуальное) представление своей модели. Это обычно выделяет некоторые атрибуты модели и подавляет другие. Таким образом, он действует как фильтр представления .

Представление присоединяется к его модели (или части модели) и получает данные, необходимые для представления из модели, задавая вопросы. Он также может обновить модель, отправив соответствующие сообщения. Все эти вопросы и сообщения должны быть в терминологии модели, поэтому представление должно знать семантику атрибутов модели, которую оно представляет. (Например, он может запросить идентификатор модели и ожидать экземпляр Text; он может не предполагать, что модель относится к классу Text.)

КОНТРОЛЛЕРЫ

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

Контроллер никогда не должен дополнять виды, например, он никогда не должен соединять виды узлов, рисуя стрелки между ними.

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

РЕДАКТОРЫ

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

Обратите внимание, что редактор взаимодействует с пользователем через метафоры связанного представления, поэтому редактор тесно связан с представлением. Контроллер завладеет редактором, запросив его представление - другого подходящего источника нет.


11

MVC - это шаблон проектирования, используемый для изоляции бизнес-логики от представления.

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

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


2
Это не совсем полезно, есть очень специфические требования для реализации шаблона MVC, которые отличают его от MVP, MP, MVVM. У него также есть другая целевая аудитория по сравнению с другими шаблонами презентации.
Ян

8

MVC - проект программного обеспечения, который разделяет следующие компоненты системы или подсистемы:

  1. Модель - данные о состоянии приложения или его компонентов. Может включать процедуры для модификации или доступа.
  2. Вид - интерпретация данных (модель). Это ограничено только визуальным представлением, но может представлять собой аудио, производную информацию (например, статистику, переданную в другой объект модели) и т. Д. Кроме того, одна модель может иметь несколько представлений.
  3. Управление - обрабатывает внешний ввод в систему, вызывая изменения в модели. Элемент управления / представление могут быть тесно связаны (в случае пользовательского интерфейса). Однако могут обрабатываться другие внешние данные (например, сетевые команды), которые полностью независимы от представления.

6

Я бы сказал, что MVC - это концепция или семейство похожих шаблонов.

Я думаю, что эту статью стоит прочитать. Архитектура GUI Мартина Фаулера


5
Эта статья Фаулера превосходна, и каждый, кто использует термин MVC, должен ее прочитать. Два момента, которые я нахожу особенно интересными, заключаются в том, что первоначальное использование термина MVC в GUI довольно сильно отличается от использования в веб-структурах, и что в GUI разделение между представлением и контроллером оказалось менее полезным, чем предполагалось.
Том Андерсон

3

Во-первых, вы должны определить, кто задает вопрос и какой ответ он ищет. Вы отвечаете на этот вопрос другим вопросом, например, «В каком смысле?»

Вы можете спросить, ссылаются ли они на MVC вообще, на конкретную реализацию MVC (то есть asp.net MVC, spring MVC, smalltalk MVC и т. Д.), Что это такое технически, что это философски (да, у него есть философия)

Если это вопрос теста, и вы не можете попросить его уточнить, то вам придется угадывать, исходя из контекста.

Хороший простой ответ:

MVC - это программная архитектура пользовательского интерфейса, используемая для разделения структурных и поведенческих проблем с целью обеспечения более удобного программного обеспечения.

Вы также можете сказать:

Отделив представление от контроллера от модели, он способствует изоляции компонентов на основе их обязанностей. Теоретически, а обычно и на практике, это помогает улучшить ремонтопригодность, предотвращая смешивание различных частей системы и создание более сложных систем.

Но, в конце концов, вы будете судить, дадите ли вы ожидаемый ответ. Единственное решение проблемы - выяснить, какого ответа они ожидают.


2

Вот что я бы сказал по этому поводу. Я бы попытался объяснить это с точки зрения мобильных приложений, потому что это то, с чем я больше всего знаком, и потому что я не думаю, что полностью понял это до того, как начал делать мобильные приложения.
Давайте возьмем Android для примера.
Презентационный слой, т.е. Пользовательский интерфейс может (должен чаще всего) быть указан полностью в XML. Для простоты предположим, что один XML-файл описывает один экран в приложении. XML-файл определяет элементы управления, расположение элементов управления, расположение, цвета, размер, строковые метки ... все, что касается представления. Тем не менее, он ничего не знает о том, когда он будет вызван, когда он будет размещен на экране. Это будет автономный макет или часть более крупного макета? Вот вам и ваш идеальный ВИД .

Теперь, видимо, нужно в какой-то момент поместить его на экран, так как это сделать? Ваш КОНТРОЛЛЕР в Android называется Activity. Как следует из названия, активность делает некоторую активность. Даже если его единственной целью является отображение вида, определенного на шаге 1, он выполнит некоторое действие. Итак, активность выбирает представление и отображает его на экране. Поскольку представление ничего не знает о деятельности, так же как и деятельность ничего не знает о фактическом представлении. Мы (программисты) могли несколько раз перестраивать компоновку представления, не меняя ни одной строчки кода в нашей деятельности.

Теперь, нет ничего особенного в том, чтобы представить свой красивый блестящий, четко определенный макет XML без каких-либо действий. Допустим, мы хотим сохранить данные, введенные пользователем. Деятельность должна решать этот процесс от передачи данных от пользователя до передачи их кому-то другому для обработки (обработки, сохранения, удаления). К кому это перейдет? Ну, к МОДЕЛИ . Мне нравится думать о модели как о чистой. Java- класс, который ничего не знает о контексте приложения, в котором он живет. (На практике это почти никогда не будет иметь место).

Допустим, у меня есть класс Person, у которого есть три свойства: имя, адрес, возраст. В моем XML-макете есть 3 поля для ввода пользователя: имя, адрес, возраст. Моя деятельность берет три значения из пользовательского ввода, создает новый объект Person и вызывает для него некоторый метод, который знает, как обрабатывать некоторую логику, специфичную для человека. Там у вас есть это. Model-View-Controller.


1

Я всегда начинаю с того, что говорю им, что шаблон не является чем-то новым и существует уже много лет ... в этот момент они бросают на меня пытливый взгляд и БАМ!

И затем я бы довольно много говорил о различных моментах, таких как предыдущие ответы, но я думаю, что важно также быть контекстным, как сказал JB King, ASP.NET MVC и т. Д.,

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.