Dependency Injection (DI) — паттерн, который передаёт управление зависимостями Инверсия управления означает, что объект получает зависимости извне Подход обеспечивает слабую связанность и делает код удобнее для тестирования Пример реализации на Python:
Как выглядит пример Dependency Injection в коде?
Dependency Injection (DI) — паттерн, который передаёт управление зависимостями Инверсия управления означает, что объект получает зависимости извне Подход обеспечивает слабую связанность и делает код удобнее для…
Короткий ответ
Что ответить на собеседовании
Подробный разбор
Ответ с пояснениями
Как выглядит пример Dependency Injection в коде?
- Dependency Injection (DI) — паттерн, который передаёт управление зависимостями
- Инверсия управления означает, что объект получает зависимости извне
- Подход обеспечивает слабую связанность и делает код удобнее для тестирования
- Пример реализации на Python:
class Engine:
def start(self):
print("Engine started")
class Car:
def __init__(self, engine):
self.engine = engine # DI через конструктор
def drive(self):
self.engine.start()
print("Car is driving")
engine = Engine()
car = Car(engine)
car.drive()
С помощью DI в тестах или для альтернативной реализации можно передать другой Engine
В крупных проектах фреймворки DI, включая Spring, Guice и Dagger, автоматически выполняют внедрение зависимостей
Ключевой принцип DI заключается в том, что зависимости передаются в класс, а не создаются внутри него
Этот код показывает принцип DI: класс Car самостоятельно не создаёт Engine, а получает его извне. Благодаря этому код становится гибче, а его тестирование — проще.
Развёрнутый ответ
Основной ответ
Dependency Injection (DI) — паттерн проектирования, при котором зависимости объекта, например сервисы и репозитории, поступают извне вместо создания внутри самого объекта. Такой подход разделяет ответственность за создание зависимостей и их применение, повышая тестируемость, гибкость и сопровождаемость кода.
Основные моменты
- В классическом примере на C# с .NET Core зависимости чаще всего передают через конструктор (Constructor Injection). Это наиболее распространённый и понятный вариант DI.
- DI-контейнер, например встроенный в ASP.NET Core, автоматически разрешает зависимости и управляет временем жизни объектов.
- Такой подход снижает жёсткую связанность компонентов и позволяет проще подменять реализации моками или альтернативными вариантами во время тестирования.
Пример кода на C#
public interface ILogger
{
void Log(string message);
}
public class ConsoleLogger : ILogger
{
public void Log(string message) => Console.WriteLine(message);
}
public class UserService
{
private readonly ILogger _logger;
// Dependency Injection через конструктор
public UserService(ILogger logger)
{
_logger = logger;
}
public void CreateUser(string username)
{
// Логируем создание пользователя
_logger.Log($"User '{username}' created.");
}
}
// Регистрация и использование
var serviceProvider = new ServiceCollection()
.AddSingleton<ILogger, ConsoleLogger>()
.AddTransient<UserService>()
.BuildServiceProvider();
var userService = serviceProvider.GetService<UserService>();
userService.CreateUser("Ivan");
Практический контекст
В реальных проектах DI помогает управлять сложной иерархией зависимостей, включая сервисы доступа к данным, логирование, кэширование и интеграции с внешними API. С ним проще создавать модульные тесты: конкретные реализации можно заменять мок-объектами. В ASP.NET Core версии 3.1+ и более новых версиях встроенный DI-контейнер является стандартным инструментом управления зависимостями.