Как будем «лечить» падения? Синхронизация ПМ и разработчиков

Довольно стандартная история, когда продакты (я — ПМ) и разработчики предлагают разные решения проблемы — каждый видит мир по своему, и не все разработчики видят общую картину с т. з продукта и пользователя. А юзер\клиент - главное.
А у вас была такая ситуация:

  • ваше приложение или его часть падает (будь-то на тестовом стенде перед релизом или уже на проде), восстановили, но было неприятно
  • в команде появляется куча различных предложений о причинах и способах починки: от “ловить ошибку и перезгружать” до любимого разработчиками рефакторинга
  • начинаются длительные обсуждения и споры

У меня случалось, на разных продуктах и проектах, с разными командами. Споры отнимали не только время, но и внимание — за ними могли потеряться какие-то другие возможные решения. В текущем продукте у нас отличная команда. Но и здесь нужно было синхронизироваться — договориться, как все предложения по устранению падений учитывать и сравнивать друг с другом, что есть хорошее решение, что плохое.

Круто, когда все с продуктовым майндсетом, помнят про юзера, и есть описанные регламенты на все случаи жизни, но в небольших и молодых командах, как мне кажется, это не часто. Проблема в целом “по больнице” есть. Про нее и рассказываю.

Ниже покажу мою систему, по которой нам удается разложить большинство предлагаемых решений и нагенерировать новых. Применяем ее не всегда, когда присутствует здравый смысл, и всем все одинаково понятно, не стоит перегружать процессы. Система опробована в паре команд и помогла “собрать мысли”, как минимум, у некоторых ребят. Объяснять друг другу стало легче.

Возможно, мой взгляд замылен B2B продуктами, где меньше эмоциональная составляющая и выше требования к бесперебойной работе, поэтому данный подход, не факт, что ляжет в чистом виде на B2C.

Проблема глазами пользователя

Первое, о чем договорились — всегда смотреть и фиксировать проблему со стороны пользователя и его задачи — понимать “импакт” (и охват). Вроде бы очевидная вещь, но на деле инженеры не всегда уделяют задаче пользователя должное внимание — они видят, что не работает часть системы, а не то, что пользователь не достиг ожидаемого результата, стал негодовать, и его недовольству есть еще куда расти.

Абстрагироваться от юзеров и работать только по метрикам, например, uptime, retention, nps и пр. — идея не очень, как минимум для нас. Наладить трекинг uptime для каждого юзкейса\фичи — круто, но — долго и дорого. А в итоге можно иметь всего десяток перебоев по 5 минут, но недовольство от этих перебоев приведет к оттоку. На Retention, CSAT и пр. влияет еще куча факторов, и падения — далеко не основные. Но от метрик не отказываемся — с ними на уровне повыше работаем;)

Для того чтобы описывать действия и намерения пользователей, и как в них вписывается внезапная проблема, я использовал формат, похожий на job story из JTBD

Для приверженцев JTBD: это адаптация JS конкретно под описание операционной проблемы с текущим B2B решением. Желающим пообсуждать JTBD — добро пожаловать в личку;)

Как и насколько полно описывать контекст и проблему?

Настолько, на сколько нужно. Важно, чтобы все, кто вовлечен, поняли одинаково. Тут просто практика нужна, и каждая команда найдет свое “необходимо и достаточно”. Вот пару моих примеров

Проблема при подключении тарифа
Проблема при создании бота

Такой простой формат помогает увидеть проблему глазами пользователя всей команде и понять его ожидания. А если в подобном виде опишите случаи у конкурентов — сможете нагенерировать конкурентных преимуществ (почитайте про JTBD)

Мои примеры могут казаться в некотором роде странными\несогласованными, но уберите строку с проблемой (красным), и все будет четко. Без красной строки будет то, как обычно, происходит работа с текущим решением. Проблема (падение, зависание) вклинивается в работу, но не изменяет ожиданий пользователя, она же не постоянно присутствует в продукте, по крайней мере мы этого не хотим.

Не допускать проблемы или быстро чинить?

Если неполадки в работе продукта\фичи появляются часто, они становятся частью ожидаемого пользователем поведения (это конкурентный недостаток) . Плохо, если для кого-то из команды нормально, что ЦА будет сталкиваться с проблемой и сама “делать приседания” для ее решения по нашим инструкциям.

Пользователь, не должен волноваться, что что-то нехорошее может случиться с его инструментом (т. е. вашим продуктом), даже если знает, что вы быстро это почините. Он не должен ощущать проблему вообще.

Например, так можно выразить desired outcome пользователя (см JTBD) — "Свести к нулю время простоя" и "Свести к нулю мою вовлеченность в устранение проблем с инструментами и сервисами"

Позиция “наши пользователи таких проблем не наблюдают” — то, к чему надо стремиться. Какими решениями? Какие выберет ваша команда в ваших обстоятельствах. Можно починить изъяны продукта, можно оперативно отлавливать и чинить неполадки, пока пользователи не ощутили последствий, можно закрыться от внешних факторов “кладущих систему”, а можно отказаться от проблемной фичи и предложить другое решение.

