償還技術債 - 經過重構拯救老代碼(翻譯)

###償還技術債 - 經過重構拯救老代碼程序員

**嘗試去接管一個陳舊的代碼庫使他成爲達成一個可控的狀態?**這幾年的大型的舊web應用程序開發給了咱們以下這些建議。web

####經過重構去拯救舊代碼 松鼠會由於忘記本身把松果放在那裏,使得每一年多了幾千棵松樹。相似的,這些事情在項目中都沒有什麼關係。你的項目是能夠被拯救的數據庫

**不管代碼多麼的雜亂,讓人瘋狂。**可是你的老闆讓你上了,你要相信無論前路多麼曲折坎坷,你總能搞定的!安全

####心無畏懼框架

公平的說。比起衝進一個四處鮮血還有巨龍守在門口的沼澤地待幾年,你更願意在一片清新的草原上散步。模塊化

不幸的是,你的老闆和這片沼澤地的公爵達成了一個協議,派你上了。函數

無論怎麼樣,你上了,所要作的就是把這塊泥濘的沼澤變成一塊美麗的牧場工具

####技術債 - 它怎麼會這樣 當你在項目中遇到一個又一個坑的時候,你可能在想:這是哪一個「無能」的人作的?有人確定能預見這個問題,可是爲何不是這樣呢。單元測試

可能吧,不過更多的時候並非這樣。包括咱們本身,很自信的寫出的東西可能以後本身也不知道是什麼了。測試

「無能」這個詞並不適合解釋這種狀況。從工做自己的角度解釋,它應該叫作「技術債」。

####代碼癌

「代碼癌」這個東西充斥在各個項目的開發週期內,指的是爲了快速解決當下問題採起的臨時方案(原文中爲「Ugly hacks」)。隨着這種只完成了功能可是很難維護的東西的出現,而後技術債就開始越積越多。

而後,一點一點的,項目就開始失控。不經手真正代碼的的人根本不會在乎這一點,可是,最終,他可能最後落在你的手上。

對於任何項目來講,快速完成需求,推出新的功能都是很是重要的。若是作不到,珍貴的用戶就會離開。舉個例子,就像是他們寧願去隔壁泥濘沼澤上的酒吧喝着長島冰茶,也不會在你花了一全年修剪工整的草坪上傻站着。

因此,就算是一個健康的項目,技術債也必定會產生,可是爲了不代碼最終變得沒法維護,這種積累的技術債在某些時候必定要解決的。

爲了不讓一羣瘋狂的受害者衝進你的沼澤地找你討債。做爲沼澤地的主人,你可能須要一些**「重構」**:交換一些代碼的位置,讓他可以更好地維護和拓展。

####說服客戶

對於這片泥沼的公爵,你須要告訴他他的土地上正在不斷的進入小怪物。由於總有客戶想要這樣那樣的功能。當你面對一個deadline定爲一週可是你完成它至少要兩週的需求,你須要學會向他解釋,讓他明白你須要花一點時間來作點小小的重構

若是作不到這一點,能夠預見,技術債將不斷增長,最後沒法收場。

其實你的目的和你的客戶是一致的,愉快而順利的工做,而後你們都能賺錢~ 這個的前提就是須要有一個穩定的項目可讓你從容的寫出你的代碼。

####爭取你的自由

你須要學會如何將狀況解釋清楚。我以爲最好的辦法就是向這片泥沼的主人解釋清楚有哪些潛在的風險隱藏在角落裏,要讓他知道你的好意。你能夠試試下面幾條建議:

1.解釋什麼叫作「技術債」,告訴這種債務太高會讓開發愈來愈慢。咱們可能須要花費不少時間才能找到問題,並且要花費不少時間去解決它。

2.給出清晰的短時間目標和計劃,告訴客戶你能夠選擇花一週去實現一個功能,也能夠給我嗎一週時間重構,而後花一天去完成這個功能。可是第二種方案對於之後的開發有不少好處。

3.告訴客戶,其實大家最終的目標是同樣的。並且,大家擔心的事情也是相似的。

一旦你和泥沼的主人達成一致,事實上最困難的事情就已經結束了。下面,讓咱們的項目走上正確的方向吧

####不要再弄出一個新的沼澤地

你能夠嘗試修復它,不要重寫它。

你可能說服了沼澤地的主人,你能夠爲他創造一個嶄新的牧場。你會用更新的工具,更好的方式。可是,聽個人,千萬不要

從新的風險有不少:

1.這樣作就像按下了一個危險的開關,新代碼歷來沒在生產環境下跑過,誰都不知道會發生什麼。

2.數據遷移,從舊的系統向新系統遷入和遷出數據很容易出現問題。

