Привет, Хабр! Сегодня я хочу поговорить о таком незначимом на первый взгляд понятии, как техническая зрелость продукта (ТЗП). В этом посте мы коснемся самого понятия, попробуем разобраться, из чего зрелость состоит, как ее измерить, а самое главное — как ее достичь и какой она, собственно, должна быть. Я расскажу о том, как сам оцениваю ТЗП и каких принципов придерживаюсь при формулировании критериев зрелости, а также о том, к каким проблемам приводит недостаточная зрелость продукта. Если вам интересно, налейте в стакан любимый напиток — и добро пожаловать под кат.  Меня зовут Иван Головащенко, и я работаю руководителем разработки в «Леруа Мерлен». Помимо помощи коллегам и выстраивания процессов разработки, основную часть времени я занимаюсь созданием backend-приложений, и поэтому в статье буду размышлять про невидимые глазу пользователя системы, вращающиеся в jvm. Но в целом описанные мысли, термины и рекомендации могут быть применены для продуктов, разрабатываемых на других технологических стеках. Давайте для начала разберемся с самим понятием. Не будем для этого лезть в словари и википедию — достаточно просто определиться, что для вас должна выражать зрелость. Предлагаю свой вариант толкования. Зрелость продукта — это такое состояние, при котором:  этим самым продуктом клиенты могут пользоваться и не испытывать головной боли; те, кто поддерживает этот продукт, могут без труда устранить возникшую в нем неисправность; его развитие происходит легко и с минимальными затратами мыслетоплива (термин Дорофеева — подробнее тут); приятно владеть продуктом, улучшать его, не стыдно показать продукт своим коллегам по IT-цеху; наконец, улучшение продукта приносит моральное удовлетворение его владельцу Как видите, понятие зрелости требует комплексного подхода к осознанию. Первое, что приходит на ум разработчику, не знакомому с принципами ТЗП, — это, следуя за трендами программной индустрии, обновить все версии используемых в системе библиотек до новейших и перейти на микросервисную архитектуру (если вы все еще «сидите на монолите»). Но поднимется ли за счет этого уровень зрелости продукта? Далеко не всегда. Исходя из определения выше, несложно выделить основные направления, изменения в которых помогут нашему продукту стать зрелым. Для себя я сформулировал следующую «золотую пятерку». Документация — с четкой структурой от блока к блоку, понятная человеку, не принимающему участия в развитии продукта, она должна быть написана на языке читающего и находиться в актуальном состоянии. В документации должны быть описаны все необходимые контракты взаимодействия как внутри самой системы, так и со смежными, с примерами запросов API. А для лучшей наглядности необходимо либо сопровождать документацию ссылками на архитектурные доски, либо добавлять архитектурные схемы. Поэтому связанные блоки документации должны быть залинкованы. Архитектура —   точно описанные структурные, функциональные и/или принципиальные схемы, находящиеся в актуальном состоянии. Технологии — современный, но при этом устоявшийся (проверенный некоторым временем) набор технологий, фреймворков и библиотек, надежный и быстрый pipeline поставки ценности, стабильная среда развертывания и жизни продукта. Тестирование — полностью покрытый unit-тестами код, а также наборы различных тест-кейсов, необходимых для фиксации и проверки ожидаемого состояния системы. Метрики и сопровождение — бизнесовые и технические метрики жизнеспособности и работоспособности продукта, а также своевременный алертинг при отклонении системы от выставленных для нее SLA и SLO на этапе проектирования. Это, конечно, минимальный набор, и представлен он здесь скорее в качестве примера. На практике для оценки ТЗП пятерка может быть трансформирована в чек-лист из нескольких десятков пунктов (критериев ТЗ), чтобы вы могли отметить каждый из них как выполняющийся либо невыполняющийся.  Лишь не упустив всех критериев и заполнив чек-лист, можно будет понять, насколько высок уровень зрелости. Но, как правило, не доходит даже до составления этого списка… Хотя именно он позволяет сделать вывод и подумать, может ли что-то принести Вам ощутимое улучшение ТЗП и запланировать работы по выполнению критерия. Кажется, тут все просто. Виной тому может быть множество причин, начиная с недостаточной компетенции или опыта сотрудников, заканчивая нехваткой ресурсов, времени или желания. Но разве кто-то хочет целенаправленно сделать свой продукт «незрелым»? Конечно, нет! И хотя сегодня в нашей команде и в компании в целом зрелость систем поддерживается на хорошем уровне, мне удалось в свое время поработать на проектах, где ТЗП была на низком уровне. Документация хранилась в word-файлах на компьютерах у аналитиков и разработчиков в плохо структурированном виде. Приложение разворачивалось на linux-серверах вручную (фактически не был настроен ci/cd pipe). Не был настроен мониторинг функционирования системы. О возникших проблемах узнавали лишь от конечных пользователей. Обратная связь от пользователей проходила через несколько отделов, и, разумеется, не была своевременной.  Владелец продукта не обсуждал планы развития с командой, а просто спускал задачи на подчиненных. На самом деле работать с такими продуктами достаточно тяжело. И, хоть это не очевидно, большое количество времени (а, следовательно, и денежных средств компании) уходило впустую. Продукт разрабатывался и развивался намного медленнее, чем мог бы. Отсутствие документации не позволяло быстро погрузить нового сотрудника в проект. Отсутствие архитектурной схемы снижало скорость погружения сотрудника в продукт. Без технического мониторинга доступности сервисов нельзя было точно сказать, работает система или нет в данный момент. Без SLA не было ясно, как работает наша система: то ли все стабильно и поэтому все довольны, то ли она дико лагает, но пользователи не обращают на это внимания или не жалуются. Без нагрузочного тестирования мы не знали, какова пропускная способность нашей системы. Было непонятно, в какой момент мы просто уперлись бы в  производительность при росте нагрузки. Использование старых версий библиотек не позволяло эффективно писать код Уязвимости могли в самый неподходящий момент выстрелить. И мы представления не имели, каков уровень рисков на данный момент времени. Все это  — неприятно, плохо и дорого. Но самое главное, что всего этого можно было бы избежать, если бы мы задумались о ТЗП и попытались ее измерять и улучшать по мере необходимости. На самом деле я размышляю о ТЗП достаточно давно и для себя пришел к некоторому алгоритму ее вычисления. Представлю здесь следующую упрощенную схему: Определяем блоки, из которых состоит техническая составляющая нашего продукта. Собираем все критерии, применимые к продукту, и помечаем их в качестве выполненных или нет. При этом, проставляя галочки, нужно придерживаться такого правила: либо критерий выполнен полностью, либо, если есть сомнения в его готовности, мы считаем его невыполненным. Делим критерии по блокам, о которых мы говорили выше. Список блоков должен быть уточнен в соответствии со спецификой продукта. По критерию блока определяем его вес, исходя из того, что сумма всех весов должна составлять 100 баллов. Отметив галочками выполненные критерии, подсчитываем итоговый рейтинг по каждому блоку. По каждому блоку определяем вес блока, исходя из того, что сумма весов всех блоков должна давать 100 (без итогового рейтинга блока из п. 4). В соответствии с весом каждого блока (т. е. если в блоке было набрано 50 баллов, значит, итоговый вес блока должен быть равен 50% от веса блока, определенного в предыдущем пункте) подсчитываем итоговую оценку по 100-балльной шкале. Допустим, мы разрабатываем с нуля элементарный продукт — каталог фильмов. Для этого используем следующий стек технологий: kotlin, spring-boot, mongodb, k8s, grafana, prometheus, elk. Задача MVP продукта – отдавать каталог фильмов в разрезе жанра, года выпуска и прочих полей, фильтрующих выдачу. Какие пойнты в чек-лист ТЗП мы можем добавить на первых этапах? Попробуем посчитать ТЗП. Если критерий выполнен - чек бокс отмечен галочкой, если нет - оставлен пустым. Цифры — это вес поля или блока. Итого у нас получается: Документация. (25 + 25)% от 15 = 7.5 Архитектура. (40 + 30)% от 15 = 10.5 Технологии. (20 + 20 + 10)% от 30 = 15 Тестирование. 35% от 25 = 8.75 Метрики и сопровождение. (30 + 10)% от 15 = 6 Суммируем все блоки (7.5 + 10.5 + 15 + 8.75 + 6) и получаем 47.75. Почти 48 баллов на старте — достаточно неплохо, но есть еще простор для совершенствования ТЗП. В данном случае я бы рекомендовал довести ТЗП до 65-70 баллов. Хотя опять же приемлемый уровень ТЗП должен быть определен командой вместе с владельцем продукта. Конечно, показатель ТЗП не только должен быть принят коллективом, но также должен коррелировать с фазой жизненного цикла продукта. Например, на начальном этапе высокий уровень ТЗП может позволить быстрее развивать продукт, но трудозатраты, вложенные в ТЗП, могут быть слишком высокими и непомерными на ранних стадиях внедрения. Но если мы как команда чувствуем, что темпы роста стали снижаться, то самое время начать задумываться о росте ТЗП. Это может позволить в будущем увеличить темпы развития продукта и/или тратить меньше времени на поддержку продукта, вышедшего на плато, и переключиться на новые продукты. Также наработанный уровень ТЗП одного продукта может быть применен на старте другого, что изначально позволит существенно ускорить темпы развития без потери качества технической составляющей. 100% зрелость будет говорить о том, что совершенствовать продукт с технической точки зрения уже некуда. Но мир не стоит на месте, все время появляются новые инструменты, улучшающие работу или оптимизирующие издержки. Поэтому в вопросах ТЗП не стоит быть излишне консервативным. Нужно время от времени обновлять свой чек-лист, добавлять в него новые пункты. Думаю, возвращаться к этому стоит хотя бы раз в квартал. А в крайнем случае — раз в год, не реже. Иначе устаревшая оценка зрелости может привести к самообману и снизить темпы развития и качество поддержки продукта. Это отличный вопрос, отвечать на который можно только с учетом специфики разрабатываемого продукта. Однако есть и общие рекомендации. Можно поискать best practice по написанию кода, документации, тест-кейсов, мониторинга, взять оттуда лучшее, реализовать на приемлемом уровне ТЗП. Как правило, понимание минимальной ТЗП может быть уже сформулировано в компании. Например, я часто сталкивался с тем, что разработчики изначально договариваются использовать определенный балансировщик нагрузки, брать СУБД только из утвержденного в компании списка, настроить алертинг в Grafana on call, использовать централизованное хранилище документации, кода, тестов, придерживаться единого стиля кода, скриптов, разворачивать приложения в k8s, не использовать незащищенные протоколы, придерживаться restful-архитектуры, настраивать runtime-бекап базы данных и так далее. И все это идет на пользу ТЗП. При этом очень важно учитывать и человеческий фактор. И здесь, исходя из своего опыта, я позволил бы ряд рекомендаций. Проводить встречи с владельцем продукта, на которых он будет рассказывать о состоянии бизнеса, планируемых задачах и потенциальном масштабировании. Желательно оформлять все это в виде осмысленной дорожной карты. Наладить своевременную обратную связь от пользователей. Ведь технические специалисты, имеющие контакт с клиентами, как правило, стараются улучшить свой продукт. Выстроить в коллективе атмосферу взаимного понимания и уважения. Сплотить команду вокруг общей идеи развития бизнеса и дать участникам возможность ощущать свой вклад в продукт. Кстати, на сегодняшний день для меня лично это является важным фактором комфорта в работе. Быть открытыми настолько, насколько позволяет ситуация. Вообще достижение зрелости очень зависит от команды. И здесь важно найти тонкую грань. Я уверен, что заставлять наращивать ТЗП точно никого не нужно. Насильно мил не будешь, как говорят. Важно создать такие условия труда, при которых у участников команды зародилась бы любовь к продукту, коллективу, чтобы они ощущали ценность своего труда, имели адекватное вознаграждение и получали удовольствие от процесса разработки и сопровождения. Но о том, как выстраивать отношения в команде, кому доверять заботу о ТЗП, мы обязательно поговорим в следующем моем посте.  Руководитель разработки