你有沒有想過爲何有時修復錯誤彷佛比它應該花費更長的時間?當你終於找到問題時,事實證實你所須要的只是一個小小的改變。然而,花了不少時間才能找到正在發生的事情。這種狀況比我想象的更頻繁。面試
另外一方面,當您編寫代碼並進行測試而且沒法正常工做時,修復錯誤很是快。你跳回編輯器,掀起一行代碼,問題就解決了。數據庫
爲何即便問題很簡單,有時修復錯誤也須要不少工做,有時候,修復問題的速度很快 - 甚至可能很難解決問題?咱們能夠從易於修復的錯誤中學到一些東西,這樣咱們能夠花更少的時間來修復bug嗎?瀏覽器
讓咱們來談談這個問題,看看咱們能夠用什麼方法來解決這個問題,而且由於很難找到錯誤而中止拔頭髮。服務器
爲了肯定在修復錯誤時花了這麼長時間,咱們先來看看修復錯誤所涉及的步驟。編輯器
嗯,我想咱們已經開始在這裏看到一個問題了。修復bug自己只有六分之一!函數
但在咱們得出結論以前,讓咱們更詳細地看一下這些步驟。而後,咱們能夠看到每一個步驟中的內容須要花費時間,並找到使它們更快的方法。 工具
錯誤修復過程的第一步是理解問題。咱們須要收集足夠的信息,以便咱們知道發生了什麼,以及應該發生什麼。性能
這個步驟花費很長時間的最大貢獻者是可怕的,糟糕的錯誤報告。單元測試
用戶從不提供好的錯誤報告。這是生活中無能否認的事實。學習
我可能會誇大一點,但我確信你已經比你想要的更頻繁地聽到「它不起做用」的字樣。
「X不起做用,它須要在昨天修復!」
而後你繼續問一些問題,但願你能從記者那裏收集一些比「它不起做用」更有用的信息。
固然,有時當行星和恆星正確對齊時,你會獲得一個好的錯誤報告。您能夠清楚地瞭解出現了什麼問題,重現它的精確步驟,甚至能夠得到有關用戶使用的瀏覽器和操做系統的信息!那時候你能夠直接進入第2步並開始修復bug。
但在最糟糕的狀況下,你只會對發生的事情有一個模糊的概念,這意味着在第2步中須要付出更多的努力。
若是您在步驟1中得到了良好的錯誤報告,則此部分能夠很容易。您能夠按照錯誤報告中的步驟操做,而後當即重現錯誤。太棒了!如今,您能夠繼續查找損壞的代碼。
可悲的是,這一步每每不是那麼順利。
因爲模糊的錯誤報告,這一步每每涉及不少猜想。
也許用戶使用的是Firefox,或者他們使用的是Chrome。在點擊此按鈕以前,他們不肯定他們作了什麼。我想知道我是否應該隨意按下按鈕並但願最好?
有時,在嘗試重現問題後,您必須反覆執行步驟1和步驟2,而不會產生任何結果。但願您能夠從用戶那裏得到更多信息,而後再試一次。
在這一點上很清楚,爲了加快步驟1和2,咱們須要收集儘量多的信息。咱們掌握的信息越多,理解和重現問題就越容易。
一旦咱們再現了這個bug,咱們就須要找到致使問題的代碼的特定部分。
此步驟的難度各不相同,主要取決於兩個因素:
代碼量會影響這一點,由於每行代碼都會增長可能的錯誤數量。值得慶幸的是,熟悉代碼庫能夠顯着縮小範圍。
找到問題一般從採起有根據的猜想開始。
「好吧,這就是問題,這就是我能夠重現它的方式,因此我認爲問題出如今代碼的Y部分」
您對代碼庫的熟悉程度越高,您的猜想就越好。這使您能夠縮小須要查看的代碼量,可能須要大量調整。
「好吧,我最近在處理函數Z,它有與此相關的代碼。我最好先檢查一下。「
根據問題的類型,您還可使用調試工具來幫助您更輕鬆地找到有問題的代碼。
「是的,當我點擊它時會出現錯誤。我將在事件處理程序中設置一個斷點並從那裏開始。「
**在此過程的這一步,最大的時間匯是找到問題發生的確切位置。**它多是行爲不當的功能,用戶的不良价值或任何數量的東西,您須要在繼續以前找到問題的根源。
這多是這個過程當中最重要的一步,但它常常被徹底跳過!
因爲感知時間限制,或者僅僅由於經驗不足的開發人員可能不知道他們應該這樣作,它可能會被跳過。不管哪一種方式,跳過此步驟一般意味着您的代碼慢慢開始填充hacks和kludges。
注意,我說感受時間限制。一般你可能會感到有壓力要快速修復。
「只需快速修復,客戶就在等待。你之後能夠作好工做。「
所以,您可使用一些代碼來修復損壞的代碼並跳過根本緣由。固然,你極可能永遠沒法妥善修復它,由於總有一些東西須要完成。
但快速修復快速修復的結果與使用膠帶修復漏水管道相同。即便在芬蘭,咱們稱膠帶爲「耶穌膠帶」,由於它具備修復任何東西的神奇能力,在某些時候膠帶修復開始泄漏,你須要再使用一些膠帶。不久以後,你手上就會有一個巨大的混亂,你必須把它所有撕下來。
最後,您須要花費更多時間來修復快速修復,而不是花費更多時間來完成正確的工做。
但我離題了。
肯定根本緣由意味着您須要找到錯誤的真正來源。讓我給你舉個例子。
假設您網站上的某些價值顯示不正確。您能夠經過更改顯示代碼來解決此問題,但更多時候,顯示症狀的代碼不是根本緣由。
若是您更深刻地研究問題,您可能會發現數據庫中的數據也是錯誤的。進一步深刻研究,您會發現保存該值的代碼已被破壞。這是問題的根本緣由。您找到的原始代碼只是在其餘地方顯示問題的症狀。
若是您只是修復了症狀,那麼真正的問題就會存在。它將繼續在未來引發問題,同時你不斷修復更多的症狀。
與查找症狀不一樣,此步驟不須要太多猜想。你有一個起點,從那裏你能夠追溯到根本緣由,因此你不須要猜想。
儘管如此,這一步可能很是耗時,由於您常常須要在幾個級別上深刻研究代碼。多長時間在很大程度上取決於根本緣由與症狀相比的位置 - 有時它們甚至多是相同的,但如示例所示,它可能會下降幾個等級。
最後咱們能夠解決這個問題。咱們已經複製了這個錯誤,找到了症狀發生的地方並找到了根本緣由。
在完成全部工做以後,這一步一般是至關微不足道的。咱們有關於出了什麼問題,應該發生什麼以及出現什麼症狀的信息。錯誤一般不須要大的修改來修復,所以實現部分每每很快。
做爲這個過程的最後一步,咱們須要確保錯誤被完全掩蓋。
這能夠經過重複您以前重現問題的步驟來完成。
偶爾這個bug仍然會重現。在這種狀況下,您一般須要返回步驟4或5並從那裏繼續。
若是對軟件測試、接口測試、自動化測試、性能測試、LR腳本開發、面試經驗交流。感興趣能夠175317069,羣內會有不按期的發放免費的資料連接,這些資料都是從各個技術網站蒐集、整理出來的,若是你有好的學習資料能夠私聊發我,我會註明出處以後分享給你們。
如今咱們已經查看了錯誤修復過程當中的每一個步驟,咱們能夠肯定這些關鍵難點:
全部這些都有助於減緩錯誤修復並使其成爲一個繁瑣的過程。咱們編寫代碼來修復bug的部分不多是最大的時間下沉!
可是,儘管如此,有時咱們能夠很是快速地修復錯誤。這一般發生在咱們添加新功能和處理全新代碼時。
爲何是這樣?
若是咱們在考慮使用全新代碼時的典型狀況,咱們一般會很是熟悉咱們剛纔寫的內容。在這種狀況下發現錯誤的人一般與編寫代碼的人相同。
這幾乎徹底消除了猜想!
所以,修復錯誤是一件垂手可得的事。一般狀況下,您只需將alt-tab返回到編輯器,當即發現問題並進行更快的修復,而不是說「它不起做用」。
咱們能夠有把握地說,缺少信息和由此產生的猜想是致使修復bug變慢的最大因素。
咱們能夠作些什麼來改善這種狀況?
讓咱們首先看一下咱們能夠作些什麼來從用戶那裏獲取更多信息並進入錯誤報告。邁出這一步的第一步是向用戶詢問一些具體問題。這有助於指導用戶爲咱們提供更有效地解決問題所需的信息。
如下是您可使用的一些問題。我不記得我第一次看到這些,但我傾向於本身使用這種格式而且效果很好。
第一個並非絕對必要的,可是若是您使用像JIRA這樣的工具,由於您須要該問題的名稱,這將很是有用。第二個是至關明顯的,第三個對於理解用戶指望發生的事情很是有用。雖然你能夠本身解決這個問題,但最好事先了解一下 - 特別是有時它可能不是技術問題,而只是混亂的結果。
第四點多是最重要的,但用戶並不老是知道如何填補這一點。若是可能的話,最好給他們一個小樣本,如你想要它填充,如「1。我在第X頁2.我點擊按鈕Y 3.我輸入值Z「。
特別是對於Web應用程序有用的其餘信息是用戶的瀏覽器和操做系統。根據用戶的不一樣,他們可能並不老是知道這一點,所以可以自動收集這些信息可能頗有價值。爲此,您能夠考慮集成Usersnap等服務,這有助於將更多數據收集到錯誤報告中。
在腳本錯誤的狀況下,具備堆棧跟蹤一般也是有用的,儘管具備良好的再現步驟,您也應該可以本身得到它。像Loggly這樣的工具可用於自動收集有關錯誤的信息(即便在客戶端JavaScript代碼中),這樣您就能夠更好地瞭解發生的狀況。
這些步驟是改進流程的良好起點。可是他們並無真正解決全部問題。例如,不管您嘗試多少,用戶均可以而且將繼續發送使人困惑的錯誤報告。
我知道。我反覆告訴用戶他們須要包含重現問題的步驟,或者咱們不能作任何事情,並且我仍然不斷獲得可怕的「它不起做用」的錯誤報告。
「Jani,X破了修復它」
啊。
那麼還有什麼咱們能夠作到這一點並不依賴於那些挑剔的用戶呢?
記錄常常被忽視做爲一種工具。也許這樣作缺少好的庫,或缺少使用日誌輸出的好工具 - 由於讓咱們面對它,誰想經過手工查找特定事件來瀏覽一個巨大的日誌文件?可是正確完成並使用好的工具,日誌能夠提供有價值的信息。
大多數開發人員僅將日誌記錄用做臨時措施。很容易將一堆`console.log'打入咱們的代碼只是爲了看看發生了什麼 - 我作了不少。
可是當我說伐木時,我不僅是談論調試日誌或錯誤日誌。我正在談論通常的登陸 - 關於代碼中發生了什麼,正在發送什麼輸入等的信息。
以更系統的方式登陸須要一些工做。咱們須要注意包括登陸咱們的代碼,咱們須要確保記錄可能有用的信息。那麼這有助於加快bug的修復速度呢?
特別是在自動化流程的狀況下,日誌記錄很重要。除非您有日誌,不然一般沒法跟蹤此類進程中發生的狀況。日誌應該足夠詳細,以便讓咱們對發生的事情有一個合理的瞭解。
使用這樣的日誌有助於經過向咱們提供更多有用信息來減小猜想工做量。
儘管我喜歡將Java變得糟糕,但日誌記錄是他們作得很好的一件事。它有許多庫和已創建的日誌實踐。若是您遇到過Java應用程序的問題,您可能會查看日誌甚至增長日誌詳細程度。他們中的許多人輸出了大量的日誌。
記錄有用的是什麼?對於每一個應用程序來講,擁有日誌或記錄全部內容並非絕對必要的,但這裏有一些例子:
根據您查找日誌的有用程度,實現啓用/禁用某些類型的日誌或基於每一個用戶啓用/禁用日誌的方法也是一個好主意。
到目前爲止咱們所看到的全部這些措施都沒有解決咱們的關鍵問題。錯誤報告和日誌雖然有用,但只會在過後提供更多信息。
還記得咱們如何找到快速修復的錯誤之間的重要區別,以及須要很長時間才能修復的錯誤是咱們檢測問題的時間。
每當咱們積極處理一段代碼並在開發過程當中發現錯誤時,它們的修復速度要快得多。咱們對代碼有了全新的記憶,咱們已經掌握了全部信息,所以咱們不須要進行其餘必要的考古。
到目前爲止,這些都沒有任何幫助,即便這是花費多少時間的最大貢獻者之一。
咱們怎樣才能更快地發現更多的錯誤,甚至在咱們的開發過程當中?
顯然,咱們能夠聘請二十多位QA專家來用顯微鏡進行更改。然而,對於大多數團隊而言,這並非很實用,即便使用質量保證流程,也可能須要一些時間來發現問題,此時咱們已經轉向了其餘方面,因此它無濟於事。
在開發過程當中能夠幫助咱們發現錯誤的是測試自動化。
測試自動化是一個更加現實的目標。它不須要大量的前期投資:您能夠逐步開始使用它,而且每一步均可以得到愈來愈多的好處。
每當咱們更改代碼時,咱們都會冒險引入錯誤。可是,若是咱們新添加的代碼存在錯誤,咱們一般會輕鬆地發現並修復它們。
新添加或更改的代碼很容易修復,由於咱們已經掌握了它 - 咱們只是花時間研究它!這意味着能夠輕鬆找到並修復其中的任何問題,由於咱們不須要開始挖掘代碼來找到它。咱們仍然能夠記住事情的發展方向。
所以,咱們能夠贊成,咱們越早發現錯誤,就越容易修復。
但單元測試如何幫助咱們作到這一點?
首先,單元測試一般包含如下部分:
而後,若是這樣的測試失敗,咱們會獲得如下信息:
讓咱們將這些與咱們想要的錯誤報告進行比較:
你能看到咱們從測試中獲得的結果嗎?咱們從一個好的錯誤報告中得到了咱們想要的信息!不只如此,測試在開發過程當中爲咱們提供了這些信息*!*
當您仍在處理代碼時,單元測試能夠爲您提供所需信息的即時反饋,所以您的想法一切都很新鮮。
全部這些都有助於確保咱們有足夠的信息來快速修復錯誤。咱們知道發生了什麼,應該發生什麼,咱們能夠經過再次運行測試來重現錯誤...咱們甚至能夠經過再次運行測試來驗證咱們的錯誤修復代碼是否正常工做。
做爲額外的好處,測試也會捕獲代碼中其餘地方的更多錯誤。一般因爲咱們的更改,咱們會在其餘地方意外地致使錯誤。這些很容易被忽視,最終難以修復,但若是你有單元測試,沒問題 - 一旦你編寫測試,你能夠保持它,它不斷捕捉錯誤和有用。
經過修復錯誤,最大的時間接收器不是編寫修復程序。在咱們開始編寫任何代碼來修復bug以前,咱們須要作的全部工做。其中大部分是因爲缺少信息 - 錯誤的錯誤報告,大量的代碼,甚至糟糕的代碼均可能致使錯誤。
咱們能夠經過嘗試在錯誤報告中獲取更多信息來改善這種狀況,但更快地修復錯誤的最佳方法是更早地發現錯誤。
在開發過程中遇到的錯誤是最快修復的,由於咱們正在積極處理有問題的代碼,而且咱們在頭腦中擁有所需的信息。這意味着咱們不須要開始挖掘錯誤報告或代碼來弄清楚發生了什麼。
在測試期間捕獲更多問題的最佳方法是單元測試。他們解決了全部三個問題:
您也不須要花費大量精力進行測試。您能夠逐個開始添加測試,例如修復錯誤時。隨着您添加的每項測試,您將得到愈來愈多的好處。
測試的主要問題是它可能很難入門。然而,一旦你學會了這些概念,它們就不會過期了 - 不像當下流行的圖書館,測試已經存在了很長時間,不管你使用什麼庫或語言,均可以使用徹底相同的原理。
單元測試還有更多的好處,而不只僅是更快地修復bug。