// codeart.ru / Вопрос/Ответ / Шаблон MVC. Мысли про “состояние” модели Форум

Шаблон MVC. Мысли про “состояние” модели rss подписка

Автор: Evgeny Sergeev

В связи с комментариями Andy к посту про MVC я невольно задумался: а правильно ли я понимаю концепцию MVC? Начал разбираться, и вот к каким мыслям пришел.

У модели должно быть “состояние”

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

Если верить Wiki, то основная ошибка веб-программистов сводится к тому, что они выносят бизнес-логику из модели в контроллер. В результате получая «Толстые тупые уродливые контроллеры».

В той же Wiki дано очень хорошее опрделение модели, которое, как мне кажется, является ключом к правильному построению модели: “Модель предоставляет данные (обычно для View), а также реагирует на запросы (обычно от контроллера), изменяя своё состояние” Здесь очень важно обратить внимание на фразу “изменяя свое состояние“.

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

Что такое состояние модели с позиции реализации

Я не знаю какое определение “состояния модели” дают в умных книгах, но для себя я сформулировал так, состояние модели - это набор характеристик которые однозначно определяют, что можно (или нельзя) сделать с моделью в текущий момент времени. И на этом с теорией можно покончить.

Более интересно, на мой взгляд, понять, что из себя должна представлять модель на практике и как ее состояние передать конкретными возможностями используемого языка программирования (далее под “языком программирования” я буду подразумевать PHP). И здесь у меня в голове формируется единственная реализация, которая сводится к тому, что модель - это класс. Никакие другие реализации я рассматривать не буду.

Понятно, что класс - это только описание модели. У него не может быть никакого состояния. Поэтому состояние может появится только у конкретного экземпляра класса - объекта. И в таком случае внутреннее состояние объекта можно интерпретировать как состояние модели. А отсюда следует, что состояние модели - это набор внутренних переменных с их значениями.

Значит, с точки зрения реализации “состояние модели” - это просто набор переменных. Замечательно, я пришел к тому, что и раньше прекрасно знал - модель должна содержать переменные. :-) Естественно, что для более правильного понимания модели этого мало. И вот почему - понятие “состояния модели” должно появляться на этапе проектирования (продумывания) модели. Если задачи модели формулировать с позиции “состояния“, то и код модели не будет попадать в контроллер.

Что такое состояние модели с позиции проектирования

Обычно я не представляю себе модель как объект с набором состояний. Поэтому пример, который я рассматриваю далее, не очень удачный. Но все же попробую представить себе совсем простую модель. Например, модель получения данных из БД. Я накидал простенькую диаграмму (State Machine Diagram):
state

Из диаграммы должно быть видно, что у модели всего три состояния: “нет данных“, “сформулированы условия фильтрации данных” и “данные загружены“. Состояния выражаются через флаги - has_data и has_filter. Кроме этого, есть методы, которые переводят модель из одного состояния в другое: where и load.

Все, на этом проектирование простой модели закончено. В коде, данная модель могла бы выглядеть так:

class DB_Model extends Model {
     var $has_data = false;
     var $has_filter = false;

     public function where($conditions) {
          $this->has_filters = $this->db->where($conditions);
     }

    public function load() {
         $this->data = $this->db->get();
         $this->has_data = (bool) $this->data;
    }

    public function get() {
         return $this->data();
    }
}

В контроллере метод работающий с БД мог бы выглядеть так:

public function some_action() {
     $someModel = new DB_Model();
     $someModel->load();

    return $someModel->has_data ? new MainView($someModel) : new EmptyView();
}

Контроллер, представление и состояние модели

Вроде бы все хорошо, но меня смущает один момент: “А правильно ли я использовал контроллер?”. Ведь до сих пор я ни слова не сказал о том, как должны взаимодействовать модель, контроллер и представление в контексте “состояния модели”. Здесь я не буду оригинальным и приведу три известных правила:

Во-первых, и “представление”, и “контроллер” должны иметь возможность получать текущее состояние модели;
Во-вторых, “контроллер” должен иметь возможность влиять на состояние модели;
В-третьих, “модель” ничего не должна знать ни о “контроллере”, ни о “представлении”, зато они в свою очередь должны знать о модели все (точнее они должны знать об интерфейсе по которому необходимо взаимодействовать с моделью).

