Вы прочитали ТЗ. Теперь прочитайте его еще раз

Допустим, вы разработчик. Вам в Jira прилетает задача — сделать на странице пользователя кнопку «Дать денег». Вы делаете кнопку, она появляется на странице, нажимается, запрос уходит на бэк, бэк отвечает 200 OK. Технически все выполнено верно, но заказчик недоволен и вопрошает: «Я уже пять раз нажал на кнопку, почему деньги так и не пришли?».
И где-то между «в ТЗ было написано просто добавить кнопку» и «давайте срочно переделаем фичу до релиза, перепишем кнопку на тумблер и подрубим биллинг» возникает вопрос: кто виноват и почему именно аналитик?
Привет, Хабр. Я Арина, системный аналитик в Selectel. Я пишу требования к внутренним сервисам, ботам, интеграциям и прочим штукам, которые сначала кажутся маленькими, а потом обрастают ролями, статусами, ретраями, правами доступами и фразой «а это точно MVP?».
В этой статье я спровоцирую холивар подниму давнюю проблему недопонимания между разработчиками и аналитиками в части ТЗ. Статья, в первую очередь, для разработчиков, чтобы можно было как можно раньше находить потенциальные проблемы, не ссориться с аналитиком и не реализовывать идеально то, что потом все равно придется переделывать. Хотя и аналитики, составляющие ТЗ для разработчиков, я уверена, смогут найти для себя что-то полезное в статье.
Почему «прочитать ТЗ» недостаточно
В теории ТЗ должно отвечать на все вопросы. В реальности оно часто отвечает только на те вопросы, которые аналитик успел осознать и задать клиенту до того, как задача ушла в разработку.
Это не оправдание плохих требований, а обычная реальность продуктовой и внутренней разработки. Бизнес меняет вводные, документация не всегда догоняет архитектуру, интеграции ведут себя не так, как обещали, а «простая доработка» внезапно оказывается завязана на три сервиса, две роли и старый процесс, который все боятся трогать.
Особенно хорошо это видно во внутренних продуктах. Снаружи фича выглядит как «добавить возможность отправить заявку кадровику». Внутри сразу появляются вопросы: кто может отправить заявку, кто ее получит, что делать при ошибке маршрутизации, можно ли прикладывать файл, как понять, что заявку обработали, и что делать, если ее не обработал никто. Все эти вопросы могут стать багами, если их не проговорить заранее.
Поэтому ТЗ — это не просто список экранов, кнопок и ручек. Это первая модель будущего поведения системы. И если читать его только на уровне «что добавить в код», легко пропустить детали, на которых потом сломается весь сценарий.
Допустим, разработчик действительно прочитал ТЗ: не только задачу в Jira и заголовки, а еще и статью в Confluence. Но прочитать ТЗ и понять будущую систему — разные вещи. Примерно как прочитать инструкцию к шкафу и потом собрать его без лишних деталей, мата и мыслей, что производитель тебя ненавидит.
Конечно, ТЗ тоже может быть неполным: аналитик мог не знать технических ограничений, бизнес мог поменять вводные, а старая логика сервиса — всплыть только после разговора с разработкой. Поэтому нормальная работа начинается не с позиции «я все написал, теперь делайте» и не с позиции «тут все непонятно, переделывайте».
Я предлагаю смотреть на ТЗ не как на закон, а как на макет будущего поведения системы. Его можно уточнять, достраивать и менять. А проблемы начинаются тогда, когда требования читают слишком буквально.
Если что, я не считаю, что разработчик должен додумывать требования за аналитика. Наоборот: додумывать опасно. Речь о том, как раньше заметить место, где команда еще не договорилась о поведении системы.
В следующих разделах разберем, как читать требования по слоям, какие красные флаги искать и как задавать вопросы аналитику до старта разработки так, чтобы снижался риск инцидентов, а потенциальные баги решались еще до старта разработки.

