Null проверка шаблона нулевого объекта - PullRequest
4 голосов
/ 03 марта 2010

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

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 и полагать, что отправленный обратно объект можно использовать, но почему бы мне просто не сделать это в первой реализации?

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

Ответы [ 2 ]

4 голосов
/ 03 марта 2010

Вы правы, если вы уверены, что никогда не возвращаете нули, просто пропустите проверку на ноль перед вызовом метода в первой реализации. Аналогичным образом, если вам нужно сделать что-то особенное в случае, если 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 голосов
/ 03 марта 2010

Со второй реализацией не все еще хорошая практика для проверки что это не нуль перед вызовом A.Method ()

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

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