读《代码不朽:编写可维护软件的10大要则》C# 版
這本書特別針對沒有接受過計算機(jī)科學(xué)或軟件工程專業(yè)學(xué)習(xí)的軟件開發(fā)人員,這類人員除了熟悉所用語言語法和語義之外,很少接受其他專業(yè)培訓(xùn),對軟件工程中的一些概念理解欠缺。軟件設(shè)計方面考慮較少。如果要成為一個專業(yè)的程序員,就需要學(xué)習(xí)已形成工業(yè)化的軟件構(gòu)建方式。
可維護(hù)性解釋
這本書解釋了可維護(hù)軟件中的“維護(hù)”的意思:可維護(hù)性是軟件質(zhì)量的一個標(biāo)準(zhǔn),代表一個系統(tǒng)可被修改的難易程度。所以它是面向程序員的,假設(shè)兩個軟件完成相同的功能,但一個軟件的源碼,讓其他人或者一段時間之后的自己,很難理解,更不用提修改了,就說明這個軟件的可維護(hù)性比另一個差。軟件維護(hù)有4種方式:發(fā)現(xiàn)并糾正bug(糾正性維護(hù));適應(yīng)操作系統(tǒng)或運(yùn)行環(huán)境的改變(適應(yīng)性維護(hù));根據(jù)需求增加新的功能(完善性維護(hù));改進(jìn)代碼質(zhì)量預(yù)防bug產(chǎn)生(預(yù)防性維護(hù))。
三個基本理論
本書提供了10條可以實現(xiàn)高可維護(hù)性的指導(dǎo)原則,這些原則背后有三個理論:
1、堅持簡單的原則最有助于提高可維護(hù)性
2、可維護(hù)性不是項目開發(fā)完后才去考慮的,而應(yīng)該是在項目開發(fā)的一開始就加以考慮。每個人的貢獻(xiàn)都應(yīng)當(dāng)計算在內(nèi)
3、不同原則的違例會帶來不同的影響,有些嚴(yán)重程度甚至于他。一個軟件系統(tǒng)越遵守原則,可維護(hù)性越高。
?
對10大要則的理解
按照從小到大,從細(xì)微到宏觀的層次,這本書提取了編寫可維護(hù)軟件中10大編程原則,小到程序開發(fā)者應(yīng)當(dāng)時刻注意的代碼規(guī)范,大到系統(tǒng)架構(gòu)師應(yīng)該考慮的系統(tǒng)重構(gòu)、組件和及接口的設(shè)計準(zhǔn)則。
編寫短小的代碼單元
代碼單元即面向?qū)ο缶幊汤锏姆椒ɑ蚝瘮?shù)。這個原則要求每個函數(shù)的長度不應(yīng)超過15行。
動機(jī)
小的函數(shù)的好處?作者提出,小的函數(shù)容易重用,因為一個巨型的方法會包含很多細(xì)節(jié),導(dǎo)致很難有一模一樣的場景使用這個方法。作者提出,小的方法更易理解和進(jìn)行單元測試。若超過15行,則意味著方法可以被拆分了。
如何使用本原則
拆分重構(gòu)的方式有提取方法和將方法替換為方法對象。
提取方法很容易理解,即從一個函數(shù)中提取一段代碼,寫成一個新的方法。但如果提取方法時發(fā)現(xiàn),這個方法訪問了很多局部變量,如果都作為新方法的參數(shù)的話,勢必會導(dǎo)致參數(shù)列表過長。還有返回值的問題,如果這個方法會產(chǎn)生不止一個結(jié)果變量。一個重構(gòu)技巧是將這個方法替換成一個方法對象,將不同的局部變量和結(jié)果變量作為類的成員,然后調(diào)用類方法。
編寫簡單的代碼單元
這里的“簡單”體現(xiàn)代碼單元的分支點,所以這個原則可量化為:限制每個代碼單元分支點的數(shù)量不超過4個。C# 中常見的分支點代碼就是if和switch語句。
動機(jī)
讓代碼單元保持簡單基于兩個原因,一是簡單的代碼更容易修改,二是簡單的代碼更容易測試,分支點過多,意味著要有更多的測試用例。
如何使用本原則
復(fù)雜的代碼單元可能是因為其中包含很多互不相關(guān)的代碼塊,這種情況可以采用“提取方法”
若是其它復(fù)雜的情況,比如碰到鏈?zhǔn)降臈l件語句,如下判斷國旗的語句:
第一種方法是引入Map數(shù)據(jù)結(jié)構(gòu),將國家映射到指定的FLAG對象上;
第二種方法是使用“使用多態(tài)來代替條件判斷”,實現(xiàn)同一個接口,代表廣泛的國旗類型,然后為每個國家的國旗實現(xiàn)一個類。
再比如碰到嵌套的條件語句,為了使代碼簡單,可以使用“使用衛(wèi)語句來代替嵌套的條件語句”的重構(gòu)技巧,即標(biāo)識出各種獨(dú)立的情況,并插入return語句來代替嵌套式的條件語句。
例如
可以改寫成
if(...) {//TODO CASE1return; } if(...) {//TODO CASE2return; } if(...) {//TODO CASE3return; }可以看到分支點并未減少,然后可以再用“提取方法”減少復(fù)雜度。
不寫重復(fù)代碼
對重復(fù)代碼的定義是,一段至少6行都相同的代碼。
動機(jī)
如果復(fù)制代碼,相同的代碼出現(xiàn)在不同的地方,不利于源碼的定位;如果需要修改的地方正是重復(fù)的代碼,意味著要做很多重復(fù)性的工作,而且容易出錯。
如何使用本原則
首先想到的是提取方法;但若是一個方法是另一個類的私有方法怎么辦?這時應(yīng)當(dāng)將提取的方法放到一個工具類中。
如果重復(fù)代碼(6行以上完全相同)已不存在,但代碼相似,具有相同的邏輯,這時應(yīng)該考慮提取父類。
保持代碼單元的接口簡單
限制每個代碼單元的參數(shù)不能超過4個。
動機(jī)
較少的接口參數(shù)能夠保持簡單的上下文,易于重用、理解和修改。
如何使用本原則
將多個參數(shù)包裝成對象,比如輸入坐標(biāo)參數(shù),x與y,可以包裝成一個點對象。
使用“使用方法對象替換方法”的重構(gòu)技巧,此處和前面有重合。
分離模塊之間的關(guān)注點
模塊對應(yīng)類的概念。
實際上就是要求類要保持小的體積,不要過大過復(fù)雜。
動機(jī)
小的體積的類帶來了類之間的松耦合,松耦合意味著類能更靈活的適應(yīng)將來的變化。如果一個類做了很多事情,其耦合度會越來越緊,積攢大量代碼,導(dǎo)致代碼很難閱讀和修改。
如何使用本原則
第一種方法:根據(jù)功能將大類拆分為很小的類。一個類一開始可能很小,只是實現(xiàn)單一功能,但都不可避免負(fù)責(zé)越來越多的職責(zé),當(dāng)意識到這個類承擔(dān)了不止一個職責(zé)時,就應(yīng)該將這個類進(jìn)行拆分。
第二種方法:提取一個接口,實現(xiàn)松耦合。比如一開始為一臺相機(jī)設(shè)計了簡單的相機(jī)類,只具備拍照,閃光燈打開和關(guān)閉3個方法。后來這個類的使用擴(kuò)展到新的移動設(shè)備上,增加了定時功能。這時類變大,而且只有一個類,還需要檢查舊設(shè)備上的代碼有沒有受影響。為了降低耦合度,可以使用一個接口,它只定義所有相機(jī)都需要實現(xiàn)的功能。
第三種方法:使用第三方庫和框架來替代自定義的實現(xiàn)。
架構(gòu)組件松耦合
組件是比模塊(類)更高一層的單元,設(shè)計到系統(tǒng)的架構(gòu)。此原則要求盡可能減少當(dāng)前模塊暴露給(例如,被調(diào)用)其它組件中模塊的相關(guān)代碼。
動機(jī)
獨(dú)立的組件可以單獨(dú)進(jìn)行維護(hù),方便劃分職責(zé),讓測試變得容易。
如何使用本原則
使用抽象工廠設(shè)計模式,簡單的講就是類的實例不能直接被創(chuàng)建(new一個),而是通過工廠類的方法返回。這種通用的工廠接口背后,隱藏了具體產(chǎn)品的創(chuàng)建過程。在這個環(huán)境下,產(chǎn)品通常都不止有一種類型。如果要使用其中的邏輯,需要通過創(chuàng)建通用的工廠對象調(diào)用類方法成員。
注:抽象工廠不同于工廠模式,簡單理解就是抽象工廠的類型不止一個,所以產(chǎn)品至少有兩個。
保持架構(gòu)組件之間的平衡
保持源代碼中的組件數(shù)量接近于9。
動機(jī)
好的組件平衡讓查找和分析代碼更容易,提供清晰的功能邊界,分離維護(hù)職責(zé)。
如何使用本原則
軟件系統(tǒng)的開發(fā)有兩種組織模式:
基于功能領(lǐng)域劃分的系統(tǒng):好處是可以從高層功能的角度來分析代碼,壞處是技術(shù)人員需要了解多個技術(shù)棧
基于技術(shù)劃分的系統(tǒng):根據(jù)技術(shù)專長來劃分,可能會有前端,后端,接口、日志等組件。
軟件架構(gòu)師需要選擇如何組合功能的合適原則。明確系統(tǒng)的領(lǐng)域并堅持下去。
保持小規(guī)模代碼庫
動機(jī)
大型系統(tǒng)更加難以維護(hù),易出現(xiàn)更密集的缺陷,以大型代碼庫為目標(biāo)的項目更容易失敗。
如何使用本原則
功能層面:控制需求蔓延,功能標(biāo)準(zhǔn)化
技術(shù)層面:不要復(fù)制黏貼代碼,重構(gòu)代碼,使用第三方庫和框架(這同樣是前面提到的準(zhǔn)則)
自動化開發(fā)部署和測試
測試包含單元測試、集成測試、端對端測試、回歸測試、驗收測試。不同類型的測試需要不同的自動化框架。
動機(jī)
自動化測試可重復(fù),有效率;自動化測試?yán)锏臄嘌?#xff08;assert)可以充當(dāng)注釋;通過編寫測試可以反過來推促編寫可測試的代碼,提高代碼質(zhì)量。
如何使用本原則
使編寫單元測試成為每個開發(fā)人員的職責(zé),比如使用C#中的單元測試框架Xunit.net。
使用像moq或者mocking這樣的技術(shù)。stub即測試樁。需要測試樁是因為有些影響測試結(jié)果的測試條件是易變、無法統(tǒng)一的。比如拍照,兩次拍攝的環(huán)境不可能完全相同,結(jié)果無法驗證,所以需要一個假對象,即測試樁。mocking(模擬)是因為測試中某些函數(shù)是沉默的,不包含任何結(jié)果,可以在函數(shù)中添加計數(shù)來驗證函數(shù)執(zhí)行過。mock技術(shù)有自動化的框架。
建議生產(chǎn)代碼和測試代碼一比一,提高覆蓋率。
編寫簡潔的代碼
給程序開發(fā)人員總結(jié)了7條“童子軍軍規(guī)”:
1、編寫單元級別的良好代碼
2、不要編寫不好的注釋
3、不要注釋代碼
4、不要保留廢棄代碼
注:包括3,同時還有其它的形式,比如不可能執(zhí)行到的代碼、無用的私有方法、注釋中的代碼
5、不要使用過長的標(biāo)識符名稱
6、不要使用魔術(shù)常量
注:指表達(dá)式中突兀出現(xiàn)的數(shù)字,應(yīng)該先定義。
7、不要使用未正確處理的異常
注:包括以下情況,捕獲異常卻不處理(catch為空),直接捕獲通用異常(比如Exception異常,這些異常不會提供觸發(fā)失敗的狀態(tài)或事件信息,所以沒意義),將異常信息展示給終端用戶(避免用戶困惑或暴露信息,應(yīng)該先轉(zhuǎn)換為通用信息)
原文地址:https://www.qcloud.com/community/article/545562
.NET社區(qū)新聞,深度好文,微信中搜索dotNET跨平臺或掃描二維碼關(guān)注
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎勵來咯,堅持創(chuàng)作打卡瓜分現(xiàn)金大獎總結(jié)
以上是生活随笔為你收集整理的读《代码不朽:编写可维护软件的10大要则》C# 版的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 用 docker secrets 保存
- 下一篇: 通过Roslyn构建自己的C#脚本(更新