Sobes.tech
Назад к вопросам
Junior — Middle
52

Почему важно внедрять зависимости в класс или модуль?

Компании, где спрашивали
NetUP

Ответ от нейросети

sobes.tech AI

Что хотят услышать интервьюеры:

Внедрение зависимостей делает код слабосвязанным и проще в сопровождении. Класс не создаёт нужные ему объекты сам, а получает их извне, поэтому его легче тестировать, заменять реализации и переиспользовать. Для Android это особенно важно, потому что так проще управлять зависимостями жизненного цикла, например для ViewModel, репозиториев и сервисов.

Определение:

Внедрение зависимостей — это подход, при котором объект получает свои зависимости извне, а не создаёт их внутри себя. Зависимостью может быть любой необходимый объект: репозиторий, API-клиент, база данных, логгер и так далее.

Главная идея — отделить использование объекта от способа его создания. Тогда класс отвечает только за свою бизнес-логику, а создание и сборка объектов выносятся наружу.

Пример использования:

Допустим, UserViewModel должен получать данные пользователя через UserRepository. Если ViewModel создаёт репозиторий сама, её сложно тестировать и заменять реализацию. Если же репозиторий передаётся через конструктор, можно подменить его на fake-реализацию в тестах.

interface UserRepository {
    fun getUserName(): String
}

class RealUserRepository : UserRepository {
    override fun getUserName(): String = "Alice"
}

class UserViewModel(
    private val repository: UserRepository
) {
    fun loadUserName(): String {
        return repository.getUserName()
    }
}

В тесте можно передать другой вариант:

class FakeUserRepository : UserRepository {
    override fun getUserName(): String = "Test User"
}

val viewModel = UserViewModel(FakeUserRepository())
println(viewModel.loadUserName()) // Test User

Пояснение кода:

В примере UserViewModel не знает, откуда берётся UserRepository. Он просто использует интерфейс и ожидает готовый объект снаружи. Это позволяет:

  1. Подставить реальную реализацию в приложении.
  2. Подставить fake или mock в тестах.
  3. Не менять ViewModel при смене источника данных.

Если бы UserViewModel создавал RealUserRepository внутри себя, то при изменении логики создания пришлось бы править саму ViewModel. При внедрении зависимостей достаточно изменить место сборки объектов.

Ключевые моменты:

  • Уменьшает связанность между классами.
  • Упрощает модульное тестирование через подмену зависимостей.
  • Повышает переиспользуемость и гибкость кода.
  • Централизует создание объектов и управление их жизненным циклом.
  • В Android помогает особенно хорошо организовать ViewModel, репозитории, UseCase и сервисы.
  • Часто реализуется через конструктор, реже через параметр метода или поле.