Add new comment

IPS Community Suite, часть 2 - погружение в код

В предыдущей статье я писал об первом знакомстве с движком IPS, сейчас напишу об его коде, который очень сильно отличается от кода ОpenСart и показался мне очень интересным для изучения.
 

Документация 

Тут все очень печально, потому что версия 4 вышла всего пару месяцев тому назад и документации по ней для программистов почти вообще нету. Я нашел около 10 статей и все. Может просто плохо искать и есть какие-то блоги или форумы, но я не нашел.
НО ситуация очень сильно спасает то, что каждый класс и методы очень хорошо документированы, напр. 

/**
   * GET /forums/topics/{id}
   * Get posts in a topic
   *
   * @param   int   $id     ID Number
   * @apiparam  int   hidden    If 1, only posts which are hidden are returned, if 0 only not hidden
   * @apiparam  string  sortDir   Sort direction. Can be 'asc' or 'desc' - defaults to 'asc'
   * @throws    1F294/1 INVALID_ID  The topic ID does not exist
   * @return    \IPS\Api\PaginatedResponse<IPS\forums\Topic\Post>
   */
  public function GETitem( $id )
  {

 
И сразу понятно что это за метод, какие параметры он получает на входе, какие из них обязательны, какие исключения вызывает, что возвращает. 
 

Стиль кодирования

Еще даже до знакомства с OpenCart  мне его стиль кодирования казался самым правильным. Напр. конструкция:

if ($condition) {
 // do something
} else {
  // do something else
}

А теперь сравним со стилем IPS:

if ( $condition )
{
 // do something
}
else
{
  // do something else
}

1. В скобках стоят лишние пробелы ( $condition ), это увеличивает читабельность кода, код с пробелами легче читается, чем когда все на кучу
2. Фигурные скобки стоят со следующей строки, это:
  • оставляет меньше шансов ошибиться и пропустить открывающую фигурную скобку, особенно когда условие длинное и она где-то в самом конце строки
  • все фигурные скобки находятся в одной линии, что делает код более однообразным и, как следствие, легче читабельным
  • между условием и кодом в скобках за счет скобки всегда есть строка (в которой находится скобка) Это тоже делает код боее однообразным, так как в стиле OpenCart эту пустую строку для больших условий можно установить, чтобы как-то отделить код для лучшей читабельности, а для небольших не нужно. Такой код также легче читать, так как везде есть строка, которая отделяет условие от самого кода. Так и более красиво и практично. 

Поэтому мне стиль кодирования IPS показался более практичным и удобным. 
 

Инициализация системы

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

require 'init.php';

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

require 'init.php';
 
// загрузить пользователя с id 1 
$member = \IPS\Member::load( 1 );
 
// вывести его имя
echo $member->name;

 
Это конечно же очень удобно, что не нужно писать десятки строк кода, подключать десятки классов, библиотек конфигов итд.
 

Пространство имен, Namespaces

 
Движок очень широко его использует, сам движок имеет пространство IPS, каждый компонент имеет свои пространства, элементы этого компонента свои итд.
Поэтому часто в коде приходится видеть что-то типа этого:
 

namespace IPS\core\modules\front\system;
 
/**
 * Sidebar Widgets
 */
class _widgets extends \IPS\Dispatcher\Controller

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

Singleton, cинглтон, одиночка

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

foreach ( json_decode( \IPS\Db::i()->select( 'widgets', 'core_widget_areas', array( 'app=? AND module=? AND controller=? AND area=?', \IPS\Request::i()->pageApp, \IPS\Request::i()->pageModule, \IPS\Request::i()->pageController, \IPS\Request::i()->pageArea ) )->first(), TRUE ) as $k => $block
 ) {

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

Active Record, актив рекорд

Еще один паттерн проектирования, который используется очень широко в движке. 
Если кто не знает, то это паттерн для работы с базой данных. Если у вас есть 100 таблиц в базе данных то вам не нужно для каждой писать отдельно методы для получения, создания, редактирования и удаления записей для этой таблицы (как происходит в OpenCartВместо этого есть 1 класс, который все это делает. 
Для того, чтобы подключить новую таблицу создается новый класс, который наследует интерфейс ActiveRecord и в котором указываются настройки новой таблицы (название таблицы, идентификаторы итд.) и все. После этого можно с помощью этого нового класса работать с новой базой используя методы для работы с базой интерфейса. 
Если ли же какой-то метод основного класса не устраивает то его всегда можно переопределить. 
Такой штуки очень не хватает OpenCart
 

Логи

Очень понравился лог в IPS. Лог там имеет разные типы ошибок:

   * @li LOG_ALERT  action must be taken immediately
   * @li LOG_CRIT   critical conditions
   * @li LOG_ERR    error conditions
   * @li LOG_WARNING  warning conditions
   * @li LOG_NOTICE normal, but significant, condition
   * @li LOG_INFO   informational message
   * @li LOG_DEBUG  debug-level message

Существует так же 3 медода для обработки ошибок:

   * Acceptable methods are "disk", "email" and "syslog".

И существует возможность каждый конкретный тип ошибки обрабатывать своим методом.
Напр., критические ошибки можно слать сразу на емейл, не очень критические - писать в лог на диск, еще какие-то в syslog
 
Дисковый лог также можно смотреть в админке.
Еще одна очень простая и приятная мелочь - для последней ошибки создается отдельный файл. Так как в основном приходится искать именно последнюю ошибку, которую приходится искать в большом лог файле, постоянно листая его в самый конец.  Вместо этого она также есть в отдельном файле, удобно. 
 

Формы

Еще одна очень классная штука, которой очень сильно не хватает OpenCart это конструктор форм. Вот как формы создаются в IPS:
$form->add( new \IPS\Helpers\Form\Text( 'theme_template_export_author_name', $this->author_name, false ) );
$form->add( new \IPS\Helpers\Form\Text( 'theme_template_export_author_url' , $this->author_url, false ) );
$form->add( new \IPS\Helpers\Form\Text( 'theme_update_check' , $this->update_check, false ) );

После этого с болью вспоминаю сколько времени уходит на создание форм для OpenCart из чистого HTML и сколько времени всем разработчикам приходится тратить чтобы перевести все модули на OpenCart 2.0 потому что создатели движка решили перейти на новый модный bootstrap.. А ведь если бы использовался конструктор форм то для переноса модулей на 2.0 вообще бы не нужно было переписывать код форм! 
 

Возможности расширения

Тут все очень классно, намного лучше, чем в OpenCart
 
1. Есть API. Об API OpenCart я писал недавно, но тут оно намного лучше:
  • есть документация по каждому методу, которая отображается в админке. Создается она автоматически из описания методов. Она достаточно полная - видно что делает этот метод, какие параметры получает, какие из них обязательные, что возвращает, какой объект с какими свойствами итд.
  • для каждого ключа можно указать IP с какого к нему можно обращаться или дать возможность подключаться с любого IP
  • для каждого ключа можно указать только конкретные методы, к которым этот ключ может обращаться
  • все запросы можно писать в лог, который показывает всю информацию об этом запросе, даже выходные данные
 
2. Хуки. Хуками в IPS называют возможность переназначить любой класс. Чем можно значительно расширить функционал не изменяя при этом код самого движка. Не стоить путать с хуками в напр. Drupal, там под хуками имеются ввиду События (Events)
 
3. События. Это возможность выполнять какой-то свой код после каких-то событий в системе. 
Для этого нужно в нужную папку закинуть свой файл, класс с нужными методами, которые будут вызываться автоматически, когда в системе произойдет это событие. По аналогии с Событиями в OpenCart или хуками в Drupal
 
4. Модульная система. Неимоверно крутой штукой является то, что модули для движка можно создавать в админке! Для этого необходимо установить расширение для разработчиков, после этого в плагинах появляется кнопка "Создать" и можно прямо из админки создавать новый плагин, виджет, добавлять настройки, переопределять классы движка итд. После чего его можно скачать одним xml и поделиться с кем-то. 
В плагинах также реализована система версий, обновление с версии на версию, а  также возможность установить плагин из админки и скачать новую версию плагина из админки. 
 
То есть системы расширения намного превосходит OpenCart.
 

Заключение.
 

Этот материал не претендует на полноту, так как автор всего пару дней как познакомился с этим движком.  
Система, которая на первый взгляд показалась очень сложной и пугающей из-за огромного к-ва неймспейсов и паттернов, через всего несколько дней стала очень удобной, понятной и логичной и это не смотря на то, что она обладает огромный функционалом. С ней приятно работать, писать новые плагины и расширять ее функционал. 
Статья больше написана для того, чтобы показать отличия в коде между OpenCart и IPS. И, как можно увидеть из этой статьи, отличия  просто огромные. В такие моменты понимаешь сколько еще нужно расти опенкарту..
 
CAPTCHA
Spam protection
Target Image