成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

重構(gòu)改善既有的代碼設(shè)計(代碼的壞味道)

Code4App / 2780人閱讀

摘要:壞的味道指的是應(yīng)該被修改,被重構(gòu)的代碼,不具有可讀性,復(fù)用性,判斷邏輯復(fù)雜,冗余代碼。它們通常能指出代碼用途和實(shí)現(xiàn)手法之間的語義距離。把所有和這個變量相關(guān)的代碼新建一個類放入。但這往往不夠,請反復(fù)運(yùn)用將某些行為移入類,直到者的協(xié)議一致為止。

壞的味道:指的是應(yīng)該被修改,被重構(gòu)的代碼,不具有可讀性,復(fù)用性,判斷邏輯復(fù)雜,冗余代碼。應(yīng)該使用各種重構(gòu)的手法去改變它!
Duplicated Code(重復(fù)代碼)
如果你在一個以上的地點(diǎn)看到相同的程序結(jié)構(gòu),那么可以肯定的:設(shè)法將他們合而為一,程序會變得更好。

同一個類的兩個函數(shù)含有相同的表達(dá)式

兩個互為兄弟子類內(nèi)含相同表達(dá)式

如果兩個毫不相關(guān)的類出現(xiàn)Duplicated Code 應(yīng)該考慮對其中一個將重復(fù)代碼提煉到一個獨(dú)立類種,然后在另一個類內(nèi)使用這個新類。

Long Method(過長函數(shù))
我們應(yīng)當(dāng)遵循這樣一條原則:每當(dāng)感覺需要以注釋來說明點(diǎn)什么的時候,我們就需要說明的東西寫進(jìn)一個獨(dú)立的函數(shù)中,并以器用途(而非實(shí)現(xiàn)手法)命名。

我們可以對一組甚至短短一行代碼做這件事。哪怕替換后的函數(shù)調(diào)用動作比函數(shù)自身還長,只要函數(shù)名稱能夠解釋其用途,我們也該毫不猶豫得那么做。關(guān)鍵不在于函數(shù)得長度,而在于函數(shù):“做什么”和“如何做”之間得語義距離。

如何確定該提煉哪一段代碼呢?一個很好得技巧是:尋找注釋。它們通常能指出代碼用途和實(shí)現(xiàn)手法之間的語義距離。如果代碼前方有一行注釋,就是再提醒你L可以將這段代碼替換成一個函數(shù),而且可以在注釋得基礎(chǔ)上給這個函數(shù)命名。就算只有一行代碼,如果他需要以注釋來說明,那也值得將它提煉導(dǎo)獨(dú)立函數(shù)去。

條件表達(dá)式和循環(huán)常常也是提煉得信號。可以使用Decompose Conditional處理?xiàng)l件表達(dá)是。至于循環(huán),你應(yīng)該將循環(huán)和期內(nèi)的代碼提煉導(dǎo)一個獨(dú)立的函數(shù)中

Large Class(過大的類)

如果類中有太多的實(shí)例變量,可以將幾個變量提煉至新類內(nèi)。提煉時應(yīng)該選擇類內(nèi)彼此相關(guān)的變量,將它們放在一起

類內(nèi)如果有太多代碼,把多余的東西消弭于類內(nèi)部。如果有五個“百行代碼”,它們之中很多代碼都相同,那么或許你可以把它們變成五個“十行函數(shù)”和十個提煉出的“雙行函數(shù)”。

Long Parameter List(過長的參數(shù)列)

如果已有的對象發(fā)出一條請求就可以取代一個參數(shù),那么你應(yīng)該激活重構(gòu)手法Replace Paramter with Method。在這里,“已有的對象”可能時函數(shù)所屬類內(nèi)一個字段,也可能是另一個參數(shù)。你也可以運(yùn)用Preserve Whole Object將來自同一個對象的一堆數(shù)據(jù)收集起來,并以該對象替換它們。如果某些數(shù)據(jù)缺乏合理的對象歸屬,可以使用Introduce Parameter Object 為它們制造出一個“參數(shù)對象”。

Divergent Change(發(fā)散式變化)
一旦需要修改,我們希望能夠跳到系統(tǒng)的某一點(diǎn),只在該處做修改。如果不能做到這點(diǎn),你就嗅出兩種相關(guān)的刺鼻味道中的一種了。

