做一些研究,似乎人们普遍认为公共方法的论据应该得到验证,而私人职能通常不会。这让我有些疑问,但到目前为止我还没有找到满意的答案。
示例:
public void DoSomething(int i)
{
if (i < 0)
throw new ArgumentOutOfRangeException("i");
double d = DoWork(i);
}
private double DoWork(int i)
{
double ret = ...; // some calculation
return ret;
}
思想:
如果i
内的DoWork()
要求为非负变化怎么办?设计风险留下过时的验证检查。我知道,程序员负责调整已更改的函数的使用情况,但这让我想知道是否有更好的方法可以将错误风险降至最低。
对来自DoWork()
的{{1}}的不同来电怎么样?我们必须冗余地验证这些论点吗?
的
DoSomething()
通过将支票放入自己的功能中,可以稍微清理一下。然后,调用public void DoSomething(int i)
{
if (i < 0)
throw new ArgumentOutOfRangeException("i");
double d = DoWork(i);
}
public void DoSomethingElse()
{
int i = 5;
if (i < 0)
throw new ArgumentOutOfRangeException("i");
double d = DoWork(i);
}
private double DoWork(int i)
{
double ret = ...; // some calculation
return ret;
}
的新功能可能会忘记验证DoWork(int i)
。
i
这一点比这更好吗?
public void DoSomething(int i)
{
ThrowIfIntegerIsNegative(i);
double d = DoWork(i);
}
public void DoSomethingElse()
{
int i = 5;
ThrowIfIntegerIsNegative(i);
double d = DoWork(i);
}
static void ThrowIfIntegerIsNegative(int i)
{
if (i < 0)
throw new ArgumentOutOfRangeException("i");
}
private double DoWork(int i)
{
double ret = ...; // some calculation
return ret;
}
根据具体情况,这些是我想要同时实现的目标:
你如何取得平衡?哪种方法最适合您?我非常感谢任何见解。
答案 0 :(得分:9)
在公共方法中验证参数而不在私有方法中验证参数的逻辑大致如下:
- 使用无效参数调用公共方法时,控件之外的编程错误。
- 使用无效参数调用非公共方法时,控件中存在逻辑错误。
这个逻辑是合理的:没有必要浪费周期来验证模块内部生成的方法的参数。另一方面,私有方法总是可以假设它们的参数是有效的,因为你可以控制所有私有方法的调用。
然而,在违反这些假设的情况下捕捉情况是非常有益的。为此,在私有方法中使用运行时断言代替参数验证是一个非常好的主意。这会从外部调用者捕获带有异常的无效调用,并通过断言警告您使用自己的方法进行无效调用。
答案 1 :(得分:1)
我喜欢在公共方法中验证异常:
public void Foo(int i)
{
if (i < 0)
throw new ArgumentOutOfRangeException("i");
double d = DoWork(i);
}
我喜欢用私有方法验证Asserts:
private double DoWork(int i)
{
System.Diagnostics.Debug.Assert(i >= 0);
// ....
}
ArgumentOutOfRangeException
异常可能会使公共方法的调用者感到困惑。要做的另一件事是将任何受保护的方法视为公共方法。
修改强>
这是一个错误验证的例子,违反了上面的#3:
public void Foo(int distanceInMetres)
{
double d = DoWork(distanceInMetres * 1000);
}
private double DoWork(int distanceInMillimetres)
{
if (distanceInMillimetres < 0)
throw new ArgumentOutOfRangeException("distanceInMillimetres");
// ....
}
如果Foo
的来电者在参数“distanceInMillimetres”上看到异常,他会感到困惑,因为他打电话给“Foo”,后者拿了一个名为“distanceInMetres”的参数。
答案 2 :(得分:1)
同意有关公共方法而非公开方法的dasblinkenlight声明。
如果您练习TDD,那么您的私有方法只是重构代码并将一些公共方法提取到私有方法中的结果。因此,如果您使用测试覆盖公共方法,则会自动测试您的私有方法。
如果您不使用TDD但想要验证逻辑是否未被违反,您可以使用不同的技术,例如 - 断言(http://msdn.microsoft.com/en-us/library/ttcc4x86.aspx)或代码合同(http://msdn.microsoft.com/en-us/library/dd264808.aspx)。