Шаблон проектирования MVC и PHP


Оглавление (нажмите, чтобы открыть):

Шаблон проектирования MVC и PHP

В предыдущем уроке мы дошли до следующей структуры:

  • Модель предметной области (или просто Модель) описана с помощью ORM (хотя это не обязательно, хранилище — вещь отдельная от модели).
  • Функция-обработчик обращается к модели для выполнения запрошенных операций и выводит необходимые данные в шаблон.
  • Шаблон описывает представление конкретной страницы и строится на основании данных переданных из функции-обработчика.

Описанная структура носит гордое имя MVC или Model-View-Controller (обычно добавляют приписку version 2, так как первая версия MVC используется для толстых клиентов, в которых все работает немного по-другому), где M — модель предметной области, C — наша функция обработчик (в других фреймворках могут быть другие сущности), а V — шаблон. MVC разделяет приложение минимум на три слоя и определяет то, как они могут взаимодействовать друг с другом. Это важно для создания модульных приложений, то есть таких, которые легко развивать и модифицировать. При этом никто не запрещает добавлять новые и дробить текущие слои, все это уже зависит от сложности самого приложения.

  • M — ядро приложения. В идеале — чистая бизнес-логика. M не знает ничего о других частях приложения и не может на них влиять.
  • C — использует M для выполнения запрашиваемых операций и отвечает за генерацию V.
  • V — получает данные от C и иногда от M, но такое не приветствуется. И уж точно V не должен знать ничего о базе данных. Кстати, этим грешат начинающие разработчики, которые выполняют SQL запросы прямо из шаблонов.

MVC является архитектурным шаблоном (или паттерном проектирования). Шаблон проектирования в разработке — повторяемая архитектурная конструкция, представляющая собой решение проблемы проектирования в рамках некоторого часто возникающего контекста. В нашем случае контекст — обработка http-запросов.

Паттернов проектирования очень много на все случаи жизни. Некоторые из них очень простые и ближе к идиомам, то есть каким-то локальным участкам кода, которые принято писать тем или иным способом в конкретном языке. Некоторые паттерны — всеобъемлющие, подобные MVC. Они определяют глобальные ограничения, но ничего не говорят о способе реализации. В любом случае паттерны — не догма и не формальная спецификация, а значит всегда есть место для самостоятельного выбора.

В MVC заложена довольно простая, но важная идея разделения приложения на слои с чёткими границами. Такой подход позволяет развивать каждый слой независимо от других, при условии, что у вас правильно выстроены зависимости между ними. Обратите внимание, что в MVC все связи однонаправленные. Другими словами, в MVC нет двух слоёв, которые знают друг о друге одновременно. Если один слой знает о другом, то второй ничего не знает о первом и наоборот. Модульность (в общем случае — абстракция) — это один из ключевых факторов, делающих приложения по настоящему качественными с точки зрения разработки. Как вы увидите позже, все веб-фреймворки построены именно по модели MVC с небольшими модификациями, не влияющими на ключевую идею.

Паттерн MVC на примере Cапера

Введение

Паттерн Model-View-Controller (MVC) является крайне полезным при создании приложений со сложным графическим интерфейсом или поведением. Но и для более простых случаев он также подойдет. В этой заметке мы создадим игру сапер, спроектированную на основе этого паттерна. В качестве языка разработки выбран Python, однако особого значения в этом нет. Паттерны не зависят от конкретного языка программирования и вы без труда сможете перенести получившуюся реализацию на любую другую платформу.

Реклама

Коротко о паттерне MVC

Как следует из названия, паттерн MVC включает в себя 3 компонента: Модель, Представление и Контроллер. Каждый из компонентов выполняет свою роль и является взаимозаменяемым. Это значит, что компоненты связаны друг с другом лишь некими четкими интерфейсами, за которыми может лежать любая реализация. Такой подход позволяет подменять и комбинировать различные компоненты, обеспечивая необходимую логику работы или внешний вид приложения. Разберемся с теми функциями, которые выполняет каждый компонент.

Модель

Отвечает за внутреннюю логику работы программы. Здесь мы можем скрыть способы хранения данных, а также правила и алгоритмы обработки информации.

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

Представление

Отвечает за отображение данных Модели. На этом уровне мы лишь предоставляем интерфейс для взаимодействия пользователя с Моделью. Смысл введения этого компонента тот же, что и в случае с предоставлением различных способов хранения данных на основе нескольких Моделей.

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

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

Контроллер

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

Фактически на каждое действие, которое может сделать пользователь в Представлении, должен быть определен обработчик в Контроллере. Этот обработчик выполнит соответствующие манипуляции над моделью и в случае необходимости сообщит Представлению о наличии изменений.

Реклама

Спецификации игры Сапер

Достаточно теории. Теперь перейдем к практике. Для демонстрации паттерна MVC мы напишем несложную игру: Сапер. Правила игры достаточно простые:

  1. Игровое поле представляет собой прямоугольную область, состоящую из клеток. В некоторых клетках случайным образом расположены мины, но игрок о них не знает;
  2. Игрок может щелкнуть по любой клетке игрового поля левой или правой кнопками мыши;
  3. Щелчок левой кнопки мыши приводит к тому, что клетка будет открыта. При этом, если в клетке находится мина, то игра завершается проигрышем. Если в соседних клетках, рядом с открытой, расположены мины, то на открытой клетке отобразится счетчик с числом мин вокруг. Если же мин вокруг открытой клетки нет, то каждая соседняя клетка будет открыта по тому же принципу. То есть клетки будут открываться до тех пор, пока либо не упрутся в границу игрового поля, либо не дойдут до уже открытых клеток, либо рядом с ними не окажется мина;
  4. Щелчок правой кнопки мыши позволяет делать пометки на клетках. Щелчок на закрытой клетке помечает ее флажком, который блокирует ее состояние и предотвращает случайное открытие. Щелчок на клетке, помеченной флажком, меняет ее пометку на вопросительный знак. В этом случае клетка уже не блокируется и может быть открыта левой кнопкой мыши. Щелчок на клетке с вопросительным знаком возвращает ей закрытое состояние без пометок;
  5. Победа определяется состоянием игры, при котором на игровом поле открыты все клетки, за исключением заминированных.

