讀代碼整潔之道
本文關(guān)鍵詞:代碼整潔之道,由筆耕文化傳播整理發(fā)布。
現(xiàn)在的軟件系統(tǒng)開發(fā)難度主要在于其復(fù)雜度和規(guī)模,客戶需求也不再像Winston Royce瀑布模型期望那樣在系統(tǒng)編碼前完成所有的設(shè)計(jì)滿足用戶軟件需求。在這個(gè)信息爆炸技術(shù)日新月異的時(shí)代,需求總是在不停的變化,隨之在2001年業(yè)界17位大牛聚集在美國(guó)猶他州的滑雪勝地雪鳥(Snowbird)雪場(chǎng),提出了“Agile”(敏捷)軟件開發(fā)價(jià)值觀,并在他們的努力推動(dòng)下,開始在業(yè)界流行起來(lái)。在《代碼整潔之道》(Clean Code),提出一種軟件質(zhì)量,可持續(xù)開發(fā)不僅在于項(xiàng)目架構(gòu)設(shè)計(jì),還與代碼質(zhì)量密切相關(guān),代碼的整潔度和質(zhì)量成正比,一份整潔的代碼在質(zhì)量上是可靠的,為團(tuán)隊(duì)開發(fā),后期維護(hù),重構(gòu)奠定了良好的基礎(chǔ)。在這本書中作者提出了注重實(shí)際開發(fā)實(shí)踐的細(xì)節(jié),而不是站在空洞的理論來(lái)談?wù)撜麧嵵馈?/p>
什么是整潔代碼?不同的人會(huì)站在不同的角度闡述不同的說(shuō)法。而我最喜歡的是Grady Booch(《面向?qū)ο蠓治雠c設(shè)計(jì)》作者)闡述:
“整潔的代碼簡(jiǎn)單直接。整潔的代碼如同優(yōu)美的散文。整潔的代碼從不隱藏設(shè)計(jì)者的意圖,充滿了干凈利落的抽象和直截了當(dāng)?shù)目刂普Z(yǔ)句。”
整潔的代碼就是一種簡(jiǎn)約(簡(jiǎn)單而不過(guò)于太簡(jiǎn)單)的設(shè)計(jì),閱讀代碼的人能很清晰的明白這里在干什么,而不是隱澀難懂,整潔的代碼讀起來(lái)讓人感覺到就像閱讀散文-藝術(shù)的沉淀,作者是精心在意締造出來(lái)。
一:命名
命名包括變量、函數(shù)、參數(shù),類等,一個(gè)好的命名能夠很好的表述其所承載的業(yè)務(wù),從命名上就已經(jīng)很好的答復(fù)了為什么存在,做了什么事,應(yīng)該怎么用等的大部分的問(wèn)題,閱讀者看到它的時(shí)候不必去深究其實(shí)現(xiàn)細(xì)節(jié),一切都在命名上一目了然。一個(gè)好的命名必須是名副其實(shí),不存在歧義(雙關(guān)語(yǔ)或常見屬于沖突),直接了當(dāng)(否定語(yǔ)句或者誤導(dǎo)性命名)。
二:函數(shù):
從匯編/C時(shí)代開始的到現(xiàn)在函數(shù)一直都存在與我們開發(fā)中不可或缺的一部分,結(jié)構(gòu)化組織,重用.作為函數(shù)式語(yǔ)言的一等公民,所有程序的第一組代碼。
三:注釋、格式:
并不是寫出完備的注釋就是好的開發(fā)人員,如果代碼清晰的表述自己意圖,那么注釋反而多余。在《重構(gòu)-改善現(xiàn)有代碼之道》中Martin Fowler指出多余的注釋是一種代碼壞味道。就是好的注釋隨著項(xiàng)目的維護(hù)不斷的重構(gòu)很多時(shí)候也會(huì)變得不那么適應(yīng),而我們很少會(huì)去主動(dòng)維護(hù)。再則誤導(dǎo)性的注釋更為使用者所憎恨。當(dāng)然有時(shí)我們也得使用注釋,注釋并不是萬(wàn)惡的,當(dāng)我們沒法用代碼來(lái)描述自己的時(shí)候,我們需要注釋去描述意圖;多余有副作用的代碼給使用者提供警告注釋。TODO開發(fā)時(shí)進(jìn)度控制,比如你在進(jìn)行較大規(guī)模領(lǐng)域重構(gòu),目前有些邏輯不再適應(yīng),不那么自然,而對(duì)它的重構(gòu)還在任務(wù)列表最后,你可以選擇標(biāo)注在TODO中,最后完成從ToDoList中去掉每一個(gè)TODO任務(wù)。
良好的代碼格式,會(huì)使得我們閱讀更容易,一套共同的格式會(huì)讓我們查找理解更快速。每個(gè)團(tuán)隊(duì)都應(yīng)該遵循一套固定的代碼格式規(guī)范,整個(gè)軟件系統(tǒng)的統(tǒng)風(fēng)格統(tǒng)一,而不是各自為政各成一體。
四:對(duì)象和數(shù)據(jù)結(jié)構(gòu):
數(shù)據(jù)結(jié)構(gòu)指的就是數(shù)據(jù)的載體,暴露數(shù)據(jù),而幾乎沒有有意義的行為的貧血類。最常見的應(yīng)用在分布式服務(wù),以wcf,webservice,reset之類的分布式服務(wù)中不可或缺的數(shù)據(jù)傳輸對(duì)象(DTO)模式,DTO(Request/Response)就是一個(gè)很典型的數(shù)據(jù)載體,只存在簡(jiǎn)單的get,set屬性,并且更傾向于作為值對(duì)象存在。而對(duì)象則剛好相反作為面向?qū)ο蟮漠a(chǎn)物,必須封裝隱藏?cái)?shù)據(jù),而暴露出行為接口,DDD中領(lǐng)域模型傾向于對(duì)象不僅在數(shù)據(jù)更多暴露行為操作自己或者關(guān)聯(lián)狀態(tài)。
數(shù)據(jù)結(jié)構(gòu)和對(duì)象之間看是細(xì)微的差別卻導(dǎo)致了不同的本質(zhì)區(qū)別:使用數(shù)據(jù)結(jié)構(gòu)的代碼便于在不改動(dòng)現(xiàn)在數(shù)據(jù)結(jié)構(gòu)的前提下添加新的行為(函數(shù)),面向?qū)ο蟠a則便于不改動(dòng)現(xiàn) 有函數(shù)的前提下添加新的類。換句話說(shuō)就是數(shù)據(jù)結(jié)構(gòu)難以添加新的的數(shù)據(jù)類型,因?yàn)樾枰膭?dòng)所有函數(shù),面向?qū)ο蟮拇a則難以添加新的函數(shù),因?yàn)樾枰薷乃械念。在任何一個(gè)復(fù)雜的系統(tǒng)都會(huì)同時(shí)存在數(shù)據(jù)結(jié)構(gòu)和對(duì)象,我們需要判斷的是我們需要的是需要添加的新的數(shù)據(jù)類型還是新的行為函數(shù)。
隱藏作為面向?qū)ο笾饕匦灾械淖钪匾匦,封裝隱藏是面向?qū)ο笾凶钪匾奶匦裕粋(gè)好的面向?qū)ο蟠a肯定是對(duì)對(duì)象的內(nèi)部細(xì)節(jié)做到很好的隱藏封裝,封裝過(guò)后才有是多態(tài),委派之類的。一個(gè)好的面向?qū)ο蟮拇a一定是具有很好的隱藏封裝,易于測(cè)試,不穩(wěn)定因素往往集中在一處很小或者固定的位置,不穩(wěn)定因素的變更不會(huì)導(dǎo)致更大面積的修改擴(kuò)散。
對(duì)象的隱藏要求:方法不應(yīng)和任何調(diào)用方法返回的對(duì)象操作,換句話之和朋友說(shuō)話,不和陌生人說(shuō)話(迪米特法則,或被譯為最小知識(shí)原則),比如:ctxt.getOptions().getSearchDir().getAbsolutePath(),就是迪米特法則的反例模式。
五:異常處理:
每個(gè)軟件系統(tǒng)都避不開異常處理,需要防止它搞亂我們的邏輯。
六:邊界:
在系統(tǒng)開發(fā)中不可能一切都得從零開始,自己寫所有的代碼,更好的方案是需要整合一些開源或者第三方的項(xiàng)目,為我所用。但是不能讓這些非自己的代碼滲侵中我們的代碼各處,有一些所以功能很強(qiáng)大的第三方產(chǎn)品,但不一定具有很好的抽象。很多時(shí)候我更寧愿花些時(shí)間抽象出我們自己所需要的接口在第三方類庫(kù)上外覆一層自己的抽象,這樣不僅便于TDD,因?yàn)槲覀兡軌蚝芎玫膭?chuàng)建偽對(duì)象,使的測(cè)試獨(dú)立不依賴外部資源,得到快速反饋;而且在設(shè)計(jì)上得到很好的擴(kuò)展,當(dāng)由于某些原因如第三方類庫(kù)不再能滿足業(yè)務(wù)需求,或者權(quán)益收費(fèi)等等,我們可以很好的切換底層而使得修改不會(huì)擴(kuò)散到系統(tǒng)各處。外覆類也是處理遺留代碼帶入測(cè)試容器的一種很好實(shí)踐。
七:單元測(cè)試:
TDD中測(cè)試代碼在往往和產(chǎn)品代碼差不多,在系統(tǒng)中占據(jù)一半的代碼量,不好的測(cè)試代碼也可能拖累項(xiàng)目的開發(fā)。整潔的測(cè)試代碼應(yīng)該是遵循first原則的:
八:類:
面向?qū)ο蟮南嗨菩袨榈某橄,函?shù)代碼塊的組織形式,在面向?qū)ο笾形覀兊能浖到y(tǒng)是由眾多的類和類之間的交互協(xié)作完成了。面向?qū)ο筇卣鳎悍庋b,繼承,多態(tài)度,委派。一個(gè)設(shè)計(jì)良好的類該是具有良好的封裝,站在使用者的調(diào)度考慮那些是使用接口,那些是內(nèi)部細(xì)節(jié);這是面向?qū)ο笞钪饕奶卣,但是有時(shí)會(huì)與測(cè)試沖突,可以適當(dāng)?shù)姆砰_并僅限于于測(cè)試調(diào)用。繼承和多態(tài)在面向?qū)ο笾锌梢詫?shí)現(xiàn)重用,但我更傾向于繼承不是為了重用,而是隔離變化;大量的濫用繼承不干凈的繼承體系將會(huì)導(dǎo)致龐大的繼承體系,繼承體系中眾多職責(zé)重復(fù)在各個(gè)同級(jí)派生類,理想的繼承應(yīng)該是滿足里氏替換原則(LSP:每個(gè)父類出現(xiàn)的地方都應(yīng)該可以被派生類所替換,并且能正確的工作);面oo第二原則組合優(yōu)先。而委派則是一個(gè)類把部分功能委派給其他類來(lái)完成,體現(xiàn)類之間的協(xié)作,類似組合。
九:并發(fā)編程:
并發(fā)是一種時(shí)間(When)和目的(What)的解耦,提供應(yīng)用程序的吞吐量,提高cpu利用率;但是并發(fā)編碼不是那么容易,再加上臨界資源競(jìng)爭(zhēng)死鎖。在并發(fā)編程的時(shí)候我們必須盡量遵守一些原則:
更多關(guān)于簡(jiǎn)單設(shè)計(jì),迭進(jìn),逐步編程代碼,,壞味道,并發(fā)示例請(qǐng)參見代碼整潔之道。
本文關(guān)鍵詞:代碼整潔之道,由筆耕文化傳播整理發(fā)布。
本文編號(hào):142216
本文鏈接:http://www.sikaile.net/wenshubaike/mishujinen/142216.html