Избегание нарушения принципа повторной абстракции

В Injection Injection мы программируем против абстракции.

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

Mark Seeman предложил в некоторых своих сообщениях, что у нас может быть реализация Null Object Implementation для абстракций, чтобы избежать нарушения RAP (это предложение от Mark Seeman может быть моим выводом. Я ошибаюсь, чтобы процитировать Марка на этом). Мой вопрос здесь.

  • Как выполнить реализацию Null Object?
  • Можно ли нарушать RAP?

Ответ 1

Лично я считаю полезным программировать абстракцию, даже если есть только одна производственная реализация. В частности:

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

Имейте в виду, что это ложное утверждение для начала:

В Injection Dependency мы программируем против абстракции.

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

Итак, в основном:

  • Не стоит недооценивать важность "тестовых удвоений" для реализации абстракций, даже если у вас есть только одна производственная реализация.
  • Не бойтесь полагаться на конкретную реализацию, если вы действительно этого хотите, но впрыскивание этой зависимости по-прежнему чище, чем создание ее в вашем классе, где она действительно является "правильной" зависимостью.
  • Не пытайтесь вводить все - если поведение зависимости не является действительно взаимодействием, тогда вы, возможно, не захотите его вводить. Например, не начинайте вводить "поставщиков коллекций", чтобы избежать создания экземпляров List<T> - вам не нужно изолировать свой класс от поведения List<T> для целей тестирования, например.