Home - Katemare/Entlink GitHub Wiki
Entlink - проект движка для веб-сайтов, который рассматривает все данные как сущности, соединённые связями (которые тоже считаются сущностями). Это значит, что всё на сайте подчинено общей логике, и для добавления новых разделов, новых типов данных, нового их представления - требуется гораздо меньше кода, чем в других движках. Принцип Entlink позволяет добиться большей гибкости движка меньшими усилиями, по крайней мере в области стандартных задач.
Примеры сущностей:
- Персона
- Запись в журнале
- Комментарий
- Метка
- Файл
- Персона
- Имеет аватар: файл.
- Зарегистрировался: дата.
- Имеет подпись: текст.
- Статья
- Опубликована кем: персона.
- Автор: персона
- Автор: другая персона (статья была написана в соавторстве)
- Метка: метка.
- Метка: ещё метка,
- Комментарий: текст
- Опубликован: персона.
Чем структура "сущность-связь" может помочь настроить, скажем, пример со статьёй выше под нужды сайта?
- Можно уточнить роль каждого автора, добавив этой связи метку "Иллюстратор" или "Автор текста". Это потребует только разрешить ставить метки на связь "А автор Б" и, возможно, указать список подходящих меток.
- Можно объединять статьи в серии. Для этого достаточно разрешить сущность "группировка" для статей. При желании для сущности "группировка" можно разрешить всё то, что есть у статей: ответственная персона, метки, комментарии...
- Можно вести историю изменений. Для этого достаточно разрешить ведение истории для сущности "статья" и, если захочется, для её связей. Поскольку все сущности хранятся в базе единообразно, то модуль ведения истории не нуждается в настройке для разных типов сущностей. Да и сам он хранит свои данные в виде сущностей и связей.
- Поскольку основа движка - это взаимосвязь данных, можно не волноваться, что данные потеряются за давностью лет. Их всегда можно будет найти через связанные с ними сущности: авторов, метки, избранные коллекции, разделы сайта, наконец. Переход по связям должен затягивать так же, как переход по гиперссылкам в Википедии, и начав с фэнтезийного рассказа друга, можно закончить просмотром коллекции рисунков об осьминогах или чтением обзора на фильм, о котором слышишь впервые.
Все сущности сайта имеют уникальный номер. При операциях с этими сущностями они используют единый класс - Entity. Каждый экземпляр Entity при необходимости создаёт дочерние объекты классов "поведение сущности" и "показ сущности" в зависимости от типа сущности и нужд текущей ситуации.
Например, развёрнутое отображение статьи использует объект класса "развёрнутый показ статьи", а при кратком показе - объект класса "краткий показ статьи". В большинстве случаев будет достаточно общих классов "развёрнутый показ" или "краткий показ", поскольку сущности часто будут разбиты на базовые элементы, например "текст", для которых способ различного отображения уже ясен.
Когда требуется просто найти и показать статьи по критерию, то объект поведения и вовсе не нужен. Однако при редактировании или создании он может понадобиться и будет создан.
Движок использует следующие технологии:
- php, как самый доступный язык веб-программирования. Одна из основных идей движка - его лёгкая модификация, а значит, чем ниже будет порог для написания плагинов и дополнений, тем лучше.
- MySQL. Впрочем, обращение к базе данных будет осуществляться через отдельных объект, так что сам тип базы данных не столь важен.
- javascript без зависимости от jQuery. Однако поскольку отображение не зависит от отображаемых данных, могут быть модули, добавляющие функции jQuery.
Прежде чем компетентно приступить к созданию движка, нужно решить ряд трудностей на этапе планирования.
То, что у каждой сущности уникальный номер, означает, что основная таблица с этими номерами может иметь сотни тысяч записей. Представьте: каждый пользователь, каждая публикация, каждый комментарий, все связи между ними, и ещё многие из этих сущностей состоят из подсущностей (аватар, дата регистрации, пол...).
Как эффективно работать с такой большой таблицей?
Видимо, в современных СУБД, включая MySQL, размер страницы проблемой не является - при условии, что не используются громоздкие операции JOIN.
В обычных движках, где у каждого типа данных свои стандарты полей и связей, количество запросов может быть невеликов. Например, у записи в таблице статей есть поля "название", "текст", "дата создания", "автор". В Entlink для выражения того же нужно прочесть около десятка записей: саму сущность публикации, её связи, затем данные о сущностях, с которыми она связана... Зачастую цепочка продолжается, поскольку у авторов, к примеру, нужно отобразить аватары - ещё два запроса (связи авторов и сущности, на которые эти связи ссылаются).
Как сократить число запросов или ресурсы для их выполнения? Сколько запросов на страницу нормально для современных движков?
Допустим, у нас есть публикация типа "рисунок". Этот рисунок связан с несколькими авторами - один сделал эскиз, другой создал финальные контуры, третий раскрасил, а четвёртый добавил текст. Это типичный квартет авторов при создании американского комикса.
Есть два способа, как обозначить роль каждого автора:
- Использовать специфическую связь "А колорист Б". Но как тогда производить поиск "перечислить всех авторов Б" или "перечислить все работы автора А"? Нужно сначала сделать запрос, какие типы связей являются дочерними как "А автор Б"? Сколько уровней вложения может понадобиться исследовать перед началом поиска?
- Дать общей связи "А автор Б" метку "колорист". Это также позволит обозначить человека и колористом, и, скажем, автором сценария в пределах одной связи. Но проблема вложенности понятий остаётся: что если нам нужно найти всех художников Б или все работы, где А был художником? Для этого нужно получить сведения о том, что колорист - это тип художника, а сценарист - нет.
Для уменьшения числа запросов из проблемы № 2, вероятно, понадобится все данные хранить в той же основной таблице, где хранятся уникальные идентификаторы. В любом случае многие сущности будут состоять из базовых элементов (текст, картинка, дата...), и даже если непосредственно содержимое будет в отдельных таблицах texts, images, dates - по сути там будут перемешаны тексты комментариев и тексты статей, аватары и рисунки, даты всего, что когда-либо происходило или было упомянуто на сайте.
Это значит, что запрос "посмотреть все статьи" или "экспортировать все статьи" будет не так уж тривиален.
Практический пример. На сайте Русской Лиги Покемонов есть покедекс - список всех монстров с их многочисленными данными: ролевые характеристики, названия на разных языках, описания из разных версий, наборы атак из разных версий, картинки... В переводе на систему "сущность-связь" один покемон может состоять из пары сотен подсущностей. Даже если ограничиться одной из версий игр, вряд ли их будет меньше сотни. В текущей Лиге Покемонов, однако, покемон описывается максимум десятком записей, большая часть из которых - список атак. Все основные данные лежат в одной записи.
В подобной ситуации как лучше дробить сущность на элементы? Например, шесть ролевых атрибутов, которые есть у всех покемонов - хранить ли их как отдельные сущности "значение атрибута"? Или в единой сущности "атрибуты покемона"? В первом случае число сущностей увеличивается в шесть раз, во втором - страдает единообразие и преимущества, связанные с ним.
См. Связи на примере покемона.
Возьмём MediaWiki - движок, используемый в Википедии и в тысячах вики по всему интернету. Несмотря на то, что в Entlink будут функции вики, отдельные сайты вполне могут решить использовать движок MediaWiki для этой цели - или сохранить уже существующую у них энциклопедию. В конце концов, едва ли в Entlink будет возможно повторить все многочисленные функции MediaWiki и её дополнений.
Как интегрировать в Entlink данные из MediaWiki или других движков, где есть чёткое различие между типами данных? Создать уникальный идентификатор Entlink для каждого пользователя и статьи, которые захочется использовать в движке? Что если данные будут удалены, объединены или перенесены в интегрированном движке?