Дублирующиеся запросы: объединение без потери голоса
5 мин чтения
Три клиентки просят одну и ту же возможность в три разные недели, сформулированную тремя разными способами, и процесс триажа, построенный ловить дубли, делает свою работу: группирует их, считает как один запрос с тремя голосами, и бэклог остаётся чистым. Это лёгкая часть. Какие метки того стоят разбирает группировку по базовой возможности перед триажем по формулировке как механическое решение для дублей; чего не разбирает — что происходит со словами самими по себе, как только три запроса становятся одной строкой, и эта потеря обычно больше проблемы подсчёта дублей, которую она решила.
Что реально теряется, когда дубли объединяются?
Конкретная формулировка, которую использовала каждая просительница, часто более информативная, чем счёт голосов, в который она схлопывается. Одна клиентка может попросить «способ экспортировать отфильтрованные результаты», другая «экспорт CSV, уважающий мои сохранённые фильтры», а третья «экспорт без скрытых колонок». Все три — один и тот же базовый запрос, правильно сгруппированный, но каждая формулировка несёт слегка иной акцент на том, что важно этому человеку, и объединение, сохраняющее только формулировку первой подачи, полностью отбрасывает две другие. Счёт выживает; текстура, которая помогла бы кому-то построить правильную версию функции, нет.
Почему текстура важна, если счёт голосов уже говорит, что спрос существует?
Потому что спрос и дизайн — разные вопросы, и только конкретная формулировка отвечает на второй. Десять голосов за «экспорт» говорят команде, что функцию стоит строить; они ничего не говорят о том, означает ли «экспорт» CSV, PDF, запланированное письмо или endpoint API, и объединение, отбрасывающее девять из десяти оригинальных подач в пользу формулировки первой, может тихо сузить спецификацию до того, что случайно попросила первая просительница, даже если остальные девять хотели чего-то тонко отличающегося. Что на самом деле должен фиксировать запрос на функцию разбирает именно этот пробел со стороны приёма; объединение дублей — это место, где он снова всплывает после приёма, ровно в той точке, где команде больше всего нужен диапазон того, что действительно просили.
Как выглядит процесс объединения, сохраняющий формулировку вместо того, чтобы её отбрасывать?
Добавление вместо замены. Канонический элемент сохраняет один заголовок для вида бэклога, но оригинальная формулировка каждой объединённой подачи остаётся прикреплённой к нему, либо как список цитат, либо как связанные исходные тикеты, так что любой, кто позже просматривает элемент, может увидеть реальный диапазон того, что просили люди, вместо резюме одного члена команды. Это стоит почти ничего построить, поле в тикете вместо новой системы, и это разница между объединением, сжимающим информацию, и тем, что сжимает только её отображение.
Функция: Отфильтрованный экспорт CSV
Голоса: 12
Объединённые запросы:
- «способ экспортировать отфильтрованные результаты» (acct_4421)
- «экспорт CSV, уважающий мои сохранённые фильтры» (acct_8832)
- «экспорт без скрытых колонок» (acct_1097)
...
Заслуживает ли каждый дубль объединения, или бывают ложные совпадения?
Некоторые — ложные совпадения, и обращение с «звучит похоже» как с «это тот же запрос» — свой собственный режим отказа. «Дайте мне экспортировать мои данные» и «дайте мне экспортировать только отфильтрованный вид» могут быть сгруппированы совпадением ключевого слова на «экспорт», хотя на самом деле описывают два разных объёма одной и той же общей возможности; объединение их либо раздувает счёт голосов не за то, либо, хуже, доставляет более узкую версию, потому что она случайно пришла первой. Человеческий проход по группировке, даже быстрый, ловит это до накопления; автоматическое совпадение по сходству само по себе переобъединит по словарю и недообъединит по намерению.
Когда проверку на дубли на самом деле стоит запускать — при приёме или позже?
И то, и другое, по разным причинам. Проверка при приёме ловит очевидный случай, новый запрос, повторяющий что-то уже открытое, ещё до того, как он станет собственной неотслеженной строкой; поиск по сходству среди открытых запросов в момент подачи закрывает большинство таких случаев без участия человека. Второй, более медленный проход позже ловит то, что упускает приём: два запроса, использовавшие достаточно разные формулировки, чтобы в момент подачи проскользнуть мимо совпадения по ключевым словам или эмбеддингам, но которые, стоит команде увидеть десяток вариаций, оказываются описанием одной и той же базовой возможности. Пропуск второго прохода оставляет почти-дубли рассеянными под отдельными заголовками бессрочно, каждый со своим маленьким счётом голосов, который никогда не складывается в число, которое довело бы дело до реализации.
Должна ли просительница знать, что её подача объединена с существующим элементом?
Да, и это та же дисциплина, что закрытие цикла обратной связи с клиентом, применённая на шаг раньше обычного: просительница, которая что-то подала и больше ничего не слышит, заключает, что её запрос никуда не привёл, даже если он был правильно объединён с элементом с одиннадцатью другими голосами, который в итоге выпустили. Короткое подтверждение, «мы объединили это с существующим запросом, который делали и другие», стоит одного сообщения и предотвращает повторную подачу клиенткой того же запроса каждые несколько месяцев, потому что у неё нет видимости, отслеживался ли он вообще на самом деле.
Меняет ли объединение, кому засчитывается заслуга, когда функция выпущена?
Должно включать всех, не только того, кто подал первым. Закрытие цикла обратной
связи разбирает уведомление просительниц, когда их желание
выпущено; для объединённого элемента это значит каждый аккаунт, привязанный к объединению, не
только тот, чья формулировка стала каноническим заголовком, потому что с точки зрения каждой
просительницы она попросила это, и это выпустили, независимо от того, чью формулировку случайно
сохранил процесс триажа. В Changeloop это значит, что pull request называет каждый связанный issue
(Fixes #142, fixes #187); issue, который он не называет, не получает комментария.
FAQ
Сколько формулировки стоит сохранять на объединённый запрос, цитату или полную ссылку на тикет? Короткой цитаты обычно достаточно для обычного случая, поскольку её цель — дать ревьюеру увидеть диапазон формулировок с одного взгляда; сохраняйте и полную ссылку на тикет, когда в оригинале был значительный дополнительный контекст, вроде скриншота или подробного описания рабочего процесса, которое однострочная цитата бы сгладила.
Делает ли сохранение формулировки каждого дубля бэклог труднее для сканирования? Нет, если это свёрнуто по умолчанию. Канонический заголовок — то, что видит бегло сканирующий ревьюер; объединённая формулировка на клик или разворот дальше, присутствует для того, кто делает более глубокое исследование, но не загромождает вид для того, кто просто считает голоса.
Что если два запроса выглядят идентичными, но оказывается, что хотят разного после постройки? Разделите их снова, как только это станет ясно, и относитесь к оригинальному объединению как к разумному решению, принятому с доступной на тот момент информацией, а не как к ошибке, повторения которой нужно избегать. Система группировки, которая никогда ничего не разъединяет, в итоге будет иметь несколько неверных объединений, навсегда запечённых.
Есть ли порог голосов, после которого объединённый запрос должен получить человеческий обзор базовой формулировки? Не фиксированное число, но любой запрос, приближающийся к решению о постройке, заслуживает этого независимо от счёта голосов, потому что это точка, где разница между «экспорт» и «экспорт как CSV с сохранёнными фильтрами» перестаёт быть нюансом и становится спецификацией.
Технические утверждения в этой статье не проходили независимую проверку. Если здесь что-то не так, сообщите нам, и мы исправим.