針對某一外界變化的所有相應(yīng)修改,都只應(yīng)發(fā)生在單一類中,而這個新類內(nèi)的所有內(nèi)容都應(yīng)該反應(yīng)此變化,為此,你應(yīng)該找出某特定原因而造成的所有變化,然后運(yùn)用Extract Class將它們提煉導(dǎo)另一個類中。

Shotgun Surgery(散彈式修改)
遇到某種變化,你都必須在不同類內(nèi)做出許多小修改,你所面臨的壞味道就是shotgun Surgery,如果需要修改的代碼散布四處,你不但很難找到它們,也很容易忘記某個重要的修改

這種情況下應(yīng)該使用Move MethodMove Field把所有需要修改的代碼放進(jìn)同一個類。如果眼下沒有合適的類可以安置這些代碼,就創(chuàng)造一個。通常可以運(yùn)用inline class把一系列相關(guān)行為放進(jìn)同一個類。

Divergent change 是指“一個類受多種變化影響”,shotgun surgery則是指“一種變化引發(fā)多個類相應(yīng)修改”。者兩種情況下你都會希望整理代碼,使“外界變化”與“需要修改的類”趨于一一對應(yīng)。

Feature Envy(依戀情結(jié))
函數(shù)對某個類的興趣高過對自己所處類的興趣,通常焦點(diǎn)便是數(shù)據(jù),某個函數(shù)為了計算某個值,從另一個對象那調(diào)用幾乎半打的額取值函數(shù)。

療法顯而易見:把這個函數(shù)移至另一個地點(diǎn)。

一個函數(shù)往往會用到幾個類的功能,那么它究竟該被置于何處呢?我們的原則是判斷哪個類擁有最多被此函數(shù)使用的數(shù)據(jù),然后把這個函數(shù)和那些數(shù)據(jù)擺在一起。

Data Clumps(數(shù)據(jù)泥團(tuán))

兩個類中相同的字段、許多函數(shù)簽名中相同的參數(shù)。這些總是綁在一起出現(xiàn)的數(shù)據(jù)真應(yīng)該擁有屬于它們自己的對象

一個好的評判方法是:刪掉眾多數(shù)據(jù)中的一項(xiàng)。這么做,其他數(shù)據(jù)有沒有因而失去意義?如果它們不在有意義,這就是個明確信號:你應(yīng)該為它們產(chǎn)生一個新對象。

Primitive Obsession(基本類型偏執(zhí))
對象的一個極大的價值在于:它們模糊(甚至打破)了橫亙于基本類型數(shù)據(jù)和體積較大類之間的界限

可以運(yùn)用Replace Data Vlaue with Object將原本多帶帶存在的數(shù)據(jù)值替換為對象

如果想要替換的數(shù)據(jù)值是類型碼,而它并不影響行為,則可以運(yùn)用Replace type Code with class 將它替換

如果有與類型碼有關(guān)的條件表達(dá)式,可運(yùn)用 Replace Type Code with Subclass 或 Replace Type Code with State/Strategy

Switch Statements(switch 驚悚現(xiàn)身)

大多數(shù)時候,一看到switch語句,你就應(yīng)該考慮以多態(tài)來替換它。問題是多態(tài)應(yīng)該出現(xiàn)在哪兒?switch語句常常根據(jù)類型碼進(jìn)行選擇,你要的是“與該類型碼相關(guān)的函數(shù)或類

Parallel Inheritance Hierarchies(平行繼承體系)
Shotgun Surgery的特殊情況,在這種情況下,每當(dāng)你為某個類增加一個子類,也必須為另一個類相應(yīng)的增加一個子類。如果你發(fā)現(xiàn)某個繼承體系的名稱前綴和另一個繼承體系名稱前綴完全相同,便是聞到了這種壞味道

消除這種重復(fù)性的一般策略是:讓一個繼承體系的實(shí)例引用另一個繼承體系的實(shí)例。再運(yùn)用Move Method 和Move Field,就可以就將引用端的繼承體系消弭于無形

Lazy Class(冗贅類)
如果一個類的所得不值其身價,它就該消失

如果某些子類沒有做足夠的工作,試試Collapse Hierarchy。對于幾乎沒用的組件,你應(yīng)該以Inline Class對付它們

