[button color=4d61d7 icon=arrow-left-2 url=https://apptractor.ru/develop/grigoriy-petrov-tehnicheskiy-dolg-i-kak-ego-otdavat.html] Предыдущая статья [/button]
Как я уже писал в предыдущих колонках, корень большинства проблем при разработке программных продуктов — это медленно, не неотвратимо накапливающаяся сложность. Опираясь на уже рассказанное, я могу выделить следующие основные источники сложности в проекте:
- Количество кода. Чем больше в проекте кода — тем выше сложность проекта.
- Не отданный технический долг добавляет много сложности, так как нарушает целостность архитектуры.
- «Старый» код, который «жалко» удалять из проекта также добавляет сложность. Несмотря на то, что он хорошо знаком «старожилам» и экономит им слоты кошелька Миллера, для новых членов команды такой код будет нести дополнительную сложность, так как уже устарел относительно архитектуры.
При этом у сложности есть неприятная особенность: во всех случаях она прямо пропорциональна содержащейся в программе информации. Сложность нельзя убрать саму по себе, можно лишь удалить порождающую ее информацию. Или переместить из одного места в другое. Вот об этом перемещении сложности мы сегодня и поговорим.
Где находится гнездо сложности?
Сложность прямо пропорциональна количеству информации, которое содержится в коде. А где в коде содержится информация?
- Непосредственно текст кода, описывающий поведение программы с помощью одного или нескольких языков программирования.
- История изменений кода в системе контроля версий, описывающая эволюцию архитектуры программы, содержащая комментарии к коммитам и позволяющая ответить на вопросы «каким образом код стал таким?» и «зачем это сделано?».
- Закрытые задачи в системе управления задачами, ссылающиеся на изменения кода в системе контроля версий. Они содержат информацию о том, какие задачи решает этот код, и какие ошибки он исправляет.
- Статьи в системе управления знаниями, описывающие основные заложенные при разработке концепции, принятые высокоуровневые архитектурные решения, историю проблем и то, как они решались, заметки о возможных путях развития проекта.
- Комментарии в коде, содержащие информацию, которая не влезла в системы управления версиями, задачами и знаниями.
- Вспомогательные утилиты: системы сборки, кодогенераторы, системы проверки кода и прочие, содержащие информацию о том, как код проекта превращается собственно в работающий программный продукт.
- Готовые библиотеки и фреймворки, содержащие информацию о функциональности, которую код не реализует сам.
Уменьшить сложность без уменьшения функционала нельзя, а вот переносить между разными частями программы — можно и нужно.
Предотвращаем накапливание сложности в одном месте
Не буду пересказывать здесь свою лекцию по работе с информацией в коде, вы всегда можете найти ее и другие мои выступления на youtube по ссылке выше. Сложность опасна только тогда, когда она скапливается в одном месте, обычно в какой-то части кода. Одна из задач управления разработкой, как я ее вижу — это отслеживание сложности в проекте и обеспечение того, что команда разработки вовремя ее переносит.
О технической стороне переноса сложности из одного места в другое, более известной как «рефакторинг», я рассказывать не буду. Этот цикл статей больше по управлению, нежели по написанию кода, поэтому желающие могут посмотреть мои видео и почитать замечательные книги «Совершенный код» Макконнелла и «Рефакторинг» Фаулера.
Практика показывает, что большинство разработчиков стараются предотвращать скапливание сложности на инстинктивном уровне. Многие из вас слышали от разработчиков фразы «нужен рефакторинг» — это оно. К сожалению, на практике менеджеры не всегда уделяют этим задачам много внимания, что приводит к одним и тем же последствиям: сложность накапливается, код теряет поддерживаемость, проект теряет управляемость.
Кому следить за сложностью?
В идеальном мире разработку организуют три человека:
- Product Manager (начитавшиеся SCRUM’а часто называют его Product Owner) знает, как должен выглядеть конечный продукт, занимается изучением рынка, конкурентов, тестирует получившееся на людях и определяет в какой последовательности что делать.
- Team Lead руководит командой разработчиков и обеспечивает их совместную работу, чтобы в результате получился целостный продукт, а не кучка несвязанных частей.
- Project Manager обеспечивает, чтобы все эти замечательные ребята не передрались между собой и хоть как-то уложились в сроки, бюджет и риски.
На практике роли часто совмещают: один человек выполняет роли Project’а и Product’а, в роли Team Lead нередко выступает один из разработчиков, или же Team Lead берет на себя еще и административную работу Project Manager’а. А тут еще и сложность надо отслеживать.
Рекомендации лучших собаководов
Хорошо зарекомендовал себя подход, при котором в самом начале работы все участники договариваются об отслеживании сложности проекта и о том, как именно менеджер будет инициировать процедуры по ее переносу. Как будет выделяться время? Как это будет объяснено внешнему заказчику (если он есть)? Как будет считаться приоритет этих задач относительно функциональности продукта? Кто будет принимать решения и ставить задачи? Чем прозрачнее и проще будет договоренность — тем эффективнее будет борьба со сложностью.
Традиционно отслеживание сложности возлагается на нехрупкие плечи тимлида. В одной из следующих колонок я подробно расскажу про типичный набор обязанностей этого загадочного бойца, а пока ограничусь той частью, которая относится к распределению сложности по проекту. Каждый рабочий день Team Lead смотрит написанный разработчиками код. Смотреть код можно с разными целями: искать ошибки, проверять общий стиль кодирования, соответствие архитектуре. А для отслеживания сложности нужно оценивать то, как архитектура проекта разбита на части и насколько высока сложность каждой из этих частей.
Затем тимлид каким-либо способом делает себе пометки о сложности разных частей продукта. Про этот вопрос мы тоже подробно поговорим в одной из следующей колонок: пометки можно делать в Google Sheets, в самом исходном коде, в системе контроля версий и много где еще. Но главное тут — это их делать. Планомерно, регулярно и целенаправленно. Один-два раза пропустили «потому что очень спешили» — и все, команда радостно делает вид, что ни за какой сложностью следить не надо. Разработчики любят делать то, что им интересно — изучать новые технологии, творить код. Никто не хочет скрупулезно каждый день записывать распределение сложности по проекту. А нужно.
В качестве вспомогательных инструментов можно использовать автоматизированные системы поиска сложности. Обычно это утилиты, которые запускают во время автобилда и статически (без исполнения) анализируют текст кода. Рассчитываемое значение очень схематично: количество условий на метод, количество методов в классе и так далее. Но схематичность перевешивает плюс автоматизации. Достаточно один раз настроить анализ сложности — и каждое утро программа будет радовать разработчиков почтовой рассылкой или изображением на одном из мониторов, явным образом сигнализируя, где в проекте могут быть проблемы.
За сим, пожалуй, все. Кстати, мои уважаемые читатели, сегодня знаменательный день: мы закончили с вводной частью. Эти девять статей были введением в управление разработкой, в котором я определил нужные термины и схематично обрисовал стоящие перед нашей индустрией проблемы. В десятой колонке я подведу промежуточный итог, кратко резюмировав уже изложенное. Надеюсь, это послужит хорошим фундаментом, опираясь на который я смогу дальше рассказывать о страшных, но интересных вещи: зачем на самом деле нужен Scrum, зачем разработчикам английский язык, как готовить автобилд, о роли юнтов в юнит-тестах и о многом другом. Оставайтесь с нами!
- Григорий Петров: Управление разработкой. Специфика разработки
- Григорий Петров: Управление разработкой. О научной дисциплине
- Григорий Петров: Управление разработкой. Специализация
- Григорий Петров: Управлять можно только тем, что можно измерить
- Трудности проектирования
- Григорий Петров: Изменяющиеся требования — проклятье индустрии
- Григорий Петров: Как размазывать сложность тонким слоем
- Григорий Петров: Управление разработкой. Вводный курс
- Григорий Петров: О магии в разработке