Как правило, качественное решение по недопущению проблемы очень трудоемкое, а бизнес не может ждать, нужно хотя бы что-то сделать сейчас, поэтому начинать с быстрого "плохого" решения нормально. Но команда должна понимать, что в таком случае она делает неидеально для пользователя, и это решение не “навсегда”. В понимании, что такое “хорошее” и "плохое" решение с т. з пользователя, нам в командах тоже нужно было синхронизироваться (про это ближе к концу).

Раскладываем причины и следствия

Для того чтобы все в команде одинаково понимали контекст, проблему, изъяны продукта и потенциальные решения, я сделал такой шаблон в Миро. Это в т. ч. инструмент брейншторминга.

Колонка 1: Проблема и контекст пользователя

Здесь мы описываем, какая проблема произошла у пользователя, и что он при этом делал. Это — по сути первая часть из Job Story

Охват пользователей и частота возникновения данной проблемы помогают понять ее масштаб.

Колонка 2: Проблемное событие в продукте

Здесь описываем техническое событие “под капотом” продукта (видим в мониторингах), которое привело к ощутимой пользователем проблеме: завис такой-то сервис, разорвалось соединение, сервис выкидывал ошибку при выполнении такой-то задачи и т. д.

Обычно начинают разбирать проблему с одного (последнего\частого\самого критичного) события, но при брейншторминге на доску стоит нанести и прочие наблюдаемые поведения системы, которые приводят к той же проблеме с т. з пользователя. Это помогает видеть картинку шире, оценивать риски и эффективность нагенерированных решений.

В моем примере мы начали разбирать проблему, когда завис один из сервисов, но при обсуждении отметили, что есть еще одна причина аналогичного поведения продукта, с т. з пользователя

Колонка 3: Изъяны продукта

Это участок, на котором мы фиксируем и разбираем проблемы архитектуры и инфраструктуры, приводящие к проблемному событию. Для полноты картины, стоит зафиксировать не только последние, но и другие возможные изъяны, которые приводят к данному проблемному событию

В моем примере проблему с сокетами мы уже знали как устранить, потому не копали причины на этой доске. Рассматривали только зависание сервиса (часть описания изъянов архитектуры скрыты, хотя к моменту написания статьи их уже устранили)

Устранение технических изъянов продукта — как правило, рефакторинг. Это как вакцина от болезни, мы работаем над недопущением проблем.

Колонка 4: Триггеры

Важно понимать, что привело к проблеме, ведь система работала, и вдруг какой-то фактор на нее повлиял, затронул технический изъян и вызвал череду событий, которые не дали пользователю сделать то, что он хотел.

Триггер может быть "внешний" (действия какого-то пользователей, влияние внешних систем и пр.) или "внутренний" (масштабировали сервис, делался бекап, что-то не донесли с релизом и др). Триггеры помогают лучше спроектировать изменения в продукте.

В моем примере один пользователь “попал” в ранее неизвестный корнер-кейс — создал специфичную ветку сценария бота, выполнение которой “прикладывало” ключевой сервис, обеспечивающий обучение всех ботов. Мы оперативно устранили триггер — “попадания” в корнер кейс сделали невозможным на уровне функционала (например, выкинуть ошибку и не продолжать действие, приводящее к проблеме).

Недопущение триггеров само решение проблемы — нет фактора — нет последствий. Если у вас аллергия на кошек, не держите кошек.

Виды решений

Как уже подмечено выше, решать проблему можно на каждом участке. Продукт - как организм, даже методы лечения можно взять из медицины и биологии.

Участок задачи и контекста пользователя

Можно ли избавить пользователя от проблемы на этом уровне, не копая дальше? Да, можно — измените его контекст, сделайте, так, чтобы ему не нужно было делать данную задачу, но ценность он получал, не можете — дайте другое решение. И то и другое — качественные изменения вашего продукта (или новый продукт). Чем меньше пользователь тратит время на получение результата, тем лучше. Можно назвать это эволюцией продукта\пользователя.

Участок проблемного события

Восстанавливая систему, мы лечим симптомы и\или последствия, здесь нам нужно самое лучшее лекарство, оно не предотвращает болезни, но лечит ее.

Участок архитектуры и инфраструктуры

Решение архитектурных изъянов, которые влекут проблемы, это как вакцина для организма, мы прививаемся, испытываем какие-то побочные эффекты в процессе выработки иммунитета, но потом все хорошо.

Участок триггеров

Подходящий термин для недопущения триггеров — изоляция. Мы изолируем нашу систему от факторов, негативно на нее влияющих, поэтому она остается стабильной

На доске мы рассматриваем только технические причины и решения, процедурные решения в части улучшения процессов разработки (лучше тестировать, лучше проектировать, лучше описывать требования и пр.) явно не рассматриваются, но все ответственные за процессы делают выводы.

Генерация решения

Разложив все факторы на доске, мы начинаем набрасывать на стикерах возможные решения на каждом участке. Зелеными стикерами отмечаем в принципе "хорошие" решения, красными — в принципе “плохие” (желтыми — “нормальные” решение, серыми — “непонятные” — не понятны последствия или возможность реализации).

