← Назад к вопросам

Какие плюсы и минусы многомодульности?

2.0 Middle🔥 181 комментариев
#Архитектура и паттерны#Многомодульность

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Многомодульность в Android проекте

Многомодульность — это разделение приложения на несколько независимых модулей (Gradle modules). Каждый модуль имеет свою логику, ресурсы и зависимости. Это важный паттерн для масштабируемых проектов.

Структура многомодульного проекта

MyApp/
├── app/                    # App module (главное приложение)
├── feature-users/          # Feature module
│   ├── build.gradle.kts
│   ├── src/
│   └── ...
├── feature-posts/          # Feature module
├── feature-comments/       # Feature module
├── shared/                 # Shared модуль
│   ├── data/              # Слой данных
│   ├── domain/            # Бизнес логика
│   └── common/            # Утилиты
├── core/                   # Core функционал
│   ├── network/
│   ├── database/
│   └── utils/
└── gradle/

Плюсы многомодульности

1. Разделение ответственности

// Каждый модуль отвечает за свое
// feature-users модуль
module: feature-users
  ├── User model
  ├── UserViewModel
  ├── UserRepository
  ├── UserScreen
  └── User Navigation

// feature-posts модуль
module: feature-posts
  ├── Post model
  ├── PostViewModel
  ├── PostRepository
  ├── PostScreen
  └── Post Navigation

// Модули независимы, могут разрабатываться параллельно

Преимущества:

  • Ясная ответственность (каждый модуль знает что он делает)
  • Легче найти код (все User related в feature-users)
  • Проще добавлять фичи (просто создай новый модуль)

2. Быстрая компиляция

// При изменении в feature-users, компилируются только зависящие модули
// Остальные (feature-posts) не перекомпилируются

// Без многомодульности:
// Изменение в любом месте → перекомпилируется все приложение

// С многомодульностью:
// Изменение в feature-users → перекомпилируются:
// - feature-users
// - shared (если он зависит от users)
// - app (главный модуль)
// feature-posts не перекомпилируется!

3. Переиспользование кода

// core/network/build.gradle.kts
dependencies {
    implementation("com.squareup.retrofit2:retrofit:2.11.0")
    implementation("com.squareup.okhttp3:okhttp:4.12.0")
}

// shared/data/build.gradle.kts
dependencies {
    implementation(project(":core:network"))
}

// feature-users/build.gradle.kts
dependencies {
    implementation(project(":shared:data"))
}

// Один API конфиг используется везде

4. Лучшая архитектура

// Явное разделение слоев
core/
  ├── network/          // Infrastructure
  ├── database/
  └── ui/

shared/
  ├── domain/           // Domain слой
  ├── data/            // Data слой
  └── common/

feature-users/
  └── presentation/     // Presentation слой

// Зависимости идут вниз, НЕ вверх
// presentation → domain → data → network

5. Контроль зависимостей

// feature-users может зависеть от shared, но не от feature-posts
// Это предотвращает циклические зависимости

// feature-users/build.gradle.kts
dependencies {
    implementation(project(":shared:data"))
    implementation(project(":core:ui"))
    // НЕ может зависеть от feature-posts!
}

// Контролируется через build.gradle

6. Тестирование

// Каждый модуль может тестироваться независимо
// shared/data имеет свои unit тесты
// feature-users имеет свои
// Они не мешают друг другу

// shared/data/build.gradle.kts
android {
    testOptions {
        unitTests {
            includeAndroidResources = true
        }
    }
}

dependencies {
    testImplementation("junit:junit:4.13.2")
    testImplementation("org.mockito.kotlin:mockito-kotlin:5.3.1")
}

7. Динамичные фичи (Dynamic Feature Modules)

// Модули могут быть загружены динамически
// Пользователь скачивает только нужные фичи

// Android App Bundle
// feature-premium может быть загружена только для premium пользователей

// build.gradle.kts
plugins {
    id("com.android.dynamic-feature")
}

