Изменения

BugzillaORM

6871 байт добавлено, 09:09, 24 июля 2012
м
Обновление модели
[[Категория:Разработка]]
В Bugzilla половина кода в шаблонах, половина на основе полу-ORM’а Bugzilla::Object. Большая часть — говнокод. С одной стороны — ORM бы туда, было бы классно, НО! ORM мало, и нужен не он! Почти все существующие ORM-движки (кроме разве что [https://docs.djangoproject.com/en/dev/topics/db/models/ Django Models]) — это просто объектный интерфейс к базе данных. А нужно некое объектное ядро, которое бы позволяло создавать свои объекты, с полями различных типов, в том числе и ссылающимися на другие объекты, с возможностью приписывания специальных особенностей полям, с общими механизмами хранения истории, рассылки уведомлений, системой прав и с автоматическим базовым CRUD-интерфейсом.
Чем плоха текущая багзильная реализация этого «добра»?
 
Очень просто: '''почти ни хрена не настраивается''' - нельзя ни добавить свои возможности, ни отрубить ненужные встроенные. Ибо всё жёстко и криво (хардкод). А ещё:
* История хранится только для багов, но не для остальных объектов.
* Шаблоны переусложнены.
* Нет "объектов", есть «значения полей», соответсвенно, им не добавишь атрибутов и не навесишь логики.
 
* Значения кастом полей в таблице багов хранятся не ссылками по ID, а по именам, что создаёт геморрой для зависимых полей, так как чтобы точно идентифицировать значение, приходится брать ещё и значение поля, от которого оно зависит.
* «Поле» (селект и мультиселект) совмещено с объектом, соответственно, не добавишь дополнительных атрибутов объекту.* Для выпадающих списков есть как «контроль значений», так и «контроль видимости поля», что в корне '''''неверно'''''! Ибо что за бред — Типа поле скрыто, но при этом есть варианты, которые можно выбрать? Бред! Или наоборот — поле доступно, но из вариантов — только пустое значение.
* По факту, ни от чего, кроме продукта, зависимым значение не сделаешь.
* История хранится только для багов, но не для остальных объектов.
* Код полей не генерится автоматически, а ручками вписываются в шаблоны.
* На всё это навёрнута туча неструктурированного кода, определяющего поведение «встроенных» полей.
Что предлагается сделать:
* Есть объекты. У объектов есть поля (разных типов). В том числе, есть типы «multi-select» и «single-select», ссылающиеся на другие объекты.* Зависимости полей могут прописываться дополнительно, в виде ограничений вида: баг«баг.компонент.продукт == баг.продуктпродукт». Могут и не прописываться. Теоретически, могут прописываться несколько ограничений на одно поле, например, чтобы какой-нибудь атрибут зависел и от продукта, и от, скажем, операционной системы. Такое устройство наиболее гибкое и в частности позволяет багу иметь несколько полей, ссылающихся на один тип объектов.
* Поля могут скрываться в зависимости от значений других полей. Селект-поля скрываются, если в них по зависимостям нечего выбирать. На поля остальных типов можно вешать «настройку видимости», подобную текущей багзильной реализации — просто тупо «поле = одно из значений…».
* HTML-код полей должен генерироваться автоматически. Также желательна возможность задавать группировку полей в интерфейсе — например, опционально раскрываемые «Advanced Fields» (только общим fieldset’ом, а не как сейчас — просто скрытие полей в разных местах формы).
* История хранится централизованно для всех объектов.
* Общий механизм рассылки изменений по почте для всех объектов каким-либо образом «связанным» пользователям. Настройки уведомлений на уровнях: событие (изменено значение поля, добавлена сущность) и отношение (собственно связь).
* Поиск: адаптировать сильно прокачанный движок поиска из [http://wiki.4intra.net/Bugzilla4Intranet Bugzilla4Intranet]. Адаптировать долго не придётся, потому что с точки зрения read-only все типы полей останутся, по сути, те же самые.С другой стороны, его нужно обобщить, так что кое-что сделать всё-таки будет нужно. Но зато в итоге получится супер-инструмент — система выборок, которая отлично хавает большие базы, сложные ''и произвольные'' структуры запросов и не давится :) (доказано Bugzilla4Intranet)
* Права доступа: Нужна опять-таки общая схема для всех объектов, с одной стороны, простая для вычисления системой, а с другой стороны, дающая достаточную гибкость разных настроек. По всей видимости, нужны с одной стороны опять-таки «связанные» пользователи, а с другой стороны — роли. Причём, пользователи могут быть «связанные» через какое-то поле — например, человек может быть связан с багом, потому что прописан как Global Watcher для продукта этого бага. Роли могут набираться из действий над полями различных объектов и права на просмотр объектов. Возможно, нужно давать возможность разграничивать доступ на просмотр к разным полям — например, в Bugzilla только группа time-tracker’ов может посмотреть информацию о рабочем времени.
Таким образом наш трекер превратится, по сути, в модульное приложение, построенное вокруг очень прокачанного автоинтерфейса полей и объектов. Естественно, это уже не Bugzilla ни разу, но зато чем-то похоже на [http://roundup.sourceforge.net/ Roundup] — «конструктор трекеров». Однако и с ним различий много — много — roundup не умеет зависимых селект-полей, модель задаётся в коде, права доступа слабые, поиск слабый. === Обновление модели === Обновление базы багзильское (тупая последовательность операций):* (+) Очевидный порядок обновлений, нет проблем с их зависимостями друг от друга (новые просто дописываются в конец, порядок всегда правильный)* (-) Не проверяется, корректна ли схема БД после обновлений* (-) Обновления задаются именно для SQL БД, а не для метамодели* (-) Не очень красивая портянка в функции обновления БД Обновление базы наше:* AddType -> RenameFields -> AddFields -> ChangeFields -> DropFields* ChangeFields с помощью функций обновления* (???) Самый интересный вопрос - как сделать функции обновления не на SQL, в условиях когда модель в неконсистентном и вообще не знает, в каком состоянии?* После каждого шага запуск хука* Переименования задаются декларативно* Возможность Dry Run, просмотра и проверки последовательности обновлений* Зависимости обновлений в рамках каждого шага можно задать декларативно (хотя ситуация редкая)*: А может, просто стоит задавать их в ассоциативном массиве по порядку* Ещё может быть, что обновление одного типа зависит от обновления другого (причём это уже более частая ситуация) === Модель === Получается, что ядро модели состоит из следующих таблиц:* Типы объектов** Название типа** Дополнительное поведение типа* Поля** Ссылка на объект** ID поля** Название поля** Тип поля** Nullable? Т.е. разрешено ли пустое значение** Поле этого же объекта, контролирующее видимость данного (для не-select полей)** Связи поля (для select-полей)** Дополнительное поведение поля* Контроль видимости полей** Ссылка на поле** ID объекта, для которого оно видно* Транзакции (группы изменений)** Момент времени** Изменивший пользователь* История изменений** Ссылка на транзакцию** Тип объекта** Ссылка на объект** Ссылка на поле (кроме добавления объекта)** Старое значение** Новое значение* Один неудаляемый тип — пользователи (их поля, тем не менее, можно менять)* Связи объектов с пользователями** ID связи** Название связи** Ссылка на объект** Цепочка свойств, заканчивающаяся объектом «пользователь»* Пользовательские настройки оповещений** Ссылка на пользователя (либо пустая для настроек по умолчанию)** Ссылка на связь** Тип события: добавление/удаление/изменение** Ссылка на поле объекта (может быть пустая)* Роли (или группы, что примерно то же самое)** Включаемые роли** Включаемые разрешения* Разрешения (из которых состоят роли)** Ссылка на связь** Тип разрешения: просмотр/создание/удаление/изменение** Ссылка на поле объекта (пустая = весь объект)** Ссылка на значение поля (пустая = любое) === Типы полей === <tab sep="bar" class="wikitable" head="top">Тип | Параметры | ПредставленияСтрока | Длина | Input, textarea, rich editЛогический | | ФлажокЧисловой | Точность (M.N) | InputДата и/или время | Дата? Время? | Поле со всплывающим календарём, просто календарь, просто полеФайл | | Поле загрузки файлаSingle-select | Тип объекта | Радиобатон, HTML-селектMulti-select | Тип объекта | HTML-мультиселект, флажки, комбо-бокс</tab>
== Текущее состояние ==
** Canconfirm
** Editbugs
* Private комментарии — комментарии — видны только инсайдер-группе* Информация о таймтрекинге — таймтрекинге — видна только группе, списывающей время
* reporter_accessible, cclist_accessible на отдельных багах
* Опциональные группы на отдельных багах
* Права на правку отдельных групп
* Права editclassifications, editcomponents, editfields, editkeywords, editusers
 
=== Настройки оповещений о багах ===
 
Отношения:
* Assignee, QA, Reporter, CC
* Requestee или Setter флага (реально в Bugzilla прикручено сильно сбоку)
* По идее — также создатель аттачмента, коммента (если разрешать править)
* Watcher указанного выше
* Global Watcher
 
События:
* Добавлен/удалён из указанного выше
* Изменено одно из полей бага (м.б отдельные настройки, м.б вместе)
* Баг / блокирующий баг меняет статус с закрытого на открытый или обратно
* «Но кроме» UNCONFIRMED
* «Но кроме» своих изменений
== Что не так? ==
* Обязательно оставить совместимость с PostgreSQL, но генерилка запросов не должна на это рассчитывать и должна работать оптимальнее, чем сейчас, например, в смысле дурацких подзапросов assigned_to=(select id from profiles where login_name=?) и т. п.
* Желательно заменить Template::Toolkit на что-нибудь, хотя бы даже на моё поделие VMX::Template, чтобы не общаться с этим тормозом. Но как МИНИМУМ, даже если не заменять — убрать ВСЮ обратную связь с БД из шаблонов, ибо именно она убивает производительность в первую очередь! Ну ладно, не в первую, а во вторую, после дурацкого движка поиска. Хотя это и будет уже не MVC, а MVP :)
 
[[Категория:Bugzilla]]