В этой статье я хочу рассмотреть подход к разбиению задач на подзадачи при использовании чистой архитектуры.
Команда мобильных разработчиков NullGravity столкнулась с проблемой декомпозиции и ниже рассказывается, как мы ее решили и что получилось в итоге.
Фон
Это была осень 2018 года, мы разрабатывали очередное приложение для оператора связи.Но на этот раз все было по-другому.
Сроки были достаточно сжатыми и привязаны к маркетинговой кампании клиента.
Команда Android выросла с 3 до 6-7 разработчиков.
Несколько задач были взяты в спринт и встал вопрос, как их эффективно декомпозировать.
Что мы имеем в виду, когда говорим «эффективно»:
- Максимальное количество параллельных задач.
Это дает возможность занять все доступные ресурсы.
- Уменьшение размера мерж-реквестов.
На них не будут смотреть напоказ, и вы все равно сможете уловить потенциальные проблемы на этапе code review.
- Уменьшение количества конфликтов слияния.
Задачи будут обрабатываться быстрее и не нужно будет переключать разработчика на разрешение конфликтов.
- Возможность сбора статистики затрат времени.
- Автоматизация создания задач в Jira.
Как мы решили проблему?
Все подзадачи разделим на следующие типы:- Данные
- Домен
- Пустой
- пользовательский интерфейс
- Элемент
- Обычай
- Интеграция
Empty, UI, Item и Custom относятся к уровню представления.
Интеграция применяется как к уровню предметной области, так и к уровню представления.
Рисунок 1. Расположение задач относительно слоев чистой архитектуры
Давайте рассмотрим каждый тип отдельно.
Данные
Описание DTO, интерфейса API, работы с базой данных, источником данных и т.д.Домен
Интерфейс репозитория, описание бизнес-моделей, интеракторов.Интерфейс репозитория также реализован на уровне данных.
Такое несколько нелогичное, на первый взгляд, разделение позволило максимально изолировать такие задачи, как данные и домен.
пользовательский интерфейс
Создайте макет основного экрана и дополнительные состояния, если таковые имеются.
Элемент
Если на экране список элементов, то для каждого типа нужно создать модель — Item. Чтобы сопоставить элемент с макетом, вам нужен адаптерDelegate. Мы используем концепцию адаптер делегата но с некоторыми улучшения .
Затем создайте пример работы с элементом списка в PresentationModel.
Пустой
Базовые классы, необходимые для задач типа пользовательского интерфейса или элемента: PresentationModel, Framgent, макет, модуль DI, фабрика AdaptorDelagate. Связывание интерфейсов и реализаций.Создание точки входа на экран.
Результатом выполнения задачи является экран приложения.
Он содержит Toolbar, RecyclerView, ProgressView и т. д., то есть общие элементы интерфейса, добавление которых могло быть продублировано разными разработчиками и привело бы к неизбежным конфликтам слияния.
Обычай
Реализация нестандартной UI-компоненты.
Дополнительный тип нужен, чтобы отделить разработку нового компонента от задачи типа UI.
Интеграция
Интеграция доменного и презентационного уровней.Как правило, это одна из самых трудоемких задач.
Необходимо объединить два слоя и уточнить моменты, которые могли быть упущены на предыдущих этапах.
Порядок задач
Такие задачи, как данные, пустые и пользовательские, можно запускать сразу после начала спринта.Они независимы от других задач.
Задача домена выполняется после задачи данных.
Задачи пользовательского интерфейса и элемента располагаются после пустой задачи.
Задача интеграции выполняется последней, поскольку она требует завершения всех предыдущих задач.
Рисунок 2. График выполнения задачи
Несмотря на то, что некоторые задачи блокируются другими, их можно запускать одновременно или с небольшой задержкой.
К таким задачам относятся домен, пользовательский интерфейс и элемент. Это ускорит процесс разработки.
Рисунок 3. Срок выполнения задач с блокировкой
Для каждого конкретного функционала набор задач может различаться.
Пустых, ui, item и интеграционных задач может быть разное количество, а некоторые типы могут просто отсутствовать.
Автоматизация процессов и сбор статистики
Для сбора статистики при создании задачи к ней прикрепляется метка.Этот механизм в дальнейшем позволит вам анализировать время, потраченное на каждый тип, и формировать средние затраты.
Собранную информацию можно использовать при оценке нового проекта.
Нам также удалось найти решение по автоматизации.
Поскольку проблемы типичны, почему их описание в Jira должно быть другим? Мы разработали шаблоны резюме и описания.
Сначала это был просто json-файл, Python разобрал этот файл и подключил REST API Jira для генерации задач.
В таком виде сценарий просуществовал почти год. Сегодня оно превратилось в полноценное десктопное приложение, написанное на Python с использованием PyQt и архитектуры MVP.
Возможно, MVP был накладным, но когда первая версия на Tkinter крашила MacOS версии 10.14.6 и не все команды могли использовать приложение, мы легко переписали представление в PyQt за полдня и всё заработало.
Мы еще раз убедились, что использование архитектурных подходов даже для таких простых задач имеет свои преимущества.
Скриншот JiraSubTaskCreator показан на рисунке 4.
Рисунок 4. Главный экран JiraSubTaskCreator.
выводы
- Мы разработали подход к декомпозиции задач на подзадачи, минимально зависящие друг от друга;
- Сгенерированные шаблоны описания задач;
- Мы получили мерж-реквесты небольшого размера, что дает возможность тщательно просматривать и изменять код изолированно.
- Уменьшено количество конфликтов во время мерж-реквестов;
- Мы смогли более точно оценить и проанализировать время, потраченное на каждый тип задач;
- Автоматизирована часть рутинной работы.
-
Виртуальная Примерочная Kinect Для Topshop
19 Dec, 24 -
Ie6 Скоро Появится На Windows Mobile
19 Dec, 24 -
Вы Служили В Армии?
19 Dec, 24 -
О Роли Груди В Современной Культуре
19 Dec, 24 -
Интервью С Легендой C# Эриком Липпертом
19 Dec, 24