Пример того, что у нас получится приведен ниже:

UML-диаграммы игры Сапер

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

Диаграмма Состояний игровой клетки

Любая клетка на игровом поле может находиться в одном из 4 состояний:

  1. Клетка закрыта;
  2. Клетка открыта;
  3. Клетка помечена флажком;
  4. Клетка помечена вопросительным знаком.

Здесь мы определили лишь состояния, значимые для Представления. Поскольку мины в процессе игры не отображаются, то и в базовом наборе соответствующего состояния не предусмотрено. Определим возможные переходы из одного состояния клетки в другое с помощью UML Диаграммы Состояний:

Диаграмма Классов игры Сапер

Поскольку мы решили создавать наше приложение на основе паттерна MVC, то у нас будет три основных класса: MinesweeperModel , MinesweeperView и MinesweeperController , а также вспомогательный класс MinesweeperCell для хранения состояния клетки. Рассмотрим их диаграмму классов:

Организация архитектуры довольно проста. Здесь мы просто распределили задачи по каждому классу в соответствии с принципами паттерна MVC:

  1. В самом низу иерархии расположен класс игровой клетки MinesweeperCell . Он хранит позицию клетки, определяемую рядом row и столбцом column игрового поля; одно из состояний state , которые мы описали в предыдущем подразделе; информацию о наличии мины в клетке ( mined ) и счетчик мин в соседних клетках counter . Кроме того, у него есть два метода: nextMark() для циклического перехода по состояниям, связанным с пометками, появляющимися в результате щелчка правой кнопкой мыши, а также open() , который обрабатывает событие, связанное с щелчком левой кнопкой мыши;
  2. Чуть выше расположен класс Модели MinesweeperModel . Он является контейнером для игровых клеток MinesweeperCell . Его первый метод startGame() подготавливает игровое поле для начала игры. Метод isWin() делает проверку игрового поля на состояние выигрыша и возвращает истину, если игрок победил, иначе возвращается ложь. Для проверки проигрыша предназначен аналогичный метод isGameOver() . Методы openCell() и nextCellMark() всего лишь делегируют действия соответствующим клеткам на игровом поле, а метод getCell() возвращает запрашиваемую игровую клетку;
  3. Класс Представления MinesweeperView включает следующие методы: syncWithModel() — обеспечивает перерисовку Представления для отображения актуального состояния игрового поля в Модели; getGameSettings() — возвращает настройки игры, заданные пользователем; createBoard() — создает игровое поле на основе данных Модели; showWinMessage() и showGameOverMessage() соответственно отображают сообщения о победе и проигрыше;
  4. И наконец класс Контроллера MinesweeperController . В нем определено всего три метода на каждое возможное действие игрока: startNewGame() отвечает за нажатие на кнопке «Новая игра» в интерфейсе Представления; onLeftClick() и onRightClick() обрабатывают щелчки по игровым клеткам левой и правой кнопками мыши соответственно.

Реализация игры Сапер на Python

Пришло время заняться реализацией нашего проекта. В качестве языка разработки выберем Python. Тогда класс Представления будем писать на основе модуля tkinter .

Но начнем с Модели.

Модель MinsweeperModel

Реализация модели на языке Python выглядит следующим образом:

В верхней части мы определяем диапазон допустимых настроек игры:

Вообще, эти настройки можно было сделать тоже частью Модели. Однако размеры поля и количество мин достаточно статичная информация и вряд ли будет часто меняться.

Затем мы определили класс игровой клетки MinesweeperCell . Она оказалась достаточно простой. В конструкторе класса происходит инициализация полей клетки значениями по умолчанию. Далее для упрощения реализации циклических переходов по состояниям мы используем вспомогательный список markSequence . Если клетка находится в состоянии ‘opened’ , которое не входит в этот список, то в методе nextMark() ничего не произойдет, иначе клетка попадает в следующее состояние, причем, из последнего состояния ‘questioned’ она «перепрыгивает» в начальное состояние ‘closed’ . В методе open() мы проверяем состояние клетки, и если оно не равно ‘flagged’ , то клетка переходит в открытое состояние ‘opened’ .

Далее следует определение класса Модели MinesweeperModel . Метод startGame() осуществляет компоновку игрового поля по переданным ему параметрам rowCount , columnCount и mineCount . Для каждого из параметров происходит проверка на попадание в допустимый диапазон значений. Если переданное значение находится вне диапазона, то сохраняется то значение параметра игрового поля не меняется. Следует отметить, что для числа мин предусмотрена дополнительная проверка. Если переданное количество мин превышает размер поля, то мы ограничиваем его количеством клеток без единицы. Хотя, конечно, такая игра особого смысла не имеет и будет закончена в один шаг, поэтому вы можете придумать какое-нибудь свое правило на такой случай.

Игровое поле хранится в виде списка списков клеток в переменной cellsTable . Причем, обратите внимание, что в методе startGame() у клеток устанавливается лишь значение позиции, но мины еще не расставляются. Зато определяется переменная firstStep со значением True . Это нужно для того, чтобы убрать элемент случайности из первого хода и не допускать мгновенный проигрыш. Мины будут расставляться после первого хода в оставшихся клетках.

Метод getCell() просто возвращает клетку игрового поля по строке row и столбцу column . Если значение строки или столбца неверно, то возвращается None .

Метод isWin() возвращает True , если все оставшиеся не открытые клетки игрового поля заминированы, то есть в случае победы, иначе вернется False . А метод isGameOver() просто возвращает значение атрибута класса gameOver .

