Powered by CodeIgniter

Разработка

(21)
17
17 голосов
Разработка новой версии cogear. Прямой эфир с места событий.
Доброго воскресенья, друзья! К работе над второй версий активно подключаются участники команды, что определенно радует. skvorets уже рисует новый интерфейс админки, JiLiZART стоит на страже багов в GIT-репозитории, inetlover продумывает интерфейсы и готовится к верстке, Varhal и Osiris вот-вот запустят сайт с темами для первой версии. Самое время продолжить вводный курс в архитектуру второй части. Хочешь принять посильное участие в общем деле? Пиши в личку!
Что является наиболее важной задачей для разработчика системы? Преемственность разработки, чтобы другие люди легко включались в оригинальный код и могли быстро реализовать собственные разработки на базе исходной. Да, конечно, это лишь часть успеха, но без преемственности нет жизни. Говорят, мы живем в наших детях. Могу перефразировать в аспекте движка — система живет в сообществе.
Итак, моя задача до релиза второй версии привести нас с вами к общему знаменателю, чтобы все понимали, что происходит внутри, и осознавали архитектуру движка самостоятельно, а не только с моих отзывов в духе «Это просто супер!» :-)

Немного об абстракции

Вы знаете, что все хорошо тогда, когда все по фен-шую. Поэтому в своих творческо-программистких изысканиях я пришел к концепции МИСО. Абстрагируемся и упрощаем, упрощаем и абстрагируемся. В конечном счете, отбросив все фантазии, я пришел к выводу, что лучшей техникой джедайского кунфу является использование заложенных в PHP5 возможностей по-максимуму вместо того, чтобы изобретать свои велосипеды и костыли.
Именно поэтому я решил все свести к полноценному ООП. Шестеренка — это класс. Нет, вы не поняли. Да, это «класс!», но это и класс по сути. Тот класс, который стоит в тени объекта.
Напомню последние изменения в файловой системе. Есть три места, где хранятся шестеренки:
  • /engine ← шестеренки ядра (энтузиастам вход запрещен)
  • /gears ← шестеренки для всех сайтов
  • /sites/домен.сайта/gears ← шестеренки конкретного сайта
Все классы, как и следует, подгружаются через autoload. Что это означает? Привет, танкистам! А означает это то, что больше не надо использовать функции include и require, которые поедают много системных ресурсов. Вы просто создаете объект из класса, а файлы подгружаются автоматически. Конечно, исходя из системной логики, которая имеет название «слоеного пирога», классы должны быть названы и расположены в файловой системе особым образом.
Для простоты поясню на примере.
$object = new User_Gear(); Что происходит при создании объекта класса User_Gear? Имя класса попадает в автолоадер, где оно преобразуется в путь. Нижнее подчеркивание _ заменяется на разделитель директории (в Windows — \, в Unix-based системах — /) и суффиксом приставляется расширение .php, после чего загрузки последовательно обходит указанные выше директории в обратном порядке и загружает первый попавшийся файл.
  • /sites/домен.сайта/gears/User/Gear.php ← упс, не существует
  • /gears/User/Gear.php ← и здесь пусто
  • /engine/User/Gear.php ← нашел! Загружаю.
Таким образом вы получаете возможность перезагрузить любой класс ядра дважды — для всех сайтов или для каждого конкретного сайта! Специально, чтобы было проще обновляться. Никаких сторонних изменений в ядре.
Да, есть люди, которые сетуют за систему оберток, как в Kohana. Она удобна, но создает море лишних файлов, и пока что не требуется в нашем варианте. Поясню, она позволяет не просто переопределять, но и наследоваться в «слоеном пироге». Обратитесь более детально к документации Kohana. Помните, что разработка — это процесс, а не результат, поэтому при необходимости мы всегда сможем расширить структуру. Вообще все во второй версии делается только по необходимости. Никаких «а вдруг пригодится…». Таким образом мы минимизируем издержки и увеличиваем производительность.

Шестеренка

