Помните, когда у вашей машины была 5-ступенчатая трансмиссия и карбюратор, с которым можно было повозиться? Да, я тоже не помню — но инженерам они нравились. Почему? Потому что этот «неэффективный» дизайн учил их тому, как на самом деле работают автомобили. Сегодняшняя индустрия программного обеспечения одержима максимальной эффективностью, и я здесь, чтобы утверждать, что мы оптимизируем некоторые из самых ценных аспектов нашего ремесла.
Культ эффективности, который мы создали
Давайте будем честными: мир разработки программного обеспечения в настоящее время охвачен тем, что я называю «манией эффективности». Цифры повсюду, и они ужасающие. Отраслевые исследования сообщают, что 92 % команд сталкиваются с неэффективными рабочими процессами разработчиков, а в крупных компаниях ошеломляющие 60 % разработки программного обеспечения считаются потраченными впустую. Эти статистические данные вызывают панику в руководящих органах компаний и создают почти религиозное стремление к «оптимизации» всего.
Давление безжалостно: устраните ненужные встречи, автоматизируйте обзор кода, сократите документацию (если только это не «правильный» вид документации), сократите сроки планирования и, ради всего святого, измерьте всё. Мы создали целые консалтинговые индустрии вокруг оптимизации разработки программного обеспечения. И да, я понимаю привлекательность. Когда вы теряете производительность, вы хотите остановить кровотечение.
Но вот где, я думаю, мы коллективно свернули не туда: в нашем стремлении устранить неэффективность мы систематически удаляем те самые практики, которые формируют экспертизу, выявляют тонкие ошибки и создают устойчивое программное обеспечение.
Скрытая стоимость идеальной эффективности
Представьте себе самого эффективного разработчика, которого вы знаете. Он пишет код с молниеносной скоростью. Он пропускает обзоры кода, потому что уверен — и, честно говоря, обычно он прав. Он не тратит время на «избыточное» тестирование, потому что знает свои шаблоны. Он документирует минимально, потому что код «самообъяснителен».
Теперь представьте этого разработчика в своей команде через пять лет. Он стал узким местом. Никто другой не понимает его код. Он накопил значительный технический долг, потому что оптимизация под его собственную скорость никогда не учитывала поддерживаемость. Он достиг предела производительности, потому что ему никогда не приходилось отстаивать свои архитектурные решения перед кем-то более осведомлённым в определённой области.
Нас учат, что автоматизация повторяющихся задач помогает разработчикам зарезервировать время для роста, и это правда — частично. Но что, если часть этого повторения на самом деле является механизмом роста? Что, если «неэффективность» сидения на обзоре кода в течение 90 минут, отстаивая своё решение перед товарищем по команде, как раз и является тем, где вы учитесь?
Недооценённая ценность «расточительных» действий
Позвольте мне разобрать некоторые действия, которые считаются неэффективными, но на самом деле весьма ценны:
Обзоры кода, которые занимают много времени
Инженерная команда Microsoft известна тем, что автоматизировала процесс обзора кода с помощью внутреннего инструмента под названием CodeFlow, сократив время обзора на 90 %. Фантастический результат, правда? Кроме скорости, они также получили бонус: меньшее трение между командами, замкнутые циклы обратной связи и лучшие «рукопожатия».
Но что они потеряли? Случайный момент обучения. Вы знаете тот — когда вы просматриваете чей-то код и думаете: «О, это умно, я никогда не видел такого шаблона раньше». Или когда вы ставите под сомнение подход, и автор должен сформулировать свои мысли, что иногда выявляет предположения, которые не были подтверждены.
Я не говорю, что мы должны отвергнуть автоматизацию. Но давайте будем реалистами: инструмент, который обрабатывает отзывы об обзоре кода, — это не то же самое, что человек, который понимает домен, контекст бизнеса и долгосрочное состояние команды, просматривающий код.
Документация, которую никто не читает
Нам говорили, что код должен быть самодокументирующимся, и до определённой степени это правда. Но команды, которые сосредотачиваются на взаимосвязи между кодом и документацией, видят повышение качества кода на 30 % и сокращение времени на обновление документации на 25 %. Эта «неэффективность» ведения документации служит цели: она заставляет вас думать о том, что вы создаёте, с другой точки зрения.
Проблема не в документации — проблема в плохой документации, написанной ради галочки. Но наличие документации, даже если она кажется избыточной, когда вы глубоко погружены в код, становится бесценным, когда вы пытаетесь разобраться в устаревших системах, привлекать новых членов команды или принимать архитектурные решения.
Время, затраченное на размышления, а не на кодирование
Вот непопулярное мнение: некоторые из наиболее важных работ в разработке программного обеспечения неэффективны по своей природе. Размышления занимают время. Проектирование занимает ещё больше времени. И если вы постоянно измеряете «количество строк кода в час» или «коммиты в неделю», вы оптимизируете не то.
Давление постоянного производства — демонстрации видимого прогресса — создало культуру, в которой сидение и размышление о проблеме в течение часа кажется неудачей. Это не так. Некоторые из величайших инженерных решений принимаются в моменты, которые никогда не появятся ни в одном показателе производительности.
Стратегическая неэффективность: какие из них действительно важны?
Не все неэффективности одинаковы. Позвольте мне прояснить: я не выступаю за отказ от всех улучшений эффективности. Это глупо. Вместо этого я предлагаю, что нам нужна структура для различения неэффективности, которая тормозит поставку, и неэффективности, которая сохраняет долгосрочное здоровье.
Хорошая неэффективность
Тщательный обзор кода: занимает время. Замедляет развёртывание. Стоит того.
Комплексное тестирование: исследования качества программного обеспечения показывают, что тщательное тестирование — модульное, интеграционное, системное и тестирование производительности — выявляет и предотвращает проблемы, устранение которых впоследствии обойдётся на порядки дороже.
Время проектирования архитектуры: две недели, потраченные на проектирование перед кодированием, лучше, чем два месяца рефакторинга, потому что вы загнали себя в угол.
Межфункциональная коммуникация: встречи могут быть утомительными, но неэффективные рабочие процессы вызывают проблемы в коммуникации между членами команды, что приводит к снижению сплочённости и задержке поставки программного обеспечения. Иногда обсуждение проблемы — самый эффективный путь вперёд.
Документация: не избыточная бюрократическая, а реальная, полезная документация. Создавайте её постепенно. Сделайте её частью разработки, а не последумкой.
Плохая неэффективность
Ненадёжные тесты: команды тратят часы, пытаясь диагностировать периодические сбои тестов, что приводит к задержке сроков реализации проектов и разочарованию разработчиков. Это потери. Реальные потери. Исправьте это.
Бюрократические процессы утверждения: те, при которых запрос на функцию проходит через пять уровней управления без существенной причины. Устраните это безжалостно.
Переключение контекста: разработчики постоянно переключаются между проектами, приоритетами и встречами. Это действительно токсично. Защищайте время сосредоточенности разработчиков.
Избегание технического долга: неэффективность отказа от выделения времени на рефакторинг и улучшение существующего кода. Это всегда возвращается.
Практическая структура: внедрение стратегической неэффективности
Здесь я на самом деле даю вам практические советы, потому что в блогах должна быть такая информация.
Шаг 1: Аудит текущего состояния
Перечислите все действия, которые ваша команда выполняет в типичном спринте. Для каждого из них задайте три вопроса:
- Предотвращает ли это действие будущие проблемы или создаёт обучение?
- Создаст ли удаление этого действия видимый ущерб в ближайшие 6 месяцев?
- Люди активно возражают против этого действия, или они просто внутренне приняли, что оно «необходимо»?
Действия, на которые вы ответили «да» на вопросы 1 и 2, — это ваша стратегическая неэффективность. Защищайте их. Действия, которые вызывают ответ «нет, мы просто продолжаем это делать», являются кандидатами на устранение.
Шаг 2: Сделайте неэффективность явной
Вот шаблон для документирования стратегической неэффективности:
strategic_inefficiency:
name: "Еженедельный архитектурный обзор"
time_investment: "4 часа в неделю"
purpose: "Выявить архитектурные отклонения до того, как они станут системными"
success_criteria:
- "Новые сервисы соответствуют установленным шаблонам"
- "Зависимости явно отображены"
- "Команда понимает, почему были приняты решения"
metrics_that_dont_matter:
- "Количество PR, объединённых в неделю"
- "Скорость разработчиков в баллах истории"
failure_mode: "Если исключить: неизвестные границы сервисов, тесно связанные системы, повторяющиеся архитектурные ошибки"
Создайте несколько таких шаблонов. Поделитесь ими с командой. Защищайте их, когда кто-то предлагает их удалить.
Шаг 3: Внедрите неэффективность в цикл разработки
Вот конкретный совет: внедрите «мыслительный спринт» в свой цикл планирования.
В традиционном двухнедельном спринте выделите один день (примерно 12 % вашего времени), когда разработчикам явно рекомендуется:
- Рефакторить код, который их беспокоил.
