Что несёт нам Zend Framework 2.0? Надежда Блинова, веб-программист, Wizartech Георгий Туревич, ведущий веб-программист, Wizartech 27 марта 2010 г. Санкт-Петербург.

Презентация:



Advertisements
Похожие презентации
Тема: «Zend Framework. Общие сведения. Реализация паттерна MVC в Zend Framework» Тема: «Zend Framework. Общие сведения. Реализация паттерна MVC в Zend.
Advertisements

Что нового в PHP 5.3Что нового в PHP 5.3Почему PHP 5.3? PHP 5.2 существует уже 1.5 года. В нем найдено несколько серьезных ошибок, которые не могут быть.
Что нового в PHP 5.3 Дмитрий Стогов.
Создание проекта Zend Лекция 2 1.Создание нового проекта 2.Анализ нового проекта 3.Создание макетов.
Лекция 1 MVC (Model-View-Controller) - это конструкционный шаблон, который описывает способ построения структуры приложения, сферы ответственности и взаимодействие.
Коллекции классов Лекция 12. С помощью коллекций вместо создания структур данных программист использует готовые структуры данных, не заботясь об их реализации.
Работа с БД в Zend Лекция 4 1.Модель 2.Классы Zend_Db_Table и Zend_Config 3.Запросы 4.Свойства и методы таблицы.
Основы объектно-ориентированного программирования (ООП)
Проф. В.К.Толстых, Технологии разработки Internet- приложений ASP.NET приложения – обработка ошибок страниц и приложения, Global.aspx.
©Павловская Т.А. (СПбГУ ИТМО) Курс «С#. Программирование на языке высокого уровня» Павловская Т.А.
Где хранить данные в web- приложении page –JSP страница request – HTTP запрос session – сессия пользователя application – веб-приложение Static Java class.
1 © Luxoft Training 2012 Java: расширенные вопросы Модуль #8.
Организация программного кода при создании информационных систем Подготовил: Студент группы МЭК-21 Акименко В. И. Руководитель: Доц. Яровенко А. Н.
Ресурсы WPF Два типа ресурсов WPF: объектные ресурсы (object resource) – определенный.NET-объект, который можно использовать многократно; ресурсы сборки.
Перегрузка операторов x = a + b результат 1-й операнд2-й операнд оператор По количеству операндов операторы делятся на: унарные (один операнд) бинарные.
Программная иженерия Андрей Дмитриев ©
1 Современные системы программирования. Часть 2. Системное и прикладное программное обеспечение Малышенко Владислав Викторович.
Обработка исключений в C# Единая техника обнаружения ошибок времени выполнения и передачи информации о них.
Интерактивная языконезависимая система поиска шаблонов и дубликатов в программном коде Куделевский Евгений Валерьевич, 545 группа Научный руководитель:
OOП Инна Исаева. Подпрограмма – это большая программа, разделённая на меньшие части. В программе одна из подпрограмм является главной. Её задача состоит.
Транксрипт:

Что несёт нам Zend Framework 2.0? Надежда Блинова, веб-программист, Wizartech Георгий Туревич, ведущий веб-программист, Wizartech 27 марта 2010 г. Санкт-Петербург

Планируемые изменения Изменения в архитектуре Изменения в MVC Изменения в стандартах кодирования Изменения в прочих компонентах

Пространства имен __invoke() Замыкания Goto Late Static Binding (LSB) И др. Используемые новинки php 5.3

Унифицированный конструктор Стандартизация массива Options Исключения Контрактное программирование Уменьшение количества синглтонов Создание компонентов общего назначения Новые возможности Php 5.3 в плагинах Автозагрузка Пространства имен goto Изменения в плагинах Изменения в архитектуре

