中文字幕在线观看,亚洲а∨天堂久久精品9966,亚洲成a人片在线观看你懂的,亚洲av成人片无码网站,亚洲国产精品无码久久久五月天

診斷Java代碼:設(shè)計(jì)輕松的代碼維護(hù)

2018-06-11    來(lái)源:

容器云強(qiáng)勢(shì)上線!快速搭建集群,上萬(wàn)Linux鏡像隨意使用

  有效調(diào)試源自良好的編程。設(shè)計(jì)易于維護(hù)的程序是程序員面臨的最困難挑戰(zhàn)之一,其部分原因在于程序通常并不是由那些編寫(xiě)代碼的程序員維護(hù)的。為了有效維護(hù)這樣的程序,新程序員必須能夠快速了解程序的工作原理,如果程序員能夠單獨(dú)理解整個(gè)程序中各個(gè)小部分,那么就可以容易地了解程序的工作原理。

??通過(guò)討論可變性、可譯碼性、私有方法、最終方法、最終類(lèi)、本地代碼、單元測(cè)試以及重構(gòu)問(wèn)題,我們將簡(jiǎn)述編寫(xiě)程序的一些方法,以幫助使程序更易理解和維護(hù)。

??可變性和可譯碼性
??首先討論可變性問(wèn)題。如果在一個(gè)程序的計(jì)算期間,其每一部分所處理的數(shù)據(jù)都沒(méi)有被該程序的其它、遠(yuǎn)程部分更改,那么就很容易單獨(dú)理解該程序的各個(gè)部分。

??太多信息
??例如,請(qǐng)考慮一個(gè)使用容器類(lèi)實(shí)例的程序,可以修改其中的成分鏈接。每次將容器從程序某一部分上的方法傳遞到該程序其它部分的方法,以及每次調(diào)用 new 表達(dá)式(其中容器被作為參數(shù)傳遞)時(shí),容器就可能脫離調(diào)用方法的控制發(fā)生改變。

??在我們首先理解調(diào)用方法調(diào)用的每個(gè)方法如何修改容器之前,我們不能真正確保我們理解了調(diào)用方法,由此我們?cè)\斷錯(cuò)誤的能力也就更差。如果這些被調(diào)用的每個(gè)方法都依次調(diào)用其它修改方法,那么維護(hù)程序員為了理解單個(gè)方法必須閱讀的代碼總量會(huì)迅速增加,多得無(wú)法控制。

??由于這個(gè)原因,對(duì)可變?nèi)萜骱筒豢勺內(nèi)萜魇褂貌煌?lèi)會(huì)非常有利。在不可變版本中,容器的字段可以標(biāo)記成 final。

??求助于函數(shù)樣式
??相對(duì)于修改舊數(shù)據(jù),為構(gòu)造新數(shù)據(jù)而進(jìn)行代碼編寫(xiě)稱為函數(shù)樣式,因?yàn)槌绦虻姆椒ㄅc數(shù)學(xué)函數(shù)相似,其行為是根據(jù)每個(gè)輸入所返回的輸出來(lái)單獨(dú)描述的。

??函數(shù)樣式經(jīng)常被忽略的優(yōu)點(diǎn)是相當(dāng)容易單獨(dú)理解程序的個(gè)別組件。如果方法所操縱的數(shù)據(jù)決不會(huì)被其主體中執(zhí)行的任何操作改變,那么程序員要理解該方法必須做的就是理解那些操作返回的結(jié)果。將之與前面的一個(gè)方法調(diào)用幾個(gè)其它方法的方案相對(duì)照,那個(gè)方案中的其它幾個(gè)方法都修改這一方法所操作的數(shù)據(jù)結(jié)構(gòu)。

??Java 語(yǔ)言的一個(gè)相當(dāng)好的特性是它允許我們使用 final 關(guān)鍵字(作為類(lèi)型檢查器的偽指令)來(lái)聲明何時(shí)我們要使某個(gè)數(shù)據(jù)成為不可變。

