LiveStreet как платформа для модулей

На основе определенного опыта выношу свои предложения по оптимизации LiveStreet под решения сторонних разработчиков.
Вот как сейчас выглядит инструкция по установке модуля галерея: docs.google.com/Edit?id=d4jv5mv_529dgshs5d2

А хочется чтобы инструкция заканчивалась на распаковании архива:) Мои предложения как этого добиться:


1. Инклуд блоков
Предлагаю вынести инклуд блоков для всех страниц в одно место (в конфиг).
Основной объем работ при установке(80%) — вставка вывода блоков.

2. Введение т.н. хуков. Примером использования хуков может быть wordpress.

Сразу хочу отметить, что понятие action в примере отличается от понятия action в livestreet и не связано.
Разработчик пишет свою функцию

  function HelloWorld(){
    print "hello world";
  }

и добавляет ее в виде action'a

  add_action('publish_post', 'HelloWorld');

При вызове функции add_action, в массив экшенов добавляются новые. А в коде в месте, где публикуется пост располагается вызов action'ов

  do_action('publish_post',$oPost);

Где они поочереди выполняются. Соответственно, в функцию HelloWorld попадает объект $oPost

Блоки, кстати, можно так же реализовать. Хотя по-моему лучше ими отдельно управлять.

Файл, где содержится описание функций работы с плагинами wordpress core.trac.wordpress.org/browser/trunk/wp-includes/plugin.php

Список всех хуков wordpress wphooks.flatearth.org/

Приложение. Как я это вижу для LiveStreet.

Возможно, следует выделить плагины(или еще как-нить) от модулей. Плагин может быть без экшена.

Простейший плагин:
EmailFriends.class.php

  class LsEmailFriends extends Plugin {

    // в массиве $aVar содержатся данные, которые вернул Hook
    public function EmailNotificationToFriends($aVar){
       $sTopicTitle = $aVar["topic"]->getTitle();
       mail('friend1@gmail.com,friend2@gmail.com','Новый топик',$sTopicTitle);
    }

    // У класса Plugin есть абстрактный метод AddHooks() такой же как и Init
    public function AddHooks(){
       // "1" это приоритет
       $this->addHook('post_topic','EmailNotificationToFriends',1); 
       //или 
       $this->addHook('post_topic','EmailFriends_EmailNotificationToFriends',1);
    }
  }

33 комментария

avatar
согласен вещь полезная и рано или поздно об неё(вернее без неё) многие спотыкаться будут
насчет хуков — нужно определиться какие типы хуков нужны
avatar
Здесь стоит отталкиваться от вопроса производительности.
WP хорош для личного блога с небольшой посещаемостью, т.к. он требователен к ресурсам системы, но прост в настройке и использовании.
Эта же платформа заточена под другие задачи, ей важна производительность.
avatar
я сам против того чтоб через каждые две строки кода вставлять вызов хуков
нужно определить только самые востребовательные + на производительности будет сказываться только при их(хуков) большом числе. В дефолтной версии лучше их вообще не использовать, а дать такую возможность только для разработчиков дополнительных решений.
avatar
Никто не спорит, что монолитная система намного производительнее кастомной!
С помощью хуков, LiveStreet сможет объединять оба преимущества.
Если нужна высокопроизводительная система (>10 000 уников), простой покупкой чужих модулей не обойдешься. Нужно вручную дописывать функционал или дорабатывать модули. (Базовая версия может быть и не использовать хуки, я имею в виду что массивы их будут пустые).
А если нужна система на 5000, то вызовы через хуки вполне подойдут.

И то, я думаю что производительность упадет не сильно. Нужно проверять.
avatar
А мне что-то подсказывает, что хуки будут не самым ресурсоемким решением. Вполне вероятно, что мы говорим об экономии на семечках. Хотя может тесты действительно покажут, что это не так.

С другой стороны, даже если производительность снизится, то возможно это нивелируется оптимизацией других моментов (запросов например, кэширования).
avatar
Тот же WP неужто бедный не держит > 10000? А как Друпал вообще выживает до сих пор?
avatar
Вот вкратце реализация в друпале
dikini.net/14.06.2006/aspects_and_honey_in_php
Там, кстати, есть пример.

По производительности, надо тесты почитать…
avatar
Главное, из-за чего требователен вордпресс — это плохо спроектированная архитектура.
1) Сначала грузится из базы всё-всё-всё, а потом доходит до шаблона и определения того, где это мы и что нам надо. И тогда из всего-всего-всего загруженного выбираются нужные нам данные и выводятся на морду. Это в лучшем случае. А в худшем эти данные грузятся опять (например, плагины такие, грузят с нуля, а не забирают из памяти).
2) Криво спроектирована работа с базой. Как пример, статья «Можно ли написать серьёзное web-приложение без знания принципов работы MySQL? Можно. Доказано разработчиками WordPress.» Здесь.

Так что хуки на каждый чих — это ещё не самое большое зло.
avatar
А что если с другого конца завернуть? Дать возможность попросту расширять классы, использовать всю мощь, которую дает ООП? Поясню на примере:

Есть класс, скажем, UserEntity_User, идущий в стандартной поставке. Сейчас экземпляры прямо от него и созаются. Я предлагаю так:
1. Есть некий класс (стандартное объявление):
class Std_UserEntity_User0 extends Entity {
  public function getId() {
    return $this->_aData['user_id'];
  }        
  public function getLogin() {
    return $this->_aData['user_login'];
  }
  // ...
  // объявление других методов и свойств
  // ...
}

