Как рефакторить большие системы

Это первая вводная статья из цикла про рефакторинг больших систем. В ней я опишу продукт, департамент, в котором я находился, а так же расскажу про то, какие методы оценивания состояния системы можно использовать.

Как рефакторить большие системы

Любая, даже хорошо спроектированная система, начинает деградировать под влиянием изменения бизнес-процессов, течением времени, уходом ключевых сотрудников, уменьшением технической компетенции внутри компаний, бюрократии. При отсутствии должного внимания, ретроспектив, сбора метрик - процесс деградации системы ускользает. Советую почитать http://www.agile-process.org/change.html и https://www.overcomingbias.com/p/why-does-software-rothtml

Сейчас я занимаю должность руководителя отдела и роль технического лидера клиентской части приложения в департаменте последние несколько лет. Мы разрабатываем большой B2B продукт уже больше 8 лет. Последние 7 лет он разрабатывался в "стол" - те, не имел продакшена, а после первого релиза core команда (почти все лиды, разработчики, которые стояли у истоков продукта) - ушли. Я застал буквально пару месяцев работы этой команды и особо не могу поделиться их процессами, но у меня сложилось ощущение, что они в каком-то виде были - проводились ретро, стендапы, существовало взаимодействие между командами. Но вот о чем я точно могу рассказать - о техническом состоянии продукта.

Клиент: Написан на полимере 2 версии(умерший фреймворк гугла, который чем‑то похож на вью). Существуют «огрызки» нового клиента, написанного на современном стеке технологий, но имеющий ряд проблем:

  • Вся разработка велась в сторибуке, нельзя было запустить приложение целиком;
  • Сложная структура — использовался монорепозиторий nx, диктующий свою структуру директорий, которая была неправильно внедрена(циклические зависимости библиотек, порядка 100 nx‑библиотек без понятных границ ответственности);
  • Использование большого количества бездумно выбранных внешних библиотек.

Бекенд: ~80 микросервисов, которые объединены в один архитектурный квант, имеют циклические зависимости сервиса от сервиса и ходят в одну монгу.

Инфраструктура: Каждый сервис имеет свой конфигурационный файл, есть куча ансибл скриптов и почти что ручная выкатка всей системы на стенды.

В департаменте используется матричная структура организации, но дизайнеры находятся в отдельном департаменте, а разработка представляет из себя такую схему:

Структура департамента
Структура департамента

На самом деле, команд больше 15 штук, но для упрощения схемы я указал лишь несколько.

После ухода core команды появилось много "дыр" на позициях руководителей, особенно руководителей команд. Из-за этого пришлось закрывать их разработчиками, которые не обладали необходимыми компетенциями. Что еще хуже, управлением всех кросс-функциональных команд взяли на себя бекенд разработчики.

По всем вводным предпосылкам, продукт стал напоминать "зомби", те, весь "мозг", который должен был управлять ушел, а новые люди на местах еще не умеют работать с мотивацией своих сотрудников, планировать, здраво оценивать сроки. Все встречи на которых нужно обсуждать общий вектор развития продукта превратились в обсуждения проблем бекенда, а их ценность с течением времени только уменьшалась. Было ощущение, что команды что-то делают, но нет общего понимания куда мы идем, потеряна коммуникация между командами. В такой конфигурации решение глобальных проблем становится затруднительным, а иногда невозможным.

На тот момент я был сеньор фронтенд разработчиком и вызвался разобраться с новым клиентом и довести его до продакшена. Я и представить не мог, насколько глубоко мне придется окунуться в продукт и в процессы разработки для решения проблемы. У меня не было большого опыта управления, очень многих проблем я бы мог избежать, решить задачи и проблемы оперативнее. Я хочу поделиться с вами своим частным опытом, и теми практиками, которые помогли в моем случае. Управление людьми и процессами достаточно сложно применять универсально и каждый случай нужно рассматривать отдельно.

С чего стоит начать:

Прежде чем начать рефакторинг нужно понять какие запросы на нашу систему у бизнеса. Есть такое понятие, как жизненный цикл продукта. Обычно, если мы говорим про B2B, завершающей стадией продукта, является поддержка, те, остались клиенты, готовые платить за продукт, но дальнейшее его развитие и масштабирование не является рентабельной или не интересует бизнес в данный момент. Продукт в таком состоянии не нуждается в глобальных рефакторингах и даже, если он написан на более неиспользуемых технологиях можно будет нанять инженеров, готовых работать с легаси по верху вилки и чинить редкие пожары.

Если же ожидается дальнейшее развитие, бурный рост продаж, новые клиенты, расширение штата сотрудников, то на таком этапе жизни продукта целесообразность новой итерации, большого количество доработок можно считать оправданой. Мы потратим ресурсы и деньги компании на решение технических проблем, а бизнес получит более стабильный продукт, широкий выбор специалистов на рынке труда, возможность быстрее деливерить фичи.

Если мы определили, что бизнес планирует дальнейшее развитие, то мы можем начать оценивать текущее состояние системы по метрикам. Они бывают 2 видов:

  • Технические
  • Менеджерские

Технические метрики - метрики, которые мы можем снять с "самой системы". Предлагаю кратко ознакомится с некоторыми из них:

1. Время отклика (Response Time)

Это время, за которое система отвечает на запросы пользователей. Увеличение времени отклика может свидетельствовать о нагрузке на систему или проблемах с производительностью.

2. Нагрузка на ЦП и память (CPU and Memory Load)

