4

我正在重构一个大类,该类在各处都对 null 进行了大量检查,以使用 null 对象模式。到目前为止,这几乎是一个平稳的变化,但我对最终结果有几个问题,我想知道是否有更好或不同的方法,甚至回到原来的方式。

最大的问题是我有以下代码:

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

如您所见,我可能会从此条件中删除空检查,但我有一个布尔属性,如果设置为默认值,它将执行一段代码。如果我总是返回 true,我可能会引入一些难以发现和消除的细微错误。

另一个问题是我不得不像这样从 null 修改检查:

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

DoSomething();

这简直丑陋,因为现在我必须检查类型,而不是只检查 null。这种情况在类中发生了 3 次,因为我没有返回对象的属性之一或执行其方法之一,我必须进行此检查。

最后,该对象有几个不可为空的 DateTime 属性,架构师不希望它们可以为空。同样,通过将 MinDate 值设为默认值,一些讨厌的错误可能会爬入代码中。

所以你有它。这是一个空对象模式比散落在各处的意大利面条空检查更糟糕的情况吗?有没有更好的方法来实现这一点?

感谢您的回答。

4

4 回答 4

1

重构代码会更好吗?这DoSomething()是 Null Object 上的方法并简单地实现为无操作?Null Object 的另一种替代方法是Maybe<T>. 它使空检查更具可读性并且调用代码更安全。

于 2011-08-30T21:54:11.413 回答
0

你应该看看Code Contracts。这是一种在方法上强制执行前置条件和后置条件的优雅方式,以避免您所指的各种问题。它通过在运行时合约被破坏时尽早引发异常,或者在某些情况下通过静态分析(Microsoft 框架)来实现这一点。

我更喜欢CutEdge Condtions,它不支持静态分析,但它有一个很好的流畅的界面,比微软的同类产品更直观。

它允许您编写这样的代码,甚至可以扩展接口:

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

       ...
   }
}

您将对输入到系统的所有数据(即所有公共方法)实施条件,并防止开发人员编写违反此规则的代码。当它由于错误而发生时,异常和堆栈跟踪会准确地告诉您问题出在哪里。

还有一些方法可以设置监视属性的条件,以确保某些条件永远不会通过不变量出现。这可以作为一个反腐败层,再次捕获错误,并阻止开发人员编写破坏系统的代码。

于 2011-08-30T21:50:01.553 回答
0

您可以在接口 IMyObject 中添加一个布尔 IsNull (IsEmpty) 属性,然后实现为该属性返回 true 的 MyNullObject。显然你必须相信在其他情况下这应该返回 false,否则你会有错误的行为。

于 2011-08-30T21:52:50.447 回答
0

Null Object 模式是一种折衷方案——您可以通过消除 null 检查获得收益,但需要支付另一个类来维护。

我建议向IsNull您的接口/基类添加一个布尔属性。

正常的实现返回false;你的空对象返回true

这使您可以避免针对确切类型的测试,并且更清楚您的意图。您还可以将其用作处理日期的代码中的测试,从而允许您保留不可为空的日期属性。

于 2011-08-30T21:55:39.963 回答