Pull to refresh

Comments 16

Инкрементальная сборка и холодная дают одинаковый артифакт? Часто инкрементальная даёт бОльший по размеру результат

Android Studio — наш основной инструмент, которым мы пользуемся изо дня в день. Хочется, чтобы он не сбоил, а был верным и надежным помощником.

медленная Android Studio: code completion, finding usages, navigation и так далее;

Android Studio не особо экономичная в этом плане, скорее прожорливая.

и лагающей Android Studio.

Отличная реклама Kotlin и описание состояния современного программирования, когда программисты для себя нормальный продукт создать не могут. Ещё и глючный. А выход в релиз сразу с критичными и выдимыми багами, останаваливающими работу, вообще заставляет задаваться вопросом где же все эти лучшие практики программирования.

Размер артефактов не измерял.

По инструментам отвечю. Android Studio и gradle имеют свои проблемы влияющие на скорость сборки или количество потребляемой памяти. И есть множество оптимизаций, оптимизаций, которые позволяют ускорить сборку. Спасибо разработчиком этих инструментов за это.

Но есть также и другая сторона - это проекты с неправильными зависимостями между модулями. Когда все переплетено в связях и нет четких границ у модулей, это приводит к тому, что при каждом чихе пересобирается пол проекта.

Однозначно нужно следить за архитектурой проекта и развязывать зависимости. За нас эту работу Android Studio или gradle не сделают.

Спасибо больше за статью, в русскоязычном сегменте не так много материалов по тому, как правильно готовить демки. Круто, что вы решили его подготовить.

Мне в статье не хватило конкретных проблем и историй о том, как вы их решали и поддерживали корректность работы. Очень часто в демо-приложениях "болит" конфигурация DI, бойлерплейт, некорректное подключение gradle-зависимостей, формирование корректного стейта приложения для конкретного экрана, демо-аппы для флоу vs атомарные демо-аппы для фич, Было бы круто это так же описать и рассказать. По моему опыту, это не только проблемы вашего проекта, они возникают у всех, кто реализует этот подход)

Мы в Avito начали делать демо-приложения еще 3 года назад, и столкнулись с многими проблемами, которые вы описали: heavy-модули, тянущие за собой огромное количество реализаций, транзитивное подключение цепочек модулей, и так далее.

Square в своих докладах по модуляризации предлагает отличную архитектуру для того, чтобы рулить сложностью демо-приложений . Там рассказывается довольно простой и понятный концепт инверсии зависимостей, только прямо на уровне билд-системы.

Еще интересные инсайты по тому, как организовать многомодульный проект и следить за корректностью связей рассказывают Tinder в своем докладе по развязыванию структуры модулей. При работе с демками очень важна валидация корректной структуры зависимостей, потому что если они будут

Спасибо за подробный уоммент и полезные ссылки)

Проблем было много и еще много осталось. Например одна из проблем это общий модуль с бд.

Чтобы избегать болерпрейт всю базовую настройку вынесли во фреймворк для демок. Разработчики только указывают то, что им нужно для конкретной демки, к примеру подключают фичи свои или выключают автризацию и используют мок ответы для бэка.

По некорректному подключению gradle завичимостей у нас есть gradle plugin. Он регает таску, которая ругается если что то подключили не туда или выводит список модулей, которые стоит почистить от неправильных зависимостей прежде всего, чтоб уменьшить модули в демке. Кстати плагин хотим заоупенсорсить.

По di зависит от проекта, но можно подумать над тем, чтобы описать как это реализовано у нас.

Про стейт приложения не совсем понял. Могли бы детальнее расписать?

Под стейтом приложения - имею ввиду, что демо фичи A может содержать только экран с фичей A.

А показа этого экрана может требоваться какое-то предварительно сформированное состояние: например, при переходе на экран оплаты заказа, юзер должен быть авторизован, а где-то в хранилище должна лежать сформированная корзина.

Еще один интересный момент - это как формировать (и стоит ли) работу с реальным/тестовым сервером в демо-аппках, и стоит ли давать такую возможность.

Кстати, по поводу DI у нас очень хорошо себя показывает Anvil: он минимизирует конфигурацию в демках, и убирает большое количество бойлерлпейта. Интересно было бы послушать и про ваше решение)

А не размышляли над тем, чтобы уменьшить количество подключаемых модулей к demo-приложению через моки?

Все зависимости, реальная работа которых не очень важна для функциональности demo-приложения и его логики, можно банально замокать через, например, MockK.

mockk<BduCustomizeDependencies>(relaxed = true)

Выглядит как костыль, не спорю, но это работает. Правда, при условии, что у вас фичи делятся на api/(impl, ui, bl) модули.

