經常能聽到一些開發人員抱怨其他人寫的代碼難以理解,這時,我常常會想,如果不告訴那些開發人員,而直接讓他們看我寫的代碼,他們也一定會有同樣的感覺吧,“這個人的代碼寫得真爛”。似乎無論你的技術水平多么高超,都很難寫出易讀的代碼來。
代碼本來就是難以閱讀的
我相信很多程序員一定都讀過《代碼大全》,《Effective Java》,《設計模式》等等介紹如何寫出更優秀代碼的書籍吧。而程序員們在寫代碼時,也確實遵循著書中的那些最佳實踐,努力地去寫出高質量的代碼。但當他們編寫更復雜一些的程序時,所寫出的代碼就會變得越來越難以閱讀,即使加上了很多注釋,這種情況也不會得到明顯的改善。
這是程序員的問題嗎?不,至少我認為不是這樣的,因為代碼并不是自然語言,它本來就是難以閱讀的,況且代碼是否易讀不僅與代碼本身有關,還與閱讀代碼的人對系統的理解程度,以及他們自身的技術水平有關,更何況,我們寫代碼的目的本身也不是為了讓它更容易閱讀。
我很喜歡拿寫作與寫代碼進行比較,當我們寫完一篇文章后,我們常常會反復修改,直到它變得流暢易讀為止,因為只有這樣,讀者才能明白你的文章所要表達的內容。而對于編碼而言卻不是這樣,我們寫代碼是為了實現功能、解決問題,因此我們一般都會通過測試來進行驗證,但極少會為了讓它變得易讀,而去修改它。與代碼的準確性相比,顯然代碼是否易讀變得次要了很多。
如何讓你的代碼更易閱讀
那么是否有一些簡單可行的方法讓你的代碼易讀或更易于維護呢?有,但前提是我們可能需要暫時跳出代碼本身才能找到那些行之有效的方法。
推行模式(Patterns)而非建立規范
我見過很多項目團隊,在開始編碼之前,都會相應地制定一整套代碼規范(多的達到幾百條),但隨著項目的深入,我們卻發現,代碼的質量還是失控了。雖然表面上,每個人都在遵守著那些代碼規范,但其實他們的思維卻沒有得到很好的統一。想象一下,在一個閱兵式上,一隊身著統一制服的士兵,他們每個人的動作都非常標準,但他們都在按照自己的節奏和步點作著動作,這場面是不是有些滑稽呢?
我所推薦的方法是推行模式(Patterns),在項目進入開發階段前,就將那些開發過程中會遇到的相同類型的問題進行分類,并為它們創建模式——標準處理方式,比如:
使用什么結構來表示數據本身
采用哪種機制來進行數據加工
如何進行統一的錯誤的處理
會話的管理及使用策略
哪些地方需要記錄日志
包與方法的命名 Name Convention
.......
在項目的進行中,我們也需要不斷地去識別那些帶有共性的問題,并為它們建立新的模式,然后再推廣到項目中。我發現,比起那些僵硬的規范,程序員們更樂意去理解這些模式,并把它們視作為項目中的最佳實踐,在開發中加以遵守。
深入理解并尊重你所使用的應用框架
如果你沒有熟練掌握駕駛技術,或者對所駕駛的車不熟悉的話,你將很難體會到駕駛所能帶給你的樂趣。而編程和駕駛一樣,你需要同時掌握所使用的編程語言和所在系統的應用框架,才能非常自如地進行開發。
每個公司或項目在開發一個產品時,往往都會建立或使用一套自己的框架,它們一般都是基于Spring,Struts這樣的流行框架之上的。在大多數情況下,構建應用框架的目的并不是為了給開發者提供一個比Spring更強大的框架,恰恰相反,它們在大多數時候,是為了限制框架的使用,而使整個系統變得更加標準且易于維護。你需要理解這一點,并在開發時盡可能使用你系統的應用框架所提供的標準方法。如果框架無法滿足你的某些需求時,嘗試與架構師溝通,是否需要對應用框架進行擴展,或找出合理的解決方案。如果你沒有這么做,而是跳過應用框架,直接使用那些更底層的框架方法或API,將會給系統帶來壞味道,而這將引發連鎖反應,更多壞味道會接踵而至,導致整個項目代碼質量的失控。
當然,要想深入理解你所使用的應用框架也絕不是件容易的事,光靠那些開發指南和代碼示例是不夠的,你還可以通過閱讀源碼,以及大量的實踐去深入地理解它們,訓練出最有效使用它們的感覺。最終當你進行開發時,那些正確且標準的應用框架使用方法會非常自然地出現在你所敲擊的每一行代碼中。
不要使用過多的所謂技巧
當我們的技術水平有所提升后,會不自覺地想著去使用一些不太常見的技巧。使用這些代碼往往能夠以非常Cool的方式快速解決問題,但如果這樣的代碼過多,便會給系統帶來難以維護的問題。
程序員們經常使用的另一個所謂技巧便是“可配置”,他們經常會在與用戶討論需求時,推銷他們可配置的點子,好像只要做到了這一點,他們所開發出來的功能就能勝人一籌似得,而結果往往是,那些所謂的可配置功能,用戶極少會去使用,而為了這些可配置,卻大大增加了系統的復雜性,而系統的性能也因此變得低下。
因此,我總是不鼓勵程序員們去寫過多Hack Code或為了引入那些不必要的可配置功能而使整個系統過于復雜。
Design Review與Code Reivew都很重要
流程有時也能幫助我們寫出更好的代碼,Design Review和Code Review就是其中非常重要的兩個。Design Review能夠幫助我們在較早的階段就發現那些潛在的設計問題,并加以糾正,這往往能發揮事半功倍的效果。在實踐中,我總是會建議采用最簡單的設計文檔模板,并讓開發人員寫下真正體現他們所做程序設計的內容,這一方面可以避免因過多Paper Work導致的效率降低,同時設計文檔中只包含那些真正重要的東西,也會使文檔本身變得更易于維護。
而在程序員開發完成后,由另一位較資深的程序員來進行Code Review也能很好地識別出代碼中的一些疏漏,而更有益的是,通過這樣的Code Reivew能夠形成一種非常有效的反饋機制,幫助那些初級程序員快速成長。
讓你的架構師忙起來
團隊中有著不同的角色,項目經理、產品經理、業務分析人員、架構師、資深開發工程師和普通開發工程師。而其中架構師作為最技術的角色顯得尤為關鍵,他甚至可以成為一個項目成功與否的關鍵先生。
架構師應該承擔起應用架構、技術風險識別、指導團隊開發等等很多工作,因為在真實的項目場景中,我們隨時面臨著架構方面的問題,他不應僅僅出現在項目的開始階段,而應該服務于整個項目生命周期中,在需要解決棘手的技術問題時,挺身而出,快速而準確地解決問題。但遺憾的是我們經??吹郊軜嫀熢趫F隊中只起到了顧問的作用,他們甚至不親手寫一行代碼,只是給出一些系統部署、核心設計方面的建議后,就早早地退出了項目。
讓你團隊中的架構師忙起來,同樣對你團隊成員的成長有很大的幫助,特別對于那些年輕程序員,通過理解架構師給出的技術解決方案,以及閱讀他們所寫的代碼,都能幫助他們提高編程能力,而更重要的是,他們將慢慢學會像那些技術專家一樣進行思考。
小比大好
最后讓我們回到編寫代碼本身上來,在文章的一開頭我就提到,對于那些復雜的程序邏輯,你很難寫出易讀的代碼,那真的是一點辦法也沒有嗎?我所能給出的唯一建議便是“小比大好”。當一段邏輯變得比較長時,就將它拿出,起一個與這段代碼功能相對應的名字,封裝成一個新的方法。
這聽起來非常顯而易見,但我告訴你大部分程序員并不會那么做,因為他們似乎遵循著另一個原則:只有當一段邏輯會被多次調用(大于等于2次)時,才為它創建一個新的方法。所以,我們便看到了包含幾百行代碼的方法。這個原則本身并沒有錯,但我們可以做適當的補充,除了在考慮復用性上可以拆分方法之外,我們也可以為了代碼的可讀性和可維護性去進行拆分,這樣將大大改善一個大的邏輯段的易讀性。可能你又會問,如果這樣做了不是會讓代碼變得很散,到處都是方法嗎?我還是想說“小比大好”,就像我們現在修理汽車更多地是更換那些有問題的零件一樣,通過將邏輯拆分成更多小的部件,在維護時我們可以更方便地進行替換從而降低開發成本以及因關聯性判斷不足帶來的風險。
雖然,我仍然無法寫出易讀的代碼,但通過對上面這些方法的實踐,我卻能在大多數項目中寫出易于維護的代碼,我想,這可能對于整個項目和團隊來說,才是更加重要的吧!
簡書簽約作者:技匠,以上內容歡迎大家分享到朋友圈/微博等。