Теперь, чтобы проверить правильно ли написан код функции “some_action”, попробую представить его в другом виде:

public function some_action() {
     return new MainView(new DB_Model);
  }

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

<html>
<body>
<?php $model->load()
    if ($model->has_data) {
?>
      … здесь идет отображение загруженных данных …
<?php }else{?>
      … здесь сообщение об отсутствии данных …
<?php>
</body>
</html>

Как только я посмотрел на код представления, я сразу понял, что так делать нельзя! Проблема в том, что код представления не должен изменять состояние модели (см. правила выше), а метод load относится к методам изменяющим состояние модели. Поэтому, согласно приведенным выше правилам, загрузка данных из БД должна выполняться в контроллере. А это значит, что первый пример был абсолютно правильным.

Заключение

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

Особо отмечу, что все сказанное - это мое понимание и восприятие шаблона. Поэтому я буду благодарен за указание на ошибки и неточности.

  1. Немного про State тестирование в TDD
  1. В шаблоне Active Record модель это одна запись из таблицы. Моя любимая реализация модели, поэтому, расскажу про нее.
    Там есть понятие “грязный” и “чистый объект”.
    Грязный объект, это тот объект, данные которого не хранятся в БД. Т.е., например, мы получили эти данные из формы и передали объекту модели. В этом случае мы можем проверить, “грязный” ли объект примерно так (ruby):

    user = User.new
    user.name = ‘Innokentiy’
    user.email = ‘kesha@mail.ru’
    user.new_record? # => true

    Вызвали метод new_record? и получили true, т.к. объект “грязный”. Дальше:

    user.save! # Сохраняем объект
    user.new_record? # => false

    Мы сохранили объект и снова проверили его на “грязность”. Объект успешно сохранился и синхронизирован с БД, значит, теперь он “чистый”.

    Кажется, именно это подразумевается под понятием “состояние” для модели в AR. Ну и конечно, я до сих пор убежден, что модель это не только методы работы над данными, но и сами даные.

  2. А Я вот еще больше запутался в этом паттерне. Сейчас предстоит разрабатывать и подымать проект довольно объемный по коду. Понял - без ООП и паттернов проектирования не обойтись. Сам Я люблю раскладывать всё по полочкам. До селе это решалось include(some_functions.php). Но с течением времени, Я как и все столкнулся с проблемой сопровождения и развития.

    и наверное Я туп….

    Мозг рвут в клочья различные книги по проектированию объектно ориентированных приложений и паттернов проектирования. Авторам настолько все это проело мозг, что чёткого определения, что именно должна содержать в себе модель нет нигде. Одна вода или в основе лежит какой-нибудь фреймворк, где “всё как вам уже надо, господа не парьтесь используйте”. >. авторизуется
    1) Контроллер отправил запрос Модели - “Пробей человечка плиз”.
    2) Модель подключилась к базе и взяла оттуда данные. Вот тут вопрос - кто должен проверять данные и делать дальнейшие действия? Контроллер или модель? Если следовать логике и товарищу, который говорит что не надо делать ТТУК, то модель. Она же описывает бизнес-логику (а бизнес-логика это реализация предметной области приложения. А что такое ПО и так понятно).
    3) Модель передала своё состояние контроллеру - “проверяю данные, погоди пять сек”.
    4) Контроллер принял к сведению состояние модели и передал вьюверу - “покажи пользователю часики и попроси подождать”.
    5) Модель проверила данные и передала контроллеру: “Это наш Великий Создатель. У меня прописано его пускать”.
    6) Контроллер получил от модели подтверждение, проверил по какому маршруту подключить шаблон главной панели управления, нашел необходимый шаблон и передал всю это вьюверу.
    7) Вьювер отобразил необходимую страничку и Автор остался доволен, приступая к написанию поста.

    Это правильный MVC, как Я его понимаю или Я иду не в том направлении.

  3. Arconas, мне Ваше объяснение очень даже нравится. Полностью совпадает с моим пониманием MVC шаблона.

  4. Evgeny Sergeev, спасибо за ответ.
    Значится Я иду верным путем, ну или по крайней мере верно ступаю по минному полю.

  5. Здравствуйте, уважаемые разработчики.
    Я тоже интересуюсь данной темой. Сейчас пишу игру похожую на тетрис на Java. Использую принцип MVC, тоже ломал голову что к чему…

    Спасибо за ваши комментарии - я Вас поддерживаю!

  6. Arconas, как Вам данная статья?
    http://hexlet.ru/blog/112.html

  7. Arthur, если честно, то не ахти. Во-первых, это выдержки из учебного курса, который по своему определению напихан кучей умных слов и нет ничего по делу. Единственное полезное - это графики и конечный абзац. Но это всё теория.

    Всё самое интересное начинается, когда программист делает над собой неимоверное усилие и начинает с нуля писать, ну… допустим, CMS для блога. И делает он это с применением MVC (ну или там MVC2, 3,4… без разницы… это всего-лишь один из способов “нарисовать круг”) и в процессе работы наглядно показывает почему он сделал выбор именно в пользу этого паттерна. И самое главное он пишет систему полностью, а не “кустисто” типа статей на Хабре: “Вот тут мы забабахаем class bla_bla_bla extend tru_lia_lia, а вот тут жахнем контролер ошибок, а здесь прикрутим шаблонизатор, и вот у нас готовая система”. Старые матерые прогеры почешут заросший щетиной подбородок и кивнут типа: “да чел ты крут, но в топку ваше говнище, надо использовать ZEND(можно заменить на любой сейчас дико модный фрейм) ибо он тащит, а еще накрутить Yii, добавить jQuery”. Интернет подобным просто кишит. Это просто ужас и нежелание помочь подрастающему поколению. А ответы типа “открой код любой CMS и разберись” вымораживают. Хочется ответить - открой капот автомобиля и разберись как двигатель работает. И да поставь мне туда турбину. Если не рванет - ты справился с заданием.

    Я немного сейчас отошел от программирования и учусь рисунку. И вот преподаватель с которым Я занимаюсь рисует вместе со мной показывая как это обычно делается. Сидим рисуем зерна кофе, не получается. Преподаватель садиться и рисует, а я наблюдаю. Потом сажусь и повторяю. За крайне короткий промежуток времени по её словам Я рисую на уровне студента конца первого курса. То же самое должно быть и в программировании с немного правда другим подходом, но не в этом суть.

    Еще ни разу мне не попадалась статья или цикл статей, где бы обучали не теории и заумным словам аля БИЗНЕС МАТЬ ЕЁ ЛОГИКА или КОНТРОЛЕРРР, состояние модели, а пошагово, с нуля, без использования “супер фраймов” (для некоторых программистов это как серпом по яйцам) и адски навороченных шаблонизаторов писали бы… там тот же блог или гостевую книгу. Что-то простое, но на чём можно обучится. Раньше это было. Серии книг Кузнецова и Симдянова, множество орейлевской литературы. Но они не позволяют двигаться дальше, предел знаний есть. Сейчас как-то всё “быстро-быстро-быстро и вуаля”. А потом мы удивляемся - почему ломают вроде бы неприступные сайты, почему они падают при высокой посещаемости и почему вокруг того же php крутится огромное количество быдлокодеров.

    Я давно уже хочу начать в своем блоге цикл статей типа: “пишем с нуля без купюр и теоретической мутатени”, но пока что уровень моих знаний оцениваю на троечку и продолжаю собирать грабли. Как вот набью тучу шишек, как только моя CMS будет написана и возьмет порог в 30 000 пользователей, обязательно примусь за написание развернутых статей или может даже скринкастов.

    Arthur, ой, кстати. Вы меня извините, но не принимайте это всё как критику или еще что-то. Просто наболело =D, такой выплеск графоманства.

Leave a Reply

« Мое понимание архитектурного шаблона MVC Про Agile методологию »

 

ремонт дачного дома объявление на сайте и мансарды строительство санкт-петербург . | Печи-камины от производителя . | экструдированный пенополистирол . | Снять комфортабельные апартаменты Равда на сайте realestatedreams.ru | Банкеты-организация, обслуживание - организация свадьбы в подмосковье .