Унифицированный конструктор public function setOptions($options) { //... foreach ($options as $key => $value) { $method = 'set'. $key; if (method_exists($this, $method)) { $this->$method($value); } } return $this; } Во многих компонентах в методе setOptions часто встречается повторяющийся код:

Изменения в архитектуре Унифицированный конструктор namespace Zend; // Новый, общий для всех класс Options c методом setOptions class Options { public static function setOptions($object, array $options) { if (!is_object($object)) { return; } foreach ($options as $key => $value) { $method = 'set'. self::_normalizeKey($key); if (method_exists($object, $method)) { $object->$method($value); } } } public static function setConstructorOptions($object, $options) {... } protected static function _normalizeKey($key) {... } }

Изменения в архитектуре Унифицированный конструктор namespace Zend; class Options { public static function setOptions($object, array $options) {... } public static function setConstructorOptions($object, $options) { if ($options instanceof Zend_Config) { $options = $options->toArray(); } if (is_array($options)) { self::setOptions($object, $options); } } protected static function _normalizeKey($key) { $option = str_replace('_', ' ', strtolower($key)); $option = str_replace(' ', '', ucwords($option)); return $option; } }

Изменения в архитектуре Унифицированный конструктор use Zend\Options as Options; class Foo { public $bar = ''; public $baz = ''; public function __construct($options = null) { Options::setConstructorOptions($this, $options); } public function setOptions(array $options) { Options::setOptions($this, $options); } public function setBar($value) { $this->bar = $value; } public function setBaz($value) { $this->baz = $value; } }

Изменения в архитектуре Унифицированный конструктор $foo = new Foo(array('bar' => 'baz')); echo $foo->bar; // "baz" $foo->setOptions(array('bar' => 'boo', 'baz' => 'bat')); echo $foo->bar. $foo->baz; // "boobat"

underscore_separated_keys camelCasedKeys UPPERCASEDKEYS lowercasedkeys all_lowercase_underscore_keys Переводим в camelCase: Изменения в архитектуре Стандартизация массива Options str_replace(' ', '', ucwords(str_replace('_', ' ', $value)));

Изменения в архитектуре Exceptions. Исключения // у каждого компонента должен быть свой интерфейс Exception namespace \Foo\Bar; interface Exception { } class InvalidArgumentException extends \InvalidArgumentException implements Exception { } try { throw new InvalidArgumentException(); } catch (\Foo\Bar\Exception $e) { }

Design By Contract формальные, точные и верифицируемые интерфейсы Минимальные требования к компонентам будут вынесены в интерфейсы. С интерфейсами будут предложены стандартные реализации Разработчик сможет расширять стандартные и создавать костюмные реализации на основе интерфейса Изменения в архитектуре Контрактное программирование

Почему стоит отказаться от синглтона: Глобальное состояние усложняет разработку и тестирование Зависимость обычного класса от синглтона не видна в публичном контракте класса Наличие синглтона понижает тестируемость приложения в целом и классов, которые используют синглтон, в частности Изменения в архитектуре Уменьшение количества синглтонов

Plugins/Helpers/Strategies Decorators Factories Caching Изменения в архитектуре Создание компонентов общего назначения Области дублирующегося кода будут вынесены в отдельные подключаемые файлы

__invoke() Изменения в архитектуре Новые возможности Php 5.3 в плагинах class Example { public function __invoke() { echo "Hello World! \n"; } } $foo = new Example; $foo();

Closures (Замыкания) Изменения в архитектуре Новые возможности Php 5.3 в плагинах Нотация: function ($var) use ($outerVar1, $outerVar2,...) {} Пример: function outer($x) //Определение внешней функции { $y = 2; //Локальная переменная внешней функции $inner = function ($a) use ($x, $y) //Определение внутренней функции { $b = 4; //Локальная переменная внутренней функции $res = $x + $y + $a + $b; echo $res; //Результат будет равен 10 }; $inner(3); //Вызов внутренней функции } outer(1);

Pros: –Польза для фреймворка в целом и Zend_Controller и Zend_Search_Lucene в частности –Создание отдельного пространства для unit тестирования: \Test\Zend, \Zend\Test, или \ZendTest Cons –Глобальное переписывание кода Изменения в архитектуре Пространства имен

Полезно при работе с конечными автоматами (FSM - Finite State Machine) –парсерами –синтаксическими / лексическими анализаторами Компоненты: –Zend_Controller_Front –Zend_Ical –Zend_Search_Lucene –Zend_Markup –… Изменения в архитектуре Использование goto

Три стандартных типа: Chains (валидаторы, фильтры, декораторы) Helpers (action helpers, view helpers) Adapters (form display groups, subforms и элементы; database adapters; translation adapters и др. ) Изменения в плагинах

Отсутствие единообразия имен Разнообразие вызовов: –Action helpers: direct() –View helpers: formSelect() (имя класса) –Validators: isValid() –Filters: filter() Снижение производительности: PluginLoader производит лишние операции при каждом поиске. Нет единой парадигмы для конструкторов и/или конфигураций адаптеров Нет единой парадигмы для передачи информации фабрикам Изменения в плагинах Проблемы с плагинами

Использование пространств имен $loader->registerNamespace('My\Validators'); $class = $loader->load('foo'); //My\Validators\Foo -un/registerNamespace() вместо addPrefixPath() -class_exists() Использование имен-через-дефис-в-нижнем-регистре $loader->registerNamespace('My\Validators'); $class = $loader->load('foo-bar'); //My\Validators\FooBar Игнорирование нижнего подчеркивания поиском плагинов Изменения в плагинах Рекомендации: именование плагинов

Предполагается, что хелперы будут всегда использовать __invoke() Изменения в плагинах Рекомендации: использование __invoke() При необходимости __invoke() должен переадресовывать на другой метод interface Validator { public function isValid($value, $context = null); public function __invoke($value, $context = null); } class FooValidator implements Validator { public function isValid($value, $context = null) { //... } public function __invoke($value, $context = null) { return $this->isValid($value, $context); } }

Пример использования: Изменения в плагинах Рекомендации: использование __invoke() $validator = new \My\Foo\Validator(); //новый вызов if ($validator($value)) {} //аналогично старому вызову if ($validator->isValid($value)) {}

Все адаптеры должны реализовывать интерфейс "Configurable". Изменения в плагинах Рекомендации: реализация интерфейса Configurable interface ConfigurableInterface { public function setOptions($options); } class Adapter implements ConfigurableInterface { public function setOptions($options) { //... настраиваем объект... } }

Фабрики будут создавать объект адаптера и передавать ему опции. Изменения в плагинах Рекомендации: реализация интерфейса Configurable class ValidatorFactory { public static function factory($options) { if ($options instance of \Zend\Config) { $options = $options->toArray(); } if (!is_array($options)) { throw new InvalidArgumentException(); } $adapter = new $options['type']; $adapter->setOptions($options['params']); return $adapter; } } Фабрики должны иметь связанный с ними загрузчик плагинов и позволять подключать другие загрузчики.

Цепочки должны расширять один из классов компонента pubsub: –Provider –FilterChain Построение стандартных цепочек везде, где это доступно, например, в декораторах Расширение цепочек и добавление подклассов к объектам, которые их подключают Цепочки должны вести себя как загрузчики плагинов, либо подключать загрузчики плагинов Изменения в плагинах Рекомендации: цепочки (Chains)

Model-View-Controller (MVC, «Модель-представление-поведение», «Модель-представление- контроллер») архитектура программного обеспечения. Шаблон MVC позволяет разделить данные, представление и обработку действий пользователя на три отдельных компонента –Модель (Model) Модель предоставляет данные и реагирует на запросы, изменяя свое состояние. –Представление (View) Отвечает за отображение информации (пользовательский интерфейс). –Поведение (Controller) Интерпретирует данные, введенные пользователем, и информирует модель и представление о необходимости соответствующей реакции. Новая реализация MVC

Zend_Controller 2.0 Zend_Controller_Router 2.0 Zend_View 2.0 Zend_Session 2.0 Zend_Form 2.0 Новая реализация MVC

Цели рефакторинга: После всех изменений компонент должен стать: –небольшим –гибким –свободно расширяемым –легким в создании и использовании кастомных реализаций Zend_Controller 2.0

Две методики : конечный автомат (FSM) событийная модель (Event-driven model) Zend_Controller 2.0

Реализация похожа на dojo pubsub PubSub == Publish/Subscribe, организация взаимодействий по подписке Основные методы: –publish() –subscribe() Zend_Controller 2.0 Event-driven Model: PubSub

Zend_Controller 2.0 Event-driven Model: PubSub class TestPubSub { public function someFunction($message) { echo('someFunction: '. $message); } public function anotherFunction($message) { echo('anotherFunction: '. $message); } } $classObject = new TestPubSub(); $providerObject = new Provider(); $outerFunction = function ($message) { echo('outerFunction: '. $message); };

Zend_Controller 2.0 Event-driven Model: PubSub $someFunctionHandle = $providerObject->subscribe( 'mvc.routing', $classObject, 'someFunction' ); $anotherFunctionHandle = $providerObject->subscribe( 'mvc.routing', $classObject, 'anotherFunction' ); $outerFunctionHandle = $providerObject->subscribe( 'mvc.routing', $outerFunction ); $providerObject->publish('mvc.routing', 'Join the Dark Side!'); $providerObject->publish('mvc.routing', 'We have cookies!'); $providerObject->unsubscribe($someFunctionHandle); echo('--- Производим unsubscribe функции someFunction ---'); $providerObject->publish('mvc.routing', 'Join the Dark Side!'); $providerObject->publish('mvc.routing', 'We have cookies!');

Zend_Controller 2.0 Event-driven Model: PubSub someFunction: Join the Dark Side! anotherFunction: Join the Dark Side! outerFunction: Join the Dark Side! someFunction: We have cookies! another Function: We have cookies! outer Function: We have cookies! --- Производим unsubscribe функции someFunction --- anotherFunction: Join the Dark Side! outerFunction: Join the Dark Side! another Function: We have cookies! outer Function: We have cookies!

Событийная модель: –Определяется 4 состояния: routing, dispatching, response, error –Методам передается событие (Event) –Методы изменяют состояние события –Вызывающий метод проверяет состояние и реагирует на изменение. Zend_Controller 2.0 Event-driven model

Zend_Controller 2.0 Event-driven model routing:... dispatching: $pubsub->publishUntil($stateChanged, 'mvc.dispatching.pre', $e); $pubsub->publishUntil($stateChanged, 'mvc.dispatching', $e); $pubsub->publishUntil($stateChanged, 'mvc.dispatching.post', $e); $e->setState('response'); response:... error: $pubsub->publishUntil($stateChanged, 'mvc.error', $e); Определяется 4 состояния :

Zend_Controller 2.0 Event-driven model //$stateChanged – замыкание, проверяющее состояние события dispatching: $e->markState(); $pubsub->publishUntil($stateChanged, 'mvc.dispatching.pre', $e); if ($e->isStateChanged()) { goto switchState; } $pubsub->publishUntil($stateChanged, 'mvc.dispatching', $e); if ($e->isStateChanged()) { goto switchState; } $pubsub->publishUntil($stateChanged, 'mvc.dispatching.post', $e); if ($e->isStateChanged()) { goto switchState; } $e->setState('response');

Zend_Controller 2.0 Event-driven model switchState: switch ($e->getState()) { case 'routing': goto routing; case 'dispatching': goto dispatching; case 'response': goto response; case 'error': goto error; default: throw new StateException(); }

Объект Request Объект Response Объект Renderer Объект Router Объект Dispatcher Action controllers Объект ErrorHandler Zend_Controller 2.0 Дополнительные компоненты

Плагины фронт контроллера подписываются только на нужные темы Action helper broker может быть встроен в объект Event Объект View станет зависимым от рендерера, который, в свою очередь, подчинен объекту Responce. Остается возможность внедрить собственные реализации Достигается большой выигрыш производительности Zend_Controller 2.0 Последствия

Сейчас по умолчанию не производится никакой фильтрации приходящих данных Планируется добавить фильтрацию/валидацию по умолчанию для суперглобальных массивов К суперглобальным массивам без фильтрации обращаться через методы getRaw*() Zend_Controller 2.0 Poka Yoke фильтрация

Передача ошибки поиска action из __call в noRouteAction() Использование оверлоадинга для доступа к action helpers: __call() будет изменен. Zend_Controller 2.0 Список изменений в Action Controller //вызов через HelperBroker $this->_helper->redirector('index'); //превратится в $this->redirector('index'); //доступ к свойствам $this->_helper->viewRenderer->setNoRender(true); //станет таким $this->viewRenderer->setNoRender(true);

легкость контрактное программирование роутер будет работать с объектами запросов будут исправлены те ошибки, которые сложно исправить без нарушения обратной совместимости Zend_Controller_Router 2.0

Используется реализация "Horde Routes" Метод getInstance() предполагается удалить getDefault() и getDefaults() могут стать методами интерфейса Метод match() будет принимать только объект Zend\Controller\Request\Http Построение маршрутов через конфиг Цепочки Маршрут Hostname Поддержка кэширования Zend_Controller_Router 2.0 Изменения в маршрутах

Поиск совпадений по дереву (tree-matching). В дереве ищется только одно совпадение. Достаточно всего раз отыскать имя хоста вместо поиска его для каждого нового маршрута. Zend_Controller_Router 2.0 Chains

Из объекта HTTP Request будет создаваться уникальный ключ Найденный результат сохранится. Каждый отдельный маршрут будет достаточно найти единожды. Zend_Controller_Router 2.0 Поддержка кэширования

Проблемы текущей реализации: Одновременная реализация как логики Модели (фильтрация, валидация, метаданные), так и логики Вида (рендеринг, декораторы) Использование объектов формы для валидации Неоднозначная реализация системы декораторов Zend_Form 2.0

Изменение form*() view helpers так, чтобы они могли принимать элементы или другие объекты Zend_Form Zend_Form 2.0 Рекомендации: рефакторинг view helpers Zend_Form 2.0 $element->setOptions(array( 'size' => 25, 'maxlength' => 140, 'class' => 'form-text', )); echo $view->formText($element);

Работать с декораторами можно, используя метод PubSub filter(): Zend_Form 2.0 Рекомендации: использование PubSub Будут предложены готовые цепочки: // Учитывая, что Zend\Form\DecoratorChain // наследует Pubsub\FilterChain // и что render() переадресует на filter(): $chain = new Zend\Form\DecoratorChain(); $chain->subscribe('Zend\Form\decorator\Label'); $chain->subscribe('Zend\Form\decorator\ViewHelper'); $chain->subscribe('My\Decorator\Div'); $chain->setView($view); echo $chain->render($element); $chain = new Zend\Form\Decorator\DefinitionListChain; $chain->setView($view); echo $chain->render($element);

Использование PubSub как базы для цепочек фильтров и валидаторов позволит их присоединять и отсоединять. Zend_Form 2.0 Рекомендации: использование PubSub $vChain = new Zend\Validator\ValidatorChain(); $vChain->subscribe('Int'); $vChain->subscribe('MinLength', array(3)); $vChain->subscribe('MaxLength', array(20)); // прекращение валидации на первой ошибке подписчика $vChain->breakOnFailure(true); $element->setValidatorChain($vChain); if ($element->isValid($values)) { … } $fChain = new Zend\Filter\FilterChain(); $fChain->subscribe('StringTrim'); $element->setFilterChain($fChain); $newValues = $elemen->filter($values);

Для полного разделения View и Model нужно доставать цепочки из формы для использования в модели – и наоборот: Zend_Form 2.0 // Извлекаем ранее созданные цепочки фильтров и валидаторов // всех элементов формы $filterChain = $form->getFilterChain(); // Присоединяем к модели: $model->setFilterChain($filterChain); Рекомендации: работа с цепочками фильтров и валидаторов

Объектная структура: Zend_Form 2.0 Zend\FilterChain::__set_state(array( "foo" => Zend\FilterChain\Element::__set_state(array( 'filterChain' => Zend\Filter\FilterChain(array( '_subscribers => array( 'StrimTrim', ), )), 'validatorChain' => Zend\Filter\ValidatorChain(array( '_subscribers => array( array('Int'), array('MinLength', array(3)), array('MaxLength', array(25)), ), )), )), )) Рекомендации: работа с цепочками фильтров и валидаторов

Zend_Form 2.0 Будет использоваться так: $chain->isValid($values); $value = $chain->get($key); $chain->set($key, $value); $chain->setAll($values); $elementChain = $chain->getChain($key); Рекомендации: работа с цепочками фильтров и валидаторов

Все классы форм могут определять свойство "metadata", содержащее пары ключ/значение, и набор методов set/get для метаданных Zend_Form 2.0 Рекомендации: разделение между метаданными и поведением $form->setMetadata(array( 'action' => $url, 'method' => 'post', 'id' => 'registration', )); $element->setMetadata(array( 'class' => 'form-text', 'size' => 25, 'maxlength' => 140, )); $element->setName('foo');

Сейчас все элементы Zend_Form генерируют id. Отмена генерации id решит целый ряд проблем с UI. Перевод можно перенести в слой view. Цепочки View и Decorators будут получать объект Translator. Zend_Form 2.0 Рекомендации: отмена установки id, перевод

Конфигурация: создание цепочек из конфигурации больше не будет доступно. Метаданные: отдельный контейнер "metadata" может повлечь проблемы с уже существующими конфигурациями. Удаление ID: Удаление генерации id может повлечь за собой проблемы с UI. Эта особенность, возможно, будет конфигурируемой. Zend_Form 2.0 Проблемы обратной совместимости

В Zend Framework 1. x компонент Zend_Session является труднотестируемым. Планируется: –сделать Zend_Session более тестируемым –добавить возможность инъекции массива сессии –Zend_Session больше не будет синглтоном Zend_Session 2.0

Планируется: –реализация компонента упростится и станет гибче –добавятся брокеры для управления фильтрами и хэлперами –благодаря изменениям в MVC переменные будут передаваться во view script по токену Zend_View 2.0

Список других элементов: –Zend_Http_Client 2.0 –Zend_Soap 2.0 –Zend_Mail 2.0 Планируется улучшить, переработать или внести улучшения / исправления багов, требующие BC breaks Подробнее: Другие элементы

GIT ACL не накладывает ограничений. Каждый разработчик сможет создать локальную копию репозитория Требования к пропускной способности и объему хранилища ниже Упрощается разделение на ветки Возможность организовать рабочие процессы, отличающиеся от рабочих процессов SVN GIT вместо Subversion

Стандарты кодирования Псевдонимы пространств имен use Zend\Pubsub\Provider as Provider; Псевдонимы (alias) назначаются при использовании "use": Шаблоны: Делая псевдонимом последнюю часть пространства имен, можно просто не использовать нотацию "as Something" use \Zend\Filter; // Псевдонимом будет "Filter" use \Zend\Form\Element; // Псевдонимом будет "Element" Псевдоним для класса: или использовать имя класса или подставлять суффиксом пространство имен класса // Псевдоним "HelperBroker" use \Zend\Controller\Action\HelperBroker; // Добавляя суффикс use \Zend\Filter\Int as IntFilter;

Абстрактные классы –имена абстрактных классов будут предваряться словом "Abstract" : AbstractController, AbstractForm, и т.п. Интерфейсы –должны именоваться описательно и достаточно обобщенно –не должны конфликтовать –должны четко указывать на задачи интерфейса Configurable Adaptable Resource Role Loadable Builder Указания типов –должны использовать доступные псевдонимы везде, где возможно –если имя класса появляется в области видимости всего раз, ему тоже рекомендуется задать псевдоним Стандарты кодирования

Надежда Блинова: Георгий Туревич: Вопросы?