Successfully reported this slideshow.
Your SlideShare is downloading. ×

Enterprise Patterns in Magento

Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad

Check these out next

1 of 22 Ad

More Related Content

Slideshows for you (19)

Advertisement

Similar to Enterprise Patterns in Magento (20)

Recently uploaded (20)

Advertisement

Enterprise Patterns in Magento

  1. 1. Тулика Евгений Magento Developer Professional Services Team evgeniy.tulika@magento.com Шаблоны корпоративных приложений в Magento
  2. 2. Шаблоны. Почему о них говорят? Craig Шаблоны не содержат B Larman новых идей C Шаблоны имеют имена Шаблоны облегчают D общение
  3. 3. • Transaction Script • Identity Map • Domain Model • Lazy Load • Data Mapper Domain Logic • Table Data Gateway Object-Relational • Active Record Behavior Data Source Architecture
  4. 4. Представление бизнес-логики Простой путь: декомпозиция по действиям AccountActions + Login + Register + Logout + ShowAccount CheckoutActions + addToCart + showCheckout + submitCheckout
  5. 5. Transaction Script Каждая операция реализована своим методом public function addToCart() { //retrieve user data from session //retrieve product from database //add product information to quote //… //… //save quote data to database }
  6. 6. Domain Model Объектами представлены реальные сущности Business Logic Layer Category Product Order Quote Payment Cart Customer_Address Customer
  7. 7. Расслоение. А как в Magento? Sales Service Layer |--Block |--controllers Domain Models |--etc |--Helper Data Mappers |--Model | |--Mysql4 Data Access Objects | |-- Billing | |-- Entity | |-- Payment | |-- Order.php | |-- Quote.php
  8. 8. Mapping Objects to Data Source
  9. 9. Data Mapper /*Осуществляет передачу данных между объектами и базой данных, сохраняя их независимыми друг от друга и от самого маппера*/
  10. 10. Zend Way <?php class App_Model_UserDataMapper { public function save(App_Model_User $user) { Matthew $dao = $this->getDao(); Weier $id = $user->getId(); O’Phinney if (!$id) { $id = $dao->insert($user->toArray()); } else { $dao->update($user->toArray(), array(‘id=?’, $id)); } $record = $dao->find($id)->current(); $user->setOptions($record->toArray()); return $user; }
  11. 11. Вернемся к Magento Ресурс-модели Sales |--Block |--controllers <global> <models> |--etc <sales> |--Helper <class>Mage_Sales_Model</class> <resourceModel>sales_mysql4</resourceModel> |--Model </sales> | |--Mysql4 <sales_mysql4> <class>Mage_Sales_Model_Mysql4</class> | | |--Order.php <sales_mysql4> | | |--Quote.php <sales> <models> | |-- Billing <!-- ... --> | |-- Entity </global> | |-- Payment | |-- Order.php | |-- Quote.php Mage::getResourceModel('sales/order'); ->load($order, $id, $field);
  12. 12. public function load(Mage_Core_Model_Abstract $object, $value, $field=null) { if (is_null($field)) { $field = $this->getIdFieldName(); Mage_Core_Model_Mysql4_Abstract } $read = $this->_getReadAdapter(); if ($read && !is_null($value)) { $select = $this->_getLoadSelect($field, $value, $object); $data = $read->fetchRow($select); if ($data) { $object->setData($data); } } $this->_afterLoad($object); return $this; }
  13. 13. Структура ресурс-модели Mage_Core_Model_Resource_Abstract #_getWriteAdapter() #_getWriteAdapter() #_getReadAdapter() #_getReadAdapter() + beginTrasnsaction() + beginTrasnsaction() Mage_Core_Model_Mysql4_Abstract Mage_Core_Model_Mysql4_Abstract + getMainTable() + getMainTable() + load() + save() + save() + delete() + delete() #_prepareDataForTable() #_prepareDataForTable()
  14. 14. Отличия от классики Доменные модели знают о своих ресурс- моделях Mage_Sales_Model_Order public function getProductIds() { $ids = $this->getData('product_ids'); if (is_null($ids)) { $ids = $this->_getResource()->getProductIds($this); $this->setProductIds($ids); } return $ids; }
  15. 15. Lazy and Eager Loading • Все данные есть под рукой • Может загрузить • Может потребоваться излишне много данных слишком много обращений к базе • Все данные есть под рукой
  16. 16. Lazy Loading in Magento public function getAddressesCollection() Mage_Sales_Model_Order { if (is_null($this->_addresses)) { $this->_addresses = Mage::getResourceModel('sales/order_address_collection') ->setOrderFilter($this); if ($this->getId()) { foreach ($this->_addresses as $address) { $address->setOrder($this); } } } return $this->_addresses; }
  17. 17. Альтернативы. Table Data Gateway Name City Telephone Age Insurance Eugene Kyiv +3804456 21 32453453 Igor New York +45066 Model_DbTable 23452345 _Person +find() +findWithName() Model_Person +update() +insert() +getName() +delete() +getAddress() +sendEmail() +addFriend() +getFRiendSuggestions()
  18. 18. Альтернативы. Active Record Name City Telephone Age Insurance Eugene Kyiv +3804456 21 32453453 Igor New York +45066 Model_Person 23452345 +getName() +getAddress() +sendEmail() +addFriend() +getFriendSuggestions() +find() +findWithName() +update() +insert() +delete()
  19. 19. Коллекции. Identity Map getElement(green) Identity Map find() empty load() Identity Map return( )
  20. 20. Magento Collections Ресурс-коллекции Sales |--Model | |--Mysql4 | | |-- Collection | | | | -- Abstract.php Mage::getResourceModel('sales/order_collection') | | | -- Report ->addFieldToSelect(‘*‘) | | | | -- Collection.php ->setOrder(‘created_at‘, ‘desc'); | | |--Order.php | | |--Quote.php | |-- Billing | |-- Entity $children = $this->getResourceCollection() | |-- Payment ->setOrderFilter($orderFilter) | |-- Order.php ->addPaymentIdFilter($paymentId) | |-- Quote.php ->addParentIdFilter($this->getId());
  21. 21. Структура коллекции Varien_Data_Collection Countable +getItemsByColumnValue() +addItem() IteratorAggregate +walk() Mage_Core_Model_Mysql4 Varien_Data_Collection_Db _Collection_Abstract +isLoaded() +addFiedToSelect() +load() +setModel() #_loadCache() +setResourceModel() #_saveCache() +save()
  22. 22. evgeniy.tulika@magento.com

Editor's Notes

  • Воркшоп. Кто знаком с Фаулером — узнает про Magento Хочу рассказать про Magento Почему начал с шаблонов? Проще начать с установки и примеров?
  • Паттерны вносят в рассказ о архитектуре структуру Позволяют увидеть картину в целом Крег Ларман сформулировал П аттерн — сконцентрированный опыт Имена чтоб быстрее общаться Легче общаться потому что общая терминология Когда видно общее легче найти отличия Мой доклад — ввод в терминологию Magento
  • Паттернов около 50 Выбрал связь с базой данных Начну с логики предметной области Затем Архитектура источника данных Затем объектно-реляционное поведение
  • Рассказ о связи решил начать с того откуда берутся объекты Есть набор требований и делаем ОО декомпозицию C амый простой способ — разбить по действиям системы он самый очевидный
  • Сценарий транзакции — процедура Данные принимает от представления Данные обрабатывает, сохраняет, проверяет, активизирует другие системы Каждое действие реализовано сценарием Возвращает данные слою представления Несколько сценариев в класс паттерн Command — Один сценарий представлен классом Достоинство — простота. Легко воспринимается Основная проблема — дублирование фрагментов кода Второй путь — для сложной логики Приложение растет — сценарии просятся на рефакторинг В результате рефакторинга приходим к Domain Model
  • Сеть взаимосвязанных объектов — каждый представляет сущность Одни имитируют данные области, другие — формализируют правила. Например статус ордера Реализация — пополнение приложения слоем объектов Функции тесно сочитаются с данными на которых они оперируют Простая модель во многом походит на схему базы данных Сложная — значительно отличается и содержит иерархии наследования, сеть сложных взаимосвязанных объектов.
  • При использовании domain model бизнес-логика концентрируется в одном скоупе классов Мадженто модульная каждый модуль имеет слой доменных объектов модели разных модулей могут связываться мужду собой Service Layer – верхушка всякого приложения, непосредственное его API Далее подробнее расскажу о слое связи с данными
  • О бъекты доменной логики имеют свое состояние Рано или поздно данные нужно загрузить или выгрузить из оперативной памяти Средства обеспечивающие Persistence Не всем посчастливилось работать с объектно-ориентированными базами данных Неоднозначное соответствие между структурой объекта и структурой базы данных Проблема отображения объекта в плоскую табличную структуру Кому назначить ответственность за привязку данных объекта к данным таблиц СУБД Не можем сделать этого в доменной модели Один вариант — вынести привязку в отдельные классы
  • = Дата Маппер — объект вызываемый клиентом = Берет данные из базы и помещает в объект = Если объект знает о структуре базы то изменение в одном приводит к необходимости в изменении в другом = Дата Маппер — слой отделяющий объекты от базы данных = Теперь объекты могут не подозревать о существовании базы данных = Преобразователь полностью скрыт от уровня домена
  • = Пример = При необходимости весь слой дата мапперов может быть заменен = Преобразователи должны справляться как с простыми задачами поле-ячейка, так и со сложными наследованием, взаимодействием разных объектов = Маппер может на один запрос к базе данных заполнить несколько объектов данными = Обычно — один маппер для каждой доменной модели = При использовании Metadata Mapping — может быть один класс = Маппер должен иметь доступ к полям объекта
  • - У Magento - ресурс-модели - К аждый модуль имеет свой набор ресурс моделей - По хорошему у каждой модели есть своя ресурс модель - Регистрируется в конфигах - Чтоб вызвать нужно воспользоваться статическим методом класса Mage
  • - Каждый ресурс екстендится от абстрактной модели - Как видим метод лоад принимает на вход объект, который он будет заполнять данными - Select формируется ранее - Read Adapter - это адаптер базы данных, в нашем случае играет роль Data Access Object - a - ничего не мешает написать полностью свой класс ресурс-объекта без абстракта
  • - C труктура стандартной MySQL ресурс-модели - O бычно ресурс-модели екстендятся от абстрактной - П арент - еще более абстрактные операции по манипулированию транзакциями и доступа к адаптеру
  • - Основное отличие от классического шаблона дата маппер - то что доменная модель знает о своей ресурс модели - У абстрактной доменной модели есть метод getResource - Чтоб объяснить зачем это сделано сперва рассмотрим следующий паттерн
  • - При использовании доменной модели нет однозначного соответсвия между таблицей и объектом - Не все поля могут быть заполнены одним запросом - Объект имеет множество ссылок насвязанные объекты - При работе с объектом ожидаем что он уже заполнен данными и связанные объекты тоже - Есть разные пути как загружать дополнительные данные. - Самый очевидный - все данные пытаться загрузить при загрузке объекта - Энергичная загрузка - модели проявляют инициативу - Недостатки - данных может быть загружено слишком много - Другой вариант - при загрузке текущего объекта совсем не доставать связанные - Необходимые данные загружаются в момент первого доступа к ним - Ленивая - пока не пнешь не полетит
  • - Ресурс модель как правило не загружает никаких данных кроме тех какие запросили в select-e при инициализации - Е сли требуется загрузить связанные данные - вызываются методы ресурс-модели - В ресурс-модель по-прежнему передается экземпляр объекта
  • = Table_Data_Gateway шаблон для немного более простых ситуаций нежели Дата Маппер. = Альтернатива - потому что это взаимоисключающие шаблоны. = В Magento не используется = Он как и Дата Маппер внешние классы по отношению к доменной модели. = Основная разница в том, что он ничего не знает про модель его использующую = Модель сама обращается к шлюзу и просит достать данные из таблицы = Шлюз как правило не имеет состояний поскольку лишь передает данные из таблицы в модель = Как правило один шлюз работает с одной таблицей или с главной таблицей и несколькими связанными. Для каждой таблицы создается свой шлюз = Включает методы поиска, обновления и вставки данных и просто вызывает соответсвующие комманды SQL Реализует такую себе виртуальную таблицу = Zend_Db_Table
  • = Оболочка для строки таблицы. = Добавляет к данным логику домена = Объект охватывает и данные и их поведение = В основе лежит шаблон Domain Model , = Классы которого повторяют структуру записей используемой Базы данных. = Структура данных должна точно соответствовать той что в таблице = Тесная зависимость от структуры базы данных что усложняет изменение этой структуры = Joomla
  • = Гарантирует что каждый объект будет загружен из базы данных только один раз = Хранит данные обо всех объектах загруженных из БД в пределах транзакции = Как только возникает необходимость в данных следует сперва обратится к коллекции чтоб убедится что их там еще нет = В случае простой схемы для каждой таблицы своя коллекция = Количество коллекций рекомендуется привязать к объектам а не к таблицам - тогда объекты не знают деталей отображения на базу = Несложно и удобно привязать коллекции к Data Mapper = Коллекция может использоваться в качестве кэша записей считываемых из базы данных
  • - В Magento коллекции рядом с ресурс моделями - С точки зрения АПИ они ничем не отличаются - Лежат в директории рядом с ресурс-моделями, но называются коллекциями - Коллекция предоставляет интерфейс для контролем загрузки, а так же манипулирования уже загруженными данными.
  • И нтерфейсы Countsble и Iterator Самая абстрактная модель - предоставляет базовую функциональность Достать элемент, добавить, пройтись по всем элементам DB-коллекция - позволяет проверить загружена ли она, провести загрузку Так же коллекции предоставляют средства кеширования - данные сериализуются и записываются в файловый кеш Коллекция от которой наследуются остальные коллекции Интерфейсы для добавления модели и ресурс-модели, сохранение, манипулирование объектом select

×