Изменения

Перейти к: навигация, поиск

BugzillaORM

15 830 байтов добавлено, 22:45, 5 марта 2012
м
Нет описания правки
В Bugzilla половина кода в шаблонах, половина на основе полу-ORM’а Bugzilla::Object. Большая часть — говнокод. С одной стороны — ORM бы туда, было бы классно, НО! ORM мало, и нужен не он! Все (существующие) ORM-движки — это просто объектный интерфейс к базе данных. А нужно некое объектное ядро, которое бы позволяло создавать свои объекты, с полями различных типов, в том числе и ссылающимися на другие такие же объекты, с возможностью приписывания специальных особенностей полю, с общим механизмом хранения истории и с автоматическим базовым CRUD-интерфейсом.
Есть сущностиОбъекты в Bugzilla:
* баг
* классификация, продукт, компонент
* вложение, комментарий, флаг, тип флага
* пользователь, группа
* если таки будет ядро - ядро — ещё появляется метакласс сущности, объекты которого описывают типы сущностей
<graph>
Причём, понятное дело, если баг принадлежит к некоторому продукту (через компонент), то и его версия, milestone, agreement должны принадлежать к тому же продукту. Сейчас в Bugzilla это реализуется так — для каждой сущности, связанной с багом, в баге есть «поле», а для ограничения значений полей поля делаются «зависимыми» от других полей. Из-за этого там куча костылей и, по сути, повесить зависимость на отличное от поля «продукт» поле невозможно.
А подумав и посмотрев на красивую картинку выше, мы приходим к другой идее — '''есть сущности, связи между ними и идея непротиворечивого состояния'''.Но это только часть картины, ибо на это ещё навёрнуты:* Права (в Bugzilla рулятся на уровне продукта)* Скрытие/показ полей бага в зависимости друг от друга* Email-уведомления об изменениях
Правда, на это ещё навёрнуты права (в Bugzilla рулятся на уровне продукта) и скрытие/показ полей бага в зависимости друг от друга.== Текущее состояние ==
У сущностей есть:* ID — первичный ключ* атрибуты* <s>ссылка на контролирующее поле и значения — Базовые (то есть если другая сущность ссылается на эту, другим полем она должна ссылаться и на контролирующую</s>чего не быть логически не может):* способ преобразования в строку* ''ВозможноОбъект, права доступа к сущности — привязка действий над сущностью (просмотрбаг, правкапользователь, возможногруппа, другие) комментарий к группам пользователейбагу. Возможно, не нужно это сюда пихать* Продукт имеет специальный смысл — разграничение прав. Поэтому он тоже обязателен.''
У объектов есть:* ID — первичный ключ* Поля* Ссылка на родителя (ID, тип задаётся в классе сущности). Сущности образуют дерево.* Способ преобразования в строку Логическая неконсистентность:* Объект «компонент» имеет поле «продукт», тип которого — ссылка на объект «продукт»* Чтобы отказаться от дурацкой системы «контролирующих значений» и сделать дерево, в объекте «баг» самостоятельного поля «продукт» быть не должно* Но как тогда выбирать сначала продукт, а потом компонент, при редактировании бага?* Получается, что «продукт» — это просто способ подразделения компонентов Ещё одна логическая неконсистентность:* Если мы не хотим завязываться на существование поля «компонент», но у нас всё равно «дерево», получается, что в случае отсутствия поля «компонент» баг привязывается напрямую к продукту И ещё одна:* Если «продукт» — это всего лишь способ уточнения компонентов, то как же ограничивать им другие поля? У каждого атрибута поля есть:
* Тип
* Значение по умолчанию
* Вид показа в интерфейсе(по умолчанию?)* Копируется ли значение атрибута при клонировании сущности* Показывается ли атрибут в форме создания сущности* <s>Ссылка на контролирующий атрибут той того же сущностиобъекта, что и этот, и на его значения</s>*: <s>Если выбрано, означает, что атрибут показывается, только если другой атрибут той же сущности, которой принадлежит этот, имеет одно из заданных значений</s> В данный момент зависимые сущности в Bugzilla хранятся в денормализованном виде, то есть если мы хотим видеть поля «продукт» и «компонент» у бага, а выбранный «компонент» однозначно определяет «продукт», то всё равно хранятся и являются атрибутами бага они оба.
Типы атрибутов:
* {{ok}} Строка
** E-mail адрес — особенности: опционально скрывается ради антиспама, может иметь настройки уведомлений
* Boolean
* {{ok}} DecimalДесятичное число
* Дата
* Время
* {{ok}} Дата+время
* Файл (вложение)
* Single-Select &rarr; ссылка на сущность (то есть «многие к 1»)
** ''Необязательный вариант синглселекта — «1 к 1».''
** {{ok}} существует в частичном виде — без выбора желаемой сущности
* Multi-Select &rarr; ссылка на несколько сущностей одного типа (то есть «многие ко многим»)
** Вариант мультиселекта — «список подчинённых» Два способа показа — поле со списком (комбобокс), или мультиселект* Список тегов, с автодобавлением значений Что ушло бы в этот типа ORM ? * Custom Fields, то есть 1 ко многим), управление полями багов. Например* Отключение стандартных полей типа OS, список аттачментов багаHardware.* Добавление спецполей в продукты, список комментов к багукомпоненты и т. д. — сейчас это делается в коде.** {{ok}} существует Версионирование всех объектов. История бы хранилась унифицированно. Не было бы отдельно таблиц bugs_activity и longdescs, соответственно не было бы и тормозов при проверке «Only bugs changed between…» либо комментарии бы дублировались в частичном виде — без выбора желаемой сущностиbugs_activity (логичнее)* Файл Простые интерфейсы типа CRUD (вложениеCreate/Read/Update/Delete), сейчас созданные непонятно каким копипастом.В основном имеется ввиду админка.* Права на редактирование объектов.* Валидаторы и подсказки значений.* Корректная валидация зависимостей полей друг от друга.* Часть SQL-запросов, написанных ручками в коде.* Вся логика постановки/обновления багов из process_bug и post_bug, дублированная сейчас в обработке входящих e-mailов и Excel-импорте* Даже Excel- и XML-импорт, причём импортировать можно было бы вообще всё что угодно. Появились бы дополнительные возможности: * Создание новых объектов типа SCRUM карточек.* Изменение типов стандартных полей типа целочисленных приоритетов.* Можно было бы прикрутить статистику по любым объектам, причём с Time Machine, то есть просмотром статистики за любой прошедший момент времени. :) == Существующие поля ==
Email-уведомления в общем виде задаются как уведомление на поле типа email, вытаскиваемое по цепочке из сущности (например bug.product.product_watcher.email) при изменении заданных атрибутов сущности.=== Поля багов ===
Поля багов перечислены ниже. Жирное «да» в колонке «можно отключить» означает, что отключать можно уже сейчас (скорее всего, через параметры типа usevotes и ти т. пп.). Нежирное «да» в колонках «можно отключить» и «можно менять тип» означают, что чисто теоретически логика работы Bugzilla это позволяет.
<tab sep=bar class=simpletable head=topleft>
поле | тип | можно отключить? | можно менять тип? | примечания
Примечания:
* Все поля-ссылки на пользователей показываются в виде строки либо в виде combo-box’а, и у них есть функция валидации — валидации — она угадывает юзеров по некорректным именам. ==== Логически минимальный набор полей ==== Совершенно точно, никогда и ни при каких условиях у бага не могут отсутствовать поля:* ID* Заголовок* История => reporter, время создания (creation_ts), время изменения (delta_ts), время оповещения по почте (lastdiffed)* КомментарииБез этого никакой «баг» смысла не имеет ни в одном баг-трекере. ==== Устаревшие поля ====
Устаревшие поля / поля, которые ХЗ зачем нужны в таблице полей багов:
* requestees.login_name
* setters.login_name
 
