丨變量聲明與賦值分離普通的怎么也有壞味道_第1頁
丨變量聲明與賦值分離普通的怎么也有壞味道_第2頁
丨變量聲明與賦值分離普通的怎么也有壞味道_第3頁
丨變量聲明與賦值分離普通的怎么也有壞味道_第4頁
丨變量聲明與賦值分離普通的怎么也有壞味道_第5頁
已閱讀5頁,還剩7頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

我們先來看一段代碼EpubStatusstatus=CreateEpubResponseresponse=if(response.getCode()==201)status=}elsestatus=7這段代碼在做的事情是向另外一個服務(wù)發(fā)請求創(chuàng)建EPUB(一種格式),如果創(chuàng)建成功,返回值是HTTP的201,也就表示創(chuàng)建成功,然后就把狀態(tài)置為CREATED;而如果沒有成功,則把狀態(tài)置為TO_CREATE。后面對于TO_CREATE狀態(tài)的作品,還需要再這里,我們暫且把是否要寫else放下,這是我們面已經(jīng)討論過的一個壞味道我們這次的重點在staus這個變量上,雖然sats這個變量在的時候,就賦上了一個nl值,但實際上,這個值并沒有起到任何作用,因為staus的變量值,其實是在經(jīng)過后續(xù)處理之后,才有了真正的值。換言之,從語義上說,第一行的變量初始化其實是沒有用的,這是一次初始化。按照我們通常的理解,一個變量的初始化是分成了和賦值兩個部分,而我這里要說的就是,變量初始化最好完成。這段代碼里的變量賦值是在很久之后才完成的,也就是說,變量初始化沒有完成。這種代碼真正的問題就是不清晰,變量初始化與業(yè)務(wù)處理混在在一起。通常來說,這種代碼后面緊接著就是一大堆更復(fù)雜的業(yè)務(wù)處理。當(dāng)代碼混在一起的時候,須翼翼地從一堆業(yè)務(wù)邏輯里抽絲剝繭,才能把邏輯理清,知道變量到底是怎么初始化的。很多代碼難讀,一個重要的原因就是把不同層面的代碼混在了一起。雜了很多的業(yè)務(wù)代碼在其中,進(jìn)一步增加了理解的復(fù)雜代123456789finalCreateEpubResponseresponse=finalEpubStatusstatus=privateEpubStatustoEpubStatus(finalCreateEpubResponse{if代123456789finalCreateEpubResponseresponse=finalEpubStatusstatus=privateEpubStatustoEpubStatus(finalCreateEpubResponse{if(response.getCode()==201){returnEpubStatus.CREATED;}return}在這段改進(jìn)的代碼中,我們提取出了一個函數(shù),將response成對應(yīng)的內(nèi)部的EPUB其實,很多人之所以這樣寫代碼,一個重要的原因是很多人的編程習(xí)慣是從C語言來C語言在早期的版本中,一個函數(shù)用到的變量必須在整個函數(shù)的一開始就出來在C語言誕生的年代,當(dāng)時計算機能力有限內(nèi)存小,編譯器技術(shù)也處于剛剛起步的階段,把變量放面出來,有助于減小編譯器編寫的難度。到了C++產(chǎn)生的年代,這個限制就逐步放開了,所以,C++程序是支持變量隨用隨的。對于今天的大多數(shù)程序設(shè)計還有一點不知道你注意到了沒有,在新的變量中,我加上了final,在Java的語義中,一個變量加上了final,也就意味著這個變量不能再次賦值。對,我們需要的正是這樣如果我們能夠按照使用場景做一個區(qū)分,把變量初始化與業(yè)務(wù)處理分開,你會發(fā)現(xiàn),在很多情況下,變量只在初始化完成之后賦值,就足以滿足我們的需求了,在一段代碼中,需要使用可變量的場景并不多。這個原則其實可以推廣一下,在能夠使用final的地方盡量使用final,限制變量的賦值??梢試L試著調(diào)整自己現(xiàn)有的代碼,給變量都加上final,你就會發(fā)現(xiàn)許多值得改進(jìn)的代對于Java序員來說,還有一個特殊的場景,就是異常處理的場景,強迫你把變量的代代123456789InputStreamis=tryis=new}catch(IOExceptione)}finallyif(is!=null)}}之所以要把InputStream變量is單獨,是為了能夠在finanlly塊里面到。其實,這段代碼寫成這樣,一個重要的原因是Java早期的版本只能寫成這樣,而如果采用Java7之后的版本,采用try-with-resource的寫法,代碼就可以更簡潔了:try(InputStreamis=newFileInputStream(...))3這樣一來,InputStream變量的初始化就完成了,我們的原則就統(tǒng)一了,不需要在接下來,我們在來看一段代List<Permission>permissions=newcheck.grantTo(Role.AUTHOR,道。我們把注意力放在permissions這個集合上。之所以要這樣一個List,是因為grantTo方法要用到一個List作為參數(shù)。我們來看這個List是怎樣生成的。這里先給permission初始化成了一個ArrayList,這個時候,permissions雖然存在了,但我們并不會把它傳給grantTo方法,它還不能直接使用,因為它還缺少必要的信息。然后,BOOK_READ和BOOK_WRITE兩個枚舉對象添加了進(jìn)去,這樣,這個permissions對象才是我們真正需要的那個對象。這種代碼是非常常見的,一個集合,然后,調(diào)用一堆添加的方法,將所需的對象添加我們不難發(fā)現(xiàn),其實permissions對象一開始的變量,并沒有完成這個集合真正的初始化,只有當(dāng)集合所需的對象添加完畢之后,這個集合才是它應(yīng)有的樣子。換言之,只有添加了元素的集合才是我們需要的。這樣解釋這段代碼,你是不是就發(fā)現(xiàn)了,這和我們前面所說的變量先后賦值,本質(zhì)上是一回事,都是從一個變量的到初始化成一個可用的狀態(tài),中間隔了太遠(yuǎn)的距離。之所以很多人習(xí)慣這么寫,一個原因就是在早期的Java版本中,沒有提供很好的集合初始化的方法。像這種代碼,也是很多動態(tài)語言的支持者調(diào)侃Java啰嗦的一個靶子?,F(xiàn)如今,Java這方面早已經(jīng)改進(jìn)了許多,各種程序庫已經(jīng)提供了一步到位的寫法,我們先來看看Java9之后的寫法:List<Permission>permissions=45check.grantTo(Role.AUTHOR,如果你的項目還沒有升級Java9之后的版本,使用Guava(提供的一個庫)也是可以做成類似的效1List<Permission>permissions= 45check.grantTo(Role.AUTHOR,經(jīng)過改進(jìn),這段代碼是不是看上去就清爽不知道你注意到?jīng)]有,第二段代碼里的List用的是一個ImmutableList,也就是一個不可變的List,實際上,你查看第一段代碼的實現(xiàn)就會發(fā)現(xiàn),它也是一個不變的List。這是什么意思呢?也就是說,這個List一旦創(chuàng)建好了,就是不能修改了,對應(yīng)的實現(xiàn)就是各種添加、刪除之類的方法全部都禁用初看起來,這是限制了我們的能力,但我們對比一下代碼就不難發(fā)現(xiàn),很多時候,我們對于一個集合的使用,除了時添加元外,后續(xù)就只是把它當(dāng)作一個只讀的集合。所以,在很多情況下,一個不變集合對我們來說就夠用了。其實,這段代碼,相對來說還是比較清晰的,稍微再復(fù)雜一些的,集合的和添加元素12privatestaticMap<Locale,String>=new3345678static{}.put(LOCALE.ENGLISH,,這是一個傳輸時的映射方案,將不同的語言版本映射為不同的代碼。這 是一個類的static變量,而這個類的里還有其它一些變量。所以,隔了很遠(yuǎn)之后,才有一個static塊向這個集合添加元素。如果我們能夠用的方式,這個單獨的static塊就是不需要的1234privatestaticMap<Locale,String>LOCALE.ENGLISH,=,碼,而后面的代碼是式的代碼。命令式的代碼,就是告訴你“怎么做”的代碼,就像改造前的代碼,一個集合,然后添加一個元素,再添加一個元素。而式的代碼,是告訴你“做什么”的代碼,改造后我在《軟件設(shè)計之美》專欄中講DSL時,曾經(jīng)講過二者的區(qū)別,式的代碼體的意圖,是更面的抽象,把意圖分開,從某種意義上來說,也是一種分離關(guān)注點。所以,用式的標(biāo)準(zhǔn)來看代碼,是一個發(fā)現(xiàn)代碼壞味道的重要參考回想一下今天講的壞味道,無論是變量的與賦值分離,還是初始化一個集合的分驟,其實反映的都是不同時代編程風(fēng)格的烙印。變量的是C早期的編程風(fēng)格,異常處理是Java早期的風(fēng)格,而集合也體現(xiàn)出不同版本Java的。我們學(xué)習(xí)編程不僅僅是要學(xué)習(xí)實現(xiàn)功能,編程的風(fēng)格也要與時俱今天我們繼續(xù)著很多人習(xí)慣的編程方式,講了變量初始化帶來的問題。變量的初始化包含變量的和賦值兩個部分,一個編程的原則是“變量要完成初始化”。這就衍生出一個壞味道:變量的和賦值是分離的。二者分離帶來的問題就是,把賦值的過程與業(yè)務(wù)處理混雜在一起。發(fā)現(xiàn)變量與賦值分離一個做法就是在前面加上式的方式進(jìn)行集合的初始化,讓初始化的過程完成。再進(jìn)一步,以式的標(biāo)如果今天的內(nèi)容你只能記住一件事,那請記?。和瓿勺兞康某跏蓟瘏⒖假Y料DSL:你也可以設(shè)計一門自己 歸科技所有 不得售賣。頁面已增加防盜追蹤,將依法其上一 09|可變的數(shù)據(jù):不要讓你的代碼“失控下一 11|依賴:你可能還沒發(fā)現(xiàn)問題

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論