[Анализ и проектирование систем, Разработка под Android] «Оливье в каждой семьей свой»: или как мы придумали ещё одну многомодульную архитектуру
Автор
Сообщение
news_bot ®
Стаж: 6 лет 9 месяцев
Сообщений: 27286
Сегодня я хочу познакомить вас с вариантом построения многомодульной архитектуры под Android. Но сначала обязательно вспомним про понятие Clean Architecture и для чего вообще надо задумываться об архитектуре вашего кода.Зачем нужна архитектура?Какую цель преследует тот, кто когда-либо писал или читал чьи-то доклады по разработке ПО? Обычно это одно из двух:
- либо человек хочет решить какую-то конкретную прикладную проблему,
- либо он хочет, чтобы его продукт был лучше.
Так вот что же это такое «лучше»? Последнее время этот вопрос всё чаще всплывает в контексте архитектуры программного продукта. Ведь мощная базовая архитектура — важный показатель для масштабируемости приложения. Внесение любых изменений в проект может потребовать переписать приложение практически полностью. В таких случаях код тесно связан. Использование Чистой архитектуры (Clean architecture) помогает решить эту проблему.
Это одно из самых популярных и часто используемых решений для крупных приложений с большим количеством функций и SOLID-принципами. Подход был предложен Робертом С. Мартином (известным как Дядя Боб) в блоге «Чистый код» в 2012 году.Всем известная схема, которую также иногда называют «Луковицей».
Источник: https://blog.cleancoder.com/uncle-bob/2012/08/13/th...cture.htmlМногие распространённые архитектуры, такие как MVC, MVP, MVVM, MVI по сути являются вариантами подхода Сlean architecture. Они могут выглядеть запутанно, но разобравшись однажды со всей внутрянкой чистой архитектуры, в дальнейшем у вас не возникнет проблем.Итак, зачем нужен чистый подход?Принципы чистой архитектуры
В основе чистой архитектуры лежит идея разделения кода на слои. Давайте бросим взгляд них.
Domain-слой: Запускает независимую от других уровней бизнес-логику. В идеале — это чистый пакет Kotlin без android-зависимостей.Data-слой: Отправляет необходимые для приложения данные в domain-слой, реализуя предоставляемый доменом интерфейс.Presentation-слой: Включает в себя как domain-, так и data-слои, а также является специфическим для android и выполняет UI-логику.Исходя из данных принципов, как правило, в проектах делают так: выделяют какие-то общие модули, а остальное организуют одним из двух вариантов:
- Код содержат в общем модуле application, при этом внутри делят по слоям на пакеты: Domain — Data — Ui.
- Заводят модуль application и какое-то количество модулей feature, внутри каждого из которых также имеются пакеты с тремя слоями.
Давайте также обозначим, что здесь имеется в виду под «feature» — это логически законченный, максимально независимый модуль программы, решающий конкретную пользовательскую проблему, с чётко обозначенными внешними зависимостями, и который относительно легко переиспользовать в другой программе. Одно из ключевых выражений в определении фичи — это «с чётко обозначенными внешними зависимостями». Поэтому давайте всё, что мы хотим от внешнего мира для фичи, будем описывать в специальном интерфейсе, например:
Здесь мы говорим о некой фиче, связанной с процессом авторизации. В данном случае мы через интерфейс LoginDataDependencies обозначаем внешние зависимости для модуля фичи. Другая важная составляющая «чистой» фичи — это наличие чёткого API, по которому внешний мир может обращаться к фиче.
Интерфейс доменного слоя предоставляет для остальных модулей чёткое API — репозиторий со своей функциональностью. Ниже приведён пример включения данного компонента в контексте Dagger2.
Здесь я буду приводить примеры кода с использованием Dagger2. Конечно, эти подходы и принципы не исчерпывающие. Ни один принцип не может быть универсальным и подходить для решения любой задачи. Плюс всегда хочется улучшать решения, либо просто поэкспериментировать. Таким образом рождаются новые решения: какие-то подходят для узких кейсов, а какие-то выходят более универсальными. И когда человек знаком с различными вариантами решений — это уже половина успеха, ведь он знает, как другие люди решали подобные задачи и всегда может воспользоваться готовым решением, адаптировав его под себя. Я хотела бы познакомить вас с нашим решением, которое лично для меня стало чем-то новым. До этого меня жизнь не сталкивала и с Dagger 2. Но основным инсайтом для меня стал принцип, который работает совместно с этим фреймворком — я говорю о варианте многомодульной архитектуры приложения Андроид.Рецепт Оливье
Суть идеи, которая отличает её от тех решений, что уже известны мне на текущий момент, в том, что каждую feature нужно делить на три модуля: «Data — Domain — Presentation». Таким образом, если в проекте, допустим, 10 feature, то у нас будет минимум 30 модулей. Почему минимум? Потому что наверняка у каждого в проекте есть какие-то common модули, utils или разделяемые модули, которые мы используем в нескольких проектах.
Минусы подхода
После озвучивания варианта многомодульной архитектуры, сразу видны два основных недостатка данного подхода. Для каких-то проектов они будут неприемлемы, но в нашем случае их серьёзность нивелирована плюсами при использовании.Теперь давайте более подробно рассмотрим, о чём же идёт речь, с примерами, картинками и т.д. Но сначала задумайтесь:
Первое, что мне приходит в голову — это логин, и дальнейшая работа с токеном авторизации во всем проекте. Я уверена, что каждый из вас может придумать миллион подобных кейсов, и на любом проекте такая ситуация вряд ли будет единичной. При этом если у вас всё делится по фичам, то, скорее всего, на примере логина вам пришлось бы тянуть весь модуль логина вместе с его UI туда, где просто нужна была бы API/репозиторий логина в какой-то другой модуль. И тогда встаёт вопрос — а зачем нам тянуть это всё, и реализацию с мапперами, ретрофитом, конвертором, который вы используете для json, если нам нужны лишь пара доменных моделей и API? Именно такой кейс и стал основной причиной разделения каждой фичи на три части. Другим примером целесообразности деления можно считать скорость инкрементальной сборки при внесении изменений: представьте, что у вас поменялся endpoint у API, а вам нужно будет пересобирать весь модуль фичи, с UI и прочими штуками? А если у вас там есть какие-то тяжеловесные компоненты? Но если разделить на три части каждую фичу, то при внесении изменений пересобрать придётся только один из трёх модулей! Это же круто! А если у вас при этом модуль ещё тянулся в других фичах, они тоже должны пересобираться. В общем, по цепочке может пойти всё довольно далеко. Да, при этом у нас множится количество модулей — их становится в три раза больше. Но скорость сборки проекта у нас при этом не сильно страдает. Цифрами я тут вас, к сожалению, не порадую, но лид проекта клялся на Котлине, что на предыдущем проекте имел более сотни модулей и сборка не улетала в космос. Поверим ему. Содержимое модулейДалее пробежимся по краткому содержанию каждого из модулей и иллюстрациями соответствующих пакетов в проекте.
В доменном слое у нас находятся абстракции:
- корневые/базовые модели (модели бизнес-логики, которые никак не связаны с сетью и отображением на Ui) — data /sealed classes;
- интерфейс репозитория.
В данном модуле DI не нужен, а в остальных модулях — Data и Ui — у нас, естественно, будет Dagger.
В дата слое у нас лежат:
- DTO модели (те модели, которые нам будут приходить по сетевому слою);
- API;
- реализации репозиториев;
- мапперы из DTO в доменные модели, какие-то дополнительные мапперы, возможно;
- DI из 3 частей:
- Module — для провайда тех сущностей, которые в данном слое будут использоваться;
- Component, в котором указан наш модуль и Dependency;
- Dependency модуля (как минимум, это baseUrl для API, скорее всего, различные common провайдеры — клиент Retrofit, парсера для Json вроде Moshi. Возможно, логин/токен providers — всё, что требуется в качестве внешних зависимостей для текущего модуля).
Что касается UI модуля: он у каждой фичи будет свой особенный, но некая общая структура у всех UI модулей, конечно, имеется. Давайте расскажу о ней подробнее.
- DI из 4 частей:
- Module;
- Component;
- (опционально) Dependency модуля;
- UiChildComponentProvider — если внутри фичи есть хотя бы один экран, который имеет свой DI, то вводим данный интерфейс, который поможет нам работать с «главным экраном» или с «хостовым экраном», о которых я расскажу подробнее чуть дальше. В любом случае он будет реализовывать функции:
fun provide(module: FeatureDataModule): FeatureDataComponent
- у каждого экрана/фрагмента будет также свой набор DI — модуль, компонент и компонент-провайдер.
Чтобы сориентироваться, давайте бросим взгляд на иерархию зависимостей / вложенностей в рамках Dagger в данном случае:
И в качестве примера представим, как может выглядеть экран по фрагментам / экранам:
- Первый — это экран, открываемый из меню. На нём лежит «основной» фрагмент фичи, в котором есть несколько табов. В каждом табе — дочерние фрагменты со списком элементов, по клику на которые мы переходим в некие «подробности элемента».
- Второй экран — «подробности». Такой экран в моём примере организован как HostFragment: он представляет из себя единую точку входа для внутреннего контента, на котором располагается/подменяется внутреннее содержимое. В качестве первого показываемого экрана (а вы помните, тут может быть и некий flow) — фрагмент с ещё одним набором табов (допустим, разделение по разным категориям информации об элементе).
ВыводИтак, зачем нужна модуляризация в приложении?
- Масштабирование разработки. Подход позволяет горизонтально расширять отдел разработки без особых трудностей: новые сотрудники занимаются новыми модулями в изоляции.
- Экономия времени и ресурсов. Когда вам понадобится переиспользовать код в другом продукте, вы сразу оцените скорость, с которой можно это сделать.
- Синергия между приложениями. Продуктовые запросы обогащают модули функциональностью, которая может быть использована во всех продуктах компании.
- Качество кода. Как уже говорилось выше, когда модули специализированные, а их интерфейс прост, связность кода становится существенно ниже, как и порог вхождения в проект новых программистов. Также упрощаются поддержка и тестирование кода.
А если я всё ещё вас не убедила перейти в своём проекте на такой вариант архитектуры, то вы можете просто попробовать проектировать так те свои фичи, которые наверняка будут переиспользоваться в других модулях / фичах, чтобы снизить скорость сборки проекта при внесении изменений , применить переиспользование слоёв и устроить хорошее разделение ответственности.
===========
Источник:
habr.com
===========
Похожие новости:
- [Высокая производительность, Компиляторы, Процессоры] DSP-процессоры: назначение и особенности
- Доступна сборка Android-x86 8.1-r6
- [Программирование, Разработка под Android, Kotlin] Более безопасный способ сбора потоков данных из пользовательских интерфейсов Android (перевод)
- [Информационная безопасность, Смартфоны, IT-компании] Google автоматически устанавливала на смартфоны жителей Массачусетса приложение для уведомлений о коронавирусе
- [Анализ и проектирование систем, Производство и разработка электроники, Электроника для начинающих] Использование оптимизации выводов ПЛИС для повышения эффективности проектирования печатных плат
- [Системное администрирование, Анализ и проектирование систем, Сетевые технологии, Сетевое оборудование] Cети 10 GBE без синяков и шишек
- [Программирование, Обработка изображений, Big Data, Машинное обучение] Помогите прочитать, что здесь написано? (OCR)
- [Анализ и проектирование систем, Проектирование и рефакторинг, Хранение данных, Прототипирование] Что нам стоит дом построить? (часть 2)
- [Анализ и проектирование систем, Бизнес-модели, Схемотехника, Разработка на Raspberry Pi, Компьютерное железо] Создание терминала для СКУД и УРВ
- [Разработка мобильных приложений, Разработка под Android, Повышение конверсии] Персонализация инвайтов в приложении с использованием AppsFlyer
Теги для поиска: #_analiz_i_proektirovanie_sistem (Анализ и проектирование систем), #_razrabotka_pod_android (Разработка под Android), #_android, #_architecture, #_dagger_2, #_kotlin, #_blog_kompanii_epam (
Блог компании EPAM
), #_analiz_i_proektirovanie_sistem (
Анализ и проектирование систем
), #_razrabotka_pod_android (
Разработка под Android
)
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 14:20
Часовой пояс: UTC + 5
Автор | Сообщение |
---|---|
news_bot ®
Стаж: 6 лет 9 месяцев |
|
Сегодня я хочу познакомить вас с вариантом построения многомодульной архитектуры под Android. Но сначала обязательно вспомним про понятие Clean Architecture и для чего вообще надо задумываться об архитектуре вашего кода.Зачем нужна архитектура?Какую цель преследует тот, кто когда-либо писал или читал чьи-то доклады по разработке ПО? Обычно это одно из двух:
Это одно из самых популярных и часто используемых решений для крупных приложений с большим количеством функций и SOLID-принципами. Подход был предложен Робертом С. Мартином (известным как Дядя Боб) в блоге «Чистый код» в 2012 году.Всем известная схема, которую также иногда называют «Луковицей». Источник: https://blog.cleancoder.com/uncle-bob/2012/08/13/th...cture.htmlМногие распространённые архитектуры, такие как MVC, MVP, MVVM, MVI по сути являются вариантами подхода Сlean architecture. Они могут выглядеть запутанно, но разобравшись однажды со всей внутрянкой чистой архитектуры, в дальнейшем у вас не возникнет проблем.Итак, зачем нужен чистый подход?Принципы чистой архитектуры В основе чистой архитектуры лежит идея разделения кода на слои. Давайте бросим взгляд них. Domain-слой: Запускает независимую от других уровней бизнес-логику. В идеале — это чистый пакет Kotlin без android-зависимостей.Data-слой: Отправляет необходимые для приложения данные в domain-слой, реализуя предоставляемый доменом интерфейс.Presentation-слой: Включает в себя как domain-, так и data-слои, а также является специфическим для android и выполняет UI-логику.Исходя из данных принципов, как правило, в проектах делают так: выделяют какие-то общие модули, а остальное организуют одним из двух вариантов:
Здесь мы говорим о некой фиче, связанной с процессом авторизации. В данном случае мы через интерфейс LoginDataDependencies обозначаем внешние зависимости для модуля фичи. Другая важная составляющая «чистой» фичи — это наличие чёткого API, по которому внешний мир может обращаться к фиче. Интерфейс доменного слоя предоставляет для остальных модулей чёткое API — репозиторий со своей функциональностью. Ниже приведён пример включения данного компонента в контексте Dagger2. Здесь я буду приводить примеры кода с использованием Dagger2. Конечно, эти подходы и принципы не исчерпывающие. Ни один принцип не может быть универсальным и подходить для решения любой задачи. Плюс всегда хочется улучшать решения, либо просто поэкспериментировать. Таким образом рождаются новые решения: какие-то подходят для узких кейсов, а какие-то выходят более универсальными. И когда человек знаком с различными вариантами решений — это уже половина успеха, ведь он знает, как другие люди решали подобные задачи и всегда может воспользоваться готовым решением, адаптировав его под себя. Я хотела бы познакомить вас с нашим решением, которое лично для меня стало чем-то новым. До этого меня жизнь не сталкивала и с Dagger 2. Но основным инсайтом для меня стал принцип, который работает совместно с этим фреймворком — я говорю о варианте многомодульной архитектуры приложения Андроид.Рецепт Оливье Суть идеи, которая отличает её от тех решений, что уже известны мне на текущий момент, в том, что каждую feature нужно делить на три модуля: «Data — Domain — Presentation». Таким образом, если в проекте, допустим, 10 feature, то у нас будет минимум 30 модулей. Почему минимум? Потому что наверняка у каждого в проекте есть какие-то common модули, utils или разделяемые модули, которые мы используем в нескольких проектах. Минусы подхода После озвучивания варианта многомодульной архитектуры, сразу видны два основных недостатка данного подхода. Для каких-то проектов они будут неприемлемы, но в нашем случае их серьёзность нивелирована плюсами при использовании.Теперь давайте более подробно рассмотрим, о чём же идёт речь, с примерами, картинками и т.д. Но сначала задумайтесь: Первое, что мне приходит в голову — это логин, и дальнейшая работа с токеном авторизации во всем проекте. Я уверена, что каждый из вас может придумать миллион подобных кейсов, и на любом проекте такая ситуация вряд ли будет единичной. При этом если у вас всё делится по фичам, то, скорее всего, на примере логина вам пришлось бы тянуть весь модуль логина вместе с его UI туда, где просто нужна была бы API/репозиторий логина в какой-то другой модуль. И тогда встаёт вопрос — а зачем нам тянуть это всё, и реализацию с мапперами, ретрофитом, конвертором, который вы используете для json, если нам нужны лишь пара доменных моделей и API? Именно такой кейс и стал основной причиной разделения каждой фичи на три части. Другим примером целесообразности деления можно считать скорость инкрементальной сборки при внесении изменений: представьте, что у вас поменялся endpoint у API, а вам нужно будет пересобирать весь модуль фичи, с UI и прочими штуками? А если у вас там есть какие-то тяжеловесные компоненты? Но если разделить на три части каждую фичу, то при внесении изменений пересобрать придётся только один из трёх модулей! Это же круто! А если у вас при этом модуль ещё тянулся в других фичах, они тоже должны пересобираться. В общем, по цепочке может пойти всё довольно далеко. Да, при этом у нас множится количество модулей — их становится в три раза больше. Но скорость сборки проекта у нас при этом не сильно страдает. Цифрами я тут вас, к сожалению, не порадую, но лид проекта клялся на Котлине, что на предыдущем проекте имел более сотни модулей и сборка не улетала в космос. Поверим ему. Содержимое модулейДалее пробежимся по краткому содержанию каждого из модулей и иллюстрациями соответствующих пакетов в проекте. В доменном слое у нас находятся абстракции:
В дата слое у нас лежат:
Что касается UI модуля: он у каждой фичи будет свой особенный, но некая общая структура у всех UI модулей, конечно, имеется. Давайте расскажу о ней подробнее.
И в качестве примера представим, как может выглядеть экран по фрагментам / экранам:
=========== Источник: habr.com =========== Похожие новости:
Блог компании EPAM ), #_analiz_i_proektirovanie_sistem ( Анализ и проектирование систем ), #_razrabotka_pod_android ( Разработка под Android ) |
|
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 14:20
Часовой пояс: UTC + 5