异常处理:在参数验证方面你会有多精细化?

Nan*_*ada 1 c# vb6 exception-handling com-interop

我用一种方法编写一个简单的小班,发送电子邮件.我的目标是在遗留的Visual Basic 6项目中实现它,通过COM Interop工具将其公开为COM对象.

有一个细节我发现很难解决,我应该在多大程度上验证参数.从那个角度来看,我真的不高兴,而且根本不是一个细节,就是我实际处理异常的方式:

public class MyMailerClass
{
    #region Creation
    public void SendMail(string from, string subject, string to, string body)
    {
        if (this.IsValidMessage(from, subject, to, body)) // CS1501
        {
            MailMessage msg = new MailMessage();
            msg.IsBodyHtml = true;
            msg.From = new MailAddress(from);
            msg.To.Add(to);
            msg.Subject = subject;
            msg.Body = body;
            SmtpClient srv = new SmtpClient("SOME-SMTP-HOST.COM");
            srv.Send(msg);
        }
        else
        {
            throw new ApplicationException("Invalid message format.");
        }
    }
    #endregion Creation

    #region Validation
    private bool IsValidMessage(string from, string subject, string to, string body)
    {
        Regex chk = new Regex(@"(\w+@[a-zA-Z_]+?\.[a-zA-Z]{2,6})");
        if (!chk.IsMatch(from))
        {
            return false;
        }
        if (!chk.IsMatch(to))
        {
            return false;
        }
        if (!string.IsNullOrEmpty(subject))
        {
            return false;
        }
        if (!string.IsNullOrEmpty(body))
        {
            return false;
        }
        else
        {
            return true;
        }
    }
    #endregion Validation
}
Run Code Online (Sandbox Code Playgroud)

任何建议将不胜感激,所以提前感谢你的所有评论!

注意:在这种特殊情况下实施Enterprise Library的验证应用程序块是否方便?

Eri*_*ert 9

考虑一下您对SendMail的调用者施加的合同.他们必须通过"有效的电子邮件地址".谁决定什么是有效的?SendMail.基本上你的方法是"高度维护" - 它完全按照自己喜欢的方式完成所需的事情,而告诉你是否会给予它的唯一方法就是尝试并希望最好.

如果不让调用者有机会知道如何满足它,或者至少有办法避免异常,就不要编写高维护方法.将验证逻辑解压缩为返回布尔值的"IsValidAddress"方法.然后让你的SendMail方法调用IsValidAddress并抛出它无效.

你会从这个变化中得到几个不错的效果:

(1)增加了关注点的分离.SendMail的工作是使电子邮件机制工作,而不是判断电子邮件地址是否有效.将该策略决策隔离为专门用于验证的代码.

(2)地址验证本身就是一个有用的工具; 有很多次你想知道一个地址是否格式正确而没有向它发送邮件.

(3)您可以轻松更新和改进验证逻辑,因为它们都在一个合理的位置.

(4)呼叫者有一种方式可以保证不会抛出任何异常.如果调用者无法在不保证参数有效的情况下调用方法,则必须捕获异常.理想情况下,您永远不应该让调用者必须处理异常以使其代码正确; 应该有一种方法可以编写永不抛出的正确代码,即使它们已被传递的数据很糟糕.

以下是我在这个主题上撰写的一些文章,您可能会发现这些文章很有帮助:

异常处理:http://ericlippert.com/2008/09/10/vexing-exceptions/

高维护方法:http://blogs.msdn.com/ericlippert/archive/2008/09/08/high-maintenance.aspx