我听说建议您验证公共方法的参数:
- 如果他不期望为空,是否应该检查为空?
- 方法是否应验证其参数?
- MSDN-CA1062:验证公共方法的参数(我具有.NET背景,但问题不是特定于C#的)
动机是可以理解的。如果将以错误的方式使用模块,则我们希望立即引发异常,而不是任何不可预测的行为。
令我困扰的是,错误的参数并不是使用模块时唯一的错误。这是一些错误情况,如果我们遵循建议并且不希望错误升级,则需要添加检查逻辑:
- 来电-意外参数
- 来电-模块处于错误状态
- 外部通话-返回意外结果
- 外部调用-意外的副作用(两次进入调用模块,破坏了其他依赖状态)
我试图考虑所有这些情况,并用一种方法(对不起,不是C#的人)编写一个简单的模块:
public sealed class Room
{
private readonly IDoorFactory _doorFactory;
private bool _entered;
private IDoor _door;
public Room(IDoorFactory doorFactory)
{
if (doorFactory == null)
throw new ArgumentNullException("doorFactory");
_doorFactory = doorFactory;
}
public void Open()
{
if (_door != null)
throw new InvalidOperationException("Room is already opened");
if (_entered)
throw new InvalidOperationException("Double entry is not allowed");
_entered = true;
_door = _doorFactory.Create();
if (_door == null)
throw new IncompatibleDependencyException("doorFactory");
_door.Open();
_entered = false;
}
}
现在很安全=)
这很令人毛骨悚然。但是,请想象一下,在具有数十种方法,复杂状态和大量外部调用(嗨,依赖注入爱好者!)的真实模块中,它有多令人毛骨悚然。请注意,如果您正在调用一个可以覆盖其行为的模块(C#中的非密封类),则您在进行外部调用,并且后果在调用者的范围内是不可预测的。
总结一下,正确的方法是什么?为什么?如果您可以从以下选项中选择,请回答其他问题。
检查整个模块的使用情况。我们需要单元测试吗?有这种代码的例子吗?是否应该限制依赖项注入的使用(因为它将导致更多的检查逻辑)?将这些检查移至调试时是否可行(发行版中不包括)?
仅检查参数。根据我的经验,参数检查(尤其是null检查)是最无效的检查,因为参数错误很少会导致复杂的错误和错误升级。大多数情况下,您会NullReferenceException
在下一行得到一个。那么,为什么参数检查是如此特别?
不要检查模块的使用情况。这是非常不受欢迎的意见,您能解释为什么吗?