寫代碼如同打掃屋子,有句話叫一屋不掃何以掃天下。如果單個(gè)的一個(gè)模塊代碼都不能管好,如何成就一個(gè)完善的軟件系統(tǒng)?今天我們來說說,一個(gè)代碼模塊的代碼是如何一步步腐化變質(zhì),到最后程序員都不愿意去維護(hù)它,然后要么重構(gòu),要么廢棄換新模塊的?
代碼是有一定的周期的,這個(gè)沒有錯(cuò)。為什么有的代碼跑上幾十年任然好用,而現(xiàn)在互聯(lián)網(wǎng)公司的很多代碼,每年都要做好幾次重構(gòu)?一個(gè)成立2年的互聯(lián)網(wǎng)公司,做一個(gè)支付系統(tǒng),可以做了4-5代,每次重構(gòu),這樣的代價(jià)有多大?如何才能讓原有的代碼生命周期更加長,而不增加很多的學(xué)習(xí)維護(hù)成本,開發(fā)一次使用更久呢?
大部分程序員是沒有很多機(jī)會(huì)從0開始搭建一個(gè)新程序的,更多的時(shí)候是接手別人寫的代碼。有代碼移交還好一點(diǎn),往往因?yàn)楦鞣N因素,這些因素你懂的,沒有產(chǎn)品文檔,沒有設(shè)計(jì)文檔,沒有程序說明,程序里可能連注釋都沒有。然后,程序員更新?lián)Q代又極其的快,互聯(lián)網(wǎng)時(shí)代,程序員在一個(gè)公司的平均年資也就1年多,程序就又被傳給下一任維護(hù)者。很大可能的情況是,最終到你手里的程序各種問題,卻能實(shí)現(xiàn)基本的功能需求,但代碼內(nèi)部各種問題讓程序員總有一個(gè)沖動(dòng),重構(gòu)它。
今天不想說重構(gòu)的問題,而是從根源角度分析,程序?yàn)槭裁磿?huì)變成這個(gè)樣子?
什么是程序的腐化?
什么是一個(gè)軟件的質(zhì)量?一個(gè)分類標(biāo)準(zhǔn)是軟件外部質(zhì)量與軟件內(nèi)部質(zhì)量的統(tǒng)一,外部質(zhì)量是對(duì)外表現(xiàn)是否正常,內(nèi)部質(zhì)量是對(duì)后續(xù)開發(fā)有沒有坑,就是我在這里說的軟件有沒有腐化。內(nèi)部質(zhì)量標(biāo)準(zhǔn)有:可維護(hù)性,靈活性,可移植性,可重用性,可測試性,可理解性(摘錄自代碼大全)。不符合以上標(biāo)準(zhǔn)都可以稱之為代碼腐化,形象的理解就是一個(gè)蘋果,從內(nèi)部開始爛了,爛到原本應(yīng)該負(fù)責(zé)內(nèi)部代碼的程序員拒絕去維護(hù)了。
實(shí)際的代碼腐化的例子:
代碼混亂,沒有代碼規(guī)范
不該連數(shù)據(jù)庫的模塊連了數(shù)據(jù)庫
模塊間的調(diào)用混亂:
模塊內(nèi)部的調(diào)用混亂,例如C#代碼已經(jīng)使用了EntityFramework,代碼中跳過EntityFramework,直接用數(shù)據(jù)庫連接修改數(shù)據(jù)。
框架與其他不一致,不統(tǒng)一:有的包管理使用gradle管理,有的使用maven。有的后臺(tái)用.Net,有的用Node,有的用Java。用了HttpClient,又使用Feign去連接其他應(yīng)用模塊
有一些設(shè)計(jì)前后不一致:有的代碼使用了統(tǒng)一的錯(cuò)誤定義CommonException,有的用原生的Exception。微服務(wù)模塊,有resource層接口,定義訪問的路徑,resource的Impl,service的接口提供具體的數(shù)據(jù)接口,serviceImpl提供具體數(shù)據(jù)獲取的實(shí)現(xiàn)。而在具體編碼時(shí),將大量的業(yè)務(wù)邏輯寫入了resource的實(shí)現(xiàn)中。
太復(fù)雜的抽象不能做方便的變更:一開始設(shè)計(jì)的Job系統(tǒng),上面是2-3張圖片,下面是動(dòng)態(tài)生成的問題。代碼層面對(duì)于此設(shè)計(jì)做了很細(xì)致的抽象。突然產(chǎn)品提出了某一個(gè)Job的圖片有特別,要求顯示10張圖片,就對(duì)抽象的圖片部分做了if-else的處理……
無用代碼,廢棄的接口沒有標(biāo)明
代碼腐化的原因
沒有代碼會(huì)是init commit的時(shí)候就開始腐化的,腐化都是循序漸進(jìn)的,要一個(gè)過程。我總結(jié)了一些代碼腐化的原因: