Как оптимизация может ухудшить поставку

Когда инженер только становится тимлидом, у него есть чёткая цель: заставить всё вокруг работать максимально эффективно. Чаще всего это происходит из-за желания закрепиться в новой роли, но и технический бэкграунд даёт о себе знать — привычка всё оптимизировать никуда не делась.

Поэтому загружать команду на 100% кажется максимально эффективным и правильным решением. Если мы за это платим – пусть работает. Желание всё оптимизировать кажется экономически оправданным. В результате юный тимлид частенько начинает заниматься локальными оптимизациями, забывая о картине в целом.

⭐️ К чему приводит локальная загрузка

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

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

⭐️ Что будет, если загрузить команду на 100%

Термин «бутылочное горлышко» ввёл Элияху Голдратт в своей теории ограничений. Впервые его можно встретить в книге «Цель» (см. мой обзор), которую я настоятельно рекомендую всем тимлидам.

Расскажу случай из своей практики. В одной из команд мы в какой-то момент озаботились наращиванием поставки. Естественно, первая же мысль была ошибочной — «нам нужно оптимизировать время работы программистов». Путём различных манипуляций с процессами мы снизили затраты времени разработчиков, в результате чего они действительно начали закрывать больше задач. Круто же?

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

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

⭐️ Производительность системы определяется бутылочным горлышком

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

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

Парадоксально, но в нашей ситуации первым правильным решением было перестать копать. И да, это означало уменьшение количества производимого кода. Поскольку ограничение системы заключалось не в скорости разработки, мы отказались от идеи «запихнуть в работу как можно больше фич» и стали отталкиваться от загрузки QA.

От этого решения выиграли все. QA выдохнули и смогли спокойно делать свою работу. У разработчиков появилось время на технический долг и изучение новых областей (например, фронты начали периодически брать задачи по бэку и наоборот). Система стабилизировалась, и всё вернулось на круги своя.

Однако изначальную проблему мы не решили. Скорость поставки осталась прежней. Но об этом я расскажу в следующем посте. :)

// Если сталкивались с ситуациями ухудшения производительности из-за локальных оптимизаций — пишите в комментах. И не забывайте про 💛**!