Comments 76
Некоторые моменты напоминают мою cms, но все равно в целом архитектура несколько другая. Согласен с тем, что про генерацию страниц и поддержку модульности надо писать отдельно, это на мой взгляд одна из самых интересных частей в подобных системах.
+1
Самое интересное, что Вовка действительно описывает свою CMS, которую делает от начала до конца сам.
Концепция очень интересная, а то, что действующий (пусть ещё с очень большими недоработками) прототип системы уже существует, оставляет надежду на то, что проект будет будет доведён до стадии продукта.
Концепция очень интересная, а то, что действующий (пусть ещё с очень большими недоработками) прототип системы уже существует, оставляет надежду на то, что проект будет будет доведён до стадии продукта.
0
Эх, многие из нас когда-то рисовали такие схемы и писали системы…
Это классный опыт ;-) Искренне желаю удачи!
Это классный опыт ;-) Искренне желаю удачи!
0
С интересом прочитал. Наверно, каждый второй программист пробует сделать свою cms или фреймворк. Я тоже отношусь к этим «кадым вторым».
И по теме, а какой модуль у Вас определяет какой именно алгоритм(модуль) логики запускать? Request? Или модули отвечающие за логику вешаются на событие?
И каким образом определяется порядок вызовов обработчиков событий (порою это может иметь критическую важность)?
И по теме, а какой модуль у Вас определяет какой именно алгоритм(модуль) логики запускать? Request? Или модули отвечающие за логику вешаются на событие?
И каким образом определяется порядок вызовов обработчиков событий (порою это может иметь критическую важность)?
0
Прочитал не отрываясь. Очень интересно. Огромное спасибо. А будет ли продолжение?
0
Продолжение будет и много))
Логика определяется набором модулей. Да, модули вешаются на события, и есть нерешенный вопрос об определении порядка вызова обработчиков одного события, например модуль страниц должен работать после того как модуль данных сохранит входящие данные… Но лучше не мудрить с событиями и просто повесить модуль страниц не на модуль запросов, а на модуль данных… т.е. когда модуль данных обработает входящие данные.
Логика определяется набором модулей. Да, модули вешаются на события, и есть нерешенный вопрос об определении порядка вызова обработчиков одного события, например модуль страниц должен работать после того как модуль данных сохранит входящие данные… Но лучше не мудрить с событиями и просто повесить модуль страниц не на модуль запросов, а на модуль данных… т.е. когда модуль данных обработает входящие данные.
0
Спасибо статьи про архитектуру всегда интересны! Вот только было бы здорово, если бы называли вещи по стандартной терминологии. Думаю, многим бы стало всё понятнее, если бы сказали, что запросы система обрабатывает по паттерну Front Controller, модули взаимодействуют по паттерну Observer, при доступе к базе данных используется Data Mapper в виде репозитария объектов. И несколько непонятно, как реализуется непосредственно логика работы приложения. Например, банальное добавление комментария. Хотелось бы простой пример именно на уровне кода или подробные диаграммы классов и последовательностей для типичной веб задачи. Больше картинок меньше слов :-)
0
Пишите дальше :)
0
Кстати, система с событиями называется Signal/Slots, в фреймворке ezComponets реализовано, не так давно писал про это как раз. очень мощная и гибкая штука
0
Вопрос, а как система узнает, какой нужно дать отклик (реакцию) на действие пользователя? Посредством урл? Если так, то хотелось бы увидеть, как выглядят эти урл (надеюсь они не тупо хранятся в БД)
0
Модуль, который формирует вывод, в частности модуль Page смотрит параметры юрла и генерерит страницу, ссылки создаются под его контролям (точнее он определяет параметры для ссылки), поэтому он знает как на них реагировать. Впрочем вопросов ещё дофига)
0
А можно примеры урлов? И где они хранятся?
0
Говорить об юрлах подробно пока сложно — много спорных решений, поймите, что проектирование ещё продолжается. Сейчас тестируется такой вариант:
Первый параметр приводит к выводу блока новости
Блок новости фильтрует содержимое по второму параметру
Для вывода данных по страницам использует специальный элемент-блок, для него аргумент — это номер страницы
Пока это странно и возможно плохо понятно и не обасновано…
Вот ещё:
Здесь третий параметр — это идентификатор объекта данных, в частности новости, а аргумент определяет действие над новостью, в частности отобразить форму для редактирования.
Юрлы пока нигде не храняться. Вы затронули тему, которая ещё изучается) Я собственно статью и написал, чтоб колективно решать вопросы архитектуры cms.
чистые ссылки преобразуется как у друпала:
url = http://boolive.ru/news/sports&2 $params = array('news', 'sports'); // переменная - это так образно $args = array(2);
Первый параметр приводит к выводу блока новости
Блок новости фильтрует содержимое по второму параметру
Для вывода данных по страницам использует специальный элемент-блок, для него аргумент — это номер страницы
Пока это странно и возможно плохо понятно и не обасновано…
Вот ещё:
http://boolive.ru/news/sports/15&edit
Здесь третий параметр — это идентификатор объекта данных, в частности новости, а аргумент определяет действие над новостью, в частности отобразить форму для редактирования.
Юрлы пока нигде не храняться. Вы затронули тему, которая ещё изучается) Я собственно статью и написал, чтоб колективно решать вопросы архитектуры cms.
чистые ссылки преобразуется как у друпала:
http://boolive.ru/news/sports/15&edit => http://boolive.ru/?q=news/sports/15&edit
+1
Интересно, спасибо! Кстати, а ваш проект по этой схеме опенсорс? Если да, то выкладывать будете что-нибудь?
0
Будем, нада доделать некоторые базовые модули, чтоб архитектуру в действии показать. А так, если интерисующихся много окажется, то открою svn
0
А можно узнать чем рисовались схемы?
0
Только не смейтесь) во флеше
0
Прикрутите иерархию ;)
Тогда можно ограничится одним контроллером, который будет все модули «разгребать».
Тогда можно ограничится одним контроллером, который будет все модули «разгребать».
0
Вы имеете в виду модули выстроить в иерархическую зависимость-связь?
0
Начать надо с иерархии объектов.
Потом, «научить» этому контроллер (от этого он станет более гибким и универсальным). Кстати в вашей архитектуре, я заметил, контроллер стоит как-то в «стороне».
При таком раскладе, модули можно не выстраивать в иерархической зависимости. Они контроллером уже будут вызываться иерархически. И «таскать» данные по модулям. В конце иерархии, данные будут содержать все что вам нужно, останется только их вывести, посредством модуля view (шаблонизаторов и т.п.).
Может я не совсем понял объяснение на пальцах, но на мой взгляд у вас есть проблемы с контроллером и иерархией вызовов
Потом, «научить» этому контроллер (от этого он станет более гибким и универсальным). Кстати в вашей архитектуре, я заметил, контроллер стоит как-то в «стороне».
При таком раскладе, модули можно не выстраивать в иерархической зависимости. Они контроллером уже будут вызываться иерархически. И «таскать» данные по модулям. В конце иерархии, данные будут содержать все что вам нужно, останется только их вывести, посредством модуля view (шаблонизаторов и т.п.).
Может я не совсем понял объяснение на пальцах, но на мой взгляд у вас есть проблемы с контроллером и иерархией вызовов
0
Если под объектами вы имеете в виду данные, которые я тоже называю объектами, дополняя их словом данные, то иерархия совсем не уместна, вы это поймете, когда я расскажу в новой статье про модуль данных. Модуль данный – это как банк данных, некоторые модули участвуют (контролируют) в манипулировании данными (создание/изменение/удаление/чтение), другие модули пользуются этими данными, например модуль страниц Page. Получается, что тоталитарного контролера нету, есть например контроллер-модуль страниц, который управляет отображением данных в html формате. Самое интересное, что есть данные так таковыми данными и являющиеся (статьи, фотки, категории…), а есть данные-представления – блоки, вьюшки… Чувствую без новой статьи сложно понять))
Если речь об иерархии, как о последовательности работы модулей и применения паттерна «цепочка обязанности», то этот вариант ещё возможен. Но реально он ничего не меняет. Посмотрите на рисунок событий – вроде иерархия. Но если отобразить все события, то будет не иерархия, а сеть. Не получиться выстроить последовательность работы модулей в иерархию.
Вот пример:
Как по рисунку событий в статье, выполняются события… модуль Request вызвал событие AFTER, первым его обрабатывает модуль данных Data, модуль Page ожидает своей очереди (он тоже зарегистрирован на AFTER), но вдруг в модуле Data возникает сбой, допустим, не может подключиться к БД – ошибка! Ошибка перехватывается модулем Errors. и модуль ошибок генерирует свое событие. На рисунке это событие не связано с модулем Page, но на самом деле модуль Page обрабатывает это событие – ему незачем ждать, когда придет его очередь от модуля Request!!! Несмотря на ошибку, модуль страниц корректно срабатывает и выводит красивую информации об отсутствии доступа к сайту.
Если речь об иерархии, как о последовательности работы модулей и применения паттерна «цепочка обязанности», то этот вариант ещё возможен. Но реально он ничего не меняет. Посмотрите на рисунок событий – вроде иерархия. Но если отобразить все события, то будет не иерархия, а сеть. Не получиться выстроить последовательность работы модулей в иерархию.
Вот пример:
Как по рисунку событий в статье, выполняются события… модуль Request вызвал событие AFTER, первым его обрабатывает модуль данных Data, модуль Page ожидает своей очереди (он тоже зарегистрирован на AFTER), но вдруг в модуле Data возникает сбой, допустим, не может подключиться к БД – ошибка! Ошибка перехватывается модулем Errors. и модуль ошибок генерирует свое событие. На рисунке это событие не связано с модулем Page, но на самом деле модуль Page обрабатывает это событие – ему незачем ждать, когда придет его очередь от модуля Request!!! Несмотря на ошибку, модуль страниц корректно срабатывает и выводит красивую информации об отсутствии доступа к сайту.
0
Таскать данные по модулям? зачем? Зачем передавать модулю то, что ему, скорее всего, не надо? модуль сам берет только то, что ему надо. Передаётся только управление. И как уже показал, возникают исключения, которые нарушают строгую иерархию передачи управления – возникает что-то типа сети.
Есть одна проблема, я её где-то озвучивал — если у события несколько обработчиков, то от последовательности вызова обработчиков будет зависеть правильность функционирования системы. Вот что нужно как-то решить. Есть вариант в таком случаи вешать на события того модуля, после которого нужно работать. Но и здесь но! А если такой зависимый модуль устанавливается в систему как дополнение??? О нем же никто не знает, не знают, что нужно только после него работать?… думать нужно)
Есть одна проблема, я её где-то озвучивал — если у события несколько обработчиков, то от последовательности вызова обработчиков будет зависеть правильность функционирования системы. Вот что нужно как-то решить. Есть вариант в таком случаи вешать на события того модуля, после которого нужно работать. Но и здесь но! А если такой зависимый модуль устанавливается в систему как дополнение??? О нем же никто не знает, не знают, что нужно только после него работать?… думать нужно)
0
И еще, я не увидел в вашей архитектуре CMS модуля кеширования. На сегодня это самый главный модуль.
Далее, вы продумали расширения БД? Сегментирование и т.п… Если нет, думайте пока не поздно. Потому, что если не подумали, то ваша система будет работать только на не нагруженных проектах, а для этого существуют joomla и drupal ;)
> вызова обработчиков будет зависеть правильность функционирования системы
Вот, вот вы и сами понимаете, что контроллер ваш не совершенен, т.е. где-то не продумана архитектура. Совет, делайте настраиваемый (обучаемый) единый универсальный контроллер, который и будет работать и обрабатывать данные которые «таскаются» по модулям. Конечно, есть небольшая избыточность данных, но тогда сокращается код и выплывает гибкость системы, а это важнее. (кстати я свою архитектуру делал 2 года, переделывал уймы раз, первый вариант архитектуры был как у вас ;), но для расширения, гибкости и нагруженности пришлось все пересматривать ;) )
Далее, вы продумали расширения БД? Сегментирование и т.п… Если нет, думайте пока не поздно. Потому, что если не подумали, то ваша система будет работать только на не нагруженных проектах, а для этого существуют joomla и drupal ;)
> вызова обработчиков будет зависеть правильность функционирования системы
Вот, вот вы и сами понимаете, что контроллер ваш не совершенен, т.е. где-то не продумана архитектура. Совет, делайте настраиваемый (обучаемый) единый универсальный контроллер, который и будет работать и обрабатывать данные которые «таскаются» по модулям. Конечно, есть небольшая избыточность данных, но тогда сокращается код и выплывает гибкость системы, а это важнее. (кстати я свою архитектуру делал 2 года, переделывал уймы раз, первый вариант архитектуры был как у вас ;), но для расширения, гибкости и нагруженности пришлось все пересматривать ;) )
+1
Но подобная проблема остается и с контроллером. Да контроллер будет определять, кому работать, но кто будет определять само условие выбора совершаемого контроллером? Если устанавливается новый модуль в систему, то контроллер должен учитывать этот появившийся модуль. А от куда контроллеру знать, когда этому модулю следует работать? Ручки администратора?? Но тогда администратор может редактировать и порядок вызова обработчиков событий. Наверно. Хочется, чтоб все-таки модули сами устанавливались, настраивались и работали как надо.
Что-то мне видится необходимость верных действий именно от человека для конфигурирования устанавливаемых модулей. Это как присоединение дополнительного жесткого диска в ПК требует правильной установки перемычки (Master/slave…) в самом устройстве.
Что-то мне видится необходимость верных действий именно от человека для конфигурирования устанавливаемых модулей. Это как присоединение дополнительного жесткого диска в ПК требует правильной установки перемычки (Master/slave…) в самом устройстве.
+1
>но кто будет определять само условие выбора совершаемого контроллером
Вот, вот подошли к самому интересному. :)))
Сама иерархия объектов — вот кто! ;)
Как? Могу объяснить более подробно, но в личной части habra.
Я свой проект уже закончил (на 90%). Дописываю админ часть.
Вначале я тоже шел вашим путем. Но смысла нет. Повторяются ошибки архитектур прошлых поколений cms.
Вот, вот подошли к самому интересному. :)))
Сама иерархия объектов — вот кто! ;)
Как? Могу объяснить более подробно, но в личной части habra.
Я свой проект уже закончил (на 90%). Дописываю админ часть.
Вначале я тоже шел вашим путем. Но смысла нет. Повторяются ошибки архитектур прошлых поколений cms.
0
так, мне кажется говорим мы об одном, а думаем о разном)) У узла иерархии могут быть несколько «детей» и порядок передачи данных/контроллера «ребенку» тоже будет иметь определяющее значение.
0
Правила, шаблоны правил.
Могу с уверенностью сказать, что вы это видите каждые день ;)
Даже, когда читаете почту в «почтовике» :)
Посмотрите вокруг. Файловые системы, почтовые клиенты, браузеры — все вокруг работает по этому принципу :)
Могу с уверенностью сказать, что вы это видите каждые день ;)
Даже, когда читаете почту в «почтовике» :)
Посмотрите вокруг. Файловые системы, почтовые клиенты, браузеры — все вокруг работает по этому принципу :)
0
Так вот эти правила не могут быть статичными — они зависят от назначения модуля — «ребенка» иерархии — это не иерархия из однотипных элементов как файловая система. Это скорее сложный механизм типа радиоузлов телевизора
+1
Не запутывайте. Все гениальное — просто.
Упрощаем и получаем гибкость ;)
Вы немного все запутали.
Упрощаем и получаем гибкость ;)
Вы немного все запутали.
0
Вы делатете ошибку старых cms. Вы делаете отдельные модули: images, files и т.п.
Это ошибка. Обьект должен иметь тип. Для примера файловая система.
Есть понятие, допустим file, который имеет тип (расширение), например jpg. Контроллер (система) сама определяет что с этим типом делать и какие модули (программы) вызывать :) Все очень легко.
Тоже и в web — есть одно понятие у обьекта- content, который имеет тип.
Так же можно ссылаться на один и тот же обьект разными ссылками на тип.
Т.е. обьект может быть как page так и иметь ссылку на тип menu_left например.
:)
Продолжать?
Это ошибка. Обьект должен иметь тип. Для примера файловая система.
Есть понятие, допустим file, который имеет тип (расширение), например jpg. Контроллер (система) сама определяет что с этим типом делать и какие модули (программы) вызывать :) Все очень легко.
Тоже и в web — есть одно понятие у обьекта- content, который имеет тип.
Так же можно ссылаться на один и тот же обьект разными ссылками на тип.
Т.е. обьект может быть как page так и иметь ссылку на тип menu_left например.
:)
Продолжать?
0
да
0
Тогда contents — это файловая система. Контроллер — ос.
Модули — программы. View — обмен данными с контроллером и программой.
В такой конфигурации — главный кто? Правильно контроллер.
Файловая система — иерархия обьектов.
Правила — это поиск и вывод нужного набора файлов в зависимости от маски запроса (*.jpg — выводит весь контент для модуля галереи)
Пока я буду показывать параллели на пальцах, точнее файловой системой.
Модули — программы. View — обмен данными с контроллером и программой.
В такой конфигурации — главный кто? Правильно контроллер.
Файловая система — иерархия обьектов.
Правила — это поиск и вывод нужного набора файлов в зависимости от маски запроса (*.jpg — выводит весь контент для модуля галереи)
Пока я буду показывать параллели на пальцах, точнее файловой системой.
0
Постойте, но у меня модули не управляют типами. Модули image, file — они только добавлют немного логики для модуля данных. а таких модулей как новости, категории и всякие прочие типы, так таковых не существуют.
0
Вы предположили, что модули системы определяют типы данных, т.е. для вас кроме модуля фотографий и файлов, я так понял, существуют образно модули сообщений, статьей, комментариев, каталогов и т.д., т.е. модули которые бы определяли и позволяли бы работать с разными типами данных. В принципе то, что мы можем наблюдать в большинстве CMS. Тогда такие вот модули конечно целесообразно было бы выстраивать в иерархическую зависимость, как нечто подобное наследованию классов.
Обращаю внимание, что предложенная здесь архитектура совершенно иная. Если не заметно – модуль данных на рисунке самый большой и находится в центре, демонстрируя свою значимость. Именно этим модулем управляются данные – это как объектно-ориентрованная база данных. Все зависимости и отношения между данными, а также типы данных контролируются этим модулем. Другие модули, как и сам пользователь, могут создавать свои типы данных, но для этого используется модуль данных, т.е. типы данных создаются в этой самой как бы объектно-ориентрованной базе данных (модулем Data). Работа с данными четко выстроена, что не имеет проблем из-за внешних факторов, от таких как последовательность обработки событий.
Один универсальный настраиваемый контроллер в системе есть – это совокупность модулей! Настройка контроллера сводится к установке/удалению модулей и регистрацией моделей на события. Вот как раз этот настраиваемый контроллер можно сравнить с электронной начинкой телевизора, модуль – это плата, для неё вроде есть разъем, воткнуть (установить) её просто, но есть ещё пара проводочков (обработчики событий) которые нужно так подсоединить в существующие разъемы, чтобы не нарушить общую логику работы телевизора (cms).
Вот и получается, что нужно либо сводить на нет зависимость от последовательности обработки событий, либо просто писать инструкции по установки модулей))) типа измените порядок обработки событий так чтобы…
Обращаю внимание, что предложенная здесь архитектура совершенно иная. Если не заметно – модуль данных на рисунке самый большой и находится в центре, демонстрируя свою значимость. Именно этим модулем управляются данные – это как объектно-ориентрованная база данных. Все зависимости и отношения между данными, а также типы данных контролируются этим модулем. Другие модули, как и сам пользователь, могут создавать свои типы данных, но для этого используется модуль данных, т.е. типы данных создаются в этой самой как бы объектно-ориентрованной базе данных (модулем Data). Работа с данными четко выстроена, что не имеет проблем из-за внешних факторов, от таких как последовательность обработки событий.
Один универсальный настраиваемый контроллер в системе есть – это совокупность модулей! Настройка контроллера сводится к установке/удалению модулей и регистрацией моделей на события. Вот как раз этот настраиваемый контроллер можно сравнить с электронной начинкой телевизора, модуль – это плата, для неё вроде есть разъем, воткнуть (установить) её просто, но есть ещё пара проводочков (обработчики событий) которые нужно так подсоединить в существующие разъемы, чтобы не нарушить общую логику работы телевизора (cms).
Вот и получается, что нужно либо сводить на нет зависимость от последовательности обработки событий, либо просто писать инструкции по установки модулей))) типа измените порядок обработки событий так чтобы…
0
>я так понял, существуют образно модули сообщений, статьей, комментариев, каталогов и т.д.
Хм. Ну, как сказать. Да, такое деление обязательно, но оно вторично. Задаётся просто дизайном и бэкендом данных.
Одни объекты получают данные с БД, другие с файловой системы и т.п.
Класс объекта может быть вообще пустой (просто нужно уникальное имя для, например, организации связок с другими объектами), если это страница фиксированного формата, в которой вся логика — лишь логика вывода и размещается которая в шаблоне. Может быть указан только механизм источника данных и, опционально, расписана структура источника. Скажем, если этот объект отображение MySQL-записи, то нужно будет указать hash-массив соответствия полей объекта и полей mysql-записи. Может быть указан особый механизм рендеринга, если это не страница, а, скажем, XML/RSS или картинка.
И т.д. по нарастающей.
>Если не заметно – модуль данных на рисунке самый большой и находится в центре
В моём случае модуль данных — это равноценный среди других модуль. Да, чисто формально, мой storage_engine_mysql_smart — один из самых толстых модулей в системе, т.к. содержит в себе гибкую ORM, которая не только скрыто от программиста загружает объекты, но также умеет возвращать массивы объектов по условию, счётчики и т.п. Но вместо него спокойно может использоваться любой другой модуль-источник данных. На практике это реализованные oci (сейчас только R/O, писать в Oracle надобности ещё не было, понадобится — это будет пара десятков строк), xml/fs, *.txt/fs и т.д.
>Один универсальный настраиваемый контроллер в системе есть – это совокупность модулей!
Я, к сожалению, не очень понимаю, что Вы тут имеете в виду под контроллером. Явно не «C» в «MVC» :) Потому что если Вы имеете его в MVC-шном смысле, то «контроллер — совокупность модулей», понятие характерно для любой модульной системы.
> Вот как раз этот настраиваемый контроллер можно сравнить с электронной начинкой телевизора, модуль – это плата, для неё вроде есть разъем, воткнуть (установить) её просто, но есть ещё пара проводочков (обработчики событий) которые нужно так подсоединить в существующие разъемы, чтобы не нарушить общую логику работы телевизора (cms).
В моём случае именно так. Каждый объект системы — связка объектов движков. Именно плат, воткнутых в сокеты. Только у меня нет проводочков-событий, всё прекрасно работает и без них :)
Ну, очень грубо, схема такая.
Механизм загрузки объекта по имени и идентификатору:
— Если такого класса ещё нет в памяти, то по имени определяем файл с классом объекта (я ранее писал про разделение ядра и расширений его, как хостовых, так и сайтовых + система укорачивания имён классов)
— Создаём объект класса
— Инициализируем его, если надо, загружая данные из БД.
— Если всё успешно — возвращаем объект. Иначе — NULL
— Опционально — кешируем объект в memcached и при следующих запросах (в т.ч. в других потоках) грузим кешированный результат.
Выглядит для программиста это так:
или
или даже так:
Механизм загрузки объекта по странице сайта:
Есть (также, раскиданные по уровням ядра и расширений) файлы, со статической привязкой регекспов URL'ов к классам:
/forum/viewtopic.bas?id=(\d+)&p=(\d+) => forum_topic(1,2)
1 и 2 — это группы в регекспе, в данном случае указывают ID объекта и номер показываемой страницы в нём.
При нахождении соответствия загружается объект и вызывается его метод content(). Который, если не переопределён, сделат всё, описанно мной в этой теме чуть ранее. Сгенерирует содержимое тела страницы с помощью указанных механизмов шаблонизации (а данные уже загружены при загрузке объекта), поместит это содержимое в общий шаблон страницы сайта, если надо, закеширует объект, если надо — привяжет его к группам кешей, чтобы изменение объектов, от которых он зависит потом приводили к сбросу статических кешей и т.п.
В конце явных поисков есть несколько записей вида:
.* => page_fs_xml,
.* => page_fs_hts,
и т.д.
Это классы, которые грузят объекты, описанные в файловой системе, параллельной структуре сайта. Иногда удобно сайт править удалённо по FTP, тупо работая с *.txt :)
…
Когда страница будет отдана браузеру унифицированный модуль выхода проверяет, не изменялся ли объект и, если нужно, сохраняет изменения в бэкенде данных, попутно очищая/обновляя все зависимые кеши.
Т.е. в явном виде сохранять изменения не нужно.
Ну и плюс к этому механизмы администрирования, генераторы форм, проверка доступа и даже конфигураторы. Например, если ряд объектов имеет схожие настройки, например, один шаблон, один набор двжков и т.п. можно указать только конфиг-класс этих классов. И т.д. Всё это тоже задаётся либо указанием соответствующих движков, либо параметрами класса.
Сами по себе разнородные объекты системы друг от друга структурно ничем не отличаются. Наследование, например, как таковое не нужно, применяется очень редко, когда реально нужно иметь несколько разных объектов с рядом схожих механизмов, или требуется расширить имеющийся объект, не трогая его.
Хм. Ну, как сказать. Да, такое деление обязательно, но оно вторично. Задаётся просто дизайном и бэкендом данных.
Одни объекты получают данные с БД, другие с файловой системы и т.п.
Класс объекта может быть вообще пустой (просто нужно уникальное имя для, например, организации связок с другими объектами), если это страница фиксированного формата, в которой вся логика — лишь логика вывода и размещается которая в шаблоне. Может быть указан только механизм источника данных и, опционально, расписана структура источника. Скажем, если этот объект отображение MySQL-записи, то нужно будет указать hash-массив соответствия полей объекта и полей mysql-записи. Может быть указан особый механизм рендеринга, если это не страница, а, скажем, XML/RSS или картинка.
И т.д. по нарастающей.
>Если не заметно – модуль данных на рисунке самый большой и находится в центре
В моём случае модуль данных — это равноценный среди других модуль. Да, чисто формально, мой storage_engine_mysql_smart — один из самых толстых модулей в системе, т.к. содержит в себе гибкую ORM, которая не только скрыто от программиста загружает объекты, но также умеет возвращать массивы объектов по условию, счётчики и т.п. Но вместо него спокойно может использоваться любой другой модуль-источник данных. На практике это реализованные oci (сейчас только R/O, писать в Oracle надобности ещё не было, понадобится — это будет пара десятков строк), xml/fs, *.txt/fs и т.д.
>Один универсальный настраиваемый контроллер в системе есть – это совокупность модулей!
Я, к сожалению, не очень понимаю, что Вы тут имеете в виду под контроллером. Явно не «C» в «MVC» :) Потому что если Вы имеете его в MVC-шном смысле, то «контроллер — совокупность модулей», понятие характерно для любой модульной системы.
> Вот как раз этот настраиваемый контроллер можно сравнить с электронной начинкой телевизора, модуль – это плата, для неё вроде есть разъем, воткнуть (установить) её просто, но есть ещё пара проводочков (обработчики событий) которые нужно так подсоединить в существующие разъемы, чтобы не нарушить общую логику работы телевизора (cms).
В моём случае именно так. Каждый объект системы — связка объектов движков. Именно плат, воткнутых в сокеты. Только у меня нет проводочков-событий, всё прекрасно работает и без них :)
Ну, очень грубо, схема такая.
Механизм загрузки объекта по имени и идентификатору:
— Если такого класса ещё нет в памяти, то по имени определяем файл с классом объекта (я ранее писал про разделение ядра и расширений его, как хостовых, так и сайтовых + система укорачивания имён классов)
— Создаём объект класса
— Инициализируем его, если надо, загружая данные из БД.
— Если всё успешно — возвращаем объект. Иначе — NULL
— Опционально — кешируем объект в memcached и при следующих запросах (в т.ч. в других потоках) грузим кешированный результат.
Выглядит для программиста это так:
$topic = object_load("forum_topic", $id);
или
$last_topics = objects_array("forum_topic", array("last_post_time>" => time()-86400));
или даже так:
$last_user_topic = objects_first("forum_topic", array('user_id' => $user_id, 'order' => '-create_time'));
Механизм загрузки объекта по странице сайта:
Есть (также, раскиданные по уровням ядра и расширений) файлы, со статической привязкой регекспов URL'ов к классам:
/forum/viewtopic.bas?id=(\d+)&p=(\d+) => forum_topic(1,2)
1 и 2 — это группы в регекспе, в данном случае указывают ID объекта и номер показываемой страницы в нём.
При нахождении соответствия загружается объект и вызывается его метод content(). Который, если не переопределён, сделат всё, описанно мной в этой теме чуть ранее. Сгенерирует содержимое тела страницы с помощью указанных механизмов шаблонизации (а данные уже загружены при загрузке объекта), поместит это содержимое в общий шаблон страницы сайта, если надо, закеширует объект, если надо — привяжет его к группам кешей, чтобы изменение объектов, от которых он зависит потом приводили к сбросу статических кешей и т.п.
В конце явных поисков есть несколько записей вида:
.* => page_fs_xml,
.* => page_fs_hts,
и т.д.
Это классы, которые грузят объекты, описанные в файловой системе, параллельной структуре сайта. Иногда удобно сайт править удалённо по FTP, тупо работая с *.txt :)
…
Когда страница будет отдана браузеру унифицированный модуль выхода проверяет, не изменялся ли объект и, если нужно, сохраняет изменения в бэкенде данных, попутно очищая/обновляя все зависимые кеши.
Т.е. в явном виде сохранять изменения не нужно.
Ну и плюс к этому механизмы администрирования, генераторы форм, проверка доступа и даже конфигураторы. Например, если ряд объектов имеет схожие настройки, например, один шаблон, один набор двжков и т.п. можно указать только конфиг-класс этих классов. И т.д. Всё это тоже задаётся либо указанием соответствующих движков, либо параметрами класса.
Сами по себе разнородные объекты системы друг от друга структурно ничем не отличаются. Наследование, например, как таковое не нужно, применяется очень редко, когда реально нужно иметь несколько разных объектов с рядом схожих механизмов, или требуется расширить имеющийся объект, не трогая его.
0
сорри, но вы прокомментировали меня, исказив смысл сказанного. Никто не понимал, что существуют модули сообщений, статьей, комментариев, каталогов и т.д. Я предположил, что maxic посчитал, что в предложенной мною архитектуре применен подобный принцип. Поэтому он аргументировал применять иерархию, зная о неизбежных и серьезных проблемах с гибкостью при расширении функций cms с такой архитектурой.
Если все очень очень сильно упростить, то модуль у меня – эта банальная функция. И чтоб расширить действия, которая она совершает, используются события. Вот и все. Модули у меня не генерируют свой контент, не владеют своими ORM, вообще ничто не делаю кроме своего локального назначения. Модулю вообще по барабану на всех)) т.е. дали порабоать, поработает, сделает свое маленькое дело и про всех забудет.
Если все очень очень сильно упростить, то модуль у меня – эта банальная функция. И чтоб расширить действия, которая она совершает, используются события. Вот и все. Модули у меня не генерируют свой контент, не владеют своими ORM, вообще ничто не делаю кроме своего локального назначения. Модулю вообще по барабану на всех)) т.е. дали порабоать, поработает, сделает свое маленькое дело и про всех забудет.
0
И еще вопрос. У вас блочно-модульная система или только модульная?
0
Если только модульная, тогда вы делаете систему как программист. Подумайте о дизайнерах, верстальщиках, обычных юзерах ;) Подумайте о юзабилити системы ;)
0
Блочная для генерации страниц
0
Вызов модулей в блоке в зависимости от данных в контроллере?
«Включение» (switch) модулей для блока и правила в контроллере ;)?
Иерархия блоков? (блок в блоке)?
Тогда вся CMS может состоять из одного контроллера, остальное — модули :)
«Включение» (switch) модулей для блока и правила в контроллере ;)?
Иерархия блоков? (блок в блоке)?
Тогда вся CMS может состоять из одного контроллера, остальное — модули :)
0
не, архитектура вывода совершенно иная, о ней расскажу после статьи про модуль данных
0
вот только про иерархию блоков угадали
0
Если так, то ваша диаграмма будет выглядеть еще проще :)
![](https://habrastorage.org/r/w780q1/getpro/habr/comment_images/8c5/2a1/bc6/8c52a1bc6ba0fd584f1b527f83de21a4.jpg)
![](https://habrastorage.org/getpro/habr/comment_images/8c5/2a1/bc6/8c52a1bc6ba0fd584f1b527f83de21a4.jpg)
0
Очень интересный вариант — впечатлила продуманность. Я бы поправил только один пункт — конфиг выбирал бы по имени домена — очень удобный вариант, в отличии от одного config.php.
Так сделано в CMS, которую сейчас разрабатываем мы. Я тоже постараюсь выложить здесь описание структуры — тогда можно будет детально обсудить плюсы/минусы. :)
Так сделано в CMS, которую сейчас разрабатываем мы. Я тоже постараюсь выложить здесь описание структуры — тогда можно будет детально обсудить плюсы/минусы. :)
+1
Взаимный обмен опытом будет полезен, ждёмс)
0
>Я бы поправил только один пункт — конфиг выбирал бы по имени домена — очень удобный вариант, в отличии от одного config.php
У себя использую тройную иерархию каталогов.
— Есть ядро системы, общее для всех проектов.
— Есть расширения хостинга, характерные для всего конечного сервера.
— Есть расширения виртуального хоста.
Лежать они могут в любом месте системы.
Когда ищется какой-то класс, include, шаблон, файл мапинга URL на классы или конфиг, он ищется сперва в виртхостовой структуре каталогов, потом в хостовой и, наконец, в основном ядре.
Таким образом обеспечивается и гибкая конфигурация, и переопределение функционала ядра без влезания в его исходники и т.п.
(На самом деле система даже ещё немного сложнее — дополнительно просматривается подкаталог vhosts/<имя_хоста>/ в хостовой структуре, куда могут класться виртхостовые же структуры — бывает удобно или просто необходимо в некоторых сложных проектах)
У себя использую тройную иерархию каталогов.
— Есть ядро системы, общее для всех проектов.
— Есть расширения хостинга, характерные для всего конечного сервера.
— Есть расширения виртуального хоста.
Лежать они могут в любом месте системы.
Когда ищется какой-то класс, include, шаблон, файл мапинга URL на классы или конфиг, он ищется сперва в виртхостовой структуре каталогов, потом в хостовой и, наконец, в основном ядре.
Таким образом обеспечивается и гибкая конфигурация, и переопределение функционала ядра без влезания в его исходники и т.п.
(На самом деле система даже ещё немного сложнее — дополнительно просматривается подкаталог vhosts/<имя_хоста>/ в хостовой структуре, куда могут класться виртхостовые же структуры — бывает удобно или просто необходимо в некоторых сложных проектах)
0
Про структуру — чуть позже, а сейчас — о самом актуальном. Здесь — пост о разделении прав доступа в CMS. По моему получилось хорошо. :)
deniso.habrahabr.ru/blog/51231/
deniso.habrahabr.ru/blog/51231/
+1
спасибо, интересно
0
можно поинтересоваться, в какой программе рисовали схемы? симпатично и понятно смотрятся…
0
извиняюсь, пропустил…
0
Мой фреймворк построен по подобной идеологии. Только абстракция немного иного уровня — вся система построена на единой система объектов. Все модули — суть объекты. В моей терминологии это — engines, движки того или иного функционала (т.е. «модули» для меня — вставки в шаблона). Соответственно, у каждого объекта могут быть движок исходных данных (обычно ORM), движок рендеринга основного контента, движок привязывания контента страницы к общему дизайну. Движки разделения доступа, кеширования, модулей в шаблонах, формирования типов ссылок и т.д. и т.п.
Если интересно, поковыряться можно на hg.balancer.ru (GPL).
Если интересно, поковыряться можно на hg.balancer.ru (GPL).
0
Модуль в терминах создаваемой системы — это статический класс
Эээ, а тестировать эти самые модули вы как собираетесь со статическими модулям? пахнет жуткостным извращением) поправьте если ошибаюсь
Эээ, а тестировать эти самые модули вы как собираетесь со статическими модулям? пахнет жуткостным извращением) поправьте если ошибаюсь
0
А что не так с тестированием должно быть из-за статичности класса?
0
ну здрасте приехали, там где статик там мока быть не может у вас же вся функциональность на статиках как я понял, когда вы используете статик вы жестко привязываетесь к имени класса вместо того чтоб использовать имя переменной за которой может быть любой класс с любой реализацией, полиморфизм там все дела)
0
В том и дело что с модулями так и надо — напрямую обращаться к ним (либо через события), незачем модули представлять как объекты и передавать их куда-то в качестве аргументов, хранить ссылки на них и другое. Там где нужны объекты, используются объекты — всё в меру, всё для достижения гибкости и простоты. Сейчас на движке поднимается серьезный проект и поверьте, от того что модули являются статическими классами не возникло не малейшей мысли об ущербности. Возможно просто у вас свое представление, что должен делать модуль и почему он должен быть объектом. :)
0
что значит напрямую?) что мешает вам инстанционировать объект и обращаться напрямую к объекту?) используя статическое обращение к классам вы делаете архитектуру вашего фреймворка слишком жесткой, это касается далеко не только тестирования, также делает весьма ограниченным применение многих паттернов, ну и фактически лишает вас возможности использовать полиморфизм там где используется статическая привязка классов. Есть такие паттерны — Service Locator и Registry они в полной мере решают ваши проблемы с «вызовом модулей напрямую», в этом случае не нужно ничего никуда передавать в качестве аргументов. Боюсь это у вас уж очень особенное представление о том что является модулем, мыслей об ущербности и не возникает пока не возникает необходимость переделать чтото в уже рабочем проекте так чтоб это не зацепило за собой каскада изменений по всему коду, это все давно придумано и не мной вот:
5 самых известных книг по проектированию и программированию
1. Design Patterns. Elements of Reusable Object-Oriented Software by Erich Gamma, Richard Helm, Ralph E. Johnson, and John Vlissides
2. Refactoring: Improving the Design of Existing Code by Martin Fowler, Kent Beck, John Brant, and William Opdyke
3. Patterns of Enterprise Application Architecture by Martin Fowler
4. Domain-Driven Design: Tackling Complexity in the Heart of Software by Eric J. Evans
5. Working Effectively with Legacy Code by Michael Feathers
Конечно не вижу того как вы используете статические члены классов, но для обработки действий юзера я не использую статики, потому что это поведение возможно захочется когда то переопределить. Я тоже использую статики в своем проекте, но исключительно в случае с утилитами, там где статический класс играет роль неймспейса, для объединения отдельных функций, относящихся к одной области, но при этом используемые отдельно, ну то есть не в рамках объекта, также есть статически дергаемый класс под названием Glob, в котором есть переменная $app — приложение и переменная $env, то есть окружение этого самого приложения, для обработки действий пользователя запускается обработчик событий так называемый роутер, но это не тот роутер что в зенде, он используется не только для урлов а вообще для всех событий системы, отдельные модули системы считаю вообще не должны напрямую дергать друг друга а должны взаимодействовать только по средсвам событий и их обработки это развяжет руки команде разработчиков, каждый будет писать свой код в соответствии с протоколом событий и их обработки, а также сделает код менее сцепленным и более независимым.
5 самых известных книг по проектированию и программированию
1. Design Patterns. Elements of Reusable Object-Oriented Software by Erich Gamma, Richard Helm, Ralph E. Johnson, and John Vlissides
2. Refactoring: Improving the Design of Existing Code by Martin Fowler, Kent Beck, John Brant, and William Opdyke
3. Patterns of Enterprise Application Architecture by Martin Fowler
4. Domain-Driven Design: Tackling Complexity in the Heart of Software by Eric J. Evans
5. Working Effectively with Legacy Code by Michael Feathers
Конечно не вижу того как вы используете статические члены классов, но для обработки действий юзера я не использую статики, потому что это поведение возможно захочется когда то переопределить. Я тоже использую статики в своем проекте, но исключительно в случае с утилитами, там где статический класс играет роль неймспейса, для объединения отдельных функций, относящихся к одной области, но при этом используемые отдельно, ну то есть не в рамках объекта, также есть статически дергаемый класс под названием Glob, в котором есть переменная $app — приложение и переменная $env, то есть окружение этого самого приложения, для обработки действий пользователя запускается обработчик событий так называемый роутер, но это не тот роутер что в зенде, он используется не только для урлов а вообще для всех событий системы, отдельные модули системы считаю вообще не должны напрямую дергать друг друга а должны взаимодействовать только по средсвам событий и их обработки это развяжет руки команде разработчиков, каждый будет писать свой код в соответствии с протоколом событий и их обработки, а также сделает код менее сцепленным и более независимым.
0
Вы не первый, кто упрекает меня в использовании статичных классов для модулей движка. Да что там, я сам, когда только начинал делать двиг, пытался сделать красивую правильную объектную структуру кода, в частности для модулей использовался паттерн singliton. Но когда прорисовалась полностью архитектура движка, решено было отказаться от правильной объектности в коде не в ущерб его гибкости, применение статичных классов для модулей только упростило программный код.
Архитектура движка такая, что желание в будущем добавлять новую логику решается через обработку событий, незачем что-то переопределять, когда не нужное можно просто отключить. С умными книжками по ооп я очень даже знаком, даже более. Только вот идеология движка не в применении объектно-ориентированного кода, не в привычной всем реализации MVC и других штучек из книжек, а в гибкости модели данных и эта гибкость не достигается правильной объектностью программного кода. Незачем судить об использовании статических классов, когда вами не видна архитектура движка комплексно. Это не в обиду вам, но если увидите изюминку в архитектуре движка, а это в основном касается модели данных и её использования, то вопросы о статичности классов модулей уже не будут вас волновать.
:)
Архитектура движка такая, что желание в будущем добавлять новую логику решается через обработку событий, незачем что-то переопределять, когда не нужное можно просто отключить. С умными книжками по ооп я очень даже знаком, даже более. Только вот идеология движка не в применении объектно-ориентированного кода, не в привычной всем реализации MVC и других штучек из книжек, а в гибкости модели данных и эта гибкость не достигается правильной объектностью программного кода. Незачем судить об использовании статических классов, когда вами не видна архитектура движка комплексно. Это не в обиду вам, но если увидите изюминку в архитектуре движка, а это в основном касается модели данных и её использования, то вопросы о статичности классов модулей уже не будут вас волновать.
:)
0
Напоследок, гибкость модели данных на мой взгляд в реляционной БД может быть только в том случае если вы используете связь сущностей по графу, когда у вас в явном виде есть типизация сущностей, их связей, отдаленно это реализовано в друпале там есть понятие НОД но нет понятия связей нод и типов связей.
0
> Боюсь это у вас уж очень особенное представление о том что является модулем.
Тут боятся незачем, я только рад что у меня оно особенное :)
Тут боятся незачем, я только рад что у меня оно особенное :)
0
>Тут боятся незачем, я только рад что у меня оно особенное :)
Контекст) упускаете), особенности нашего мышления часто объясняются просто недостатком информации, проще говоря незнанием, но конечно все точки зрения имеют право на существование.
singleton то тут причем? этот паттерн, который многие часто используют неправильно, синглтон нужен только в том случае если вам действительно так уж критично чтобы экземпляр объекта был единственный, синглтон также осложняет модульное тестирование ну и вообще нужно крепко думать прежде чем его использовать. Для доступа к звездным объектам обычно используют Service Locator или Registry
>применение статичных классов для модулей только упростило программный код.
Далеко невсегда самый простой путь является «правильным», но каждый сам выбирает себе путь что правда то правда) и понятие правильный весьма относительно, вашего «двига» я не видел и не берусь что либо утверждать да и даже еслибы видел ваш код то так как он не имеет непосредственного отношения ко мне то и высказывать какой либо негатив нестал бы, по кармическим причинам) (не на хабре)
Вобщем желаю вам удачи в разработке вашего двига, как вы выражаетесь просто заметил для себя, что мне такой подход стал чуждым некоторое время назад ну и имел желание поделится своими соображениями.
Контекст) упускаете), особенности нашего мышления часто объясняются просто недостатком информации, проще говоря незнанием, но конечно все точки зрения имеют право на существование.
singleton то тут причем? этот паттерн, который многие часто используют неправильно, синглтон нужен только в том случае если вам действительно так уж критично чтобы экземпляр объекта был единственный, синглтон также осложняет модульное тестирование ну и вообще нужно крепко думать прежде чем его использовать. Для доступа к звездным объектам обычно используют Service Locator или Registry
>применение статичных классов для модулей только упростило программный код.
Далеко невсегда самый простой путь является «правильным», но каждый сам выбирает себе путь что правда то правда) и понятие правильный весьма относительно, вашего «двига» я не видел и не берусь что либо утверждать да и даже еслибы видел ваш код то так как он не имеет непосредственного отношения ко мне то и высказывать какой либо негатив нестал бы, по кармическим причинам) (не на хабре)
Вобщем желаю вам удачи в разработке вашего двига, как вы выражаетесь просто заметил для себя, что мне такой подход стал чуждым некоторое время назад ну и имел желание поделится своими соображениями.
0
Загибулина в том, что первостепенна цель, а не инструмент, абсурдно судить какой молоток правильный не зная какой гвоздь забивать. В общем, сколько не говори, как хороши всякие методики, паттерны и прочее, о каждом я знаю, но выбираю или придумываю своё, именно то, что лучшим образом приблизит цель к осуществлению.
Спасибо за пожелания, приятно что спустя более полугода появляются новые комменты :)
Спасибо за пожелания, приятно что спустя более полугода появляются новые комменты :)
0
Sign up to leave a comment.
Архитектура CMS