Страницы

Поиск по вопросам

среда, 18 декабря 2019 г.

Для чего необходимо внедрение зависимости (dependency injection)?

#шаблоны_проектирования #net #c_sharp


Вот пример кода из всеми любимого тутора Nerddinner
public class DinnersController : Controller {

    IDinnerRepository dinnerRepository;

    //
    // Dependency Injection enabled constructors

    public DinnersController()
        : this(new DinnerRepository()) {
    }

    public DinnersController(IDinnerRepository repository) {
        dinnerRepository = repository;
    }

   ...

Какая разница, если я буду создавать объект репозитория в методах контроллера? 
   public ActionResult Edit(int id) {

        DinnerReposotiry dinnerRepository = new DinnerRepository();
        Dinner dinner = dinnerRepository.GetDinner(id);

        if (!dinner.IsHostedBy(User.Identity.Name))
            return View("InvalidOwner");

        return View(dinner);
    }
    


Ответы

Ответ 1



Использование DependencyInjection даёт три преимущества. Возможность подменить некий сервис, не являющийся технологически нейтральным. Возможность автоматически тестировать различные модули программы независимо. В Вашем примере Dependency Injection позволяет написать автоматический тест, проверяющий, что DinnersController правильно вызывает методы DinnerRepository. Возможность повторно использовать код DinnersController с другими реализациями IDinnerRepository.

Ответ 2



Разница в том, что в классе-потребителе ты будешь работать с объектом на уровне абстракций и иметь возможность подставлять любую реализацию абстрактного интерфейса. Приведу пример: У тебя есть интерфейс, который предоставляет некий набор операций. Сегодня заказчик хочет, чтобы метод GetSomeInfo() реализации этого интерфейса обращался к локальной БД, а так же в будущем еще и к веб-сервисую На начальном этапе ты пишешь реализацию MyBDInterfaceImplementation, у которой GetSomeInfo() обращается к базе. Класс-потребитель при этом просто знает об интерфейсе, что он владеет методом GetSomeInfo и вызывает его. Потом ты реализуешь другой класс, который реализует этот интерфейс и метод GetSomeInfo() в данном случае обращается к веб-сервису. В итоге в классе потребителе тебе не нужно ничего менять, только в месте, где вызывается конструктор этого класса передать ему объект другого типа. Таким образом, на практике пользователь твоего приложения выбирает использовать локальную БД - ты в конструктор класса потребителя передаешь первую реализацию интерфейса, если пользователь выберет веб-сервис - аналогично подставляешь реализацию с доступом через веб-сервис. Следующий плюс - тестируемость. Во-первых, легко писать используя TDD, User Stories и тд. Во-вторых, легко тестировать с помощью моков, подставных реализаций и тд. Так же полезной будет статья Фаулера об IoC. Книги Роба Мартина об агил-девелопменте и чистом коде. Надеюсь, ответ на вопрос помог разобраться.

Комментариев нет:

Отправить комментарий