Предложение по типам топиков

Уважаемые разработчики есть к вам предложение по улучшению внутренней структуры ЛС
РЕчь идет о поле БД topic_type. кому интересно смотрим под кат.

CREATE TABLE IF NOT EXISTS `prefix_topic` (
  `topic_id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `blog_id` int(11) unsigned NOT NULL,
  `user_id` int(11) unsigned NOT NULL,
=========>  `topic_type` enum('topic','link','question','photoset') NOT NULL DEFAULT 'topic',

Собственно суть.
Есть некоторые плагины которые добавляють другие типы топиков в ЛС, и собственно при инсталяции — меняют это поле через Alter
Тепер допустим что есть 2 таких модуля:
1 — добавляет тип event
2 — добавляет тип video
Если оставить структуру такой как сейчас то сомневаюсь что можно будет установить эти 2 плагина одновременно а если и получиться, то удалить их мы уже не сможем, так как при удалении они будут менять это поле в стандартный вид и будут затираться изминения другого модуля.

Предлагаю
Заменить тип поля на smallint
Добавить справочник типов полей:

+create table if not exists `prefix_topic_type` (
+    `topic_type_id` INTEGER not null auto_increment,
+    `topic_type_name` varchar(32),
+    PRIMARY KEY (`topic_type_id`)
+) engine=innoDB default charset=utf8 auto_increment=1;


Добавить функции конвертации

public function TopicTypeName2Id($oTopicName)
public function TopicTypeId2Name($oTopicId)

Таким образом это может облегчить расширение функциональности ЛС за счет более гибкого внедрения новых типов топиков

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

avatar
так только старые плагины делают...
в движке есть механизм чтоб аккуратно этот момент обойти
avatar
Можете мне указать на мой недосмотр?
avatar
если правильно понял вопрос...
www/engine/classes/Plugin.class.php(208)
/**
* Добавляет тип в поле enum
*
* @param string $sTableName
* @param string $sFieldName
* @param string $sType
*/
protected function addEnumType($sTableName,$sFieldName,$sType) {
$this->Database_addEnumType($sTableName,$sFieldName,$sType);
}
avatar
Пересмотрел я тот код.
Остается открытым вопрос об удалении плагина т.к не нашел функции removeEnumType
то получаеться что удаление плагинов как минимум засорит базу.
avatar
смотреть в «ширь» многие умеют… тут в «глубь» надо.
а собственно почему вопрос то возник?
столкнулся с проблемой при разработке?!
если так, то имеет смысл продолжать искать «истину», а если о других беспокоишься или проблемы реально с плагинами, то врятли к чему приведет, по вполне понятным причинам
avatar
Вообще-то о других беспокоился. То что мне надо сделать я могу сделать и без этого, просто хотелось чтоб было как-то… лучше
avatar
Заменить тип поля на smallint
Вот этого делать нельзя категорически, т.к. придется слишком много кода перелопачивать, если уж и переделывать, то оставлять varchar. Но в целом идея здравая, но старая, а потому — непроходная.

ЗЫ извини за оффтоп, но чо у тя за ник такой… странный? это твой номер телефона?
avatar
Скорее он знаком с нравами «местных» =)
avatar
2^40 Реально странный. Видимо, он мнемоникой увлекается)
avatar
+1
avatar
Дык врод нормальный ник, такой же как и на хабре.
avatar
З
Ы извини за оффтоп, но чо у тя за ник такой… странный? это твой номер телефона?
всего навсего терабайт )
avatar
Если оставить структуру такой как сейчас то сомневаюсь что можно будет установить эти 2 плагина одновременно


Список ENUM в MySQL может содержать максимум 65535 различных величин. Так что установятся без проблем и ещё вагон других.

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


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

Единственный нюанс с этим полем может возникнуть при обновлении структуры таблицы топиков, если таковая будет иметь место в будущих релизах Livestreet. Но, я думаю, ort сделает всё красиво, как всегда. Да и сами при обновлении можете код update.sql проверить.
avatar
Вот пример обновления convert_0.4.2_to_0.5.1.sql:

-- Добавляет новый тип топика 'photoset', этот запрос автоматически выполняется через инсталлятор при конвертации БД (для сохранения ваших кастомных типов топиков)
-- ALTER TABLE  `prefix_topic` CHANGE topic_type topic_type ENUM('topic','link','question','photoset') NOT NULL DEFAULT 'topic';
-- 


Так что никаких проблем с текущим положением дел.
avatar
Ты не понял — ТС верно пишет по сути.

Вот напишу я плагин с типом 'foo' и приложу sql-фалик к нему:
ALTER TABLE  `prefix_topic` CHANGE topic_type topic_type 
ENUM('topic','link','question','photoset', 'foo') NOT NULL DEFAULT 'topic';

А ты другой плагин напишешь со своим типом 'foo' и приложишь свой sql-фалик:
ALTER TABLE  `prefix_topic` CHANGE topic_type topic_type 
ENUM('topic','link','question','photoset', 'moo') NOT NULL DEFAULT 'topic';

Надо объяснять, почему эти два плагина не будут работать одновременно без вмешательства в базу ручками?
avatar
Зачем так? Когда можно так:

Один пишет:

$this->addEnumType(Config::Get('db.table.topic'),'topic_type','foo');

Другой:

$this->addEnumType(Config::Get('db.table.topic'),'topic_type','moo');

Третий:

$this->addEnumType(Config::Get('db.table.topic'),'topic_type','hru');

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

Тебе кажется, что это правильным, когда меняющйся набор загоняется в ENUM, а мне (с точки зрения проектирования) — нет. И то, что часть манипуляций с базой вынесена в sql-файл, а часть прямо в код активации плагина вшита, мне тоже кажется не очень логичным. Я понимаю, что иногда может быть довольно сложная логика, которую проще в PHP обернуть, нежели в sql-коде выполнять, но добавление типа — это немного не тот случай.

Все это ИМХО, разумеется. Хоть я и знаю, что оно не совпадает с ИМХОй разработчика.
avatar
Тебе кажется, что это правильным, когда меняющйся набор загоняется в ENUM
Перечисление типов топиков не меняется в движке. Это мы, те, кому нужны новые типы топиков, его меняем. Я не вижу смысла создавать отдельную таблицу в БД для этого перечисления, ибо меняется оно в одностороннем порядке — только добавляются новые элементы. Ведь если ты создал новый тип топика, то будешь им пользоваться, а раз будешь пользоваться — всё, удалять тип нельзя. Млм, что архитектурное решение верно по части enum.
avatar
А если не в одностороннем порядке. А если у нас есть 2 модуля которые ВДРУГ добавляют одинаковый тип топика тотже «event» но по разному работают с контектом и если мы захочем поменять один модуль на другой то полюбому надо будет удалять все топики этого типа иначе работа новоог модуля будет неправильной
avatar
Если одинаковый тип топика «event» добавить хоть в отдельную таблицу, хоть в перечисление enum — будет коллизия.

Если меняем один модуль на другой, в БД ничего менять не нужно. Вы же меняете логику работы, зачем же менять «event» на «event» в базе? :)
avatar
Правильно в том то и суть, если есть 2 модуля с одинаковым типом топика но разной логикой работы(начиная от разного форматирования елементов, заканчивая ентерпритацией служебных тэгов и т.д) и вы сначала поставили один, наполнили его чем-то, потом удалили (не удаляя посты) и поставили другой, то при работе с теми предыдущими постами он будет работать неправильно
avatar
Правильно в том то и суть, если есть 2 модуля с одинаковым типом топика но разной логикой работы(начиная от разного форматирования елементов, заканчивая ентерпритацией служебных тэгов и т.д) и вы сначала поставили один, наполнили его чем-то, потом удалили (не удаляя посты) и поставили другой, то при работе с теми предыдущими постами он будет работать неправильно

От этой маловероятной ситуации не спасёт отдельная таблица для типов топиков.
avatar
а как часто такое встречается?..
avatar
Как чато — не знаю. только недавно начал работать с ЛС.
avatar
Такого не будет никогда с вероятностью 99,99999999999% :)
avatar
Хорошо покачто поверю :) Но если вдруг встречу то обязательно напишу сюда
avatar
тогда другой вопрос, стоят ли затраты на поиск решания, разработку, внедрение, и тд. если подобная ситуация будет появляться с преодичностью раз в 3 года на 1 плагин из сотни?.. я конечноже утрирую )
avatar
Т.е. весь смысл манипуляций по добавлению нового типа — просто шоб було? Но при этом надо еще учесть, что следующий шаг, который предпринимается разработчиками — прописывают жестко в коде мапперов набор типов топиков и блогов, с которыми работают. Что, в принципе, логично при таком подходе, т.к. подразумевается, что набор типов — это забронзовевший неизменяемый сет. Но если возникает необходимость реально работать с этим сетом, как-то манипулировать им, в то время как в проекте два-три десятка плагинов и часть из них работает с типами блогов, понятия не имея ни о типах, добавленных другими плагинами — вот это уже становится похоже на лечение гнойной ангины через задний проход.

Понимаешь, я ведь не просто теоретически рассуждаю, я с этим гемором на практике столкнулся. Поэтому я считаю, что тип топика и тип блога — это должна быть такая сущность, обладающая набором свойств, которые можно расширять (а не как сейчас, все свойства — это название типа). Такой подход мне кажется более грамотным и более гибким.
avatar
Если честно, пока не столкнулся с проблемой при создании нового типа топика, которая была бы именно из-за того, что тип в enum. Да, он жестко зашивается в коде. Тут соглашусь, что это не очень красиво. Но как оно есть, так оно есть.

Ну вот, например, что нужно от типа, кроме него самого, какие свойства?
avatar
Примеры навскидку: хочу фильтровать топики для вывода на главной по их типу, ограничить юзеров в праве создания топиков того или иного типа (напр., по рейтингу), задавать в писке перечень типов топиков, в которых буду искать и т.д.

Да собственно и сейчас — просто топик и опрос это разные типы. Почему? По сути опрос — это тот же топик (один в один!), только с дополнительными свойствами.

Но еще больше проблем возникает, когда с типами блогов начинаешь работать. Вот конкретный пример из движка:
/**
 * Проверяем доступные типы блога для создания
 */
if (!in_array(getRequest('blog_type'),array('open','close'))) {
  // something
}

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

Вот конкретный пример из движка
этот пример не показывает минусу enuma'а, он показывает косяки в коде еще со времен версии 0.1, когда и не предполагалось наличие модификаций, плагинов и т.п. Здесь так же можно хранить в классе набор доступных типов, а плагинами его дополнять/изменять.

Действительно большой минус enum — это долгое выполнение alter на большой таблце
avatar
Ухххх
нехилый холивор у Вас получился.
Может я действительно поторопиля с этими табицами, может стоит начать с изминения типа topic_type на varchar уже бы подало разработчикам
комментарий был удален
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.