??使用 final 關(guān)鍵字來(lái)避免變化是“釘住”類(lèi)的方法行為的一個(gè)好方法。每次修改字段時(shí),都有可能改變引用該字段的方法的行為。另外,將字段標(biāo)記為 final 讓閱讀程序的其他程序員立即知道:不管整個(gè)程序有多大,決不要修改該字段。例如,請(qǐng)考慮下列表示不可變列表的類(lèi)層次結(jié)構(gòu)。

清單 1. 表示不可變列表的類(lèi)層次結(jié)構(gòu)

abstract class List {...}
class Empty extends List {...}
class Cons extends List {
private final Object first;
private final List rest;
}

??這些類(lèi)中的所有字段都被標(biāo)記成 final。要確保這些類(lèi)的實(shí)例不可變,這樣做夠了嗎?不太夠。當(dāng)然,即使字段被標(biāo)記成 final,該字段本身的組件可能不是 final,記住這一點(diǎn)很重要。當(dāng)那些組件更改時(shí),引用那些組件的程序的任何部分可能會(huì)被修改,而不管字段本身是否改變。在上面的示例中,盡管列表的組成元素不能被修改,但是我們必須檢查那些元素本身沒(méi)有包含可能被修改的非最終字段。

??在這種情形中,盡管列表可能包含可變?cè)兀俏覀兛梢钥吹酱鎯?chǔ)在給定列表中的元素序列由于以下原因而不可變:Empty 列表(即,長(zhǎng)度為零的列表)的實(shí)例根本不包含任何元素;因此不能修改它們。Cons(非空列表)實(shí)例包含兩個(gè)字段,都是 final。第一個(gè)字段包含該列表的第一個(gè)元素,它不能被修改;第二個(gè)字段包含一個(gè)列表,其中包含所有剩余元素。如果這個(gè)列表的內(nèi)容不可變,那么該包含列表也不可變。

??但是包含在這第二個(gè)字段中的列表比包含列表的長(zhǎng)度小一,所以如果我們知道長(zhǎng)度為 n 的所有列表都不可變,那么我們就知道長(zhǎng)度為 n + 1 的列表也不可變。因?yàn)槲覀円呀?jīng)知道長(zhǎng)度為零的列表不可變,所以我們也知道長(zhǎng)度為 1、2、3 等的列表同樣不可變。

??跟蹤與此類(lèi)似的數(shù)據(jù)結(jié)構(gòu)連接會(huì)很乏味,但當(dāng)您能確定這種結(jié)構(gòu)的全局特性(諸如不可變性)時(shí),這樣做是值得的。

??控制變化
??防止出現(xiàn)不期望的變化的最佳策略就是盡可能避免所有變化。只有當(dāng)出現(xiàn)一定要改變的原因時(shí)(例如,當(dāng)這樣做大大簡(jiǎn)化了代碼結(jié)構(gòu)時(shí)),我們才應(yīng)該使用它。當(dāng)可以避免變化時(shí),所產(chǎn)生的好處是巨大的(在較低的維護(hù)費(fèi)用和增強(qiáng)的健壯性方面)。

??即使存在一定要改變數(shù)據(jù)的原因,最好還是設(shè)法控制那種變化,從而盡可能限制可能產(chǎn)生的破壞。迭代器和流是數(shù)據(jù)結(jié)構(gòu)的極佳示例,這些數(shù)據(jù)結(jié)構(gòu)明確設(shè)計(jì)成通過(guò)允許我們以常規(guī)的、定義良好的形式利用一系列元素,而不是明確修改這些元素的某個(gè)句柄來(lái)控制變化。

??私有方法
??就如同將字段設(shè)置成 final 有助于限制對(duì)字段值產(chǎn)生外部影響一樣,將它們?cè)O(shè)置成 private 有助于限制它們對(duì)程序其它部分產(chǎn)生的影響。如果字段是私有的,那么我們可以確信該程序的其它部分都不與它直接相關(guān)。如果我們除去了該字段,并替換了該類(lèi)數(shù)據(jù)的內(nèi)部表示,那么我們只要關(guān)心修正該類(lèi)內(nèi)部的方法,以正確訪問(wèn)新數(shù)據(jù)。

