异常处理:在参数验证时你会有多细微? [英] Exception handling: how granular would you go when it comes to argument validation?

查看:210
本文介绍了异常处理:在参数验证时你会有多细微?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用单一方法编写一个简单的小类来发送电子邮件。我的目标是在遗留的Visual Basic 6项目中实现它,通过COM Interop工具将其显示为COM对象。



有一个细节我发现很难解决,我应该如何精细地验证参数。在这个光线上,我真的不高兴,而且根本不是一个细节,是我实际处理例外的方式:

  public class MyMailerClass 
{
#region创建
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
{
抛出新的ApplicationException(无效的邮件格式);
}
}
#endregion创建

#region验证
私有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验证
}

任何的建议将不胜感激,所以非常感谢您的所有评论!



注意:实施企业库的验证应用程序块在这个特定情况下

解决方案

考虑您对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


I'm coding a simple little class with a single method send an email. My goal is to implement it in a legacy Visual Basic 6 project, exposing it as a COM object via the COM Interop facility.

There's a detail I'm finding difficult to resolve, that being how granular should I be at validating parameters. On that light, a thing I'm really not happy about, and which is not a detail at all, is the way I'm actually handling exceptions:

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
}

Any suggestion will be much appreciated, so thanks much in advance for all your comments!

Note: Would it be convenient to implement Enterprise Library's Validation Application Block on this particular case?

解决方案

Consider the contract that you are imposing upon the callers of SendMail. They are required to pass you a "valid email address". Who decides what is valid? SendMail does. Basically your method is "high maintenance" -- it wants things exactly the way it likes, and the only way to tell whether what you're going to give it will be satisfactory is to try and hope for the best.

Don't write high-maintenance methods without giving the caller a chance to know how to satisfy it, or at least have a way to avoid the exception. Extract the validation logic to an "IsValidAddress" method that returns a Boolean. Then have your SendMail method call IsValidAddress and throw if it is invalid.

You get several nice effects from this change:

(1) Increased separation of concerns. SendMail's job is to make the email mechanism work, not to pass judgment on whether an email address is valid. Isolate that policy decision to code that specializes in verification.

(2) Address validation is a useful tool in of itself; there are lots of times when you want to know whether an address is well-formed without sending mail to it.

(3) You can update and improve your validation logic easily because it is all in one sensible place.

(4) Callers have a way that they can guarantee that no exception will be thrown. If a caller cannot call a method without guaranteeing that the arguments are valid, then they have to catch the exception. Ideally you should never make a caller have to handle an exception to make their code correct; there should be a way they can write correct code that never throws, even if the data they've been handed is bad.

Here are a couple of articles I've written on this subject that you might find helpful:

Exception handling: http://ericlippert.com/2008/09/10/vexing-exceptions/

High-maintenance methods: http://blogs.msdn.com/ericlippert/archive/2008/09/08/high-maintenance.aspx

这篇关于异常处理:在参数验证时你会有多细微?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