我多年来一直忽略了“告诉,不要问”OOP原则,因为我刚刚在几天前第一次了解它。
但是上下文是关于验证代码的讨论,该代码已经从ASP.NET Web表单页面转移到数据/业务对象中,并且没有“Validate()”方法,只是一个自身的save方法做了验证,并且(据说)提出了例外。我问为什么这是以这种方式设计的,我被引导到OOP的“告诉,不要问”原则,这是我从未听说过的,所以我们一起看了谷歌,我立即接受了教育。 ;)
然而,有些东西闻不到,不应该在将数据从用户传递到处理和/或收集的业务层之前清除数据,而不是反过来?我对如何做好设计感到困惑。
似乎“告诉,不要问”的规则与你不应该向目标对象询问目标对象的状态的想法有关,并且该原则从未真正意味着应用于数据将传递给目标对象。
答案 0 :(得分:3)
我觉得这听起来像是一堆“最佳实践”和“设计方法”出错了,但现在对我来说有点意义了。以这种方式看待它:
想象一下将验证放在业务对象中,但是在表示层中“如果验证失败了我该怎么办。这将允许多个不同的表示层重用相同的验证逻辑,但处理错误的方式不同。”
public Foo { Validate(Baz bar) { if(!is_number(bar)) throw numberexception(); } AssignBar(Baz bar) { Validate(bar); } } //... try { foo.AssignBar(bar); } catch(numberexception e) { alert('Not a number!'); }
n.b。你可以争论所有关于抛出异常的想法,这只是一个例子。返回状态,bools,无论你想要什么。
答案 1 :(得分:2)
我同意AviewAview,但只会在用户告知(而不是他要求)时抛出异常:
public Foo
{
bool Validate(Baz bar)
{
if(!is_number(bar)) return false;
return true;
}
AssignBar(Baz bar)
{
if (!Validate(bar)) throw numberexception();
}
}
推荐:
try
{
foo.AssignBar(bar);
}
catch(numberexception e)
{
alert('Not a number!');
}
问:
if (foo.Validate(bar)
{
foo.AssignBar(bar);
}
else
{
alert('Not a number!');
}
所以AssignBar需要一个VALID栏并且如果不是则抛出异常,但是我们还提供了一个Validate方法,它不会抛出异常。
答案 2 :(得分:0)
我想知道这是否更像是“关注点分离”而不是“告诉不要问”。谁负责验证数据?可以说,这是坚持它的责任。
当然,有时验证多层数据非常有用。如果你的应用程序是这种情况,我在“用户”层中公开验证逻辑没有问题。但我仍然希望它在业务层。