Вступление в виде басни "Бэкендер, фронтендер и аналитик"
Когда в коллегах согласья нет,
На лад проект их не пойдет,
И выйдет из него не profit, только cost.
Однажды Бэкендер, Фронтендер да Аналитик
Везти с тасками US взялись,
И вместе трое все в него впряглись;
Из кожи лезут вон, а US всё нет ходу!
Таски бы для них казались и легки:
Да Фронт рвется в Cloud-решения,
Бэк пятится назад, а Аналитик тянет в воду.
Кто виноват из них, кто прав, — судить не нам;
Да только UserStory и ныне там.
Привет, друг!
Меня зовут Сергей Павлов — тот, который любит погамать в VR, порубиться в настолки и ещё, оказывается, тот, который начальник отдела развития в банке «Открытие».
Давай немного отвлечемся от привычного формата технических и научных текстов. А вместо этого одну простую сказку, а может и не сказку, а может не простую … в общем будем вспоминать сочинять.
Сегодня я пришел поделиться с тобой очередной практикой эффективного (сейчас будет умное слово) Cycle Time.
Cycle Time — время, которое задача находилась в разработке от момента, когда ей начали заниматься, до момента, когда она прошла фазу конечной поставки.
Но речь пойдет не конкретно про Cycle Time, поэтому я не буду заострять на этом внимание.
Перейду к сути — уверен, многие узнали всем известную басню про трёх товарищей, которые пытаются затащить одну общую хотелку (некий воз). Только вот каждый тянет эту задачу в свою сторону, игнорируя усилия других.
Задача
Сейчас будет описание крайне сложной задачи! Т-с-с! Никому не рассказывай эту идею… это идея на миллион (чего-нибудь, возможно, ценного).
«Нам нужно реализовать сбор уникальных слов от пользователей»
Также давай не будем обращать внимание на бизнес-значение текущего запроса. Как я сказал, эта идея — бомба, она выстрелит сразу. Да и вообще будем считать, что на старте проекта уже будет пройдена ТБУ (точка безубыточности).
Ну что, всё предельно ясно, можно начинать реализацию.
Го разрабатывать, я создал!
Круглое таскать, квадратное — катить
ПОНЕДЕЛЬНИК: берем задачу в аналитику
Думаю, тут будет всё просто. Накидаем тзшку на разработку.
Введение
Наименование программы — "Словособиралка". Система предназначена для коллекционирования уникальных слов от пользователей.
Данные о введенных словах хранятся в базе данных (СУБД). Обязательное условие — исключаем дубликаты.
Входные параметры
POST/word
Параметр | Тип | Обязательность | Описание |
word | string | да | новое слово |
Выходные параметры
Код | Описание |
200 | слово уже имеется в базе |
201 | новое слово добавлено |
400 | некорректное значение параметров |
Сценарий пользователя
Для добавления нового слова пользователь заполняет поле ввода и нажимает кнопку "Отправить".
Выдерживаю паузу … Держу паузу для того, чтобы ты, мой дорогой читатель, успел принять решение о том, всё ли ок в ТЗ и готовы ли мы двигаться дальше. Если пауза затянулась, то я приму решение двигаться дальше, т.к. задача простая, тут особо не разгуляешься. Есть описание сценария пользователя, есть описание запроса и ответа. Разработчику понятно, что делать — это главное!
ВТОРНИК: ну как тут без оптимизации? Работаем по Кайдзен! Во как!
Кайдзен (Kaizen) — ключевая концепция менеджмента. Это японская философия, система с фокусом на непрерывном совершенствовании всех производственных процессов, нашего образа жизни и всех аспектов жизни. Kai — перемены, изменения, Zen — к лучшему.
Поэтому можно смело запустить два процесса в параллель (реализация бэкенд и фронтенд части).
Реализуем фронтенд
У фронта тут будет самая простая часть. Вот бездельник!
Таак, посмотрим, что там у нас пришло по ТЗ: "Нужна форма для отправки запроса по нажатию на кнопку. Форма, в свою очередь, состоит только из одного поля для ввода текста и той самой кнопки".
Раз-два, тяп-ляп и формочка готова:
![](https://habrastorage.org/getpro/habr/upload_files/cb0/767/4a6/cb07674a65fef70ef942bdad301dbbed.png)
Чтобы было ещё проще форма будет выглядеть так:
<form action="/word" method="post">
<input type="text" value="" name=”word”/>
<input type="submit" value="Отправить!"/>
</form>
Форму сабмитим одноименным инпутом типа=”submit”
На этом, как говорится, "здесь наши полномочия всё".
Реализуем бэкенд
Первым делом создаем таблицу для хранения слов:
Поле | Тип | Обязательность | Описание |
word | string | да | слово |
Далее пишем маппинг на входящие параметры для сохранения в таблицу. Чтобы исключить дубликаты, пишем вставку в таблицу через INSERT IGNORE.
Возвращаем ответ согласно поставленному ТЗ.
Всё готово! Довольный разработчик запускает доту и продолжает рубить, пока нет других задач.
Задача выполнена, все счастливы!
Казалось бы, каждый выполнил своё дело и даже успел получить талоны на бесплатные обеды! Но давай рассмотрим, что мы имеем при таком подходе.
СРЕДА
Город засыпает, просыпается мафия тестировщик. На этапе функционального тестирования совместной dev-сборки выясняется, что запрос с фронта уходит, но данные в БД не появляются. Причем мы ещё и получаем в ответ статус 400. Смотрим в ТЗ, сравниваем исходящие параметры с фронта на бек и снова удивляемся — "Почему 400?! Почему так?". Закрываем глаза, нажимаем кнопку "отправить", открываем глаза … увы, картина не поменялась … даже при таком секретном подходе с закрытыми глазами. Всё так же ошибка 400.
Ок, я же крутой тестировщик, сейчас во всём разберусь! Беру HAR-файл, иду к бэкенд-разработчику с вопросами:
![](https://habrastorage.org/getpro/habr/upload_files/0c2/e3e/a10/0c2e3ea1001704b04d8f3a2be3c5bd08.jpg)
Тэк бэт, смотри, запрос на бэк приходит, всё по ТЗ, но почему-то данные в таблице не появляются, а в ответ я получаю 400.
Смотрим на бэк и понимаем, что мы ожидаем application/json, а приходит application/x-www-form-urlencoded. Итог — крах, тлен, уныние, приём депрессантов.
Что мы делаем дальше — отправляем таску на доработку, т.к. дальнейшее тестирование в целом невозможно.
За кем закрепляем? Хм… да конечно же за разработчиком бэкенда! Ведь он же, такой неумёха, не сохраняет данные!
Тестировщик засыпает...
ЧЕТВЕРГ
Слово предоставляется BE-разработчику:
Представим, что наш бэкенд-разработчик само спокойствие и пример умиротворения. Спокойно открывает задачу, читает, анализирует, открывает код и всё такое. И выдает вполне себе ожидаемую фразу — "Товарищи по цеху, а причем тут я?!". Далее ласково и красноречиво отписывает в комментариях просьбу переделать отправку с фронта в json-формате. Закрепляет задачу на фронт-разработчике, при этом делает акцент, как бы оправдывая себя: "Вы же видели ошибку 400! Всё должно быть понятно по ней. Значит, что-то с параметрами".
Свою работу я выполнил, сделайте, пожалуйста, свою!
Слово предоставляется FE-разработчику:
— Уважаемый, прошу обратить внимание на то, что вообще-то это я инициатор запроса, что собственно означает, что ваша обязанность — подстраиваться под меня!
Речь фронта была краткая и понятная. Ну что тут говорить… инициатор диктует правила.
— В любом случае я так и не понял, как мне обрабатывать ошибки. Давайте повесим какие-нибудь нотификации исходя из статусов ответов. Они же для чего-то есть. В общем, передаю задачу системному аналитику.
Дружище, пиши нормальное ТЗ!
ПЯТНИЦА
Во всем как всегда виноват аналитик...
Вообще любой баг в большинстве случаев довольно просто повесить на системного аналитика, опираясь на любую из подобных фраз:
— Ты не собрал до конца требования;
— Ты не продумал полностью интеграцию;
— Ты не указал формат передачи данных (О, наш вариант!);
— Ты не спроектировал хранение данных;
— Ты не описал описание описания;
— В какое время года наступает новый год на Северном полюсе?;
— И т.д....
Итак, системному аналитику прилетела задача (баг) из-за того (как показалось), что он не описал формат передачи данных. Штош, подсудимый, отвечайте!
Господа присяжные! Дело в том, что при проектировании ТЗ я пользовался здравым смыслом. И в надежде на то, что у разработчиков есть здравый смысл, не стал указывать формат отправки данных с фронтенда на бэкенд. Тем более, вы — оба разработчики и должны понимать, как отправить запрос с фронта на бэк. Не прави ли я? И самый главный встречный вопрос к вам: "Вы пользуетесь здравым смыслом?"
Давайте разбираться
Подведу предварительный итог, к чему это всё было написано.
В этой ситуации каждый прав и неправ одновременно. Каждый участник проделал свою работу над задачей. А когда возникла проблема — тут началась игра "Переложи проблему на другого".
![](https://habrastorage.org/getpro/habr/upload_files/9de/607/e64/9de607e64228e1a0508f4cebc3557aa3.jpg)
Каждый пытался переложить текущую проблему с себя на своего коллегу. Хотя вот тут я бы вступил в холивар на тему "Кто есть коллега?". Потому что для меня коллега — это надежный партнер по работе, на которого можно смело рассчитывать и с кем можно планировать реализацию задачи любой сложности.
Аналитик
Пошел по пути наименьшего сопротивления для реализации задачи. Он составил ТЗ быстро и кратко. Ровно для того, чтобы на этом этапе задача задержалась как можно меньше, чтобы можно было её уже передать в разработку. В целом он аргументировал это решение тем, что его так называемые “коллеги” вполне себе адекватные синьор-специалисты и смогут совместно решить аспекты отправки данных.
Бэкенд
Строго реализовал задачу согласно поставленному ТЗ. Он не отклонялся в сторону, не пытался видоизменить ход мысли аналитика. К тому же unit-тесты успешно выполняются на 100%.
Фронтенд
Задача была крайне простая. Нужно просто отправить форму с данными. Имена переменных озвучены в ТЗ, собственно, эти данные и уходят на бэк, где он в свою очередь должен был их обработать.
Прошла неделя. Вот только ТЗ и ныне там...
Забудем, что было и начнем с начала
А теперь давай разберем, к чему мы пришли у нас в «Открытии».
В первую очередь, мы — команда! Перед нами стоял ряд объективных проблем:
Задача проходит несколько раз по одному и тому же этапу;
Некоторые задачи, хотя и реализуются по скраму, но их исполнение очень похоже на вотерфлоу;
Ресурсы разработки простаивают из-за ожидания выполнения этапов;
Уровень напряжения и недоверия в командах растет;
Отсутствует единое понимание цели выводимой задачи, также рассинхрон в техническом понимании задачи, т.е. в том, как она "выглядит изнутри";
И т.д....
Очевидно, что все эти проблемы надо решать. Можно бесконечно искать оправдания и откладывать изменение уже устоявшихся процессов, но я считаю — лучше начать делать хоть что-то, чем ничего не делать.
Итак, самое основное — убрать барьеры. Убрать преграды между коллегами, когда кто-то боится, кто-то стесняется, кто-то не хочет что-либо говорить. Внутри команды и даже между командами мы всегда открыты к диалогу и обсуждению каких-то задач, вопросов, да и просто поболтать на свободные от работы темы — разумеется, не во вред текущему рабочему процессу:)
Чтобы описать сам процесс подхода к изменению коммуникаций, нужна будет отдельная тема. Поэтому я вернусь к текущей теме и опишу, как оно работает у нас сейчас.
Процесс работы над задачей построен так, что сотрудник не остаётся с ней один на один бесконечное время.
Отменяем 1:1 митинги между задачей и исполнителем!
Будь то аналитика или разработка (бэк или фронт), всегда происходит активное взаимодействие со всеми участниками текущей задачи. Решение, которое сейчас выполняет сотрудник, обязательно обсуждается с другими исполнителями.
![](https://habrastorage.org/getpro/habr/upload_files/091/ee8/f13/091ee8f13ed522591eef618b46ac3a89.png)
Этот подход, кстати, позволяет нам работать эффективно со специалистами разного уровня (Junior, Middle, Senior). Поэтому ошибки при реализации из-за отсутствия компетенций не пройдут мимо из-за общего груминга. И коллега обязательно сделает акцент на то, где, как и что лучше исправить. Тем самым мы ускоряем прокачку и рост специалистов от Junior до Senior.
Вернемся к нашей абстрактной задаче про "Словособиратор". Мы пойдем по той реализации, которая была заложена изначально. Возьмем то ТЗ, которое подготовил наш системный аналитик.
Далее мы подключаем важный этап, который был упущен — коммуникацию!
Что мы получаем? До передачи ТЗ на разработку оно должно пройти груминг, т.е. исполнители задачи должны ознакомиться с тем, что нужно будет сделать. Далее в режиме открытого диалога происходит обсуждение возникших вопросов. Как раз в этот момент и должны появиться вопросы из серии "Воу-воу, ребят, а в каком формате данные будут ходить?".
Чтобы не останавливать процесс (в банке мы же не бюрократы:)), ТЗ уже можно отдать в разработку с пометкой "поправить момент отправки и обработки данных". Ведь на груминге все услышали и зафиксировали решение. Будем отправлять и принимать JSON.
Кстати, хочу добавить, что на груминге необходимо присутствие и тестировщика, потому что ему тоже нужно понимать, как это всё работает, чтобы качественно провести тесты.
Итак, вернемся к нашему условному понедельнику.
ПОНЕДЕЛЬНИК: берем задачу в аналитику
Думаю, тут будет всё просто. Накидаем задачку на разработку. Введение, Входные параметры, Выходные параметры, Сценарий пользователя оставим без изменений, как описывали в начале.
ВТОРНИК
Грумим задачу, собираем фидбек, понимаем, что нужно указать формат передачи данных и запускаем два процесса в параллель (реализация бэкенд и фронтенд частей). В этот же день дописываем формат передачи данных, но получаем момент, на который стоит обратить внимание — ТЗ обновлено в момент разработки! Поэтому обязательно уведомляем об этом разработчиков, подсвечивая те места, где были изменения в ТЗ.
Вот теперь задача выполнена, все счастливы!
СРЕДА
Тестируем задачу, поскольку она чересчур простая, а формат передачи данных мы уже обсудили, ошибок на этом этапе не должно быть обнаружено. Итого — в среду наша задача уже имеет статус RFR (ready for release).
Profit!
Подведем итоги
К:
Команда
КоммуникацияКапризы
Клевета
Работа над задачей должна идти коллективно, каждый член команды должен держать в голове мысль о том, что задача исполняется в первую очередь для клиента, а не для списка к отчету релиза. Нужно понимать, как твои действия над задачей повлияют на вывод её в прод.
Отклонения от ТЗ допустимы, но должны быть согласованы между всеми исполнителями. Также в обязательном порядке изменения должны быть зафиксированы до вывода задачи в прод.
Если есть вопросы — СПРАШИВАЙ!
![](https://habrastorage.org/getpro/habr/upload_files/041/34f/e68/04134fe68ee816883d8bb5600a2728c2.jpg)
Adios!