[.net] 是“死亡是真棒”首選?



Answers

也被稱為進攻性編程。

你應該檢查,“ 進攻編程:早崩潰,經常崩潰 ”。

防守規劃的規範來看,這是一個非常不同的意識形態:

[防禦性編程]旨在確保一個軟件的持續功能,儘管不可預見的使用該軟件。

我個人喜歡“早期崩潰,經常崩潰”的哲學。

我見過太多了:

try  
{  
    // ... Huge block of code goes here  
}  
catch(Exception ex)  
{  
   // Do nothing...  
}  

這比糟糕的事情糟糕得多。 如果異常處理得當,那麼一個小小的防禦性編程就沒問題了。

Question

最近我參加了Jeffrey Richter關於.NET的培訓課程。 他提到了一個編碼“死亡是真棒”的策略。 也就是說,即使在程序或事件循環的根部,也不要寫“catch(Exception ex)”。 如果拋出一些不能處理的異常,就讓進程死掉。

我不確定這是對的。 就個人而言,我更喜歡有一個“ try {...} catch(Exception ex) {log and try to recover} ”以包裝在執行的頂層。 實際上,如果有任何異常從asXx中拋出,ASP.NET不會死。 如果它死了,例外,那麼一個銀彈的請求可以沉默整個服務。

你怎麼看?




聽起來像Guruspeak

這聽起來像是大師們鼓吹的一般指導方針中的另一個,本身並不是一個壞的建議。 但是,這個準則很容易適用於不屬於的地方。 我想上面使用的關鍵詞是“編碼策略”,因為這個策略在某些領域是非常有用的,但是在其他領域卻是相當有害的。

死亡真棒 - 如果你有很多緊密耦合的組件,其狀態依賴於對方,那麼異常很可能是一個災難性的事件。 但是,您的目標之一應該是編寫代碼,以便單個故障不必使整個系統(通知目標)失效。

你認為下面的應用程序在普通的例外中死去了什麼?

  • 醫療設備
  • 發電廠
  • 入侵檢測系統

對於你在try / catch中捕捉到的異常,你應該期待和處理它們。 對於所有其他情況,快速達到預測的運行水平是很好的。 那麼,如果你在網絡或者網絡處理器上,為什麼不把當前的操作去死呢? 你真的需要整個應用程序下去嗎?

如果您正在開發一個關鍵任務應用程序並且具有公共界面,這變得越來越重要。 如果有例外可以使應用程序失效,那麼這就成為黑帽黑客意圖造成拒絕服務攻擊的一種攻擊手段。

濫用這種策略的邊緣案例有點太大,不能給予太多讚揚。 一個更好的方法,就是解決你的域的問題。 了解這個狀態是什麼,並將適當的部分應用到你的問題。

注意事項:我在正常運行時間和安全性至關重要的服務器端系統上工作。

編輯:我想我是什麼意思是“過程死”的困惑 - 這是整個應用程序的參考或只是正在運行的線程等?




既然你不知道Exception IS的每個子類是什麼,你根本就不知道可以抓住它們。 因此,您應該介意自己的業務:捕獲您知道和關心的異常,這些異常主要是您為自己的程序明確創建的異常,或者是由您使用的庫調用中的錯誤創建的。 特別是,捕捉Exception類只是懶惰的,糟糕的編程 - 實質上,你是在說“我不在乎問題是什麼,不要告訴我,只是做這個。 看看java程序如何處理異常,因為異常處理的做法通常相當不錯。




我對里希特的材料並不熟悉,但是我認為這個哲學/理由是,在絕大多數情況下,這個程序確實沒有任何東西可以從一個沒有處理的意外的異常中恢復過來。

然而,讓程序在用戶面前死亡並不是一個好主意 - 這留下了非常不好的印象。 我更喜歡將未處理的異常記錄到數據庫中,通知開發人員並跟踪它們以確保它們得到修復。

然後,我再次為了這個目的而出售一種產品,所以我在這方面有點偏頗!




我說你應該總是有一個根異常捕獲器...尤其是如果你可以在例外說出什麼地方出錯,代碼或什麼東西,並且把它打印出來給用戶。 然後,用戶總是可以問你(或支持或不管)出了什麼問題,並提供一些信息..而不是“它與保護故障墜毀”




真棒的答案已經在這裡,特別是由Simucal。 我只想補充一點:

有攻擊性的編程非常適合調試。 以我的經驗來說,“提前失敗,經常失敗”可以被認為是為代碼中的錯誤設置陷阱。 當某些事情發生錯誤時(無論是內存洩漏,內存壓低,意外的NULL等),如果程序立即失敗(通過調用數據,例如調用堆棧),通常會更容易看到問題。

防禦性編程對於生產環境非常有用。 一旦你的應用程序已經發貨,你可能不希望你的最終用戶看到一個很好的對話,說:“在foo()的未處理的異常”。 如果您的應用程序處於測試階段,並且您仍在收集調試信息,那麼這可能會很好,但是如果您要發布穩定的應用程序,則可能只是希望在極少數情況下某些程序失敗的情況下,不要打擾用戶。

有時你可以雙方都有。 我經常寫下面的代碼C代碼:

void foo(char* data) {
    ASSERT(data);
    if (!data) { return; }
    // ... work with data
}

如果此代碼在測試環境中編譯,則assert語句會陷入錯誤狀況。 如果它是在生產環境中編譯的,斷言將被預處理器刪除,並且foo()將自動失敗。

例外情況比斷言更具表現力和靈活性,並且有多種方式來管理它們,以便應用程序在測試環境中提前失敗,並在生產環境中記錄錯誤時繼續前進。 根據項目的類型,這種設計可能對你有意義。




您始終可以設置自定義錯誤處理程序,並忽略捕捉您不准備處理的異常。 如果符合正確的條件,試圖從未知中恢復也可能會產生負面影響。 但是,再一次,這確實取決於什麼是例外,以及如何處理它們。

另一方面,我認為人們對整個“例外是邪惡”的心態感到不知所措。 他們是一個工具,如果使用得當,可以有驚人的特權。 然而,很多人通過用catch(Exception)包裝root來濫用它們。




這是非常微軟的。

MS希望你把所有未處理的異常丟到WER。 (Windows錯誤報告,它是當你的應用程序崩潰時將你的錯誤發送給微軟的對話框)

這樣你就可以獲得使用指標,並可以關注導致客戶悲傷的關鍵未處理異常。 我相信這個想法是迫使你去思考例外的來源。

但我完全同意你的意見。 即使你重新拋出後,你總是會抓住一個未處理的根,記錄發生了什麼。 唯一的問題是,如果你的未處理的ex是內存不足,在這種情況下你的調用日誌可能會失敗,因為JIT不能分配更多的內存等。我認為C ++程序通過記憶泡沫來處理這個問題,釋放一個未處理的異常,然後運行一個非常緊湊的日誌例程來嘗試和優雅地失敗。




Related