Толстые модели и тощие контроллеры звучат как создание моделей Бога

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

  1. Контроллер и маршрутизатор на самом деле не выполняют много разных задач, кроме простого вызова метода в богоподобной модели на основе маршрута.
  2. Модели слишком много делают. Отправка электронных писем, создание отношений, удаление и изменение других моделей, постановка задач в очередь и т. Д. По сути, теперь у вас есть богоподобные объекты, которые должны делать все, что может или не может иметь отношение к моделированию и работе с данными.

Где вы проводите черту? Разве это не соответствует образцу Бога?


person Jungle Hunter    schedule 26.12.2012    source источник


Ответы (3)


Возможно, было бы не лучшей идеей рассматривать Rails как один из основных элементов шаблона проектирования MVC. Указанная структура была сделана с некоторыми внутренними недостатками (я как бы подробно остановился на этом в другом сообщении), и сообщество только сейчас начали устранять последствия. Вы можете рассматривать разработку DataMapper2 как первый важный шаг.

Немного теории

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

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

Основные части, из которых состоит слой модели:

  • Объекты домена

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

  • Абстракции хранения:

    Обычно реализуется с использованием шаблона data mapper (не путайте с ORM, которые злоупотребляли этим именем). Этим экземплярам обычно поручается хранение и извлечение информации из объектов домена. Каждый объект домена может иметь несколько сопоставителей, так же как существует несколько форм хранения (БД, кеш, сеанс, файлы cookie, / dev / null).

  • Услуги:

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

Между этими группами может быть несколько структур: DAO, единиц работы и репозитории.

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

Так что насчет божеств?

Вместо того, чтобы работать с какой-то пугающей и монолитной моделью, контроллеры должны взаимодействовать со службами. Вы передаете данные из пользовательского ввода в конкретную службу (например, MailService или RecognitionService). Таким образом, контроллер изменяет состояние уровня модели, но это делается с использованием понятного API и без вмешательства во внутренние структуры (что может вызвать утечку абстракции).

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

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

Заключительные примечания

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

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

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

person tereško    schedule 26.12.2012
comment
Очень полезный и полный ответ! Знаете ли вы какую-нибудь книгу, в которой более подробно объясняется архитектурный паттерн MVC? Особенно в части модели, которую все ошибочно считают. Модель представляет данные и больше ничего не делает. и это больше похоже на идею объекта домена, а не на "Модель" - ›tomdalling.com/blog/software-design/ - person thermz; 16.06.2013
comment
@thermz, afaik, действительно нет книг, посвященных исключительно шаблону MVC. Обычно я просто говорю людям прочитать PoEAA , а потом копайте. Возможно, этот список ссылок может оказаться полезным. Я считаю, что, когда люди хорошо разбираются в принципах и концепциях ООП, этот шаблон становится довольно легко понять. - person tereško; 16.06.2013
comment
@ tereško красивый ответ. Достигает ли этого Hibernate? Я не уверен в ответах здесь - ›http://stackoverflow.com/questions/1308096/which-pattern-does-hibernate-follow - person Ankan-Zerob; 20.06.2014
comment
@ Ankan-Zerob, как вы могли заметить, я не разработчик java, но из того, что я знаю о Hibernate, он предоставляет полный набор инструментов для уровня сохраняемости. Это даст вам часть того, что там описано, но не полный слой модели. - person tereško; 20.06.2014
comment
@ tereško Подскажите, как это помогает? Я понимаю разделение проблем, но рано или поздно нужно изменить логику, которая попадает в базу данных. Это, в свою очередь, потребует, возможно, нового метода где-то, и этот новый метод должен быть вызван из другого места. Таким образом, кажется, что изменения действительно идут по цепочке от m до v и c. Как это изменит что-то в слое модели, сервисе или другом слое, превратившись в огромный? Спасибо. Я искал повсюду и не могу найти ответа ни на один из вопросов MVC, кроме того, как вы это делаете, будь то этот MVC или другой. - person johnny; 04.09.2014
comment
@ tereško Это все очень сбивает с толку, потому что какой-то уровень абстракции рано или поздно должен измениться. - person johnny; 04.09.2014
comment
@johnny Почему изменения в логике БД (которые обрабатываются преобразователями данных) распространяются за пределы уровня обслуживания ? Черт, изменения даже не должны зайти так далеко, если вы передаете объект домена в вызовах метода универсального картографа: $userMapper->save($user). Зачем вам нужно менять этот интерфейс, если вы решили хранить пользователей в двух таблицах вместо одной? - person tereško; 04.09.2014
comment
@ tereško Я думаю, становится яснее. Есть ли какая-нибудь структура, которая делает это правильно? В частности, PHP. Этого не должно быть, Java тоже хороша. Что-либо? - person johnny; 04.09.2014
comment
@johnny, насколько я знаю, нет. Большинство так называемых фреймворков mvc в php являются вариациями Rails. И, как часть курса, большинство из них поставляется с некоторыми ORM на основе активных записей. решения (эти вещи, как известно, уязвимы к изменениям в БД). Вы можете реализовать что-то подобное с SF2.x или ZF2.x, но суть фреймворка заключается не в реализации / обеспечении соблюдения определенной архитектуры, а в предоставлении инструментов. Кроме того, когда дело доходит до MVC, он реализуется кодом приложения, а не фреймворком. - person tereško; 04.09.2014
comment
Краткий ответ: мне неизвестна какая-либо структура, которая значительно отдает предпочтение вышеописанному подходу. - person tereško; 04.09.2014
comment
Во введении используется слово «наследовать», когда имеется в виду «присуще». У меня недостаточно репутации, чтобы исправить это, и изменение недостаточно существенно, как предлагаемое изменение, так может ли кто-нибудь исправить это, пожалуйста? - person BCdotWEB; 11.08.2015

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

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

Просмотр ==== Контроллер ==== Модель ---> Уровень бизнес-процессов -> Основные модели

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

BPL может вызывать шаблоны UoW / репозитория, выполнять бизнес-правила и вызывать функции инфраструктуры посредством внедренных объектов или шаблонов интерфейса.

Таким образом, рекомендация держать контроллер "тонким" не означает, что класс "person" в классической модели Core должен иметь 50 методов и напрямую вызывать Email. Вы правы, думая, что это неправильно.

Контроллер может по-прежнему потребоваться для создания экземпляров и внедрения классов инфраструктуры в BPL или базовый уровень, если вызывается напрямую. Должен существовать бизнес-уровень или, по крайней мере, классы, управляющие вызовами между классами классической объектной модели. В любом случае, это моя "точка зрения" ;-)

Для общего использования MVC см. Описание вики http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller

Небольшой блог, в котором рассказывается о букве "M" в MVC. http://www.thedeveloperday.com/skinny-controllers/

person phil soady    schedule 26.12.2012
comment
Если вы не согласны, по крайней мере, будьте достаточно вежливы, чтобы оправдать свою точку зрения. - person phil soady; 26.12.2012

Я думаю, вы можете провести различие между одной толстой моделью (возможно, названной "Приложение" или "Приложение") и несколькими толстыми моделями, разбитыми на логические группы (Бизнес, Клиент, Заказ, Сообщение). Последнее - это то, как я структурирую свои приложения, и каждая модель примерно соответствует таблице базы данных в реляционной базе данных или коллекции в базе данных документов. Эти модели обрабатывают все аспекты создания, обновления и управления данными, составляющими модель, независимо от того, обращаются ли они к базе данных или вызывают API. Контроллер очень тонко отвечает за то, что вызывает соответствующую модель и выбирает шаблон.

person Bryan Young    schedule 26.12.2012