當前位置:
首頁 > 科技 > 程序員,欠下的技術債怎麼還?

程序員,欠下的技術債怎麼還?

所謂「技術債務」,是指過去犯下的錯誤,最終需要通過重構來彌補。那麼開發者該如何分辨哪些才是良好的技術債務呢?

作者 |Jon Thornton

譯者 |彎月,責編 | 郭芮

出品 | CSDN(ID:CSDNnews)

以下為譯文:

在軟體工程領域中,「技術債務」是一個貶義詞。人們在使用這個詞的時候常常表達出某種遺憾,過去犯下的錯誤,最終需要通過重構來彌補。

然而,金融債務卻沒有遭遇到眾口一詞的譴責。比如你的朋友抵押貸款夠買了新房子,你會說什麼?肯定會說:「恭喜!」債券是基礎設施和公共事業標準的融資形式。企業使用了各種債務,而華爾街卻對股價上漲充滿了信心。

技術債務與金融債務之間的不同之處在於意圖——如果技術債務也並非總是意外,或者由錯誤的假設和意外情況導致,那會怎麼樣?你會如何處理技術債務的貸款呢?

如果我們將技術債務定義為將來必須完成的工作,那麼就可以根據將來所需要花費的工作時間來計算開銷。我們也可以選擇現在就「投入」時間來完成這些工作。

這種心理上的模型可以幫助我避免浪費開銷,或承擔起力所不及的系統維護工作,同時也讓我有機會看到有目的性地使用技術債務的機會。在以下幾個案例中,我藉助技術債務取得了項目的成功。

腳手架

在劃分某個大項目主要功能的優先順序時,通常我會首先驗證項目中最具風險性的部分。這裡的風險我指的是最容易出錯的部分,因為這些部分很複雜、難以定義、未得到充分的理解,或者讓我嗅到了「危險的氣息」。由於這些是最艱難的部分,所以我會趕在代碼庫尚小且容易擴展的時候,首先構建這些部分。

然而,僅僅構建有風險的組件還遠遠不夠。我需要知道構建這些有風險組件的方式是否正確。然而,實踐才能出真知,所以我會全力推動我的代碼進入現實世界。這也就意味著我需要在構建應用程序的其餘部分之前,找到一種方法有效利用這部分有風險的代碼。

在我們團隊開發電子郵件營銷活動時,我們首先需要構建電子郵件編輯器。我們擁有頂級的設計和強大的內容編輯工具,我們希望構建一流的應用程序。幾個月後,我們興沖沖地向同事們展示了我們的編輯器,但當時我們還沒有構建實際發送電子郵件的系統。如果這個編輯器只是一個無法發送電子郵件的玩具,那麼我們就無法獲得真實的反饋。

最終的產品需要快速可靠地發送數億封電子郵件,但我們不需要立即實現這個功能。

所以,我們問自己:「怎樣才能通過最簡單的方式鼓勵我們的同事使用這個編輯器?」當時我們公司有幾百名員工,而且內部的測試人員可以容忍這個編輯器的不穩定性。與我們一直在考慮的健壯系統相比,構建一個發送幾百封郵件的不穩定系統肯定會容易很多。於是,我們意識到我們可以構建一個廉價的應用程序,即便日後丟棄了也不可惜,目的只是為了快速獲取用戶的反饋,這就成了我們的腳手架系統。

如下自我實施的指導方針幫助我們順利地實現了這個腳手架系統:

嚴守預估的工時。如果我們無法在預定的時間範圍內完成腳手架系統,那麼就表明我們承擔了過多的工作,需要重新考慮實現方法。

從一開始就明確傳達,這個系統會被拋棄。代碼需要很好地封裝,而且我們也沒有浪費時間來討論實現細節。

我們明白腳手架的局限性,因此有意避免在故障會造成傷害的情況下使用腳手架。如果我們花時間清理腳手架造成的錯誤,那麼必將帶來更深入的債務,所以我們小心翼翼地測試腳手架的使用情況。

利益相關者知道我們在有意承擔債務。我們在利益相關者和用戶前面誇大了這個系統的限制,告訴他們這些只是為了節約時間,而且在這個過程中確保他們知道之後我們需要投入時間來構建真正的電子郵件發送系統。

我們利用這個腳手架填補了依賴項空缺,目的是為了調整應用程序的構建順序,確保儘早驗證應用程序,同時又不會遇到構建組件的問題。

當代碼在我們腦海中記憶猶新的時候,我們丟棄的電子郵件發送系統收穫了很多有關電子郵件編輯器的反饋意見,這幫助我們加快了迭代的速度,並完善了我們的難題。當構建真正的電子郵件發送系統時,我們從腳手架系統的構建中吸取了大量經驗。

硬編碼

最近,我正在開發一個產品的儀錶板,其中有一個功能是在某個區域顯示最新的消息,比如:「祝所有訂閱者節日快樂!」我們團隊需要每隔一個月或兩個月刷新儀錶板在該區域顯示的內容。