Высокая загрузка процессора и оперативной памяти может быть признаком перегрузки системы или утечек памяти. Это особенно важно для серверов приложений и баз данных.

3. Пропускная способность сети (Network Throughput)

Измерение объёма данных, передаваемых по сети. Снижение пропускной способности или увеличение задержек в сети могут приводить к деградации производительности.

4. Частота ошибок (Error Rate)

Увеличение количества ошибок (например, 500-е ошибки в веб-приложении) может свидетельствовать о внутренних проблемах системы, таких как сбои серверов, проблемы с базой данных или конфликты кода.

6. Время отклика базы данных (Database Response Time)

Если время выполнения запросов к базе данных начинает расти, это может сигнализировать о проблемах с оптимизацией запросов, индексацией или перегрузке сервера базы данных.

7. Уровень отказоустойчивости (Fault Tolerance)

Измеряется способностью системы продолжать работу при возникновении отказов. Если система не может восстанавливаться после сбоев, это ухудшает её отказоустойчивость.

8. Доступность системы (System Availability)

Время, в течение которого система доступна для пользователей. Снижение этого показателя может указывать на серьезные проблемы с инфраструктурой.

9. Ошибки конфигурации (Configuration Errors)

Возникают при неправильной настройке серверов, сервисов или приложений. Увеличение таких ошибок может указывать на деградацию в управлении конфигурациями.

Основным их недостатком я считаю возможные сложности в подсчете. Если у продукта отсутствует логгирование/нет продакшена/разработка ведется хаотично/продукт очень большой, то собрать эти метрики за короткий срок бывает тяжело. Поэтому, я бы для начала попробовал собрать менеджерские метрики, а для технических составил бы план на их развитие и дальнейший сбор.

Менеджерские метрики - это метрики, которые можно снять по артефактам работы команды/отдела/департамента, используя инструмент управления рабочим процессом - как один из самых известных - Jira. Вот примеры некоторых из них:

1. Количество открытых задач (Open Issues)

Это общее число задач, которые остаются невыполненными. Увеличение этого числа может свидетельствовать о проблемах с приоритетами или о перегрузке команды.

2. Время выполнения задачи (Cycle Time)

Измеряет, сколько времени требуется команде для завершения задачи — от начала работы над ней до закрытия. Это помогает оценить скорость выполнения задач и может выявить «узкие места».

3. Время в очереди (Lead Time)

Это время с момента создания задачи до её завершения. Разница между Lead Time и Cycle Time показывает, сколько времени задачи проводят в состоянии ожидания перед тем, как команда начинает над ними работать.

4. Среднее время до разрешения (Mean Time to Resolution)

Эта метрика помогает понять, как быстро команда решает задачи, будь то баги, задачи поддержки или разработки.

5. Скорость выполнения задач (Velocity)

Velocity — это количество задач (или story points), которые команда завершает за спринт. Это важный показатель производительности для agile-команд. Снижение скорости может указывать на проблемы с планированием или перегрузку.

6. Долгоживущие задачи (Aging Issues)

Задачи, которые остаются открытыми дольше обычного, могут быть признаком блокеров, недостаточной приоритезации или проблем с ресурсами. Jira позволяет настроить отчеты для отслеживания таких задач.

7. Количество перезапусков задач (Reopened Issues)

Задачи, которые были закрыты, но затем вновь открыты, могут свидетельствовать о проблемах с качеством работы или недостаточной проверке выполненных задач.

8. Количество задач по приоритетам (Issues by Priority)

Этот отчет показывает, сколько задач открыто для каждого уровня приоритета (высокий, средний, низкий). Слишком много задач с высоким приоритетом может сигнализировать о перегрузке команды и снижении эффективности.

9. Диаграмма выгорания (Burn Down Chart)

Используется для оценки прогресса по выполнению задач в спринте. Она показывает, насколько быстро команда завершает работу по задачам, и помогает выявить отклонения от плана.

10. Эффективность исправления багов (Bug Fixing Time)

Эта метрика измеряет время, которое команда тратит на исправление багов, что может указывать на качество кодовой базы и эффективность команды в решении проблем.

11. Технический долг (Technical Debt)

Отслеживание задач, которые связаны с устранением технического долга, позволяет команде контролировать, не откладываются ли критические улучшения или рефакторинг.

12. Количество зависимых задач (Blocked Issues)

Отображает количество задач, которые заблокированы и не могут быть выполнены из-за зависимости от других задач или проблем. Это полезная метрика для управления приоритетами и ресурсами.

Я привел достаточно большое количество разных метрик. Нужно понимать, что их показания носят скорее косвенный характер и делать вывод только на их основе может быть ошибочно из-за специфики продукта, допустим. А применение санкций или поощрений только по ним, согласно закону Гудхарда , в какой-то момент может привести к смещению основной цели команды с развития продукта, на соблюдение метрик. Не стоит уходить в метрики с головой и пытаться собрать их все. Набор наших метрик будет являться для нас ориентиром во время рефакторинга (с течением времени показания должны улучшаться) и соотношением нашего субъективного видения продукта с его настоящем состоянием.

В статье я познакомил вас с предпосылками и кратко описал проблемы, которые были в департаменте. А так же мы разобрали первый шаг перед рефакторингом - оценили необходимость этого у бизнеса и метрики по которым можно оценить деградацию системы. В следующих частях мы рассмотрим как рефакторить процессов и продукта, а так же жизнь после него.

Начать дискуссию