Перейдем к самому важному — шестеренке. Это базовая сущность второго cogear. Шестеренками представлено все — модули, плагины и даже темы.
Шестеренка — это класс, который обладает всеми данными ему PHP5 атрибутами. В том числе и возможностью наследования.
В чем удобство? В том, что вы можете создавать свои продукты, основываясь лишь на различии от других. К примеру, базовый код шестеренки /engine/Core/Gear.php содержит информацию:
<?php /** * Gear * * @author Dmitriy Belyaev <admin@cogear.ru> * @copyright Copyright © 2010, Dmitriy Belyaev * @license http://cogear.ru/license.html * @link http://cogear.ru * @package Core * @subpackage * @version $Id$ */ abstract class Gear { /** * Gear name * @var string */ protected $name; /** * Gear description * @var string */ protected $description; /** * Gear version * * By default it equals Cogear version * * @var string */ protected $version = COGEAR; /** * Core version * * By default it equals Cogear version * * @var string */ protected $core = COGEAR; /** * Gear type * * 0 — Core * 1 — Module * 2 — Plugin * 3 — Theme * * @var int */ protected $type = Gear::CORE; /** * Package * * @var string */ protected $package = 'Core'; /** * Gear authors name * * @var string */ protected $author = 'Dmitriy Belyaev'; /** * Gear email * * Contact email to resolve everything * @var string */ protected $email = 'admin@cogear.ru'; /** * Gear website * * @var string */ protected $site = 'http://cogear.ru'; /** * Order in gear stack * * Value can be positive or negative to load after or before other gears. * * @var int */ protected $order = 0; … Поэтому при создании шестеренок ядра, я переопределяю только название и описание, все остальные данные (версия, разработчик и так далее) остаются теми же. И не надо в каждой новой шестеренке указывать, что ее версия совпадает, например, с версий движка (а для компонентов ядра это всегда так), или что я — ее автор. Также и вы можете создать свою базовую шестеренку, и все другие свои продукты от нее наследовать. Убирая повторы даже в информации, мы экономим время. Ведь чтобы поправить информацию во всех своих шестеренках, вы можете изменить таковую только в первоначальной, от которой все наследуются.
<?php /** * User gear * * @author Dmitriy Belyaev <admin@cogear.ru> * @copyright Copyright © 2011, Dmitriy Belyaev * @license http://cogear.ru/license.html * @link http://cogear.ru * @package Core * @subpackage * @version $Id$ */ class User_Gear extends Gear { protected $name = 'User'; protected $description = 'Manage users.'; protected $order = -10;…

Наследование

В классе шестеренки есть метод init, который вызывается движком в порядке загрузки шестеренок (параметр order). По-умолчанию, он загружает скрипты и стили, создает базовый роут и вызывает хук. В отнаследованных шестеренках вы можете переопределить метод, сохраняя вызов родительского через parent::init(), к примеру.
Класс темы /engine/Core/Theme.php наследуется от шестеренки. Как я уже упоминал, тема — тоже шестеренка, только более продвинутая. В методе init абстрактного класса темы вызывается родительский метод у всех отнаследованных тем, чтобы подгрузить их скрипты и стили. Это очень удобно, потому что вы можете создавать свои темы, указывая только лишь изменения от предыдуших. При этом вы вольны переопределить метод init абстрактного класса темы и выстроить такую загрузку, которая вам потребуется. Полная свобода для творчества и самореализации!
/engine/Core/Theme.php:
… /** * Init */ public function init(){ $Reflection = new ReflectionClass($this); $parent = $Reflection->getParentClass(); if($parent->name != 'Gear' && $parent->name != 'Theme'){ $theme = new $parent->name; $theme->init(); $cogear = getInstance(); $cogear->gears->{$parent->name} = $theme; } parent::init(); $cogear = getInstance(); $cogear->theme = $this; Template::bindGlobal('theme',$this); $cogear->hook('done',__CLASS__.'->render'); $this->template = new Template($this->gear.'.'.$this->layout); } …
Напоследок код темы Default и отнаследованной от нее темы 960 на базе замечательного CSS-фреймворка 960.gs.
/engine/Theme/Default/Gear.php:
<?php /** * Default Theme gear * * * * @author Dmitriy Belyaev <admin@cogear.ru> * @copyright Copyright © 2010, Dmitriy Belyaev * @license http://cogear.ru/license.html * @link http://cogear.ru * @package Theme * @subpackage Default * @version $Id$ */ class Theme_Default_Gear extends Theme{ protected $name = 'Default Theme'; protected $description = 'Default engine theme.'; } /engine/Theme/960/Gear.php:
<?php /** * 960 Theme gear * * * * @author Dmitriy Belyaev <admin@cogear.ru> * @copyright Copyright © 2010, Dmitriy Belyaev * @license http://cogear.ru/license.html * @link http://cogear.ru * @package Theme * @subpackage Default * @version $Id$ */ class Theme_960_Gear extends Theme_Default_Gear{ protected $name = '960.gs Theme'; protected $description = 'Theme based on 960 grid system.'; protected $version = '1.0'; }
Приветствую любые вопросы, пожелания и предложения!
12:25 ← 13 марта 2011 Отправить в Твиттер adminadmin  RSS comments 16

Комментарии (16) ↓

Isildien Isildien time 12:35 ← 13 марта 2011 #
Отличная статья, спасибо!
Автор
admin admin time 12:38 ← 13 марта 2011 #
Пожалуйста. Пытаюсь «нащупать» формат, чтобы было не утомительно и, в то же время, интересно.
inetlover inetlover time 21:57 ← 13 марта 2011 #
Полезный пост!
Varhal Varhal time 04:16 ← 14 марта 2011 #
Да же мне, далекому от программирования дошло))) Спасибо, Дима!
А запуск сайта с шаблонами намечен на этой неделе, сейчас несколько премиум тем доверстываем и ГОУ!
Автор
admin admin time 08:14 ← 14 марта 2011 #
Пожалуйста!
Ramir Ramir time 12:14 ← 14 марта 2011 #
тут пропущено слово или неправильно просклонено
после чего загрузки последовательно обходит указанные выше директории

