2010-03-02 4 views
4

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

void Class::SetPrivateMemberA() { 
    m_A = GetObject(); 
} 

void Class::UseA() { 
    if (m_A != null) { 
     m_A.Method(); 
    } else { 
     // assert or log the error 
    } 
} 

... с этой реализации:

void Class::SetPrivateMemberA() { 
    m_A = GetObject(); 
} 

void Class::UseA() { 
    m_A.Method(); 
} 

Проблема, которую я имею в виду, что GetObject() по-прежнему возвращает объект, пустое значение Объект или иное. Мне нравится идея неоднократно не проверять значение null и доверять тому, что возвращаемый объект можно использовать, но почему бы мне просто не сделать это в первой реализации?

Является ли преимущество шаблона Null Object незначительным увеличением доверия для очистки кода? Что касается второй реализации, разве не все-таки хорошая практика проверить, что она не является нулевой до вызова A.Method()?

ответ

4

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

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

Это также иллюстрируется пустыми классами контейнеров, которые по существу представляют собой шаблон нулевого объекта: вместо возврата нулевого контейнера из запроса вы просто возвращаете пустой контейнер. Для таких вещей, как итерация через все записи контейнера, часто не имеет значения, пуст он или нет, поэтому избавление от необходимости нулевой проверки делает код более удобным для обслуживания/более читаемым. Однако, если вы хотите заполнить представление своего набора данных, вам все равно нужно явно показывать разные «Нет записей». который проверяет пустой контейнер.

Редактировать для ясности

одна проблема смотрит только на него с сайта вызова. Как и большинство шаблонов проектирования, это должно охватывать обе стороны, которые должны быть полностью использованы. Рассмотрим:

public PossiblyNull GetSomethingNull() 
{ 
    if (someBadSituation()) 
     return null; 
    else 
     return SomehowProduceSomething(); 
} 

против

public PossiblyEmpty GetSomethingEmpty() 
{ 
    if (someBadSituation()) 
     return StaticEmptySomething(); 
    else 
     return ProdueSomethingYay(); 
} 

Теперь, ваш код вызова, вместо того, чтобы смотреть как

public void DoSomethingWithChild(Foo foo) 
{ 
    if (foo != null) 
    { 
     PossiblyNull bar = foo.GetSomething(); 
     if (bar != null) 
      bar.DoSomething(); 
    } 
} 

может быть

public void DoSomethingWithChild(Foo foo) 
{ 
    if (foo != null) 
     foo.GetSomething().DoSomething(); 
} 
+0

Я согласен с вашими комментариями и Карлом внизу. Он считает, что это чересчур параноидально, усложняет код, замедляет просмотры кода и т. Д. Проблема заключается в защите аргумента «что-если»: «Что, если« что-то »происходит в производстве, и мы сбой, потому что мы не проверяли значение null ? Как бы вы отреагировали на это? – TERACytE

+0

@TERACyTE: Ну, добавление ветвей кода для нулевых состояний, когда они не нужны, также добавляет сложности, которые сложнее поддерживать. Идея не-check-for-null довольно раздельна из шаблона нулевого объекта, который предполагает использование null в качестве регулярного расширения, и рассматривает его скорее как исключительный случай. – Tanzelax

+0

(редактируется сообщение с примером). Идея здесь состоит в том, что если все еще может быть нулевым, вы все же необходимо проверить наличие нулей. Однако, беря возможные ** источники ** этих нулей, вы делаете ветви кода более удобными. – Tanzelax

0

Со вторым реали что это Не все-таки хорошая практика, чтобы проверить , что это не null перед вызовом A.Method()?

№ Если вы знаете, что m_A не является нулевым, тогда проверка является излишней; это пример параноидального кодирования. Какой вред он делает?Это усложняет ваш код - излишне; это затрудняет чтение, сложнее отлаживать.

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