Создайте веб-приложение и получите бонусы на его деплой в облако
В новом бесплатном курсе по JavaScript.
Как читать требования по слоям, чтобы потом в день релиза не чинить «просто кнопку»
ТЗ обычно написано не в том порядке, в котором разработчик будет писать код. Аналитик может начать с цели, потом уйти в сценарий, потом вспомнить про ограничения, а в конце в AC внезапно дописать условие, без которого половина реализации меняется.
И это не потому, что аналитик хочет усложнить вашу работу. Просто аналитик думает не методами, таблицами и классами. Он думает процессом: кто пришел, зачем пришел, что сделал, кто после этого получил уведомление, кто не получил, где все сломалось и почему теперь на созвоне 12 человек разбираются, кто был не прав.
Разработчик читает иначе. Он пытается понять, что надо поменять в системе: где хранить, что вернуть, какую ручку вызвать, где проверить права, что делать с ошибкой.
И оба этих подхода правильные. Они дополняют друг друга и позволяют посмотреть на один и тот же артефакт разработки с разных сторон. Но на стыке этих подходов может потеряться смысл фичи.
Я буду сравнивать слои чтения ТЗ на основе аналогии с бутербродом, потому что считаю, что такие простые бытовые аналогии лучше откладываются в памяти, а еще потому что я была немного голодной, когда описывала эту концепцию.
Цель
Крепкая основа нашего бутерброда — цель фичи. Не «что сделать», а «зачем это вообще нужно бизнесу». Если цель фичи — снизить ручную работу, странно делать решение, после которого человек все равно руками разбирает половину заявок.
Когда разработчик читает ТЗ, ему не обязательно погружаться во всю бизнес-драму. Но полезно понимать, какую проблему закрывает его часть фичи. Иначе можно сделать все точно по формулировке, но не решить задачу.
Поэтому цель лучше держать в голове как фильтр. Не для того, чтобы разработчик заменял аналитика или лида, а чтобы вовремя заметить: «Кажется, мы сейчас реализуем то, что клиенту вообще не нужно».
Сценарии
Самая питательная часть ТЗ, которую может выдать аналитик. Именно в сценариях и содержится та боль, те проблемы и решения, которые должна решать фича. Не «есть кнопка», а что происходит до кнопки, после кнопки и в случае, если пользователь нажал ее не вовремя. Очень часто фича ломается не на основном действии, а вокруг него.
Хороший способ проверить сценарий — посмотреть не только на действие пользователя, но и на то, что уже могло произойти до него.
Например, есть сервис для поиска исполнителей под бытовые задачи. Пользователь хочет выкопать пруд на даче, описывает задачу и нажимает «Начать поиск». Бот берёт запрос, находит подходящих исполнителей и пишет им. Исполнители могут согласиться или отказаться, а пользователь — ждать ответов, дождаться окончания срока поиска или попытаться отменить запрос.
На бумаге отмена выглядит просто: перевести запрос в статус «отменен» или удалить его. Но запрос уже мог уйти исполнителям, кто-то мог согласиться, кто-то отказаться, а срок поиска еще не закончился. При этом все происходит не в тикет-системе с понятными статусами, а в чатах с ботом. У инициатора свой диалог, у исполнителей свои, общего экрана состояния просто нет.
Если делать настоящую отмену, нужно продумать, что увидят исполнители, как отозвать уже отправленные сообщения, что делать с согласившимися и как показать всем участникам, что запрос не потерялся. Для MVP реализовать все эти функции было бы было слишком дорого.
Поэтому мы выбрали ограничение: активный запрос нельзя отменить вручную. Бот сообщает инициатору, что запрос уже в обработке и завершится сам, если все исполнители откажутся или истечет срок ожидания.
Сценарий нужно читать целиком именно для этого: чтобы не раздуть задачу и чтобы понять, где простое действие на самом деле тянет за собой новый процесс. А еще чтобы понять, где этот процесс можно срезать, по крайней мере на период внедрения MVP.
Данные
Следующий слой — данные. Если в ТЗ появляется новая сущность, ее надо сразу приземлить на уровень контекста системы.
Для бизнеса «заявка», «запрос» и «тикет» часто означают одно и то же: человек куда-то написал, ему должны помочь. Для разработки это могут быть разные объекты с разными полями, статусами, владельцами и историей.
Поэтому разработчику стоит проверять не только «что показать в интерфейсе», но и что именно появляется в системе: где объект создается, где хранится, кто его меняет и какие действия с ним доступны.
То же самое со статусами. Статус — не просто плашка на фронте, зачастую от него зависят права, уведомления и другие объекты системы. В таком случае уже надо продумывать жизненный цикл: какие статусы есть, что запускает переходы, можно ли откатиться назад и что происходит при спорных действиях.
Если этого нет в ТЗ, то лучше уточнить все эти детали до разработки. Иначе команда рискует реализовать одинаковые слова как разные сущности — или разные процессы как один красивый бейдж.
Бизнес-правила
Этот ингредиент IT-бутерброда можно сравнить с соусом, потому что он проникает во все слои ТЗ и красной нитью проходит через все разделы статьи. Все эти милые сердцу аналитика формулировки по типу «только», «если», «кроме», «не более», «в течение», «по умолчанию». Они выглядят как уточнения, но на самом деле это часто и есть основная бизнес-логика. Для примера приведу несколько реальных бизнес-правил, которые я описывала по одной из крупных фич:
-
Повторную отправку необработанной заявки делаем только один раз.
-
Если внешний сервис не ответил, создание заявки недоступно.
-
При переадресации заявки отправляем уведомление пользователю.
-
Если отсутствует правило переадресации, отправляем пользователю сообщение-заглушку.
Каждое такое правило может изменить реализацию. Но в ТЗ оно может быть спрятано в середине абзаца, потому что для аналитика это «логичное ограничение процесса», а для разработчика — отдельная ветка обработки.
Поэтому такие с виду невинные детали тоже стоит вычленять из текста и досконально проговаривать, чтобы не переписывать 1 000 строк кода из-за того, что фича не проходит один маленький, но очень важный тест-кейс, построенный на бизнес-ограничениях.
Интеграции, ошибки и права
Эти компоненты бутерброда я сравню со специями и объединю в один блок, так как, с одной стороны, это уже конкретные детали реализации фичи, а с другой — эти детали могут развернуть всю разработку на 180 градусов. Давайте разберем несколько примеров.
Если по задаче надо научить систему ходить во внешний сервис, то сразу стоит спросить: а если он не ответит? А если ответит дважды? А если пользователь нажмет кнопку еще раз?
В одном из кейсов с массовыми операциями было принципиально важно понять, что делать при частичной ошибке. Не просто «показать ошибку». А продолжать обработку или останавливать? Откатывать все или только проблемные элементы? Что показать пользователю? Как он поймет, какие объекты обработались, а какие нет?
Всеми этими вопросами пришлось задаться заранее, чтобы потом не оказаться в ситуации, где часть операции уже отработала, а часть — отвалилась с ошибкой.
Права, если по ТЗ они меняются или отличаются от текущей модели, тоже лучше проговаривать заранее, особенно если модель доступа в сервисе еще не устоялась.
Как пример плохой фразы для ТЗ: «пользователь может редактировать». Она слишком общая: нужно понять, кто именно редактирует, какие поля, в каких статусах и где проверяется доступ. Иначе «потом прикрутим права» легко превращается в переделку кнопок, ручек и части бизнес-логики.
Нефункциональные требования
Это слой, о котором часто забывают и разработчики, и аналитики. Часто НФТ выглядят как украшение в конце ТЗ: «система должна быть быстрой, стабильной и удобной». «Спасибо», — скажет мне любой мало-мальски опытный разработчик, очень полезно, пошел делать медленную, падающую и неудобную систему, капитан очевидность.
Нормальные НФТ — это не красивые формулировки, а ограничения, которые непосредственно влияют на реализацию. Например: историю храним 12 месяцев. Ошибки интеграции логируем с ID сущности. Данные обновляются каждые 15 минут. Операция должна быть идемпотентной. При падении внешнего сервиса нельзя терять заявку.
Вот это уже точно, понятно, измеряемо и, что самое главное, — тестируемо. Это влияет на архитектуру, хранение, мониторинг и оценку задачи. И это можно реально проверить при разработке и тестировании.
И вот если такие вещи всплывают после разработки, всем становится грустно, начиная от клиента и заканчивая DevOps-инженером. Особенно разработчику, который «уже почти все сделал» и в мыслях открестился от этой проклятой задачи. А теперь из-за одного небольшого уточнения придется переписывать половину кода.
Acceptable criteria
Завершающий слой нашего бутерброда. В нормальном мире AC должны отвечать на вопрос «Как мы поймем, что задача готова?». Не «кнопка есть» и не «у меня локально работает», а именно что бизнес-сценарий закрыт.
Хороший AC должен проверять самые важные и ключевые сценарии, ради которых вся фича и затевалась. И если после прочтения AC все еще непонятно, как QA будет проверять задачу, значит команда пока не договорилась, что именно она делает и как.
Красные флаги в ТЗ
После чтения ТЗ по слоям обычно становится понятно, где задача выглядит устойчиво, а где держится на слове «ну понятно же». Вот на такие места лучше обращать внимание до разработки. В этом разделе я приведу несколько примеров красных флагов, которые я сама делала в своей работе, чтобы вы могли не повторять моих ошибок.
Первый красный флаг — в требованиях описано решение, но не описана задача. Например: «добавить чекбокс», «завести поле», «сделать статус». Иногда это действительно нужное изменение. А иногда это готовое решение, которое кто-то придумал вместо описания проблемы. В таком случае полезно уточнить у аналитика: какую функцию закрывает это поле, кнопка или статус и что пользователь должен получить в итоге.
Второй флаг — сущность используется, но не определена. Если в ТЗ есть «заявка», «запрос» или «активность», но неясно, где объект создается, где хранится, кто его меняет и какие действия с ним возможны, это почти гарантированная зона путаницы. Аналитик, разработчик, QA-инженер и заказчик могут понимать одно слово по-разному — и все будут по-своему правы.
Третий флаг — неясен источник истины. Во внутренних сервисах данные часто размазаны по нескольким системам: где-то лежит сотрудник, где-то роль, где-то смена, где-то статус. Поэтому формулировка «отображать актуальные данные» сама по себе ничего не значит. Нужно понять, откуда именно берем данные и чему верим, если значения расходятся.
Четвертый флаг — описан только happy path. Пользователь нажал, система отправила, внешний сервис ответил, все счастливы. Но в реальности бывают таймауты, дубли, повторные действия, частичные ошибки и недоступные интеграции. Не нужно описывать все возможные катастрофы мира, но критичные edge cases должны быть проговорены до разработки.
Пятый флаг — слова без проверяемого смысла: «просто», «автоматически», «актуальный», «корректный» и т. д. Они выглядят нормально в тексте, но плохо переживают реализацию и тестирование. Если условие нельзя проверить тестом, его обязательно нужно расшифровать.
В целом красный флаг — это не повод писать «тут все непонятно». Это повод прийти с конкретным вопросом: что именно делаем, откуда берем данные, какой сценарий покрываем, где граница MVP и как поймем, что все работает правильно.
Я перечислила, конечно же, далеко не все красные флаги и потенциальные косяки в ТЗ, которые могут вылиться в споры. В комментариях вы можете привести свои примеры флагов, которые встречали в работе и которые потом могли вылиться в неприятности при релизе.
Вместо вывода: как читать ТЗ и не превращать ревью в разбор полетов
Работа с требованиями не заканчивается в момент, когда аналитик написал ТЗ, а разработчик открыл задачу. С этого момента начинается совместная командная работа: все ли одинаково поняли цель, сценарий, ограничения и границы MVP.
И самый бесполезный вопрос к аналитику на этом этапе — «что тут делать?». Он просто возвращает весь ком непонимания обратно. Лучше спрашивать через риск: что сломается, если внешний сервис не ответит; что будет при повторном действии; кто имеет право выполнить операцию; что входит в первый релиз, а что сознательно не делаем.
Такие и подобные им вопросы не звучат как «ТЗ плохое». Они звучат как «я вижу место, где система может повести себя по-разному, давайте решим до разработки». Это сильно снижает шанс превратить ревью требований в перекидывание ответственности.
Еще важно не спорить на уровне «в ТЗ было / не было». Этот спор почти всегда ведет в тупик. Полезнее сразу переводить разговор в плоскость решения: есть несколько вариантов поведения, у каждого своя цена, риск и влияние на сервис. Значит, нужно выбрать вариант и зафиксировать его письменно. Не «мы же на созвоне обсудили», а в ТЗ, комментарии к задаче или другом месте, где это потом можно найти.
Чтобы не перечитывать каждый раз статью перед взятием задачи в работу, можно быстро пройтись по короткому чек-листу:
-
я понимаю, какую проблему решает фича;
-
я могу пройти пользовательский сценарий от начала до конца;
-
я понимаю, какие сущности, поля и статусы появляются или меняются;
-
я знаю, какая система считается источником истины;
-
я вижу ключевые правила, ограничения и права;
-
я понимаю, что будет при ошибке, дубле или недоступности внешнего сервиса;
-
я понимаю, что входит в MVP, а что осознанно не делаем;
-
я понимаю, как QA и аналитик будут принимать задачу.
Если на часть вопросов ответа нет, это не повод брать задачу в разработку с мыслью «ну как-нибудь разберемся». Это повод задать вопрос сейчас, пока проблема еще стоит дешево.
ТЗ можно прочитать как список работ: что добавить, где сохранить и какую ручку вызвать. А можно прочитать как модель будущего поведения системы. Второй вариант дольше и иногда неприятнее: придется задавать вопросы, вытаскивать ограничения и признавать, что в требованиях есть дыры. Зато это дешевле, чем потом чинить «просто кнопку», которая технически нажимается, но соточка после этого на карту почему-то не падает.

На этом все. Надеюсь, в следующий раз «просто кнопка» покажется вам чуть подозрительнее — и это спасет кому-нибудь релиз.
Автор: prost_arina

