Закон Хофштадтера
Всегда потребуется больше времени, чем вы ожидаете, даже если вы знаете закон Хофштадтера.
Вступление
Сразу хочу отметить, что метод не универсальный и подходит не для всех задач, проектов, команд. Например, описываемый метод не подойдёт для исследовательских задач или багов. Скорее подойдёт для устоявшихся проектов, чем для стартапов.
На тему оценки сроков сказано многое, написаны книги, статьи и комментарии, придуманы покеры планирования, майки, футболки, шорты и прочие PERT-ы и эталонные задачи. Но надо ещё.
Кто виноват?
Если коротко:
мы переоцениваем себя
мы недооцениваем задачу
мы не углубляемся в детали перед началом работы
меняется на ходу ТЗ
внезапная простуда
сложности у смежников или поставщиков
баг в сторонней библиотеке или сервисе
...
Поскольку мне не нравится факапить и я не люблю быть виноватым в срыве сроков, отсюда вопрос.
Что делать?
Для начала разделить проблемы на два типа:
проблемы, которые зависят от меня лично, и я могу на это повлиять (например, плохо проанализировал задачу)
проблемы, которые не зависят от меня лично, и я не могу на это повлиять (например, изменение ТЗ в процессе работы)
Поскольку я смотрю на вопрос с точки зрения исполнителя, то меня больше волнует почему лично я могу сорвать сроки. Если поменялось ТЗ в процессе, это, извините, к менеджерам и аналитикам, я тут не при делах, идите учитесь формулировать задачи да спеки писать. Этот спектр проблем вне моей власти и я оставляю его за бортом.
А вот если я не почитал ТЗ перед началом, или почитал, но не выявил ошибки в ТЗ или просто не обдумал ТЗ - вот, это мой косяк, и с ним надо бороться. Но что я могу улучшить и как?
В процессе накопления опыта, как программиста, я заметил одну простую зависимость: если перед началом работы на фичей я пошёл в код, нашёл места в проекте, с которыми предстоит работать, прикинул что и как я буду делать, то такие задачи чаще шли хорошо. Если я перед началом работы я выполнил оценку "на глаз", то сюрпризов и срывов сроков было больше.
Ну дальше последовала простая гипотеза, которая привела к любопытным выводам и решениям.
Перед началом работы, надо пойти в код, найти места, которые будешь менять и написать комментарий с сутью изменений
Однажды, работая в стартапе, когда эйфория от начала работ прошла, а деньги начали заканчиваться, у менеджеров стали возникать странные вопросы типа: а где результат, а когда сделаем фичу, и вообще, кто эти люди в офисе и чем они заняты? Нас, разработчиков, начали просить оценивать сроки и, что еще хуже, соблюдать их.
Тут-то я и попробовал систематизировать идею, а заодно и свою работу.
Плоский план. Первая попытка
Итак, перед началом работы, я стал читать ТЗ с одновременным походом в код, где я ставил пометки, что предстоит сделать. Как минимум это заставляет тебя не просто "пробежаться" по спеке, а вдумчиво вычитать каждый абзац, да еще сопоставить с каким-то блоком в коде. Стали выявляться проблемы в ТЗ, и я чаще стал возвращать ТЗ на доработку, еще до начала работы, на раннем этапе. А это гораздо лучше, чем вернуть спеку уже в процессе, когда ты пообещал к определенному сроку сделать задачу. Если уже взял работу, то это говорит о том, что ты со всем согласен, ТЗ в норме, можно работать, и вдруг, в средине сказать, что в ТЗ косяк - ну, такое, выглядит не солидно.
А потом с нас стали требовать написать план работ и дать оценку сроков. И с запросом сделать план всё стало на свои места. Нужно:
Пойти в код тезисно написать однострочный комментарий. Комментарий должен содержать, помимо описания работы, пометку с оценкой времени, конкретно на этот блок работ
Написать утилиту, которая вытянет из кода комментарий и время и сформирует текстовый документ с перечнем работ и суммой часов на работу
Профит!
Пример комментария
# TODO: PL: Добавить поля в модель Post 0.5
___________ ___________________________ _____
Маркер описание время
Вначале маркер, по которому утилита ищет комментарий, в конце оценка времени в часах.
Думаю особо не нужно обосновывать, что человек тормоз плохо оценивает большие работы и лучше оценивает маленькие. Так и тут, много оценок маленьких кусочков, а потом подсчитать их сумму.
Но не может же быть всё так просто? Конечно, вылезли проблемы и появились идеи.
Проблема, что собрать комментарии в документ надо в каком-то логичном порядке. Для этого пришлось добавить пометку с порядком сортировки.
Появилась хорошая мысль, что можно еще и добавить процент выполнения и, если обновлять в процессе работы процент выполнения блока, то можно автоматически считать оставшееся время.
В финальном виде комментарий прибрёл вид:
# TODO: PL: Добавить поля в модель Post 0.5/0/10
___________ ___________________________ ________________________________________
Маркер описание время/готовность/положение в документе
Теперь можно собрать документ примерно в таком виде:

