2010-01-02 3 views
3

Я пытаюсь охватить широко распространенную инъекцию зависимости/IoC. Поскольку я читаю все больше и больше о преимуществах, которые я, безусловно, могу им их оценить, однако я обеспокоен тем, что в некоторых случаях использование шаблона инъекций зависимости может привести к созданию гибкости за счет возможности ограничения риска путем инкапсуляции элементов управления на то, что система способна делать и какие ошибки я или другой программист проекта могут сделать. Я подозреваю, что у меня что-то отсутствует в шаблоне, который касается моих проблем, и я надеюсь, что кто-то сможет это указать.Влияет ли инъекция зависимости, мой риск сделать что-то глупое?

Вот упрощенный пример того, что касается меня. Предположим, у меня есть метод NotifyAdmins в классе Notification, и я использую этот метод для распространения очень чувствительной информации для пользователей, которые были определены как администраторы в приложении. Информация может быть распространена по факсу, электронной почте, чату и т. Д. На основе пользовательских настроек. Этот метод должен получить список администраторов. Исторически я бы инкапсулировал создание набора администраторов в методе вызовом класса AdminSet или вызовом класса UserSet, который запрашивает набор пользовательских объектов, которые являются администраторами, или даже посредством прямого вызова (-ов) база данных. Затем я могу вызвать метод Notification.NotifyAdmins, не опасаясь случайной отправки конфиденциальной информации не-администраторам.

Я считаю, что инъекции зависимостей требуют, чтобы я взял список администраторов в качестве параметра (в той или иной форме). Это облегчает тестирование, однако, что мешает мне совершить глупую ошибку при вызове кода и передаче в составе NonAdmins? Если я не буду вводить набор, я могу случайно послать неверным людям неправильные ошибки в одном или двух фиксированных местах. Если я делаю инъекцию набора, я не подвергаюсь этой ошибке всюду, я вызываю метод и вводя набор администраторов? Я делаю что-то неправильно? Существуют ли средства в рамках IoC, которые позволяют вам указывать эти ограничения, но все же использовать инъекции зависимостей?

Спасибо.

+0

Нет, но посещение stackoverflow.com делает :-) – bmargulies

ответ

0

Нет, инъекция зависимостей не требует передачи списка администраторов в качестве параметра. Я думаю, вы слегка недооцениваете это. Тем не менее, в вашем примере вам понадобится инъецировать экземпляр AdminSet, который использует ваш класс Notification для создания своего списка администраторов. Затем это позволит вам обмануть этот объект, чтобы проверить класс Notification в изоляции.

Зависимости обычно вводятся во время создания экземпляра класса с использованием одного из этих методов: интродукция конструктора (передача зависимых экземпляров класса в конструкторе класса), свойство injecion (установка зависимых экземпляров класса как свойств) или что-то еще (например, делая все инъекционные объекты реализовать конкретный интерфейс, который позволяет контейнер МОК вызвать единственный метод, который вводит его зависимость. Они обычно не вводят в каждый вызов метода, как вы предлагаете.

+0

По параметру я имел в виду инъекцию в отличие от определенного внутри класса. Извините за отсутствие ясности. Меня заставляет нервничать, вводя информацию о Admin вообще. В более общем плане, если я получаю данные внутри метода, я знаю, откуда я его получаю. Если он вводится, как я знаю, данные - это те же самые данные, которые я хочу, а не только структурно идентичные? Если я могу издеваться над тем, какой класс/набор классов представляет собой информацию администратора (что, безусловно, хорошо с точки зрения проверки), не означает ли это, что метод не может доверять полученным данным? – bglenn

+0

Это не данные, которые вы вводите, это класс, который используется для создания/извлечения данных. –

4

вы должны изменить свое мышление.

Если у вас есть служба/класс, который должен отправлять только частную информацию администраторам, вместо этого передачи списка админов этой службе, вместо этого вы передаете другую службу, из которой класс может получить список администраторов.

Да, у вас еще есть возможность совершить ошибку, но этот код:

AdminProvider provider = new AdminProvider(); 
Notification notify = new Notification(provider); 
notify.Execute(); 

сложнее ошибиться, чем это:

String[] admins = new String[] { "[email protected]" }; 
Notification notify = new Notification(admins); 
notify.Execute(); 

В первом случае, методы и классы должны были быть названы так, что было бы легко обнаружить ошибку.

Внутренне в вашем Execute метод, то код может выглядеть следующим образом:

List<String> admins = _AdminProvider.GetAdmins(); 
... 

Если по какой-то причине, код выглядит следующим образом:

List<String> admins = _AdminProvider.GetAllUserEmails(); 

то у вас есть проблемы, но это должно быть легко обнаружить.

+0

+1 - Не мог бы лучше сказать это. – ChaosPandion

+0

Вы можете даже «отменить» его еще больше и передать поставщику уведомлений в свой AdminSet. – Cellfish

+1

+1 Хороший ответ, но см. Мой ответ для получения дополнительных параметров. –

0

Другие хорошие ответы уже даны, но я хотел бы добавить следующее:

Вы можете быть как открытой для расширяемости (после Open/Closed Principle) и по-прежнему защищать чувствительные активы. Один хороший способ - использовать шаблон Specification.

В этом случае вы можете передать полностью произвольный список пользователей, но затем фильтровать эти пользователи с помощью AdminSpecification, чтобы только администраторы получали уведомление.

Возможно, ваш класс Уведомление будет иметь API, подобную этой:

public class Notification 
{ 
    private readonly string message; 

    public Notification(string message) 
    { 
     this.message = message; 

     this.AdminSpecification = new AdminSpecification(); 
    } 

    public ISpecification AdminSpecification { get; set; } 

    public void SendTo(IEnumerable users) 
    { 
     foreach(var u in users.Where(this.AdminSpecification.IsSatisfiedBy)) 
     { 
      this.Notify(u); 
     } 
    } 

    // more members 
} 

Вы все еще можете переопределить поведение фильтрации для тестирования-целей путем присвоения гладкошерстных спецификации, но значение по умолчанию является безопасным, так что вы бы с меньшей вероятностью ошибиться в этом API.

Для лучшей защиты вы можете обернуть всю реализацию за интерфейсом Facade.

+0

Notification.SendTo принимает пользователей в качестве параметра, который согласуется с DI и, безусловно, хорош для проверки (другие будут комментировать, он должен быть введен в конструктор, что не имеет для меня значения для целей этого вопроса). Но не может ли какой-либо звонящий собрать любой набор пользовательских объектов и отправить их методу? Шаблон спецификации интересен, но не нужно ли его применять к доверенному набору объектов, и не означает ли это, что SendTo нужно забирать сами пользователи (что, разумеется, прерывает DI)? – bglenn

+0

Спецификация по существу является фильтром, поэтому вы можете предоставить любое количество пользователей, и только те, кто передает фильтр, получат уведомление.Таким образом, неважно, какие пользователи вы предоставляете, потому что у вас есть внутренний охранник, который защищает вас от ошибок. –

Смежные вопросы