假設(shè)你是正在開(kāi)發(fā)和維護(hù)一個(gè)包含2000個(gè)類并使用了很多框架的Java開(kāi)發(fā)人員。你要如何理解這些代碼?在一個(gè)典型的Java企業(yè)項(xiàng)目小組中,大 部分能夠幫你的高級(jí)工程師看起來(lái)都很忙。文檔也很少。你需要盡快交付成果,并向項(xiàng)目組證明自己的能力。你會(huì)如何處理這種狀況?這篇文字為開(kāi)始一個(gè)新項(xiàng)目的 Java開(kāi)發(fā)者提供了一些建議。
0. 不要試圖一下子搞懂整個(gè)項(xiàng)目好好考慮一下,為什么理解項(xiàng)目代碼是第一位的?大部分情況是你被要求修復(fù)一個(gè)bug或者加強(qiáng)系統(tǒng)已有功能。你要做的第一件事情不是理解整個(gè)項(xiàng)目的架構(gòu)。當(dāng)對(duì)項(xiàng)目進(jìn)行維護(hù)時(shí),這樣(理解整個(gè)項(xiàng)目架構(gòu))可能會(huì)對(duì)你造成巨大的壓力。
即便是有著10年可靠編程經(jīng)驗(yàn)的Java開(kāi)發(fā)者可能也沒(méi)有理解項(xiàng)目的核心工作機(jī)制,盡管他們可能已經(jīng)在這個(gè)項(xiàng)目工作超過(guò)一年(假設(shè)他們并非原始開(kāi)發(fā)人員)。比如,對(duì)于認(rèn)證機(jī)制或事務(wù)管理機(jī)制。
他們是怎么做的?他們對(duì)于自己負(fù)責(zé)的部分非常了解,并且能夠交付價(jià)值給小組。每天的交付價(jià)值遠(yuǎn)比了解一些以后還不確定有沒(méi)有的東西重要的多。
1. 關(guān)注于盡快交付價(jià)值
那我是否定了你對(duì)于項(xiàng)目架構(gòu)理解的熱情了么?完全不。我只是要求你盡早的交付價(jià)值,一旦你開(kāi)始一個(gè)項(xiàng)目,搭建了開(kāi)發(fā)環(huán)境,你就不應(yīng)該花一兩周時(shí)間才交付什么,無(wú)論他的規(guī)模大小。假如你是一個(gè)有經(jīng)驗(yàn)的程序員卻兩周都沒(méi)有任何交付,你的經(jīng)理怎么會(huì)知道你是真的在工作還是在看新聞。
所以交付可以使大家都輕松起來(lái)。不要認(rèn)為你能夠做有價(jià)值的交付前必須理解整個(gè)項(xiàng)目。這是完全錯(cuò)誤的。加一段javascript的驗(yàn)證代碼對(duì)業(yè)務(wù)就很有價(jià)值,經(jīng)理能夠通過(guò)你的交付達(dá)到對(duì)你的信任。這樣能夠向上級(jí)領(lǐng)導(dǎo)證明你的貢獻(xiàn)以及員工價(jià)值。
日復(fù)一日,在你不斷修復(fù)bug及增強(qiáng)功能之后,就能夠慢慢開(kāi)始理解項(xiàng)目架構(gòu)。不要低估對(duì)系統(tǒng)方方面面理解時(shí)需要花費(fèi)的時(shí)間。花3-4天理解認(rèn)證機(jī) 制,2-3天理解事物管理。這些都是依靠之前的相似項(xiàng)目的經(jīng)歷,但關(guān)鍵還是要花時(shí)間才能透徹的理解。要在日常工作中擠出時(shí)間,不要向經(jīng)理要求特定的時(shí)間來(lái)做這些。
找找項(xiàng)目是否有一些不斷維護(hù)的單元測(cè)試用例。有效的單元測(cè)試用例是理解大型項(xiàng)目代碼的很好途徑。單元測(cè)試能夠幫助理解代碼片段,包括一個(gè)單元的外部接口(單元如何被調(diào)用以及返回內(nèi)容)及其內(nèi)部實(shí)現(xiàn)(調(diào)試單元測(cè)試比調(diào)試整個(gè)實(shí)際用例簡(jiǎn)單許多)。
你如果能夠很好的理解一些內(nèi)容,寫(xiě)一些筆記,或者畫(huà)一些類圖、時(shí)序圖、數(shù)據(jù)模型圖,以便你或日后其他的開(kāi)發(fā)者維護(hù)。
2. 維護(hù)大型項(xiàng)目所必須的技能
你能從事當(dāng)前的工作,必然已經(jīng)具有良好的java技術(shù)。我們來(lái)談?wù)勀軌蜃屇阍谛马?xiàng)目中良好表現(xiàn)的其他技能。大部分時(shí)間,你在項(xiàng)目中的任務(wù)是修復(fù)bug和增強(qiáng)功能。
有兩項(xiàng)很重要的技能能夠協(xié)助你維護(hù)大型項(xiàng)目代碼。
2.1 能夠迅速發(fā)現(xiàn)需要的類
在任何維護(hù)活動(dòng)中,無(wú)論是修復(fù)bug或增強(qiáng)功能,第一個(gè)動(dòng)作就是識(shí)別出當(dāng)前修復(fù)或增強(qiáng)的用例中調(diào)用的類。當(dāng)你定位到需要修復(fù)或增強(qiáng)的類/方法,就已經(jīng)完工了一半。
2.2 能夠分析變更的影響當(dāng)你在完成必要的修改或增強(qiáng)工作后,最重要的就是要確認(rèn)你的修改沒(méi)有破壞代碼的其他部分。你要用你的java技術(shù)及對(duì)其他框架的理解找出變更可能影響的部分。下面有兩個(gè)簡(jiǎn)單的例子詳細(xì)描述了最后提及的情況:
a)當(dāng)類A的equals()方法變更后,調(diào)用一個(gè)保護(hù)A實(shí)例的List的contains()方法時(shí)就會(huì)被影響到。若Java知識(shí)不夠,很難考慮到這樣的影響。
b)在一個(gè)web項(xiàng)目中,我們假設(shè)“user id”保存在session中。一個(gè)新入程序員可能在“user id”中加入一些信息作為bug修復(fù)的方法,但是卻不知道會(huì)影響到那些關(guān)聯(lián)“user id”的用例。
當(dāng)你提高了如上兩個(gè)技能,盡管你對(duì)項(xiàng)目不是非常了解,但大部分的維護(hù)任務(wù)會(huì)變得簡(jiǎn)單很多。若你修復(fù)一個(gè)bug,你會(huì)定位并修復(fù)這個(gè)bug,并且保證變更不會(huì)破壞項(xiàng)目的其他部分。若你增強(qiáng)或加入一個(gè)特性,基本上你只需要模仿現(xiàn)有的特性使用相似的設(shè)計(jì)。
在一個(gè)在線銀行項(xiàng)目中,為什么“查看賬戶摘要”和“查看交易歷史”的設(shè)計(jì)需要巨大的差別呢?如果你理解了“查看賬戶摘要”的設(shè)計(jì),完全可以模仿開(kāi)發(fā)出“查看交易歷史”的功能。
就修復(fù)bug和增強(qiáng)來(lái)說(shuō),你不必完全理解所有2000個(gè)類的工作內(nèi)容和代碼如何運(yùn)行來(lái)推動(dòng)系統(tǒng)。你若有上面的技能,就能很快定位需要修改的代碼的部分,使用良好的java和框架技能修復(fù),保證變更不會(huì)破壞項(xiàng)目的其他部分并交付,盡管你可能只知道一小部分項(xiàng)目的設(shè)計(jì)。
3. 使用工具找到需要的變更內(nèi)容以及變更產(chǎn)生的影響繼續(xù)我們盡快交付的主題,你應(yīng)當(dāng)尋找那些能夠通過(guò)盡量少的了解項(xiàng)目但能幫助你盡快實(shí)施交付的工具作為輔助。
3.1 迅速發(fā)現(xiàn)需要變更內(nèi)容的工具無(wú)論是修復(fù)bug還是系統(tǒng)增強(qiáng),首先都要找到該用例調(diào)用的你需要修改的類及方法。基本有兩種方式理解一個(gè)用例的工作方式,靜態(tài)代碼分析和運(yùn)行時(shí)分析。
源碼分析統(tǒng)計(jì)掃描所有代碼并且展示類之間的關(guān)系。市場(chǎng)上有很多設(shè)備與工具。比如:Architexa, AgileJ, UModel, Poseidon等。
所有的靜態(tài)代碼分析工具缺點(diǎn)在于無(wú)法確切展示用例中類或方法的運(yùn)行時(shí)調(diào)用情況。因此Java新加入了特性,如回調(diào)機(jī)制(callback patterns)。如靜態(tài)分析工具無(wú)法推斷出當(dāng)頁(yè)面提交按鈕被點(diǎn)擊時(shí)哪個(gè)Servlet被調(diào)用了。
運(yùn)行時(shí)分析工具能夠展示類和方法在用例運(yùn)行時(shí)的狀態(tài)。工具包括:MaintainJ, Diver,jSonde,Java Call Tracer等。這些工具可以捕獲運(yùn)行時(shí)的堆棧狀態(tài),并以此為一個(gè)用例生成序列圖和類圖。
序列圖展示了該用例在運(yùn)行時(shí)所有調(diào)用的方法。若你在修復(fù)一個(gè)bug,那這個(gè)bug很可能就是這些被調(diào)用的方法之一。
若你在增強(qiáng)已有功能,利用序列圖理解調(diào)用流程然后再修改。可能是新增一個(gè)驗(yàn)證,修改DAO等。
若你在新增功能,找到一些相似的特性,利用序列圖理解調(diào)用流程然后模仿開(kāi)發(fā)新功能。
要小心挑選運(yùn)行時(shí)分析工具。信息過(guò)多是這類工具的主要問(wèn)題。選擇一些提供簡(jiǎn)單過(guò)濾無(wú)效信息并能夠方便的查看各種視圖的工具。
3.2 迅速發(fā)現(xiàn)需要變更內(nèi)容的工具若單元測(cè)試有效,可以通過(guò)運(yùn)行單元測(cè)試發(fā)現(xiàn)變更有沒(méi)有破壞其他測(cè)試用例。有效維護(hù)并且覆蓋大型企業(yè)應(yīng)用的單元測(cè)試還是比較少的。下面有一些針對(duì)該情況的工具。
仍然是有兩種技術(shù)靜態(tài)代碼分析和運(yùn)行時(shí)分析可以使用。市場(chǎng)中有很多靜態(tài)代碼分析工具可用。如:Lattix, Structure101, Coverity, nWire and IntelliJ’s DSM。
給定一個(gè)變更后的類,上述工具均可識(shí)別對(duì)該類存在依賴的類的集合。開(kāi)發(fā)者需要根據(jù)這些信息“猜測(cè)”可能產(chǎn)生影響的用例,因?yàn)檫@些工具無(wú)法展示運(yùn)行時(shí)類之間的調(diào)用關(guān)系。
市場(chǎng)上的可以用于運(yùn)行時(shí)影響分析的工具并不多,除了MaintainJ。MaintainJ先捕獲在一個(gè)用例中調(diào)用的所有類和方法。當(dāng)所有用例的上 述信息都被捕獲之后,就很容易發(fā)現(xiàn)類的變更對(duì)用例的影響。MaintainJ能夠有效工作的前置條件就是項(xiàng)目的所有用例都應(yīng)當(dāng)先運(yùn)行一遍,以便能夠獲得運(yùn) 行時(shí)的依賴關(guān)系。
總之,目前你在迅速準(zhǔn)確分析變更影響方面,還是可以從工具中獲得有限的幫助。首先根據(jù)需要實(shí)施一些影響分析,然后根據(jù)自己或小組其他高級(jí)成員評(píng)審來(lái)判斷變更的影響。你可能需要上面提到的工具對(duì)你的判斷進(jìn)行反復(fù)確認(rèn)。
4. 對(duì)上述內(nèi)容的兩個(gè)忠告
4.1 不要降低代碼質(zhì)量
為了快速交付,所以沒(méi)有全盤(pán)理解架構(gòu),但絕不能以降低代碼質(zhì)量為條件。下面是一些你可能因?yàn)橹豢紤]快速交付而引發(fā)的代碼質(zhì)量問(wèn)題。
因?yàn)樾薷拇a涉及到很多的依賴,所以新增代碼相對(duì)而言風(fēng)險(xiǎn)較小。例如,有5個(gè)用例都調(diào)用了某個(gè)方法。為了改進(jìn)某個(gè)用例,你需要修改這個(gè)方法的實(shí)現(xiàn)。 最簡(jiǎn)單的做法就是復(fù)制這個(gè)方法,重命名,然后在改進(jìn)的用例中調(diào)用新方法。千萬(wàn)不要這么做。代碼冗余絕對(duì)是非常有害的。嘗試對(duì)方法進(jìn)行包裝或者重寫(xiě),甚至是 直接修改,然后重新測(cè)試所有用例,通常停下來(lái)想一想,然后親手去實(shí)施,是一個(gè)比較好的方式。
( 伯樂(lè)在線配圖)
另一個(gè)例子是將“private”方法改為“public”,使得別的類也可以調(diào)用。盡量不要將非必須的部分暴露出來(lái)。假如為了更好的設(shè)計(jì)需要重構(gòu),就應(yīng)當(dāng)著手去做。
大部分應(yīng)用都有確定的結(jié)構(gòu)和模式來(lái)實(shí)施。修復(fù)或增強(qiáng)程序時(shí),確認(rèn)你沒(méi)有偏離這樣的模式。若對(duì)約定不確定,請(qǐng)其他的高級(jí)開(kāi)發(fā)者來(lái)審核你的變更。若你必須做一些違背約定的實(shí)施,盡量放置于一個(gè)規(guī)模較小的類中(一個(gè)200行代碼的類中的私有函數(shù)應(yīng)當(dāng)不會(huì)影響應(yīng)用的整體設(shè)計(jì))
4.2 不要停止深入理解項(xiàng)目架構(gòu)按照文章列出的方式,假設(shè)你能夠在對(duì)項(xiàng)目了解較少的情況下進(jìn)行交付并以此持續(xù)下去,可能你會(huì)停止對(duì)項(xiàng)目架構(gòu)的深入了解。這樣從長(zhǎng)遠(yuǎn)角度來(lái)說(shuō)對(duì)你的職 業(yè)生涯沒(méi)有幫助。當(dāng)你的經(jīng)驗(yàn)增加時(shí),你應(yīng)當(dāng)承擔(dān)比較大的模塊任務(wù)。如構(gòu)建一個(gè)完整的新特性或者修改項(xiàng)目的一些基礎(chǔ)設(shè)計(jì)等較大的改進(jìn)。當(dāng)你能夠做這些改進(jìn) 時(shí),你對(duì)項(xiàng)目的整體架構(gòu)應(yīng)該相當(dāng)了解。文中列舉的方法是讓你在最短的時(shí)間內(nèi)提升自己,而不是阻止你完整理解整個(gè)項(xiàng)目。
5. 結(jié)論整篇文章集中在對(duì)項(xiàng)目進(jìn)行必要了解的前提下進(jìn)行快速交付。你可以在不降低代碼質(zhì)量的前提下這么做。
若修復(fù)一個(gè)bug,迅速定位并修復(fù)。有必要可以使用運(yùn)行時(shí)分析工具。若新增一個(gè)特寫(xiě),可以尋找相似特寫(xiě),理解流程(有必要使用工具)并編寫(xiě)。
或許這些聽(tīng)起來(lái)很簡(jiǎn)單,但是實(shí)用嗎?當(dāng)然。但前提是你有良好的java技術(shù)以及對(duì)框架足夠了解才能先修改代碼,然后對(duì)變更影響進(jìn)行分析。對(duì)變更影響的分析比實(shí)施變更需要更多的技巧。你可能需要高級(jí)開(kāi)發(fā)人員協(xié)助你分析變更影響。
大約有50%的IT可操作預(yù)算用于簡(jiǎn)單的bug修復(fù)和功能增強(qiáng)。根據(jù)文中的建議,對(duì)于維護(hù)活動(dòng)中的經(jīng)費(fèi)的節(jié)省應(yīng)當(dāng)還是很有幫助的。
作者 Choudary Kothapalli 也是 MaintainJ 項(xiàng)目的建立者。
代碼編寫(xiě)規(guī)范目的:能夠在編碼過(guò)程中實(shí)現(xiàn)規(guī)范化,為以后的程序開(kāi)發(fā)中養(yǎng)成良好的行為習(xí)慣。
代碼編寫(xiě)規(guī)范使用范圍:J2EE項(xiàng)目開(kāi)發(fā)。
包命名規(guī)范:
目的:包的命名規(guī)范應(yīng)當(dāng)體現(xiàn)出項(xiàng)目資源良好的劃分
servlet類所在包命名規(guī)范:公司名稱.開(kāi)發(fā)組名稱.項(xiàng)目名稱.web.servlet
例如:net.linkcn.web.servlet
自定義標(biāo)簽類所在包命名規(guī)范:公司名稱.開(kāi)發(fā)組名稱.項(xiàng)目名稱.web.tags
例如:net.linkcn.web.tags
過(guò)濾器類所在包命名規(guī)范:公司名稱.開(kāi)發(fā)組名稱.項(xiàng)目名稱.web.filter
例如:net.linkcn.web.filter
Action類所在包命名規(guī)范:公司名稱.開(kāi)發(fā)組名稱.項(xiàng)目名稱.web.struts.action
例如:net.linkcn.web.struts.action
ActionForm類所在包命名規(guī)范:公司名稱.開(kāi)發(fā)組名稱.項(xiàng)目名稱.web.struts.form
例如:net.linkcn.web.struts.form
Javabean所在包命名規(guī)范:公司名稱.開(kāi)發(fā)組名稱.項(xiàng)目名稱.web.struts.service.impl
例如:net.linkcn.web.service.impl
Javabean實(shí)現(xiàn)接口命名規(guī)范:公司名稱.開(kāi)發(fā)組名稱.項(xiàng)目名稱.web.service
例如:net.linkcn.web.service
DAO類所在包命名規(guī)范:公司名稱.開(kāi)發(fā)組名稱.項(xiàng)目名稱.dao.impl
例如:net.linkcn.dao.impl
DAO類所實(shí)現(xiàn)的接口在包中命名規(guī)范:公司名稱.開(kāi)發(fā)組名稱.項(xiàng)目名稱.dao
例如:net.linkcn.dao
POJO類與hbm文件所在包命名規(guī)范:公司名稱.開(kāi)發(fā)組名稱.項(xiàng)目名稱.dao.hbm
例如:net.linkcn.dao.hbm
全局公共類、接口類所在包命名規(guī)范:公司名稱.開(kāi)發(fā)組名稱.項(xiàng)目名稱.global
例如:net.linkcn.global
全局工具類所在包命名規(guī)范:公司名稱.開(kāi)發(fā)組名稱.項(xiàng)目名稱.util
例如:net.linkcn.util
類命名規(guī)范
基本命名規(guī)范:
類、接口命名
命名規(guī)范:以大寫(xiě)字母開(kāi)頭,如果有多個(gè)單詞,每個(gè)單詞頭字母大寫(xiě)
例如:StudentInfo
接口命名
命名規(guī)范:以大寫(xiě)字母"I"開(kāi)頭,如果有多個(gè)單詞,每個(gè)單詞頭字母大寫(xiě)
例如:IStudentInfo
接口實(shí)現(xiàn)類命名:
命名規(guī)范:將實(shí)現(xiàn)的接口名稱的首字母"I"去掉,以"Impl作為結(jié)尾",如果有多個(gè)單詞,每個(gè)單詞頭字母大寫(xiě)。
例如:StudentInfoImpl
J2EE+SSH框架命名規(guī)范
servlet類命名:
命名規(guī)范:以Servlet單詞結(jié)尾
例如:LoginServlet
POJO命名:
使用hibernate自動(dòng)生成的類即可
DAO類命名:
使用hibernate自動(dòng)生成的類即可
Action類命名:
命名規(guī)范:Action的命名以POJO名稱來(lái)制定,POJO名稱Action
例如:
一個(gè)POJO名稱為Diary,其對(duì)應(yīng)的action為DiaryAction
ActionForm類命名:
命名規(guī)范:ActionForm的命名以POJO名稱來(lái)制定,POJO名稱Form
例如:
一個(gè)POJO名稱為Diary,其對(duì)應(yīng)的actioForm為DiaryForm
業(yè)務(wù)邏輯接口命名:
命名規(guī)范:業(yè)務(wù)邏輯接口的命名以POJO名稱來(lái)制定,IPOJO名稱Service
例如:
一個(gè)POJO名稱為Diary,其對(duì)應(yīng)的業(yè)務(wù)邏輯接口為IDiaryService
業(yè)務(wù)邏輯實(shí)現(xiàn)類命名:
命名規(guī)范:業(yè)務(wù)邏輯接口實(shí)現(xiàn)類的命名以POJO名稱來(lái)制定
例如:
一個(gè)POJO名稱為Diary,對(duì)應(yīng)的業(yè)務(wù)邏輯接口實(shí)現(xiàn)類名為DiaryServiceImpl
類變量命名:
命名規(guī)范:變量名首字母必須小寫(xiě),如果該變量名有多個(gè)單詞組成,后面的單 詞首字母大寫(xiě),單詞與單詞之間不要使用"_"做連接,變量名訪問(wèn)控制必須為私有, 可以對(duì)其增加setter與getter方法。
例如:
private int studentAge;
public int getStudentAge(){
return studentAge;
}
public void setStudentAge(int studentAge) {
this.studentAge=studentAge;
}
常量命名:
命名規(guī)范:所有字母大寫(xiě),如果有多個(gè)單詞組成,單詞與單詞之間以” _“隔開(kāi)。而 且該變量必須是公共、靜態(tài)、final類型
例如:public static final String USER_NAME=”userName“;
方法命名
命名規(guī)范:首字母必須小寫(xiě),如果該變量名有多個(gè)單詞組成,后面的單詞首字母 大寫(xiě),單詞與單詞之間不要使用"_"做連接。單詞不要使用名詞。
例如:public int checkLogin(String name,String pwd){}
注釋規(guī)范:注釋規(guī)范是整個(gè)開(kāi)發(fā)規(guī)范中最為重要的組成部分,必須嚴(yán)格執(zhí)行。
類的注釋:
作用:注釋整個(gè)類,簡(jiǎn)單概述該類作用。
書(shū)寫(xiě)規(guī)范:類的注釋必須寫(xiě)在該類的聲明語(yǔ)法之前。在注釋中要描述該類的基 本作用,作者,日期,版本,公司名稱,版權(quán)聲明。
格式:
類的聲明語(yǔ)法
例如:
public class AdminDAO
變量、常量注釋:
作用:簡(jiǎn)單描述該變量的意義。
書(shū)寫(xiě)規(guī)范:變量注釋必須寫(xiě)在變量定義之前,簡(jiǎn)單描述其代表的意義。
格式:
例如:
public int age;
方法注釋:
作用:對(duì)該方法功能簡(jiǎn)單描述,其參數(shù)、返回值意義的注解。
書(shū)寫(xiě)規(guī)范:方法注釋必須寫(xiě)在方法定義之前。該注釋包括:方法其功能的簡(jiǎn)單 描述,方法的參數(shù)、返回值類型、返回值意義簡(jiǎn)單的描述。
格式:
例如:
public booleaneditAdminPassword(int adminId,String oldPassword,
String password) throws UserException,ServiceException;
Jsp頁(yè)面命名:
命名規(guī)范:jsp頁(yè)面名稱要以小寫(xiě)字母開(kāi)頭,如果有多個(gè)單詞組成,后面的單詞以 大寫(xiě)字母開(kāi)頭。名稱要體現(xiàn)出該頁(yè)面的意義,最好能夠與模塊名稱聯(lián)系在一起。
例如:
login.jsp --登錄頁(yè)面
register.jsp --注冊(cè)頁(yè)面
message.jsp --客戶留言頁(yè)面
J2EE項(xiàng)目工程文件夾組織規(guī)范:
目的:規(guī)范學(xué)員web應(yīng)用程序的資源組織形式,形成良好的文件組織習(xí)慣。文件的組織形式應(yīng)當(dāng)體現(xiàn)模塊的劃分。
根據(jù)eclipse工具的特征,項(xiàng)目的目錄結(jié)構(gòu)為:
src
----存放java文件
WebRoot
|--images --存放web程序所需的公共圖片
|--css --存放web程序所需的公共樣式表
|--js --存放web程序所需的公共js文件
|--commons --存放web程序所需的公共文件
|--功能模塊文件夾(存放與某個(gè)功能模塊相關(guān)的資源)
|--images --存放與該功能模塊相關(guān)的圖片
|--css --存放與該模塊相關(guān)的樣式表文件
|--js --存放與該模塊相關(guān)的js文件
|--jsp、html頁(yè)面
|--WEB-INF
|--classes
|--lib
|--tld文件
J2EE項(xiàng)目提交規(guī)范
項(xiàng)目完成時(shí)要將項(xiàng)目作為一個(gè)產(chǎn)品交付用戶,良好的項(xiàng)目組織規(guī)范可以使用戶可以方便的找尋項(xiàng)目中需要的資源,同時(shí)也是一個(gè)公司專業(yè)性的體現(xiàn)。項(xiàng)目提交時(shí),要按照下列文件格式進(jìn)行提交。
項(xiàng)目主文件夾:
作用:存放項(xiàng)目其他資源文件。
命名規(guī)范:時(shí)間_班級(jí)編號(hào)_第X小組。
例如:070706_GS2T18_第四小組。
項(xiàng)目主文件夾下面包括以下文件夾和文件:
|--src:保存.java文件。
|--database:保存數(shù)據(jù)庫(kù)的腳本文件或者數(shù)據(jù)庫(kù)備份文件。
|--source:保存eclipse工程中WebRoot目錄下的所有文件。
|--depend:保存編譯該程序必須依賴的其他jar文件。
|--javadoc:保存所有類生成的javadoc api文檔。
|--war:保存程序的歸檔文件
|--xx.war:已經(jīng)打包好的工程文件,可以直接運(yùn)行。
|--project:保存開(kāi)發(fā)項(xiàng)目原工程代碼及文件。
|--產(chǎn)品說(shuō)明書(shū).doc:圖文方式展現(xiàn)該產(chǎn)品使用方法。
|--build.xml:ant腳本,用于生成運(yùn)行的war文件。
|--項(xiàng)目解說(shuō).ppt:進(jìn)行項(xiàng)目講解的ppt(ppt僅供在校模擬項(xiàng)目使用,不用于其他商業(yè)用途)
注:一個(gè)完整的項(xiàng)目中,數(shù)據(jù)庫(kù)必須有一定量的有效的測(cè)試數(shù)據(jù)來(lái)支持該程序的運(yùn)行
包的命名
Java包的名字都是由小寫(xiě)單詞組成。但是由于Java面向?qū)ο缶幊痰奶匦裕恳幻鸍ava程序員都可以編寫(xiě)屬于自己的Java包,為了保障每個(gè) Java包命名的唯一性,在最新的Java編程規(guī)范中,要求程序員在自己定義的包的名稱之前加上唯一的前綴。由于互聯(lián)網(wǎng)上的域名稱是不會(huì)重復(fù)的,所以程序 員一般采用自己在互聯(lián)網(wǎng)上的域名稱作為自己程序包的唯一前綴。
例如: net.frontfree.javagroup
類的命名
類的名字必須由大寫(xiě)字母開(kāi)頭而單詞中的其他字母均為小寫(xiě);如果類名稱由多個(gè)單詞組成,則每個(gè)單詞的首字母均應(yīng)為大寫(xiě)例如TestPage;如果類名 稱中包含單詞縮寫(xiě),則這個(gè)所寫(xiě)詞的每個(gè)字母均應(yīng)大寫(xiě),如:XMLExample,還有一點(diǎn)命名技巧就是由于類是設(shè)計(jì)用來(lái)代表對(duì)象的,所以在命名類時(shí)應(yīng)盡量 選擇名詞。
例如: Circle
方法的命名
方法的名字的第一個(gè)單詞應(yīng)以小寫(xiě)字母作為開(kāi)頭,后面的單詞則用大寫(xiě)字母開(kāi)頭。
例如: sendMessge
常量的命名
常量的名字應(yīng)該都使用大寫(xiě)字母,并且指出該常量完整含義。如果一個(gè)常量名稱由多個(gè)單詞組成,則應(yīng)該用下劃線來(lái)分割這些單詞。
例如: MAX_VALUE
參數(shù)的命名
參數(shù)的命名規(guī)范和方法的命名規(guī)范相同,而且為了避免閱讀程序時(shí)造成迷惑,請(qǐng)?jiān)诒M量保證參數(shù)名稱為一個(gè)單詞的情況下使參數(shù)的命名盡可能明確。
Javadoc注釋
Java除了可以采用我們常見(jiàn)的注釋方式之外,Java語(yǔ)言規(guī)范還定義了一種特殊的注釋,也就是我們所說(shuō)的Javadoc注釋,它是用來(lái)記錄我們代 碼中的API的。Javadoc注釋是一種多行注釋,以結(jié)束,注釋可以包含一些HTML標(biāo)記符和專門(mén)的關(guān)鍵詞。使用Javadoc 注釋的好處是編寫(xiě)的注釋可以被自動(dòng)轉(zhuǎn)為在線文檔,省去了單獨(dú)編寫(xiě)程序文檔的麻煩。
例如:
在每個(gè)程序的最開(kāi)始部分,一般都用Javadoc注釋對(duì)程序的總體描述以及版權(quán)信息,之后在主程序中可以為每個(gè)類、接口、方法、字段添加 Javadoc注釋,每個(gè)注釋的開(kāi)頭部分先用一句話概括該類、接口、方法、字段所完成的功能,這句話應(yīng)單獨(dú)占據(jù)一行以突出其概括作用,在這句話后面可以跟 隨更加詳細(xì)的描述段落。在描述性段落之后還可以跟隨一些以Javadoc注釋標(biāo)簽開(kāi)頭的特殊段落,例如上面例子中的@auther和@version,這 些段落將在生成文檔中以特定方式顯示。
變量和常量命名
變量命名的方法采用匈牙利命名法,基本結(jié)構(gòu)為scope_typeVariableName,它使用3字符前綴來(lái)表示數(shù)據(jù)類型,3個(gè)字符的前綴必須 小寫(xiě),前綴后面是由表意性強(qiáng)的一個(gè)單詞或多個(gè)單詞組成的名字,而且每個(gè)單詞的首寫(xiě)字母大寫(xiě),其它字母小寫(xiě),這樣保證了對(duì)變量名能夠進(jìn)行正確的斷句。例如, 定義一個(gè)整形變量,用來(lái)記錄文檔數(shù)量:intDocCount,其中int表明數(shù)據(jù)類型,后面為表意的英文名,每個(gè)單詞首字母大寫(xiě)。這樣,在一個(gè)變量名就 可以反映出變量類型和變量所存儲(chǔ)的值的意義兩方面內(nèi)容,這使得代碼語(yǔ)句可讀性強(qiáng)、更加容易理解。byte、int、char、long、float、 double、boolean和short。
變量類型和首字母對(duì)照關(guān)系如下表:
數(shù)據(jù)類型/對(duì)象類型 / 變量前綴 / 備注
byte bye
char chr
float flt
boolean bln 做布爾變量時(shí),使用bln
Integer/int int
String str
Single sng
short sht
Long/long lng
Double/double dbl
Currency cur
Variant bln astr obj vnt 做布爾變量用時(shí),用bln,做字符串?dāng)?shù)組用時(shí),用astr,做為對(duì)象使用時(shí),用obj,不確定時(shí),用vnt。
對(duì)于數(shù)組,在數(shù)據(jù)類型的前綴前再增加一個(gè)a,例如字符串?dāng)?shù)組為astr。對(duì)于在多個(gè)函數(shù)內(nèi)都要使用的全局變量,在前面再增加“g_”。例如一個(gè)全局的字符串變量:g_strUserInfo。
在變量命名時(shí)要注意以下幾點(diǎn):
· 選擇有意義的名字,注意每個(gè)單詞首字母要大寫(xiě)。
· 在一段函數(shù)中不使用同一個(gè)變量表示前后意義不同的兩個(gè)數(shù)值。
· i、j、k等只作為小型循環(huán)的循環(huán)索引變量。
· 避免用Flag來(lái)命名狀態(tài)變量。
· 用Is來(lái)命名邏輯變量,如:blnFileIsFound。通過(guò)這種給布爾變量肯定形式的命名方式,使得其它開(kāi)發(fā)人員能夠更為清楚
的理解布爾變量所代表的意義。
· 如果需要的話,在變量最后附加計(jì)算限定詞,如:curSalesSum。
· 命名不相包含,curSales和curSalesSum。
· Static Final 變量的名字應(yīng)該都大寫(xiě),并且指出完整含義。
· 如果需要對(duì)變量名進(jìn)行縮寫(xiě)時(shí),一定要注意整個(gè)代碼中縮寫(xiě)規(guī)則的一致性。例如,如果在代碼的某些區(qū)域中使用intCnt,而在另一些區(qū)域中又使用intCount,就會(huì)給代碼增加不必要的復(fù)雜性。建議變量名中盡量不要出現(xiàn)縮寫(xiě)。
· 通過(guò)在結(jié)尾處放置一個(gè)量詞,就可創(chuàng)建更加統(tǒng)一的變量,它們更容易理解,也更容易搜索。例如,請(qǐng)使用 strCustomerFirst和strCustomerLast,而不要使用strFirstCustomer和strLastCustomer。常 用的量詞后綴有:First(一組變量中的第一個(gè))、Last(一組變量中的最后一個(gè))、Next(一組變量中的下一個(gè)變量)、Prev(一組變量中的上 一個(gè))、Cur(一組變量中的當(dāng)前變量)。
· 為每個(gè)變量選擇最佳的數(shù)據(jù)類型,這樣即能減少對(duì)內(nèi)存的需求量,加快代碼的執(zhí)行速度,又會(huì)降低出錯(cuò)的可能性。用于變量的數(shù)據(jù)類型可能會(huì)影響該變量進(jìn)行計(jì)算所產(chǎn)生的結(jié)果。在這種情況下,編譯器不會(huì)產(chǎn)生運(yùn)行期錯(cuò)誤,它只是迫使該值符合數(shù)據(jù)類型的要求。這類問(wèn)題極難查找。
· 盡量縮小變量的作用域。如果變量的作用域大于它應(yīng)有的范圍,變量可繼續(xù)存在,并且在不再需要該變量后的很長(zhǎng)時(shí)間內(nèi)仍然占用資源。它們的主要問(wèn)題是,任何類 中的任何方法都能對(duì)它們進(jìn)行修改,并且很難跟蹤究竟是何處進(jìn)行修改的。占用資源是作用域涉及的一個(gè)重要問(wèn)題。對(duì)變量來(lái)說(shuō),盡量縮小作用域?qū)?huì)對(duì)應(yīng)用程序的 可靠性產(chǎn)生巨大的影響。
關(guān)于常量的命名方法,在JAVA代碼中,無(wú)論什么時(shí)候,均提倡應(yīng)用常量取代數(shù)字、固定字符串。也就是說(shuō),程序中除0,1以外,盡量不應(yīng)該出現(xiàn)其他數(shù) 字。常量可以集中在程序開(kāi)始部分定義或者更寬的作用域內(nèi),名字應(yīng)該都使用大寫(xiě)字母,并且指出該常量完整含義。如果一個(gè)常量名稱由多個(gè)單詞組成,則應(yīng)該用下 劃線“_”來(lái)分割這些單詞如:NUM_DAYS_IN_WEEK、MAX_VALUE。