Примечания к документу:
Заголовок берётся из имени ветки
Дата - это дата генерации
В документ вставляется, также, имя файла и строчка, где находится комментарий. Удивительно, но только эта информация уже ценна, даже без текста комментария. Например, если синьор возьмёт ТЗ, и пробежится по коду написав комментарий "делай тут" и передаст ТЗ с этими пометками юниору, без указания, что именно делать, то уже это облегчит юниору жизнь, он будет сориентирован, где трудиться.
Отмечу, что менеджмент не интересует всё, что дальше шапки:

То есть, если в плане полно технических деталей - то в целом всем всё равно. Главное срок и процент готовности.
Вернёмся к комментарию. Комментарий приобрёл сложную структуру и всякий раз писать его руками не очень хотелось. Но современные IDE позволяют немного упростить нам жизнь. Добавляем шаблон кода (snippet) и жизнь налаживается:

Что вообще это дало?
Если ты разработчик:
гарантия, что ты прочитал ТЗ, и не просто прочитал, а вдумался
посмотрел на код, и возможно, нашёл белые пятна или нелогичности в ТЗ
более-менее точно прикинул срок задачи
Если ты тех-лид или тим-лид, в общем какой-то начальник и тебе разраб показал план:
как минимум разработчик читал ТЗ, а не от фонаря назвал сроки
Если ты старший разраб и написал план, то:
можешь дать его юниору, пусть страдает с реализацией и не бегает к тебе с каждым вопросом
Теперь касательно того, что это бюрократия. И да и нет. Лишняя бумажка, трата времени на оформление. К чему всё это если можно просто сесть и начать кодить?
Во-первых, глубокое ознакомление с задачей. Во-вторых, как я отметил выше, оценка по времени маленьких кусочков точнее, чем всей задачи сразу. В-третьих, план для менеджмента, им так спокойнее. И, в-четвёртых - это изменение самого процесса работы над задачей.
На последнем пункте остановлюсь подробнее.

Процесс 1 - это "как обычно": думаем, кодим, думаем, кодим, думаем, кодим.
Процесс 2 - с анализом/написанием плана: думаем, думаем, думаем, кодим, кодим, кодим.
И когда всё идёт хорошо, то разницы особой и нет. А вот, когда что-то идёт не так, то разница становится заметна:

Можно обнаружить проблемы на ранних этапах работы.
Да, картинки упрощённые, может даже идеализированные, и в жизни всё сложнее, но я думаю идею они передают.
По факту, написание плана через комментарии добавляет новый этап работы: написание плана, ваш Кэп. И по моим ощущениям это важный и правильный этап.
Но есть проблема. Это работает для маленьких задач, а для больших - нет. А для маленьких задач такое углубление не особо-то и нужно. Ну да, хорошо для менеджмента - у них появился план и ход работ. Можно использовать как план для юниора или стажёра: в плане сразу написано где делать и что делать.
Но если ты хочешь "распутать" сложную задачу - то это не работает и вот почему.
Простой плоский план работает с "прямолинейными" задачами, как и сам план, а сложные задачи чаще состоят из многих частей, подзадач, эти части имеют взаимозависимости. Для сложных задач я сталкивался с такой проблемой: я нашёл места в коде, проставил комментарии, запустил утилиту, она собрала мне план. Но в этом плане ничего не понятно. В нём пункты стоят как попало. Ты начинаешь выстраивать эти пункты в каком-то осмысленном порядке, ставишь в комментах порядок сортировки для пункта, смотришь на обновлённый план, и так повторяешь много раз, но легче не становится. Всё равно каша, по которой работу не выполнить. В общем выделить некую прямую очевидную последовательность действий, которая бы привела к решению задачи не выходит.
Почему?
Ну в общем-то очевидно, сложная задача имеет нелинейную структуру, которая просто не ложится на линейный план.
Вот еще один пример, поближе к реальности. Есть вебсайт, задача: добавить профиль пользователя, его просмотр и редактирование. Задача должна включать создание таблицы в БД (миграция), модель в ORM, контроллеры, HTML страницы.
Если разложить эту задачу на кусочки и проставить зависимости между частями, то получится такая картина:

(Сейчас не стоит сильно вдаваться в подробности, что написано в квадратиках, достаточно отметить что схема сильно нелинейная)
Пару комментариев к схеме. Тут подразумевается, что есть некоторые блоки работ, выполнение которых зависит от других. Например, для того чтобы сделать ORM-модель для профиля пользователя, нам для начала надо создать таблицу в БД. Вот кусочек схемы:

Стрелочка, соединяющая эти два блока работ указывает на зависимость между ними: модель зависит от миграции. Если связи рассматривать, как порядок выполнения работ, то стрелки будут указывать в обратную сторону.
Возвращаясь к проблеме простого плоского плана. Напомню, в нём порядок выполнения частей работы нужно было указывать вручную с помощью числа. Меньше число - раньше пункт в документе. Для задачи типа "Добавление профиля пользователя", это уже за гранью возможностей (как минимум моих).
Если посмотреть на диаграмму, то очевидно что она и есть прекрасный анализ задачи и план на одной картинке. Можно ли что-то сделать, что бы автоматически генерировать такую картинку? Чего не хватает? Текст комментария есть, имя файла есть, нет связей. Значит их нужно добавить!
План граф. Вторая попытка
Граф не тот, который барон, а тот, что со стрелочками.
Итак, попытка номер два. Из опыта с плоским планом я вынес, что комментарии в коде - это хорошо. Но когда их много - я теряю контроль над ними. Эксперименты с построением графа показали, что графическое представление намного информативнее, осталось только построить картинку. Не буду утомлять описанием процесса поиска того как я это сделал - опишу сразу результат.
Для того что бы определить связи пришлось каждому комментарию присвоить некий уникальный идентификатор. Добавить к комментарию блок, в котором перечислены ссылки на другие комментарии (блоки работ), от которых зависит данный комментарий (блок работ).
Комментарий приобрёл более сложный вид:
# TODO: PL: Create model Post Маркер и текстовое описание
# ID: id-1 ID комментария, произвольная уникальная строка
# DEP: id-2 ID комментария, от которого зависит данный комментарий
# TIME: 1 Оценка времени выполнения, часы
# COMPL: 50 Готовность в процентах
Опять, ускорение ввода комментария с помощью средств IDE:

Для каждого комментария IDE генерирует ID в виде "имя-файла:строка", чего вполне хватает.
Также потребовалось ввести "Главный" комментарий. Главное предназначение - собрать в одну точку задачи самого верхнего уровня, а также дать заголовок задаче. Такой комментарий я, как правило, кладу в новый файл с именем plan.txt в корень проекта.
С такими комментариями можно получить вполне себе адекватную схему и документ.
Для случая с профилем пользователя это выглядит так:

Для построения этой красоты используется сторонняя программа Graphviz. То есть утилита собирает комментарии, затем формирует описание графа подзадач, и дальше Graphviz формирует картинку.
Одной этой картинки, я думаю, достаточно для программиста, чтоб распутать задачу и контролировать выполнение. Однако это не документ, который хочет менеджмент. Нужен документ.
Если из графа выкинуть рёбра, которые на картинке изображены пунктиром, то получится остовное дерево. И, что характерно, из такого дерева получается отличный и весьма логичный документ. Дерево легко можно представить в виде документа с пунктами и подпунктами. Верхний уровень графа - пункты верхнего уровня, вниз по графу - подпункты в документе.

