修改代碼的風(fēng)險(xiǎn)
重構(gòu),就是在不改變外部行為的前提下断部,有條不紊地改善代碼猎贴。
為了保障軟件的外部行為,唯一的辦法就是通過測(cè)試。
因此她渴,重構(gòu)是建立在完備的測(cè)試覆蓋基礎(chǔ)之上的达址。
如果我們不能保證修改后的代碼還能提供相同的功能,
那么這種修改就是錯(cuò)誤的趁耗,會(huì)給用戶帶來極大的損失沉唠。
在有風(fēng)險(xiǎn)意識(shí)的團(tuán)隊(duì)中,不會(huì)同意發(fā)生這樣的修改苛败。
什么是所有的功能
一個(gè)涉及幾百個(gè)頁面的網(wǎng)站满葛,多個(gè)角色處于不同狀態(tài)的用戶都可以訪問它,
那么它總共提供了哪些功能罢屈?
頁面之間的跳轉(zhuǎn)嘀韧,以及同一個(gè)網(wǎng)頁為他們展示的不同功能,都是業(yè)務(wù)邏輯的細(xì)節(jié)表現(xiàn)缠捌。
沒有人知道“所有的功能”指的是什么锄贷,因?yàn)樘珡?fù)雜。
代碼中的某個(gè)分支曼月,看起來似乎用不到谊却,但是可能就是有那百分之一的用戶會(huì)使用它。
另外某處哑芹,為什么這里要向一個(gè)莫名的服務(wù)器發(fā)送請(qǐng)求炎辨,很可能必不可少。
某個(gè)類到底有沒有人在使用它聪姿,我們只知道自己的依賴碴萧,很難知道誰依賴了我們。
如果不確定誰在以什么方式使用它咳燕,就不能進(jìn)行修改勿决。
償還周期
哪怕我們已經(jīng)有了完備的測(cè)試,如果重構(gòu)所花費(fèi)的時(shí)間周期太長(zhǎng)招盲,還是很危險(xiǎn)低缩,
我們不得不在這段時(shí)間內(nèi),同時(shí)應(yīng)付重構(gòu)工作和新功能的開發(fā)曹货。
框架遷移就是這樣的一個(gè)典型例子咆繁,如果我們打算把舊框架的功能遷移到新框架,
那么幾乎所有的功能顶籽,都不得不在新框架下重新開發(fā)并測(cè)試一遍玩般,
新需求也不得不在舊框架中完成,并且最終還得再遷移過去礼饱。
高利貸
我們很容易低估重構(gòu)的成本坏为,
假設(shè)框架遷移需要n個(gè)“人日”的工作量究驴,團(tuán)隊(duì)中有x人,需要y天才能把事情做完匀伏,
則n不等于xy洒忧。
因?yàn)檫@y天中會(huì)有新功能要開發(fā),這些新功能需要xy人日的工作量够颠,
于是熙侍,人們必須加班,假設(shè)人們比原來努力t倍履磨,
則蛉抓,n+xy=txy
,因此xy=n/(t-1)
剃诅。
如果以前已經(jīng)在加班了巷送,那么我只能說,真是太不幸了综苔。
如果框架遷移需要100人日惩系,有5個(gè)人來完成它,他們都用1.5倍的努力進(jìn)行工作如筛,
則事實(shí)上需要40天才能完成,而不是20天抒抬,居然比原來估算的時(shí)間多了一倍杨刨。
這40天中,每人每天必須想辦法比原來多做一半的事情擦剑,
我們知道妖胀,就算加班其實(shí)也很難達(dá)到這個(gè)目標(biāo)。
這就是技術(shù)負(fù)債的利滾利效應(yīng)惠勒,也是著名的牛頓問題赚抡。
償還周期越長(zhǎng),所需償還的債務(wù)總量就越多纠屋。
試錯(cuò)的代價(jià)
重構(gòu)其實(shí)很難進(jìn)行下去涂臣,即使進(jìn)行下去了也做的很不徹底,
項(xiàng)目中混雜了各個(gè)時(shí)代的代碼遺骸售担,戰(zhàn)場(chǎng)從來沒有干凈過赁遗。
一開始就寄希望于用重構(gòu)來逐漸解決問題,可能是有害的族铆,
代碼中會(huì)留下很多做到一半的事情岩四,開發(fā)者必須小心謹(jǐn)慎的理解所有技術(shù)細(xì)節(jié)。
快速試錯(cuò)能反映出這種僥幸心理哥攘,雖然快速試錯(cuò)的目的是為了降低最終出錯(cuò)的代價(jià)剖煌,
但是實(shí)際上很難承認(rèn)自己的確是錯(cuò)了材鹦,人們會(huì)想盡辦法彌補(bǔ)它,
于是耕姊,等我們看到失敗時(shí)侠姑,再退出已經(jīng)來不及了。
快速試錯(cuò)通常是一個(gè)借口箩做,掩飾自己還沒有想清楚它莽红。
參考
重構(gòu):改善既有代碼的設(shè)計(jì)
測(cè)試驅(qū)動(dòng)開發(fā)
程序員的職業(yè)素養(yǎng)
人月神話