Декомпозиция задач: как разработчику съесть слона?

Ответьте себе на вопрос, бывает ли такое, что в процессе выполнения задачи на разработку вы понимаете, что не укладываетесь в срок, сталкиваетесь с чем-то, что не учли заранее, какие-то доработки занимают больше времени и усилий, чем вы планировали? Из-за нарастающей сложности задач в процессе их выполнения вы заводите дополнительные технические задачи на исправление, оставляете по коду множество TODO и комментариев в надежде позже вернуться к задаче и сделать ее качественнее?
К сожалению, как показывает практика, эти отложенные задачи так и замораживаются в первозданном виде и никто и никогда до них не доберется. А если и случайным образом лед разморозится и кто-то их обнаружит, никто уже не будет знать, что с ними делать. Хорошо, если потомки внимательно отнесутся к вашим комментарием в коде и попробуют доработать и привести в приятный вид то, что вы не успели.

Чтобы реже попадать в такие ситуации, несмотря на горящие сроки и амбициозные задачи бизнеса, мы можем сделать то, что в наших силах сейчас – провести грамотный анализ, сделать оценку и декомпозицию задач. И эта статья именно о последнем пункте – декомпозиции. Как же правильно съесть слона? — Есть его по кусочкам.
Меня зовут Анастасия Дронина. Я Android-разработчик в MedTech-компании СберЗдоровье. В этой статье расскажу о своем подходе к декомпозиции продуктовых и технических задач, который помогает мне укладываться в сроки, при этом сохраняя кодовую базу проекта в хорошем состоянии.
Начнем с основ
Декомпозиция задач — процесс разделения сложной задачи на множество простых, каждая из которых не превышает сложность исходной задачи.
Допустим, вам нужно разработать мобильное приложение или фичу к нему. Вместо того, чтобы сразу бросаться писать всё и сразу, намного рациональнее разделить процесс на последовательные шаги:
-
определение требований к приложению;
-
разработка архитектуры приложения;
-
дизайн пользовательского интерфейса (UI/UX);
-
программирование функциональных модулей;
-
тестирование;
-
запуск и поддержка.
Варианты декомпозиции задач в ИТ
Есть несколько видов декомпозиции задач, каждый из которых подходит для определенных ситуаций и типов проектов. Рассмотрим основные.
-
Функциональная декомпозиция. Задача делится на отдельные функции или модули, которые выполняют конкретные операции. Этот вид декомпозиции часто используется в разработке программного обеспечения.
-
Объектно-ориентированная декомпозиция. В этом случае задача разбивается на объекты, каждый из которых имеет свои данные и методы. Объекты взаимодействуют друг с другом для выполнения общих целей.
-
Процессная декомпозиция. Эта декомпозиция фокусируется на последовательности шагов или процессов, необходимых для достижения цели. Она особенно полезна в управлении проектами и бизнес-процессами.
-
Структурная декомпозиция. Задача разбивается на структурные компоненты, которые связаны между собой иерархически. Этот подход часто используется в архитектуре систем и проектировании сложных программных продуктов.
-
Итеративная декомпозиция. Этот вид декомпозиции предполагает постепенное уточнение и улучшение решений на каждом этапе разработки. Он широко используется в гибких методологиях разработки, таких как Agile.
-
Компонентная декомпозиция. Задача разбивается на независимые компоненты, которые могут быть разработаны отдельно и затем интегрированы в общую систему. Такой подход полезен при создании модульных систем.
Зачем нужна декомпозиция?
Правильная декомпозиция задач потенциально дает возможность получить комплексный результат и закрыть многие боли разработчиков.
-
Качества кода. Работая над более крупными задачами, проще упустить важные детали из виду, поскольку из-за объема работ внимание уходит на выполнение основных требований по задаче. В результате могут формироваться неожиданные работы по техническому долгу, которых могло и не быть. Декомпозиция позволяет исключить такие риски и издержки.
-
Ревью. При разделении задачи на подпроцессы изменений в ваших Merge Request-ах будет меньше. Это поможет коллегам легче отслеживать обновления, более активно и внимательно их ревьюить.
-
Параллельность. С грамотной декомпозицией больших задач над ними одновременно может работать больше одного разработчика и QA.
-
Уточнение оценок. Маленькие задачи легче оценить, а оценка у них более предсказуемая.
-
Управление сложностью. Разбивка крупных задач на мелкие часто помогает снизить их сложность и улучшает понимание требований в целом.
-
Планирование. В наших командах мы работаем по Scrum. У разработчиков есть capacity на спринт, и большие задачи могут в него не уместиться. Декомпозиция решает этот вопрос.
Что учитывать при декомпозиции?
То, как в итоге будет декомпозирована задача, зависит от множества разных факторов. Для наглядности рассмотрим, как с декомпозицией работаем мы в СберЗдоровье.

