緣由
阿里JAVA開發(fā)手冊(cè)已經(jīng)發(fā)表有很長(zhǎng)時(shí)間了控漠,值得認(rèn)真研究思考推廣
阿里官方的Java代碼規(guī)范標(biāo)準(zhǔn),這份開發(fā)手冊(cè)不僅規(guī)范了一些開發(fā)細(xì)節(jié)霜浴,也提出了很多工程開發(fā)的哲學(xué)柜某,值得好好閱讀。
可謂包羅萬象沧烈,幾乎日常Java開發(fā)中方方面面都有所涉及掠兄。
每一條都是前人踩過的坑,通過血的教訓(xùn)總結(jié)出來的锌雀。
能公布出來真是造福全部Java開發(fā)者蚂夕。
開發(fā)手冊(cè)詳細(xì)列舉如何開發(fā)更加高效,更加容錯(cuò)腋逆,更加有協(xié)作性婿牍,力求知其然,更知其不然惩歉,結(jié)合正反例等脂,提高代碼質(zhì)量。比如撑蚌,異常日志處理時(shí)的各種不規(guī)范行為上遥;集合轉(zhuǎn)換的各種坑;創(chuàng)建線程池出現(xiàn)的等待隊(duì)列OOM等争涌。
的確阿里JAVA開發(fā)手冊(cè)值得我們好好閱讀和思考粉楚,每一條都是前人踩過的坑,通過血的教訓(xùn)總結(jié)出來的第煮。所以今天就其中一點(diǎn)自己的思考理解進(jìn)行分享解幼。
阿里JAVA開發(fā)手冊(cè)
看完這條抑党,個(gè)人覺得主要是圈復(fù)雜度,由于代碼是人寫的撵摆,并且需要人來進(jìn)行維護(hù)底靠,如果足夠的復(fù)雜的話,那么編寫出現(xiàn)錯(cuò)誤的可能性都很大特铝,并且維護(hù)理解起來難度也非常高暑中,以及后期如果需要擴(kuò)展本來就很復(fù)雜再加一個(gè)很簡(jiǎn)單的功能都變得很困難(相信大家一定都有這樣的經(jīng)歷)。
圈復(fù)雜度
圈復(fù)雜度(Cyclomatic complexity)是一種代碼復(fù)雜度的衡量標(biāo)準(zhǔn)鲫剿。
在軟件測(cè)試的概念里鳄逾,圈復(fù)雜度用來衡量一個(gè)模塊判定結(jié)構(gòu)的復(fù)雜程度,數(shù)量上表現(xiàn)為獨(dú)立線性路徑條數(shù)灵莲,即合理的預(yù)防錯(cuò)誤所需測(cè)試的最少路徑條數(shù)雕凹。圈復(fù)雜度大說明程序代碼可能質(zhì)量低且難于測(cè)試和維護(hù),根據(jù)經(jīng)驗(yàn)政冻,程序的可能錯(cuò)誤和高的圈復(fù)雜度有著很大關(guān)系枚抵。
看看上面阿里JAVA開發(fā)手冊(cè)里面提到的,如果非得使用if()...else if()...else...方式表達(dá)邏輯,【強(qiáng)制】避免后續(xù)代碼維護(hù)困難,請(qǐng)匆超過3層渣刷。如果超過3層的if-else的邏輯判斷代碼可以使用衛(wèi)語句、策略模式逼泣、狀態(tài)模式等來實(shí)現(xiàn)。
其實(shí)在我看來舟舒,使用衛(wèi)語句拉庶、策略模式、狀態(tài)模式就是來降低圈復(fù)雜度魏蔗,讓代碼更加簡(jiǎn)單砍的,這樣不管是編寫代碼人員以及維護(hù)人員都可以非常方便了解到本質(zhì)意思。
雖然阿里JAVA開發(fā)手冊(cè)提到的是if()...else if()...else...方式表達(dá)邏輯莺治,延伸下廓鞠,關(guān)于多次嵌套循環(huán)等道理也一樣,需要考慮優(yōu)化的谣旁。
思路分析
判斷樹
如上圖床佳,其實(shí)看起來就是一顆樹結(jié)構(gòu),相對(duì)來說其實(shí)比較復(fù)雜了榄审,優(yōu)化的思路其實(shí)就是把樹結(jié)構(gòu)變成順序結(jié)構(gòu)即可砌们,那樣條理就清晰了,總體思路是這樣的,下面看看使用衛(wèi)語句浪感、策略模式昔头、狀態(tài)模式怎么達(dá)到的。
衛(wèi)語句
衛(wèi)語句影兽?衛(wèi)語句就是把復(fù)雜的條件表達(dá)式拆分成多個(gè)條件表達(dá)式揭斧,比如一個(gè)很復(fù)雜的表達(dá)式,嵌套了好幾層的if - then-else語句峻堰,轉(zhuǎn)換為多個(gè)if語句讹开,實(shí)現(xiàn)它的邏輯,這多條的if語句就是衛(wèi)語句捐名。
其中衛(wèi)語句示例如下:
publicvoidtoday(){if(isBusy()) {? ? ? ? System.out.println("change time.");return;? ? }if(isFree()) {? ? ? ? System.out.println("go to travel.");return;? ? }? ? System.out.println("stay at home to learn Alibaba Java Coding Guidelines.");return;}
其實(shí)這個(gè)比較簡(jiǎn)單旦万,每一個(gè)if對(duì)應(yīng)葉子節(jié)點(diǎn)的一條路徑(每個(gè)if基本就return了)。
策略模式
概述:使用這個(gè)模式來將一組算法封裝成一系列對(duì)象镶蹋。通過傳遞這些對(duì)象可以靈活的改變程序的功能成艘。
策略模式比較有名的就是諸葛亮的三個(gè)錦囊妙計(jì)說起,如圖:
諸葛亮為什么要這么麻煩梅忌,做三個(gè)錦囊狰腌?他完全可以只做一個(gè)錦囊除破,將這三個(gè)妙計(jì)都寫在它上面牧氮。可他沒有這么做瑰枫,而是正確的運(yùn)用了策略模式做了三個(gè)錦囊踱葛。這樣做的好處十分明顯:諸葛亮一個(gè)錦囊寫一個(gè)妙計(jì),他的思路十分清晰光坝,不會(huì)三個(gè)計(jì)策相互混亂尸诽。而趙云看妙計(jì)的時(shí)候也十分方便,什么時(shí)候看哪個(gè)妙計(jì)盯另,使用十分方便性含,如果三個(gè)妙計(jì)混在一起,他就沒這么方便了鸳惯。
在JDK中java.util.Comparator#compare()就是使用的策略模式商蕴,比如我們經(jīng)常對(duì)商品進(jìn)行排序,條件有很多啊芝发,按照商品瀏覽量绪商、價(jià)格、更新時(shí)間辅鲸、【價(jià)格格郁、時(shí)間】、【瀏覽量、更新時(shí)間】(進(jìn)行升序例书、降序操作)其實(shí)這個(gè)也是上面那顆樹锣尉,需要做的就是每次取其中一條葉子節(jié)點(diǎn)。很多時(shí)候這些判斷都是寫在一個(gè)公用的方法里面决采,進(jìn)行大量的判斷之后寫排序悟耘,而JDK怎么做的呢?把變化的比較判斷拿出來织狐,其實(shí)判斷樹中每個(gè)葉子結(jié)點(diǎn)就是一種策略暂幼,想象我們平時(shí)怎么做的呢? 都是把Comparator#compare()寫好(可能有很多實(shí)現(xiàn)Comparator接口的排序算法)每次我們調(diào)用的時(shí)候選擇其中一種即可移迫。
與衛(wèi)語句不同的是旺嬉,衛(wèi)語句把每一個(gè)if對(duì)應(yīng)葉子節(jié)點(diǎn)的一條路徑。而策略模式是所以葉子都在實(shí)現(xiàn)Comparator接口了厨埋,具體開始用那個(gè)是調(diào)用的直接用(所以不會(huì)像衛(wèi)語句那樣看見很多if了)
狀態(tài)模式
概述:當(dāng)一個(gè)對(duì)象的內(nèi)在狀態(tài)改變時(shí)允許改變其行為邪媳,這個(gè)對(duì)象看起來像是改變了其類。主要解決的是對(duì)象的行為依賴于它的狀態(tài)(屬性)荡陷,并且可以根據(jù)它的狀態(tài)改變而改變它的相關(guān)行為雨效。
封裝了轉(zhuǎn)換規(guī)則。
枚舉可能的狀態(tài)废赞,在枚舉狀態(tài)之前需要確定狀態(tài)種類徽龟。
將所有與某個(gè)狀態(tài)有關(guān)的行為放到一個(gè)類中,并且可以方便地增加新的狀態(tài)唉地,只需要改變對(duì)象狀態(tài)即可改變對(duì)象的行為据悔。
允許狀態(tài)轉(zhuǎn)換邏輯與狀態(tài)對(duì)象合成一體,而不是某一個(gè)巨大的條件語句塊耘沼。
可以讓多個(gè)環(huán)境對(duì)象共享一個(gè)狀態(tài)對(duì)象极颓,從而減少系統(tǒng)中對(duì)象的個(gè)數(shù)。
由于狀態(tài)模式是封裝了轉(zhuǎn)換規(guī)則群嗤,所以一般樹的深度最少需要2層以及上菠隆,個(gè)人理解的感覺就是一個(gè)流程了,比如*水低于0度是冰的狀態(tài)--> 大于0度又變成液態(tài)--> 100度又變成沸騰的狀態(tài)
狀態(tài)模式與策略模式很像狂秘,策略模式是外驅(qū)動(dòng)骇径,而狀態(tài)模式是內(nèi)驅(qū)動(dòng)。本質(zhì)也是把判斷樹里面只取其中一條葉子的路徑赃绊。
狀態(tài)模式有一個(gè)明顯的缺點(diǎn):狀態(tài)模式對(duì)"開閉原則"的支持并不太好既峡,對(duì)于可以切換狀態(tài)的狀態(tài)模式,增加新的狀態(tài)類需要修改那些負(fù)責(zé)狀態(tài)轉(zhuǎn)換的源代碼碧查,否則無法切換到新增狀態(tài)运敢,而且修改某個(gè)狀態(tài)類的行為也需修改對(duì)應(yīng)類的源代碼校仑。
程序員笑話
老婆給當(dāng)程序員的老公打電話:下班順路買十個(gè)包子,如果看到賣西瓜的传惠,買一個(gè)迄沫。當(dāng)晚老公手捧一個(gè)包子進(jìn)了家門…老婆怒道:你怎么只買一個(gè)包子?卦方!老公甚恐羊瘩,喃喃道:因?yàn)槲艺婵吹劫u西瓜的了∨慰常”
如果使用策略模式就簡(jiǎn)單了尘吗,2條信息,1:買十個(gè)包子浇坐。2:買一個(gè)西瓜睬捶,沒有就算了。
雖然是個(gè)笑話近刘,但是順序的就是比判斷的要簡(jiǎn)單擒贸。
總結(jié)
圈復(fù)雜度概念
衛(wèi)語句
策略模式
狀態(tài)模式
匯總:本質(zhì)就是把較深的判斷樹,使用的時(shí)候觉渴,就是把判斷樹結(jié)構(gòu)變成順序結(jié)構(gòu)即可介劫,就是給出每個(gè)葉子的路徑而不需要看起來是一顆復(fù)雜的樹結(jié)構(gòu)。
思考
阿里JAVA開發(fā)手冊(cè)
這是阿里JAVA開發(fā)手冊(cè)其中一條明細(xì)案淋,為什么呢座韵,結(jié)果是啥,怎么出乎意料啦哎迄?回右?期待你的留言和分析!J俊!
上面的一些分析都是個(gè)人自己的理解和思考渺氧,如果發(fā)現(xiàn)有不對(duì)的希望留言指出旨涝,謝謝!B卤场白华!
如果讀完覺得有收獲的話,歡迎點(diǎn)贊加關(guān)注贩耐。
作者:匠心零度
鏈接:http://www.reibang.com/p/2dc45c02b024
來源:簡(jiǎn)書
著作權(quán)歸作者所有弧腥。商業(yè)轉(zhuǎn)載請(qǐng)聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請(qǐng)注明出處潮太。