Ответ 1
Примечание: шаблоны, основанные на MVC и MVC, являются продвинутыми конструкциями. Они предназначены для использования в кодовых базах, где обычный объектно-ориентированный (который следует SOLID и другим рекомендациям) код становится неуправляемым. Введя этот шаблон, вы наложите дополнительные ограничения, которые затем позволят вам содержать очень сложные приложения. MVC не предназначен для приложений "Hello World".
Давайте начнем с самого начала...
Основная идея шаблонов проектирования, основанных на MVC и MVC, - Разделение проблем. Указанное разделение состоит из двух частей:
- Уровень модели отделен от уровня пользовательского интерфейса:
- представления отделены от контроллеров
Слой модели (не "класс" или "объект") будет содержать несколько групп структур, каждая из которых имеет дело с различным аспектом бизнес-логики. Основные части будут:
- доменные объекты: проверка, бизнес-правила
- абстракция хранилища: постоянство и кэширование данных из доменных объектов
- услуги: логика приложения
Также могут быть смешаны в хранилищах, единицах работы и других.
Уровень пользовательского интерфейса в основном состоит из представлений и контроллеров. Но они оба используют сервисы для взаимодействия с уровнем модели. Сервисы предоставляют контролерам возможность изменять состояние уровня модели и представлениям собирать информацию на основе этого нового состояния.
В контексте Интернета представления и контроллеры образуют неплотную пару из-за природы запроса-ответа, которую демонстрируют веб-приложения.
Следует отметить, что хотя контроллеры могут напрямую изменять состояние текущего представления, чаще всего эти изменения осуществляются через модель. Одна из причин прямого изменения представления - это, например, когда вместо XML вам нужно ответить JSON.
Хотя можно также утверждать, что можно просто создать другое представление для каждого выходного формата и воспользоваться преимуществами полиморфизма.
Что не вид?
Существует распространенное заблуждение, что представления представляют собой просто прославленный файл шаблона. Эта ошибка стала чрезвычайно популярной после выпуска среды прототипирования RubyOnRails.
Представления не являются шаблонами. Если вы используете их как таковые, вы нарушаете основной принцип, лежащий в основе шаблонов, основанных на MVC и MVC.
Если вы делаете вид, что шаблоны являются представлениями, это оказывает огромное влияние на вашу архитектуру. В представлении нет места логике представления, поэтому вы продвигаете логику представления либо на уровне контроллера, либо на уровне модели. Обычный выбор - "контроллер", потому что большинство людей понимают, что логике представления не место на уровне модели.
По сути, это вызывает слияние представлений и контроллеров.
Что делает представление?
Ответственность за представление заключается в том, чтобы иметь дело с логикой представления. В контексте сети цель просмотра - создать ответ для пользователя (который, между прочим, является браузером, а не человеком).
Технически было бы возможно создать виды на стороне клиента, чтобы пользовательские веб-сокеты наблюдали за уровнем модели, но на практике это практически невозможно реализовать. Особенно в среде PHP.
Для создания этого представления отклика получает информацию из слоя модели и на основе собранных данных либо собирает отклик, распределяя данные по шаблонам и визуализируя, либо иногда просто отправляя заголовок местоположения HTTP.
При использовании Post/Redirect/Get часть перенаправления выполняется представлением, а не контроллером, как это часто делают люди.
Субъективный бит:
В последнее время я предпочел взаимодействовать с MVC, используя следующий подход:
// the factory for services was injected in constructors
$controller->{ $method.$command }($request);
$response = $view->{ $command }();
$response->send();
$method
- это текущий REQUEST_METHOD, который был настроен под REST-подобный API, а $command
- это то, что люди обычно называют "действием". Контроллер имеет отдельные подпрограммы для запросов GET
и POST
(другой). Это помогает избежать одинакового if
в каждом "действии".
И в представлении я вызываю метод с аналогичным именем, который готовит ответ, который отправляется клиенту.
Предупреждение: я подозреваю, что эта настройка содержит нарушение SRP. Принятие его как своего собственного может быть плохой идеей.
Что насчет СУХОГО?
Как вы уже могли заметить, существует небольшая проблема с использованием представлений в качестве экземпляров. Вы бы в конечном итоге с повторяющимися частями кода. Например: меню или нумерация страниц.
Давайте посмотрим на нумерацию страниц. Нумерация страниц содержит логику, но эта логика не связана со слоем модели. Модель не имеет понятия "страница". Вместо этого эта часть логики будет находиться на уровне пользовательского интерфейса. Но если каждое из ваших представлений содержит или наследует нумерацию страниц, это будет явным нарушением ПСП (и фактически нескольких других принципов).
Чтобы избежать этой проблемы, вы можете (и должны, ИМХО) представлять объекты презентации в своих представлениях.
Примечание:, хотя Фаулер называет их "моделями презентаций", я думаю, что это имя лишь добавляет путаницы "что такое модель". Поэтому я бы рекомендовал называть их "объектами презентации".
Объекты презентации имеют дело с повторяющимися кусочками логики. Это делает представления намного "более легкими", а в некоторых аспектах начинает отражать структуру сервисов на уровне модели.
Взаимодействие между объектами презентации и шаблонами становится аналогичным взаимодействию между объектами домена и преобразователями данных.
Мне всегда нужно все это?
Нет. Этот конкретный подход в значительной степени ориентирован на код, где уровень пользовательского интерфейса имеет большую сложность, и вам необходимо отделить обработку ввода от представления только для здравого смысла.
Если ваше приложение имеет очень простой пользовательский интерфейс, например... эмм... вы создаете REST API для более крупного интегрированного проекта. В таком случае прагматичный вариант может состоять в том, чтобы просто объединить каждую пару контроллер-представление в один класс.
Это также может быть хорошим шагом при рефакторинге устаревшей кодовой базы, потому что этот менее ограниченный подход позволяет перемещать целые куски старого кода. Когда вы изолировали такие фрагменты старого кода и проверили, что все по-прежнему работает (поскольку унаследованный код никогда не тестирует... как он становится "унаследованным"), вы можете начать разделять его дальше, сосредоточившись на разделении бизнес-логики. из пользовательского интерфейса.
П.С. Я сам все еще пытаюсь найти способ, как лучше всего иметь дело с представлениями. Этот пост - скорее не ответ, а скорее снимок моего текущего понимания.