Подтвердить что ты не робот

Вложенные Try/Catch

Имеет ли вложенный Try/Catch сигнал, что вы не кодируете чисто? Интересно, потому что в моем уловке я вызываю другой метод, и если это не удается, я получаю еще одну ошибку времени выполнения, поэтому у меня возникает соблазн обернуть эти вызовы в catch с помощью другого try/catch. Интересно, нормально ли это делать?

например.

    catch (Exception ex)
    {
        transaction.VoidOrder(transactionID);

        LogError(ex.ToString());
        Response.Redirect("Checkout", false);
    }

поэтому методы VoidOrder или даже LogError могли бы выскочить. Прямо сейчас, когда я вызываю VoidOrder, я получаю null ref на transactionID, потому что он вызывает метод BL и в этом методе BL, который я перебрасываю, чтобы я мог поймать его на этом более высоком уровне в коде выше. Но если я снова бросаюсь в ловушку, мне тоже нужно поймать это.

4b9b3361

Ответ 1

Вот как мы подходим к проблеме:

Все вызовы с уровня UI/codebehind на другие уровни используют try-catch, где мы всегда получаем пользовательское исключение. Все действия, выполняемые лежащими в основе слоями, имеют свой собственный try-catch, который регистрирует, переносит и генерирует настраиваемое исключение. Пользовательский интерфейс затем может полагаться на это и искать обработанные исключения с дружественными сообщениями об ошибках.

Codebehind:

protected void btnSubmit_Click(object sender, EventArgs e)
{
    //do something when a button is clicked...
    try
    {
        MyBL.TakeAction()
    }
    catch(MyApplicationCustomException ex)
    {
        //display something to the user, etc.
        ltlErrorPane.Text = ex.Message;

        //or redirect if desired
        if(ex.ErrorType == MyCustomErrorsType.Transactional)
        {
            Response.Redirect("~/Errors/Transaction.aspx");
        }
    }
}

BL:

На бизнес-уровне любые операции, которые могут не использовать try-catch, которые регистрируют и обертывают проблему, прежде чем бросать ее в пользовательский интерфейс.

public class MyBL
{
    public static void TakeAction()
    {
        try
        {
            //do something
        }
        catch(SpecificDotNetException ex)
        {
            //log, wrap and throw
            MyExceptionManagement.LogException(ex)
            throw new MyApplicationCustomException(ex, "Some friendly error message", MyCustomErrorsType.Transactional);
        }
        finally
        {
            //clean up...
        }
    }
}

Обработчик исключений:

Фактический обработчик исключений имеет несколько способов ведения журнала, включая журнал событий, журнал файлов и последний email, если все остальное не работает. Мы выбираем простой возврат false, если регистратор не может выполнять какие-либо ожидаемые действия. ИМО это личный выбор. Мы полагаем, что вероятность того, что три метода не удастся подряд (журнал событий не удался, попробуйте файл журнала, не удается, попробуйте электронную почту, не удается) очень маловероятен. В этом случае мы решили разрешить приложению продолжать. Другой вариант - разрешить полностью сбой приложения.

public static class MyExceptionManagement
{
    public static bool LogException(Exception ex)
    {
        try
        {
            //try logging to a log source by priority, 
            //if it fails with all sources, return false as a last resort
            //we choose not to let logging issues interfere with user experience

            //if logging worked
            return true;
        }
        catch(Exception ex)
        {
            //in most cases, using try-catch as a true-false is bad practice
            //but when logging an exception causes an exception itself, we do
            //use this as a well-considered choice.
            return false;
        }
    }
}

Наконец, как отказоустойчивый, мы реализуем глобальный обработчик событий Application_ErrorGlobal.asax). Это последнее средство для случаев, когда мы неправильно пытались что-то поймать. Обычно мы регистрируем и перенаправляем на страницу с дружественной ошибкой. Если вышеупомянутая пользовательская обработка ошибок выполнена успешно, очень мало ошибок приведет к глобальному обработчику.

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

Ответ 2

Вложенные блоки try/catch неизбежны в приложениях верхнего уровня, которые должны регистрировать, отправлять сообщения или реагировать на исключения другими нетривиальными способами.

Есть способы сократить количество вложенных блоков (например, консолидировать обработку ошибок с помощью обработчика ASP.NET HttpApplication.Error (aka Application_Error)), но вы должны поймать любые исключения, созданные вашим кодом обработки и реализовать план резервного копирования в случае неудачи остальных.

Ответ 3

Еще одно решение вашей проблемы с вложением - это инкапсулировать логику try/catch для внутренних функций (LogError и т.д.) в этих функциях вместо того, чтобы зависать от вызывающего, чтобы их поймать. Для LogError это имеет смысл, потому что вы, вероятно, захотите обработать сломанный регистратор ошибок одинаково, независимо от того, кто пытается зарегистрировать ошибку.

Ответ 4

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

Метод getControl не должен вставлять в него script, ни метод сохранения не должен делать больше, чем сохранять.

Изучите, что именно должны делать эти методы, и вы получите ответ. Это не выглядит так неудобно, чтобы обнулить порядок в случае ошибки. Звучит разумно.

Ответ 5

Вы думали об использовании объекта TransactionScope вместо того, чтобы пытаться отменить транзакцию вручную? Я знаю, что иногда это невозможно, но большую часть времени для меня TransactionScope работал. Таким образом, мне не нужно было вручную управлять элементами отката - вручную ручные откаты могут быть проблемой, потому что данные являются добрыми в "нестабильном" состоянии, что может испортить всю вашу логику.