Что такое модель в MVC

Что такое модель в MVCПервое, что я должен сказать: модели — это слой, второе, — существует различия между классической MVC и той, что используется в веб-программировании.

Чем модели НЕ являются?

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

Так что такое модель?

В правильном MVC, M содержит в себе логику проблемной области.Слой моделей как правило состоит из сущностей трех типов:

  • Domain Objects

    domain object — это логическое хранилище чистой информации проблемной области, часто представляет из себя сущность этой проблемной области.

    Это то место, где вы определяете валидацию данных перед тем, как отправить запрос или место, где проходит расчет итоговой цены заказа. В тоже время, Объекты Домена независимы хранилища, и не осведомлены о том как хранятся данные (SQL database, REST API, text file, и т.п.) и даже хранятся ли где-то вообще.

  • Data Mapper’ы. Эти объекты ответственны за хранение. Если используется база данных, то тут будет жить ваш SQL. Или может вы используете XML -файлы для хранения данных, тогда Data Mapper’ы парсят xml туда и обратно
  • Services(«Службы» — за неимением лучшего определения). Представляют собой объекты домена верхнего уровня(лежат над мапперами и объектами домена), но вместо бизнес логики, Службы ответственны за взаимодействие между Объектами Домена и Мапперами. В общем эти структуры представляют из себя «публичный» интерфейс для взаимодействия с логикой проблемной области. Вы можете их не использовать, но в конечном итоге получится неприятная ситуация, когда контроллеры содержат часть бизнес логики.

Как работать с моделями?

Взаимодействие между моделями-объектами и другими частями триплета MVC должно происходить только через Службы. Такое разделение несет в себе преимущества:

  • легче следовать принципу «единственной ответственности» (single responsibility principle)
  • создается пространство для маневров в случае, если бизнес логика внезапно изменилась
  • контроллеры остаются максимально простыми
  • у вас есть хорошая заготовка, на случай если вам резко понадобится внешний API

Как строить модель?

В связи с тем что не существует единого универсального класса «Модели», вы не «строите модель». Вместо этого, вы начинаете с создания Службы, которая совершает необходимые манипуляции в своих методах. Затем, вы реализуете Объект Домена и его Мапперы.

Пример. обощенно, так может выглядеть метод авторизации

[php]
class AuthenticationService {
// — snip —
public function login( $username, $password ){
$account = $this->domainObjectFactory->build(‘User’);
$userMapper = $this->dataMapperFactory->build(‘User’);
$sessionMapper = $this->dataMapperFactory->build(‘Session’);
$account->setUsername( $username );
$userMapper->fetch( $account );
if ($account->isValidPassword( $password )){
$sessionMapper->storeId(‘user’, $account);
return true;
}
return false;
}// — snip — }
[/php]

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

P.S.: Также где-то примерно здесь должно быть реализовано кэширование. например, в дополнительном Маппере.

Некоторые дополнительные уточнения

  1. Таблицы данных и модели.Иногда бывает, что между таблица, объектами Домена и Мапперами отношение 1:1:1, но в больших проектах все может быть запутаннее:
    • Информация, используемая одним Объектом Домена может быть собрана из нескольких мапперов, в то время как сам объект не представлен в таблицах базы данных. Например, если вы создаете месячный отчет, данные будут собраны из нескольких таблиц, но в базе данных не существует волшебной таблицы MonthlyReport.
    • Один Маппер может затрагивать несколько таблиц. Пример: когда вы храните данные объекта User, его Объект Домена может содержать в себе ряд других объектов. Если понадобится сохранить User, его Мапперу придется обновить данные или вставить записи в несколько таблиц.
    • Данные одного Объекта Домена могут хранится в нескольких таблицах.Пример: в больших проектах (или среднего размера социальной сети), разумной идеей является отдельное хранение
      данных авторизации и часто используемых данных отдельно от больших данных, доступ к которым требуется реже. Получается,  что класс User один, но содержимая в нем инфорация разнесена по нескольким таблицам и зависит от того, какая информация потребовалась в данном конкретном случае.
  2. View — это не шаблон. Представители View в MVC ответственны за всю логику представления данных. Это означает, что одна View View зачастую использует несколько шаблонов. Она получает данные из Слоя Моделейи затем, основываясь на полученной информации, выбирает шаблон и проставляет значения. Одним из преимуществ такого подхода — возможность повторного использования. Если у вас есть готовый класс ListView, грамотно написанный, вы можете использовать этот же класс для представления списка пользователей или списка комментариев к статье. Потому что у них есть общая логика представления, и вам остается только выбрать нужный шаблон.
  3. Как взаимосвязаны View и Controller instances? Структура MVC состоит из двух основных слоев: представления и моделей. Основными структурами внутри слоя Представления являются views и контроллеры. В случае обычных вебсайтов, которые используют паттерн, лучше всего подходит отношение 1:1 view-controller. Одна view представляет собой одну страницу вашего сайта и ее контроллер обрабатывает все запросы исходящие с этой страницы. Например, для представления одной Заметки, у вас будет \Application\Controller\Document и\Application\View\Document.

Оставить комментарий