Speculative Generality(夸夸其談的未來性)
不要過分對的為未來考慮
如果你的某個抽象類其實(shí)沒有太大作用,請運(yùn)用Collapse Hierarchy。不必要的委托可運(yùn)用Inline Class除掉。如果函數(shù)的某些參數(shù)違背用上,可對它實(shí)施Remove Parameter。如果函數(shù)名稱帶有多余的抽象意味,應(yīng)該對它實(shí)施rename Method,讓它現(xiàn)實(shí)一點(diǎn)
Temporary Field (令人迷惑的暫時字段)

某個實(shí)例變量僅為某種特定的情況而設(shè)。這樣的代碼讓人不易理解,因?yàn)槟阃ǔUJ(rèn)為對象在所有時候都需要它的所有變量,在未被使用的情況下猜測當(dāng)初其設(shè)置目的,會讓你發(fā)瘋的。把所有和這個變量相關(guān)的代碼新建一個類放入。

Message Chains(過度耦合的消息鏈)
如果你看到用戶一個對象請求另一個對象,然后后者請求另一個對象,然后再請求另一個對象這就是消息鏈

先觀察消息鏈最終得到的對象用來干什么的,看看能否以Extract Method 把使用該對象的代碼提煉到一個獨(dú)立的函數(shù)中再運(yùn)用Move Method 把這個函數(shù)推入消息鏈

Middle Man(中間人)
人們可能過度運(yùn)用委托,會有某個接口有一半的函數(shù)都委托給其他類,這樣就是過度運(yùn)用, 使用Remove Middle Man ,直接和真正負(fù)責(zé)的對象打交道
Inappropriate Intimacy(狎昵關(guān)系)

過分狎昵的類必須拆散. 你可以采用Move MethodMove Field 幫它們劃分界限, 從而減少狎昵行徑. 你可以可以看看是否可以運(yùn)用Change Bidirectional Association to Unidirectional (將雙向關(guān)聯(lián)改為單向關(guān)聯(lián))讓其中一個類對另一個斬斷情絲.

如果兩個類實(shí)在是情投意合, 可以運(yùn)用Extract Class 把兩者的共同點(diǎn)提煉到一個安全的地點(diǎn),讓它們坦蕩地使用這個新類. 或者也可以嘗試運(yùn)用Hide Delegate讓另一個類來為它們傳遞相思情.

繼承往往造成過度親密, 因?yàn)樽宇悓Τ惖牧私饪偸浅^超類的主管愿望. 如果你覺的該讓這個孩子獨(dú)立生活了, 請運(yùn)用Replace Inheritance with Delegation 讓它離開繼承體系.

Alternative Class with Different Interfaces(異曲同工的類)

如果兩個函數(shù)做同一件事,卻有著不同的簽名,請運(yùn)用Rename Method根據(jù)它們的用途重新命名。但這往往不夠,請反復(fù)運(yùn)用?Move Method將某些行為移入類,直到2者的協(xié)議一致為止。如果你必須反復(fù)而贅余的移入代碼才能完成這些,或許可運(yùn)用Extract SuperClass

Incomplete Library Class(不完美的類庫)

如果只想修改類庫的一兩個函數(shù),可以運(yùn)用Introduce Foreign Method 如果想要添加一大堆額外行為,就得運(yùn)用Introduce Local Extension

Data Class(純稚的數(shù)據(jù)類)
所謂Data Class是指:它們擁有一些值域(fields),以及用于訪問(讀寫〕這些值域的函數(shù),除此之外一無長物。

這樣的classes只是一種「不會說話的數(shù)據(jù)容器」,它們幾乎一定被其他classes過份細(xì)瑣地操控著。這些classes早期可能擁有public值域,果真如此你應(yīng)該在別人注意到它們之前,立刻運(yùn)用Encapsulate Field?(封裝值域)將它們封裝起來。如果這些classes內(nèi)含容器類的值域(collection fields),你應(yīng)該 檢査它們是不是得到了恰當(dāng)?shù)姆庋b;如果沒有,就運(yùn)用 Encapsulate Collection(封裝群集)?把它們封裝起來。對于那些不該被其他classes修改的值域,請運(yùn)用 Remove Setting Method(移除設(shè)置函數(shù))。

然后,找出這些「取值/設(shè)值」函數(shù)(getting and setting methods)被其他classes運(yùn)用的地點(diǎn)。嘗試以Move Method(搬移函數(shù))?把那些調(diào)用行為搬移到Data Class來。如果無法搬移整個函數(shù),就運(yùn)用 Extract Method(提煉函數(shù))?產(chǎn)生一個可被搬移的函數(shù)。不久之后你就可以運(yùn)用Hide Method?(隱藏某個函數(shù))把這些「取值/設(shè)值」函數(shù)隱藏起來了。

