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

16

У меня есть приложение, которое использует MVC, но я немного борюсь за то, как контроллер должен быть спроектирован. Например, представление одновременно просматривает только некоторое подмножество данных модели. Однако я не уверен, как именно это должно быть организовано. Например, нормально ли для представления или модели напрямую вызывать функции на контроллере? Через какой-то интерфейс? Или они полностью инкапсулированы и никогда не знают о контроллере или друг о друге?

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

DeadMG
источник
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
Эдвард Стрендж

Ответы:

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 - это архитектурный паттерн, очень похожий на его паттерн «Interactor / Entity / Boundary», который он создает. С другой стороны, любая конкретная система MVC, такая как Spring или что-то еще, действительно является тем, что он рекомендует отложить. Однако, как он объясняет, эти структуры, называемые «MVC», являются своего рода ублюдком этого термина.
Эдвард Стрендж
Да, я написал это так, что люди думают, что это MVCтакое. Вот почему я написал MVC Framework.
Hakan Deryal
2

Мартин Фаулер хорошо описывает парадигму MVC. Вот ссылка на его статью об этом http://martinfowler.com/eaaDev/uiArchs.html

Обратите внимание на его цитату о Separated Presentation «Идея Separated Presentation заключается в том, чтобы сделать четкое разделение между объектами домена, которые моделируют наше восприятие реального мира, и объектами презентации, которые являются элементами GUI, которые мы видим на экране».

Johnnie
источник
1

Вот простой пример того, как MVC может использоваться в типичном приложении Java Swing ...

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

Таким образом, это будет типичный подход, используемый простым приложением MVC ...

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

Контроллер получает это уведомление и должен решить, кто должен обрабатывать его (представление или модель). Поскольку это событие изменит состояние приложения, оно решает переслать информацию в модель, которая отвечает за данные и логику программы. Некоторые делают ошибку, помещая программную логику в контроллер, но в ООП модели представляют как данные, так и поведение. Прочитайте Мартина Фаулера о его взгляде.

Сообщение получено Моделью в соответствующем контексте. То есть он полностью лишен каких-либо ссылок на Swing или любых других специфических ссылок для графического интерфейса. Это сообщение говорит о модели и только модели. Если вы обнаружите, что импортируете в модель операторы javax.swing, вы неправильно кодируете модель.

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

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

Constantin
источник
0

Сцепление (вид вы хотите избежать) предполагает взаимную зависимость между двумя классами. То есть Foo зависит от Bar, а Bar зависит от Foo, так что вы не можете реально изменить одно без изменения другого. Это плохо.

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

В шаблоне MVC Контроллер управляет связью между Моделью домена и Представлением представления. Таким образом, Контроллер должен знать достаточно о Модели, чтобы попросить ее сделать то, что он должен делать. Контроллер также должен знать достаточно о представлении, чтобы иметь возможность представить его клиенту или пользователям. Таким образом, Model Controller зависит от обоих. Тем не менее, представление может прекрасно существовать без контроллера - там нет никакой зависимости. Точно так же Модель не зависит от контроллера - она ​​просто есть. Наконец, Модель и Вид полностью отделены друг от друга.

По сути, Контроллер - это уровень косвенности, который отделяет Представление от Модели, так что они не должны знать друг о друге.

Мэтью Флинн
источник
Ах - вот почему отрицательные голоса - я неправильно написал. Я имел в виду, что у Контроллера есть зависимости от обоих. D'о!
Мэтью Флинн
-5

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

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

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

Конечно, это всего лишь тенденция, которую я наблюдал, и она ничего не говорит о каком-либо конкретном примере.

Чтобы понять, что такое MVC и каковы отношения связывания, вы должны посмотреть, как возник MVC. Среда, в которой был создан MVC, была такой, в которой «виджеты» как элементы формы, с которыми можно создавать диалоги, не существовали. «Вид» был коробкой, и он рисовал вещи. Текстовое представление будет блоком, который будет рисовать текст. Представление списка было коробкой, которая нарисует список. «Контроллер» получил все события мыши и клавиатуры от системы пользовательского интерфейса, которые имели место в этом представлении; не было никаких событий "textChanged" или "selectionChanged". Контроллер будет принимать все эти события низкого уровня и генерировать взаимодействие с моделью. Модель, будучи измененной, уведомит свои взгляды; с тех пор мы стали рассматривать эти отношения как «наблюдателя», и это

В этом суть паттерна 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
@Crazy Eddie Вы сказали: «По моему опыту, как правило, модель зависит только от представления, а не от конкретного, часто в качестве наблюдателя». В приведенной вами ссылке говорится: «Однако модель не зависит ни от представления, ни от контроллера». Вы вообще читали процитированную статью? Не похоже на это.
CodeART
2
@Crazy Eddie: Меня не волнует, что кто-то пишет в дерьмовом кодпроекте. Это ужасный дизайн. Использование наблюдателя для прослушивания изменений - это нормально, но помещать интерфейс представления в модель предметной области - ну очень неправильно. Приведенный в статье код имеет некоторые недостатки в отношении MVC. Это даже позволяет модели неявно зависеть от контроллера. Что за хрень
Сокол
3
@Crazy Eddie: lol @ неистовствовать. Я тебя разозлил?
Сокол
-7
  • Контроллер отправляет модель представлению и обрабатывает представленную модель из представлений, однако она не тесно связана с представлением или моделью.

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

Из-за этого контроллер не связан с моделью или представлением. Это просто механизм для обработки запросов и отправки ответов.

  • Вид тесно связан с моделью. Внесите изменения в свою модель (например, измените ее свойство), и вам придется вносить изменения в свой вид.

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

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

Еще один способ думать об этом:

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

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

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

Эта слабая связь в проектах MVC позволяет легко их тестировать.

CodeART
источник
1
Это так неправильно, это не смешно. Даже не стоит объяснять. Просто игнорируйте этот ответ полностью.
Reactgular
1
@MathewFoscarini Хватит плакать и оставь «правильный ответ»
CodeART
2
LOL, вся теория проектирования MVC заключается в том, что они не зависят друг от друга.
Reactgular
Я оставил больше информации для вас, надеюсь, это будет иметь смысл
CodeART