Предлагаю кешировать пути, чтобы не обходить каждый раз «указанные выше директории». Оптимизировано на мелочь, но все равно приятно
JiLiZART JiLiZART time 16:46 ← 14 марта 2011 #
Ага и при добавлении новой шестерёнки, мы её просто не увидим в системе.
Хотя в mzz есть такая фишка, там создаётся фаил со списком всех просканированных файлов и обращение к файловой системе происходит через него.
Isildien Isildien time 19:05 ← 14 марта 2011 #
Я лично за.
Isildien Isildien time 19:05 ← 14 марта 2011 #
кеширование :)
Ramir Ramir time 17:19 ← 14 марта 2011 #
ну во-первых есть очистить кеш. и перед активацией шестерни его можно удалять и даже автоматически.
а во-вторых, как часто ты ставишь новые шестеренки и как часто будет проводиться «проход» по файлам?
Автор
admin admin time 23:25 ← 14 марта 2011 #
Предлагаю убрать мыли о динамическом кеше, как было раньше.
Система может пребывать в двух состояниях — разработки и продакшена. В режиме разработки кеш выключен всегда (кроме системного, который перманентный и хранит данные). И все.
По поводу ресурсоемкости операции file_exists — она очень дешевая. Не стоит пока париться на этот счет, данное место всегда можно оптимизировать, а сейчас итак показатели по производительности более чем отличные.
Ramir Ramir time 18:46 ← 16 марта 2011 #
Система может пребывать в двух состояниях — разработки и продакшена. В режиме разработки кеш выключен всегда (кроме системного, который перманентный и хранит данные).
Следовательно, в режиме продакшына кеш включен всегда ))
Автор
admin admin time 19:08 ← 16 марта 2011 #
Да. Откуда узнал? :-)
Ramir Ramir time 19:10 ← 16 марта 2011 #
дык это… есть опыт медитативных практик ;-)
krilya krilya time 13:52 ← 11 июня 2011 #
Добрый день,
Версия 2 из git-репозитория достаточно стабильна для использования на реальном проекте?
Если я правильно понял, то во второй ветке отказались от CodeIgniter?
Автор
admin admin time 15:59 ← 11 июня 2011 #
День добрый. Когда будет готова бета, мы напишем об этом на сайте обязательно.