В методе openCell() происходит делегирование вызова open() объекту игровой клетки, которая расположена на игровом поле в позиции, указанной в параметрах метода. Если открытая клетка оказалось заминированной, то мы устанавливаем значение gameOver в True и выходим из метода. Если игра еще не окончена, то мы смотрим, а не первый ли это ход, проверяя значение firstStep . Если ход и правда первый, то произойдет расстановка мин по игровому полю с помощью вспомогательного метода generateMines() , о которой мы поговорим немного позже. Далее мы подсчитываем количество заминированных соседних клеток и устанавливаем соответствующее значение атрибута counter для обрабатываемой клетки. Если счетчик counter равен нулю, то мы запрашиваем список соседних клеток с помощью метода getCellNeighbours() и осуществляем рекурсивный вызов метода openCell() для всех закрытых «соседей», то есть для клеток со статусом ‘closed’ .

Мастер Йода рекомендует:  Частичная проверка правильности ввода данных.

Метод nextCellMark() всего лишь делегирует вызов методу nextMark() для клетки, расположенной на переданной позиции.


Расстановка мин происходит в методе generateMines() . Здесь мы просто случайным образом выбираем позицию на игровом поле и проверяем, чтобы клетка на этой позиции не была открыта и не была уже заминирована. Если оба условия выполнены, то мы устанавливаем значение атрибута mined равным True , иначе продолжаем поиск другой свободной клетки. Не забудьте, что для того, чтобы использовать на Python модуль random нужно явным образом его импортировать командой import random .

Метод подсчета количества мин countMinesAroundCell() вокруг некоторой клетки игрового поля полностью основывается на методе getCellNeighbours() . Запрос «соседей» клетки в методе getCellNeighbours() тоже реализован крайне просто. Не думаю, что у вас возникнут с ним проблемы.

Представление MinesweeperView

Теперь займемся представлением. Код класса MinesweeperView на Python представлен ниже:

Наше Представление основано на классе Frame из модуля tkinter , поэтому не забудьте выполнить соответствующую команду импорта: from tkinter import * . В конструкторе класса передаются Модель и Контроллер. Сразу же вызывается метод createBoard() для компоновки игрового поля из клеток. Скажу заранее, что для этой цели мы будем использовать обычные кнопки Button . Затем создается Frame , который будет выполнять роль нижней панели для указания параметров игры. На эту панель мы последовательно помещаем кнопку «Новая игра», обработчиком которой становится наш Контроллер с его методом startNewGame() , а затем три счетчика Spinbox для того, чтобы игрок мог указать размер игрового поля и число мин.

Метод syncWithModel() просто проходит в двойном цикле по каждой игровой клетке и изменяет соответствующим образом вид кнопки, которая представляет ее в нашем графическом интерфейсе. Для простоты я использовал текстовые символы для вывода обозначений, однако не так сложно поменять текст на графику из внешних графических файлов.

Кроме того, обратите внимание, что для представления открытой клетки мы используем стиль кнопки SUNKEN . А в случае проигрыша открываем местоположение всех мин на игровом поле, показывая соответствующие кнопки черным цветом, а кнопку, отвечающую последней открытой клетке с миной, выделяем красным цветом:

Следующий метод blockCell() выполняет вспомогательную роль и позволяет контроллеру устанавливать состояние блокировки для кнопок. Это нужно для предотвращения случайного открытия игровых клеток, помеченных флажком, и достигается путем установки пустого обработчика щелчка левой кнопки мыши.

Метод getGameSettings() всего лишь возвращает значения размещенных в нижней панели счетчиков с размером игрового поля и количеством мин.

Создание представления игрового поля осуществляется в методе createBoard() . В первую очередь идет попытка удаления старого игрового поля, если оно существовало, а также мы пробуем установить значения счетчиков из панели в соответствии с текущей конфигурацией Модели. Затем создается новый Frame , который мы назовем board , для представления игрового поля. Таблицу кнопок buttonsTable мы компонуем по тому же принципу, что и игровые клетки в Модели с помощью двойного цикла. Обработчики каждой кнопки привязываются к методам Контроллера onLeftClick() и onRightClick() для щелчка левой и правой кнопок мыши соответственно.

Последние два метода showWinMessage() и showGameOverMessage() всего лишь отображают диалоговые окна с соответствующими сообщениями с помощью функции showinfo() . Для того, чтобы ей воспользоваться вам понадобится импортировать еще один модуль: from tkinter.messagebox import * .

Контролер MinesweeperController

Вот мы и дошли до реализации Контроллера:

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

Метод-обработчик для нажатия на кнопке «Новая игра» startNewGame() сначала запрашивает параметры игры, введенные в Представление. Параметры игры возвращаются в виде кортежа из трех компонент, которые мы пытаемся преобразовать в int . Если все пройдет нормально, то мы передаем эти значения в метод Модели startGame() для построения игрового поля. Если же что-то пойдет не так, то мы просто пересоздадим игровое поле со старыми параметрами. А в завершении мы направляем запрос на создание нового отображения игрового поля в Представлении с помощью вызова метода createBoard() .

Обработчик onLeftClick() сначала указывает Модели на необходимость открыть игровую клетку в выбранной игроком позиции. Затем сообщает Представлению о том, что состояние Модели изменилось и предлагает все перерисовать. Затем происходит проверка Модели на состояние победы или проигрыша. Если что-то из этого произошло, то сначала в Представление направляется запрос на отображение соответствующего уведомления, а затем происходит вызов обработчика startNewGame() для начала новой игры.

Щелчок правой кнопкой мыши обрабатывается в методе onRightClick() . В первой строке происходит вызов метода Модели nextCellMark() для циклической смены метки выбранной игровой клетки. В зависимости от нового состояния клетки Представлению отправляется запрос на установку или снятие блокировки на соответствующую кнопку. А в конце вновь обеспечивается обновление вида Представления для отображения актуального состояния Модели.

Комбинируем Модель, Представление и Контроллер

Теперь осталось лишь соединить все элементы в рамках нашей реализации Сапера на основе паттерна MVC и запустить игру:

Заключение

