Изменения

BugzillaORM

39 797 байтов добавлено, 09:09, 24 июля 2012
м
Обновление модели
[[Категория:Разработка]]В Bugzilla (например, 3.6) половина кода в шаблонах, половина на основе полу-ORM’а, а большая часть не пойми какBugzilla::Object. А Большая часть — говнокод. С одной стороны — ORM бы туда, было бы классно, НО! ORM мало, и нужен не он! Почти все существующие ORM-движки (кроме разве что[https://docs.djangoproject.com/en/dev/topics/db/models/ Django Models]) — это просто объектный интерфейс к базе данных. А нужно некое объектное ядро, которое бы позволяло создавать свои объекты, с полями различных типов, в том числе и ссылающимися на другие объекты, с возможностью приписывания специальных особенностей полям, с общими механизмами хранения истории, рассылки уведомлений, системой прав и с автоматическим базовым CRUD-то интерфейсом. == Идеи по созданию объектного ядра == === Объекты в духе:Bugzilla ===
Есть сущности:
* баг
* классификация, продукт, компонент
* тег (ключевое слово/ keyword), milestone, версия, статус бага, agreement (кастомное поле!пример кастомного поля)
* вложение, комментарий, флаг, тип флага
* пользователь, группа
* как ни странно, «сущность» — «метакласс» (класс если таки будет ядро — ещё появляется метакласс сущности), объекты которого описывают типы сущностей
У сущностей <graph>digraph G { Классификация -> Продукт -> Компонент -> Баг; Продукт -> Версия -> Баг; Продукт -> Milestone -> Баг; Продукт -> Agreement -> Баг; Продукт -> Тег; Продукт -> "Тип флага" -> Флаг; Статус -> Баг; Баг -> Коммент; Баг -> Вложение; Баг -> Флаг; Баг -> Тег [dir=both, color=blue]; Баг [shape=box, style=filled, fillcolor="#ffe0e0"]; Продукт [shape=box];}</graph> Причём, понятное дело, если баг принадлежит к некоторому продукту (через компонент), то и его версия, milestone, agreement должны принадлежать к тому же продукту. Сейчас в Bugzilla это реализуется так — для каждой сущности, связанной с багом, в баге есть«поле», а для ограничения значений полей поля делаются «зависимыми» от других полей. Из-за этого там куча костылей и, по сути, повесить зависимость на отличное от поля «продукт» поле невозможно. === Минусы текущей реализации === Чем плоха текущая багзильная реализация этого «добра»? Очень просто: '''почти ни хрена не настраивается''' - нельзя ни добавить свои возможности, ни отрубить ненужные встроенные. Ибо всё жёстко и криво (хардкод). А ещё:* ID — первичный ключИстория хранится только для багов, но не для остальных объектов.* атрибутыШаблоны переусложнены.* ссылка на контролирующую сущность (тип + Нет "объектов", есть «значения полей», соответсвенно, им не добавишь атрибутов и не навесишь логики. * Значения кастом полей в таблице багов хранятся не ссылками по ID, а по именам, что создаёт геморрой для зависимых полей, так как чтобы точно идентифицировать значение, приходится брать ещё и значение поля, от которого оно зависит.* Для выпадающих списков есть как «контроль значений», так и «контроль видимости поля», что в корне '''''неверно'''''! Типа поле скрыто, но при этом есть варианты, которые можно выбрать? Бред! Или наоборот — поле доступно, но из вариантов — только пустое значение.* По факту, ни от чего, кроме продукта, зависимым значение не сделаешь.* Код полей не генерится автоматически, а ручками вписываются в шаблоны.* На всё это навёрнута туча неструктурированного кода, определяющего поведение «встроенных» полей. === Проект супер-объектного-ядра === Что предлагается сделать:* Есть объекты. У объектов есть поля (разных типов) <br /> то . В том числе, есть типы «multi-select» и «single-select», ссылающиеся на другие объекты.* Зависимости полей могут прописываться дополнительно, в виде ограничений вида: «баг.компонент.продукт == баг.продукт». Могут и не прописываться. Теоретически, могут прописываться несколько ограничений на одно поле, например, чтобы какой-нибудь атрибут зависел и от продукта, и от, скажем, операционной системы. Такое устройство наиболее гибкое и в частности позволяет багу иметь несколько полей, ссылающихся на один тип объектов.* Поля могут скрываться в зависимости от значений других полей. Селект-поля скрываются, если другая сущность ссылается в них по зависимостям нечего выбирать. На поля остальных типов можно вешать «настройку видимости», подобную текущей багзильной реализации — просто тупо «поле = одно из значений…».* HTML-код полей должен генерироваться автоматически. Также желательна возможность задавать группировку полей в интерфейсе — например, опционально раскрываемые «Advanced Fields» (только общим fieldset’ом, а не как сейчас — просто скрытие полей в разных местах формы).* На поля можно назначить дополнительные обработчики, задающие более хитрое поведение. Сами обработчики пишутся в коде, по возможности — максимально абстрагированно от конкретного поля. Назначаться они при этом должны не из кода, а из интерфейса конфигурации модели. На этих дополнительных обработчиках должно работать всё! Примеры:** Платформа, ОС: функции угадывания значения по умолчанию на этуоснове заголовков запроса.** Статус: есть ограничения переходов из состояния в состояние (workflow). Возможно, другим полем она должна ссылаться его нужно попытаться вынести в базовые настройки модели.** CC: специальное поведение при клонировании, смене Assignee и QA (старые добавляются в CC), специальное «значение по умолчанию», зависящее от компонента. Возможно, зависимые значения по умолчанию стоит как-то протащить в общее ядро, но это чуть более тонкий момент, чем всё остальное.** Keywords/теги: автосоздание новых значений.* История хранится централизованно для всех объектов.* Общий механизм рассылки изменений по почте для всех объектов каким-либо образом «связанным» пользователям. Настройки уведомлений на контролирующуюуровнях: событие (изменено значение поля, добавлена сущность) и отношение (собственно связь).* способ преобразования Поиск: адаптировать сильно прокачанный движок поиска из [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> == Текущее состояние == Базовые поля (то, чего не быть логически не может) :* Объект, баг, пользователь, группа, комментарий к группам пользователейбагу.* Продукт имеет специальный смысл — разграничение прав. Поэтому он тоже обязателен. У каждого поля есть:* Тип* Значение по умолчанию* Вид показа в интерфейсе (по умолчанию?)* Копируется ли значение атрибута при клонировании* Показывается ли атрибут в форме создания* Ссылка на контролирующий атрибут того же объекта, что и этот, и на его значения*: Если выбрано, означает, что атрибут показывается, только если другой атрибут той же сущности, которой принадлежит этот, имеет одно из заданных значений
Типы атрибутов:
* {{ok}} Строка
* Boolean
* Decimal{{ok}} Десятичное число
* Дата
* Время
* {{ok}} Дата+время* Файл (вложение)
* Single-Select &rarr; ссылка на сущность (то есть «многие к 1»)
** ''Необязательный вариант синглселекта — «1 к 1».''
* Multi-Select &rarr; ссылка на несколько сущностей одного типа (то есть «многие ко многим»)
** Атрибут атрибута — в каком виде показывать список Два способа показа — поле со списком (если в коде/шаблонах не задано специального поведениякомбобокс)., или мультиселект** Вариант мультиселекта — «список подчинённых» (то есть 1 ко многим). Например, список аттачментов багаСписок тегов, список комментов к багу.с автодобавлением значений
У всех атрибутов тоже есть ссылка на контролирующую сущность, означающая, что атрибут показывается, только если его сущность ссылается на его контролирующую сущность (или одну из них).== Существующие поля ==
=== Поля багов:=== Поля багов перечислены ниже. Жирное «да» в колонке «можно отключить» означает, что отключать можно уже сейчас (скорее всего, через параметры типа usevotes и т. п.). Нежирное «да» в колонках «можно отключить» и «можно менять тип» означают, что чисто теоретически логика работы Bugzilla это позволяет.
<tab sep=bar class=simpletable head=topleft>
поле | тип | можно отключить? | можно менять тип? | примечанияshort_desc | строка | нет | нет |classification | single-select | '''да''' | нет |product | single-select | да | нет | контролируется classification (или никем), у поля есть привязка к правам пользователяcomponent | single-select | да | нет | контролируется productversion | single-select | да | да | контролируется product, если тип = single-select. значение по умолчанию контролируется componentrep_platform | single-select | '''да''' | да | специальная функция «угадывания» дефолтного значенияbug_file_loc | строка | да | да |op_sys | single-select | '''да''' | да | специальная функция «угадывания» дефолтного значенияbug_status | single-select | нет | нет | есть функция валидации (Bug Status Workflow)resolution | single-select | да | нет | у атрибута есть контролирующая видимость сущность (показывается только при bug_status.closed=1)status_whiteboard | строка | да | да |keywords | multi-select | да | да | показ в виде спискаbug_severity | single-select | да | нет |priority | single-select | да | да | есть желание сделать decimalassigned_to | single-select | показ в виде select’а или строки, есть функция валидации (угадывания юзера нет | нет | ссылка на пользователя. значение по некорректному имени)умолчанию контролируется componentreporter | single-select | показ в виде select’а или строки, есть функция валидации (угадывания юзера по некорректному имени)нет | нет | ссылка на пользователяqa_contact | single-select | показ в виде select’а или строки, есть функция валидации (угадывания юзера '''да''' | нет | ссылка на пользователя. значение по некорректному имени)умолчанию контролируется componentvotes | decimal(,0) | '''да''' | нет |cc | multi-select | показ в виде combo-box’а, есть функция валидации (угадывания юзера да | нет | ссылка на пользователей. значение по некорректному имени)умолчанию контролируется componentdependson | multi-select | да | нет | ссылка на баги. показ в виде спискаblocked | multi-select | да | нет | ссылка на баги. показ в виде спискаtarget_milestone | строка single-select |да | да | контролируется product, если тип = single-selectsee_also | multi-select | да | да | ссылка на баги. показ в виде списка (багов), если тип = single-selectalias | строка | '''да''' | да |reporter_accessible | boolean | нет | нет |cclist_accessible | boolean | нет | нет |estimated_time | время | '''да''' | нет |remaining_time | время | '''да''' | нет |deadline | дата | '''да''' | нет |creation_ts | дата+время | нет | нет |delta_ts | дата+время | нет | нет |cf_agreement | single-select | '''да''' | да | контролируется product
*** нет в fielddescs *** |
lastdiffed | дата+время | нет | нет | скрыто в интерфейсеattachments | multi-select | нет | нет | 1 ко многимlongdescs | multi-select | нет | нет | 1 ко многимflags | multi-select | да | нет | 1 ко многим
</tab>
 
Примечания:
* Все поля-ссылки на пользователей показываются в виде строки либо в виде 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’а или строки, есть функция валидации (угадывания юзера по некорректному имени)
description | single-select, показ в виде select’а или строки, есть функция валидации (угадывания юзера по некорректному имени)строка
filename | строка
mimetype | строка
</tab>
[[Категория=== Поля компонентов === <tab sep=bar class=simpletable head=top>поле | тип | можно отключить? | можно менять тип? | примечанияname | строка | нет | нет |initialowner | single-select | да | нет | ссылка на пользователяinitialqacontact| single-select | да | нет | ссылка на пользователяinitialcc | multi-select | да | нет | ссылка на пользователейdefault_version | single-select | да | нет | ссылка на версиюdescription | строка | да | да |product_id | single-select | нет | нет |wiki_url | строка | да | нет |is_active | boolean | да | нет |</tab> == Из чего состоит багзилла? == === С внешней точки зрения === Крупные блоки функционала в Bugzilla с точки зрения пользователя:Разработка]] * Создание, просмотр, изменение багов, история по багу** Форматирование комментариев* Создание, просмотр, изменение вложений* Поиск багов, форма поиска* Графики одни, графики другие, Summarize Time* Исходящая почта* Входящая почта* Запросы флагов* Напоминания (whining)* Регистрация, изменение, раздача групп пользователям* Пользовательские настройки* ''XML-импорт (в полудохлом виде)''* Web-сервисы (XML-RPC, JSON-RPC)* Sanity Check* Графы и деревья зависимостей* Голосование за баги ==== Наши крупные фичи ==== * SCRUM-карточки* RSS-лента активности* XML-Simple Web-сервисы* Проверки корректности* Excel-импорт* Информер* Глобальная авторизация* Today Worktime, Super Worktime Плюс вагон и маленькая тележка мелочи. === Страница создания бага (enter_bug.cgi) === Текущая логика страницы создания бага: * выбор classification, если она включена* classification выбрана &rarr; выбор product, если он не вообще один* тот же выбор продукта/классификации при клонировании багов* продукт выбран &rarr; форма создания бага* показ корректных списков возможных значений полей:** типы флагов в зависимости от компонента** cf_agreement в зависимости от продукта** списки пользователей, относящихся к багу в combo-box’ы** опциональный запрет на ввод приоритета на основе конфигурации (letsubmitterchoosepriority)** список флажков — ограничителей доступа группами* значения полей по умолчанию:** которые совсем по умолчанию** угадывание op_sys и rep_platform на основе заголовков запроса** версия, qa_contact, assigned_to, cc по умолчанию для компонента** хитрая логика для изменения списков cc при выборе компонентов** assigned_to=ты при выборе статуса ASSIGNED** показ поля resolution при выборе закрытого статуса** версия из cookies** загруженные из шаблона ввода бага** загруженные из клонированного бага*** ссылка на старый аттач в описании нового клонированного бага*** хитрая логика для CC при клонировании багов* напоминания о вводе времени* предпросмотр комментариев* добавление ссылки на старый аттач для клонированного из коммента бага* переключатель 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 === Настройки оповещений о багах === Отношения:* Assignee, QA, Reporter, CC* Requestee или Setter флага (реально в Bugzilla прикручено сильно сбоку)* По идее — также создатель аттачмента, коммента (если разрешать править)* Watcher указанного выше* Global Watcher События:* Добавлен/удалён из указанного выше* Изменено одно из полей бага (м.б отдельные настройки, м.б вместе)* Баг / блокирующий баг меняет статус с закрытого на открытый или обратно* «Но кроме» UNCONFIRMED* «Но кроме» своих изменений == Что не так? == Что в Bugzilla не так? Что нужно поменять, чтобы она перестала быть говном? Да, я знаю, что почти всё, но дело не в этом — дело в том, что создавать систему «от противного» — есть хороший тон, ведущий к прогрессу. === Ядро === Самое жирное «не так» в Bugzilla — это слабость ядра. Если бы ядро было прокачанным, как в начале статьи, оно бы заменило: * Custom Fields, то есть, управление полями багов.* Отключение стандартных полей типа OS, Hardware.* Добавление спецполей в продукты, компоненты и т. д. — сейчас это делается в коде.* Версионирование всех объектов. История бы хранилась унифицированно. Не было бы отдельно таблиц bugs_activity и longdescs, соответственно не было бы и тормозов при проверке «Only bugs changed between…» либо комментарии бы дублировались в bugs_activity (логичнее)* Отправка почты, которая сейчас отправляется через 2 разных места.* Простые интерфейсы типа CRUD (Create/Read/Update/Delete), сейчас созданные непонятно каким копипастом. В основном имеется ввиду админка.* Система прав стала бы и проще (по сравнению с хрен-пойми-системой Mandatory/Default/Shown/NA), и имела бы больше возможностей.* Валидаторы и подсказки значений.* Корректная валидация зависимостей полей друг от друга.* Часть SQL-запросов, написанных ручками в коде.* Вся логика постановки/обновления багов из process_bug и post_bug, дублированная сейчас в обработке входящих e-mailов и Excel-импорте* Даже Excel- и XML-импорт, причём импортировать можно было бы вообще всё что угодно. Появились бы дополнительные возможности: * Создание новых объектов типа SCRUM карточек.* Изменение типов стандартных полей типа целочисленных приоритетов.* Можно было бы прикрутить статистику по любым объектам, причём с Time Machine, то есть просмотром статистики за любой прошедший момент времени. :) === Внешности === * Большая часть интерфейсов нуждается в полной переделке. Например:** На форме бага «Show Advanced Fields» должно быть сделано отдельной группкой полей (fieldset), а не скрытием полей прямо посреди формы в разных местах (пугает).** Страница настройки прав продукта — мегастрёмная. Таблица с группами там на хрен не нужна никому вообще.** Частично относится к ядру, но — интерфейс редактирования «контроля значений» кастом-полей это сейчас полная жесть — например, нельзя посмотреть список значений кастом поля для конкретного продукта (от которого зависят наборы значений).* Историю изменений бага показывать вперемешку с комментариями к багу (а-ля Trac). Туда же можно заинтегрировать и замешать коммиты из системы контроля версий.* Добавить ленту обновлений по багам, поиск «последних багов», что-то типа форум-функциональности.* Возможно, добавить Grid View с возможностью массовых обновлений в поиске.* Отрефакторить кучу действий, связанных с поиском, расположенных под списком багов.* Keywords переделать в «теги», то есть, сделать, чтобы они сами заводились новые.* <s>Заменить YUI на jQuery</s> в Bugzilla4Intranet уже, форму поиска сгруппировать (но не так, как в 4.0), сделать почти все фильтры добавляемыми, добавляемыми через JS, чтобы не перезагружалась страница каждый раз* Документацию «насытить» в вики, POD-документацию по коду туда же. === Кишки, кроме ядра === * Добавить глобальный объект статуса, в который сохранять почту, которую нужно отправить, и сообщения, которые сейчас руками сохраняются в сессию.* Использовать не CGI, а хеши параметров запроса, это улучшает и производительность, и переносимость, и спасает от кучи глюков, так как например, $cgi->param может вернуть как список, так и скаляр* Использовать не кучу CGI-скриптов, а несколько (мало) точек входа и классы, всю мохнатую логику перенести в них. Не использовать модуль CGI.pm вообще (!), потому что он прости господи даже без use strict написан и порождает некоторые глюки сам по себе. В крайней форме точки доступа — это один index.cgi, позволяющий работать через CGI, один server.fcgi (FastCGI), один модуль для апача, и м.б. один для HTTP::Server::Simple. Ибо по сути, интерфейс «запроса» тривиален и не требует никакого бешеного CGI.* Убрать ВСЕ строки (terms и т. п.) и описания ошибок из шаблонов и «длинного if’а», добавить отдельный уровень «локализации» / «таблицы строк», и переместить всё это в него. Потенциально также переместить туда же вообще все строки/тексты из шаблонов, для лёгкой локализации.* Обязательно оставить совместимость с PostgreSQL, но генерилка запросов не должна на это рассчитывать и должна работать оптимальнее, чем сейчас, например, в смысле дурацких подзапросов assigned_to=(select id from profiles where login_name=?) и т. п.* Желательно заменить Template::Toolkit на что-нибудь, хотя бы даже на моё поделие VMX::Template, чтобы не общаться с этим тормозом. Но как МИНИМУМ, даже если не заменять — убрать ВСЮ обратную связь с БД из шаблонов, ибо именно она убивает производительность в первую очередь! Ну ладно, не в первую, а во вторую, после дурацкого движка поиска. Хотя это и будет уже не MVC, а MVP :)