На каком уровне декомпозиции стоит делать модули в Android приложении?
Что проверяют
По какому критерию вы режете проект. Правильного числа модулей не существует, поэтому слушают, называете ли вы цену решения: время сборки, граф зависимостей, владение кодом. Ответ «по слоям» или «по фичам» без обоснования засчитывается плохо.
Как отвечать
Скажите главное: модуль в Android это единица сборки Gradle, поэтому декомпозиция это решение про сборку и границы команд, а не про красоту структуры. Рабочая раскладка:
:appтонкий: сборка графа зависимостей, навигация верхнего уровня, инициализация;:feature:*по фичам, каждая со своим UI, логикой и данными;:core:*общие кирпичи: сеть, база, дизайн-система, аналитика;- где фичам нужно знать друг о друге, деление на
apiиimpl: зависят от лёгкогоapi, реализация подставляется в:app.
Дальше правила: фичи не ссылаются друг на друга напрямую, переходы через абстракцию навигации, общие настройки сборки выносятся в convention plugins, а не копируются по всем скриптам сборки.
И критерий, ради которого вопрос задан: делить стоит там, где есть выигрыш. Параллельная и инкрементальная сборка, отдельное владение у команды, переиспользование, изоляция тестов. Если ни одного повода нет, лишний модуль только добавляет время конфигурации проекта.
Где спотыкаются
Режут по слоям на весь проект: :ui, :domain, :data. Любая правка одной фичи трогает все три модуля, пересборка идёт по всей цепочке, и обещанного выигрыша в скорости нет.
Второе: десятки микромодулей «для чистоты». Конфигурация проекта и кодогенерация внедрения зависимостей начинают занимать больше времени, чем сама компиляция, а навигация по коду усложняется.
Третье: модуль :common, куда складывают всё, что понадобилось двум фичам. От него зависит весь проект, поэтому любая правка внутри инвалидирует кэш сборки целиком, и он же быстро обрастает циклическими связями, которые приходится разрывать интерфейсами задним числом.