經(jīng)常能聽到一些開發(fā)人員抱怨其他人寫的代碼難以理解抑月,這時(shí)树叽,我常常會(huì)想,如果不告訴那些開發(fā)人員谦絮,而直接讓他們看我寫的代碼题诵,他們也一定會(huì)有同樣的感覺吧,“這個(gè)人的代碼寫得真爛”层皱。似乎無論你的技術(shù)水平多么高超性锭,都很難寫出易讀的代碼來。
代碼本來就是難以閱讀的
我相信很多程序員一定都讀過《代碼大全》叫胖,《Effective Java》,《設(shè)計(jì)模式》等等介紹如何寫出更優(yōu)秀代碼的書籍吧草冈。而程序員們?cè)趯懘a時(shí),也確實(shí)遵循著書中的那些最佳實(shí)踐臭家,努力地去寫出高質(zhì)量的代碼疲陕。但當(dāng)他們編寫更復(fù)雜一些的程序時(shí),所寫出的代碼就會(huì)變得越來越難以閱讀钉赁,即使加上了很多注釋蹄殃,這種情況也不會(huì)得到明顯的改善。
這是程序員的問題嗎你踩?不诅岩,至少我認(rèn)為不是這樣的,因?yàn)?strong>代碼并不是自然語言带膜,它本來就是難以閱讀的吩谦,況且代碼是否易讀不僅與代碼本身有關(guān),還與閱讀代碼的人對(duì)系統(tǒng)的理解程度膝藕,以及他們自身的技術(shù)水平有關(guān)式廷,更何況,我們寫代碼的目的本身也不是為了讓它更容易閱讀芭挽。
我很喜歡拿寫作與寫代碼進(jìn)行比較滑废,當(dāng)我們寫完一篇文章后蝗肪,我們常常會(huì)反復(fù)修改,直到它變得流暢易讀為止蠕趁,因?yàn)橹挥羞@樣薛闪,讀者才能明白你的文章所要表達(dá)的內(nèi)容。而對(duì)于編碼而言卻不是這樣俺陋,我們寫代碼是為了實(shí)現(xiàn)功能豁延、解決問題,因此我們一般都會(huì)通過測(cè)試來進(jìn)行驗(yàn)證腊状,但極少會(huì)為了讓它變得易讀诱咏,而去修改它。與代碼的準(zhǔn)確性相比寿酌,顯然代碼是否易讀變得次要了很多胰苏。
如何讓你的代碼更易閱讀
那么是否有一些簡(jiǎn)單可行的方法讓你的代碼易讀或更易于維護(hù)呢?有醇疼,但前提是我們可能需要暫時(shí)跳出代碼本身才能找到那些行之有效的方法硕并。
推行模式(Patterns)而非建立規(guī)范
我見過很多項(xiàng)目團(tuán)隊(duì),在開始編碼之前秧荆,都會(huì)相應(yīng)地制定一整套代碼規(guī)范(多的達(dá)到幾百條)倔毙,但隨著項(xiàng)目的深入,我們卻發(fā)現(xiàn)乙濒,代碼的質(zhì)量還是失控了陕赃。雖然表面上,每個(gè)人都在遵守著那些代碼規(guī)范颁股,但其實(shí)他們的思維卻沒有得到很好的統(tǒng)一么库。想象一下,在一個(gè)閱兵式上甘有,一隊(duì)身著統(tǒng)一制服的士兵诉儒,他們每個(gè)人的動(dòng)作都非常標(biāo)準(zhǔn),但他們都在按照自己的節(jié)奏和步點(diǎn)作著動(dòng)作亏掀,這場(chǎng)面是不是有些滑稽呢忱反?
我所推薦的方法是推行模式(Patterns),在項(xiàng)目進(jìn)入開發(fā)階段前滤愕,就將那些開發(fā)過程中會(huì)遇到的相同類型的問題進(jìn)行分類温算,并為它們創(chuàng)建模式——標(biāo)準(zhǔn)處理方式,比如:
使用什么結(jié)構(gòu)來表示數(shù)據(jù)本身
采用哪種機(jī)制來進(jìn)行數(shù)據(jù)加工
如何進(jìn)行統(tǒng)一的錯(cuò)誤的處理
會(huì)話的管理及使用策略
哪些地方需要記錄日志
包與方法的命名 Name Convention
.......
在項(xiàng)目的進(jìn)行中间影,我們也需要不斷地去識(shí)別那些帶有共性的問題注竿,并為它們建立新的模式,然后再推廣到項(xiàng)目中。我發(fā)現(xiàn)巩割,比起那些僵硬的規(guī)范胰丁,程序員們更樂意去理解這些模式,并把它們視作為項(xiàng)目中的最佳實(shí)踐喂分,在開發(fā)中加以遵守。
深入理解并尊重你所使用的應(yīng)用框架
如果你沒有熟練掌握駕駛技術(shù)机蔗,或者對(duì)所駕駛的車不熟悉的話蒲祈,你將很難體會(huì)到駕駛所能帶給你的樂趣。而編程和駕駛一樣萝嘁,你需要同時(shí)掌握所使用的編程語言和所在系統(tǒng)的應(yīng)用框架梆掸,才能非常自如地進(jìn)行開發(fā)。
每個(gè)公司或項(xiàng)目在開發(fā)一個(gè)產(chǎn)品時(shí)牙言,往往都會(huì)建立或使用一套自己的框架酸钦,它們一般都是基于Spring,Struts這樣的流行框架之上的咱枉。在大多數(shù)情況下卑硫,構(gòu)建應(yīng)用框架的目的并不是為了給開發(fā)者提供一個(gè)比Spring更強(qiáng)大的框架,恰恰相反蚕断,它們?cè)诖蠖鄶?shù)時(shí)候欢伏,是為了限制框架的使用,而使整個(gè)系統(tǒng)變得更加標(biāo)準(zhǔn)且易于維護(hù)亿乳。你需要理解這一點(diǎn)硝拧,并在開發(fā)時(shí)盡可能使用你系統(tǒng)的應(yīng)用框架所提供的標(biāo)準(zhǔn)方法。如果框架無法滿足你的某些需求時(shí)葛假,嘗試與架構(gòu)師溝通障陶,是否需要對(duì)應(yīng)用框架進(jìn)行擴(kuò)展,或找出合理的解決方案聊训。如果你沒有這么做抱究,而是跳過應(yīng)用框架,直接使用那些更底層的框架方法或API魔眨,將會(huì)給系統(tǒng)帶來壞味道媳维,而這將引發(fā)連鎖反應(yīng),更多壞味道會(huì)接踵而至遏暴,導(dǎo)致整個(gè)項(xiàng)目代碼質(zhì)量的失控侄刽。
當(dāng)然,要想深入理解你所使用的應(yīng)用框架也絕不是件容易的事朋凉,光靠那些開發(fā)指南和代碼示例是不夠的州丹,你還可以通過閱讀源碼,以及大量的實(shí)踐去深入地理解它們,訓(xùn)練出最有效使用它們的感覺墓毒。最終當(dāng)你進(jìn)行開發(fā)時(shí)吓揪,那些正確且標(biāo)準(zhǔn)的應(yīng)用框架使用方法會(huì)非常自然地出現(xiàn)在你所敲擊的每一行代碼中。
不要使用過多的所謂技巧
當(dāng)我們的技術(shù)水平有所提升后所计,會(huì)不自覺地想著去使用一些不太常見的技巧柠辞。使用這些代碼往往能夠以非常Cool的方式快速解決問題,但如果這樣的代碼過多主胧,便會(huì)給系統(tǒng)帶來難以維護(hù)的問題叭首。
程序員們經(jīng)常使用的另一個(gè)所謂技巧便是“可配置”,他們經(jīng)常會(huì)在與用戶討論需求時(shí)踪栋,推銷他們可配置的點(diǎn)子焙格,好像只要做到了這一點(diǎn),他們所開發(fā)出來的功能就能勝人一籌似得夷都,而結(jié)果往往是眷唉,那些所謂的可配置功能,用戶極少會(huì)去使用囤官,而為了這些可配置冬阳,卻大大增加了系統(tǒng)的復(fù)雜性,而系統(tǒng)的性能也因此變得低下党饮。
因此摩泪,我總是不鼓勵(lì)程序員們?nèi)戇^多Hack Code或?yàn)榱艘肽切┎槐匾目膳渲霉δ芏拐麄€(gè)系統(tǒng)過于復(fù)雜。
Design Review與Code Reivew都很重要
流程有時(shí)也能幫助我們寫出更好的代碼劫谅,Design Review和Code Review就是其中非常重要的兩個(gè)见坑。Design Review能夠幫助我們?cè)谳^早的階段就發(fā)現(xiàn)那些潛在的設(shè)計(jì)問題,并加以糾正捏检,這往往能發(fā)揮事半功倍的效果荞驴。在實(shí)踐中,我總是會(huì)建議采用最簡(jiǎn)單的設(shè)計(jì)文檔模板贯城,并讓開發(fā)人員寫下真正體現(xiàn)他們所做程序設(shè)計(jì)的內(nèi)容熊楼,這一方面可以避免因過多Paper Work導(dǎo)致的效率降低,同時(shí)設(shè)計(jì)文檔中只包含那些真正重要的東西能犯,也會(huì)使文檔本身變得更易于維護(hù)鲫骗。
而在程序員開發(fā)完成后,由另一位較資深的程序員來進(jìn)行Code Review也能很好地識(shí)別出代碼中的一些疏漏踩晶,而更有益的是执泰,通過這樣的Code Reivew能夠形成一種非常有效的反饋機(jī)制,幫助那些初級(jí)程序員快速成長(zhǎng)渡蜻。
讓你的架構(gòu)師忙起來
團(tuán)隊(duì)中有著不同的角色术吝,項(xiàng)目經(jīng)理计济、產(chǎn)品經(jīng)理、業(yè)務(wù)分析人員排苍、架構(gòu)師沦寂、資深開發(fā)工程師和普通開發(fā)工程師。而其中架構(gòu)師作為最技術(shù)的角色顯得尤為關(guān)鍵淘衙,他甚至可以成為一個(gè)項(xiàng)目成功與否的關(guān)鍵先生传藏。
架構(gòu)師應(yīng)該承擔(dān)起應(yīng)用架構(gòu)、技術(shù)風(fēng)險(xiǎn)識(shí)別彤守、指導(dǎo)團(tuán)隊(duì)開發(fā)等等很多工作漩氨,因?yàn)?strong>在真實(shí)的項(xiàng)目場(chǎng)景中,我們隨時(shí)面臨著架構(gòu)方面的問題遗增,他不應(yīng)僅僅出現(xiàn)在項(xiàng)目的開始階段,而應(yīng)該服務(wù)于整個(gè)項(xiàng)目生命周期中款青,在需要解決棘手的技術(shù)問題時(shí)做修,挺身而出,快速而準(zhǔn)確地解決問題抡草。但遺憾的是我們經(jīng)呈渭埃看到架構(gòu)師在團(tuán)隊(duì)中只起到了顧問的作用,他們甚至不親手寫一行代碼康震,只是給出一些系統(tǒng)部署燎含、核心設(shè)計(jì)方面的建議后,就早早地退出了項(xiàng)目腿短。
讓你團(tuán)隊(duì)中的架構(gòu)師忙起來屏箍,同樣對(duì)你團(tuán)隊(duì)成員的成長(zhǎng)有很大的幫助,特別對(duì)于那些年輕程序員橘忱,通過理解架構(gòu)師給出的技術(shù)解決方案赴魁,以及閱讀他們所寫的代碼,都能幫助他們提高編程能力钝诚,而更重要的是颖御,他們將慢慢學(xué)會(huì)像那些技術(shù)專家一樣進(jìn)行思考。
小比大好
最后讓我們回到編寫代碼本身上來凝颇,在文章的一開頭我就提到潘拱,對(duì)于那些復(fù)雜的程序邏輯,你很難寫出易讀的代碼拧略,那真的是一點(diǎn)辦法也沒有嗎芦岂?我所能給出的唯一建議便是“小比大好”。當(dāng)一段邏輯變得比較長(zhǎng)時(shí)垫蛆,就將它拿出盔腔,起一個(gè)與這段代碼功能相對(duì)應(yīng)的名字,封裝成一個(gè)新的方法。
這聽起來非常顯而易見弛随,但我告訴你大部分程序員并不會(huì)那么做瓢喉,因?yàn)樗麄兯坪踝裱硪粋€(gè)原則:只有當(dāng)一段邏輯會(huì)被多次調(diào)用(大于等于2次)時(shí),才為它創(chuàng)建一個(gè)新的方法舀透。所以栓票,我們便看到了包含幾百行代碼的方法。這個(gè)原則本身并沒有錯(cuò)愕够,但我們可以做適當(dāng)?shù)难a(bǔ)充走贪,除了在考慮復(fù)用性上可以拆分方法之外,我們也可以為了代碼的可讀性和可維護(hù)性去進(jìn)行拆分惑芭,這樣將大大改善一個(gè)大的邏輯段的易讀性坠狡。可能你又會(huì)問遂跟,如果這樣做了不是會(huì)讓代碼變得很散逃沿,到處都是方法嗎?我還是想說“小比大好”幻锁,就像我們現(xiàn)在修理汽車更多地是更換那些有問題的零件一樣凯亮,通過將邏輯拆分成更多小的部件,在維護(hù)時(shí)我們可以更方便地進(jìn)行替換從而降低開發(fā)成本以及因關(guān)聯(lián)性判斷不足帶來的風(fēng)險(xiǎn)哄尔。
雖然假消,我仍然無法寫出易讀的代碼,但通過對(duì)上面這些方法的實(shí)踐岭接,我卻能在大多數(shù)項(xiàng)目中寫出易于維護(hù)的代碼富拗,我想,這可能對(duì)于整個(gè)項(xiàng)目和團(tuán)隊(duì)來說鸣戴,才是更加重要的吧媒峡!
簡(jiǎn)書簽約作者:技匠,以上內(nèi)容歡迎大家分享到朋友圈/微博等葵擎。