Документация, управление релизами и разделение ответственности: как упростить разработку
Платформа Android работает с несколькими продуктами и с разным функционалом. Но всех нас объединяет одна операционная система и выверенные общие принципы работы и организации — именно они помогают нам делать надёжные продукты, которыми миллионы людей пользуются каждый день: СБОЛ, СберБизнес Онлайн, СберИнвестор Х, СберKids, Салют и другие.
Первое, где нужно навести порядок — это документация. Представьте, что ваша команда начинает новый проект: кто-то вспоминает, что в компании уже была реализована подобная задача, но никаких следов не осталось. Но если бы предыдущая команда вела документацию, всё было бы намного проще. У нас процесс документирования стандартизирован — есть определённый подход к любой новой функциональности, которую мы выпускаем. Мы работаем в Confluence — описываем любой новый функционал в качестве некой аналитики, которая потом согласовывается бизнесом, безопасниками и самими разработчиками. Когда ведётся разработка нового функционала, открывается новая страница аналитики. Там же мы ведём большой блок с рекомендациями (гайдами) по использованию и развитию тех или иных возможностей продукта — например, как должна выглядеть архитектура и выполняться сетевые запросы в приложении. Это очень помогает новичкам влиться в продукт и облегчает процесс ревью кода.
Про код-ревью.
Вообще, стоит сказать про процесс код-ревью. У нас миллионы строк кода. В какой-то момент может быть не очень понятно, кого добавлять в ревьюеры, а кого не добавлять, кто отвечает за какой код. На Atlassian Bitbucket мы создали систему лейблов (идентификаторов для более удобного указания данных и кода в языках программирования) и владельцев кода. В каждом gradle модуле у нас написан собственный плагин, и у каждого модуля есть свой владелец (какая-то команда). Плагин применяется во всех модулях приложения и позволяет указать команду-владельца. Соответственно, при создании пул-реквеста в модулях в обязательном порядке добавляются владельцы этих модулей, без аппрува которых невозможно изменить код.
Также у нас код обязательно покрывается Java документацией (javadoc). Поскольку именно код содержит самую актуальную информацию — в первую очередь меняется код, а потом может быть уже доработана документация в Confluence. Вообще, основной объём нашей документации — в коде. Это позволяет не лезть глубоко в него, а на верхнем уровне проанализировать метод (или функция — блок кода с инструкциями), что значительно упрощает разработку. А ещё мы регулярно проводим unit- и ui -тестирование — это тоже правильный принцип ведения технической документации.
Важно грамотно выстроить процесс управления релизами для поддержания качества продуктивной среды, увеличения скорости выпуска изменений и уменьшения риска несогласованности между командами. У нас непрерывный стабильный процесс релизов — 1 релиз в 3 недели.
Когда релизная ветка отведена, одними из обязательных ревьюеров являются члены релизной команды, которые следят за тем, чтобы никто не пытался добавлять фичи в релизную ветку – здесь, кстати, очень эффективной оказывается наша механика с лейблами. Релизные ветки постоянно формируются в сборки, которые автоматически отправляются тестировщикам, чтобы они не тратили время на поиск последней версии или доработки. У нас это реализовано с помощью Jenkins. Ещё мы написали скрипт, который уведомляет по почте о том, что такая-то сборка опубликована по такой-то ссылке. Это очень удобно.
Естественно обязательным условием аппрува релиза являются успешные UI- и unit -тесты. И, конечно, всегда тестим код на качество с помощью SonarQube и SonatLint.
Ну и, наконец, третье – для качественной разработки важна продуманная структура команды. У нас очень сильное деление на команды. Есть фичёвые команды, работающие с платежами, кредитами, профилями и т.д. Есть команда android- платформы – она отвечает за архитектуру, владеет техдолгом и управляет зависимостями проекта. Команда дизайн-системы даёт возможность всем командам, нуждающимся в UI, использовать уже готовые элементы. Релизная команда позволяет, например, фичёвому разработчику не лезть в core-функционал , в зависимости проекта, в стейт машину. Или проверяет, чтобы разработчик в своём пул-реквесте не принёс новый функционал в релизную ветку. Благодаря такой жёсткой фиксации функционала и ответственности за его реализацию у нас слаженно и выверенно выстроены процессы.