我們需要一個內容管理系統(CMS),我們的產品經理和設計人員可以通過這個系統自行更新儀錶板上的消息。此外,產品經理還希望儀錶板能在特定時間點更新,而工程師不希望為了響應這些需求而定時手動更新生產版本。

一種方法是構建資料庫支持的CMS,幫助我們團隊的各個成員在無需工程師干預的情況下,自行更新儀錶板上的內容。

然而,這種方法的成本很高:額外的前端、驗證以及數據管理。這些隱藏的成本是沉重的技術債務,將來必然給開發人員帶來更多的維護工作,相比這個功能就得不償失了。此外,儀錶板上的消息內容可以持續數周而無需更新,因此即時更新內容的解決方案對我們並沒有好處。

因此,我們沒有採用會帶來額外開銷的基於資料庫的CMS,而是將我們的內容存儲在YAML文件中,並重用現有的工具來提供CMS功能。更新儀錶板消息傳遞的用戶界面不一定非要用瀏覽器界面,也可以是文本編輯器和Git。其他團隊成員可以通過代碼審查來驗證這些更新,因此我們不需要花時間編寫驗證和錯誤處理程序。我們現有的CI工具可以跨環境自動同步內容更改。

為了實現在特定時間發表新內容,我們編寫了更多的硬編碼,如下所示:

在採用硬編碼時,我考慮了以下幾個因素:

這些更新需要幾個小時才能生效嗎?硬編碼有一個明顯的限制:這些更新的新代碼需要部署到生產中。如果沒有意識到這個限制,那麼可能會引發棘手的維護問題,從而產生惡劣的技術債務。

用戶願意接受Git的這個新界面嗎?每個更新都需要與團隊版本控制工具以及CI系統交互。為了避免更多的協調或培訓的開銷,我們測試了一下:參與這個過程的人中是否有人了解Git?

是否有現成的UI、驗證和數據模式?硬編碼可以避免定義新模式,從而獲得最大受益。如果應用程序現有的模式可以徹底解決問題,那麼就不值得使用硬編碼。

通常,下面這些設計模式都可以考慮使用硬編碼:許可權列表、表單欄位選項和功能開關等。

無需修復所有的邊緣案例

我曾經構建的一個功能允許用戶創建最多10個項目,但不允許超過10個。這裡面包含一個很常見的競爭條件:如果我們同時發出兩個創建項目的請求,那麼這兩個請求都會計算現有的項目數,然後同時創建兩個項目。如果此時我們已有9個項目,那麼最終就會創建11個項目——超過了我們的限制。

大多數測試人員會認為這是一個bug,而bug是用戶可見的技術債務。

在這種情況,我們本可以利用資料庫事務解決這個問題,但我們使用的資料庫是不支持事務的NoSQL。讀/寫鎖都沒問題,但我們需要在分散式系統中運行,因此需要分散式鎖。如果我們編寫一堆鎖定代碼來實現這種「完美」的限制,那麼最終可能會引入其他意外的bug。而且我們必須花大量時間編寫一堆鎖定代碼,而且之後的每位開發人員都必須理解這段鎖定代碼。

似乎我們付出了這麼多努力只是為了不會多創建一個項目。那麼非技術性的解決方案呢:如果我們故意不修復這種競爭條件,會怎麼樣?

我說的可不是對這個問題視而不見,留給下一位開發人員來處理!我說的「故意」是說搞清楚以下幾個問題:

如果創建了11個項目,那麼會怎麼樣?嗯,實際上也沒什麼大不了。這是一個很武斷的限制,應用程序的其餘部分並不在意多出來的幾個項目。

我們可以了解一下這種競爭條件的發生頻率是否高於預期?也就是說,通過一條資料庫查詢找出超過10個項目的賬號,且每條項目記錄都有一個時間戳。結果卻發現生產環境中並沒有這種競爭條件。

因此,我們大可以不必理會這筆技術債務。由於創建額外項目的影響很小且易於監控,我們可以將時間花在優先順序更高的工作上,無需在這種不是問題的問題上浪費時間。

對於良好的技術債務要做到心中有數

許多沉重的技術債務都是因為構建的功能過多,而且花在維護和改bug上的時間超過了預期。這就好像你購買了太多地產,最終陷入溺水屋的困境(註:按揭買房者所欠銀行的錢超過房子本身的價值)。

關鍵在於你清楚投入的時間,並了解你所承擔的成本。由於構建的功能太少而引發的問題並不可怕,因為你隨時可以構建更多功能。我們應該構建方便丟棄和替換的功能,這樣代碼會更加模塊化。良好的技術債務的局限性很明顯,且眾所周知。你可以在代碼的注釋、README、常見問題解答以及與人的對話中澄清這些局限性。

你可以善加利用良好的技術債務,將時間集中在重要的工作上,加快構建軟體的速度。

原文:https://engineering.squarespace.com/blog/2019/three-kinds-of-good-tech-debt

本文為CSDN翻譯,轉載請註明來源出處。

【END】

熱 文推 薦

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 CSDN 的精彩文章:

TIOBE 8 月編程語言排行榜:Python 奮力追趕 C,Swift 下跌
面試總是死在網路協議,我該怎麼辦?

TAG:CSDN |