Попытка рефакторинга в шаблон объекта Null, но конечный результат кажется хуже - PullRequest
4 голосов
/ 31 августа 2011

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

Самая большая проблема в том, что у меня есть следующий код:

IMyObject myObject = GetMyObject();
if(myObject != null && !myObject.BooleanProperty)
   DoSomething();

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

Другая проблема заключается в том, что мне пришлось изменить проверку с нуля следующим образом:

if(myObject.GetType() != typeof(MyNullObject))
   return false;

DoSomething();

Это просто ужасно, так как вместо проверки нуля, теперь я должен проверить тип. Такая ситуация случается в классе три раза, так как я не возвращаю одно из свойств объекта или не выполняю один из его методов, я должен выполнить эту проверку.

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

Так что у вас это есть. Является ли это случаем, когда шаблон нулевого объекта просто хуже, чем спагетти-нулевые проверки, разбросанные по всему? Есть ли лучший способ сделать это?

Спасибо за ваши ответы.

Ответы [ 4 ]

1 голос
/ 31 августа 2011

Было бы лучше реорганизовать ваш код, чтобы DoSomething() был методом для Null Object и просто реализован как no-op?Другая альтернатива нулевому объекту - Maybe<T>.Это делает нулевые проверки немного более читабельными, а вызов кода более безопасным.

0 голосов
/ 31 августа 2011

Шаблон Null Object - это компромисс - вы получаете за счет исключения проверок NULL, но платите другим классом для поддержки.

Я бы предложил добавить логическое свойство IsNull в ваш интерфейсбазовый класс.

Обычные реализации return false;ваш нулевой объект возвращает true.

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

0 голосов
/ 31 августа 2011

Вы можете добавить логическое свойство IsNull (IsEmpty) в интерфейсе IMyObject, а затем реализовать MyNullObject, который возвращает значение true для этого свойства.Очевидно, вы должны верить, что в других случаях это должно вернуть false, иначе вы будете вести себя неправильно.

0 голосов
/ 31 августа 2011

Вы должны взглянуть на Кодовые контракты .Это элегантный способ обеспечить предварительные и последующие условия для методов, чтобы избежать проблем, на которые вы ссылаетесь.Он делает это, вызывая исключения на ранней стадии, когда контракт нарушается во время выполнения, или в некоторых случаях посредством статического анализа (Microsoft Framework).

Я предпочитаю CuttingEdge Condtions , он не поддерживает статическийанализ, но он имеет хороший беглый интерфейс и более интуитивно понятен, чем эквивалент Microsoft.

Он позволяет вам писать такой код и даже расширять интерфейс:

public class MyClass
{
   public void MyMethod(string param1, int param2)
   {
       Condition.Requires(param1).IsNotNullOrWhiteSpace();
       Condition.Requires(param2).IsGreaterThan(0);

       ...
   }
}

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

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

...