В нашем случае это помогало избегать подключения аналогов :legacy-heavy-module. Что резко сокращало количество подключаемых модулей.

Похожая схема как раз описывается в докладе Square, и там называется fake-модулями.

У каждой фичи есть feature:public-часть, которая содержит только публичные интерфейсы. Реальные имплементации этих интерфейсов находятся в feature:impl, а фейковые - в feature:fake:

С такой структурой модулей настраивать различные степени валидации и проверки для демо-приложений. Например, если для критична атомарность - каждое демо-приложение может подключить в себя только одну реальную фичу, а все остальные реализации public-модулей должны быть фейками.

В Avito мы в данный момент адоптим этот подход, и переходим на структуру модулей с public/impl/fake, одновременно выправляя зависимости демок.

Спасибо за детальный коммент)

Мы также подключаем api модули с минимальным количеством зависимостей. Fake это видимо что то по типу заглушек без реальной реализации. У нас такие вещи в test fixtures, отдельный модуль не создаем для этого. Но это вопрос реализации, кому как удобнее. Отдельный модуль с фейками тоже ок, главное его не подключать к модулю app и убирать из settings.gradle чтоб не синкать, а подключать только в settings.gradle для демки.

Движемся как раз в сторону api/impl. Пока есть горстка модулей без api.

Для уже существующих модулей api так и делаем, мокаем/стабаем все лишнее.

Спасибо за интересную статью. Тема крайне актуальная и важная для крупных проектов. Тоже пытался по разному подступиться к этой проблеме на рабочем проекте (550+ gradle модулей, 2М+ LOC), делал оптимизацию сборки, дружащие с местным DI стабы -impl модулей (разбиение на -api, -impl, -stub), но взрывного эффекта, это, конечно, всё равно не давало.

По моему опыту работы с Gradle, он очень плохо переносит большое количество модулей, каждый новый модуль добавляет существенный импакт на время сборки, даже если это просто -stub модуль с "пустыми" реализациями интерфейсов из -api, количество модулей, к сожалению не меняется, время конфигурации (существенное узкое место, особенно актуальное в "горячих" сборках) не уменьшается, configuration-cache не всегда адекватно работает из-за некоторых подключённых к сборке плагинов, а выигрыш на тасках сборки модуля есть, но не огромный.

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

Спасибо ещё раз!

Спасибо за такой развернутый комментарий!

Очень рад, когда выходят такие статьи, спасибо!
А пробовали ли вы хранить модули в виде .aar и работать с исходным кодом модулей (от которых зависит текущий модуль разрабатываемой фичи) только если требуется вносить изменения в них?
Изменился модуль - пересобрали .aar и зависимые от него модули так же по графу дальше (в сторону верхнего, :bank в вашем случае).
Сейчас думаю про это, кажется, такой подход может позволить остановить растущую сложность проекта на приемлемой отметке: для сборки assemble, assembleAndroidTest это так же даст профит (т.е. на релиз не тратим 30минут, а успеваем за кратно меньшее время).

Имеется ввиду подключать не исходники, а уже скомпилированные .aar? Если да, то мы это исследуем сейчас. Пока ничего не могу сказать. Это может помочь, если приходится менять код в главном модуле :app, куда подключены все остальные модули. Все модули к можно подключить как .aar к :app модулю, тогда синк и сборка. :app должна быть быстрее. Но пока это лишь предположения)

Если сделаете - дайте пож знать) Хоть без статьи, просто в лс - буду благодарен

Получается, что архитектура с делением модулей на "api" и их имплементации это самое идеальное решение, если нужна модульная архитектура (почти всегда, если приложение теоретически должно работать больше месяца). И зависимости провайдятся замечательно Даггером между модулями, и имплементации в любой момент можно поменять/отредачить без затрагивания других. Ну и как уже написали выше, можно подменять в депоприложениях в тех случаях, когда какой-нибудь "feature-impl" модуль зависит от большого количества "feature-impl".

Есть и другие способы. Зависит от архитектуры проекта. Api/impl подходит для нашего проекта.

Но есть еще вариант когда каждая фича внутри себя объявляет Dependencies (например интерфейс навигации, который нужен только этой фиче, провайдер данных и т.д.), которые должны предоставить этой фиче из других фич, как правило это происходит где-нибудь в app модуле (так он знает обо всех модулях). Этот подход также позволяет создавать модули изолировано. Тогда в демоприложении не будет подключаться ничего лишнего, так как связей между модулями нет.

Sign up to leave a comment.

Information

Website
l.tbank.ru
Registered
Founded
Employees
over 10,000 employees
Location
Россия