簡體   English   中英

錯誤處理的設計模式

[英]Design Pattern for Error Handling

我在各個項目中遇到過這個問題幾次,我想知道是否有比我通常最終使用的解決方案更好的解決方案。

假設我們有一系列需要執行的方法,並且我們想知道其中一個方法中是否出現問題並優雅地突破(可能撤消任何先前的更改......),我通常會執行以下操作(偽C#,因為這是我最熟悉的):

private bool SomeMethod()
{
    bool success = true;
    string errorMessage = null;
    success = TestPartA(ref errorMessage);
    if (success)
    {
        success = TestPartB(ref errorMessage);
    }
    if (success)
    {
        success = TestPartC(ref errorMessage);
    }
    if (success)
    {
        success = TestPartD(ref errorMessage);
    }
        //... some further tests: display the error message somehow, then:
        return success;
}

private bool TestPartA(ref string errorMessage)
{
    // Do some testing...
    if (somethingBadHappens)
    {
       errorMessage = "The error that happens";
       return false;
    }
    return true;
}

我只是想知道(這是我的問題),如果有更好的方法來應對這種事情。 我似乎最終寫了很多if語句似乎應該更流暢。

我被建議在一組委托函數上進行循環,但是我擔心這會過度設計解決方案,除非有一個干凈的方法來完成它。

我認為你應該使用例外。 請注意,通常只應在應用程序的“頂層”捕獲異常。

private void TopLevelMethod()
{
    try
    {
        SomeMethod();
    }
    catch (Exception ex)
    {
        // Log/report exception/display to user etc.
    }
}

private void SomeMethod()
{
    TestPartA();
    TestPartB();
    TestPartC();
    TestPartD();
}

private void TestPartA()
{
    // Do some testing...
    try
    {
        if (somethingBadHappens)
        {
            throw new Exception("The error that happens");
        }
    }
    catch (Exception)
    {
        // Cleanup here. If no cleanup is possible, 
        // do not catch the exception here, i.e., 
        // try...catch would not be necessary in this method.

        // Re-throw the original exception.
        throw;
    }
}

private void TestPartB()
{
    // No need for try...catch because we can't do any cleanup for this method.
    if (somethingBadHappens)
    {
        throw new Exception("The error that happens");
    }
}

我在我的例子中使用了內置的System.Exception類; 您可以創建自己的派生異常類,也可以使用從System.Exception派生的內置類。

您也許可以嘗試查看SOLID原則“打開/關閉”部分。 在您的示例中,您可以創建一個ITestRule接口,其中包含一個名為CheckRule()的方法,該方法將更新您的消息並返回一個bool 然后,您將為要測試的每個規則創建一個接口實現,並將該類添加到List<ITestRule>對象。 從上面的Redmondo示例中,我將更改為以下內容:

var discountRules =
                new List<ITestRule>
                    {
                        new TestPartA(),
                        new TestPartB(),
                        new TestPartC(),
                        new TestPartD(),
                    };

然后,您將新的List<ITestRule>傳遞給一個求值器,它將循環遍歷每個類並運行CheckRule()方法。

我試圖堅持一個稱為“快速失敗”的原則; 方法應該在它們應該發生時失敗,並立即返回錯誤的詳細信息。 然后調用方法適當地響應(將異常重新拋出給它的調用者,記錄細節,如果它是一個UI綁定方法則顯示錯誤等): -

http://en.wikipedia.org/wiki/Fail-fast

但是,這並不意味着使用異常來控制應用程序的流程。 剛養的時候,你可以對付它通常是不好的做法異常: -

http://msdn.microsoft.com/en-us/library/dd264997.aspx

在你的情況下,我會重新編寫你的代碼(例如): -

private bool SomeMethod()
{
    bool success = false;

    try
    {
        TestPartA();
        TestPartB();
        TestPartC();
        TestPartD();

        success = true;
    }
    catch (Exception ex)
    {
        LogError(ex.Message);
    }

    //... some further tests: display the error message somehow, then:
    return success;
}

private void TestPartA()
{
    // Do some testing...
    if (somethingBadHappens)
    {
        throw new ApplicationException("The error that happens");
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM