本文僅僅是對《代碼整潔之道》摘錄:
簡單代碼悯仙,重要順序:
1.能通過所有的測試
2.沒有重復(fù)代碼
3.體現(xiàn)系統(tǒng)中的全部設(shè)計理念龄毡,提高表達(dá)力。
4.包括盡量少的實體锡垄,比如類沦零,方法,函數(shù)等货岭。
整潔的代碼總是看起來像是某位特別在意它的人寫的路操,幾乎沒有改進(jìn)的余地,代碼作者什么都想到了千贯,如果你企圖改進(jìn)它屯仗,總會回到原點,贊嘆某人留給你的代碼搔谴。
一.有意義的命名
1.名副其實的命名
2.避免誤導(dǎo)
3.為較大作用范圍選用較長名稱
二.函數(shù)
1.短小的函數(shù)
2.一個函數(shù)只做一件事
3.自頂而下規(guī)則魁袜,自向而下讀代碼。
4.減少過長的switch語句敦第。利用多態(tài)峰弹。
5.使用描述性的語句
6.函數(shù)參數(shù),最好是零參芜果,或一鞠呈,或二,超過三就要考慮是否可以優(yōu)化右钾。
7.一元函數(shù)蚁吝,盡量有輸入?yún)?shù),和輸出參數(shù)霹粥。讓讀者清楚的知道上下文和語境和轉(zhuǎn)換的事件灭将。
8.無副作用。函數(shù)只做一個事情后控。
如圖中的副作用就在于,在一個checkPassword()的函數(shù)中做了Session.initialize()的調(diào)用空镜。函數(shù)名代表修改密碼浩淘,但是將抹除現(xiàn)有會話數(shù)據(jù)的邏輯藏了起來捌朴。其實,違背了函數(shù)只做一件事情的原則张抄。
9.分割指令和詢問
函數(shù)要么做一件事砂蔽,要不回答一件事,二者不可兼得署惯。函數(shù)應(yīng)該修改某對象的狀態(tài)左驾,或者返回改對象的信息,极谊。兩樣都干會導(dǎo)致混亂诡右。
10.使用try/catch 異常來替代錯誤碼。
11.try/catch 代碼塊不加修飾轻猖,很容易搞亂代碼結(jié)構(gòu)帆吻,代碼丑陋不堪。錯誤處理和正常流程不能混為一談咙边。最好把try/catch 代碼塊的主體抽離出來猜煮,形成函數(shù)。如下圖:
12.消滅重復(fù)代碼败许。
13.減少返回null值王带。幾乎每行代碼都在檢查null值。這種代碼看似不壞市殷,其實糟透了辫秧,返回null是在給自己添加工作量,也是在給調(diào)用者添亂被丧。只要一處沒檢查盟戏,應(yīng)用程序就會失控。
14.別傳遞null值甥桂。
15.不要繼承常量
三.注釋
1.用代碼來解釋你的邏輯柿究。很顯然,我們更希望讀到下面這段代碼黄选。
2.好注釋蝇摸。避免廢話注釋,無意義的注釋办陷,不能明確表達(dá)函數(shù)的注釋貌夕。
3.代碼直接刪除,不要注釋民镜。其他人不敢刪除注釋掉的代碼啡专,他們會想,代碼放在那里制圈,一定有道理们童,久而久之畔况,注釋掉的代碼堆積在一起,十分難看慧库。
四.格式
1.向報紙學(xué)習(xí)跷跪。能夠讓讀者從上到下閱讀。像報紙一樣有頭條齐板,告訴故事主題吵瞻。名稱要簡單,名稱本身應(yīng)該足夠告訴我們是否在正確的模塊中甘磨,頂部給出高層次概念橡羞。細(xì)節(jié)往下漸次展開。
2.垂直方向上的間隔:封包聲明宽档,倒入聲明尉姨,每個函數(shù)之間,空白行隔開吗冤。
3.垂直方向上的靠近
4.概念相關(guān)的代碼放在一起又厉,相關(guān)性越強(qiáng),彼此之間的距離就該越短椎瘟。
5.函數(shù)的長度盡量小覆致,100行以內(nèi)最好。代碼行寬度肺蔚,80以內(nèi)最好煌妈。超過120,就過分了啊宣羊。
五.單元測試
TDD三定律:
1.沒有測試之前不要寫任何功能代碼
2.只編寫恰好能夠體現(xiàn)一個失敗情況的測試代碼
3.只編寫恰好能通過測試的功能代碼
整潔的測試遵循5條規(guī)則:
1.快速(運(yùn)行快)
2.獨立(每個測試單個運(yùn)行)
3.可重復(fù)(在任何無網(wǎng)絡(luò)環(huán)境中運(yùn)行測試)
4.自足驗證(應(yīng)有boolean輸出璧诵,無論是失敗或成功)
5.及時(編寫測試代碼要在生產(chǎn)代碼之前及時編寫)。
測試代碼和生產(chǎn)代碼一樣重要:
1.測試帶來一切好處:讓你的代碼可擴(kuò)展仇冯,可維護(hù)之宿,可復(fù)用。有了測試苛坚,不用擔(dān)心對代碼的修改比被,沒有測試,每2.次修改都有可能帶來缺陷泼舱。
3.整潔的代碼最主要的就是可讀性等缀。以盡可能少的文字表達(dá)大量內(nèi)容。
4.每個測試一個斷言
5.每個測試一個概念
六.類
1.類簡短娇昙,小
2.單一職責(zé)原則:只有一條修改的理由尺迂,一個類只做一件事。
3.內(nèi)聚:類應(yīng)該只有少量的實體變量。類中的每個方法都應(yīng)該操作一個或多個變量枪狂。
4.保持內(nèi)聚性就會得到許多短小的類
5.為了修改而組織:希望將系統(tǒng)打造成在添加或修改特性時危喉,盡可能少改動其他宋渔。我們期望通過擴(kuò)展系統(tǒng)而非修改現(xiàn)有代碼來添加新特性州疾。
6.隔離修改:
如果系統(tǒng)解耦到足以這樣測試的程度。就更靈活和可復(fù)用皇拣。部件之間的解耦代表著系統(tǒng)中的元素互相隔離的很好严蓖。也讓對系統(tǒng)的每個元素的理解變得更加容易。
七.系統(tǒng)
1.將系統(tǒng)的構(gòu)造與使用分開
2.分解main
3.工廠氧急,有時程序也要負(fù)責(zé)確定何時創(chuàng)建對象
4.依賴注入DI / 控制反轉(zhuǎn)IOC:
對成員變量賦值的控制權(quán)颗胡,從代碼反轉(zhuǎn)到配置文件中(本來new一個實例的工作由開發(fā)者反轉(zhuǎn)到Spring容器中)
Person p = new Person();//主動獲取方式
反轉(zhuǎn)為:
Person p = ac.getBean("a");//被動獲取
5.擴(kuò)容:橫貫式關(guān)注面AOP
將程序中的交叉業(yè)務(wù)邏輯,比如(安全吩坝,日志毒姨,事務(wù))封裝成一個切面啦扬。然后墩衙,注入到目標(biāo)對象中(具體的業(yè)務(wù)邏輯)
在運(yùn)行時,動態(tài)的將代碼切入到類的指定方法士败, 指定位置上的編程思想是面向切面的編程
aop的想法就是將非邏輯部分的代碼抽離出來嵌纲,只考慮邏輯代碼就好俘枫。
八.并發(fā)編程
并發(fā)防御原則:
1.單一職責(zé)原則:單一職責(zé)原則認(rèn)為方法和類組件應(yīng)當(dāng)只有一個修改的理由。并發(fā)設(shè)計自身足夠復(fù)雜到成為修改的理由逮走。分離并發(fā)相關(guān)代碼和其他代碼鸠蚪。
2.推論:限制數(shù)據(jù)作用域
3.推論;使用數(shù)據(jù)復(fù)本
4.線程盡可能獨立
5.Java庫
6.執(zhí)行模型:
“生產(chǎn)者-消費(fèi)者模型”:一個或多個生產(chǎn)者線程創(chuàng)建某些工作师溅,并置于緩存或隊列中茅信。一個或多個消費(fèi)者線程從隊列中獲取并完成這些工作。生產(chǎn)者和消費(fèi)者之間的隊列是一種限定資源墓臭。
”讀者-作者模型“:當(dāng)一個主要為讀者線程提供信息源蘸鲸,但只偶爾被作者線程更新的共享資源,吞吐量是個問題起便,增加吞吐量,會導(dǎo)致線程饑餓和過時信息的堆積妙痹。更新會影響吞吐量鼻疮,協(xié)調(diào)讀者線程,不去讀作者線程正在更新的信息(反之亦然)耿芹。作者線程傾向于長期鎖定許多讀者線程,從而導(dǎo)致吞吐量問題琉闪。
”宴席哲學(xué)家“:一群哲學(xué)家圍著圓桌吃飯砸彬,每人左手拿叉,中間放一碗面蛀蜜。但吃飯必須要兩個叉。如果左邊或右邊的哲學(xué)家已經(jīng)取用過一把叉子增蹭,中間這位就必須等到別人吃完滴某,放下叉。每位哲學(xué)家吃完后滋迈,就把兩把叉子放回去霎奢,直到肚子再餓。
用線程代表哲學(xué)家杀怠,資源代表叉子椰憋。如果沒有用心設(shè)計,這種競爭系統(tǒng)赔退,就會遭遇死鎖橙依,活鎖,吞吐量和效率低的問題硕旗。
7.同步鎖:synchronized 窗骑;避免使用一個共享對象的多個方法。有時必須使用一個共享對象的多個方法可以使用一下方案:
“基于客戶端的鎖定“:客戶端在調(diào)用第一個方法前鎖定服務(wù)端漆枚,確保鎖的范圍覆蓋了調(diào)用最后一個方法的代碼
”基于服務(wù)端的鎖定“创译;在服務(wù)端內(nèi)創(chuàng)建鎖定服務(wù)端的方法,調(diào)用所有的方法墙基,然后解鎖软族,讓客戶端調(diào)用新的方法
”適配服務(wù)端“:創(chuàng)建執(zhí)行鎖定的中間層,這是基于服務(wù)端的鎖定的例子残制,但不修改原始服務(wù)端代碼
8.同步鎖:synchronized 立砸;盡可能縮小同步區(qū)域
9.加入一個系統(tǒng)的父線程分裂數(shù)個子線程,父線程等所有子線程結(jié)束螺戳,然后盖腿,釋放資源奸忽,關(guān)閉。如果,其中一個子線程發(fā)生死鎖禁炒。父線程會一直等待下去幕袱,而系統(tǒng)永不會關(guān)閉⊥或者父線程告知全體子線程放棄任務(wù)并結(jié)束,但如果其中兩個子線程正以生產(chǎn)者/消費(fèi)者模型操作摄欲,消費(fèi)者線程還在等待生產(chǎn)者發(fā)來消息胸墙,于是鎖定在無法接收到關(guān)閉信號的狀態(tài)中,它會死等生產(chǎn)者線程玻淑,用不結(jié)束添坊,從而導(dǎo)致父線程也無法結(jié)束。
此中情況需要編寫設(shè)計平靜關(guān)閉的代碼阳准,預(yù)留時間搞對關(guān)閉過程野蝇。
解決方案:
1.將偽失敗看作可能的線程問題
2.先使非線程代碼可工作
3.編寫可插拔的線程代碼,在不同配置環(huán)境下運(yùn)行乍狐。