(轉(zhuǎn))編寫優(yōu)良的Java代碼
也許有多少專業(yè)Java程序員,就有多少種對(duì)于編寫優(yōu)良Java代碼的答案!
以下可能是大多數(shù)專業(yè)Java程序員都贊同、也愿意執(zhí)行的八點(diǎn)規(guī)則:
1) 保持類最小
還有什么比擁有較少的類更壞的事情嗎?可能不會(huì)再有了。當(dāng)然,最好還是有滿足自己需要的類。
一般來(lái)說(shuō),一個(gè)帶有大量方法的類總是具有一些不屬于這里的方法,因?yàn)檫@個(gè)龐大的對(duì)象所做的事情太多了。如果您有一個(gè)帶有 100 個(gè)方法的對(duì)象,就應(yīng)該好好想想,這個(gè)對(duì)象是否應(yīng)該拆成多個(gè)對(duì)象。大類通常在大學(xué)里大行其道。Java 代碼與之一樣。
2) 保持方法最小
小方法就與小類一樣可取,并且原因也類似。
很多有經(jīng)驗(yàn)的 OO 程序員對(duì) Java 語(yǔ)言具有的苦惱之一就是,它提供大量的 OO 能力,但是卻沒(méi)有教他們?nèi)绾巫龊?OO。換句話說(shuō),它給了他們很多繩子去捆綁自己(盡管至少?zèng)]有 C++ 給他們的多)。能看到這一點(diǎn)的一個(gè)常見(jiàn)地方是main()
方法離得很遠(yuǎn)的類,或者一個(gè)單個(gè)的名叫doIt()
的方法。僅僅因?yàn)?em>能夠 將所有的代碼放在類中的單個(gè)方法中,并不意味著就應(yīng)該 如此。Java 語(yǔ)言比很多其他 OO 語(yǔ)言具有更多的語(yǔ)法糖,所以一定的羅嗦是必要的,但是不要過(guò)了度。思考一下這些超長(zhǎng)的方法。滾動(dòng)十屏代碼去了解代碼所做的工作是很艱難的。該方法做什么工作?您需要泡上一杯大大的咖啡花幾個(gè)小時(shí)去研究才能知道。一個(gè)小的,甚至微小的方法是一個(gè)容易看懂的代碼塊。運(yùn)行時(shí)效率不是要具有小方法的原因,可讀性才是真正的目標(biāo)。這將使得代碼更加容易維護(hù),并且在需要添加功能時(shí)更加容易更改。
將每個(gè)方法局限于執(zhí)行一項(xiàng)工作。
3) 給方法取好名稱
本要求很簡(jiǎn)單,只需要花上一點(diǎn)時(shí)間想出一個(gè)具有描述性的方法名,足夠明了但不過(guò)長(zhǎng)。
這一技巧很簡(jiǎn)單,也許在小規(guī)模的代碼行中是微不足道的,但是當(dāng)代碼變得越來(lái)越復(fù)雜時(shí),它就會(huì)顯露出驚人的威力。
4) 保持類的數(shù)量最少
XP 中關(guān)于簡(jiǎn)單設(shè)計(jì)的其中一個(gè)指導(dǎo)方針是,用盡可能少的類完成一個(gè)目標(biāo)。如果您需要另一個(gè)類,盡管添加就是了。如果另一個(gè)類將使得代碼更簡(jiǎn)單或者簡(jiǎn)化您的意圖表達(dá),那么就添加這個(gè)類吧。但是沒(méi)有理由只是為了具有而具有類。當(dāng)然,通常項(xiàng)目早期比結(jié)束時(shí)具有的類要少,但是一般將代碼重構(gòu)成更多的類比組合類更容易。如果您有一個(gè)具有大量方法的類,那么分析一下,看是否有另一個(gè)對(duì)象陷入在其中,正在等待出去。如果有的話,就創(chuàng)建一個(gè)新的對(duì)象。
在我經(jīng)歷的幾乎所有 Java 項(xiàng)目上,沒(méi)有人害怕創(chuàng)建類,但是我們也總是試圖在不降低意圖清晰度的情況下,減少類的數(shù)量。
5) 保持注釋的數(shù)據(jù)最少
我過(guò)去常常在代碼中編寫很多的注釋,讀起來(lái)就像一本書(shū)。后來(lái)我變得聰明一些了。
每一個(gè)計(jì)算機(jī)科學(xué)程序、每一本編程書(shū)籍和我知道的很多程序員,都要您給代碼編寫注釋。在有些情況下,注釋是有幫助的。在許多情況下,注釋使得代碼維護(hù)更加困難。想想您更改代碼時(shí)必須做什么。有注釋嗎?如果有的話,您最好更改注釋,否則它會(huì)可怕地過(guò)期,甚至隨著時(shí)間的推移,根本就不再能夠描述代碼。依我的經(jīng)驗(yàn),幾乎會(huì)使維護(hù)時(shí)間加倍。
我的經(jīng)驗(yàn)法則是:如果代碼太難閱讀和理解而需要注釋,我就需要使它足夠清晰,從而不需要注釋。代碼可能會(huì)太長(zhǎng),或者做太多的事情。如果這樣的話,我就簡(jiǎn)化它。代碼可能太隱晦。如果這樣的話,我就添加助手方法,使之清晰。實(shí)際上,在與同一團(tuán)隊(duì)的其他成員一起進(jìn)行 Java 編程的三年當(dāng)中,我所編寫的注釋屈指可數(shù)。保持代碼清晰!如果您需要系統(tǒng)或者某個(gè)特定組件的全景描述,就編寫一個(gè)簡(jiǎn)短的注釋來(lái)描述。
羅嗦的注釋一般比較難維護(hù),通常不及一個(gè)小的、編寫良好的方法那么好地表達(dá)意圖,并且很快就會(huì)過(guò)期。根本不要過(guò)分依賴注釋。
6) 使用一致的風(fēng)格
編碼風(fēng)格實(shí)際上是您的環(huán)境中必然的并且可接受的東西。我甚至不知道哪一種風(fēng)格可以稱為“典型的”。這通常是個(gè)人品味問(wèn)題。
有時(shí)候,對(duì)于同一段代碼,可能有好幾種排列方法,實(shí)際上沒(méi)有絕對(duì)的“對(duì)”與“錯(cuò)”。實(shí)際項(xiàng)目過(guò)程中,應(yīng)該進(jìn)行協(xié)商,挑選出一種來(lái),然后一直堅(jiān)持用這一種。惟一絕對(duì)的風(fēng)格規(guī)則是一致性。如果一個(gè)項(xiàng)目上的每個(gè)人都用不同的風(fēng)格,那么閱讀代碼將變得很困難。挑選一種風(fēng)格并且不要改變。
7) 避免switch
一些 Java 程序員對(duì)
switch
語(yǔ)句情有獨(dú)鐘。我曾經(jīng)認(rèn)為它們很好,但是后來(lái)我認(rèn)識(shí)到了,一個(gè)switch
實(shí)際上就是幾個(gè)if
,并且通常意味著條件邏輯出現(xiàn)在代碼中的多個(gè)地方。這是代碼重復(fù),是應(yīng)該禁忌的。為什么?因?yàn)樵诙嗵幘哂邢嗤拇a使得代碼比較難更改。如果我在三處具有相同的switch
,并且想要更改對(duì)某個(gè) case 的處理,我就得在三處更改代碼。現(xiàn)在,如果您可以重構(gòu)具有單個(gè)
switch
語(yǔ)句的代碼,那會(huì)怎么樣呢?很好!我不相信使用它有什么壞處。在有些情況下,它比嵌套的if
更清晰。但是如果您看到它出現(xiàn)在很多地方,就有了應(yīng)該解決的問(wèn)題了。防止這一問(wèn)題的一個(gè)容易的方法是,避免switch
,除非它對(duì)于該工作是最佳的工具。依我的經(jīng)驗(yàn),它很少是最佳的。
8) 是public的
我把最具爭(zhēng)議的建議放在最后。做一下深呼吸。
我相信您會(huì)反對(duì)讓所有的方法都是
public
的。實(shí)例變量應(yīng)該是protected
的。當(dāng)然,許多專業(yè)程序員會(huì)害怕這種想法,因?yàn)槿绻魏螙|西都是公共的,那么任何人都可以更改它,也許會(huì)以未授權(quán)的方式更改。在任何東西都是公共可訪問(wèn)的世界中,您就不得不依賴于程序員紀(jì)律,以確保人們?cè)谄洳粦?yīng)該訪問(wèn)時(shí)不會(huì)訪問(wèn)其不應(yīng)該訪問(wèn)的東西。但是在編程生活當(dāng)中,很少有什么事情比想要訪問(wèn)一個(gè)不可見(jiàn)的變量或方法更受挫的了。如果您對(duì)代碼中您設(shè)想其他人不應(yīng)該訪問(wèn)的東西限制訪問(wèn),您就是在設(shè)想自己無(wú)所不知。這在大多數(shù)時(shí)候是一個(gè)危險(xiǎn)的假設(shè)。
當(dāng)使用其他人的代碼時(shí),這種受挫感會(huì)經(jīng)常出現(xiàn)。您會(huì)看到一個(gè)方法剛好做您想要做的工作,但是它不是公共可訪問(wèn)的。有時(shí),這有一個(gè)很好的原因,并且使得限制可訪問(wèn)性有意義。但是有時(shí),不
public
的惟一原因是,編寫代碼的人這樣想“沒(méi)有人需要訪問(wèn)該代碼”,或者他們這樣想“沒(méi)有人應(yīng)該訪問(wèn)該代碼,因?yàn)?#8230;…”,于是他們并沒(méi)有很好的理由。許多時(shí)候,人們使用private
是因?yàn)樗捎谩2灰@樣做。使方法是
public
的,變量是protected
的,直到您有一個(gè)很好的理由限制訪問(wèn)。
現(xiàn)在您知道了如何創(chuàng)建優(yōu)良的 Java 代碼,以及如何保持它優(yōu)良。
關(guān)于該主題,業(yè)界最好的書(shū)籍是 Martin Fowler 編著的 Refactoring(參見(jiàn) 參考資料 中的鏈接)。它讀起來(lái)甚至很有趣。重構(gòu)(refactoring) 的意思是在不改變代碼結(jié)果的情況下,更改現(xiàn)有代碼的設(shè)計(jì)。Fowler 談?wù)摿苏?qǐng)求重構(gòu)的“代碼氣味”,并且詳細(xì)介紹了用于改變“代碼氣味”的各種技巧(或者“重構(gòu)”)。依我的觀點(diǎn),重構(gòu)和編寫一次通過(guò)測(cè)試的代碼的能力(參閱 參考資料)是新手程序員要學(xué)習(xí)的最重要的技能。如果每個(gè)人都擅長(zhǎng)于這兩點(diǎn),那將徹底改變行業(yè)當(dāng)前的局面。如果您 擅長(zhǎng)于這兩點(diǎn),就會(huì)比較容易找到工作,因?yàn)槟鼙绕渌水a(chǎn)生更好的結(jié)果。
編寫 Java 代碼相當(dāng)簡(jiǎn)單。編寫優(yōu)良的 Java 代碼則是一門手藝。傾力成為一個(gè)手藝人。
posted on 2007-07-22 12:12 快車道 閱讀(418) 評(píng)論(0) 編輯 收藏 所屬分類: J2EE實(shí)踐