Вот мы и рассмотрели паттерн MVC. Коротко прошлись по теории. А потом по шагам создали полноценное игровое приложение, пройдя путь от постановки задачи и проектирования архитектуры до реализации на языке программирования Python с использованием графического модуля tkinter .

Шаблон проектирования MVC и PHP

И так начнем. Паттерн MVC подразумевает одну точку входа – index.php, через это скрипт будут проходить все запросы, через него будет работать вся логика проекта. Для того чтобы реализовать такой подход необходимо настроить сервер, подразумевается, что сайт работает на сервере apache, поэтому нам достаточно создать файл .htaccess, в котором мы укажем правила маршрутизации URL. Помимо определения точки входа, маршрутизация позволяет создавать ЧПУ(человеко-понятные урлы). То есть после правильной настройки, адреса страниц буду выглядеть вот так site.ru/article/new.
Для начала, давайте составим .htaccess, который перенаправит обработку всех страниц на скрипт index.php. Код выглядит вот так:

Файл .htaccess должен лежать в корневой папке сайта, тут же необходимо создать скрипт index.php, который является точкой входа. Давайте запишем в index.php одну строку, для проверки работы перенаправления:

Теперь можно проверять работу перенаправления, введите любой адрес и посмотрите, что получиться: test-mvc.web/sdf/sdf/ или test-mvc.web/sdf/sdf/2342/не важно, на экране в любом случае, должно появиться «Test». Если Вы увидели эту надпись, значит, у нас все получилось.
Продолжим, давайте для удобства создадим в корне сайта файл config.php, в котором будем задавать различные константы, облегчающие своим существование настройку сайта. Это могут быть различные пути к скриптам, подступы к базе данных и так далее. Сейчас в конфиге давайте зададим следующее:

Для того, чтобы константы и другие данные конфига мы могли использовать во всем проекте, в файле index.php необходимо подключить скрипт config.php.
Помимо подключения файла с настройками, в index.php нужно создать подключение к базе данных, подключить скрипт с ядром сайта и запустить роутер, в котором будет происходить маршрутизация.
Теперь по порядку, создание соединения с базой данных будет находиться в index.php для того, чтобы соединение открывалось только один раз. Единожды открыв соединение, мы сможем использовать его во всех контроллерах и моделях, но об этом чуть позже. Сейчас просто создадим соединение с базой. Для работы с бд я решил использовать PDO. Подробнее почитать про PDO можно тут.
Ядро сайта расположим в папке core и назовем скрипт core.php, тут мы напишем функцию, которая будет сама подключать, необходимы для работы классы. Такая функция очень облегчит и упростит нам работу с контролерами, моделями и тд. Поскольку, забегая вперед скажу, что каждый контролер и каждая модель будут представлять собой отдельный класс.
Помимо авто подключения классов, добавим в ядро создания хранилища (реестра), в котором будем хранить все необходимые объекты и переменные, которые могут пригодиться в любом месте проекта.
Роутер тоже подключим в индексном файле, он будет анализировать URL и подключать необходимый контроллер и экшен. Что такое контролер я писал в предыдущей статье, а информацию про экшен я пропустил умышленно, не став нагружать лишней информацией. Так что же такое экшен?
Контролер это класс, в котором заключены различные методы, при MVC подходе каждый метод будет являться экшеном. То есть экшен(action) – это метод класса, который будет обрабатывать данные и передавать их в представление (в шаблон). Может быть, пока не совсем понятно, но после примера все станет на свои места.
На данном этапе теории достаточно, давайте перейдем к практике. Приведу код файлов, работу которых, я описывал выше.
Код скрипта index.php:

Класс хранилища Registry.php, будет находиться в папке /classes/

Код файла router.php, который находиться в папке /classes/

Теперь необходимо создать папки для хранения контроллеров, шаблонов и моделей – в корне создадим три папки controllers, views и models. И создадим несколько тестовых файлов /controllers/index.php, /views/index/index.php и /models/model_users.php, а теперь заполним файлы:
Для контроллера:

Как вы могли заметить, класс контролера наследуется от родительского класса Controller_Base. Это сделано, для того, чтобы упростить класс контролера. Поскольку нам еще необходимо подключать класс для работы с шаблонами, его подключение вынесено в Controller_Base.
Приведу его код, он расположен в папке /classes/ и называется controller_base.php :

Теперь осталось только разобраться с шаблонами. В абстрактном классе Controller_Base мы вызываем класс Template и передаем ему имя шаблона и имя контроллера.
Код класса Template, который лежит тут /classes/ и называется template.php

Если вы внимательно прочитали код, то наверняка поняли, что для отображения на страницах у нас используется шаблон first_layouts и вьюха(отображение) index.php – ее код я приводил чуть выше. Все что нам осталось, это создать файл шаблона first_layouts. Расположим его в папке /views/layouts/first_layouts.php
Шаблон будет содержать вот такой код:

Вот и все, на этом создание «каркаса» закончено. Сейчас у нас получилась самая простая структура, использующая в своей основе паттерн MVC.

Архитектура MVC — Model, View, Controller

В сегодняшнем уроке мы вообще не будем писать код. Вместо этого мы поговорим о том, как вообще построить приложение на PHP так, чтобы самому в нём не запутаться. Мы поговорим о том, что вообще такое архитектура приложения. А после этого мы разберем пример архитектуры на паттерне проектирования MVC и рассмотрим, как его использовать в разработке программ на языке PHP.

Продолжение урока будет доступно вам
после покупки курса ООП в PHP

Об авторе

Если вам интересно узнать
как я стал программистом,
читайте вот эту статью.

MVC PHP: Понятие, преимущества, пример

В данной статье мы разберемся с понятием MVC, и как, на примере, можно применить это в PHP.

Понятие MVC

MVC(Model-view-controller, «Модель-представление-поведение», «Модель-представление-контроллер») — это шаблон проектирования приложений, при котором управляющая логика поделена на три отдельных компонента таким образом, что модифицирование одного из них дает минимальное влияние на остальные.