// AndroidManifest.xml
<manifest>
    <dist:module
        dist:instant="false"
        dist:onDemand="true"
        dist:title="@string/feature_title" />
</manifest>

Минусы многомодульности

1. Сложность и overhead

// Больше файлов конфигурации
// каждый модуль имеет свой build.gradle.kts

// settings.gradle.kts
include(
    ":app",
    ":feature-users",
    ":feature-posts",
    ":feature-comments",
    ":shared:data",
    ":shared:domain",
    ":core:network",
    ":core:database"
)

// Много конфигурации
// Сложнее для начинающих

2. Навигация между модулями

// СЛОЖНЕЕ: Прямая навигация через intent
// feature-users не может просто вызвать DetailActivity из feature-posts

// РЕШЕНИЕ 1: Через Navigation
// feature-users/src/main/res/navigation/users_nav.xml
<navigation>
    <deepLink
        app:uri="myapp://posts/{id}"
        android:id="@+id/post_detail" />
</navigation>

// РЕШЕНИЕ 2: Через implicit intents
val intent = Intent(Intent.ACTION_VIEW).apply {
    data = Uri.parse("myapp://posts/123")
}
startActivity(intent)

// РЕШЕНИЕ 3: Через dependency injection
interface PostNavigator {
    fun navigateToDetail(postId: String)
}

feature-users зависит от интерфейса, а app провайдит реализацию

3. Синхронизация версий

// Нужно следить чтобы все использовали одну версию зависимостей

// gradle/libs.versions.toml
[versions]
kotlin = "1.9.0"
compose = "1.7.0"
retrofit = "2.11.0"

[libraries]
retrofit = { group = "com.squareup.retrofit2", name = "retrofit", version.ref = "retrofit" }

// Все модули используют отсюда
dependencies {
    implementation(libs.retrofit)
}

4. Общие ресурсы

<!-- Ресурсы (drawable, colors) нужно помещать в shared модуль -->
<!-- или в app если они общие -->

core/ui/res/values/colors.xml
<resources>
    <color name="primary">#6200EE</color>
    <color name="secondary">#03DAC6</color>
</resources>

feature-users/res/values/colors.xml
<!-- Используй ресурсы из core.ui -->

5. Разработка вместе

// Команда может работать параллельно
// Dev1 разрабатывает feature-users
// Dev2 разрабатывает feature-posts
// Dev3 работает над core/network

// Но нужна хорошая коммуникация
// если меняется shared/domain API

Когда использовать многомодульность

ИСПОЛЬЗУЙ если:

  • Приложение > 10k строк кода
  • Команда > 2 человек
  • Нужна параллельная разработка
  • Нужна хорошая архитектура
  • Хочешь динамичные фичи

НЕ ИСПОЛЬЗУЙ если:

  • Приложение маленькое (< 3k строк)
  • Работаешь один
  • Проект в прототипе
  • Боишься сложности

Пример структуры production приложения

MyApp/
├── app/                           # App module (главное)
│   └── build.gradle.kts
├── feature/
│   ├── feature-auth/              # Авторизация
│   ├── feature-users/             # Пользователи
│   ├── feature-posts/             # Посты
│   └── feature-comments/          # Комментарии
├── shared/
│   ├── domain/                    # Entities, UseCases
│   ├── data/                      # Repositories, DataSources
│   └── ui-components/             # Переиспользуемые UI компоненты
├── core/
│   ├── network/                   # Retrofit, OkHttp
│   ├── database/                  # Room, entities
│   ├── cache/                     # Кэширование
│   └── logger/                    # Логирование
└── gradle/
    └── libs.versions.toml         # Версии всех зависимостей

Итог

Плюсы:

  • Чистая архитектура
  • Быстрая компиляция
  • Параллельная разработка
  • Переиспользование кода
  • Контроль зависимостей
  • Лучше тестируемость
  • Динамичные фичи

Минусы:

  • Сложность
  • Навигация между модулями
  • Синхронизация версий
  • Управление ресурсами

Многомодульность — это best practice для production приложений и показывает профессиональный подход к разработке.