??在前面的示例中,請(qǐng)注意類(lèi) Cons 的字段是私有的。這樣的話,我們就可以通過(guò)讀方法(getter)及類(lèi)似方法來(lái)控制如何訪問(wèn)那些元素。如果我們列表的未來(lái)維護(hù)人員有時(shí)想要修改列表的內(nèi)部表示(例如,可以論證在某些平臺(tái)上,基于數(shù)組的列表或許更有效),那么程序員可以這樣做,而不必修改或甚至查看那些列表的任何客戶機(jī)。他只要重寫(xiě) getter 就可以對(duì)新數(shù)據(jù)采取適當(dāng)?shù)牟僮鳌?/P>

??最終方法、最終類(lèi)和理解本地代碼
??與將字段標(biāo)記成 final 形成對(duì)比的是,將方法標(biāo)記成 final 通常被指責(zé)為與 OO 設(shè)計(jì)目標(biāo)不一致,因?yàn)檫@樣禁止繼承多態(tài)性。但是在嘗試?yán)斫獯笮统绦虻男袨闀r(shí),這樣有助于了解什么方法沒(méi)有被重寫(xiě)。

??現(xiàn)在良好的 OO 設(shè)計(jì)涉及使用大量繼承,這的確是事實(shí)。事實(shí)上,繼承是許多 OO 設(shè)計(jì)模式的核心。但是那并不意味著我們應(yīng)該允許我們編寫(xiě)的每個(gè)方法都被重寫(xiě)。通常程序?qū)㈦[式地依賴某些沒(méi)有被重寫(xiě)的關(guān)鍵方法。通過(guò)將這樣的方法標(biāo)記成 final,我們將允許其他程序員更好地理解調(diào)用該方法的表達(dá)式行為。

??另外,將類(lèi)標(biāo)記成 final 會(huì)極大提高可譯碼性。它會(huì)真正有助于初步了解程序中哪些類(lèi)決不會(huì)被子類(lèi)化。事實(shí)上,我認(rèn)為:只有不應(yīng)被標(biāo)記成 final 的類(lèi)才是程序中真正被子類(lèi)化的類(lèi),以及那些有意從外部組件上被子類(lèi)化的類(lèi)(作為程序設(shè)計(jì)的固有部分)。

??有人可能認(rèn)為這個(gè)概念會(huì)束縛將來(lái)的代碼維護(hù)人員,使他們不能擴(kuò)展代碼。我認(rèn)為這肯定不會(huì)限制他們。如果程序?qū)?lái)的維護(hù)人員需要擴(kuò)展代碼以包含以前不存在的子類(lèi),那么只要他們擁有對(duì)源代碼的訪問(wèn)權(quán)(如果他們無(wú)權(quán)訪問(wèn),那么如何成為該代碼的“維護(hù)人員”呢?),刪除相應(yīng)類(lèi)上的 final 關(guān)鍵字并重新編譯并不太困難。

??同時(shí),那個(gè)被添加的關(guān)鍵字充當(dāng)關(guān)于該程序的重要不變量的自動(dòng)驗(yàn)證文檔形式(“自動(dòng)驗(yàn)證”是因?yàn)槿绻撐臋n被破壞,那么該程序甚至不會(huì)編譯)。通過(guò)強(qiáng)制開(kāi)發(fā)人員自覺(jué)選擇何時(shí)要?jiǎng)h除這樣的不變量,我們可以幫助減少錯(cuò)誤的引入。

??單元測(cè)試和變化
??單元測(cè)試總是能夠有助于理解具有副作用的代碼。如果一套單元測(cè)試充分證明了方法在程序中的作用,那么程序員只要通過(guò)閱讀其單元測(cè)試就可以更迅速理解每個(gè)方法。當(dāng)然,單元測(cè)試是否真的涵蓋了所有的作用是個(gè)大問(wèn)題。類(lèi)似于 Clover 的有效范圍分析工具在這里可以提供某種程度的幫助。