Refused Bequest(被拒絕的遺贈)
指的是一個子類,不需要父類中的過多方法

這樣我們可以為這個子類創(chuàng)建一個兄弟類,把父類中不需要的方法下移到兄弟類中去。 如果子類復(fù)用了超類的行為(實(shí)現(xiàn)),卻又不愿意支持超類的接口。不過即使不愿意繼承接口,也不要胡亂修改繼承體系,應(yīng)該運(yùn)用Replace Inheritance with Delegation 來達(dá)到目的

Comments(過多的注釋)
引用作者的一句話"當(dāng)你感覺需要撰寫注釋,請先嘗試重構(gòu),試著讓所有注釋都變得多余。"

并不是說寫注釋不好,而是當(dāng)你寫一段很長的注釋來說明代碼邏輯的時候,說明這段代碼真的很糟糕,你就要考慮重構(gòu)了。?

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/72464.html

相關(guān)文章

  • 重構(gòu)-改善代碼設(shè)計(三)--代碼的壞味道

    摘要:壞味道的代碼重復(fù)代碼會自動標(biāo)注重復(fù)的代碼。一般都是遇到真實(shí)情況后才考慮得到霰彈式修改添加或修改一個功能引發(fā)多個類相應(yīng)修改遇到這種情況可以移動代碼,將需要修改的代碼都放在同一個類下。被拒絕的遺贈子類應(yīng)該繼承超類的函數(shù)和數(shù)據(jù)。 壞味道的代碼 重復(fù)代碼 idea會自動標(biāo)注重復(fù)的代碼。一般重復(fù)代碼就是可以重構(gòu)的點(diǎn)。 同一個類的兩個函數(shù)還有相同的表達(dá)式,這時需要提煉出重復(fù)代碼。 兩個互為兄弟的...

    Mr_houzi 評論0 收藏0
  • 重構(gòu)---改善代碼設(shè)計

    摘要:為何重構(gòu)重構(gòu)有四大好處重構(gòu)改進(jìn)軟件設(shè)計如果沒有重構(gòu),程序的設(shè)計會逐漸腐敗變質(zhì)。經(jīng)常性的重構(gòu)可以幫助維持自己該有的形態(tài)。你有一個大型函數(shù),其中對局部變量的使用使你無法采用。將這個函數(shù)放進(jìn)一個單獨(dú)對象中,如此一來局部變量就成了對象內(nèi)的字段。 哪有什么天生如此,只是我們天天堅持。 -Zhiyuan 國慶抽出時間來閱讀這本從師傅那里借來的書,聽說還是程序員的必讀書籍。 關(guān)于書的高清下載連...

    baihe 評論0 收藏0
  • 編寫可維護(hù)的代碼

    摘要:編寫可維護(hù)的代碼前言我們在修改他人代碼的時候,閱讀他人代碼所花的時間經(jīng)常比實(shí)現(xiàn)功能的時間還要更多如果程序結(jié)構(gòu)不清晰,代碼混亂。這樣可以去除重復(fù)的代碼,提高靈活性關(guān)鍵點(diǎn)找出不同的地方和重復(fù)的地方。 編寫可維護(hù)的代碼 前言 我們在修改他人代碼的時候,閱讀他人代碼所花的時間經(jīng)常比實(shí)現(xiàn)功能的時間還要更多 如果程序結(jié)構(gòu)不清晰,代碼混亂 。牽一發(fā)而動全身。那維護(hù)起來就更難維護(hù)了 可讀性 可理解性...

    imingyu 評論0 收藏0
  • 重構(gòu):一項(xiàng)常常被忽略的基本功

    摘要:無論如何,單元測試一直是一中非常重要卻常常被忽視的技能。在實(shí)踐中,重構(gòu)的要求是很高的它需要有足夠詳盡的單元測試,需要有持續(xù)集成的環(huán)境,需要隨時隨地在小步伐地永遠(yuǎn)讓代碼處于可工作狀態(tài)下去進(jìn)行改善。 showImg(https://segmentfault.com/img/bVbttWF?w=1000&h=528); 五月初的時候朋友和我說《重構(gòu)》出第 2 版了,我才興沖沖地下單,花了一個...

    idealcn 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<