"Модульность" проектов
Нужно это больше для моих нужд, так как сейчас снова засел за WEB-проекты.. Чтобы легче было разрабатывать фрагменты кода как для меня, так и для сторонних доработчиков.
Сейчас я это представляю как разделение модулей на специфичные категории. Т.е. часть работает как бы сама по себе на сайте (типа голосования, счетчики); часть берет инфу с сайта (например, создание меню); другие встраиваются в статьи; третьи вообще нигде не отображаются, кроме как в админке, но в коде должны исполняться (типа сбор инфы о юзере, etc.).
Далее завести функцию, например, register_module($module_name,$category). Ну и в коде будет участок, который будет выполнять все эти зарегистрированные модули в необходимом месте.
Для каждого типа модулей написать свой interface (т.е. все модули будут идти как классы, часть основных функций для работы будет уже реализована мной, т.е. остается только расширить необходимый класс), тем самым упростив жизнь как себе, так и сторонним людям.
Понимаю, что в моём вопросе уже есть ответ. Но перед тем как начать писать, хотелось бы послушать мнения других более опытных людей, чтобы потом не пришлось повторять чужих ошибок.
Метод реализации модулей и плагинов напрямую зависит от того как реализовано основное ядро и какой функционал вообще закладывается в эти самые модули.
В нашей системе управления например взаимодействие модулей с ядром осуществляется через несколько общих буферов + API. Подключение же модуля - это уже каждый сам решает. Мы, например, написали инсталлятор и менеджер модулей - копируешь модуль в нужную директорию, но чтобы он заработал нужно его проинсталлировать. К тому же многие модули требуют свои собственные таблицы в БД, например.
Поэтому реализация подобных вещей как правило индивидуальна. Но стоит все же постараться предусмотреть возможные проблемы и заложить как можно большую гибкость. Хотя все равно всего не предусмотришь.
поясните пожалуста о чем идет речь..
модули вставляются в php?..
hardcase, спасибо за ссылку. На днях почитаю. Заодно английский вспомню))
Гладкий, как бы объяснить на примере.. Вот допустим используете вы QIP, а к нему есть плагин, который транслирует название исполняемой песни в Winamp/AIMP в статус QIP. Чтобы установить плагин требовалось всего лишь закопировать его в нужную папку plugins и, затем, активировать его в настройках программы. Вот тут примерно все так же)
Я вот тоже не совсем понимал о чем речь :). А теперь появилась мысль. Не пинайте пожалуйста ежели велосипед придумываю.
1. Для простоты изясненеия розделяем систему на ядро и модули (хотя такое розделение будет условным так как ядро не что иное как главный модуль, к которому дописываются все остальлные). В свою очередь к каждому модулю можно дописывать дополнительные модули и т.д.
2. Ядро имеет набор интерфейсов и обращения ко всем сущностям поведение которых может менятся с добавлением новых модулей должно идти только через интерфейсы.
3. В ядре есть чтото типа реестра реализацыи для интерфейсов.
Ну тоесть есть у нас 2 интерфейса I1, I2. Есть реестр в виде массива
$reestr = array("I1"=>"Impl1", ""=>"Impl2");
4. Создание сущностей должно выглядеть примерно так
$o1 = new $reestr["I1"];
Может я тут накосячил, но есть в РНР такая возможность создать екземпляр класса по его названию.
В модуле понятно что будет дополнительный функционал, но, как уже говорилось выше, - главная проблема как его интегрировать. А для етого придется менять поведение сущностей ядра.
5. Для сущности, поведение которой придется поменять, в модуле пишем свой класс. Наследовать его от класса из ядра вижу нелогичным така как получим проблему при подключении двух модулей меняющих одну сущность. Просто имплементим соответственный интерфейс. Наш новый класс SuperImpl1 явлется чемто типа прокси. Он агрегирует в себе екземпляр класса Impl1 и в большинстве случаев будет просто повторять его повидение вызывая его методы, а там где нужно будет делать и чтото свое.
6. При подключении модуль должен запоминать старое состояние реэстра (нужно для агрегирования в новых классах екземпляров старых) и подменять название классов имплементацыи.
Реестр можно сделать в виде двухмерного масива. первое измерение = название интерфейса, второе измерение - уровень наслоения разными модулями. В каждой ячейке хранится пара строчек: Название класса имплементации и название модуля в котором оно реализовано. Таким образом модуль всегда сможет найти название прежней реализации етажом выше (по второму измерению). Модули также могут добавлять свои интерфейсы реализацыя для которых может быть изменена подмодулями и т.д.
Ну вот собственно и вся идея. Интересно выслушать Вашы мнения.
Корявый пример со счетчиком на логировании. Есть сущность отвечающая за логирование. LogI, LogImpl соответственно интерфейс и реализацыя.
Изначально реализацыя не умеет щитать сколько раз и когда юзер логинился.
На странице логина написано чтото типа
$loginer->login($name, $password);
В модуле будет примерно так;
$oldLoginerName = $reestr['LogI']; // тоесть LogImpl
$reestr['LogI'] = 'ExtLogger';
class ExtLogger implements LogI {
private $oldLoginer
public ExtLogger() {
$oldLoginer = new $oldLoginerName();
}
public login($name, $pass) {
$oldLogger->login($name, $pass)
/// а тут пишем в БД когда он логинился
}
}
Для создания проксей нужно использовать нечто умнее чем переопределения всех методов (в данном случае login)
Согласен. Можно и ефективнее в плане быстродействия. Но сделать также гибко не так уж и просто ;)
По крайней мере, я считаю ее мощной, поработав в проекте где использовались широко собственные business-level плагины для эклипса.
так же или почти так же как в любом другом языке.
просто ведь можно написать много разных скриптов (каждый со своим интерфейсом, но ессесно в условия одного сайта интерфейс обычно одинаков): счетчик там кокойнибудь, поле для голосования, контейнер для вывода главного меню и написать сканер так сказать этих скриптов, который сканирует их (находящихся в одной папке) и выводит в определенном месте страницы....