??但是,請(qǐng)注意單元測(cè)試本身要比編寫(xiě)嚴(yán)格的函數(shù)方法簡(jiǎn)單得多。要測(cè)試嚴(yán)格的函數(shù)方法,涉及的全部就是用各種具有代表性的輸入調(diào)用這些方法,并檢查它們的輸出(并確保它們?cè)趹?yīng)該拋出異常時(shí)能拋出)。

??在測(cè)試修改數(shù)據(jù)結(jié)構(gòu)狀態(tài)的方法時(shí),我們必須首先執(zhí)行這樣的操作,這些操作是將輸入數(shù)據(jù)放入該方法所期望的狀態(tài)中所需要的,然后在調(diào)用該方法之后,檢查是否正確執(zhí)行了客戶機(jī)所期望的數(shù)據(jù)的每次修改。

??用重構(gòu)工具封裝
??在編寫(xiě)新代碼時(shí)這些技巧很有用,但是當(dāng)您必須維護(hù)幾乎不能譯碼的舊代碼時(shí),怎么辦呢?重構(gòu)、重構(gòu)、還是重構(gòu)。

??盡管重構(gòu)舊代碼很費(fèi)時(shí),但是這些時(shí)間是值得的,特別是所有支持重構(gòu)的工具現(xiàn)在也支持 Java 代碼了,F(xiàn)在已經(jīng)有許多自動(dòng)重構(gòu) Java 代碼的強(qiáng)大工具,這些工具可以自動(dòng)保存關(guān)鍵的不變量。

??重構(gòu) Java 代碼的一個(gè)功能相當(dāng)齊全的工具是 IDEA 開(kāi)發(fā)環(huán)境。該環(huán)境對(duì)相當(dāng)多的 Martin Fowler 重構(gòu)模式提供自動(dòng)支持。我找到的另一個(gè)非常有用的工具是 CodeGuide,它是一個(gè)來(lái)自德國(guó)的 IDE。盡管相對(duì)于 IDEA,其自動(dòng)重構(gòu)的列表很小,但是它顯示了一個(gè)極其強(qiáng)大的特性 ? 連續(xù)編譯。當(dāng)您輸入新代碼時(shí),CodeGuide 分析它并告知您項(xiàng)目中是否不完整(當(dāng)然,這產(chǎn)生很短的延遲,它防止對(duì)每次擊鍵發(fā)出錯(cuò)誤信號(hào))。

??盡管連續(xù)編譯對(duì)響應(yīng)產(chǎn)生負(fù)面影響,但是在某些上下文中非常值得這樣的等待。例如,您可以在字段前輸入 final,會(huì)立即看到項(xiàng)目中是否不完整。如果無(wú),那么您知道該字段在該程序的任何地方都沒(méi)有被修改。同樣,您可以在字段之前輸入 private,那么立即獲得對(duì)該字段的所有外部訪問(wèn)的列表(以錯(cuò)誤的形式)。

??CodeGuide 的另一個(gè)極佳特性是它用泛型類(lèi)型對(duì) JSR-14 實(shí)驗(yàn)擴(kuò)展提供了無(wú)縫支持(計(jì)劃正式添加到 Java 1.5)。

??盡管為了可譯碼性而編寫(xiě)代碼會(huì)花費(fèi)非常多的時(shí)間和精力,但是它會(huì)有助于提高代碼的生命期和健壯性,而且它可以顯著提高面臨維護(hù)代碼任務(wù)的那些程序員的生活質(zhì)量。最后,重構(gòu)舊代碼使之

標(biāo)簽: 代碼 計(jì)劃 問(wèn)題 選擇

版權(quán)申明:本站文章部分自網(wǎng)絡(luò),如有侵權(quán),請(qǐng)聯(lián)系:west999com@outlook.com
特別注意:本站所有轉(zhuǎn)載文章言論不代表本站觀點(diǎn)!
本站所提供的圖片等素材,版權(quán)歸原作者所有,如需使用,請(qǐng)與原作者聯(lián)系。

上一篇:Google CEO安撫用戶 稱搜索記錄不會(huì)被泄露

下一篇:戴爾直銷(xiāo)網(wǎng)站標(biāo)錯(cuò)價(jià) 三小時(shí)損失千萬(wàn)元