Цвета решений — как ориентир, помогают видеть и помнить, как должно и как не должно быть.

Важно понимать, что это стадия брейншторминга, а не приоритизации и планирования: здесь мы называем решения "хорошим" или "плохим" с т. з эффекта на пользователей, их desired outcomes и рисков для продукта, не обращая внимание на «цену вопроса». В расчет берутся не только пользователи с данной проблемой, а все, ибо какие-то решения могут негативно повлиять на пользователей, у которых все работает.

Т.к. на этом этапе мы не сравниваем решения друг с другом и не смотрим на стоимости их реализации, то даже самые “сумасшедшие” и мегадорогие предложения, типа “переписать все на GO” могут оказаться хорошими решением в принципе. И да, может получиться так, что все решения на отдельном участке — плохие.

Общие критерии

Я предлагаю своим командам следующие критерии хорошего решения, которые можно применить при брейншторминге (актуально для всех типов)

  • Не оказывает негативного эффекта на ЦА и SLA («ничего не ломает»)
  • Не оказывает негативного эффекта на работу продукта под ожидаемыми нагрузками
  • Не приносит новых очевидных корнер кейсов
  • Не урезает востребованный функционал продукта
  • Не несет очевидных рисков безопасности
  • Не несет очевидных юридических рисков

Почему именно "очевидные" риски и проблемы — неочевидные долго копать, не для брейншторминга. Разберемся с этим при проектировании и сравнении.

Хорошее лекарство

На сколько заморачиваться по восстановлению и устранению последствий падений? Как по мне, хорошее лекарство должно быть нацелено на все те же Desired Outomes - "Свести к нулю время простоя" и "Свести к нулю мою вовлеченность в устранение проблем с инструментами и сервисами". Если уж пользователь и заметил проблему, то нужно максимально быстро все починить, и так, чтобы п делал минимум приседаний из-за нас, а лучше вообще не делал. Грубый пример: «поднять сервис и попросить пользователя перезапустить задачу» — плохое решение, когда можно все сделать автоматически.

Я для себя выделил следующие критерии хорошего лекарства:

  • “Моментально” находит проблемное событие, как только оно случилось
  • Начинает принимать меры сразу же при обнаружении симптомов
  • Предполагает минимальное вовлечение пользователя в исправление последствий
  • Уведомляет пользователя о восстановлении и завершении его задачи (если применимо)
  • Предполагает минимальное вовлечение поддержки\разработчиков для восстановления работы (чтобы обеспечить скорость и снизить человеческий фактор)
  • Собирает статистику, достаточную для анализа причин

Хорошая вакцина

Сказать хорошее это или плохое решение по устранению технического изъяна — на откуп инженерам. Если все решения удовлетворяет общим критериям (указаны выше в статье) и приводят к стабильной работе кейса, то в контексте конкретной проблемы — они все хорошие, а какое в нашей ситуации лучше — будем сравнивать по другим параметрам (эффект на другие кейсы, стоимость создания и владения и пр.) на следующем этапе — при приоритизации и планировании

Хорошая изоляция

Нет каких-то особенных критериев, кроме общих

Хорошая эволюция

Это тема отдельной статьи, так как тут речь идет, как сделать новый продукт\сервис\фичу. В брейншторминге по падениям, мы не разбираем решения на этом участке. Это дельный процесс, к результатам которого мы прибегаем, если после оценки и проектирования у нас нет приемлемых технических решений проблемы. Иногда бывает быстрее и дешевле сделать новую фичу и выкинуть проблемную старую.

Что потом с этим делать

После того как решения сгенерированы, их можно прорабатывать, сравнивать, приоритизировать и брать в работу. При этом, как правило, к моменту брейншторминга какие-то решения из второй колонки уже реализованы (словили падение, восстановили, пошли встречаться, разбираться) .

Ярлыки "хорошее\плохое" помогают сфокусироваться над тем, что оценить и спроектировать в первую очередь. Сначала сравниваем грубые оценки и эффекты хороших решений, если что-то не устраивает (стоимость, сроки, риски) — заглядываем в “наименее плохие”, и потом все глубже.

Реализовав хорошие решения, мы «забываем» о проблеме.

Реализовав плохие — мы остаемся в долгу — где-то пользователю все еще не хорошо. Мы должны понимать, что это временно, и создать в беклоге задачи на устранение недостатков.

Откуда берутся такие долги и зачем нам их закрывать — это должны осознавать все члены команды, чтобы быть на одной волне, понимать что и зачем мы делаем. Описанная в статье система помогала мне этого достичь.

Надеюсь, кому-то будет полезно.
П.С.: применяем не каждому случаю, а когда имеет смысл.

0
2 комментария
Богдан В.

Имхо, вы переусложняете. Подозреваю, что ваша команда рано или поздно таки вернется к более простому описанию процесса работы с багами.)

Ответить
Развернуть ветку
Александр Меньщиков
Автор

Мы работаем с багами в более простом режим, просто система очень большая и сложная, и к этому прибегаем периодически

Ответить
Развернуть ветку
-1 комментариев
Раскрывать всегда