==== Вычисляемые поля ====
Вычисляемые поля багов:
</tab>
=== Поля вложений:=== 
<tab sep=bar class=simpletable head=left>
submitter | single-select, показ в виде select’а или строки, есть функция валидации (угадывания юзера по некорректному имени)
</tab>
=== Поля компонентов:===
<tab sep=bar class=simpletable head=top>
</tab>
Что ушло бы в ORM== Из чего состоит багзилла?==
* Custom Fields, то есть, управление полями багов.* Отключение стандартных полей типа OS, Hardware.* Изменение типов стандартных полей типа целочисленных приоритетов.* Добавление спецполей в продукты, компоненты и т. д. — сейчас это делается в коде.* Версионирование всех объектов. История бы хранилась унифицированно. Не было бы отдельно таблиц bugs_activity и longdescs, соответственно не было бы и тормозов при проверке «Only bugs changed between…»* Простые интерфейсы типа CRUD (Create/Read/Update/Delete), сейчас созданные непонятно каким копипастом. В основном имеется ввиду админка.* Права на редактирование объектов.* Валидаторы и подсказки значений.* Корректная валидация зависимостей полей друг от друга.* Часть SQL-запросов, написанных ручками в коде.* Создание новых объектов типа SCRUM карточек.* Мохнатая логика автоматической постановки/обновления багов из обработки входящих e-mailов и Excel-импорта=== С внешней точки зрения ===
Крупные блоки функционала в Bugzilla с точки зрения пользователя: * Можно было бы прикрутить статистику Создание, просмотр, изменение багов, история по любым объектамбагу** Форматирование комментариев* Создание, причём с просмотр, изменение вложений* Поиск багов, форма поиска* Графики одни, графики другие, Summarize Time Machine* Исходящая почта* Входящая почта* Запросы флагов* Напоминания (whining)* Регистрация, то есть просмотром статистики изменение, раздача групп пользователям* Пользовательские настройки* ''XML-импорт (в полудохлом виде)''* Web-сервисы (XML-RPC, JSON-RPC)* Sanity Check* Графы и деревья зависимостей* Голосование за любой прошедший момент временибаги ==== Наши крупные фичи ==== * SCRUM-карточки* RSS-лента активности* XML-Simple Web-сервисы* Проверки корректности* Excel-импорт* Информер* Глобальная авторизация* Today Worktime, Super Worktime Плюс вагон и маленькая тележка мелочи. : === Страница создания бага (enter_bug.cgi)===
Текущая логика страницы создания бага:
** списки пользователей, относящихся к багу в combo-box’ы
** опциональный запрет на ввод приоритета на основе конфигурации (letsubmitterchoosepriority)
** список флажков — флажков — ограничителей доступа группами
* значения полей по умолчанию:
** которые совсем по умолчанию
* напоминания о вводе времени
* предпросмотр комментариев
* постановка вложения сразу при создании добавление ссылки на старый аттач для клонированного из коммента бага
* переключатель Show Expert Fields
* Submit по Ctrl-Enter
 
