我在測試中沒有發現bug,所以系統沒有bug,對吧?
不幸的是,大規模的軟體太複雜,無論多少測試都無法做到沒有bug。你無法對使用者使用應用程式的所有不同方式進行測試。因此,理解應用程式中錯誤和異常的區別是非常重要的,同時要了解處理它們的正確方法,以便你可以採取主動的方式為開發團隊和終端使用者提供健康的應用程式。
測試的侷限性
即使使用最徹底的測試過程,仍然只是在測試特定的情況,並且包含了自己的想法在其中。
想象一下,突然有成千上萬的使用者以你沒有想到的方式使用你的應用程式——他們幾乎肯定會碰到你在測試時沒有碰到的東西。
如何正確處理應用程式中的錯誤
簡單地說,bug可以導致錯誤和異常。錯誤和異常是有不同含義的術語。
主要的問題應該是如何更好地處理這些錯誤和異常,使它們不會產生負面後果。
首先,讓我們看看一些定義,以及為什麼這些區別很重要。
錯誤和異常——有什麼區別?
一些程式語言有它們自己的錯誤和異常定義,但是我想定義它們的區別。
錯誤無法優雅地恢復/繼續的程式設計錯誤,通常需要開發人員介入並修改**來進行修復。有時可以將錯誤轉換為異常,以便在**中處理它們。
通過簡單檢查可以避免錯誤,如果簡單檢查不能滿足要求,錯誤還可以轉化為異常,以便應用程式能夠優雅地處理這種情況。
異常利用特定語言的語義,並在發生異常時表示。異常可以**獲和丟擲,以便**可以恢復和處理這種情況,而不進入錯誤狀態。
可以丟擲和捕獲異常,以便應用程式能夠正常恢復或繼續。還可以記錄未處理的異常(即錯誤),以便開發人員檢視它們以修復底層錯誤。
示例# 1
使用者錯誤——使用者輸入錯誤資料,也不需要異常處理,但仍可能導致錯誤/不可恢復狀態。**應該進行簡單的檢查,以防止發生這種情況。應該使用前端和後端驗證,對於本例,只丟擲乙個異常作為「最後的防禦」。
示例# 2
檔案無法開啟並丟擲fileloadexception或filenotfoundexception。這是一種特殊情況,不應該破壞應用程式。應用程式應該能夠處理這種情況,因為這種情況可能由於許多原因而發生,因此,你必須預期到這種情況。
該出錯的還是會出錯……至少一次
「所以……如果我捕捉到每個異常,我的**就不會出錯了,對吧?」
正如我前面提到的,並非所有錯誤都會導致異常。這個結論的主要問題是你不知道**出了問題。你的**可能存在許多問題,由於捕獲異常而對其不做任何處理,你會丟失這些資訊。
不要只是捕捉每個異常,然後繼續,就像什麼都沒有發生過一樣。捕獲塊的目的是在一定情況下進行處理。
不要做什麼——把他們捕獲起來。
如何編寫應用程式來恢復自己
丟擲和捕獲異常是讓應用程式自行恢復並防止它執行到錯誤狀態的好方法。
如果你知道可能會丟擲哪一種型別的異常,最好在catch塊中顯式地顯示,因為每種不同型別的異常都將意味著**由於不同的原因而停止。
異常型別要具體,這樣就可以向使用者提供反饋,並在確切知道失敗的原因後更優雅地處理其他情況。
為什麼指定要捕捉哪種型別的異常很重要?
某些異常可能破壞資料或以意外的方式執行,這取決於你的程式如何繼續執行。這將導致應用程式出現錯誤。
如果你確切地知道發生了哪種異常,那麼你應該知道要按照哪些步驟進行恢復。或者,如果無法恢復,你應該知道如何優雅地處理這種情況。
那麼,它能恢復嗎?在很多情況下,異常具有足夠的資訊來知道發生了什麼錯誤,並且在catch塊中,你有時可以從錯誤狀態中恢復。可以通過修復一些資料、重新獲取資料或甚至要求使用者再試一次。
你可以捕獲異常,但有時應用程式仍然無法繼續執行,因為它所依賴的資料已經以不可恢復的方式被損壞,或者它期望資料採用不同的格式。
示例陣列上的outofrangeexception異常?乙個程式如何才能恢復?這是乙個將錯誤轉化為異常的例子。你的應用程式期望資料以某種方式出現,但這並沒有發生。雖然恢復並不總是可能,但現在可能不進入錯誤狀態並優雅地處理這種情況。如果將此記錄下來,開發人員可以通過在訪問陣列之前新增一些簡單的檢查或更改訪問它的方式來修復此問題。
如何處理未處理的異常
有一些你意想不到的異常,通常表示**中的錯誤。你可以記錄那些沒有被**捕獲的未處理的異常,因為大多數語言都提供了這樣做的方法。任何未處理的異常都表示錯誤。你的**沒有預料到這一點,因此無法正常恢復或處理這種情況。
將它們記錄下來是乙個好主意,這樣就可以修復。這樣,錯誤就不會經常丟擲異常。如果它們真的發生了,你想要了解它們,這樣你就可以捕獲它們並處理它們。
錯誤日誌
錯誤日誌可以幫助捕獲這些錯誤。有乙個可以檢視這些日誌錯誤/異常的地方是除錯的關鍵,也是確定何時修復什麼問題的優先順序。
此外,你也不希望依賴於螢幕截圖和已經沮喪的使用者提供的更多資訊。錯誤日誌記錄還可以使你的團隊在出現錯誤時能夠積極主動地聯絡受影響的使用者。這是為了讓他們知道你正在解決問題,這不僅會促進你的客戶關係,而且你還可以在其他使用者遇到錯誤之前修復錯誤。
示例**中產生多個不正確的賬單費用的錯誤通常比無法顯示特定詳細資訊頁面的錯誤更重要,即使詳細資訊頁面錯誤發生得更頻繁。
最終,你希望應用程式遇到的異常盡可能少,但是當它遇到異常時,你希望了解它。只有1%的使用者報告錯誤,所以還有很多錯誤仍然存在。
解決部分問題
編寫一些**將異常和堆疊儲存到檔案中,或者通過電子郵件傳送,以便在發生錯誤時得到通知,這可能是部分解決方案。
示例乙個使用者會遇到上千個異常。100個使用者也遇到了較少發生的錯誤。哪個更重要?在不知道錯誤細節的情況下,影響更多使用者的錯誤更重要。
使用異常的堆疊應該有助於定位錯誤可能出現的位置,並且你應該能夠重新生成它或閱讀**以理解那裡出了錯。
有時這還不夠,問題需要進一步調查。如果發生這種情況,在記錄異常之前向異常新增更多資訊,包括上下文特定細節(例如帳戶id或特定物件狀態),這些資訊將允許你在本地重新生成錯誤。
是時候修正錯誤了
現在,你應該已經捕獲了所有的錯誤和異常,並記錄未處理的錯誤……現在該怎麼辦呢?
根據應用程式的規模,錯誤通知中的噪音是乙個問題。你可以使用電子郵件過濾/grep做一些聰明的事情,它可以分組錯誤並分離到不同的資料夾/檔案中。這可能有所幫助,但只是對噪音問題的部分解決方案。
幾年前,我個人也這麼做過,但很快意識到這只是乙個部分的解決方案,原因有很多。問題是,我仍然不知道哪些錯誤對使用者的影響最大。我關注的是那些丟擲的錯誤,而不是那些對應用程式/使用者體驗最有害的錯誤——正因為如此,我從未真正清楚地知道**出了問題。
我無法看到發生了什麼,但必須執行手動查詢才能弄清楚,這非常耗時。
對於大型軟體,總是會丟擲錯誤和異常。正確地處理錯誤將有助於將你定義為乙個軟體團隊,並圍繞異常和錯誤建立更好的過程。
好的應用程式包含可以在可能的情況下從異常中恢復的**。處理和記錄異常對軟體的執行狀況非常重要!
大型軟體專案中的組織環境
專案管理的三大主要任務就是 計畫 組織和控制。在這三大任務中,組織是其中的核心和鈕帶。關鍵字 pm 專案經理 csa 軟體架構師 sa 設計師 testmanager 測試經理 tester 測試員 developer 程式設計師 customer 客戶代表 consultant 諮詢顧問 軟體生命...
在PHP中如何處理錯誤情況更優雅?
假設現在有乙個查詢使用者資訊的函式getuserinfo 引數是userid,如果傳進來的userid不符合格式要求,或者根據這個userid查不到對應的使用者資訊,這時候函式有2種處理方式 返回false或者null給呼叫者 丟擲乙個異常 以上兩種方式哪種更好呢,為什麼?有沒有更好的錯誤處理方式?...
大型專案裡是如何進行log處理,和異常處理
面試時,問我大型專案中log處理,和異常處理 我做的專案沒有涉及到這些,所以想問問大型專案裡是如何進行log處理,和異常處理 有否這方面的資料和書籍,謝謝大家 我們做的乙個200多萬的專案,不知道是不是算大的。也就是通一記錄。資料庫記錄操作日誌。本地存異常到檔案.感覺處理的也不好。日誌存在庫里被。異...