Чтобы не запутаться, обычно я держу в голове и учитываю сразу несколько аспектов.
-
Требования по срокам. Для разработчика почти всегда более эффективно и удобно делать задачи по очереди. Но в условиях жестких сроков часто требуется параллелить задачи и работать вдвоем/втроем, а также сделать возможным тестирование части задач еще до завершения работ над всей User Story.
-
Внешние зависимости. СберЗдоровье — Super App. У нас есть много кросс-функциональных команд, каждая из которых занимается разными фичами, и они периодически пересекаются. Иногда мы ждём, пока другая команда закончит разработку функционала, который мы планируем использовать в своей задаче.
-
Внутренние зависимости. Мобильные разработчики работают с единой кодовой базой проекта, поэтому когда код пишется параллельно, мы задеваем одни и те же классы и сущности.
-
Блокеры. Если мы видим в задаче какие-то трудности и блокеры, которые точно возникнут, можно закладывать отдельную задачу и время на разбирательства с ними. Сюда также входят коммуникации и последующее ревью с возможными исправлениями, связанное со спорными изменениями.
-
Совместная работа. Сейчас мы используем в своем проекте GitFlow. Это значит, что для больших фич мы создаем отдельные ветки и в процессе работы направляем мерж реквесты на них. Если над одной фичей работает несколько разработчиков, то может получаться так, что один из них не может взять задачу, поскольку другой еще не влил свои изменения.
Первичная декомпозиция
У нас в СберЗдоровье до начала разработки каждая фича проходит довольно большой процесс. Нет смысла описывать его здесь целиком, важно только то, в каком виде задачи приходят к разработчикам.
Первый раз мы узнаем требования по задаче на грумминге. Обычно это встреча, на которой системный аналитик показывает нам макеты и уже описанную документацию с требованиями, где сказано:
-
какие данные мы ожидаем получить от бэкенда;
-
что отрисовать на фронте;
-
какие действия произвести с данными пользователя при его манипуляциях с интерфейсом приложения.
От разработчиков в этот момент просят дать примерные оценки задачи.
Если задача занимает больше 1-2 дней, здесь важно начать примерную первичную декомпозицию задачи где-то на бумаге, в блокноте или хотя бы в голове. Это нужно, чтобы даже примерная оценка была не слишком «примерной».
Мой стандартный список задач для большинства крупных фич будет выглядеть так:

Шаг 1
-
Технический анализ. Анализ фичи с описанием всех изменений в виде текста/таблиц/схем. Его результатом будет финальная, уже более точная, декомпозиция с оценками. Об этом процессе есть отдельная статья моего коллеги: «Die But Do: теханализ и почему без него разработка обречена на провал».
-
Доработки существующих сущностей. Изменения в существующем коде, добавление новых полей, исправления бизнес-логики и другие процессы.
-
Написание новой логики. В моем случае это добавление новых запросов, создание новых моделей, экранов, элементов на экране.
-
Работа с зависимостями. У нас многомодульное приложение и модули разделяются по фичам. А еще мы используем подход api-impl. Более подробно об этом можно почитать в статье моего коллеги «Принципы построения многомодульного Android-приложения и их применение в СберЗдоровье». Здесь я учитываю перенос сущностей из одного модуля в другой, возможности объединения логики и переиспользования кода, а также другие аспекты.
-
Написание тестов. Мы покрываем Unit-тестами все слои логики. В рамках этой задачи я примерно оцениваю объем логики, которую будет нужно покрыть тестами. У нашей команды iOS есть статья, описывающая их подход к модульному тестированию в двух частях: 1 часть и 2 часть.
-
Отладка. До передачи в тестирование нужно проверить код, по возможности пройдя все популярные сценарии, и убедиться, что ничего не падает и не ломается. Закладываю время на это и на исправление багов.
Это примерный список, на который можно ориентироваться. Части этих задач может не быть, или могут быть добавлены дополнительные.
Каждую из этих задач я анализирую, складываю их и формирую примерную оценку для бизнеса. Важно, чтобы эта оценка была чуть больше (с запасом) и учитывала возможные риски. Потом, в процессе технического анализа, ее можно уточнить и уменьшить, если будет нужно.
Финальная декомпозиция
Первичная декомпозиция — не финальная точка. Зачастую она нужна только для того, чтобы дать оценку задаче. Но во время технического анализа нам нужно будет выделить финальный скоуп задач в таск-трекере, с понятным описанием, которые не конфликтуют между собой и могут выполняться параллельно (или последовательно, в зависимости от требований).
Чтобы сделать такой скоуп задач, возьмем таблицу из предыдущего шага и разделим крупные задачи на еще более мелкие.

Шаг 2
Стоит отметить, что иногда может понадобиться еще одна стадия декомпозиции. Но обычно это оправданно не для всех указанных задач, а только для тех, где есть изменения бизнес-логики и UI.
Большую задачу можно делить до того момента, пока она не станет чем-то типа атомарной задачи, которую уже некуда делить.

Шаг 3
Примечание: Надо понимать, что не всегда работать с атомарными мини-задачами удобно и рационально. Поэтому декомпозиция должна быть обоснованной.
В итоге можно получить максимально объективный и наглядный спектр процессов, которые предстоит выполнить для завершения исходной задачи. При этом группировать скоуп задач лучше так, чтобы их можно было сделать вместе и связность с другими такими группами задач была слабой.
Например, можем получить такую задачу: «Реализовать N» со следующим набором подпроцессов:
-
Добавить ресурсы X.
-
Написать маппинг Z.
-
Сетевой слой X.
-
Поправить логику Y.
Заключение
Описанный паттерн декомпозиции задач в ИТ — не «серебряная пуля». Но подход вполне можно использовать во многих проектах: несмотря на то, что для маленьких процессов он избыточен, такая декомпозиция применима к большим и сложным задачам.
Важно здесь и то, что описанный мной подход — не строгая инструкция, а набор правил и рекомендаций. Следуя им, можно научиться обращать внимание на важные детали, тем самым:
-
уменьшить количество замечаний на ревью;
-
существенно повысить попадание в оценки при разработке:
-
снизить уровень неопределенности и стресса из-за срыва сроков.
А какой метод декомпозиции используете вы в своих проектах? Делитесь опытом в комментариях.
Автор: AnastasiaDronina