Шаблон MVC хорошо применять при создании сложных проектов, где необходимо отделить работу php программиста (или разделить группу программистов на отделы), дизайнера, верстальщика, и т.д.

Шаблон MVC разделяет представление, данные, и обработку действий пользователя на три отдельных компонента:

MVC Модель (Model). Модель предоставляет данные (обычно для View), а также реагирует на запросы (обычно от контроллера), изменяя своё состояние.

MVC Представление (View). Отвечает за отображение информации (пользовательский интерфейс).

MVC Поведение (Controller). Интерпретирует данные, введённые пользователем, и информирует модель и представление о необходимости соответствующей реакции.

Для наглядности схемы действия шаблона MVC, ниже предоставлена иллюстрация.

Такие компоненты как представление и поведение зависят от модели, но никак не влияют на нее. Модель может иметь несколько представлений. Может быть, концепция MVCсложная для понимания, но если ее осмыслить, она становиться незаменимой при разработке приложений на PHP.

MVC в PHP

Особенностью при использовании MVC в PHP, является то, что существует одна точка входа в php приложение, которая, например, достигается следующим образом. Создается index.php через который будут обрабатываться все запросы, для этого создаем в папке с индексом файл .htaccess и помещаем в него такой код:

Мастер Йода рекомендует:  Разработано приложение, позволяющее с помощью нейронных сетей раскрашивать чёрно-белые снимки

В предоставленном коде, первой строкой, проверяется существование запрашиваемого файла, и если его нет, то идет перенаправление на index.php, иначе даже запросы картинок сайта будут перенаправляться на индекс. Последняя строка кода преобразовывает запросы вида index.php?route=chat/index у вид index.php/chat/index. Если у вас нет возможности использовать ModRewrite в своем приложении, то вам придется делать переадресацию вручную.

PHP Модель

Данные о PHP модели содержаться в ее атрибутах и могут быть изменены только через специальные функции. Модель может содержать в себе несколько представлений. Как правило, phpмодель это класс работающий с БД, конкретнее: запись, чтение, удаление. Естественно чтение информации с БД может быть реализовано несколькими представлениями (функциями). Как пример модель статей на сайте: можно получить конкретную статью из БД, список последних, популярных, какой-то категории… это все представления модели. Для наглядности ниже предоставлен пример php модели.

PHP контролер (Поведение)

PHP контролеры получают запросы пользователей, которые мы направляли через index.php, и в соответствии с ними, корректируют работу модели. Правильнее сказать контролируют работу php приложения.

PHP Представление

Представление отслеживает изменение в модели и создает или меняет интерфейс php приложения.


Как работает данный PHP MVC шаблон?

При обращении пользователем по нужному url выбирается соответственный контролер, который обращается к представлению и модели, и выводится информация. Другими словами контролер в mvc есть связующим звеном модели и представления.

Преимущества MVC шаблона при создании PHP приложения

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

MVC пример

Особо не будем зацикливаться на примере работы MVC, так как уже имеется пример mvc на php. Добавлю лишь еще пару схем для более глубокого понимания.

Еще одна схема работы MVC шаблона на PHP, она более чем доступна для понимания.

Теперь можно сказать, что понятие mvc раскрыто. Если вы впредь не использовали MVC шаблон при организации создания вашего проекта, то советую вам не медлить с применением полученных знаний. Если еще сомневаетесь – читайте пункт преимущества mvc шаблона. Если же имеете практические предложения по поводу использования mvc в php, просьба высказаться в комментариях.

Реализация архитектурного шаблона MVC с использованием шаблона проектирования «Наблюдатель» на языке PHP

Рубрика: Информационные технологии

Дата публикации: 04.05.2014 2014-05-04

Статья просмотрена: 1325 раз

Библиографическое описание:

Лясин Д. Н., Симонова О. Н. Реализация архитектурного шаблона MVC с использованием шаблона проектирования «Наблюдатель» на языке PHP // Молодой ученый. — 2014. — №6. — С. 108-111. — URL https://moluch.ru/archive/65/10770/ (дата обращения: 10.11.2020).

В статьерассматриваются особенности реализации и пример использования архитектурного шаблона MVCи шаблона «наблюдатель» для разработки веб-приложений на языке PHP.

Ключевыеслова: архитектурный шаблон, шаблон проектирования, MVC, наблюдатель, веб-приложение.

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

При разработке серверных веб-приложений на языке PHP все чаще применяется объектно-ориентированный подход с использованием архитектурного шаблона MVC (от англ. Model-View-Controller). Этот шаблон предполагает разделение программной системы на несколько компонентов, называемых модель (Model), вид (View) и контроллер (Controller), благодаря чему бизнес-логика приложения отделяется от пользовательского интерфейса. Такое приложение проще изменять, масштабировать, тестировать и сопровождать.

Реализовать взаимодействие между моделью и видом можно различными способами. Часто для этой цели используется поведенческий шаблон проектирования «наблюдатель» (Observer). Он позволяет классу-наблюдателю (observer) получать оповещения от класса-наблюдаемого (observable) об изменении своего состояния, реализуя тем самым схему взаимодействия «издатель-подписчик». В качестве наблюдателя в шаблоне MVC выступает вид (или несколько видов), а в качестве наблюдаемого — модель. Виды регистрируются в модели, которая оповещает их об изменении своего состояния. После получения оповещения виды извлекают из модели необходимые данные и динамически генерируют веб-страницу.

Эффективно реализовать шаблон «наблюдатель» на языке PHP можно с использованием стандартной библиотеки PHP (Standard PHP Library, SPL), которая была введена в PHP5 [1]. Для этого используются следующие классы и интерфейсы, предоставляемые SPL:

SplSubject — интерфейс, предназначенный для наследования классом-наблюдаемым. Интерфейс объявляет следующие абстрактные методы:

SplSubject::attach(SplObserver$observer) — метод, позволяющий зарегистрировать объект-наблюдатель для последующей отправки ему оповещений;

SplSubject::detach(SplObserver$observer) — метод, удаляющий наблюдателя из списка зарегистрированных;

