在 過去的幾乎整整十年中,人們編寫了很多有關(guān) Java™ Platform, Enterprise Edition (Java EE) 最佳實踐的內(nèi)容。現(xiàn)在有十多本書籍和數(shù)以百計(可能更多)的文章,提供了關(guān)于應(yīng)該如何編寫 Java EE 應(yīng)用程序的見解。事實上,這方面的參考資料如此之多,并且這些參考資料之間往往還存在著一些矛盾的建議,以至于在這些混雜的內(nèi)容中進行學(xué)習(xí)本身也成為了采 用 Java EE 的障礙。因此,為了給剛進入這個領(lǐng)域的客戶提供一些簡單的指導(dǎo),我們匯編了這個最重要的最佳實踐列表,其中包括我們認(rèn)為最重要和最有效的 Java EE 最佳實踐。遺憾的是,我們無法僅在 10 大最佳實踐中描述所有需要介紹的內(nèi)容。因此,為了避免遺漏關(guān)鍵的最佳實踐和尊重 Java EE 的發(fā)展,我們的列表中包含了“19 大”關(guān)鍵的 Java EE 最佳實踐。
![]() ![]() |
![]()
|
- 始終使用 MVC 框架。
- 不要做重復(fù)的工作。
- 在每一層都應(yīng)用自動單元測試和測試管理。
- 按照規(guī)范來進行開發(fā),而不是按照應(yīng)用服務(wù)器來進行開發(fā)。
- 從一開始就計劃使用 Java EE 安全性。
- 創(chuàng)建您所知道的。
- 當(dāng)使用 EJB 組件時,始終使用會話 Facade。
- 使用無狀態(tài)會話 Bean,而不是有狀態(tài)會話 Bean。
- 使用容器管理的事務(wù)。
- 將 JSP 作為表示層的首選。
- 當(dāng)使用 HttpSession 時,盡量只將當(dāng)前事務(wù)所需要的狀態(tài)保存其中,其他內(nèi)容不要保存在 HttpSession 中。
- 充分利用應(yīng)用服務(wù)器中不需要修改代碼的特性。
- 充分利用現(xiàn)有的環(huán)境。
- 充分利用應(yīng)用服務(wù)器環(huán)境所提供的服務(wù)質(zhì)量。
- 充分利用 Java EE,不要欺騙。
- 安排進行版本更新。
- 在代碼中所有關(guān)鍵的地方,使用標(biāo)準(zhǔn)的日志框架記錄程序的狀態(tài)。
- 在完成相應(yīng)的任務(wù)后,請始終進行清理。
- 在開發(fā)和測試過程中遵循嚴(yán)格的程序。
![]() ![]() |
![]()
|
將業(yè)務(wù)邏輯(Java Bean 和 EJB 組件)從控制器邏輯(Servlet/Struts 操作)和表示邏輯(JSP、XML/XSLT)中清晰地分離出來。良好的分層可以帶來許多好處。
這項實踐非常重要,以致沒有其他最佳實踐可以與其相提并論。對于良好的 Java EE 應(yīng)用程序設(shè)計而言,模型-視圖-控制器 (MVC) 是至關(guān)重要的。它將程序的任務(wù)簡單地分為下面幾個部分:
- 負(fù)責(zé)業(yè)務(wù)邏輯的部分(模型,通常使用 Enterprise JavaBeans™ 或傳統(tǒng) Java 對象來實現(xiàn))。
- 負(fù)責(zé)用戶接口表示的部分(視圖)。
- 負(fù)責(zé)應(yīng)用程序?qū)Ш降牟糠郑刂破鳎ǔJ褂?Java Servlet 或類 Struts 控制器這樣相關(guān)的類來實現(xiàn))。
對于 Java EE,有許多關(guān)于這個主題的優(yōu)秀評論,我們特別推薦感興趣的讀者可以參考 [Fowler] 或者 [Brown](請參見參考資料部分)的評論,以便全面和深入地了解相關(guān)內(nèi)容。
如 果不遵循基本的 MVC 體系結(jié)構(gòu),在開發(fā)過程中就會出現(xiàn)許多的問題。最常見的問題是,將過多的任務(wù)放到該體系結(jié)構(gòu)的視圖部分中。可能存在使用 JSP 標(biāo)記來執(zhí)行數(shù)據(jù)庫訪問,或者在 JSP 中進行應(yīng)用程序的流程控制,這在小規(guī)模的應(yīng)用程序中是比較常見的,但是,隨著后期的開發(fā),這樣做將會帶來問題,因為 JSP 逐步變得越來越難以維護和調(diào)試。
類似地,我們也經(jīng)常看到將視圖層構(gòu)建到業(yè)務(wù)邏輯的情況。例如,一個常見的問題就是將在構(gòu)建視圖時使用的 XML 解析技術(shù)直接應(yīng)用到業(yè)務(wù)層。業(yè)務(wù)層應(yīng)該對業(yè)務(wù)對象進行操作,而不是對與視圖相關(guān)的特定數(shù)據(jù)表示進行操作。
然 而,僅僅使用適當(dāng)?shù)慕M件無法實現(xiàn)應(yīng)用程序的正確分層。我們常常見到一些應(yīng)用程序包含 Servlet、JSP 和 EJB 組件所有這三項,然而,其主要的業(yè)務(wù)邏輯卻是在 Servlet 層實現(xiàn)的,或者應(yīng)用程序?qū)Ш绞窃?JSP 中處理的。您必須對代碼進行嚴(yán)格的檢查和重構(gòu),以確保僅在模型層中處理業(yè)務(wù)邏輯,在控制器層中進行應(yīng)用程序?qū)Ш剑晥D應(yīng)該只關(guān)心如何將模型對象呈現(xiàn)為合 適的 HTML 和 Javascript™。
本文中這項建議的涵義應(yīng)該比原始版本中的更加清楚。用戶接口技 術(shù)不斷地發(fā)生著變化,將業(yè)務(wù)邏輯關(guān)聯(lián)于用戶接口,會使得對接口的更改影響到現(xiàn)有的系統(tǒng)。幾年之前,Web 應(yīng)用程序用戶接口開發(fā)人員可能從 Servlet 和 JSP、Struts 和 XML/XSL 轉(zhuǎn)換中進行選擇。在那以后,Tiles 和 Faces 非常流行,而現(xiàn)在,AJAX 大行其道。如果每當(dāng)首選的用戶接口技術(shù)發(fā)生了更改就要重新開發(fā)應(yīng)用程序的核心業(yè)務(wù)邏輯,那么就糟透了。
![]() ![]() |
![]()
|
使用常見的、經(jīng)過證實的框架,如 Apache Struts、JavaServer Faces 和 Eclipse RCP。使用經(jīng)過證實的模式。
回
到我們開始幫助客戶使用剛出現(xiàn)的 Java EE 標(biāo)準(zhǔn)的時候,我們發(fā)現(xiàn)(和許多其他人一樣),通過直接使用基礎(chǔ)的 Servlet 和 JSP
規(guī)范構(gòu)建 UI 應(yīng)用程序來開發(fā)用戶接口開發(fā)框架,可以極大地提高開發(fā)人員工作效率。因此,許多公司開發(fā)了他們自己的 UI
框架,這些框架可以簡化接口開發(fā)的任務(wù)。
隨著開放源碼的框架(如 Apache Struts)的出現(xiàn) [Brown],我們相信,可以自動地和快速地轉(zhuǎn)換到這些新的框架。我們認(rèn)為,使用開放源碼社區(qū)支持的框架非常適合于開發(fā)人員,并且這些框架很快得到了廣泛認(rèn)可,不僅可用于新的開發(fā),還可以修改現(xiàn)有的應(yīng)用程序。
但 令人感到奇怪的是,事實并非如此。我們?nèi)钥梢钥吹皆S多公司在維護或甚至開發(fā)新的用戶接口框架,而這些框架的功能與 Struts 或者 JSF 是完全相同的。之所以會出現(xiàn)這種情況,有許多原因:機構(gòu)惰性,“非我發(fā)明”癥,不了解更改現(xiàn)有代碼的好處、或者甚至傲慢地認(rèn)為能夠比開放源碼開發(fā)人員的特 定框架做得更好。
然而,這些原因都已經(jīng)過時了,不能夠成為不采用標(biāo)準(zhǔn)框架的借口。Struts 和 JSF 不僅在 Java 社區(qū)中得到了廣泛認(rèn)可,而且還受到 WebSphere 運行時和 Rational® 工具套件的全面支持。同樣地,在富客戶端領(lǐng)域中,Eclipse RCP(富客戶端平臺,Rich Client Platform)獲得了廣泛的認(rèn)可,可用于構(gòu)建獨立的富客戶端。盡管不是 Java EE 標(biāo)準(zhǔn)中的一部分,但這些框架現(xiàn)在已成為 Java EE 社區(qū)的一部分,并且理應(yīng)如此。
對于那些因為傲慢而不愿使用現(xiàn)成的 UI 框架的人,應(yīng)該閱讀 [Alur] 和 [Fowler] 中介紹的內(nèi)容。這兩本書詳細(xì)地描述了企業(yè) Java 應(yīng)用程序中最常用的可重用模式。從類似于會話 Facade 這樣簡單的模式(將在后面的建議中討論)到類似于 Fowler 持久性模式(許多開放源碼的持久性框架對其進行了實現(xiàn))這樣比較復(fù)雜的模式,其中的內(nèi)容體現(xiàn)了 Java 前輩們所積累的智慧。那些不能吸取教訓(xùn)的人必定會重蹈覆轍(如果他們非常幸運,能夠在第一次失敗之后獲得重來一次的機會),他們不得不向哲學(xué)家 Santayana 說抱歉。
![]() ![]() |
![]()
|
3. 在應(yīng)用程序的每一層都使用自動單元測試和測試管理。
不要只是測試您的圖形用戶界面(GUI)。分層的測試使得調(diào)試和維護工作變得極其簡單。
在過去的幾年中,在方法學(xué)領(lǐng)域有了相當(dāng)大的革新,例如新出現(xiàn)的被稱為 Agile(如參考資料部
分中的 SCRUM [Schwaber] 和極限編程
[Beck1])的輕量級方法現(xiàn)在已經(jīng)得到了很普遍的應(yīng)用。幾乎所有的這些方法中的一個共同特征是它們都提倡使用自動的測試工具,這些工具可以幫助開發(fā)人
員用更少的時間進行回歸測試,并可以幫助他們避免由于不充分的回歸測試造成的錯誤,因此可以用來提高程序員的工作效率。實際上,還有一種被稱為
Test-First Development [Beck2]
的方法,這種方法甚至提倡在開發(fā)實際的代碼之前就先編寫單元測試。然而,在您測試代碼之前,您需要將代碼分割成一些可測試的片斷。一個“大泥球”是難以測
試的,因為它不是只實現(xiàn)一個簡單的易于識別的功能。如果您的每個代碼片斷實現(xiàn)多個方面的功能,將難以測試其中的每個部分以保證其正確性。
MVC 體系結(jié)構(gòu)(以及 Java EE 中的 MVC 實現(xiàn))的一個優(yōu)點就是元素的組件化能夠(實際上,相當(dāng)?shù)暮唵危δ膽?yīng)用程序進行單元測試。因此,您可以方便地對實體 Bean、會話 Bean 以及 JSP 獨立編寫測試用例,而不必考慮其他代碼。現(xiàn)在有許多用于 Java EE 測試的框架和工具,這些框架及工具使得這一過程更加簡單。例如,JUnit(是一種由 junit.org 開發(fā)的開放源代碼工具)和 Cactus(由 Apache 協(xié)會開發(fā)的開放源代碼工具)對于測試 Java EE 組件都非常有用。[Hightower] 詳細(xì)探討了如何在 Java EE 中使用這些工具。
盡 管所有這些詳述了怎樣徹底地測試您的應(yīng)用程序,但是我們?nèi)匀豢吹揭恍┤苏J(rèn)為只要他們測試了 GUI(可能是基于 Web 的 GUI,或者是獨立的 Java 應(yīng)用程序),則他們就全面地測試了整個應(yīng)用程序。僅進行 GUI 測試是不夠的。GUI 測試很難達到全面的測試,有以下幾種原因。
- 使用 GUI 測試很難徹底地測試到系統(tǒng)的每一條路徑,GUI 僅僅是影響系統(tǒng)的一種方式。可能存在后臺運算、腳本和各種各樣的其他訪問點,這也需要進行測試,然而,它們通常并不具有 GUI。
- GUI 級的測試是一種非常粗粒度的測試。這種測試只是在宏觀水平上測試系統(tǒng)的行為,這意味著一旦發(fā)現(xiàn)存在問題,則與此問題相關(guān)的整個子系統(tǒng)都要進行檢查,這使得找出錯誤將是非常困難的事情。
- GUI 測試通常只有在整個開發(fā)周期的后期才能很好地得到測試,這是因為只有這那個時候 GUI 才得到完整的定義。這意味著只有在后期才可能發(fā)現(xiàn)潛在的錯誤。
- 一 般的開發(fā)人員可能沒有自動的 GUI 測試工具。因此,當(dāng)一個開發(fā)人員對代碼進行更改時,沒有一種簡單的方法來重新測試受到影響的子系統(tǒng)。這實際上不利于進行良好的測試。如果開發(fā)人員具有自動 的代碼級單元測試工具,開發(fā)人員就能夠很容易地運行這些工具以確保所做的更改不會破壞已經(jīng)存在的功能。
- 如果添加了自動構(gòu)建功能,則在自動構(gòu)建過程中添加一個自動的單元測試工具是非常容易的事情。當(dāng)完成這些設(shè)置以后,整個系統(tǒng)就可以有規(guī)律地進行重建,并且回歸測試幾乎不需要人的參與。
另 外,我們必須強調(diào),使用 EJB 和 Web 服務(wù)進行分布式的、基于組件的開發(fā)使得測試單個組件變得非常必要。如果沒有“GUI”需要測試,您就必須進行低級(lower-level)測試。最好以 這種方式開始測試,省得當(dāng)您將分布式的組件或 Web 服務(wù)作為您的應(yīng)用程序的一部分時,您不得不花費心思重新進行測試。
總之,通過使用自動的單元測試,能夠很快地發(fā)現(xiàn)系統(tǒng)的缺陷,并且也易于發(fā)現(xiàn)這些缺陷,使得測試工作變得更加系統(tǒng)化,因此整體的質(zhì)量也得以提高。
![]() ![]() |
![]()
|
4. 按照規(guī)范來進行開發(fā),而不是按照應(yīng)用服務(wù)器來進行開發(fā)。
要將規(guī)范熟記于心,如果要背離規(guī)范,需經(jīng)過慎密的考慮后才可以這樣做。這是因為當(dāng)您背離規(guī)則的時候,您所做的事情往往并不是您應(yīng)該做的事情。
當(dāng)
您要背離 Java EE 允許您做的事情的時候,這很容易讓使您遭受不幸。我們發(fā)現(xiàn)有一些開發(fā)人員鉆研一些 Java EE
允許之外的東西,他們認(rèn)為這樣做可以“稍微”改善 Java EE
的性能,而他們最終只會發(fā)現(xiàn)這樣做會引起嚴(yán)重的性能問題,或者在以后的移植(從一個廠商到另一個廠商,或者是更常見的從一個版本到另一個版本)中會出現(xiàn)問
題。實際上,這種移植問題是如此嚴(yán)重,以致 [Beaton] 將此原則稱為移植工作的基本最佳實踐。
現(xiàn) 在有好幾個地方如果不直接使用 Java EE 提供的方法肯定會產(chǎn)生問題。一個常見的例子就是開發(fā)人員通過使用 JAAS 模塊來替代 Java EE 安全性,而不是使用內(nèi)置的遵循規(guī)范的應(yīng)用服務(wù)器機制來進行驗證和授權(quán)。要注意不要脫離 Java EE 規(guī)范提供的驗證機制。如果脫離了此規(guī)范,這將是系統(tǒng)存在安全漏洞以及廠商兼容性問題的主要原因。類似地,要使用 Servlet 和 EJB 規(guī)范提供的授權(quán)機制,并且如果您要偏離這些規(guī)范的話,要確保使用規(guī)范定義的 API(例如 getCallerPrincipal())作為實現(xiàn)的基礎(chǔ)。通過這種方式,您將能夠利用廠商提供的強安全性基礎(chǔ)設(shè)施,其中,業(yè)務(wù)要求需要支持復(fù)雜的授權(quán) 規(guī)則。(有關(guān)授權(quán)的更詳細(xì)內(nèi)容,請參見 [Ilechko]。)
其 他常見的問題包括使用不遵循 Java EE 規(guī)范的持久性機制(這使得事務(wù)管理變得困難)、在Java EE程序中使用不適當(dāng)?shù)?J2SE 方法(例如線程或 singleton),以及使用您自己的方法解決程序到程序(program-to-program)的通信,而不是使用 Java EE 內(nèi)在支持的機制(例如 JCA、JMS 或 Web 服務(wù))。當(dāng)您將一個遵循 Java EE 的服務(wù)器移植到其他的服務(wù)器上,或者移植到相同服務(wù)器的新版本上,上述的設(shè)計選擇將會造成無數(shù)的問題。使用 Java EE 之外的元素,通常會導(dǎo)致一些細(xì)微的可移植性問題。唯一要背離規(guī)范的情況是,當(dāng)一個問題在規(guī)范的范圍內(nèi)無法解決的時候。例如,安排執(zhí)行定時的業(yè)務(wù)邏輯在 EJB2.1 出現(xiàn)之前是一個問題。在類似這樣的情況下,我們建議當(dāng)有廠商提供的解決方案時就使用廠商提供的解決方案(例如 WebSphere Application Server Enterprise 中的 Scheduler 工具),而在沒有廠商提供的解決方案時就使用第三方提供的工具。當(dāng)然,現(xiàn)在的 EJB 規(guī)范提供了基于時間的函數(shù),所以我們鼓勵使用這些標(biāo)準(zhǔn)接口。如果使用廠商提供的解決方案,應(yīng)用程序的維護以及將其移植到新的規(guī)范版本將是廠商的問題,而不 是您的問題。
最后,要注意不要太早地采用新技術(shù)。太過于熱衷采用還沒有集成到 Java EE 規(guī)范的其他部分或者還沒有集成到廠商的產(chǎn)品中的技術(shù)常會帶來災(zāi)難性的后果。支持是關(guān)鍵的——如果您的廠商不直接支持某種特定的技術(shù),那么您在采用此技術(shù)時 就應(yīng)該非常謹(jǐn)慎。有些人(尤其是開發(fā)人員)過分關(guān)注于簡化開發(fā)過程,忽略了依賴大量本組織之外開發(fā)的代碼的長期后果,而供應(yīng)商并不支持這些代碼。我們發(fā) 現(xiàn),許多項目團隊沉迷于新技術(shù)(例如最新的開放源代碼框架),并很快地依賴于它,卻沒有考慮它對業(yè)務(wù)帶來的實際代價。坦白地說,對于使用您的供應(yīng)商所提供 的產(chǎn)品之外的任何技術(shù)的決策,都應(yīng)該由企業(yè)組織結(jié)構(gòu)中的各個部門、業(yè)務(wù)團隊和法律團隊(或您的環(huán)境中的等同機構(gòu))仔細(xì)地進行評審,這與正常的產(chǎn)品購買決策 完全相同。畢竟,我們中的大多數(shù)人是在解決業(yè)務(wù)問題,而不是推進技術(shù)的發(fā)展。
![]() ![]() |
![]()
|
啟用 WebSphere 安全性。這使您的 EJB 和 URL 至少可以讓所有授權(quán)用戶訪問。不要問為什么——照著做就是了。
在
與我們合作的客戶中,一開始就打算啟用 WebSphere Java EE 安全性的顧客是非常少的,這一點一直讓我們感到吃驚。據(jù)我們估計大約只有
50%
的顧客一開始就打算使用此特性。例如,我們曾與一些大型的金融機構(gòu)(銀行、代理等等)合作過,他們也沒有打算啟用安全性。幸運的是,這種問題在部署之前的
檢查時就得以解決。
不使用 Java EE 安全性是件危險的事情。假設(shè)您的應(yīng)用程序需要安全性(幾乎所有的應(yīng)用程序都需要),敢打賭您的開發(fā)人員能夠構(gòu)建出自己的安全性基礎(chǔ)設(shè)施,其比您從 Java EE 廠商那里買來的更好。這可不是個好的賭博游戲。為分布式的應(yīng)用程序提供安全性是異常困難的。例如,您需要使用網(wǎng)絡(luò)安全加密令牌控制對 EJB 的訪問。以我們的經(jīng)驗看來,大多數(shù)自己構(gòu)建的安全性基礎(chǔ)設(shè)施是不安全的,并且有重大的缺陷,這使產(chǎn)品系統(tǒng)極其脆弱。(有關(guān)更詳細(xì)的信息,請參考 [Barcia] 的第 18 章。)
一 些不使用 Java EE 安全性的理由包括:擔(dān)心性能的下降,相信其他的安全性(例如 IBM Tivoli® Access Manager 和 Netegrity SiteMinder)可以取代 Java EE 安全性,或者是不知道 WebSphere Application Server 安全特性及功能。不要陷入這些陷阱之中。尤其是,盡管像 Tivoli Access Manager 這樣的產(chǎn)品能夠提供優(yōu)秀的安全特性,但是僅僅其自身不可能保護整個 Java EE 應(yīng)用程序。這些產(chǎn)品必須與 Java EE 應(yīng)用服務(wù)器聯(lián)合起來才可能全面地保護您的系統(tǒng)。
其他一種常見的不使用 Java EE 安全性的原因是,基于角色的模型沒有提供足夠的粒度訪問控制以滿足復(fù)雜的業(yè)務(wù)規(guī)則。盡管事實是這樣的,但這也不應(yīng)該成為不使用 Java EE 安全性的理由。相反地,應(yīng)該將 Java EE 驗證及 Java EE 角色與特定的擴展規(guī)則結(jié)合起來。如果復(fù)雜的業(yè)務(wù)規(guī)則需要做出安全性決策,那就編寫相應(yīng)的代碼,其安全性決策要基于可以直接使用的以及可靠的 Java EE 驗證信息(用戶 ID 和角色)。(有關(guān)授權(quán)的更詳細(xì)的信息,請參見 [Ilechko]。)
![]() ![]() |
![]()
|
反復(fù)的開發(fā)工作將使您能夠逐漸地掌握所有的 Java EE 模塊。要從創(chuàng)建小而簡單的模塊開始而不是從一開始就馬上涉及到所有的模塊。
我們必須承認(rèn) Java EE 是龐大的體系。如果一個開發(fā)團隊只是開始使用 Java EE,這將很難一下子就能掌握它。在 Java EE 中有太多的概念和 API 需要掌握。在這種情況下,成功掌握 Java EE 的關(guān)鍵是從簡單的步驟開始做起。
這 種方法可以通過在您的應(yīng)用程序中創(chuàng)建小而簡單的模塊來得到最好的實現(xiàn)。如果一個開發(fā)團隊通過創(chuàng)建一個簡單的域模型以及后端的持久性機制(也許使用的是 JDBC),并且對其進行了完整的測試,這會增強他們的自信心,于是他們會使用該域模型去掌握使用 Servlet 和 JSP 的前端開發(fā)。如果一個開發(fā)團隊發(fā)現(xiàn)有必要使用 EJB,他們也會類似地開始在容器管理的持久性 EJB 組件之上使用簡單的會話 Facade,或者使用基于 JDBC 的數(shù)據(jù)訪問對象(JDBC-based Data Access Objects,DAO),而不是跳過這些去使用更加復(fù)雜的構(gòu)造(例如消息驅(qū)動的 Bean 和 JMS)。
這 種方法并不是什么新方法,但是很少有開發(fā)團隊以這種方式來培養(yǎng)他們的技能。相反地,多數(shù)開發(fā)團隊由于嘗試馬上就構(gòu)建所有的模塊,同時涉及 MVC 中的視圖層、模型層和控制器層,這樣做的結(jié)果是他們往往會陷入進度的壓力之中。他們應(yīng)該考慮一些敏捷(Agile)開發(fā)方法,例如極限編程(XP),這種 開發(fā)方法采用一種增量學(xué)習(xí)及開發(fā)方法。在 XP 中有一種稱為 ModelFirst [Wiki] 的過程,這個過程涉及到首先構(gòu)建域模型作為一種機制來組織和實現(xiàn)用戶場景。基本說來,您要構(gòu)建域模型作為您要實現(xiàn)的用戶場景的首要部分,然后在域模型之上 構(gòu)建一個用戶界面(UI)作為用戶場景實現(xiàn)的結(jié)果。這種方法非常適合讓一個開發(fā)團隊一次只學(xué)到一種技術(shù),而不是讓他們同時面對很多種情況(或者讓他們讀很 多書),這會令他們崩潰的。
還有,對每個應(yīng)用程序?qū)又貜?fù)的開發(fā)可能會包含一些適當(dāng)?shù)哪J郊白罴褜嵺`。如果您從應(yīng)用程序的底層開始應(yīng)用一些模式(如數(shù)據(jù)訪問對象和會話 Facade),您就不應(yīng)該在您的JSP和其他視圖對象中使用域邏輯。
最后,當(dāng)您開發(fā)一些簡單的模塊時,在開始的初期就可以對您的應(yīng)用程序進行性能測試。如果直到應(yīng)用程序開發(fā)的后期才進行性能測試的話,這往往會出現(xiàn)災(zāi)難性的后果,正如 [Joines] 所述。
![]() ![]() |
![]()
|
7. 當(dāng)使用 EJB 組件時,始終使用會話 Facade。
在體系結(jié)構(gòu)合適的情況下,使用本地 EJB。
當(dāng)
使用 EJB 組件時,使用會話 Facade 是一個確認(rèn)無疑的最佳實踐。實際上,這個通用的實踐被廣泛地應(yīng)用到任何分布式技術(shù)中,包括
CORBA、EJB 和
DCOM。從根本上講,您的應(yīng)用程序的分布“交叉區(qū)域”越是底層化,對小塊的數(shù)據(jù)由于多次重復(fù)的網(wǎng)絡(luò)中繼造成的時間消耗就越少。要達到這個目的的方法是,
創(chuàng)建大粒度的 Facades
對象,這個對象包含邏輯子系統(tǒng),因而可以通過一個方法調(diào)用就可以完成一些有用的業(yè)務(wù)功能。這種方法不但能夠降低網(wǎng)絡(luò)開銷,而且在 EJB
內(nèi)部通過為整個業(yè)務(wù)功能創(chuàng)建一個事務(wù)環(huán)境也可以大大地減少對數(shù)據(jù)庫的訪問次數(shù)。[Alur]
對這種模式進行了規(guī)范的表示,[Fowler](并且包括除 EJB 之外的情況)和 [Marinescu] 也對其進行了描述(請參見參考資料)。細(xì)心的讀者會發(fā)現(xiàn),這實際上正是面向服務(wù)的體系結(jié)構(gòu) (SOA) 中的核心原則之一。
EJB 本地接口(從 EJB 2.0 規(guī)范開始使用)為共存的 EJB 提供了性能優(yōu)化方法。本地接口必須被您的應(yīng)用程序顯式地進行訪問,這需要代碼的改變和防止以后配置 EJB 時需要應(yīng)用程序的改變。如果您確定 EJB 調(diào)用始終是本地的,那么可以充分利用本地 EJB 的優(yōu)化。然而,會話 Facade 本身的實現(xiàn)(典型例子如無狀態(tài)會話 Bean)應(yīng)該設(shè)計為遠(yuǎn)程接口。通過這種方式,其他的客戶端可以遠(yuǎn)程地使用 EJB 本身,而不會破壞現(xiàn)有的業(yè)務(wù)邏輯。因為 EJB 可以同時具有本地和遠(yuǎn)程接口,所以這是完全可以實現(xiàn)的。
為了性能的優(yōu)化,可以將一個本地接口添加到會話 Facade。這樣做利用了這樣一個事實,在大多數(shù)情況下(至少在 Web 應(yīng)用程序中),您的 EJB 客戶端和 EJB 會共同存在于同一個 Java 虛擬機(JVM)中。另外一種情況是,如果會話 Facade 在本地被調(diào)用,可以使用 Java EE 應(yīng)用服務(wù)器配置優(yōu)化(configuration optimizations),例如 WebSphere 中的“No Local Copies”。然而,您必須注意到這些可供選擇的方案會將交互方法從按值傳遞(pass-by-value)改變?yōu)榘匆脗鬟f(pass-by- reference)。這可能會在您的代碼中產(chǎn)生很微妙的錯誤。最好使用本地 EJB,因為對于每個 Bean 而言,其行為是可以控制的,而不會影響到整個應(yīng)用服務(wù)器。
如果在您的會話 Facade 中使用遠(yuǎn)程接口(而不是本地接口),您也可以將同樣的會話 Facade 在 Java EE 1.4 中以兼容的方式作為 Web 服務(wù)來配置。(這是因為 JSR 109,Java EE 1.4 中的 Web 服務(wù)部署部分,要求使用無狀態(tài)會話 Bean 的遠(yuǎn)程接口作為 EJB Web 服務(wù)和 EJB 實現(xiàn)的接口。)這樣做是值得的,因為這樣做可以為您的業(yè)務(wù)邏輯增加客戶端類型的數(shù)量。
![]() ![]() |
![]()
|
8. 使用無狀態(tài)會話 Bean,而不是有狀態(tài)會話 Bean。
這樣做可以使您的系統(tǒng)更經(jīng)得起故障轉(zhuǎn)移。使用 HttpSession 存儲和用戶相關(guān)的狀態(tài)。
以
我們的觀點來看,有狀態(tài)會話 Bean 的概念已經(jīng)過時了。如果您仔細(xì)對其考慮一下,一個有狀態(tài)會話 Bean 實際上與一個 CORBA
對象在體系結(jié)構(gòu)上是完全相同的,無非就是一個對象實例綁定到一個服務(wù)器,并且依賴于服務(wù)器來管理其生命周期。如果服務(wù)器關(guān)閉了,這種對象也就不存在,那么
這個 Bean 的客戶端的信息也就不存在。
Java EE 應(yīng)用服務(wù)器為有狀態(tài)會話 Bean 提供的故障轉(zhuǎn)移能夠解決一些問題,但是有狀態(tài)的解決方案沒有無狀態(tài)的解決方案易于擴展。例如,在 WebSphere Application Server 中,對無狀態(tài)會話 Bean 的請求,是通過對部署無狀態(tài)會話的成員集群進行平衡加載來實現(xiàn)。相反地,Java EE 應(yīng)用服務(wù)器不能對有狀態(tài) Bean 的請求進行平衡加載。這意味著您的集群中的服務(wù)器的加載過程會是不均衡的。此外,使用有狀態(tài)會話 Bean 將會再添加一些狀態(tài)到您的應(yīng)用服務(wù)器上,這也是不好的做法。有狀態(tài)會話 Bean 增加了系統(tǒng)的復(fù)雜性,并且在出現(xiàn)故障的情況下使問題變得復(fù)雜化。創(chuàng)建健壯的分布式系統(tǒng)的一個關(guān)鍵原則是盡量使用無狀態(tài)行為。
因 此,我們建議對大多數(shù)應(yīng)用程序使用無狀態(tài)會話 Bean 方法。任何在處理時需要使用的與用戶相關(guān)的狀態(tài)應(yīng)該以參數(shù)的形式傳送到 EJB 的方法中(并且通過使用一種機制如 HttpSession 來存儲它)或者從持久性的后端存儲(例如通過使用實體 Bean)作為 EJB 事務(wù)的一部分來進行檢索。在合適的情況下,這個信息可以緩存到內(nèi)存中,但是要注意在分布式的環(huán)境中保存這種緩存所潛在的挑戰(zhàn)性。緩存非常適合于只讀數(shù)據(jù)。
總 之,您要確保從一開始就要考慮到可擴展性。檢查設(shè)計中的所有設(shè)想,并且考慮到當(dāng)您的應(yīng)用程序要在多個服務(wù)器上運行時,是否也可以正常運行。檢查設(shè)計中所有 的假設(shè),判斷如果您的應(yīng)用程序運行于多個服務(wù)器之上,它們是否依然成立。這個規(guī)則不但適合上述情況的應(yīng)用程序代碼,也適用于如 MBean 和其他管理接口的情況。
避免使用有狀態(tài)性不只是對 IBM/WebSphere 的建議,這是一個基本的 Java EE 設(shè)計原則。請參見 [Jewell] 的 Tyler Jewell 對有狀態(tài) Bean 的批評,其觀點和上述的觀點是相同的。
![]() ![]() |
![]()
|
學(xué)習(xí)一下 Java EE 中的兩階段提交事務(wù),并且使用這種方式,而不是開發(fā)您自己的事務(wù)管理。容器在事務(wù)優(yōu)化方面幾乎總是比較好的。
使用容器管理的事務(wù)(CMT)提供了兩個關(guān)鍵的優(yōu)勢(如果沒有容器支持這幾乎是不可能的):可組合的工作單元和健壯的事務(wù)行為。
如 果您的應(yīng)用程序代碼顯式地使用了開始和結(jié)束事務(wù)(也許使用 javax.jts.UserTransaction 或者甚至是本地資源事務(wù)),而將來的要求需要組合模塊(也許會是代碼重構(gòu)的一部分),這種情況下往往需要改變事務(wù)代碼。例如,如果模塊 A 開始了一個數(shù)據(jù)庫事務(wù),更新數(shù)據(jù)庫,隨后提交事務(wù),并且有模塊 B 做出同樣的處理,請考慮一下當(dāng)您在模塊 C 中嘗試使用上述兩個模塊,會出現(xiàn)什么情況呢?現(xiàn)在,模塊 C 正在執(zhí)行一個邏輯動作,而這個動作實際上將調(diào)用兩個獨立的事務(wù)。如果模塊 B 在執(zhí)行中失敗了,而模塊 A 的事務(wù)仍然能被提交。這是我們所不希望出現(xiàn)的行為。如果,相反地,模塊 A 和模塊 B 都使用 CMT 的話,模塊 C 也可以開始一個 CMT(通常通過配置描述符),并且在模塊 A 和模塊 B 中的事務(wù)將是同一個事務(wù)的隱含部分,這樣就不再需要重寫復(fù)雜的代碼了。
如 果您的應(yīng)用程序在同一個操作中需要訪問多種資源,您就要使用兩階段提交事務(wù)。例如,如果從 JMS 隊列中刪除一個消息,并且隨后更新基于這條消息的紀(jì)錄,這時,要保證這兩個操作都會執(zhí)行或都不會執(zhí)行就變得尤為重要。如果一條消息已經(jīng)從隊列中被刪除,而 系統(tǒng)沒有更新與此消息相關(guān)的數(shù)據(jù)庫中的記錄,那么這種系統(tǒng)是不一致的。一些嚴(yán)重的客戶及商業(yè)糾紛源自不一致的狀態(tài)。
我 們時常看到一些客戶應(yīng)用程序試圖實現(xiàn)他們自己的解決方案。也許會通過應(yīng)用程序的代碼在數(shù)據(jù)庫更新失敗的時候“撤銷”對隊列的操作。我們不提倡這樣做。這種 實現(xiàn)要比您最初的想象復(fù)雜得多,并且還有許多其他的情況(想象一下如果應(yīng)用程序在執(zhí)行此操作的過程中突然崩潰的情況)。作為替代的方式,應(yīng)該使用兩階段提 交事務(wù)。如果您使用 CMT,并且在單一的 CMT 中訪問兩階段提交的資源(例如 JMS 和大多數(shù)數(shù)據(jù)庫),WebSphere 將會處理所有的復(fù)雜工作。它將確保整個事務(wù)被執(zhí)行或者都不被執(zhí)行,包括系統(tǒng)崩潰、數(shù)據(jù)庫崩潰或其他的情況。其實現(xiàn)在事務(wù)日志中保存著事務(wù)狀態(tài)。當(dāng)應(yīng)用程序 訪問多種資源的時候,我們怎么強調(diào)使用 CMT 事務(wù)的必要性都不為過。如果您所訪問的資源不支持兩階段提交,那么您當(dāng)然就沒有別的選擇了,只能使用一種比較復(fù)雜的方法,但是您應(yīng)該盡量避免這種情況。
![]() ![]() |
![]()
|
只有在需要多種表示輸出類型,并且輸出類型被單一的控制器及后端支持時才使用 XML/XSLT。
我
們常聽到一些爭論說,為什么您選擇 XML/XSLT 而不是 JSP 作為表示層技術(shù),因為 JSP“允許您將模型和視圖混合在一起”,而
XML/XSLT 不會有這種問題。遺憾的是,這種觀點并不完全正確,或者至少不像白與黑那樣分的清楚。實際上,XSL 和 XPath
是編程語言。事實上,XSL
是圖靈完備的(Turing-complete),盡管它不符合大多數(shù)人定義的編程語言,因為它是基于規(guī)則的,并且不具備程序員習(xí)慣的控制工具。
問 題是既然給予了這種靈活性,開發(fā)人員就會利用這種靈活性。盡管每個人都認(rèn)同 JSP 使開發(fā)人員容易在視圖中加入“類似模型”的行為,而實際上,在 XSL 中也有可能做出一些同樣的事情。盡管從 XSL 中進行訪問數(shù)據(jù)庫這樣的事情會非常困難,但是我們曾經(jīng)見到過一些異常復(fù)雜的 XSLT 樣式表執(zhí)行復(fù)雜的轉(zhuǎn)換,這實際上是模型代碼。
然而,應(yīng)該選擇 JSP 作為首選的表示技術(shù)的最基本的原因是,JSP 是現(xiàn)在支持最廣泛的、也是最被廣泛理解的 Java EE 視圖技術(shù)。而隨著自定義標(biāo)記庫、JSTL 和 JSP2.0 的新特性的引入,創(chuàng)建 JSP 變得更加容易,并且不需要任何 Java 代碼,以及可以將模型和視圖清晰地分離開。在一些開發(fā)環(huán)境中(如 IBM Rational Application Developer)加入了對 JSP(包括對調(diào)試的支持)的強大支持,并且許多開發(fā)人員發(fā)現(xiàn)使用 JSP 進行開發(fā)要比使用 XSL 更加簡單,主要是因為 JSP 是基于例程的,而不是基于規(guī)則的。盡管 Rational Application Developer 支持 XSL 的開發(fā),但一些支持 JSP 的圖形設(shè)計工具及其他特征(尤其在 JSF 這樣的框架下)使得開發(fā)人員可以以所見即所得的方式進行 JSP 的開發(fā),而使用 XSL 有時不容易做到。
然而,這并不表示您絕不 應(yīng)該使用 XSL。在一些情況下,XSL 能夠表示一組固定的數(shù)據(jù),并且可以基于不同的樣式表(請參見 [Fowler])來以不同的方式顯示這些數(shù)據(jù)的能力是顯示視圖的最佳解決方案。然而,這只是一種特殊的情況,而不是通用的規(guī)則。如果您只是生成 HTML 來表達每一個頁面,那么在大多數(shù)情況下,XSL 是一種不必要的技術(shù),并且,它給您的開發(fā)人員所帶來的問題遠(yuǎn)比它所能解決的問題多。
![]() ![]() |
![]()
|
11. 當(dāng)使用 HttpSession 時,盡量只將當(dāng)前事務(wù)所需要的狀態(tài)保存在其中,其他內(nèi)容不要保存在 HttpSession 中。
HttpSessions
對于存儲應(yīng)用程序狀態(tài)信息是非常有用的。其 API 易于使用和理解。遺憾的是,開發(fā)人員常常遺忘了 HttpSession
的目的——用來保持臨時的用戶狀態(tài)。它不是任意的數(shù)據(jù)緩存。我們已經(jīng)見到過太多的系統(tǒng)為每個用戶的會話放入了大量的數(shù)據(jù)(達到兆字節(jié))。如果同時有
1000 個登錄系統(tǒng)的用戶,每個用戶擁有 1MB 的會話數(shù)據(jù),那么就需要 1G 或者更多的內(nèi)存用于這些會話。保持這些 HTTP
會話數(shù)據(jù)較小。不然的話,您的應(yīng)用程序的性能將會下降。一個大約比較合適的數(shù)據(jù)量應(yīng)該是每個用戶的會話數(shù)據(jù)在 2K-4K
之間。這不是一個硬性的規(guī)則。8K 仍然沒有問題,但是顯然會比 2K 時的速度要慢。一定要注意,不要使 HttpSession
變成數(shù)據(jù)堆積的場所。
一個常見的問題是使用 HttpSession 緩存一些很容易再創(chuàng)建的信息,如果有必要的話。由于會話是持久性的,進行不必要的序列化以及寫入數(shù)據(jù)是一種很奢侈的決定。相反地,應(yīng)該使用內(nèi)存中的哈希表 來緩存數(shù)據(jù),并且在會話中保存一個對此數(shù)據(jù)進行引用的鍵。這樣,如果不能成功登錄到另外的應(yīng)用服務(wù)器的話,就可以重新創(chuàng)建數(shù)據(jù)。(有關(guān)更詳細(xì)的信息,請參 見 [Brown2]。)
當(dāng) 談及會話持久性時,不要忘記要啟用這項功能。如果您沒有啟用會話持久性,或者服務(wù)器因為某種原因停止了(服務(wù)器故障或正常的維護),則所有此應(yīng)用服務(wù)器的 當(dāng)前用戶的會話將會丟失。這是件令人非常掃興的事情。用戶不得不重新登錄,并且重新做一些他們曾經(jīng)已經(jīng)做過的事情。相反地,如果啟用了會話持久性, WebSphere 會自動將用戶(以及他們的會話)移到另外一個應(yīng)用服務(wù)器上去。用戶甚至不知道發(fā)生了這樣的事情。我們曾經(jīng)見到過一些產(chǎn)品系統(tǒng),因為本地代碼中存在令人難以 忍受的錯誤(不是 IBM 的代碼!)而經(jīng)常崩潰,在這種情況下,上述功能仍然可以運行良好。
![]() ![]() |
![]()
|
12. 充分利用應(yīng)用服務(wù)器中不需要修改代碼的特性。
使用某些特性(如 WebSphere Application Server 緩存和 Prepared Statement 緩存)可以極大地提高性能,并且使得開銷最小。
前
面的最佳實踐 4
清楚地描述了這樣一種案例,即關(guān)于為什么應(yīng)該謹(jǐn)慎的使用可能修改代碼的應(yīng)用服務(wù)器特定的特性。它使得難以實現(xiàn)可移植性,并且可能給版本的遷移帶來困難。然
而,特別是在 WebSphere Application Server
中,有一套應(yīng)用服務(wù)器特定的特性,您可以并且應(yīng)該充分地利用它們,因為它們不會修改您的代碼。您應(yīng)該按照規(guī)范來編寫代碼,但如果您了解這些特性以及如何正
確地使用它們,那么您就可以利用它們顯著地改善性能。
作為這個最佳實踐的一個示例,在 WebSphere Application Server 中,您應(yīng)該開啟動態(tài)緩存,并且使用 Servlet 緩存。系統(tǒng)性能可以得到很大的提高,而開銷是最小的,并且不影響編程模型。通過緩存來提高性能的好處是眾所周知的事情。遺憾的是,當(dāng)前的 Java EE 規(guī)范沒有包括一種用于 Servlet/JSP 緩存的機制。然而,WebSphere 提供了對頁面以及片斷緩存的支持,這種支持是通過其動態(tài)緩存功能來實現(xiàn)的,并且不需要對應(yīng)用程序作出任何改變。其緩存的策略是聲明性的,而且其配置是通過 XML 配置描述符來實現(xiàn)的。因此,您的應(yīng)用程序不會受到影響,并保持與 Java EE 規(guī)范的兼容性和移植性,同時還從 WebSphere 的 Servlet 及 JSP 的緩存機制中得到性能的優(yōu)化。
從 Servet 及 JSP 的動態(tài)緩存機制得到的性能的提高是顯而易見的,這取決于應(yīng)用程序的特性。Cox 和 Martin [Cox] 指出,對一個現(xiàn)有的 RDF(資源描述格式)站點摘要 (RSS) Servlet 使用動態(tài)緩存時,其性能可以提高 10%。請注意這個實驗只涉及到一個簡單的 Servlet,這個性能的增長量可能并不能反映一個復(fù)雜的應(yīng)用程序。
為 了更多地提高性能,將 WebSphere Servlet/JSP 結(jié)果緩存與 WebSphere 插件 ESI Fragment 處理器、IBM HTTP Server Fast Response Cache Accelerator (FRCA) 和 Edge Server 緩存功能集成在一起。對于繁重的基于讀取的工作負(fù)荷,通過使用這些功能可以得到許多額外的好處。(請參見參考資料的 [Willenborg] 和 [Bakalova] 中描述的性能的提高。)
作 為該原則的另一個示例(我們常常發(fā)現(xiàn)客戶不使用它,僅僅是因為他們根本不知道它的存在),在編寫 JDBC 代碼時可以利用 WebSphere Prepared Statement Cache。在缺省情況下,當(dāng)您在 WebSphere Application Server 中使用 JDBC PreparedStatement 時,它將對該語句進行一次編譯,然后將其放到緩存中以便再次使用,不僅可以在創(chuàng)建 PreparedStatement 的同一方法中重用,還可以跨程序重用,只要其中使用了相同的 SQL 代碼或者另一個 PreparedStatement。省去重新編譯的步驟可以極大降低調(diào)用 JDBC 驅(qū)動程序的次數(shù),并且提高應(yīng)用程序的性能。要利用這個特性,您只需編寫相應(yīng)的 JDBC 代碼以使用 PreparedStatements,而不需要進行任何其他工作。在編寫代碼時,使用 PreparedStatement 代替常規(guī)的 JDBC Statement 類(它使用了純的動態(tài) SQL),您就可以實現(xiàn)性能的增強,而不會損失任何可移植性。
![]() ![]() |
![]()
|
提供一個 Java EE EAR 和可配置的安裝腳本,而不是黑盒二進制安裝程序。
在
大多數(shù)的實際場景中,大量的 WebSphere Application Server
用戶在相同的共享單元中運行多個應(yīng)用程序。這意味著,如果您提供一個需要安裝的應(yīng)用程序,那么它必須能夠合理地安裝到現(xiàn)有的基礎(chǔ)設(shè)施中。這意味兩個方面:
首先,您必須限制關(guān)于環(huán)境的假設(shè)的數(shù)目,并且因為您無法預(yù)料到所有的情況,所以您的安裝過程必須是可見的。這里所說的可見是指,不應(yīng)該提供二進制可執(zhí)行文
件形式的安裝程序。執(zhí)行安裝任務(wù)的管理員需要清楚安裝過程對他們的單元所進行的操作。為了實現(xiàn)這種方式,您應(yīng)該提供一個 EAR 文件(或者一組
EAR
文件)以及相關(guān)的文檔和安裝腳本。這些腳本應(yīng)該具有可讀性,以便安裝程序能夠知道它們需要執(zhí)行的操作,并對腳本的內(nèi)容進行驗證以確保不會執(zhí)行任何危險的操
作。在有些情況下,腳本并不合適,用戶可能需要使用一些曾用過的其他方法來安裝 EAR,這表示您必須記錄安裝程序所完成的工作!
![]() ![]() |
![]()
|
14. 充分利用應(yīng)用服務(wù)器環(huán)境所提供的服務(wù)質(zhì)量。
設(shè)計可使用 WebSphere Application Server Network Deployment 集群的應(yīng)用程序。
我
們已經(jīng)介紹了利用 WebSphere Application Server
安全和事務(wù)支持的重要性。還有一個更重要的、常常被我們忽視的問題,即集群。需要將應(yīng)用程序設(shè)計為能夠運行于集群的環(huán)境。大多數(shù)實際的環(huán)境需要通過集群來
實現(xiàn)可擴展性和可靠性。無法進行集群的應(yīng)用程序很快會導(dǎo)致災(zāi)難的出現(xiàn)。
與集群緊密相關(guān)的是支持 WebSphere Application Server Network Deployment。如果您正在構(gòu)建一個應(yīng)用程序并打算將它賣給其他人,請確保您的應(yīng)用程序可以運行于 WebSphere Application Server Network Deployment,而不僅僅是單個服務(wù)器版本。
![]() ![]() |
![]()
|
致力于構(gòu)建真正利用 Java EE 功能的 Java EE 應(yīng)用程序。
有
件非常煩人的事情我們曾多次遇到過,某個應(yīng)用程序聲稱可以運行于 WebSphere 中,但它并不是一個真正的 WebSphere
應(yīng)用程序。我們曾見過幾個這樣的示例,其中有一小段代碼(可能是一個 Servlet)位于 WebSphere Application
Server 中,而其余所有的應(yīng)用程序邏輯實際上位于單獨的進程中,例如一個以 Java、C、C++ 或其他語言(沒有使用 Java
EE)編寫的守護進程負(fù)責(zé)完成實際的工作。這并不是一個真正的 WebSphere Application Server
應(yīng)用程序。對于這樣的應(yīng)用程序,WebSphere Application Server 所提供的幾乎所有的服務(wù)質(zhì)量都不可用。對于那些認(rèn)為這是
WebSphere Application Server 應(yīng)用程序的人來說,他們會突然的醒悟過來,原來并非如此。
![]() ![]() |
![]()
|
更改是在所難免的。安排新的發(fā)行版和修復(fù)程序更新,以便您的客戶能夠獲得最新的版本。
WebSphere
Application Server 在不斷地發(fā)展,所以 IBM 定期地給出 WebSphere Application Server
的修復(fù)程序,這是很正常的,并且 IBM
還定期地發(fā)布新的主要版本。您需要為此做好安排。這會影響到兩類開發(fā)組織:內(nèi)部開發(fā)人員和第三方應(yīng)用程序供應(yīng)商。基本的問題是相同的,但對兩者的影響則有
所不同。
首先考慮修復(fù)程序。IBM 定期發(fā)布建議更新, 以修復(fù)產(chǎn)品中已發(fā)現(xiàn)的錯誤。盡管不太可能始終運行于最新的級別,但請注意,不要隔得太久。那么究竟“隔多久”是可以接受的呢?對于這個問題沒有什么正確的 答案,但是您應(yīng)該安排好對幾個月內(nèi)的發(fā)行版進行修復(fù)級別更新。是的,這表示一年要更新好幾次。內(nèi)部開發(fā)人員可以忽略某些修復(fù)級別,一次僅支持一個修復(fù)級 別,以降低測試成本。應(yīng)用程序供應(yīng)商則沒有這么幸運。如果您是應(yīng)用程序供應(yīng)商,那么您同時需要支持多種修復(fù)級別,以便您的客戶能夠?qū)⒛能浖c其他軟件一 同運行。如果您僅支持一種修復(fù)級別,那么很可能無法找到同時兼容于多種產(chǎn)品的修復(fù)級別。實際上對于供應(yīng)商而言,最好的方法是使用支持“向上兼容修復(fù)程序” 的模型。IBM 使用了這種方法來支持所集成的來自其他供應(yīng)商的產(chǎn)品(如 Oracle®、Solaris™ 等等)。有關(guān)更詳細(xì)的信息,請參考我們的支持策略。
下 面再考慮一下主要版本更新。IBM 定期地發(fā)布新的主要發(fā)行版,其中對我們的產(chǎn)品進行了主要的功能更新。我們暫時繼續(xù)支持舊的主要發(fā)行版,但不會太久。這意味著您必須安排從一個主要發(fā)行版轉(zhuǎn) 到另一個主要發(fā)行版。這是不可避免的,并且應(yīng)該在您的成本模型中加以考慮。如果您是供應(yīng)商,這意味著您必須經(jīng)常地對您的產(chǎn)品進行更新,以支持新的 WebSphere Application Server 版本,否則您的客戶將停滯于不受支持的 IBM 產(chǎn)品,我們曾多次碰到過這種情況!如果您正從供應(yīng)商處購買產(chǎn)品,我們鼓勵您要留心您的供應(yīng)商,以確保他們承諾支持 IBM 產(chǎn)品新的版本。停滯于不受支持的軟件是一種非常危險的情況。
![]() ![]() |
![]()
|
17. 在代碼中所有關(guān)鍵的地方,使用標(biāo)準(zhǔn)的日志框架記錄程序的狀態(tài)。
這包括異常處理程序。使用像 JDK 1.4 Logging 或 Log4J 這樣的日志框架。
有
些時候,日志記錄是最乏味的工作,降低了編程的價值,但是這樣做可以減少調(diào)試的時間,并盡快地完成相應(yīng)的任務(wù)。根據(jù)一般的經(jīng)驗,在每個過渡的地方,需要進
行日志記錄。當(dāng)您將參數(shù)從一個方法傳遞到另一個方法,或從一個類傳遞到另一個類,需要進行日志記錄。在對一個對象進行某種轉(zhuǎn)換時,需要進行日志記錄。在碰
到不解之處時,需要進行日志記錄。
在決定了進行日志記錄之后,需要選擇一種合適的框架。實際上有許多選擇,但是我們偏愛 JDK 1.4 Trace API,因為它們已全面地集成到了 WebSphere Application Server 跟蹤子系統(tǒng)中,并且是基于標(biāo)準(zhǔn)的。
![]() ![]() |
![]()
|
18. 在完成相應(yīng)的任務(wù)后,請始終進行清理。
無
論運行于開發(fā)、測試或生產(chǎn)環(huán)境中,我們發(fā)現(xiàn) Java EE
應(yīng)用程序最常見的錯誤之一是內(nèi)存泄漏。絕大部分情況是因為開發(fā)人員忘了關(guān)閉連接(大多數(shù)情況下是 JDBC
連接)或?qū)ο蠓祷氐匠刂小τ谌魏涡枰@式關(guān)閉的或需要返回到池中的對象,請確保進行了這樣的操作。不要編寫出這樣糟糕的代碼。
![]() ![]() |
![]()
|
19. 在開發(fā)和測試過程中遵循嚴(yán)格的程序。
大
型系統(tǒng)的開發(fā)是非常困難的,所以應(yīng)該十分謹(jǐn)慎。但是,我們常常發(fā)現(xiàn)一些團隊疏于管理、或者不能全心全意地遵循相關(guān)的開發(fā)方法(這些方法可能不適用于他們正
在進行的開發(fā)類型)、或者他們并沒有很好地理解這一點。最為糟糕的可能是嘗試每個月更換不同的開發(fā)方法,在單個項目的生命周期中,一個團隊從 RUP
改變?yōu)?XP,以及一些其他敏捷方法。
總之,對于大多數(shù)團隊而言,只要團隊成員能夠很好地理解、嚴(yán)格地執(zhí) 行、并根據(jù)特定的技術(shù)本質(zhì)和使用該方法的團隊進行適當(dāng)?shù)恼{(diào)整,那么幾乎任何一種方法都是有效的。對于那些尚未采用任何方法、或者那些不能夠完全地利用所選 方法的團隊,我們建議他們參考一些優(yōu)秀的著作,如 [Jacobson]、[Beck1] 或 [Cockburn]。另一個有價值的信息來源是最近公布的用于 Eclipse Process Framework [Eclipse] 的 OpenUP 插件。對于這個已經(jīng)介紹過的主題,我們不想做過多的重復(fù),建議讀者參考 [Hambrick] 和 [Beaton2](請參見參考資料)。
![]() ![]() |
![]()
|
在這個簡短的摘要中,我們已經(jīng)向您介紹了 Java EE 中的核心模式和最佳實踐,它們使得 Java EE 開發(fā)成為一種可管理的過程。盡管我們并沒有給出所有在實踐中使用這些模式的必要細(xì)節(jié),但是我們希望能夠給您足夠的指點和指導(dǎo),以幫助您決定下一步要做什么。