МОК и разрешение антишаблона сверхинжекции конструктора

Этим вопросом является результат сообщения Jeffery Palermo о том, как обойти разветвленный код и внедрение зависимости http://jeffreypalermo.com/blog/constructor-over-injection-anti-pattern/

В его сообщении у Jeffery есть класс (public class OrderProcessor : IOrderProcessor) это берет 2 интерфейса на конструкторе. Каждый - блок проверки допустимости IOrderValidator и IOrderShipper интерфейс. Его ответвления кода метода только после использования методов на IOrderValidator взаимодействуйте через интерфейс и никогда ничего не использует на IOrderShipper интерфейс.

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

Я предполагаю, что затруднение проблемы, мы используем МОК для создания всех наших объектов независимо, если они используются или нет. Если Вы инстанцируете объекта с 2 интерфейсами и имеете код, который мог бы перейти для не использования одного из них, как Вы обрабатываете его?

В этом примере мы принимаем _validator.Validate(order) всегда возвращает false и IOrderShipper.Ship() метод никогда не называют.

Исходный код:

public class OrderProcessor : IOrderProcessor
{
    private readonly IOrderValidator _validator;
    private readonly IOrderShipper _shipper;

    public OrderProcessor(IOrderValidator validator, IOrderShipper shipper)
    {
      _validator = validator;
      _shipper = shipper;
    }

    public SuccessResult Process(Order order)
    {
      bool isValid = _validator.Validate(order);
      if (isValid)
      {
          _shipper.Ship(order);
      }
      return CreateStatus(isValid);
    }

    private SuccessResult CreateStatus(bool isValid)
    {
        return isValid ? SuccessResult.Success : SuccessResult.Failed;
    }
}

public class OrderShipper : IOrderShipper
{
  public OrderShipper()
  {
      Thread.Sleep(TimeSpan.FromMilliseconds(777));
  }

  public void Ship(Order order)
  {
      //ship the order
  }
}

Пересмотренный код

public class OrderProcessor : IOrderProcessor
{
    private readonly IOrderValidator _validator;

    public OrderProcessor(IOrderValidator validator)
    {
      _validator = validator;
    }

    public SuccessResult Process(Order order)
    {
      bool isValid = _validator.Validate(order);
      if (isValid)
      {
          IOrderShipper shipper = new OrderShipperFactory().GetDefault();
          shipper.Ship(order);
      }
      return CreateStatus(isValid);
    }

    private SuccessResult CreateStatus(bool isValid)
    {
        return isValid ? SuccessResult.Success : SuccessResult.Failed;
    }
}   

public class OrderShipperFactory
{
    public static Func CreationClosure;
    public IOrderShipper GetDefault()
    {
        return CreationClosure(); //executes closure
    }
}

И вот метод, который настраивает эту фабрику во время запуска (global.asax для ASP.NET):

private static void ConfigureFactories()
{
    OrderShipperFactory.CreationClosure =
        () => ObjectFactory.GetInstance();
}

10
задан alexandrul 19 May 2010 в 09:11
поделиться

3 ответа

Я только что опубликовал опровержение поста Джеффри Палермос .

Короче говоря, мы не должны позволять деталям реализации конкретных влияния на наш дизайн. Это было бы нарушено принципу замены Лисива в архитектурном масштабе.

Более элегантное решение позволяет нам сохранить дизайн, представляя предусматривание ленивого загрузки.

22
ответ дан 3 December 2019 в 17:20
поделиться

Я думаю, что анти-образник здесь - чрезмерное использование интерфейсов.

-2
ответ дан 28 October 2019 в 22:00
поделиться

Я опаздываю поздно для встречи, но несколько быстрых моментов ...

Прилипать к коду разветвлению использования только одной зависимости, есть две ветви для предложения:

  • применение практики DDD, вы бы Не иметь порядковогоссора с зависимостью на IorderValidator. Вместо этого вы бы сделали обязательство по заказу () за его собственную проверку. Или, придерживайтесь своего iOnderValidator, но имейте свою зависимость в руководстве (), которая реализована - поскольку она вернет любые коды ошибок.
  • Убедитесь, что вводят впрыскивание зависимостей, построенные с использованием синглтонного подхода (и сконфигурированного как синглтон в использовании IOC контейнера). Это решает любую проблему памяти.

Как и кто-то еще, который здесь упомянул здесь, точка состоит в том, чтобы нарушить зависимость от конкретных классов и свободно пару зависимостей, использующих инъекцию зависимости с использованием некоторого контейнера IOC.

Это делает будущий рефакторинг и обмениваться устаревшим кодом гораздо проще в большом масштабе путем ограничения технического долга в будущем. После того, как у вас есть проект возле 500 000 строк кода, с тестами на 3000 единиц, вы узнаете из первых рук, почему IOC так важен.

1
ответ дан 3 December 2019 в 17:20
поделиться
Другие вопросы по тегам:

Похожие вопросы: