我有一个负责发送电子邮件的对象,因此我创建了一个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设计原则的商业责任,因为我现在说:“你必须尝试发送电子邮件,你也要负责用于初始化和填充诊断数据“
也许责任不是正确的词,但是一种模式比另一种更好?
答案 0 :(得分:2)
您没有违反单一责任原则 - SRP并不意味着对象不应该知道如何与其合作者交谈。这是合同的一部分,这是一项自然的责任。如果EmailSender
不负责报告有关邮件传递的诊断信息,那么会是谁?
您唯一需要确保的是Diagnostics
与EmailSender
保持相关的粒度级别。 EmailSender
不依赖于其消费者,消费者依赖于EmailSender
,因此EmailSender
不应采用消费者的形式主义,而应强加其自身的语义。
答案 1 :(得分:1)
您没有违反任何SOLID原则,违反了所谓的Samurai Principle:
每个操作都应该完成合同并返回有效结果,或者抛出异常。
如果要提供有关失败的其他诊断信息,请改为添加自定义异常。如果您拥有的是您和客户之间合同的一部分,那么您可以通过输出参数返回此信息。
答案 2 :(得分:0)
看看你的代码示例,我想知道AOP设计是否合适。您可以使用Policy Injection来包含对EmailSender(和其他组件)的调用。
使用Policy Injection注入调用的包装器可以负责捕获和记录抛出的异常,因此调用SendEmail
的代码不必执行此操作。
包装器也可以负责监视时间,编写跟踪信息等等。我只是在推测,但也许这类信息与您使用Diagnostics
属性的内容排列在一起。
这样,调用者不必负责处理/记录异常,也不必负责处理诊断信息。此外,EmailSender无需负责监控自身的性能或通过Diagnostics
属性公开该信息。
此外,CurrentError
属性似乎很奇怪。您已经捕获了异常,因此看起来捕获包含CurrentError
属性所具有的任何信息的特定类型的异常似乎更合适。