在有状态对象的方法中添加参数添加职责吗?

时间:2012-11-29 21:08:37

标签: c# design-patterns solid-principles

我有一个负责发送电子邮件的对象,因此我创建了一个EmailSender,然后告诉SendEmail,传递了一些EmailDetails

string diagnostics;    

EmailSender sender = new EmailSender();
try
{
    sender.SendEmail(details);
    //sender.SendEmail(details, out diagnostics);
}
catch(Exception e)
{
    logger.log(sender.CurrentError);
}

diagnostics = sender.Diagnostics;

如果我向SendEmail添加一个out参数,那么这是否会增加SOLID设计原则的商业责任,因为我现在说:“你必须尝试发送电子邮件,你也要负责用于初始化和填充诊断数据“

也许责任不是正确的词,但是一种模式比另一种更好?

3 个答案:

答案 0 :(得分:2)

您没有违反单一责任原则 - SRP并不意味着对象不应该知道如何与其合作者交谈。这是合同的一部分,这是一项自然的责任。如果EmailSender不负责报告有关邮件传递的诊断信息,那么会是谁?

您唯一需要确保的是DiagnosticsEmailSender保持相关的粒度级别。 EmailSender不依赖于其消费者,消费者依赖于EmailSender,因此EmailSender不应采用消费者的形式主义,而应强加其自身的语义。

答案 1 :(得分:1)

您没有违反任何SOLID原则,违反了所谓的Samurai Principle

  

每个操作都应该完成合同并返回有效结果,或者抛出异常。

如果要提供有关失败的其他诊断信息,请改为添加自定义异常。如果您拥有的是您和客户之间合同的一部分,那么您可以通过输出参数返回此信息。

答案 2 :(得分:0)

看看你的代码示例,我想知道AOP设计是否合适。您可以使用Policy Injection来包含对EmailSender(和其他组件)的调用。

使用Policy Injection注入调用的包装器可以负责捕获和记录抛出的异常,因此调用SendEmail的代码不必执行此操作。

包装器也可以负责监视时间,编写跟踪信息等等。我只是在推测,但也许这类信息与您使用Diagnostics属性的内容排列在一起。

这样,调用者不必负责处理/记录异常,也不必负责处理诊断信息。此外,EmailSender无需负责监控自身的性能或通过Diagnostics属性公开该信息。

此外,CurrentError属性似乎很奇怪。您已经捕获了异常,因此看起来捕获包含CurrentError属性所具有的任何信息的特定类型的异常似乎更合适。