遺留代碼
從何而來
軟件是如何演變成遺留代碼?
- 初期,架構(gòu)清晰,代碼精煉,指點(diǎn)江山
- 中期,新功能簡(jiǎn)單在原有代碼加上邏輯,頁(yè)面自測(cè),談笑中高效完成
- 最后,另一個(gè)團(tuán)隊(duì)接手
- 面對(duì)難以理解的復(fù)雜代碼,新增功能異常困難。
- 他們?nèi)缗R大敵,為避免更多的坑,選擇繼續(xù)在原有代碼上堆積邏輯,但結(jié)果卻是導(dǎo)致更多的bug,一首《涼涼》蕩氣回腸。
- 他們一邊在批評(píng)著前人,一邊在不堪負(fù)重的代碼繼續(xù)挖坑,漸漸變得與前人一樣……
定義
為什么大部分系統(tǒng)最后都變成了沒有活力的遺留系統(tǒng)?
因?yàn)殚_發(fā)人員成日奔波在填坑之中,新功能根本無暇顧及或者無法輕易添加。
系統(tǒng)缺失了一個(gè)最關(guān)鍵的東西:測(cè)試。
因?yàn)闆]有編寫測(cè)試的代碼就是遺留代碼。
改變
為什么大家不愿意為遺留代碼編寫測(cè)試?
因?yàn)樵瓉泶a難以理解,心生敬畏且無從下手,加之bug絡(luò)繹不絕,根本無暇顧及。
忍無可忍的開發(fā)者,含淚揮刀自宮——重新寫一套系統(tǒng)。但由于缺少測(cè)試,慢慢又變成另一個(gè)遺留系統(tǒng)。
仿佛《恐怖游輪》般的結(jié)局。
如何破局?或許你應(yīng)該先試試重構(gòu)。
重構(gòu)
為什么要重構(gòu)
風(fēng)險(xiǎn)與收益
- 軟件是高風(fēng)險(xiǎn)和多變性
- 重構(gòu)可以降低成本
- 改善設(shè)計(jì)
- 更快添加新功能
- 更少產(chǎn)生問題
- 更快定位問題
個(gè)人成長(zhǎng)與挑戰(zhàn)
- 通過重構(gòu)糟糕代碼來培養(yǎng)良好習(xí)慣
- 保持既有行為不變是軟件開發(fā)最有挑戰(zhàn)的任務(wù)之一
- 我們可能無法選擇好的項(xiàng)目,但我們可以選擇好的挑戰(zhàn)
何時(shí)重構(gòu)
- 當(dāng)關(guān)鍵代碼維護(hù)不善的時(shí)候
- 當(dāng)唯一理解代碼的人沒空的時(shí)候
- 當(dāng)有信息可以揭示更好的設(shè)計(jì)的時(shí)候
- 當(dāng)修復(fù)bug的時(shí)候
- 當(dāng)需要添加新功能的時(shí)候
- 當(dāng)需要為遺留代碼寫文檔的時(shí)候
- 當(dāng)重構(gòu)比重寫容易的時(shí)候
考慮問題
我們?cè)谥貥?gòu)時(shí)需要考慮各個(gè)方面,修改遺留代碼永遠(yuǎn)是一件危險(xiǎn)的事情。
多問問自己:
- 哪些需要修改?
- 如何驗(yàn)證正確完成修改?
- 如何確保沒有破壞既有功能?
- 如何避免修改帶來越來越難以理解的代碼?
正確重構(gòu)
- 從已有系統(tǒng)中學(xué)習(xí),只重構(gòu)熟悉的功能
- 循序漸進(jìn),一次不要重構(gòu)過多
- 在遺留代碼中添加測(cè)試,單元測(cè)試是重構(gòu)最有力的保障
- 有更好的理解后對(duì)一個(gè)實(shí)現(xiàn)進(jìn)行重新設(shè)計(jì)
單元測(cè)試
好的單元測(cè)試
- 快速反饋,十分之一秒都算慢
- 重構(gòu)后能夠快速定位問題所在
- 以行為作為單元,而不是代碼量
- 一個(gè)獨(dú)立可驗(yàn)證的行為
- 產(chǎn)生可觀察的影響
- 不與其他行為耦合
- 行為不變,測(cè)試也不變
- 成為活文檔
- 單元測(cè)試也是代碼,與其他代碼同等質(zhì)量要求
bad:testConstructor good:testRetrievingValuesAfterConstruction
編寫策略
全新功能
采用測(cè)試驅(qū)動(dòng)開發(fā)(TDD),需要我們改變習(xí)慣——從做什么開始,再關(guān)注怎么做。
編寫步驟:
- 先設(shè)計(jì)測(cè)試,可在任何時(shí)候進(jìn)行
- 設(shè)計(jì)接口,確定方法名稱、收入?yún)?shù)、返回值
- 編寫測(cè)試
- 實(shí)現(xiàn),重構(gòu)
遺留代碼
解除依賴性以使遺留代碼改動(dòng)更容易,所以要編寫測(cè)試,往往需要先修改代碼。
編寫步驟:
- 確定改動(dòng)點(diǎn)
- 找出測(cè)試點(diǎn)
- 解依賴,為測(cè)試創(chuàng)造空間
- 編寫測(cè)試
- 修改,重構(gòu)
關(guān)于bug
最后我們聊聊bug,解決bug最好的方法,就是避免Bug的出現(xiàn),這就要求我們編寫高質(zhì)量代碼。
如果功力不夠,那就盡早發(fā)現(xiàn)bug,依賴持續(xù)集成,自動(dòng)化測(cè)試。
設(shè)計(jì)時(shí)打印關(guān)鍵日志信息,讓bug更容易找到。
每發(fā)現(xiàn)一個(gè)bug,就當(dāng)作一項(xiàng)缺失的測(cè)試。
利用發(fā)現(xiàn)的缺陷修正流程,不斷從錯(cuò)誤中學(xué)習(xí)。
后續(xù)
后續(xù)章節(jié)將重點(diǎn)關(guān)注如何對(duì)遺留代碼進(jìn)行測(cè)試,為重構(gòu)保駕護(hù)航。