=== Обработчик создания бага (post_bug.cgi) ===
 
* Редирект на enter_bug.cgi если форма не заполнена
* Проверка, не был ли уже использован этот token для постановки другого бага?
* Вывод страницы с URL-шаблоном постановки бага, если попросили
* Заполнение описания по шаблону, если использовался спецвид формы (например create_guided)
* Отправка куки VERSION
* Начало/конец транзакции в БД
* Постановка собственно бага (Bug::create)
* Постановка вложения сразу при создании бага
* Постановка флагов на вложение
* Постановка флагов на баг
* Рассылка почты по багу, по его зависимостям
* Вывод сообщения о том, что баг поставлен, о том, что CC-список обрезан по группе
 
=== Обработчик изменения бага (process_bug.cgi) ===
 
* Начало/конец транзакции в БД
* SELECT FOR UPDATE багов
* Удаление значений полей, равных dontchange (используется в групповом редактировании)
* Угадывание юзеров по части логина/имени
* Проверка коллизии по delta_ts, вывод только действительно изменённых полей в форму подтверждения
* Проверка token формы
* Загрузка следующего бага из списка ДО обновления текущего (O_O)
* Проверка прав редактирования по всем багам
* Установка значения продукта до всех остальных полей
* Установка новых групп до остальных изменений, когда включён strict_isolation
* Установка/изменение флагов
* Установка зависимостей бага
* Установка ключевых слов
* Установка остальных полей
* Установка некоторых значений только для обновлений отдельных багов (alias, cclist_accessible, reporter_accessible, isprivate на комментах)
* БОльшая часть логики обновления поля CC
* Вызов функции проверки strict_isolation
* Перемещение багов (MOVE) — полуживое, хз как работает
* И после всего этого — ещё изменения, status, resolution, dup_id
* Теперь всё это ещё незакоммичено, вызов реальных обновлений из Bug.pm
* Отправка почты по зависимостям, если статус поменялся с открытого на закрытый
* Обрезание CC-списка по группе (наше)
* Сообщение, если очищено remaining_time
* Удаление голосов за баг, если переместили в другой продукт, и проверка голосо-подтвеждённости бага
* Отправка почты CC, Assignee, Reporter’у, QA, старым Assignee, QA и CC
* Отправка почты по багу, дубликатом которого был помечен данный
* Добавление нескольких вложений (наше)
* Отправка почты по флагам, через отдельный механизм сбоку
* Редирект (наше) или показ следующего/того же/никакого бага
* Не показывает ничего, если USAGE_MODE_EMAIL
 
=== Список/поиск багов (buglist.cgi) ===
 
* SuperWorkTime (наше доработко)
* Редирект на форму поиска для пустого запроса
* Редирект на форму поиска с добавленными пустыми полями, если на форме поиска жмут Add/Remove поле без JS
* Редирект с POST’енного запроса на GET
* Быстрый поиск
* Посыл на хрен, если content пуст при включённом параметре specific_search_allow_empty_words
* Обратная совместимость: format=rdf -> ctype=rdf, ctype=rss -> ctype=atom
* ctype=js слать в хрен
* Поддержка server-push
* regetlastlist — открытие последнего просмотренного списка багов (берётся из куки)
* Удаление колонки relevance из списка колонок, если юзер не просит полнотекстовый поиск
* В buglist.cgi почему-то тусуются функции InsertNamedQuery, LookupSeries, GetQuip, GetGroups
* Генерация имени файла, если попросили список не в html-формате
* Выполнение запросов поиска
* Сохранение и удаление сохранённых запросов из БД
* Запуск series
* Если сохранённый запрос не говорил нам свой формат, решаем что advanced
* Вкуривание списка колонок (длинное, тварь)
* Определение порядка сортировки
* Подсчёт сумм значений полей таймтрекинга
* Проверка доступа к багам и установка значения в implied или manual (х.з зачем нужно)
* Массовое редактирование багов, в частности сборка пересечений доступных значений полей
* Кодировка CSV (наше доработко)
 
