提著代碼跑路了!
大家好,我是二哥呀!
今天在知乎上刷到一個問題,感覺還是挺有意思的:為什么程序員會有代碼能跑就不要動的觀點?

瀏覽量有 300 多萬,說明還是有挺多人關注的。我第一時間想到的答案是:人和代碼,有一個能跑就行!哈哈哈
舉個例子。
要得出 1+2+3+4,某程序員寫出了 A、B 兩行代碼:
A:1+2=2;
B:3+4=8;
運行?1+2+3+4?=?A+B=2+8=10
結果正確,皆大歡喜。
某天,新來的小二看到了代碼 A,破口大罵,于是怒發(fā)沖冠的修改了代碼 A:1+2=3;
然后由于實在是太困了,連續(xù)加班一個月,中間無休,代碼 B 小二沒看到,結果程序崩潰了:A+B=11 了!
于是小二因為這事被公司辭退了!
淺顯理解,歡迎指正:修改了某一行代碼,很可能會像蝴蝶效應一樣影響到其他代碼,而其他代碼可能并不在你的掌握之內(nèi),那么大廈將傾!
當然了,奔著學習成長的目的,我們程序員絕不能抱著這種“代碼能跑就不要動的心態(tài)”活下去,很可能到最后你只能是一名 CURD boy !
(注意,接下來不賣課哦,請放心把收藏給交一下)
每一個有責任心(代碼潔癖)的程序員都會去考慮重構的問題,重構代碼有很多好處:
后期修正 bug 更加容易 提高程序的可讀性 改進程序原有設計 更重要的是當你在小組討論會上,向同事展示代碼時不會覺得丟人。
當你接手了一個遺留工程,之前的開發(fā)人員早已不知去向,不管是要增加功能還是修正 bug,你都需要讀懂代碼,你能依靠的除了你堪比福爾摩斯的推理能力,就只有重構這把瑞士軍刀了。
但是,重構之前也需要做好心理準備。
不要破壞已有代碼。比如說你的一個修改可能導致 10000 元的商品被 1 元錢買走了,那最終你會吃不了兜著走。 重構有可能是個漫長的工作,假如領導問你今天干嘛了,你總不能一直說你在重構代碼,一次可以,兩次可以,三次可能領導覺得你在摸魚了。 你有沒有時間,日益逼近的 deadline 可能是壓垮你的最后一根稻草。
那,有沒有一些方法,能讓我們在享受重構的同時,避免這些風險呢?
答案當然是有的。
一、重構入門
1、格式化代碼
當你發(fā)現(xiàn)代碼縮進層次不齊,代碼塊中缺少{}等問題時,就需要考慮代碼格式化了,現(xiàn)在的 IDE 工具已經(jīng)對格式化提供了很好的支持。
在團隊開發(fā)中,為了保證開發(fā)代碼樣式統(tǒng)一,需要建立編碼規(guī)范。我們并不需要重頭建立編碼規(guī)范,可以在大廠的編碼規(guī)范基礎上進行定制,比如在 Java 領域可采用阿里、華為、Google Java Style Guide 等編碼規(guī)范。
2、注釋
在代碼開發(fā)中,好的注釋可以提高程序的可讀性,壞的注釋可能會畫蛇添足,甚至起反作用。作者提到好的注釋要做到和代碼相關、及時更新。很多時候,代碼剛開始編寫時,注釋和代碼是一致,后期因為間隔時間過長或其他人接手修改代碼,沒有對注釋及時修改,就會造成注釋和代碼漸行漸遠。
盡量減少不必要的注釋。如很多函數(shù)或者類,如果設計架構清晰,通過命名就能知道他們做什么,注釋不是必須的。還有一種情況是暫時不用的代碼,很多人會覺得以后會用到,會加個注釋,作者給出的建議是刪掉它,如果你將來真的用到了,可以到 git(一種代碼管理工具)的歷史記錄中查找。
對于邏輯混亂的代碼,如在循環(huán)中隨意使用 break,復雜的 if 語句嵌套等,你要做的是理清邏輯,重構代碼,而不是讓注釋替你補鍋。正如《重構》中提到的 “當你感覺需要撰寫注釋,請先嘗試重構,試著讓所有注釋都變得多余?!?/p>
3、刪除廢棄的代碼
隨著系統(tǒng)版本的不斷迭代,有一些函數(shù)或類不再使用后,我們應該將它及時刪除,否則隨著時間流逝,會造成代碼庫臃腫,程序可讀性變差。而且如果還發(fā)生人員的變動,慢慢會成為誰也不敢動的代碼,因為都不知道有啥用和在哪用到。
4、重新命名
就像我們?nèi)艘粯?,一個好名字對變量、常量、函數(shù)和類都很重要,一個好的名字會讓其他開發(fā)人員很容易明白其功能是什么。以下是命名的一些注意事項:
類和文件名使用名詞,但這個名詞要有意義,比如 Data、Information 就意義不明顯,不是好名字。 函數(shù)使用動詞或短語命名,比如 isReady hasName。 長名字 vs 無意義名字:在長名字和無意義名字中選擇時,請選擇長且有意義的名字,比如 java 語言中使用最廣的類庫 spring 中的一個命名是:SimpleBeanFactoryAwareAspectInstanceFactory。 命名法則:常見的有駝峰命名法(camelCase)和蛇形命名法(snake_case),比如文件名使用蛇形是 file_name,駝峰式 fileName。選擇一種,所有的命名都按照這個規(guī)則,并將其作為編碼規(guī)范的一部分,讓團隊成員都要遵守。
二、重構進階
1、模塊化重復的代碼
當你發(fā)現(xiàn)相同的代碼塊在三個地方都出現(xiàn)時,你就需要考慮重構代碼了。對于同一個類中重復的代碼塊,可使用提取方法(extract method:將重復代碼提取出單獨的函數(shù))來完成;對于一組相關類如父類、子類 A、子類 B 中的重復函數(shù),通過上移方法(pull method:將子類中的方法移入父類中)和模板方法(template method:父類方法定義模板,子類編寫不同實現(xiàn))來完成。
2、參數(shù)優(yōu)化
函數(shù)的形參中有一個是 boolean 類型,函數(shù)體根據(jù)該參數(shù)為 true 或者 false 執(zhí)行不同的代碼塊。這種方式會導致重構的另一個壞味道——大函數(shù)(big function)的形成,從而增加代碼的復雜性。重構方法是:去掉這個開關參數(shù),將函數(shù)拆分成兩個函數(shù)。
參數(shù)用于外界向函數(shù)體傳遞信息,好的做法是參數(shù)對于函數(shù)是只讀的。如果在函數(shù)內(nèi)修改參數(shù),會造成函數(shù)功能難以理解,如果函數(shù)內(nèi)多次修改參數(shù),這個函數(shù)會變成一座迷宮,重構方法是:將參數(shù)賦值給局部變量,對局部變量修改。
函數(shù)的參數(shù)最多有三個是合理的,超過三個就需要提高警惕了。重構方法是:根據(jù)邏輯拆分函數(shù);引入?yún)?shù)對象(parameter object:構造參數(shù)類,將原來傳遞的參數(shù)作為類的屬性,調用方傳入該類的一個對象)
3、去掉多余的變量
當定義的變量沒太多含義,而且沒有賦值操作,完全可以刪除。
優(yōu)化前:
double?basePrice?=?anOrder.basePrice();
return?(basePrice?>?1000);
優(yōu)化后:
return?(anOrder.basePrice()?>?1000);
4、每個變量只承擔一個責任
某個臨時變量被賦值超過一次,它既不是循環(huán)變量,也不被用于收集計算結果。如果它們被賦值超過一次,就意味著它們在函數(shù)中承擔了一個以上的職責。如果臨時變量承擔多個責任,它就應該被替換為多個臨時變量,每個變量只承擔一個責任。
重構方法:針對每次賦值,創(chuàng)造一個獨立、對應的臨時變量
5、不要讓條件變得復雜
我們都見過由 && || 構成的復雜的多行條件。復雜條件可讀性很差,調試和修改也很麻煩。
double?fetchSalary(double?money,?int?day)?{
??if(money>10000?&&?day>30?)?{
??????return?money*day/365*0.2;?
??}else?{
??????return?money*30.0/365*0.1;
??}
}
一個簡單的重構方式是:將這塊代碼抽取出來,變成一個單獨的判斷函數(shù)。
boolean?isHigherSalary(double?money,int?day){
???return?(money>10000?&&?day>30?);
}
三、老舊代碼的重構
在進行代碼重構時,需要考慮測試代碼是否能覆蓋重構的功能,如果沒有,需要增加測試用例覆蓋所做的修改,否則重構可能會破壞已有的功能。
只做必要的重構,如當需要修正 bug 或者增加新的功能,這種情況下,先為遺留代碼編寫測試用例,在理解的基礎上重構代碼,為代碼修改做好準備,然后進行代碼修改。
從這點上來說,你可以進行任何類型代碼的重構:一次只做一步重構,從小的容易的重構做起,并頻繁測試。
為了讓重構變得更容易,市面上提供了大量相關工具,如 pylint( Python 代碼分析工具)、Checkstyle、sonarlint(代碼規(guī)范工具)、Sonarqube(代碼質量管理的開源工具)

此外,你要保證你的測試用例跑的足夠快,否則你會沒有耐心等待測試運行結果,或者直接就不運行了。
理想情況下,程序在構建后部署到測試環(huán)境前,可以借助 CI/CD(持續(xù)集成/持續(xù)部署)工具實現(xiàn)代碼質量檢查、代碼樣式檢查、潛在 bug 監(jiān)測等模塊的自動化運行。
參照鏈接:https://www.zhihu.com/question/491132556/answer/2165148470
最近,簡單總結一下哈。
不要專門花費大量的時間去進行重構,利用小塊時間,每次只做一部分,只要保證代碼質量比之前有進步就可以了。
不要想著以后再做,這個以后很可能是永遠不,最終你將面對一系列可怕的遺留代碼,然后你就深刻理解了“出來混遲早是要還的”這句話的涵義。
那希望,這些重構大法能幫助到大家喲,這樣就不怕“被逼著”跑路了??

沒有什么使我停留——除了目的,縱然岸旁有玫瑰、有綠蔭、有寧靜的港灣,我是不系之舟。
推薦閱讀:
