2009-02-18 93 views
5

这些年来,我总是忽略了“告诉,不要问”OOP原则,因为我几天前第一次了解到它。“告诉,不问”适用于用户输入验证吗?

但是上下文是关于验证代码的讨论,这些验证代码已经从ASP.NET Web窗体页面移出到数据/业务对象中,并且没有“Validate()”方法,只是一种保存方法本身做了验证和(据说)提出了一个例外。我问这是为什么这样设计的,我被引导到OOP的“告诉,不要问”的原理,这是我从来没有听说过的,所以我们一起看了谷歌,我立即受到了教育。 ;)

尽管如此,某些东西并没有正确的味道,但不应该在数据从用户手中转移出去并进入处理和/或收集的业务层之前进行清理,而不是反过来?我很困惑这是如何为优秀的设计做出的。

似乎“告诉,不要问”的规则属于这样的想法,即您不应该向目标对象询问目标对象的状态,并且该原则从未真正意图应用于数据正在通过的目标对象。

回答

2

我AviewAview同意,但是woul如果用户告诉ð只抛出异常(如果没有他问):

public Foo 
{ 
    bool Validate(Baz bar) 
    { 
     if(!is_number(bar)) return false; 
     return true; 
    } 

    AssignBar(Baz bar) 
    { 
     if (!Validate(bar)) throw numberexception(); 
    } 
} 

TELL:

try 
{ 
    foo.AssignBar(bar); 
} 
catch(numberexception e) 
{ 
    alert('Not a number!'); 
} 

问:

if (foo.Validate(bar) 
{ 
    foo.AssignBar(bar); 
} 
else 
{ 
    alert('Not a number!'); 
} 

所以AssignBar需要一个有效的酒吧和抛出一个异常如果不是,但我们也提供了一个方法来验证哪些不会抛出异常。

+3

例外情况可用于处理意外情况(内存不足/磁盘已满/连接已关闭/分布式事务失败) - 验证用户提交的数据并非意外。使用“处理程序”方法 - 只需调用validate_number(invalid_handler_callback) – 2011-04-03 23:08:33

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!'); 
} 

NB,你可以说你想了解抛出异常,它的意思,例如,返回美国,布尔变量,任何你想要的。

0

我不知道这是否是“分离问题”而不是“告诉别人问题”的问题。它是谁的责任来验证数据?可以说,这是坚持它的责任。

当然,有时验证多个图层中的数据是有用的。如果您的应用程序属于这种情况,那么在“用户”图层中公开验证逻辑没有问题。但我仍然希望它在业务层。