=== Система прав ===
 
Какие в Bugzilla есть права / ограничения доступа?
 
* Права доступа к продуктам
** MANDATORY / SHOWN / DEFAULT / NA
** Entry
** Canedit
** Editcomponents
** Canconfirm
** Editbugs
* Private комментарии — видны только инсайдер-группе
* Информация о таймтрекинге — видна только группе, списывающей время
* reporter_accessible, cclist_accessible на отдельных багах
* Опциональные группы на отдельных багах
* Права на правку отдельных групп
* Права editclassifications, editcomponents, editfields, editkeywords, editusers
 
== Хорошо бы рефакторить ==
 
Что нужно рефакторить, чтобы багзилла перестала быть говном:
 
=== Внешности ===
 
* Историю изменений бага показывать прямо внутри комментов (как в trac, кстати)
* Добавить ленту обновлений по багам, поиск «последних багов», что-то типа форум-функциональности
* Добавить грид
* Необязательно — кучу действий, связанных с поиском, расположенных внизу, можно на вики-манер превратить во вкладочки
* keywords переделать в «теги»
* Заменить YUI на jQuery, форму поиска сгруппировать (но не так, как в 4.0), сделать почти все фильтры добавляемыми, добавляемыми через JS, чтобы не перезагружалась страница каждый раз
* Механизм «ограничения показа»… кастом-полей переделать в древовидную структуру
* Переделать систему прав:
*: Сейчас продукт задаёт, по сути, КНФ («группа = юзеры + набор групп; продукт = & групп»), а задавать тупо доступ ОДНОЙ группой. А группа может быть либо пересечением N других, либо объединением N других + юзеров. Причина: пересечение в реальности используется ОЧЕНЬ редко.
*: Соответственно все включения в группы сделать, чтобы материализовывались и чтобы вычислять каждый раз вычислять замыкания по наборам групп было не нужно. Это упростит и ускорит ВСЁ, в первую очередь фильтрацию.
* Документацию в вики, POD-документацию по коду туда же
 
=== Кишки ===
 
* Историю изменений по багам хранить в общей таблице с комментариями. История по другим объектам тоже хранить там же. То есть нужен такой вот общий метод хранения истории по всем сущностям.
* Переписать код отправки почты, во-первых так чтобы отправлялась она через одно место, а не через 2 (в оригинале 3) разных, во-вторых чтобы параметры формировались не через жопу.
* Добавить глобальный объект статуса, в который сохранять почту, которую нужно отправить, и сообщения, которые сейчас руками сохраняются в сессию.
* Использовать не CGI, а хеши параметров запроса, это улучшает и производительность, и переносимость, и спасает от кучи глюков, так как например, $cgi->param может вернуть как список, так и скаляр
* Использовать не кучу CGI-скриптов, а несколько (мало) точек входа и классы, всю мохнатую логику перенести в них. Не использовать модуль CGI.pm вообще (!), потому что он прости господи даже без use strict написан и порождает некоторые глюки сам по себе. В крайней форме точки доступа — это один index.cgi, позволяющий работать через CGI, один server.fcgi (FastCGI), один модуль для апача, и м.б. один для HTTP::Server::Simple. Ибо по сути, интерфейс «запроса» тривиален и не требует никакого бешеного CGI.
* Прокачать объектное ядро, чтобы 90 % полей настраивались / отключались + см. начало статьи типа ORM.
* Убрать ВСЕ строки (terms и т. п.) и описания ошибок из шаблонов и «длинного if’а», добавить отдельный уровень «локализации» / «таблицы строк», и переместить всё это в него. Потенциально также переместить туда же вообще все строки/тексты из шаблонов, для лёгкой локализации.
* Обязательно оставить совместимость с PostgreSQL, но генерилка запросов не должна на это рассчитывать и должна работать оптимальнее, чем сейчас, например, в смысле дурацких подзапросов assigned_to=(select id from profiles where login_name=?) и т. п.
* Желательно заменить Template::Toolkit на что-нибудь, хотя бы даже на моё поделие VMX::Template, чтобы не общаться с этим тормозом. Но как МИНИМУМ, даже если не заменять — убрать ВСЮ обратную связь с БД из шаблонов, ибо именно она убивает производительность в первую очередь! Ну ладно, не в первую, а во вторую, после дурацкого движка поиска.
[[Категория:Bugzilla]]

Навигация