Госконтракт: история о том, как мы не справились
Десклеймер:
Все факты, описанные в статье, основаны исключительно на моём личном опыте в рамках одного проекта и одной компании. Я понимаю, что мой опыт может не быть универсальным, и он не отражает работы других команд или людей. Всё, что написано, — это исключительно мои ощущения и впечатления, которые могут быть ошибочными или неполными.
Я сознательно упустил многие рабочие моменты, которые не относятся к истории.
Я не осуждаю никого в этой статье.
Я не собираюсь вас чему‑то научить.
Введение
Доброго времени суток, Хабр!
Сегодня я подкину своим хейтерам отличный повод провести вечер в комментариях под этой статьёй. Речь пойдёт о том, как я участвовал в провале гос. контракта.
Сразу развею возможные тезисы вроде: «Ты ужасный прогер, только и ноешь о своих проблемах и некомпетентности.» На самом деле, я пишу об этом намеренно. Меня раздражают весёлые, а порой и лицемерные статьи, где авторы только и делают, что кичатся своими успехами.
Увы, я претендую на искренность. Моя цель — подсветить негативные моменты и ошибки. Возможно, мои провалы помогут кому-то не наступить на те же грабли, что и я. Да, я осознаю, что меня могут заклеймить как «неудачника» или «плохого прогера», но меня это устраивает.
Предыстория
Устроился я в обычный классический аутсорс фронтенд-разработчиком. После успешно пройденного собеседования (довольно лёгкого) наступил мой первый рабочий день.
Я ожидал получить обещанный онбординг, но, как оказалось, пришлось самостоятельно находить членов команды и поодиночке писать им в личку, чтобы разведать обстановку и познакомиться. Первым делом я нашёл тимлида и попросил у него аудиенции — ждал от него вводной о том, что мне делать.
Тимлидом оказался старый пердун, который позвонил мне на телефон по обычной связи и с ужасным микрофоном. Как выяснилось позже, тимлид никак не участвовал в жизни команды, проваливал задачи и время от времени пропадал с радаров. «Этот перец мне не помощник,» — подумал я и пошёл искать братьев-фронтов.
Обещанная команда опытных фронтендеров состояла из одного человека, который устроился за пару дней до меня. Мы сразу нашли общий язык, и на мой вопрос: «Ну что, как тут тебе?» он без раздумий заявил: «Тут [нарушение правил Хабра], а в коде тут [нарушение правил Хабра].»
Я немного расстроился, но решил, что стоит попробовать и убедиться во всём лично. Вдруг всё не так плохо, а я, как Д«Артаньян, смогу повлиять на процессы.
Компания занималась преимущественно госзаказами и работой с дубайскими коллегами. В нашей команде было два мидла-фронтендера, джун-бэкендер (работавший исключительно на Битриксе, без знаний основ нативного PHP и существования REST API), пре-синьор BA, тестировщица, ПМ и директор дивизиона. Наша супер-компашка отправилась «поднимать с колен отечественную IT-индустрию» (шутка).
Через полтора месяца лида выкинули ссаными тряпками из компании, и мы выдохнули. В основном занимались внутренним продуктом — маркетплейсом с авторскими правами.
Ненужные детали
Это чудо было написано в формате MPA на Vue 2. Роутинг был монструозно реализован прямо в конфигурации Webpack, а каждый роут представлял собой новый экземпляр Vue. Шаблон компонента создавался на Pug.js, а манипуляции с DOM происходили с помощью jQuery. И всё это — на базе Vue.js. Vue.js, Карл!
Может, для Multi Page Application это и норма, я не в курсе. Сказали, что такой подход обещал им хорошее SEO. Ну, такое…
Мы довели это дело до MVP. Нам с коллегой разрешили переписать проект на Nuxt.js и дали на это месяц. С чем мы отлично справились.
Спустя 4 месяца началось…
Госконтракт: Погоня за собственным хвостом
Общий созвон. ПМ довольный, рассказывает нам, что мы стартуем крупный госзаказ. По его словам, сдача этого проекта должна была перекрыть долг дивизиона и вывести его в плюс. Что? Долг дивизиона? 5 млн? Опешил я, но виду не подал. Окей, работаем!
Нам взяли нового лида, который был очень токсичным, но тем не менее толковым. Хоть и не сразу, но мы нашли с ним общий язык и приступили к делу…
Какая задача перед нами стояла
Реализация трёх модулей для учёта трудозатрат государственного аппарата. В них входили:
Модуль с дашбордами. Состоял из диаграммы Ганта и двух других диаграмм, похожих на первую, но с более урезанным функционалом.
Модуль учёта времени, потраченного на проект или инициативу. Полный список под каждого сотрудника: кто, где и на что потратил время. Представлял собой таблицу с фильтрами и списком сотрудников с возможностью в реальном времени редактировать данные внутри таблицы с автосохранением.
Модуль с таблицей проектов, инициаторов, ответственных. Представлял собой вложенные таблицы с данными, тесно связанными с модулем учёта времени.
Каждый модуль является отдельным модулем, который интегрируется в CRM Битрикс24 как компонент.
На всё про всё — три месяца, не больше. Время пошло!
Наши ограничения
ТЗ ещё не разработано, но есть скрины похожего модуля. Нет понимания конечного функционала и требований к нему. Только широкими мазками из брифов ПМа, основанных на созвонах с конечным клиентом, у нас было абстрактное описание проекта.
На счету дивизиона нет дизайнера. Как это должно выглядеть — мы не знали.
Неизвестен API-контракт.
Неизвестна конечная точка интеграции. О том, что это модуль для Битрикса, мы узнали уже в конце. До этого не было понимания, где эти модули будут находиться и использоваться.
Диаграмма Ганта имела специфический набор дополнительного функционала, который не могла предоставить ни одна библиотека для отрисовки диаграмм и графиков. По крайней мере, мы такую не нашли.
Первые шаги
Оценили фронт работ и разбили его на зоны ответственности. Фронт решили писать на Vue.js. У каждого был свой модуль с таблицами, а работу с дашбордами мы проводили втроём: я, лид и второй фронтендер. Модули учёта времени и сводка проектов были довольно простыми, не буду заострять на них внимание. Особого внимания требовала диаграмма Ганта. Из-за её функциональных особенностей и требований заказчика пришлось писать кастомное решение на TS + . Всё ещё нет финального ТЗ.
Три не признанных художника
Мы довольно быстро накидали классы, которые давали нам абстракцию для удобного рисования на canvas. Базовый инструмент для рисования был готов, начали художничать. У нас был только скриншот примерного результата, остальное приходилось дофантазировать аналитике и ПМу. Потихоньку стала вырисовываться первая версия ТЗ. Мы уже начали понимать, какой примерно функционал требует заказчик.
Тучи сгущаются
Прошло половина срока, большая часть работы была уже готова. Модули с табличками были завершены. Два дашборда находились на завершающем этапе. Диаграмма Ганта имела весь необходимый функционал, но всё ещё оставались пару неприятных багов со скроллом и подсчётом праздничных дней.
Ненужные детали
Праздничные дни считались неправильно, потому что с бека приходил неверный контракт, который не учитывал актуальные выходные дни и праздники РФ. К тому же, не было до конца ясно, какие выходные учитывать, а какие нет. Проблема скорее заключалась в недопонимании.А баг со скроллом приводил к тому, что временами заставлял моргать отрисовку или вовсе рендерил объекты на Ганте неверно. Изначально мы реализовали вариант с тем, что горизонтальный скролл был стандартный, а Гант увеличивался в размерах столько, сколько ему было нужно. Такой вариант работал хорошо без сбоев в рендере, но Лид решил заморочиться и сделать иначе. Его концепция предполагала написание виртуального скрола поверх статического канваса с фиксированной шириной. Изменения координат скролла должны были запускать процесс перерисовки всей видимой области Ганта, стирая части позади таймлайна и дорисовывая в конце (при движении вправо, и наоборот — если влево). Идея звучала круто. Он принялся её реализовывать, и, чёрт возьми, это переусложнило логику настолько, что из-за ошибки в пересчёте координат появился этот чёртов баг, с которым он продолжал сидеть неделями.
На руках у нас появилось первое «финальное ТЗ». Но не всё так просто. Оно сильно отличалось от того, что спускали нам ПМ и аналитик. Изменения касались всего: где-то появился новый функционал, а где-то полностью изменилась концепция подсчёта затрат.
Мы принялись переделывать то, что есть. Время утекает через наши ладони. В процессе реализации правок ещё неоднократно появятся новые требования и улучшения, а ни одно ТЗ в этой истории не будет финальным.
Время отвечать
Наша команда утопает в правках, каждую неделю нам спускают пачку «хотелок», и мы послушно начинаем их реализовывать. Срок сдачи уже через неделю, а мы в четвёртый раз перерисовываем дашборды, потому что заказчику захотелось добавить туда ещё пару метрик, которые будут отрисовываться в виде плавающих окошек. Команда разработки уже смирилась с тем, что мы не успеем. Пока директор дивизиона и ПМ вытаскивают нас на очередные выходные, пришёл Кабан Кабаныч…
Эшафот
Кабан Кабаныч в ярости. Неустойка за проваленный контракт 12 млн. Кабан Кабаныч не был осведомлен, что у нас пожар в дивизионе, а осталась неделя. Ауф… Полетели головы… первым уволили директора дивизиона. Все обязанности за завершение проекта возложили на ПМ`а. Аналитика забрали на другой проект. Бекендер уволился незадолго до прихода Кабан Кабаныча. Нам в команду прислали двух синьоров со словами «их время стоит намного дороже чем ваше, используйте его с умом». К нашему сожалению синьоры оказались бутафорскими. Синьор фронт не особо пробовал Vue (говорил, что они такие вещи в своих отделах на Jquery пишут) и другие фреймворки, а синьор бек оставшуюся неделю ждал какие-то доступы вместе со своим коллегой. Так, что за черту невозврата мы вошли с высокооплачеваемыми специалистами с гордо поднятой головой. Команда усиления не помогла, даже коммитов не было. ПМ был уволен сразу. Дивизион расформировали. К фронтам и тестировке вопросов не было, даже наоборот нас сохранили и отправили работать в другие отделы.
Ненужные детали
Я, лид и второй фронт уволились из компании, не отработав и недели в других дивизионах. Акция увольнения была уже спланирована заранее и по одной причине. Дивизион, в который мы пришли изначально, был самым современным в плане технологий и взглядов. Остальные дивизионы отрицали существование фреймворков и современных инструментов. Поголовно всё было написано на jQuery и нативном JS. Очень низкое качество кода и низкая квалификация коллег. Откуда мы это знали заранее? До того как попасть на госзаказ, каждый из нас уже успел поработать в других командах на усилениях. Истории там были забавные. Да и связывать себя с Битриксом не было желания.
Кто виноват?
Кто виноват в этой ситуации — решайте сами. Разработчики, которые не справились, несмотря на всяческие усиления? Или директор дивизиона с ПМ, которые принимали все правки, не оговорённые контрактом, и без увеличения срока исполнения, в добавок не оповещали руководство о проблемах? А может, Кабан Кабаныч, который пришёл проверить важный госзаказ только за неделю до дедлайна? Кто знает…
Возможно, стоило «дать заднюю», когда тимлид позвонил по телефону, а не назначил встречу в Google Meet)))