2NetFly
-
MCV в целом и реализация контроллера в частности
Логическое продолжение всех тем, посвященных парадигме модель-контроллер-представление. Я заметил, что очень многие участники форума пишут и поддерживают собственные системы, в основе которых лежит MCV model 2. Большинство знакомы с такими решениями, как Tapestry, Struts, php-mcv (php), OpenInteract (perl), Maypole (perl), поэтому, я думаю, мы легко поймем друг друга.
В данной теме хотелось бы прежде всего обсудить реализацию контроллера и его взаимодействие с представлением. Этот вопрос актуален независимо от того, какой подход используется для реализации бизнес логики или самого представления. Хочется напомнить, что мы говорил о написании MCV фреймворка на нетипизированном языке (PHP, Perl, Ruby etc.), поэтому иногда правильностью можно пожертвовать ради гибкости и простоты. "Объекты Perl не плохи; просто они другие" (с) Кристиансен.
Итак, к теме. Большинство MCV реализованы с использование контроллера запросов. Все запросы направляются на определенный скрипт, который, на основе конфигурационного файла (ini, xml, языковой структуры) находит, создает и передает управление обработчику команды. При этом обработчику передается глобальный конфигурационный файл, запрос и прочие данные. Обработчик манипулирует объектами модели, а затем либо передает управление шаблонизатору, либо другому обработчику (форвардинг).
Момент первый, который хотелось бы обсудить. Я знаком с двумя способами реализации обработчиков:
1. Обработчиком является метод некоторого класса. Часто один класс содержит все методы-обработчики для модуля.
2. Обработчиком является отдельный класс, наследующий базовый класс-обработчик, в котором реализован стандартный набор методов (new, init, process). Переопределяя метод process происходит управление поведением обработчика.
Я долгое время использовал первый вариант, но затем перешел на классы-обработчики.
Момент второй. Необходим класс, который будет на основе переменных окружения определять модуль и команду, должным образом обрабатывать параметры, загружать и предоставлять доступ к глобальному конфигу (базовый URL, основные пути и т.д.), устанавливать и считывать некоторые атрибуты, устанавливать значения, которые будут доступны из шаблона и т.д. Плюс к этому, установка заголовков, плюшек, управление буфером.
В PHP-порте Struts, например, существуют отдельные классы request, response, context (порты java классов). С одной стороны, такое разделение оправдано, с другой - не очень удобно передавать в каждый класс 4-5 объектов (на входе они все равно собираются), да и иногда не понятно, какой метод в каком классе нужно искать. В одной из Perl систем, встретившихся мне, реализован только класс request, который берет на себя практически все обязанности (установка заголовков, обработка параметров, установка переменных для шаблона). Я в своей системе пришел к компромиссному решению: написал классы Response, Config, Displayer и Request. В Request существуют три поля, которые хранят экземпляры объектов Response, Config, Displayer. Таким образом, имеем четкую структуру, сохраняя возможность держать все в одном объекте и передавать только его. Кстати, была идея сделать ничего не делающий контейнер для всех объектов, но т.к. Request у меня самый используемый решил поручить эту задачу именно ему.
Итак, вот затравка для начала дискуссии.
Логическое продолжение всех тем, посвященных парадигме модель-контроллер-представление. Я заметил, что очень многие участники форума пишут и поддерживают собственные системы, в основе которых лежит MCV model 2. Большинство знакомы с такими решениями, как Tapestry, Struts, php-mcv (php), OpenInteract (perl), Maypole (perl), поэтому, я думаю, мы легко поймем друг друга.
В данной теме хотелось бы прежде всего обсудить реализацию контроллера и его взаимодействие с представлением. Этот вопрос актуален независимо от того, какой подход используется для реализации бизнес логики или самого представления. Хочется напомнить, что мы говорил о написании MCV фреймворка на нетипизированном языке (PHP, Perl, Ruby etc.), поэтому иногда правильностью можно пожертвовать ради гибкости и простоты. "Объекты Perl не плохи; просто они другие" (с) Кристиансен.
Итак, к теме. Большинство MCV реализованы с использование контроллера запросов. Все запросы направляются на определенный скрипт, который, на основе конфигурационного файла (ini, xml, языковой структуры) находит, создает и передает управление обработчику команды. При этом обработчику передается глобальный конфигурационный файл, запрос и прочие данные. Обработчик манипулирует объектами модели, а затем либо передает управление шаблонизатору, либо другому обработчику (форвардинг).
Момент первый, который хотелось бы обсудить. Я знаком с двумя способами реализации обработчиков:
1. Обработчиком является метод некоторого класса. Часто один класс содержит все методы-обработчики для модуля.
2. Обработчиком является отдельный класс, наследующий базовый класс-обработчик, в котором реализован стандартный набор методов (new, init, process). Переопределяя метод process происходит управление поведением обработчика.
Я долгое время использовал первый вариант, но затем перешел на классы-обработчики.
Момент второй. Необходим класс, который будет на основе переменных окружения определять модуль и команду, должным образом обрабатывать параметры, загружать и предоставлять доступ к глобальному конфигу (базовый URL, основные пути и т.д.), устанавливать и считывать некоторые атрибуты, устанавливать значения, которые будут доступны из шаблона и т.д. Плюс к этому, установка заголовков, плюшек, управление буфером.
В PHP-порте Struts, например, существуют отдельные классы request, response, context (порты java классов). С одной стороны, такое разделение оправдано, с другой - не очень удобно передавать в каждый класс 4-5 объектов (на входе они все равно собираются), да и иногда не понятно, какой метод в каком классе нужно искать. В одной из Perl систем, встретившихся мне, реализован только класс request, который берет на себя практически все обязанности (установка заголовков, обработка параметров, установка переменных для шаблона). Я в своей системе пришел к компромиссному решению: написал классы Response, Config, Displayer и Request. В Request существуют три поля, которые хранят экземпляры объектов Response, Config, Displayer. Таким образом, имеем четкую структуру, сохраняя возможность держать все в одном объекте и передавать только его. Кстати, была идея сделать ничего не делающий контейнер для всех объектов, но т.к. Request у меня самый используемый решил поручить эту задачу именно ему.
Итак, вот затравка для начала дискуссии.