Обработка исключений:насколько детально вы бы подходили к проверке аргументов?

StackOverflow https://stackoverflow.com/questions/1102030

Вопрос

Я пишу простой небольшой класс с одним методом отправки электронного письма.Моя цель — реализовать его в устаревшем проекте Visual Basic 6, представив его как COM-объект через средство COM Interop.

Есть деталь, которую мне трудно решить, а именно, насколько детальным мне следует быть при проверке параметров.В этом свете меня совсем не устраивает то, как я на самом деле обрабатываю исключения:

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
}

Любой предложение будет высоко оценено, поэтому Спасибо большое заранее за все ваши комментарии!

Примечание:Было бы удобно реализовать корпоративную библиотеку Блок приложения проверки в этом конкретном случае?

Это было полезно?

Решение

Рассмотрим контракт, который вы навязываете вызывающим абонентам 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

Другие советы

Имея двоих throw операторы подряд не имеют смысла - будет выполнен только первый, а затем управление будет передано обработчику исключений и никогда второму throw.

По моему мнению, этого более чем достаточно, чтобы просто сказать, как «Электронная почта отправителя недействительна». Электронная почта довольно проста и короткая, и поэтому пользователь сможет разрешить это без какого-либо дополнительного руководства.

Я тоже считаю, что лучше сначала проверить все передаваемые значения и только потом приступать к работе.Какой смысл частично выполнять работу, если потом можно встретить недопустимое значение параметра, выдать исключение и никогда не завершить эту работу.Постарайтесь указать на ошибки как можно раньше, если возможно, в самом начале.

И:

Использовать

string.IsNullOrEmpty(subject)

скорее, чем

subject == null

для проверки того, пусты ли ваши строки.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top