讀書(shū),收獲,分享
建議后面的五角星僅代表筆者個(gè)人需要注意的程度。
Talk is cheap.Show me the code
建議144:提倡良好的代碼風(fēng)格★★☆☆☆
優(yōu)秀團(tuán)隊(duì)的編碼風(fēng)格應(yīng)該具有哪些特征:
-
整潔
代碼首先是給人看的,然后才是給機(jī)器執(zhí)行的,對(duì)于機(jī)器來(lái)說(shuō),只要代碼符合規(guī)范,不在乎其格式是否整潔、是否有縮進(jìn)、是否有回車(chē),只要代碼正確就能正常運(yùn)行,而人就不同了,沒(méi)有縮進(jìn)沒(méi)有回車(chē)的代碼基本上是不可閱讀的。
-
統(tǒng)一
從一個(gè)團(tuán)隊(duì)中誕生的代碼應(yīng)該具有一致的風(fēng)格,不要帶有個(gè)人色彩的風(fēng)格標(biāo)識(shí)。盡量讓我們的代碼看起來(lái)很職業(yè)。
-
流行
一種潮流風(fēng)行世界的時(shí)候必然有其誕生的原因(感冒也包括在內(nèi)),一種編碼格式的流行也必然有它存在的理由,我們完全可以借鑒流行的編碼格式,沒(méi)有必要對(duì)這種風(fēng)格進(jìn)行重塑,而且使用流行風(fēng)格可以讓新成員盡快融入項(xiàng)目,避免出現(xiàn)進(jìn)入一個(gè)新環(huán)境而出現(xiàn)茫茫無(wú)助的狀態(tài)。
-
便捷
制定出來(lái)的編碼規(guī)范必須有通用開(kāi)發(fā)工具支撐,不能制定出只能由個(gè)別開(kāi)發(fā)工具支持的規(guī)范。
建議145:不要完全依靠單元測(cè)試來(lái)發(fā)現(xiàn)問(wèn)題★★☆☆☆
原因有以下四點(diǎn):
-
單元測(cè)試不可能測(cè)試所有的場(chǎng)景(路徑)
單元測(cè)試必須測(cè)試的三種數(shù)據(jù)場(chǎng)景是:正常場(chǎng)景、邊界場(chǎng)景、異常場(chǎng)景。如果這三種測(cè)試場(chǎng)景都能出現(xiàn)預(yù)期的結(jié)果,則認(rèn)為代碼正確。
-
代碼整合錯(cuò)誤是不可避免的
單元測(cè)試只是保證了分割的獨(dú)立單元的正確性,它不能保證一個(gè)功能的完整性。
部分代碼無(wú)法(或很難)測(cè)試
單元測(cè)試驗(yàn)證的是編碼人員的假設(shè)
敏捷開(kāi)發(fā)中提倡的TDD(Test-Driven Development)測(cè)試驅(qū)動(dòng)開(kāi)發(fā):?jiǎn)卧獪y(cè)試先行,而后才會(huì)編寫(xiě)生產(chǎn)代碼,這可以大幅度地提升代碼質(zhì)量,加快項(xiàng)目開(kāi)發(fā)的進(jìn)度。
建議146:讓注釋正確、清晰、簡(jiǎn)潔★★☆☆☆
一些不好的注解習(xí)慣:
廢話式注釋
-
故事式注釋
一句話說(shuō)清即可,不需要講故事
-
不必要的注釋?zhuān)ㄏ胄Γ?/p>
//默認(rèn)值為0 private int num; -
過(guò)時(shí)的注釋
注釋與代碼的版本不一致,注釋是1.0版本,而代碼早已竄到了5.0版本
-
大塊注釋代碼
廢棄(在生產(chǎn)版本上肯定不用該代碼),則應(yīng)該完全刪除掉。
流水賬式的注釋
-
專(zhuān)為
JavaDoc編寫(xiě)的注釋建議在注釋中只保留
<p>、<code>等幾個(gè)常用的標(biāo)簽,不要增加<font>、<table>、<div>等標(biāo)簽。
那好的注釋?xiě)?yīng)該是這樣子的:首先要求正確,注釋與代碼意圖吻合;其次要求清晰,格式統(tǒng)一,文字準(zhǔn)確;最后要求簡(jiǎn)潔,說(shuō)明該說(shuō)明的,惜字如金,拒絕不必要的注釋。
如下類(lèi)型的注釋就是好的注釋?zhuān)?/p>
-
法律版權(quán)信息
這是我們?cè)陂喿x源代碼時(shí)經(jīng)??吹降?,一般都是指向同一個(gè)法律版權(quán)聲明的。
-
解釋意圖的注釋
說(shuō)明為什么要這樣做,而不是怎么做的
警示性注釋
-
TODO注釋對(duì)于一些未完成的任務(wù),則增加上
TODO提示,并標(biāo)明是什么事情沒(méi)有做完,以方便下次看到這個(gè)TODO標(biāo)記時(shí)還能記憶起要做什么事情
注意:注釋不是美化劑,而是催化劑,或?yàn)閮?yōu)秀加分,或?yàn)樽玖訙p分。
建議147:讓接口的職責(zé)保持單一★★☆☆☆
職責(zé)是一個(gè)接口(或類(lèi))要承擔(dān)的業(yè)務(wù)含義,或是接口(或類(lèi))表現(xiàn)出的意圖。
單一職責(zé)有以下三個(gè)優(yōu)點(diǎn):
-
類(lèi)的復(fù)雜性降低
職責(zé)單一,在實(shí)現(xiàn)什么職責(zé)時(shí)都有清晰明確的定義,那么接口(或類(lèi))的代碼量就會(huì)減少,復(fù)雜度也就會(huì)減少。當(dāng)然,接口(或類(lèi))的數(shù)量會(huì)增加上去,相互間的關(guān)系也會(huì)更復(fù)雜,這就需要適當(dāng)把握了。
-
可讀性和可維護(hù)性提高
職責(zé)單一,會(huì)讓類(lèi)中的代碼量減少,我們可以一眼看穿該類(lèi)的實(shí)現(xiàn)方式,有助于提供代碼的可讀性,這也間接提升了代碼的可維護(hù)性。
-
降低變更風(fēng)險(xiǎn)
變更是必不可少的,如果接口(或類(lèi))的單一職責(zé)做得好,一個(gè)接口修改只對(duì)相應(yīng)的實(shí)現(xiàn)類(lèi)有影響,對(duì)其他的接口無(wú)影響,那就會(huì)對(duì)系統(tǒng)的擴(kuò)展性、維護(hù)性都有非常大的幫助。
注意:接口職責(zé)一定要單一,實(shí)現(xiàn)類(lèi)職責(zé)盡量單一。
建議148:增強(qiáng)類(lèi)的可替換性★★☆☆☆
里氏替換原則是說(shuō)“所有引用基類(lèi)的地方必須能透明地使用其子類(lèi)的對(duì)象”,通俗點(diǎn)講,只要父類(lèi)型能出現(xiàn)的地方子類(lèi)型就可以出現(xiàn),而且將父類(lèi)型替換為子類(lèi)型還不會(huì)產(chǎn)生任何錯(cuò)誤或異常,使用者可能根本就不需要知道是父類(lèi)型還是子類(lèi)型。但是,反過(guò)來(lái)就不行了,有子類(lèi)型出現(xiàn)的地方,父類(lèi)型未必就能適應(yīng)。
為了增強(qiáng)類(lèi)的可替換性,就要求我們?cè)谠O(shè)計(jì)類(lèi)的時(shí)候考慮以下三點(diǎn):
子類(lèi)型必須完全實(shí)現(xiàn)父類(lèi)型的方法
-
前置條件可以被放大
class Base { public void doStuff(HashMap hashMap) { } } class Sub extends Base { public void doStuff(Map map) { } }
- 后置條件可以被縮小
增強(qiáng)類(lèi)的可替換性,則增強(qiáng)了程序的健壯性,版本升級(jí)時(shí)也可以保持非常好的兼容性。即使增加子類(lèi),原有的子類(lèi)還可以繼續(xù)運(yùn)行。
建議149:依賴(lài)抽象而不是實(shí)現(xiàn)★★☆☆☆
在面向過(guò)程開(kāi)發(fā)中,我們考慮的是如何實(shí)現(xiàn),依賴(lài)的是每個(gè)具體實(shí)現(xiàn),而在OOP中,則需要依賴(lài)每個(gè)接口,而不能依賴(lài)具體的實(shí)現(xiàn),比如我們要到北京出差,應(yīng)該依賴(lài)交通工具,而不是依賴(lài)的具體飛機(jī)或火車(chē),也就是說(shuō)我們依賴(lài)的是交通工具的運(yùn)輸能力,而不是具體的一架飛機(jī)或某一列火車(chē)。這樣的依賴(lài)可以讓我們實(shí)現(xiàn)解耦,保持代碼間的松耦合,提高代碼的復(fù)用率,這也是依賴(lài)倒置原則(Dependence Inversion Principle,簡(jiǎn)稱(chēng)DIP)提出的要求:
- 高層模塊不應(yīng)該依賴(lài)低層模塊,兩者都應(yīng)該依賴(lài)其抽象。
- 抽象不應(yīng)該依賴(lài)細(xì)節(jié)。
- 細(xì)節(jié)應(yīng)該依賴(lài)抽象。
依賴(lài)倒置原則在Java語(yǔ)言中的表現(xiàn)就是:
- 模塊間的依賴(lài)是通過(guò)抽象發(fā)生的,實(shí)現(xiàn)類(lèi)之間不發(fā)生直接的依賴(lài)關(guān)系,其依賴(lài)關(guān)系是通過(guò)接口或抽象類(lèi)產(chǎn)生的。
- 接口或抽象類(lèi)不依賴(lài)于實(shí)現(xiàn)類(lèi)。
- 實(shí)現(xiàn)類(lèi)依賴(lài)接口或抽象類(lèi)。
我們?cè)趺丛陧?xiàng)目中使用這個(gè)規(guī)則呢?只要遵循以下的幾個(gè)規(guī)則就可以:
- 盡量抽象
- 表面類(lèi)型必須是抽象的
- 任何類(lèi)都不應(yīng)該從具體類(lèi)派生
- 盡量不要覆寫(xiě)基類(lèi)的方法
- 抽象不關(guān)注細(xì)節(jié)
建議150:拋棄7條不良的編碼習(xí)慣★★☆☆☆
自由格式的代碼
不使用抽象的代碼
-
彰顯個(gè)性的代碼
“最小驚詫原則”(Principle Of Least Surprise簡(jiǎn)稱(chēng)POLS,或者Principle Of LeastAstonishment簡(jiǎn)稱(chēng)POLA),其意是說(shuō)要使用最常見(jiàn)的,而不是最新穎的功能。
-
死代碼,冗余代碼
忘記刪除的代碼或者廢棄的代碼等
-
拒絕變化的代碼
一個(gè)在
JDK 1.1中就過(guò)時(shí)的方法還還能在使用JDK 1.6項(xiàng)目中存在,謂之曰“沒(méi)有壞,就不要去修它”—該重構(gòu)它了,它沒(méi)壞,但它賴(lài)以生存的環(huán)境已經(jīng)變了! -
自以為是的代碼
相信自己編寫(xiě)的工具類(lèi),而不是開(kāi)源工具,寧愿自己寫(xiě)序列化工具,也不選擇
kryo或protostuff;寧愿自己寫(xiě)日期處理工具,也不選擇Joda或date4j;寧愿自己寫(xiě)批處理框架,也不選擇Spring Batch,這樣是不行的!—相信天外有天吧,更多更好的工具等待著你去發(fā)掘。
建議151:以技術(shù)員自律而不是工人★★★★★
下20條建議可以逐步把我們向技術(shù)人員方向培養(yǎng):
-
熟悉工具
軍人手中有槍?zhuān)r(nóng)民手中有鋤頭,而我們手里只有Java,這也是我們能夠引以為豪的工具,我們應(yīng)該了解它的使用范圍,了解的它的生態(tài)系統(tǒng),了解它的發(fā)展趨勢(shì)—它也可能就是陪伴我們一生的那個(gè)工具,也祝愿它是。
-
使用
IDE在技術(shù)領(lǐng)域,不要相信“無(wú)刀勝有刀”之類(lèi)的鬼話—“高手都用記事本或VI開(kāi)發(fā)”
-
堅(jiān)持編碼
不要考慮自己的職位、崗位,只要是Java圈子的生物都應(yīng)該堅(jiān)持編碼,沒(méi)有編碼,就等于是無(wú)源之水,無(wú)本之木,何來(lái)靈感和靈性?
-
編碼前思考
在坐下來(lái)開(kāi)始編碼之前,必須已經(jīng)完成設(shè)計(jì),最低要求是對(duì)開(kāi)發(fā)中遇到的問(wèn)題有清晰的認(rèn)識(shí),不要在編碼中解決問(wèn)題。
-
堅(jiān)持重構(gòu)
不要相信一次就能寫(xiě)出優(yōu)秀的代碼,這是不現(xiàn)實(shí)的,任何優(yōu)秀的代碼、算法都是經(jīng)過(guò)多次重構(gòu)磨練的,堅(jiān)信自己的下一個(gè)版本或代碼更優(yōu)秀。
寫(xiě)注釋、寫(xiě)說(shuō)明、寫(xiě)報(bào)告都是對(duì)代碼或項(xiàng)目的回顧和總結(jié),不僅僅是為了后續(xù)的參與人員,同時(shí)也是為了整理自己頭腦中混亂的思維。
-
保持程序版本的簡(jiǎn)單性
一個(gè)項(xiàng)目不要保持多個(gè)版本,即使有分支也必須定義出項(xiàng)目合并的條件,或者時(shí)間約束,或者目標(biāo)約束,不可任由版本擴(kuò)散。
-
做好備份
世界上沒(méi)有萬(wàn)無(wú)一失的事情,不做備份,一旦災(zāi)難發(fā)生就無(wú)挽救的余地了
-
做單元測(cè)試
單元測(cè)試不僅能增強(qiáng)你的信心,也能給你帶來(lái)好名聲—后續(xù)者一看,“哇哦,單元測(cè)試寫(xiě)得這么完整,肯定是一個(gè)認(rèn)真、負(fù)責(zé)的人”。
-
不要重復(fù)發(fā)明輪子
在項(xiàng)目中使用已經(jīng)成熟的工具或框架,而不是自己編寫(xiě)。但是如果想共享一個(gè)新的
MVC框架,那就盡管去重復(fù)發(fā)明輪子吧,它不是以交付為目的的,而是以技術(shù)研究為目標(biāo)的。 當(dāng)按下
Ctrl+C的時(shí)候,問(wèn)問(wèn)自己“我在做什么?拷貝是否是唯一能做的?為什么不能重構(gòu)一下呢”,不要讓大段的代碼散落在各處,不要做搬運(yùn)工,不要做拷貝工,要做技術(shù)工。-
讓代碼充滿靈性
為變量、類(lèi)、方法起個(gè)好聽(tīng)的名字是一個(gè)不錯(cuò)的主意,為代碼增加必要的注釋也是很好的辦法,“One Line”能解決一個(gè)上百行代碼的問(wèn)題,也是一個(gè)優(yōu)秀的實(shí)現(xiàn)。
-
測(cè)試自動(dòng)化
不管是性能測(cè)試、單元測(cè)試,還是功能測(cè)試,想盡辦法讓它自動(dòng)化,不要在測(cè)試之前手動(dòng)配置或觸發(fā)條件,這不夠人性化,也同時(shí)讓代碼“汗顏”—本是用來(lái)自動(dòng)執(zhí)行的,但卻被手動(dòng)設(shè)置了條件。
-
做壓力測(cè)試
不要相信業(yè)務(wù)人員“最多200個(gè)用戶使用”之類(lèi)的話,把業(yè)務(wù)人員制定的指標(biāo)擴(kuò)大3倍,然后再做壓力測(cè)試。不要迷信自己的代碼很健壯,在高并發(fā)時(shí)只有上帝知道發(fā)生了何事,你又怎么能知道?
-
“剽竊”不可恥
多看開(kāi)源代碼,學(xué)習(xí)一下人家是如何編碼的,然后經(jīng)?!柏飧`”一下,這也是提高技能的最佳途徑,我們不是孔乙己,“剽竊”不可恥。
-
堅(jiān)持向敏捷學(xué)習(xí)
不管“敏捷”與“非敏捷”之間的爭(zhēng)論有多激烈,敏捷中的一些思想是非常優(yōu)秀的,例如
TDD測(cè)試驅(qū)動(dòng)開(kāi)發(fā)、交流的重要性、循序漸漸開(kāi)發(fā)等。 重里更重面
UI(User Interface)是“面”,Java程序是“里”,客戶首先感受到的是“面”,然后才是“里”,要想獲得良好的第一印象,那就需要有一個(gè)簡(jiǎn)潔、清晰、便捷的UI,即使“金玉其外敗絮其中”,我們也可以繼續(xù)重構(gòu)。
-
分享
“獨(dú)樂(lè)樂(lè)”不如“眾樂(lè)樂(lè)”,把自己的代碼分享出去收獲的不僅僅是贊許,還有自己能力的提升—暴露出自己的Bug,在眾目睽睽之下修正之,知恥而后勇也。
-
刨根問(wèn)底
有問(wèn)題不可怕,可怕的是掩蓋,或者虛假掩蓋,“哦,這個(gè)問(wèn)題呀,加上這個(gè)參數(shù)就可以解決了”—這不是解決問(wèn)題的辦法,在答案之后加上“是因?yàn)椤?,這才是解決了問(wèn)題。
-
橫向擴(kuò)展
Java要運(yùn)行在
JVM、操作系統(tǒng)上,同時(shí)還要與硬件、網(wǎng)絡(luò)、存儲(chǔ)交互,另外要遵循諸如FTP、SMTP、HTTP等協(xié)議,還要實(shí)現(xiàn)Web Service、RMI、XML-RPC等接口,所以我們必須熟悉相關(guān)的知識(shí)—擴(kuò)展知識(shí)面,這些都是必須去學(xué)習(xí)的。