2. Делаем его расширение (кастомное объявление):
class Ext_UserEntity_User extends Std_UserEntity_User {
  // в стандартной поставке оно "пустое", т.е. просто наследование от родителя и все
}

3. Все экземпляры создаем от этого — расширенного объявления класса

Файлы с описаниями кастомного (расширенного) класса кладем в отдельную папку. Если я хочу чего-то дописать, я не трогаю стандартных описаний (как это сейчас нередко делается), а дополняю описание кастомного класса, например так:

class Ext_UserEntity_User extends Std_UserEntity_User {
  public function getLogin() {
    return '['.parent::getLogin().']';
  }
}


Что это дает? Не нужно ничего дополнительно прописывать в конфигах или где-то еще. Не надо принудительно цеплять какие-то обработчики и проч. Переход к новой версии ЛС может проходить с минимальной головной болью (в лучшем случае просто заливается на хост весь код новой версии, кроме папки с кастомными классами).
avatar
Поддерживаю. С точки зрения расширяемости и собственного «допиливания» будет удобно. И на производительности сильно не скажется.
avatar
это можно использовать дополнительно, но как замена хуков не катит
avatar
Сходу не вижу, в каких случаях на поможет исключительно хук. Если брать пример топикстартера, то мы в классе Ext_LsTopic (который, как говорилось выше, является расширением стандартного LsTopic) объявляем свой метод:
public function AddTopic(TopicEntity_Topic $oTopic) {
  parent::AddTopic(TopicEntity_Topic $oTopic);
  mail('friend1@gmail.com,friend2@gmail.com','Новый топик',$oTopic->getTitle());
  return $oTopic;
}

На мой взгляд, гораздо проще и понятней. Но я допускаю, что в каких-то случаях (я просто не придумал еще, в каких) спасут только хуки. Но в любом случае, если ставить приоритеты, то кастомное расширение классов я бы поставил выше, чем хуки. Тут ведь и придумывать ничего не надо, работа чисто механическая (хоть и не маленькая) — добавить к каждому классу расширение и переписать рождение экземпляров объектов.
avatar
я почему то подумал, что имелось ввиду расширение исключительно сущностей
тут есть минус по сравнению с хуками — на одно событие можно повешать несколько хуков от разных разработчиков, тогда как при одном кастомном будут конфликты
avatar
Да, вот о том, как «помирить» несколько разработчиков, создающих разные расширения, я не подумал :(
avatar
:) vopros bazovyh klassov uje podnimalsya eshe do novogo goda (s tipami topikov). Eto 2 raznyh mehanizma I, bezuslovno, oba nujny.
Prioritet ya by stavil na hooki
avatar
приоритеты приоритетами, просто реализация кастомных классов для сущностей и модулей по сути простая, достаточно немного Engine.class.php поправить
avatar
Ты думаешь это принесет какую-либо пользу?))
avatar
Я имею поправление Engine. Тут, мне кажется, требуется более комплексный подход
avatar
Конфликты действительно будут, но все равно решать их в кастомном классе будет значительно проще, чем в основных.

Может даже и хуки при этом не понадобятся.
avatar
«значительно проще» это как интересно?
У меня есть 2 модуля. Один задает роли пользователям, а другой вводит градацию по рейтингу (новичек, эксперт). Они оба должны наследоваться от одного базового класса User.
Оба класса имеют свои закрытые интерфейсы и как ты думаешь они будут взаимодействовать?
И какой класс будет вызываться по-дефолту??
avatar
Проще — это значит, что класс у них будет один, и конфликт будет решаться (опять же ручками разумеется) с учетом того, как оба модуля должны работать одновременно. Просто не нужно будет копаться в одном здоровом классе.

Понятно дело, что с хуками все может быть гораздо удобнее.
avatar
Это принцип объектного наследования классов. Вот после этого никто не сможет сказать, что PHP это «детский» язык etc.
avatar
Вот вынести вставку блоков в отдельное место это действительно не помешало бы, а вот Wordpress в качестве примера для подражания (в смысле кода) как-то не очень. IMHO
avatar
a ty dumaesh, kak proishodit integraciya plaginov v joomle, osCommerce itp? problema wordpressa ne v etom.
avatar
Я не против Wordpress-а, а как в большинстве CMS происходит интеграция с этим тоже знаком. С точки зрения пользователя, его все эти изыски программирования слабо волнуют — ему нужено что бы плагин легко поставить, а иногда и убрать (желательно так же легко и чисто).
avatar
Я извиняюсь, что так дроблю комменты, просто походу думаю, а думаю я туго. Так вот с точки зрения человека который пишет модуль — ему нужен максимально простой, лаконичный и понятный код (вот и всё).
avatar
Адназначна! +1
комментарий был удален
avatar
Я тут подпишусь под каждым словом benone, поскольку уже сейчас тот же 0.2 (0.3 пока не пробовал) на siege показывает слабый результат (Максим, без обид).

48 pageload против 312 на phpinfo, поэтому если делать все еще более динамично и с хуками, то, как мне кажется, будет совсем плохо.
avatar
Продолжу мысль. Я бы наоборот сейчас бы ратовал за то, чтобы можно было бы делать некоторые части движка монолитными, получая прирост.
avatar
я не обижаюсь, тем более мало что понял в этих словах/цифрах :)
avatar
Максим, специально для LiveStreet.ru, эксклюзив:
livestreet.ru/blog/wishlist/1476.html

:)
avatar
Предлагаю простое решение, можно потестить:
livestreet.ru/blog/1478.html
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.