Все примеры ниже — специфичные и подойдут не каждому, они построены в основном на продуктах Mindbox «Рассылки» и «Программа лояльности». Продукты помогают нашим клиентам запускать автоматические рассылки по триггерам (действиям или событиям), чтобы не спамить пользователей, выдавать промокоды и выстраивать бонусные системы. Если поймете, что чек-лист полезен, можете заменить примеры на свои и использовать.
Ниже подробнее о том, как сделать качественный грум:
- цель грума,
- необходимый минимум,
- уточнение требований и контекста,
- типичные этапы,
- особенности при доработке механик.
Цель грума
Цель грума — провалидировать решение с командой перед тем, как брать задачу в работу. Для этого нужно:
- снять технические риски,
- уточнить требования,
- разбить грум на небольшие части, которые можно ревьюить и мержить отдельно,
- уточнить оценку задачи,
- сохранить информацию о решении и его мотивации.
Необходимый минимум
Контекст
Зачем задача нужна бизнесу:
- какую потребность бизнеса решает,
- какие сервисы затрагивает,
- как реализовано сейчас и что меняем.
Плохо | Чуть лучше | Хорошо |
Делаем SentMailingConnectedEntitiesContext , храним в нем датапарты с идентификаторами сущностей |
Для бизнеса важно иметь связь рассылки с заказом и, возможно, другими сущностями | Кейс: в саппорт звонит пользователь и говорит, что ему не пришло письмо про заказ. Задача: иметь возможность быстро найти в админке рассылки, которые связаны с заказом |
Список этапов
Краткое описание этапов реализации — минимум по одному предложению на каждый этап. Желательно, чтобы каждый этап можно было ревьюить и мержить отдельно. При этом этапы нужно добавлять по необходимости и не пытаться во всех задачах разгрумить все аспекты.
Плохо | Хорошо |
Добавляем сохранение связи рассылки и заказа в триггеры и операции |
|
Приемочные критерии
Недвусмысленное описание того, как должна работать система по завершении задачи.
Плохо | Чуть лучше | Хорошо |
Привязывать сущность при отправке рассылки сразу при срабатывании триггера или вызове операции | В тестах при отправке рассылка связывается с тестовой сущностью. Принимает программист. Плюс всю задачу можно принимать на тесте при простой отправке |
При отправке письма о заказе из триггера или операции можем отфильтровать все действия рассылки с помощью фильтра по ID рассылки |
Уточнение требований и контекста
Валидация проблемы
Какую проблему решаем? Точно ли нужно ее решать именно так? Не нужно ли более общее решение?
Консистентность системы
Не позволяем ли мы создавать один и тот же функционал двумя способами без особых на то причин?
Пример, как не надо. Обычно все страницы списков сущностей стандартные и в них используется стандартный контрол фильтра для поиска. При этом на странице проблем нет стандартной подгрузки батчами и контрола фильтра, потому что ПО решил, что нужен другой UX. В результате написали кастомный код, еще и страница тормозит:
Страница проблем в админке Mindbox. Фильтр не такой, как на других страницах, в нем всего один параметр — статус проблемы
Сценарии приемки
Как проверить, что приемочные критерии выполнены?
Плохо | Чуть лучше | Хорошо |
В задаче со сложной приемкой отсутствуют критерии | Проверяем работу фильтра после отправки письма | Кейс 1:
Кейс 2:
|
BDD-тест (behavior driven development)
В задаче сложная бизнес-логика с большим количеством неочевидных сценариев? Если да, нужен BDD-тест.
При этом нужно учесть, что мы пишем тесты в коде, — у бизнес-аналитика нет фреймворка для тестов.
Примеры, когда понадобилась детальная подготовка тестовых сценариев от бизнес-аналитика:
Кейсы дедубликации и безопасности операций
Кейсы фильтров по времени относительно текущего из контекста
Фича-тоггл
Как тестировать новые изменения на части клиентов: с помощью фичи-тоггла или другим способом?
Плохо | Хорошо |
Делаем без фичи-тоггла, выкладываем код на продакшен. Там дурацкая ошибка, и сервис падает на всех клиентах в «канареечном» окружении. Приходится откатывать и блокировать пайплайн | Делаем под фичей; включаем на одном клиенте в бете; видим, что не работает; выключаем фичу и спокойно чиним |
Объем железа
Начинаем ли хранить терабайты новых данных или расходовать много CPU? Если да, то нужно обновить модель железа.
Плохо | Хорошо |
Строим новый индекс на большой таблице, никого не предупредив | При добавлении новых таблиц оцениваем их размер. Если он большой, разбираемся, есть ли столько места и как его выделить |
Поведение в случае отказов
Как ведем себя в случае отказов, если сервис недоступен, LRT лежал, был регулярный даунтайм БД?
LRT (long running task) — обработчик фоновых задач.
Плохо | Хорошо |
Описываем этап задачи, который обрабатывает записи с текущей минуты. Если LRT не работал какое-то время, часть периода остается непокрытой | Описываем этап задачи, который сохраняет (например, в свои настройки) информацию, за какой период он обработал данные. Неважно, когда он запустится в следующий раз, но продолжит обработку он с нужного времени |
Проблемы
Нужно ли заводить проблемы в каком-то из сценариев?
Под проблемами мы понимаем сообщения для клиентов о том, что какие-то автоматические механики в админке работают неправильно, в чем ошибка и как ее исправить. Например:
- настроена автоматическая выдача промокодов, а промокоды в пуле закончились;
- настроено списание бонусов по событию, а у клиента нет баллов, и баланс станет отрицательным;
- в шаблоне письма что-нибудь делим на количество заказов, а заказов ноль — получается, что делим на ноль.
Плохо | Чуть лучше | Хорошо |
Клиент криво настроил триггер, в нем падает отправка письма и заводится баг на разработчика. Это отвлекает разработчика и заставляет связываться с клиентом через менеджеров и поддержку | Клиент криво настроил триггер, в нем падает отправка письма и заводится проблема на рассылку с текстом, который придумал программист. Клиенту приходит об этом письмо на почту, он сам не может разобраться в том, что произошло, и обращается в поддержку | Клиент криво настроил триггер, в нем падает отправка письма и заводится проблема на этот триггер с текстом, который придумал ПО. Клиенту приходит об этом письмо на почту, он сам разбирается со своим триггером и никого не отвлекает |
Ограничение доступа
Какие должны быть ограничения доступа: пермиссии персонала, авторизация?
Плохо | Хорошо |
Любой младший маркетолог клиента, который отправляет массовые рассылки, может зайти на страницу точек интеграции и посмотреть секретные ключи для вызовов сервисов | Страница интеграций закрыта пермиссией «Просмотр точек интеграции», которая выдается только доверенному персоналу |
Типичные этапы
Two-phase-миграция
Как именно будет происходить миграция: изменения в базе данных, контрактах сервисов, наборе топиков Kafka? Не сломается ли обратная совместимость?
Плохо | Хорошо |
Из сущности «Персонал» договорились удалить «Тип персонала», так как теперь у всех один тип и этот функционал больше не используется. Удаляем свойство из сущности и сразу пишем скрипт, удаляющий колонку.
Почему это плохо: при деплое миграция базы может произойти раньше, чем деплой нового кода. Старому коду будет не хватать этой колонки, и он упадет. |
Удаляем свойство из сущности, мержим и ждем, когда этот код окажется на всех проектах. После этого пишем скрипт, удаляющий колонку. |
Обнаружили ошибку в контракте: при передаче суммы изменения баланса возвращаем <bBalanceChangesSum>650<bBalanceChangesSum/> Исправляем ошибку и возвращаем узел <balanceChangesSum>650<balanceChangesSum/> |
Исправляем ошибку, возвращаем два узла:
Ждем, когда все клиенты перейдут на новый узел, удаляем его. |
UI и бэкенд
Отдельно ли редактируем метаданные и рантайм, который их использует? Стандартный пример задачи на блоки в сценариях: UI, бэкенд для UI, рантайм — все отдельно.
Примеры подэпиков в эпике сценариев:
Нагрузочные тесты
Нужны ли нагрузочные тесты? Какой риск хотим снять, используя нагрузочный тест?
Метрики, алерты, хартбит
Какие метрики используем?
Плохо | Чуть лучше | Хорошо |
Описание этапа подготовлено без метрик | В описании этапа рассказано, какие метрики было бы интересно репортить | В описании этапа расписано, какие метрики было бы интересно репортить, какие алерты на них можно построить и какой примерный текст ранбука ожидается |
Описание этапов
Место для начала и копипасты
Только если другие члены команды плохо знакомы с этой частью кода.
Плохо | Хорошо |
Добавляем SentMailingConnectedEntitiesContext , который умеет связывать сущности с отправленной рассылкой |
Добавляем SentMailingConnectedEntitiesContext, который умеет связывать сущности с отправленной рассылкой. Сама отправка и привязка должна происходить в MailingProtocol'3.SendInterna l, куда нужно пробрасывать SentMailingConnectedEntitiesContext |
Нюансы реализации
Только важные и неочевидные, не надо расписывать «до бетона» реализацию каждого класса.
Плохо | Хорошо |
Добавляем SentMailingConnectedEntitiesContext , который умеет связывать сущности с отправленной рассылкой. Много текста с подробностями реализации |
Добавляем SentMailingConnectedEntitiesContext , который умеет связывать сущности с отправленной рассылкой.
Чтобы привязать все контекстные сущности к рассылке, можно сделать в нем метод |
Тест-кейсы
Только важные и неочевидные. Полный список нужных тестов описывать не надо — его можно окончательно составить только в процессе реализации.
Плохо | Хорошо |
Сложная задача, в которой не написано, какие тесты можно написать хотя бы от бизнеса.
Несложная задача, в которой детально расписаны все возможные тест-кейсы, которые могут появиться |
Описаны базовые тест-кейсы, которые точно должны выполняться. См. пример ниже |
Пример, как надо. Несколько кейсов при отложенной отправке:
Интерфейсы классов или контрактов сервисов
Только важные и неочевидные, которые хочется обсудить перед реализацией.
Плохо | Хорошо |
Несколько задач, в каждой не указаны контракты. При разработке людям нужно синхронизироваться по этим контрактам самостоятельно, и если они забудут, придется решать эту проблему при интеграции | См. пример ниже |
Пример, как надо. Классы, их взаимодействие и интерфейсы при привязке заказов к рассылкам:
Схема данных в БД
В том числе — какие нужны индексы и типы полей.
Пример. Этап задачи о модели связи заказа с рассылкой:
Этап, после которого можно мержить код
Важно грумить так, чтобы задачи можно было ревьюить небольшими частями. +300 строк — норм, +1500 — нет.
Пример. В каждой задаче о новом виде проблемы написано, что можно мержить отдельно:
Гарантия консистентности при параллельных запросах
Плохо | Хорошо |
Человек с сайта быстро отправляет два запроса на списание баллов так, что они обрабатываются одновременно, а не последовательно, и уходит в отрицательный баланс | Кейс параллельного списания баллов рассмотрели в задаче и объяснили, как не допускать такой ситуации |
Особенности при доработке механик
Этот блок — специфика Mindbox, но может пригодиться тем, кто работает над созданием админок.
Новые поля
Новые поля должны валидироваться, экспортироваться, импортироваться, фильтроваться, отображаться в UI, логироваться и копироваться.
Новая сущность и связь
Новая сущность должна синхронизироваться с сервисом зависимостей, а новая связь — отправляться в сервис зависимостей.
Авторы
Тёма Рудневский, разработчик, техлид
Николай Андрейчук, разработчик, техлид
ссылка на оригинал статьи https://habr.com/ru/articles/581864/
Добавить комментарий