3.復刻舊的錯誤,你開始重寫了,就有可能重複舊項目中的問題,舊項目的一些巧妙的特性也會被弄丟。不少問題都發生在系統的一些你自己剛開始就有疑問的地方。你會浪費不少時間,無論是你仍是你的客戶。

4.你須要緊跟着業務,你在作新工程的時候,舊的工程也須要同時跟進業務需求。這樣相同的東西須要在兩邊同時開展。

因此,聽個人,不要從頭開始,優化現有的

####讓問題變得可見

這種事情很容易讓人不爽,把問題都暴露出來。就像是讓沼澤裏的怪物們通通跑到了你的眼前向你的臉上吐痰,巨龍噴着火要燒掉你的頭髮,住在蘑菇旁的小侏儒踢着你的小腿。

無論你有沒有注意到,這些害蟲一直在侵蝕你的項目,你得想辦法擺脫他們。因此必須得在任什麼時候候都能看到到底問題出在哪

預見錯誤。每週花一點時間處理最常出現的一些問題。將問題圖表化,可能能更有效的作到這一點,

監控環境變化。這多是找到瓶頸和預見危機的關鍵(見下文)。

這樣,你就能知道是什麼問題對你的項目傷害最大,你就能提前發現問題展開救治,而不是最後面對一個垂死的病人一籌莫展。

####處理最重要的問題

作到這一點。你就須要有一個對系統完整的目標。就像你清楚的知道你最終要構建的完美的牧場是什麼樣,在你的每一步工做都是朝着這個目標。

這樣你就不會忘記你每一小步作了什麼。在這一小步一小步中間,你就會發現本身到達了本身最終的目標。

結合上文所說的監控方式以及你的最終目標,肯定什麼是你最早要處理的。你最大的問題應該不是立刻實現某個目標,並且開始管理重構路上你找出的問題

還有個建議,有些小問題就像是一寫坡腳的小精靈,你可能看她們不爽,可是實際上她們是無害的。你最好把時間花到如何踢出真正對人有傷害的那些食人魔。

####這行代碼是我寫的

解決問題是最重要的,可是不意味着其中的實現細節不重要。事實上,他們一樣重要。

這裏有個沼澤生存原則,保持你的宿營地比你發現他的時候更乾淨。隨着你持續的整理,注意不留下什麼垃圾。你的環境就會愈來愈好直到你發現這篇泥沼變成了綠洲。

態度決定一切:

1.細心。代碼是你寫的,你要能向全部接觸它的解釋清楚它,不要草率馬虎。

2.團隊要同樣細心。你辛苦的填上一個有一個坑,可是後來人還在不斷挖坑的話,依然仍是那個樣子。

3.紀律。團隊任何一我的開始讓事情變糟,都不要讓他逃掉責任。

4.保持小步驟。在正確的方向上,進度比完美實現重要。

5.小小的勝利都能讓人信心十足。你會發現一些地方優秀的修改會促使你想去修復它邊上的問題。

####創建標準模塊

一個對文明評價的重要指標是 在每平方米的土地上有多少圖書館。一樣的,這對你的項目來講也是一個相似的指標(固然在項目裏咱們不叫他(Library)圖書館)。

舉個例子,即便在最爛的沼澤地裏,也會有幾個不是特別糟糕的景點。不管什麼時候,當你發現了一些好代碼,他們完成了一些很不錯的事情,就把他們挪到你的標準模塊裏,是的他們能夠複用。

毫無疑問,你要修復的代碼作的都是很差的。它們徹底忽略和和避開了能讓程序員以爲更輕鬆的能夠陳祚最佳實踐標準的原則。沒有人會幫你搞定他們,你只有一條路可走:在你的新代碼中實踐下面的標準

讓你的代碼標準化和模塊化。有些狀況下你不得不使用舊的方式和不標準的方式處理舊的問題,可是這不意味着,你不能不在新的代碼中實踐這些正確的東西。

####用你的新模塊重構 每當你的新模塊寫好,你就能夠用它來重構舊的。你作這件事的時候不必向馬拉松的衝刺階段同樣緊迫。每當你偶然發現你有一個好的新方式替代那部分老代碼的時候。保持小步驟,最後你會發現一點一點你就找不到那些困惑你的老代碼了。

一般,上述步驟是可行的。不過有時候你發現有些代碼包含無數的依賴關係四處分佈(好比會話訪問,各類模塊和服務糾纏在一塊兒)。這時候,有個好方法是把它們的依賴方法和函數從他們內部暴露出來,外部就能夠經過這些函數和方法訪問他們。這種方式使得這些代碼相對獨立,之後更利於分離和移動它們。

同時,一旦代碼獨立了,它們就變得可測試了。

####經過測試創建信任

