Предложение Guard и Null Object Pattern в внедрении зависимостей и C#
Используя Constructor Injection, зависимость вводится для потребителя следующим образом (по крайней мере, я надеюсь, что я правильно понял):
public class SomeConsumer
{
private IDependency someDependency;
public SomeConsumer(IDependency someDependency)
{
if (someDependency != null)
{
this.someDependency = someDependency;
}
else
{
throw new ArgumentNullException("someDependency");
}
}
public void Baz()
{
someDependency.DoSomething();
}
(...)
}
Если бы я использовал шаблон пустых объектов для IDependency, нужно ли мне выражение guard? Или неправильно вводить нулевой объект?
ОБНОВЛЕНИЕ: чтобы уточнить, давайте предположим, что у меня есть классы и интерфейсы, подобные этому:
public interface IDependency
{
void DoSomething();
}
public class NullDependency : IDependency
{
public void DoSomething()
{
//Do nothing...
}
}
public class RealDependency : IDependency
{
public void DoSomething()
{
Console.WriteLine("Did something");
}
}
public class Foo
{
public void Bar()
{
IDependency dependency = new NullDependency();
SomeConsumer sc = new SomeConsumer(dependency);
sc.Baz();
}
}
Могу ли я затем безопасно удалить пункт охраны из SomeConsumer, чтобы он выглядел следующим образом:
public class SomeConsumer
{
private IDependency someDependency;
public SomeConsumer(IDependency someDependency)
{
this.someDependency = someDependency;
}
public void Baz()
{
//if someDependency is a NullDependency, this does nothing
someDependency.DoSomething();
}
(...)
}
Или я должен использовать пункт охраны, потому что я не могу быть уверен, что null
никогда не будет введен?
3 ответа
ИМХО, я бы отказался от пункта охраны при следующих обстоятельствах:
SomeConsumer
используется только внутри вашего продукта- Нулевой объектный шаблон полностью поддерживается вашей командой и / или конфигурацией контейнера внедрения зависимостей
Я бы, вероятно, не отказался от оговорки об охране, если:
- потребность в нулевом объекте недостаточно задокументирована для целевой аудитории
SomeConsumer
является частью открытого API, который используется разработчиками, которые не знают о шаблоне нулевого объекта- Я хотел бы получить обратную связь от моего контейнера ввода зависимостей к моменту его создания
SomeConsumer
, что я ошибся
Я не люблю отказываться от пунктов охраны ни при каких обстоятельствах. Кто бы ни использовал этот класс, все созданные объекты должны быть действительными. Если вы разрешаете вводить null через конструктор, вы разрешаете создание недопустимого объекта. Позже что-то сломается при вызове метода.
Вопрос не в том, является ли этот класс внутренним или нет. Вопрос заключается в том, убедитесь ли вы, что во всех местах все меры принимаются для получения ненулевого значения при вызове конструктора? Даже если ваш ответ "да", следующий вопрос - зачем вам тратить время и энергию на проверку этого?
Просто оставьте пункт охраны, и вы будете знать, что все объекты этого класса будут построены правильно. В противном случае, если вы случайно передадите null конструктору, произойдет сбой какого-либо совершенно несвязанного класса, и вам будет сложно отследить ошибку до этого конструктора.
С другой стороны, некоторые защитные предложения (те, которые проверяют условия, отличные от нуля) часто являются причиной для пересмотра дизайна. Вы можете найти эту статью интересной - Зачем нам нужны пункты охраны?
ИМХО, это совершенно нормально, чтобы ввести нулевой объект, это часто используется в тестировании. Я часто внедряю макеты с поведением по умолчанию в своих модульных тестах, когда меня не волнует эта зависимость.
Я бы наверное заменил null
проверьте с выбрасыванием исключения или удалите его вообще. В настоящее время он ничего не делает, так как значение по умолчанию someDependency
переменная null
тем не мение.