На мой взгляд весьма логичный документ, который не стыдно показать.
Непростой процесс
Теперь про процесс составления графа через комментарии в коде.
Процесс выглядит так. Сначала читаем ТЗ и параллельно создаём комментарии, но без связей. В консоли (IDE или системной) запускается утилита workplan. В IDE или с помощью внешнего просмотрщика изображений смотрим на граф. В начале работы он имеет нечитаемый вид, примерно такой:

Утилита обильно выводит ошибки, как на сам граф, так и в консоль:

И с этого места начинается, пожалуй, самое интересное, полезное и противное: выстраивание связей.
Я, обычно, собираю в "сосиски" (последовательные блоки) самые очевидные части. Например, я знаю что эти три блока должны быть сделаны один за одним (что-бы это не значило, просто знаю).
Подключить crispy_forms
Добавить UserForm и ProfileForm
Во view добавить классы поддержки отображения и редактирования профиля
Также я понимаю, что самые верхнеуровневые задачи - это HTML страницы, которые, собственно и являются целью задачи.
Создать страницу с отображением профиля
Создать страницу с формой редактирования профиля
Эти задачи я соединяю с "главным" комментарием (напомню, это комментарий пустышка, содержит имя задачи и, я, как правило, его создаю в новом файле plan.txt, хотя не обязательно именно в таком файле)
Соединение выглядит так. Мне нужно комментарии дополнить корректными блоками DEP:
# TODO: PL: Во view добавить классы поддержки отображения и редактирования профиля
# ID: bloggitt/core/views.py:180
# DEP: bloggitt/core/forms.py:13 <------ Добавлен ID комментария "Добавить UserForm и ProfileForm"
# TIME: 4
# COMPL: 0
Что бы более-менее удобно осуществлять навигацию между блоками можно использовать вывод консоли IDE, в ней щелчок по имени файла открывает файл в нужном месте:

Или с помощью TODO плюс фильтр по префиксу комментария:

Итак, соединив блоки верхнего уровня и "сосиски" получается уже что-то, что доступно для понимания:

Еще немного соединений:

И тут я хочу обратить внимание на "повисший" блок с миграцией. Он ни с чем не соединён. Я специально "забыл" добавить на диаграму блок "Создание модели". Я это сделал что-бы проиллюстрировать, как построение схемы позволяет находить "пробелы" в плане. В данном примере, при создании плана, мы вспомнили, что нужно создать миграцию БД и добавить таблицу, но про модель забыли. И тут диаграмма показывает, что блок миграции есть, а прицепить его как бы некуда. То есть мы выявили пробел. Мы забыли связующее звено - модель.
Ну и финал:

Для настройки зависимостей хорошо было бы иметь некий плагин к IDE, который бы позволял выбирать зависимости с помощью, например выпадающего списка, но это пока только мечты.
Важный момент. Порядок перечисления зависимостей в комментарии соответствует порядку, в котором зависимые блоки будут идти на диаграмме и в документе. Это позволяет достаточно гибко формировать, как документ, так и диаграмму.
Должен отметить, что сам процесс создания связей несколько утомителен. Однако когда схема готова, ты на неё посмотрел несколько раз, подправил мелочи, добавил парочку пропущенных деталей - испытываешь чувство глубокой удовлетворённости, подобно тому, как ощущаешь себя, когда хорошо сделал задачу и доволен результатом. В общем сидишь и любуешься красотой. У меня к этому моменту наступало просветление и задача становилась совершенно понятной.
Сколько времени это занимает? Половину или весь рабочий день, зависит от задачи, от того сколько раз надо с кем-то созвонится и уточнить детали.
Стоит ли оно того? Думаю да.
Свистоперделки
По ходу дела утилита обросла разными полезными и не очень фишками. Начну с полезных.
Цветовая дифференциация. Узлы в графе могут быть окрашены в один из трёх цветов, на основании пути и расширения файла. Это позволяет визуально разделить, например frontend и backend.
Также узлы меняют свою яркость в зависимости от процента готовности:

