Планирование — важная задача не только для тимлида или менеджера. Часто разработчику приходится отвечать на вопрос «когда это будет готово?».
В этой заметке я хотел бы разобрать подходы, которые эффективно использовать в ситуациях, когда что-то должно быть сделано кем-то к какому-то сроку. Например, выпуск релиза с фичей или передача готового функционала другой команде для интеграции. Или другая команда меняет структуру базы данных в соответствии со своими планами, и вам надо заранее к этому подготовиться. Или заканчивается поддержка старого интерфейса в совместно используемой библиотеке. То есть некие события в будущем, к которым нам надо что-то сделать на своей стороне. Но вообще, приёмы, которые я предлагаю в этой статье, подходят ко многим проектам, не только в разработке.
Есть несколько разновидностей вопроса «когда это будет готово?». Простые, например: «Когда нам нужно начать, чтобы успеть к концу ноября?». Или посложнее: «Можем ли мы подключить ещё разработчиков, чтобы успеть раньше?». Этот вариант мы тоже разберем.
Проблемы у разработчика начинаются уже с интерпретации вопроса. «Готово» — это готово к использованию, а не «почти готово». То есть, сделана реализация, есть тесты, проведена отладка, пройдено ревью, собран фидбек. Значит, для ответа на наш вопрос надо заложить все эти стадии тоже. Обычно разработчик отвечает что-то типа: «Будет готово, когда будет готово», — и аргументирует это тем, что много «неопределенности». ОК, а как тогда анонсировать фичи клиентам, заключать контракты, синхронизировать работу между командами и в целом вести бизнес, если по каждой фиче много «неопределенности»?
Другой вариант, не сильно лучше, — разработчик дает некую случайную оценку и менеджер умножает ее на три, чтобы подстраховаться.
При этом, в повседневной жизни люди прекрасно справляются с планированием. Например, не опаздывают на самолет. Но ведь там тоже много «неопределенности»: пробки на дороге, очереди в аэропорту. Давайте попробуем разобрать этот пример.
Итак, у нас есть «что» должно быть сделано — посадка на самолет, и «когда» — определенное время вылета. Вы не можете быть «почти» в самолете, когда он вылетает. Вы либо там, либо нет. Также вы не можете пройти мимо паспортного контроля. То есть, существуют некие стадии, которые нельзя проигнорировать. Точно так же, как тестирование и отладку нельзя выкинуть из скоупа работ по разработке.
ОК, попробуем прикинуть время прохождения паспортного контроля и других стадий в аэропорту. На каждой стадии есть «неопределенность». Например, размер очереди вы не знаете заранее. Учтем этот риск и заложим некий запас, исходя из худшего варианта. Так же поступаем и с другими стадиями.
Затем мы вычитаем из времени посадки на самолет время, которое мы заложили на прохождение всех стадий в аэропорту. Получаем майлстоун, который можно будет легко отслеживать — оптимальное время прибытия в аэропорт.
Далее нам надо определить, во сколько нужно выехать, чтобы попасть в аэропорт в это время. На дорогу тоже закладываем буфер, исходя из худшего варианта. Получаем время, когда нужно выехать.
Выходит такая схема: берем известное событие, например, дату релиза, и откладываем назад все стадии, которые надо выполнить, добавляя буферы на риски. Получаем дату начала работ.
Почему я предлагаю отсчитывать с конца? Во-первых, во многих случаях у нас есть дата или диапазон дат для окончания работ, и мы можем от этого отсчитывать. Во-вторых, важно сделать фокус на «последней миле» — это как раз те этапы, на которых проект (или задача) становится из «почти готового» «готовым». Эти этапы обычно расположены в конце цепочки (кстати, это еще один повод определить критерии готовности).
Наш пример с самолетом — это простой случай с одним исполнителем. Стадии были последовательны. Исполнитель не уйдет в отпуск в середине пути и не переключится на другой проект. Да и степень неопределенности все же была достаточно низкая. Но все же можно сделать еще некоторые наблюдения:
-
Проект в целом может быть новым для вас, но при этом состоять из частей, понятных для оценки. Например, часть «добраться до аэропорта» не сильно отличается от других случаев, когда надо доехать до какого-то места к определенному сроку. Поэтому, поделив проект на стадии, часть из них можно точно оценить на основе своего прошлого опыта.
-
Величина буферов зависит от цены неуспеха всего проекта. Например, я бы заложил x2 на дорогу в аэропорт. Но при этом в большинстве других ситуаций такой запас не нужен. Определяйте буферы соразмерно рискам не только отдельных стадий, но и проекта целиком.
-
Для некоторых стадий возможны запасные варианты. Например, альтернативные маршруты до аэропорта. Это тоже способ снижения рисков.
-
Составив свой план, вы можете определить зависимости от других исполнителей. Например, такси можно заказать заранее, к моменту выезда.
А теперь давайте усложним эту модель.
Во-первых, у нас может не быть конечной даты. Наоборот, нам надо ее определить в ходе планирования. В таком случае подход прежний, но мы не отсчитываем от какой-то точки, а просто складываем длительности всех стадий с учетом буферов и получаем общую длительность работ. Например, два месяца.
В этом случае не так важно, откуда отсчитывать стадии, с начала или с конца. Но я предлагаю делать это с конца, чтобы держать фокус на результате проекта.
Также у нас могут быть зависимости и ресурсы, необходимые для начала работ. Например, нужен исполнитель, а он пока занят на другой задаче. И еще мы можем ждать чего-то от другой команды. В этом случае мы узнаем дату, когда все необходимое для начала будет готово, добавляем некоторый буфер, потому что и тут могут быть задержки.
Если работаем в спринтах, то округляем, сдвигаем дату на начало следующего спринта. Прибавляем длительность работ и получаем предполагаемую дату окончания проекта.
Во-вторых, если проект длительный, то на него скорее всего наложатся другие задачи и отпуска. Чтобы уменьшить негативный эффект, можно планировать работы так, чтобы отпуск или другие задачи находились между стадиями, а не перекрывали их. Например, как в случае спринтов, округляем в большую сторону, сдвигая начало следующей стадии вправо. Может быть, исполнитель начнет задачу и до отпуска, но в планировании разумно исходить из худшего возможного варианта.
В-третьих, зависимости от других команд могут потребоваться не только для начала работ, но и позже, во время работы над проектом. Подход тот же — договариваемся о сроке, добавляем запас, выстраиваем работы под этот срок. В процессе периодически проверяем статус зависимостей.
Будет хорошо, если получится провести раннюю интеграцию с промежуточной версией. Это тоже можно обсудить на этапе планирования. Так мы обнаружим проблему заранее, и её исправление меньше повлияет на сроки поставки.
В-четвертых, на проекте может быть несколько исполнителей. Определите стадии, работа по которым может идти независимо. Их можно будет выполнять параллельно. Синхронизация и планирование делаются также, как в случае с зависимостями от других команд.
А может быть и другая ситуация, когда какие-то из этапов будут проходить через исполнителя, который станет бутылочным горлышком из-за своей загруженности. Это тоже надо учесть на этапе планирования. Например, можно попробовать заранее договориться об окне времени для вашего проекта. Либо придется заложить время на ожидание в очереди.
В-пятых, неопределенность бывает действительно высокой, но ее можно попробовать снизить. Например:
-
Планировать разные варианты реализации. Если не сработает основная гипотеза, то будет запасная.
-
Сузить область неопределенности. Вычленить те части, которые более понятны, чтобы сфокусироваться на анализе непонятных.
-
Провести прототипирование для проверки гипотезы, чтобы отбросить нерабочий вариант как можно раньше. Прототипирование может быть, как отдельным шагом в проекте, так и подготовительным, до начала проекта. Разница заключается в рисках — либо мы должны заранее проверить реализуемость проекта в целом, либо можем это отложить на более поздний срок.
Давайте подытожим. Вот основные шаги, которые стоит соблюдать при планировании проекта:
-
Определить критерии готовности.
-
Составить список стадий и майлстоунов. Можно это сделать, начиная с конца проекта.
-
Оценить каждую стадию. Добавить буфер для каждой стадии. Подбирать буфер с учетом рисков для стадии и для проекта в целом.
-
Определить зависимости между стадиями, спланировать параллельную работу с учетом этих зависимостей.
-
Выявить боттлнеки.
-
Заложить отпуска и переключения исполнителей на другие проекты.
-
Определить необходимые ресурсы и зависимости для начала работ, а также зависимости, нужные в процессе работы над проектом. Добавить их в план.
Да, существуют проекты, в которых гораздо больше неизвестных. А может быть, даже заранее неизвестна конечная цель и есть только направление. И в эту простую схему такие проекты не вписываются. Но проблемы с планированием встречаются и на более простых проектах, где изначально понятно, что надо сделать и примерно понятно, как сделать.
И еще один важный момент. Подготовить план недостаточно, важно контролировать его выполнение в процессе работы. Для этого и нужны майлстоуны. Они помогают увидеть проблему вовремя и внести корректировки в план по ходу работы. Например, что-то упростить, убрать из скоупа, попробовать переключить людей с других проектов или разгрузить исполнителей, сняв с них второстепенные задачи. К тому же, люди болеют или берут незапланированные отпуска. Под это тоже надо адаптировать план по ходу работы.
Основное, что я хотел сказать в этой заметке — планирование проекта строится на трех навыках: декомпозиции, анализе зависимостей и анализе рисков. Из них самый сложный, на мой взгляд, — это анализ рисков. И здесь у меня, к сожалению, нет какой-то готовой рекомендации, кроме как учиться на ошибках, своих и чужих.
Давайте хотя бы начнем думать о возможных рисках и тогда планирование будет более реалистичным. А при реалистичном планировании и результат будет ближе к ожиданиям.
Автор: MikeAlexeev