SplSubject::notify(void) — метод, который нужно вызывать для оповещения зарегистрированных наблюдателей об изменении своего состояния.

SplObserver — интерфейс, предназначенный для наследования классом-наблюдателем. Он объявляет единственный абстрактный метод SplSubject::update(), который должен быть определен в наблюдателе. Этот метод будет вызываться, когда объект класса SplSubject вызовет метод notify().

SplObjectStorage — класс, позволяющий сохранять в контейнере и удалять из контейнера объекты классов-наблюдателей при помощи методов attach() и detach().

Рассмотрим пример PHP-приложения, построенного на основе архитектурного шаблона MVC с применением шаблона «наблюдатель» для реализации взаимодействия модели и вида.

Диаграмма UML, иллюстрирующая взаимосвязи между классами, приведена на рисунке 1.

Рис. 1. Диаграмма классов, реализующих шаблон MVC с использованием шаблона «наблюдатель»

Базовый класс Model, который будет являться родительским для всех моделей приложения, определяется следующим образом:

class Model implements SplSubject

public function __construct($server, $user, $pass, $base)

$this->storage = new SplObjectStorage();

function attach(SplObserver $observer)

Шаблон проектирования MVC и PHP

The best implementation of the Model-View-Controller architectural pattern in PHP!

  • Templates
  • Routing
  • Filters
  • Cache
  • Val >

The server must send the entire request to the ./index.php file.

Create the following structure in the project root directory:

IMPORTANT: You must use namespaces in your application. Be sure to specify the root namespace of your application using the AppBuilder::useNamespace(string) function.

IMPORTANT: The names of all controller classes must end with the Controller suffix. For example: HomeController , AccountController , TestController etc.

Your projects must implements the strict structure:

And adhere to the following rules:

Folder names must be in lowercase.

The views filenames must be in lowercase.

The file names of the controllers must be specified in the camel style, with a capital letter. The names must end with the Controller suffix. For example: HomeController.php .

The model is just classes. You can create any classes, with any structure.

It is recommended to adhere to the rule: the simpler, the better.

Using the static class Model , you can add metadata to a model in the constructor of the controller.

The views files contain markup. Markup can be complete or partial.

Using the PhpMvc\Html class, you can create markup for HTML elements or output some views within other views.

Use the helper class PhpMvc\View to customize the behavior of the view:


The controller classes names must match the controllers filenames. For example: file name is TestController.php , class name is TestController .

Each controller class must inherit from the PhpMvc\Controller class.

The controller classes must contain action methods.

The action names must match filenames of views. For example: view file is index.php , action name is index .

All methods of actions must have the modifier public.

The names of the action methods must not start with the underscore (_).

Each action can take any number of parameters.

The parameters can be received from the query string, or from the POST data.

The following example shows the output of parameters retrieved from the query string:

Below is an example of obtaining a model sent by the POST method:

Methods of action can return different results, in addition to views.

You can use the ready-made methods of the base class of the controller to output the data in the required format:

  • $this->view([string $viewOrModel = null[, object $model = null[, string $layout = null]]])
  • $this->json(mixed $data[, int $options = 0[, int $depth = 512]])
  • $this->file(string $path[, string $contentType = null[, string|bool $downloadName = null]])
  • $this->content(string $content[, string $contentType = ‘text/plain’])
  • $this->statusCode(int $statusCode[, string $statusDescription = null])
  • $this->notFound([string $statusDescription = null])
  • $this->unauthorized([string $statusDescription = null])
  • $this->redirect(string $url)
  • $this->redirectPermanent(string $url)
  • $this->redirectPreserveMethod(string $url)
  • $this->redirectPermanentPreserveMethod(string $url)
  • $this->redirectToAction(string $actionName[, string $controllerName = null[, array $routeValues = null[, string $fragment = null]]])

Instead of the presented methods, you can independently create instances of the desired results and return them:

All result classes implement the ActionResult interface. You can create your own result classes!

Filters allow you to add handlers before and after the action. And also handle errors of the action execution.

The filters must be in the ./Filters folder.

Each filter must be inherited from the PhpMvc\ActionFilter class.

Filters can be global, or work at the level of an individual controller, or action.

Filters for specific controller or action can be set in the controller’s constructor:

MVC — фундамент интернет магазина

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

В общих чертах суть работы шаблона понятна из расшифровки аббревиатуры: Model-View-Controller (Модель – Представление – Контроллер). Представление – отвечает, за пользовательский интерфейс, контролер – связывает представление и модель. Модель в свою очередь представляет собой всю логику работы скриптов.

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

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

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

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

Основа интернет магазина с использованием MVC

Потихоньку начнем писать наш интернет магазин, попутно изучая паттерн MVC.

Важной особенностью этого шаблона является то что, все страницы будут генерироваться только после того как пройдут через файл index.php , к которому будут перенаправлены все запросы пользователя. Чтобы добиться такого эффекта нужно в корневом файле .htaccess написать код:

Теперь я предлагаю вам для удобства восприятия материала скачать:

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

Разархивируйте скачанные файлы в корневую директорию вашего тестового сайта.

Найдите среди них файл LifeExampleShop.sql , это дамп базы данных необходимой для демонстрации урока по созданию интернет магазина. Импортируйте базу данных из LifeExampleShop.sql , для дальнейшей работы.

Если все сделанно верно то запустив свой сайт вы увидите примерно следующее:

Задачей данного урока является создание фундамента под интернет магазин с использованием шаблона программирования MVC. Внешне наш фундамент будет включать в себя три страницы: Главная, Каталог и Страница авторизации. Этих страничек будет более чем достаточно для демонстрации логики работы шаблона MVC. Забегая вперед сообщу, вам данные для учетной записи администратора:

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

И так, теперь, когда вы скачали и распаковали архив, а также импортировали БД, мы можем двигаться дальше и приступить непосредственно к самой сути патерна MVC.

