Внедрение зависимостей - DI - Dependency injection - термин часто встречающийся на собеседованиях. Сам по себе концепт опирается на более объемный принцип инверсии зависимостей (буква D в SOLID), но намного проще и ближе к практике. Кратко можно сказать, что при внедрении зависимостей, мы задаем значения переменных объекта в момент выполнения программы, а не в момент компиляции. В этой статье я постараюсь показать, что использование специальных библиотек для DI  - это легко и удобно, даже для небольших проектов и опишу три случая с кодом ДО и ПОСЛЕ. Надеюсь, даже в небольшом проекте сразу станет понятно, что код после применения внедрения зависимостей стал чуть-чуть лучше.  Часто программисты не понимают, для чего им в их небольших проектах, которые далеки от тысяч файлов корпоративных громад, нужно внедрение зависимостей. В таких проектах не описываются интерфейсы, используются одни и те же классы, экземпляры которых можно передать всем, кому это необходимо. На самый крайний случай, используются синглтоны для получения единственного экземпляра класса во всем приложении. Работать мы будем с достаточно популярной библиотекой GetIt. Проект минималистичен: приложение показывает погоду в настоящий момент  с использованием одного из двух сервисов: Yandex.Weather или VisualCrossing. Если пользователь разрешит, то учитывается его местоположение и погода будет актуальна для его города. Пример 1. Переход от внедрения переменных через конструктор и создания их в коде к использованию GetIt. В нашем случае настройки приложения, а именно - какой сервис для получения погодных данных был выбран пользователем - хранятся в стандартном платформенно-зависимом хранилище - SharedPreferences. При запуске приложения запускается тот сервис, который был выбран ранее. Если ничего не выбрано, запускается сервис по-умолчанию.  До внедрения GetIt класс настроек создавался в main и передавался в остальные классы через конструктор: После внедрения GetIt класс настроек регистрируется в нем и затем его получают только там, где он действительно нужен, промежуточные классы не загромождаются лишними переменными. И переход на внедрение зависимостей вместо создания переменной: получение позиции пользователя. Для этой операции в _HomePageState используется Geolocator. В дальнейшем при юнит-тестировании и виджет-тестировании мы не сможем обращаться к этой библиотеке, поэтому нужно заменить способ получения позиции пользователя на DI. Было: Стало: Аналогично может быть зарегистрирована служба логирования, служба обработки ошибок, клиент http и т.д. Нет нужды упоминать экземпляр класса в конструкторе, а значит меньше параметров, которые необходимо задать при инициализации. Пример 2. Использование одного из поставщиков данных. В приложении описан общий интерфейс получения погодных данных, тем не менее каждый раз определять, к какому конкретно классу надо обратиться для получения данных, - неудобно. Здесь тоже поможет GetIt. Вместо того, чтобы создавать экземпляр класса в виджете, который ответственен за показ погоды и пересоздавать виджет или экземпляр класса, в коде используется геттер, который получает всегда актуальный класс-поставщик погодных данных через GetIt.  Было: Стало: Аналогично можно регистрировать онлайн/оффлайн поставщики данных, любые взаимозаменяемые модули. Пример 3. Использование mock-объектов для тестирования. А теперь нам нужно написать виджет-тесты. Если бы проект был чуть более сложным и включал например BLoC для управления состоянием, то эти модули тоже нужно было бы тестировать с помощью юнит-тестов. И здесь мы сразу встречаемся с невозможностью сделать это без дополнительного изменения кода, потому что при юнит-тестировании и виджет-тестировании SharedPreferences и Geolocator недоступны, да и предсказать, что ответит бэкенд невозможно. С GetIt тест написать просто - создаем mock-класс для настроек или для поставщика данных, моделируем ответы бэкенда, отображение которых будет легко проверить, через Mockito и можно быть уверенным в корректности работы приложения. В наших проектах в Россельхозбанке мы применяем GetIt в основном для тестирования и упрощения кода аналогично первому и третьему примеру. Бывают и ситуации, когда используются разные классы, реализующие одинаковый интерфейс, в зависимости от того, какой билд был создан. Например, для debug билда все логирование происходит в консоли, а для release билда используется другой класс логирования, который отправляет информацию о критических ошибках на бэкенд. Подведу итоги. В применении библиотек для Dependency Injection есть неоспоримые преимущества:  меньше параметров в классах,  нет нужды менять код объекта, если зависимый класс поменял что-то в своей реализации или был заменен другим,  возможность использования mock-объектов при тестировании. Mobile developer