Наиболее ярко выделяются те узлы, которые в рабооте (процент готовности больше 0, но меньше 90)
Приглушёнными цветами - "почти готовые" от 90 до 99 процентов. Лично для меня, это готовый код, но в конце надо еще просмотреть, почистить, перепроверить. Чаще всего я задачи делаю до состояния 90%, оставляя на самый конец финальную чистку и доведение до 100%.
Сильно приглушённые - 100%. Для меня это уже просмотренный, почищенный и перепроверенный код. Выполняется в самом конце.
Такое "приглушение" позволяет в процессе работы визуально отсеивать те части которые еще или уже не актуальны.
Также есть светлая цветовая схема и возможность в конфигурационном файле настроить цвета.
Очень полезная опция командной строки --scale, которая позволяет умножить время из комментариев на этот самый scale. Например, в комментарии стоит, что оценка этого блока 3 часа, а scale=2, то в диаграмму и документ пойдёт 6 часов. Можно использовать, например для коррекции плана под исполнителя. Допустим синьор составил план и указал время из своих способностей, но задачу будет делать юниор. Тут можно просто указать scale=3, предполагая, что юниору понадобится втрое больше времени, по сравнению с синьором. Также можно использовать для создания запаса времени.
Еще один хороший параметр командной строки - количество рабочих часов в день. Если оценка времени задачи 8 часов, это совсем не значит, что задача может быть сделана за день. Если разработчик непосредственно кодированию уделяет в день в среднем 4 часа, то мы можем это указать, и в документ, и диаграмму добавится оценка в днях с учётом количества рабочих часов. Ниже на диаграмме указаны места, где выводится информация о количестве дней.
Менее полезными оказались такие возможности:
Подсветить заблокированные участки работы и разбить подзадачи на разных исполнителей.

Как показала практика, отображение заблокированных задач еще имеет смысл, то разбивка на разных исполнителей уже нет. С разбивкой по ролям становится не совсем ясно, что за время мы считаем. Напрашивается диаграмма Гантта... Эта утилита всё же больше про индивидуального исполнителя.
Заключение
Построение детального плана требует усилий. Такого рода план нужен далеко не для всех задач. Если у вас с отчётностью и соблюдением сроков строго, то да, скорее это будет полезно.
Программа требует некоторой сноровки, особенно в части создания связей. Хотелось бы плагин для IDE, который бы облегчал эту работу. Если кому-то зайдёт, обещаю подумать над плагином.
Для работы с диаграммой нужен большой монитор, у меня 30 дюймов, но хотелось бы больше. Не знаю можно ли на ноутбуке с этим работать.
Построенная диаграмма вызывает чувство удовлетворения. Как нарисую еще битый час рассматриваю, ищу дырки в логике, украшаю. Нравится.
Реально влияет на понимание задачи. После построения схемы не ощущаешь себя ёжиком в тумане. Всё ясно.
Хорошо помогает ориентироваться в больших задачах, когда ты перестаешь понимать: а что уже сделано, а что еще осталось? Этому хорошо способствует затенение выполненных блоков.
Вот куда может завести простая идея: "перед началом работы, надо пойти в код, найти места, которые будешь менять и написать комментарий с сутью изменений"
Спасибо за внимание.
ПС.
Утилита на гитхабе: https://github.com/stg34/workplan
Обращу внимание, что в ёё состав входит 3 программы:
plan-plain - плоский план
plan-graph - граф
purgen - чистилка кода от комментариев
Там же на гитхабе подробная информация обо всех параметрах комментариев, командной строки и конфигурационном файле.
И еще. В свете развития ИИ, было бы интересно попробовать отдать план на реализацию ИИ. Такой себе, железный юниор. Но это уже совсем другая история.
Поскольку канала в телеграмме у меня нет, то вместо подписки попрошу поставить репозиторю звездочку. Если понравилось, конечно.