自由穿行的食人魔們能夠比帶着枷鎖的食人魔更可怕。把系統中最爲關鍵的部件(同時它們可能形成最嚴重的問題)加上鎖鏈對於掌控一個系統是很是重要的。在每次構建的時候進行測試(最好是自動化的)尤其關鍵

若是有更多的對你的系統行爲的自動化測試,你就能在改動項目的時候有更充足的信心。一點有東西出錯,這些測試就能讓你在發版前及時修改它們

####高級別測試

有一個有效的測試方式叫作:關鍵場景驗收測試。對於一個電子商務系統,確定包括一個結帳的流程。沒有訂單你確定不賺錢,測試這個訂單流程,你就能在客戶沒有發覺以前解決這個問題。有了這樣的測試,你就能夠避免本身不知不覺的引進重大問題

####低級別測試

這種低級別測試咱們推薦單元測試。使用上文說的小步驟逐一分解依賴的方式,你會使得你的代碼有一套清晰的輸入和輸出結構。這種狀況下就很適合用單元測試覆蓋這些代碼的功能。你能夠定義一組輸入,而且定義它預期的輸出。這些測試能夠確保這些代碼的行爲和你預期的一致

####不要測試全部的東西

不必測試系統的每一行代碼。原則上讓系統的每個方面可使咱們對全部事情充滿信心,可是讓全部東西可測試併爲他們編寫和維護測試用例會讓成本變太高。根據個人經驗,你最好把時間花在爲重要的業務邏輯和有可能形成重大問題的代碼上(即便他們看起來很簡單)。

這樣你就至關於把沼澤裏最危險的怪物們鎖起來了,整個沼澤變得更安全咯。

####隔離和更換

結合咱們上文提到的戰略模式和技術,咱們總結惟一個原則:「隔離和替換」。

每當你遇到某些代碼,他們的內部邏輯很難理解,並且打算用那種小步驟重構的方式整理出來。下面有些步驟建議:

1.隔離混亂的部分,把他們放到一些單獨的方法裏。

2.把依賴的部分拆出來做爲他的參數

3.把邏輯裏的反作用分離出來(好比向數據庫保存數據),這裏也是小步驟進行

4.隔離單獨的邏輯到不一樣的方法裏

5.添加單元測試覆蓋邏輯模塊

6.重寫的邏輯模塊。就算他能經過測試,也要保證至少他的行爲要相似老系統中的行爲。

7.保持新老版本同時能在線上運行。保證舊版本也能運行

8.log記錄下新老版本的輸出。

9.對比日誌,看看他們輸出的不一樣,若是有不一樣就爲該模塊添加一個新的單元測試,而後開始修復它。

10.重複上述步驟直到他們一致爲止。

11.最後新版本能徹底替換舊版本的相關邏輯

這種作法就像是不須要停車就能爲他換了發動機,甚至是沒有人能主要到他的內部發生了變化。

####說服本身

在這裏,上述的態度和方法,至少對於我來講,是一個拯救一個瀕臨崩潰的系統之路

最初我還在猶豫,爲何要把個人時間花在這樣一個長期的舊工程上。可是這期間我也得到了不少能幫助我變得更好的技能

1.識別糟糕的代碼。你認識到什麼是糟糕的代碼由於你花了大量的是在在它上面。你在新項目中就不會使用它這種方式由於你知道它會在將來搞出多少問題。

2.迴歸本質。我認識到系統的每個方面都值得質疑和從新評估。項目裏沒什麼是無懈可擊的,你會發現許多更現代的框架能夠幫你處理不少問題。

3.你和項目同時成長。隨着你對項目的關注越多,你就會看到更多的挑戰。你知道了哪些是這個系統的瓶頸,愈來愈多的人在依賴的工做成果,而你是整件事情的中心。

4.人們老是不斷的生產新的東西。若是趕在在他們對項目形成傷害以前,理解他們的運做方式也是個不錯的技能。

5.有趣的經歷。回頭看你這一路的歷程,看看這個系統的樣子和你幾年前第一次遇到他的時候。是否是也蠻有成就感的呢。

####去完成這個巨大(至少是長期)的任務吧 你能夠選擇作一個膽小的農民,期待中誰能把你從這片沼澤地帶到迪士尼樂園。或者你能夠擺正你的姿態,扮演好救世主的角色。在任何一個有堅固地面的沼澤地裏,你均可以找到你的位置。

####最後 幾年以後,你漫步在這片牧場上。你看到公爵在地平線上豎起了啤酒廣告代替了原來「這裏有怪物」的標誌牌。

######感受翻譯的不太像人話。。。。

原文連接:http://blog.intracto.com/paying-technical-debt-how-to-rescue-legacy-code-through-refactoring

相關文章
相關標籤/搜索