Рефакторинг - нарушение зависимостей - PullRequest
0 голосов
/ 05 октября 2018

В настоящее время я работаю над Racing-Car-Katas .Цель состоит в том, чтобы реорганизовать персик кода, чтобы он следовал твердым принципам.

Я пытаюсь добавить Принцип инверсии зависимостей .Где я могу передать зависимость через конструктор.

Исходная ситуация

Инсайд класса Alarm - это зависимость Sensor, которая генерирует psiPressureValue.

public class Alarm {
    Sensor sensor = new Sensor();

    public void check()
    {
        double psiPressureValue = sensor.popNextPressurePsiValue();
        /* ... */
    }
}

Идея

public class Alarm {
    Sensor sensor;

    public Alarm() {
        this.sensor = new Sensor();
    }

    public Alarm(ISensor sensor) {
        this.sensor = sensor;
    }

    public void check()
    {
        double psiPressureValue = sensor.popNextPressurePsiValue();
        /* ... */
    }
}

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

public Alarm() {
    this.sensor = new Sensor();
}

Но мое внутреннее чувство говорит, что это запах кода ..

Как обрабатывать такие зависимости в реальных приложениях?

Ответы [ 3 ]

0 голосов
/ 06 октября 2018

Принцип инверсии зависимости (DIP) гласит:

Модули высокого уровня не должны зависеть от модулей низкого уровня.

Но при определении конструктора по умолчанию, которыйсоздает реализацию Sensor, однако вы нарушаете DIP, потому что Sensor является модулем низкого уровня, и Alarm (ваш модуль высокого уровня) зависит от него:

public Alarm() {
    this.sensor = new Sensor();
}

Еслинеобходимо позволить модулю высокого уровня зависеть от абстракции (как показывает ваш дополнительный конструктор), нет необходимости добавлять конструктор по умолчанию.Это приводит только к зависимости от модуля низкого уровня.Поскольку и ваше конечное приложение, и ваши тесты должны использовать перегруженный конструктор, конструктор по умолчанию не имеет смысла и вызывает только тесную связь и, следовательно, нарушение DIP.

Это не теоретическое упражнение.DIP следует соблюдать в реальных приложениях.Хорошо разработанное реальное приложение применяет принципы SOLID и использует Dependency Injection как способ достижения слабой связи и DIP.Это разъединяет модули и позволяет составлять полные графы объектов в Composition Root .

0 голосов
/ 06 октября 2018

Чтобы не нарушать никакой зависимости между Alarm и Sensor, вам необходимо:

  1. Использовать все методы Sensor, которые используются Alarm;
  2. Поместите их в один (или более) интерфейс (ы);и затем
  3. Имейте Sensor для реализации этих интерфейсов.

Второй подход конструктора не является правильным способом защиты зависимостей.Он нарушает DIP, создавая объект класса Sensor.

Вместо этого добавьте код проверки к другому конструктору и убедитесь, что Alarm всегда использует действительный Sensor через ISensor (а не создавать экземпляр Sensor напрямую).

0 голосов
/ 06 октября 2018

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

В ваших предложенных решениях показаны два конструктора, один из которых вводит объект датчика (созданный извне), а другой - создание объекта датчика напрямую.Вы должны сбросить:

public Alarm() {
    this.sensor = new Sensor();
} 

, потому что это не нужно и потому, что оно продлевает ту жесткую связь, которую вы пытаетесь избежать с помощью SOLID.Делая это, вы не нарушаете зависимость.

В общем, наиболее распространенные варианты создания зависимостей:Зависимые объекты создаются:

1) Непосредственно клиентским объектом (тесная связь)

2) Косвенным образом клиент использует фабричные методы клиента

3) Косвенным образом Клиент использует Abstract Factory объект, введенный в Клиент (фабричный ввод - DI).Вы можете вводить различные фабрики.

4) Внешне вручную и вводить в клиент (DI)

5) Внешне через контейнер DI и вводить в клиент (DI)

Ключевым моментом DI является то, что Клиент не контролирует, как создаются его иждивенцы.Это объясняет термин " инверсия управления ".

Однако клиент сохраняет управление с помощью " Factory Method ", " Abstract Factory «.

Контейнеры DI стали в последние годы чрезвычайно популярными, особенно в современных каркасах.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...