Давайте я расскажу о структуре каталогов системы, и их содержимом. В корне сайта мы имеем 4-ре файла.

  1. .htacces – перенаправляет все запросы на index.php
  2. config.php – подключает автоматическую загрузку новых классов, и содержит в себе настройки для работы с БД.
  3. index.php – инициализирует запуск MVC системы.
  4. LifeExampleShop.sql – дамп базы интернет магазина.

Также в корне сайта у нас есть 4-ре каталога:

  1. application – по большому счету содержимое данной папки и есть патерн MVC. В ней находятся три подпапки с контролерами, моделями, и представлениями.
  2. images – без этой папки не обойдется ни один сайт, т.к. картинки нужны везде. В данном случае в ней находятся изображения продуктов каталога, а также логотип магазина.
  3. lib – в этой папке находятся библиотеки необходимые для работы сайта. Важными файлами в разрезе нашей темы являются: Application.php и BaseController.php . Именно эти файлы в купе с папкой application делают все, что нужно для исправной работы патерна MVC.
  4. template – как понятно из названия, эта папка с шаблоном для сайта, ее файлы содержат верстку графического интерфейса нашего интернет магазина.

Есть множество материалов в интернете, каждый из них описывает работу шаблона MVC в теории. Я считаю большим упущением отсутствие примера подробного алгоритма работы на основе практической работы системы. На начальных стадиях знакомства с MVC, мне было сложно понять, что от чего зависит, пока на конкретном примере не проанализировал ход работы системы.

Именно поэтому в данной статье я напишу о том, как же все это крутится и вертится. Благо есть для этого простая и готовая MVC система, которую вы скачали в начале статьи.

Ход работы MVC системы (алгоритм)

Как я уже и говорил, точкой входа будет файл index.php , это означает то, что с помощью файла index.php будут инициализироваться все необходимые компоненты. А именно компонент паттерна: Application.php , который определяет маршрут до нужного контролера и библитека настроек сайта и взаимодействия с БД: config.php .

Допустим, мы находимся на главной странице сайта, и хотим перейти на страницу каталога, для этого мы жмем на соответствующую ссылку в меню. Что же происходит в момент нажатия на ссылку? Ссылка имеет вид:

Первым делом данная ссылка преобразуется файлом .htaccess в вид

Далее в index.php , происходит инициализация MVC системы. И управление передается в файл Application.php , который в свою очередь по GET переменной $_GET[‘route’] определяет, какой контролер должен быть вызван. В данном случае это будет контролер с именем catalog.

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

  1. Запускает контролер для странницы каталога.
  2. Обрабатывает полученные данные. В этом случае данных не передается, запрашивается только вывод каталога.
  3. Обращается к модели каталога, которая и формирует html код для показа в публичной части.
  4. Сформированный html код передается в соответствующий вид (представление) контролера. И благополучно выводится в шаблоне интернет магазина.

Запомните важный момент: для любой новой страницы сайта должен существовать одноименный контролер (Сontroler), а также одноименный вид (View). Заметьте модель (Model) создавать для каждой страницы не обязательно, т.к. можно использовать другие модели либо не использовать их вовсе, так сделано с главной страницей нашего учебного интернет магазина.

Плюсы MVC

Сложно не заметить плюсов использования паттерна MVC в больших проектах. С помощью данного паттерна программирования мы легко можем оперировать разными программными кодами отдельно друг от друга, не боясь навредить всей системе в целом. Неверно написав код контролера страницы для авторизации, мы не заметим, неполадок находясь на странице каталога. И только когда будет вызван контролер страницы авторизации, система выдаст ошибку.


Вносить изменения в конкретную часть сайта не заморачиваясь о работе других очень удобно, и именно это позволяет сделать систему с реализацией MVC.

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

Правила использования MVC в нашем проекте.

Если вы взгляните на код функции __autoload() , отвечающей за загрузку вызываемых классов:

То вы обязательно заметите закономерность между названиями классов и структурой папок системы. Функция преобразует имя вызываемого класса в адрес, по которому расположен данный класс, заменяя символ _ подчеркивания на привычный / слеш.

Поясню: все названия классов должны содержать путь, по которому они расположены, где вместо символа / слеш, должен стоять символ _ подчеркивание. Например создание экземпляра инициализирующего класса Application будет иметь вид:

Это значит, что файл Application.php должен находиться в папке Lib . А класс контролера Application_Controllers_Catalog , будет расположен в application\controllers\сatalog.php , и тогда система MVC при анализе ссылки:

запросто определит, что нужный контролер именуется как «Catalog » и находится по адресу application\controllers\ , а следовательно сам класс называется Application_Controllers_Catalog . Такая логика позволит безошибочно определить необходимый контролер для обработки страницы.

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

В этой статье я рассказал об алгоритме разработанной мной MVC системы под интернет магазин, конечно, хотелось бы поведать еще многое и о взаимодействии модулей магазина, таких как каталог, и система авторизации, но это выходит за рамки данной статьи о паттерне программирования Model-View-Controller.

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

А пока вы ждете выхода следующего урока, я советую вам самостоятельно изучить содержимое архива с MVC ситемой.

Поскольку в следующем уроке о создании интернет магазина мы не будем возвращаться к логике работы паттерна Model-View-Controller (Модель–Представление–Контроллер), а просто будем создавать исправный интернет магазин.

Внимание! Уважаемый читатель прошу тебя не лениться и писать свои отзывы о данной статье, это повлияет на сорость написания следующей, а также буду учтены все замечания.

Паттерн MVC

Термин используется с конца 70-х гг. прошлого столетия. Эта модель явилась результатом проекта Smalltalk в компании Xerox PARC, где она была задумана как способ организации некоторых из ранних приложений графического пользовательского интерфейса. Некоторые из нюансов первоначальной модели MVC были связаны с концепциями, специфичными для Smalltalk, такими как экраны и инструменты, но более глобальные понятия все еще применимы к приложениям, и особенно хорошо они подходят для веб-приложений (MVC нашел отличное применение в ASP.NET, но ниже мы рассмотрим этот паттерн в WPF).

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

Модели

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

Представления

Применяются для визуализации некоторой части модели в виде пользовательского интерфейса.

Контроллеры

Обрабатывают поступающие запросы, выполняют операции с моделью и выбирают представления для визуализации пользователю.

Ниже структура MVC показана на диаграмме:

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

Уровень представления

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

Бизнес-уровень

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

Уровень данных

Уровень данных отвечает за получение, передачу и сохранение данных в файле, базе данных, службе или XML.

Данная структура представлена ниже на рисунке:

Итак, давайте продемонстрируем реализацию паттерна MVC на простом приложении WPF, разделив его на три части — модель, представление и контроллер.

Модель

Создайте новый проект WPF в Visual Studio, добавьте ссылку на сборку ProjectBilling.DataAccess, которая рассматривалась в предыдущей статье, добавьте класс ProjectsModel со следующим содержимым:

Этот код создает модель для использования нашим представлением. Представление получает обновления из модели и через контроллер передает данные обратно в модель используя ссылку на IProjectsModel. Мы создали класс ProjectsModel реализующий IProjectsModel для возможности легкой расширяемости и тестируемости приложения. Давайте рассмотрим этот код более подробно. Интерфейс IProjectsModel содержит следующие члены, необходимые для реализации в классе:

Projects — свойство, содержащее коллекцию проектов, загружаемых из кода доступа к данным.

ProjectUpdated — это событие для уведомления экземпляра класса Project об обновлении.

UpdateProject — метод представления проекта, который будет обновляться.

Класс модели соответственно реализует данный интерфейс добавляя простейшую функциональность.

Контроллер

Следующий код был добавлен в файл ProjectsController.cs и реализует функциональность контроллера:

Мы реализовали контроллер на основе интерфейса IProjectsController, включающего два метода. ShowProjectsView — метод позволяющий отображать представление (реализованное классом ProjectsView) конечному пользователю. Update — метод обновления данных проекта, который вызывает прототип IProjectsModel.

Представление

Представление реализовано в файлах ProjectView.xaml и ProjectView.xaml.cs:

Этот код создает простую форму, для отображения подробностей о проекте. Затем добавьте следующий код для ProjectsView.xaml.cs:

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

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

Самое интересное в моделе MVC, что обновление распространяется через представления. Выполните следующие шаги чтобы это увидеть:

Выберите проект Jones в раскрывающемся списке ComboBox первого диалогового окна.

Установите актуальную стоимость для него 1600.

Щелкните кнопку Update в этом окне.

Вы должны увидеть автоматическое обновление представления во втором окне:

Можете поэкспериментировать с другими проектами или открыть еще несколько окон, при этом везде обновление представления будет работать так же. Итак, как видно MVC абстрагирует бизнес-логику от уровня представления, тем самым добиваясь легкой синхронизации пользовательского интерфейса. Я не буду рассматривать здесь модульное тестирование (еще один аспект использования паттернов) просто потому, что MVC больше подходит для веб-приложений, нежели для приложений WPF. Тестирование будет показано позже с использованием паттерна MVVM.

Шаблон проектирования MVC и PHP

В предыдущем уроке мы дошли до следующей структуры:

  • Модель предметной области (или просто Модель) описана с помощью ORM (хотя это не обязательно, хранилище — вещь отдельная от модели).
  • Функция-обработчик обращается к модели для выполнения запрошенных операций и выводит необходимые данные в шаблон.
  • Шаблон описывает представление конкретной страницы и строится на основании данных переданных из функции-обработчика.

Описанная структура носит гордое имя MVC или Model-View-Controller (обычно добавляют приписку version 2, так как первая версия MVC используется для толстых клиентов, в которых все работает немного по-другому), где M — модель предметной области, C — наша функция обработчик (в других фреймворках могут быть другие сущности), а V — шаблон. MVC разделяет приложение минимум на три слоя и определяет то, как они могут взаимодействовать друг с другом. Это важно для создания модульных приложений, то есть таких, которые легко развивать и модифицировать. При этом никто не запрещает добавлять новые и дробить текущие слои, все это уже зависит от сложности самого приложения.

  • M — ядро приложения. В идеале — чистая бизнес-логика. M не знает ничего о других частях приложения и не может на них влиять.
  • C — использует M для выполнения запрашиваемых операций и отвечает за генерацию V.
  • V — получает данные от C и иногда от M, но такое не приветствуется. И уж точно V не должен знать ничего о базе данных. Кстати, этим грешат начинающие разработчики, которые выполняют SQL запросы прямо из шаблонов.

MVC является архитектурным шаблоном (или паттерном проектирования). Шаблон проектирования в разработке — повторяемая архитектурная конструкция, представляющая собой решение проблемы проектирования в рамках некоторого часто возникающего контекста. В нашем случае контекст — обработка http-запросов.

Паттернов проектирования очень много на все случаи жизни. Некоторые из них очень простые и ближе к идиомам, то есть каким-то локальным участкам кода, которые принято писать тем или иным способом в конкретном языке. Некоторые паттерны — всеобъемлющие, подобные MVC. Они определяют глобальные ограничения, но ничего не говорят о способе реализации. В любом случае паттерны — не догма и не формальная спецификация, а значит всегда есть место для самостоятельного выбора.

В MVC заложена довольно простая, но важная идея разделения приложения на слои с чёткими границами. Такой подход позволяет развивать каждый слой независимо от других, при условии, что у вас правильно выстроены зависимости между ними. Обратите внимание, что в MVC все связи однонаправленные. Другими словами, в MVC нет двух слоёв, которые знают друг о друге одновременно. Если один слой знает о другом, то второй ничего не знает о первом и наоборот. Модульность (в общем случае — абстракция) — это один из ключевых факторов, делающих приложения по настоящему качественными с точки зрения разработки. Как вы увидите позже, все веб-фреймворки построены именно по модели MVC с небольшими модификациями, не влияющими на ключевую идею.

Добавить комментарий