轉:J2EE專案10大風險

zingers發表於2002-11-16

避免本文所列之10大J2EE風險,確保企業級Java專案成功
作者:Humphrey Sheil

翻譯:Blueski

說明:
本文已在51CMM網站《中國系統分析員》雜誌第3期刊載。
原文在 http://www.javaworld.com/javaworld/jw-03-2001/jw-0330-ten.html

摘要
當你開始著手組織一個企業級Java專案的時候,就如同開始同時輪迴地扔好幾個魔術小球: 業主關係處理、持續而漫長的設計開發過程,以及保持健全與完整性,等等。每一個“小球”都會帶來其固有的風險,有些顯而易見,有些則不易發現。儘管如此,所有這些風險都是完全可以避免的。本文作者Humphrey Sheil分析了威脅到企業級Java專案成功的10大風險, 並一一列出了風險規避的策略方法。

--------------------------------------------------------------------------------

在過去這段時期裡,我擔任過程式設計師、高階設計師以及架構設計師等工作,見識過很優秀的企業級Java專案,也見識過不好的,甚至很"醜陋"的專案。有時候我會自己問自己,為什麼一個專案可以取得成功,而另一個卻走向失敗?很難定義出某種規則或標準來表明各個不同的專案應該如何成功,J2EE專案也並不例外。但與此相反的是,我們可以從各個角度和層次上去考察專案失敗的原因,如果很好地避開了這些風險,專案就可以取得成功。在本文中,我將提出排名前10位的企業級Java專案風險,供讀者參考。

在各種各樣的風險中,有些風險只是延緩了專案的進度,有些帶來了一些不必要的工作,而另一些則會把成功的可能性徹底地消除。不過,如果預先有了足夠的準備和清醒的認識,那麼並沒有不可避免的事情。這好比如果你是一名旅行者,你清楚地知道前面的道路在什麼方向,做了充分的準備,又有一位清楚知道哪裡有危險的嚮導,這樣就會比較順利地到達自己的目的地。

本文采用了以下結構來描述風險: 

風險名稱:風險的標題(使用粗體)
專案階段:在哪個專案階段會發生風險情況
影響階段:會影響到以後的哪些階段
症狀: 風險產生時的症狀
規避方案:如何規避風險或者把其對專案的影響降低到最小程度
備註: 風險相關的補充說明和提示
透過對企業級Java專案的仔細考察,本文將J2EE專案過程分解為以下幾個階段:

提供商選擇: 在開始你的J2EE專案之前,要選擇最合適的提供商,從應用伺服器到開發工具組合,一直至工作期間享用的咖啡的廠商。:) 
設計: 在遵照一系列嚴格的規範和軟體工程方法的前提下,可以開始進行足夠充分的設計,然後再很自然地進入開發階段。在開發之前,要周全地考慮好正在做什麼,以及如何往下做的問題。另外,我使用了一些設計模板來確信在進入開發之前,已經想到了所有的問題和可能的解決方案。但是,我有時也在該階段做一些編碼,有時候這樣做可以回答一些問題,有效地判斷出效能上和模組劃分上的問題。 
開發: 也就是程式開發階段,選擇一些好的開發工具,進行精良的設計等等,在這個階段將顯示其優越性,並且可以給開發帶來很大的幫助。 
穩定性/負載測試:在該階段,系統架構師和專案經理應該凍結住產品特性,並把焦點放在質量以及產品引數(允許的併發使用者數量,故障恢復情況,等等)上。質量和效能在該階段應得到足夠的重視。當然,最好應該避免在前階段寫出不良的執行緩慢的程式碼而到本階段來作很多的修改。
成熟期:這不是一個真正的專案階段,而是一個固定的準備階段。過去潛伏的錯誤(來自於糟糕的設計和開發、錯誤的廠商選擇)可能出現並影響你的系統。


圖1 由於各種原因而受到影響的專案階段

 

OK,以下讓我們進入 top 10 專案風險!

 


--------------------------------------------------------------------------------

風險1:沒有真正理解 Java, EJB, 和J2EE

這個問題可以分解為3個部分,以便於分析。

描述: 沒有真正理解Java

專案階段:開發

影響階段:設計、穩定性測試、成熟期

對系統效能的影響:可維護性、可擴充套件性、效能

症狀:

重複開發了JDK核心API中的功能或類
不懂得以下列表中的某些項(這只是一些主題或者實際例子而已):
垃圾收集器 (train, generational, incremental, synchronous, asynchronous)
物件在何時能被進行垃圾收集 -- dangling references
使用的繼承機制及其權衡
over-riding和over-loading方法
為什麼java.lang.String (在這裡用你所中意的類代替) 提供的效能不好
Java中的pass-by參考語義和EJB中pass-by值的語義的比較
使用 == 或者使用equals() 方法 for nonprimitives
在不同平臺上Java執行緒的執行順序方式(例如是否是搶先方式的)
新執行緒和本地執行緒的比較
Hotspot技術(以及為什麼舊的效能調整技術降低了Hotspot 的最佳化效果)
JIT,以及什麼時候好的JIT變得不好(未安裝的JAVA編譯器,以及你的程式碼執行得剛夠良好)
API蒐集
RMI
規避方案:
你需要不斷改進Java方面的知識,尤其是深入瞭解Java的優勢和不足之處。Java的存在價值已經遠不止是一種語言,理解平臺(JDK及工具等)也是同樣重要的。具體地說,你應該是經過認證的Java程式設計師,如果你不是的話,也許你有時會為還有那麼多不知道的內容而感到驚訝。另外,你可以加入Java的郵件列表。以前我曾加盟過的每一個公司都加入了這樣的郵件列表,從同行中學到技術,這將是你最好的資源。

備註:
如果你或者你的團隊中的成員不真正瞭解程式語言和平臺,怎麼還能保持成功的希望呢?強幹的Java程式設計師之於EJB和J2EE,就象是鴨子之於水一樣。與此相反,比較弱的、沒有經驗的程式設計師只能開發出質量低劣的J2EE應用程式。

描述: 沒有真正理解EJB

專案階段:
設計

影響階段:
開發、穩定化

對系統的影響:
維護

症狀:

EJB在第一次被呼叫後沒有再被使用到(尤其是stateless session bean)
沒有重複利用價值的EJB
不理解開發者要做什麼,容器提供什麼
EJB沒有依照規範定義(fire執行緒, 載入了本地庫,試圖執行I/O,等等)
解決方案:
要改進關於EJB方面的知識,可以找一個週末來閱讀EJB規範 (1.1版有314頁),然後閱讀2.0規範(524頁!),這樣可以瞭解到1.1沒有定義到的而在2.0規範中補充的內容。EJB開發者從18.1及18.2章節開始閱讀是比較合適的。

備註:
不要從提供商的角度去看EJB,要確切地知道規範所支援的標準EJB模型和基於這些模型的特殊應用之間的區別。這也會有助於你遷移到別的提供商的時候所用。

描述: 沒有真正理解J2EE

專案階段:
設計

影響階段:
開發

對系統的影響:
維護、擴充套件性、效能

症狀:

"Everything is an EJB"的設計方式
用手工事務管理取代了容器-提供的機制
自定義方式的安全處理 -- J2EE平臺在企業級計算中,從表示邏輯到後臺處理,已具有最完整的整合安全架構;但很少用到其全部功能。
解決方案:
學習J2EE的關鍵元件,並且瞭解它們的優缺點,依次用它們替代每一個服務;“知識就是力量”在這裡是行之有效的。

備註:
只有知識能夠彌補這些問題。好的Java開發者會成為好的EJB開發者,此後也應逐漸成為J2EE得道高手。Java和J2EE知識掌握得越多,設計和開發工作就會越出色。在設計階段一切都會有條不紊。



--------------------------------------------------------------------------------

風險2: 過度設計(Over-engineering) (採用 EJB或者不採用EJB)
專案階段:
設計

影響的專案階段:
開發

對系統的影響:
維護、擴充套件性、效能

症狀:

過於龐大的EJB
開發者無法解釋EJB做什麼,以及其間的聯絡
無法重複使用的EJB、元件或者服務
EJB啟動了新的事務,而該事務本該由一個已存在的EJB啟動
為了安全,把資料分離級別定得太高
解決方案:
過度工程化的解決之道直接來自於極限程式設計 (XP)方法:用最小的設計和程式設計來滿足需求,除此之外別無它幹。除非你需要明確知道今後可能的需求,如將來的負載要求,或者系統在最高負載下的表現,否則大可不必為系統將來的情況做太多考慮或猜測。另外,J2EE平臺已經定義了可伸縮性及出錯恢復等特性,可以讓伺服器系統為你進行處理。
在最小的系統中,只包含一個個小元件,這些元件只做一件事,只要把這些要求做到的進行實現,系統穩定性就已經得到了提高,而且,你的系統的可維護性會變得很強,在未來要增加功能以滿足新的需求也將變得容易。

備註:
除了上面所列方案之外,可以推行設計模式 -- 它們可以顯著地改進你的系統設計。EJB模型本身也廣泛使用了設計模式。例如,每個EJB所帶的Home 介面就是Finder和Factory模式的例項。EJB的remote介面扮演了一種實際bean實現的代理,並且對於提供容器的能力也是至關重要的,這些容器擷取呼叫訊號並提供諸如透明(transparent)負載均衡的服務。忽視設計模式也是危險的一部分。

我常提到要反對的另外一種危險是:僅僅是為了使用EJB而使用EJB。在你的應用中的某一部分可能並不需要EJB,甚至你的整個應用都不需要。這是過度工程化所走的極端,而且我確實也目睹了一些良好的servlet和JavaBean應用被重構為EJB,而這樣做並沒有很好的技術上的理由。



--------------------------------------------------------------------------------

風險3: 沒有將業務規則和邏輯表現形式相分離
專案階段:
設計

影響的專案階段:
開發

對系統的影響:
維護、擴充套件性、效能

症狀:

過於龐大、沒有邊際的JSP程式
在業務邏輯改變的時候必須修改JSP
在要求改變介面顯示的時候需要修改並重新配置EJB和其它後臺元件
規避方案:
J2EE平臺使你有機會將表示邏輯和導航控制相分離,進而與業務規則相分離。這被稱為模式2結構。

備註:
可以使用具有一致性的設計來進行使用者介面框架的連線。(例如可以使用taglib),這將幫助你避免邏輯分離的問題。有許多現成的好的方法可供選擇。對每一個分別進行評估,然後採用最合適的框架。



--------------------------------------------------------------------------------

風險4: 沒有在開發環境中進行適當的配置
專案階段:
開發

影響的專案階段:
穩定化、併發、成熟期

對系統的影響:
你的權衡

症狀:

經過多日或數週的時間才能過渡到成熟系統
風險存在與過渡期,帶有很多不確定性,有些主要的功能場景沒有被測試到
實際系統中的資料和開發、測試中的資料不同
無法在開發者機器上進行組建
應用行為在開發、穩定化及產品環境中各不相同
規避方案:
解決之道是忠實地在開發環境中配置實際的環境,讓開發所用環境接近於要實施產品的環境。如果未來環境是JDK 1.2.2及Solaris 7,那麼不要在JDK 1.3及Red Hat Linux上進行開發。對於所用的應用伺服器也是如此。同樣,要快速地看一下產品資料庫中的資料,並將這樣的資料用於測試。不要依賴於人工建立的資料。如果產品資料很敏感,則要使之變得不敏感,然後把它配置起來。開發中未能預期到的產品資料將對以下過程產生破壞:

資料檢驗規則
系統測試行為
系統元件構建(特別地包括:EJB-EJB以及EJB-資料庫)
最為糟糕的是,這樣還可能產生異常、空指標,以及你從沒見過的問題。

備註:
開發人員常把安全性問題放到穩定化階段才開始解決。要防止這樣的陷阱產生,你也可以花費同樣多的時間在業務邏輯中改進安全性。

成熟期是一個複雜的過程,其中充滿了技術性問題和非技術性問題。你可能會陷於想不到的一大堆問題中,這就是成熟化所意味的一切。開發及穩定化環境過程為你提供了製造更多這樣的問題,以及發現這樣的問題的地方,不斷去做,就可以大大減少風險。

你做的工程越多,你就越能瞭解什麼是可行的,什麼是不可行的。你可以對工程問題進行記錄,以避免同樣的錯誤重複發生。



--------------------------------------------------------------------------------

風險5: 選擇了錯誤的提供商
專案階段:
提供商選擇

影響階段:
設計、開發、穩定化/負載測試,成熟化

對系統的影響:
可伸縮性、效能、可維護性及穩定性

症狀:


開發人員要使用更多的時間來處理工具方面的問題,而不是很有成效地使用這些工具
為了應付已知的和未知的問題,而不得不進行顯著的系統重新設計
在不同的工具之間很難進行整合(應用伺服器與IDE工具,IDE工具與偵錯程式,原始碼控制與合成工具,等等)
對於IDE工具和偵錯程式等,開發人員往往排斥它們,而推崇自己所喜歡的工具
規避方案:
為了避免風險5,你需要一個很好的提供商選擇過程,風險10的規避也適用於此。

要真正衡量一種IDE工具是否最合適的方法是真正地進行使用。而唯一來評估一種J2EE應用的方法是建立一種概念試驗來進行證明,在試驗中要包含你的應用框架。事實上,你也不希望在花費了3個月時間進行了培訓和開發後,在使用時又發現一些bug。

假設在開發到一半的時候,突然發現你的工具集有問題,那麼你早應該知道,有些工具確實比另一些更重要。如果你所選的應用伺服器不能充分滿足你的需要,你只好修改原先的設定。如果IDE不好,則需要設定最低限度的程式碼標準,並讓開發人員任意選擇他們認為最為有效的工具。

備註:
要真正瞭解到哪一個供應商對一項特殊的任務來說最合適,其實並不是一件一次性決定的事情。你需要不斷地跟蹤與評估這個市場。例如,在過去的一年裡我用過4種不同的IDE工具,這取決於我使用了什麼樣的應用伺服器、平臺,是否使用EJB等。



--------------------------------------------------------------------------------

風險6: 不瞭解你的提供商
專案階段:
提供商選擇

影響階段:
提供商選擇階段後面的所有階段:設計、開發、穩定化/負載測試、成熟化

對系統的影響:
可維護性、可伸縮性、效能

症狀:

開發所用週期超過了最壞預測的週期1/3以上
提供商已經提供了某項功能,但開發者在不知道的情況下重新進行了該項功能的開發
規避方案:
為了規避這樣的風險,你可以儘可能地訂閱提供商的網上資源,例如郵件列表、新聞組、版本資訊(尤其是其中的bug修復補丁的說明等),你能從中得到無法估量之多的收穫。

一旦你已經選定了提供商,那麼立即就要投資進行培訓,並且儘可能趕在專案啟動以前。然後,逐漸在團隊中建立起對此提供商的認識及信任。試著建立幾個EJB並部署一下,再用你的表示層技術 (Swing GUI, JSP等)來呼叫它們。如果你既要搭建開發環境,又要同時在實現專案目標,就會產生一些不必要的衝突。實際上,我也見到過一直沒有進行構建過程的情況:“我們沒有時間。”因此,這些工作必須提早進行。有些人會說:“我們的計劃中沒有為我們提供這些時間。”我的回答是:“你的計劃中並沒有不給你時間使你不這麼做啊。”

備註:
在J2EE世界裡,各提供商產品的技術相容性究竟如何?讓我們看一下IBM和BEA的具體分析吧。兩者都分別在各自的應用伺服器中支援EJB 1.1。那麼,實際上BEA WebLogic 5.1和IBM WebSphere 3.5究竟有多少相似之處呢?

BEA WebLogic和IBM WebSphere的系統配置和管理方式幾乎完全不同。
IBM在WebSphere中採用了全面的GUI環境,而與之相對的是,BEA 在WebLogic中提供一整套命令列。
IBM WebSphere使用IIOP來和CORBA異常進行通訊,這些異常對程式設計師來說是可見的;WebLogic根本沒有CORBA構造,而預設使用t3協議。
WebSphere和Visual Age銜接緊密,而WebLogic是IDE無關的,實際上,你幾乎可以使用任何的開發工具。
由此可見,差異還是相當多。如果你是一種應用伺服器的專家,並不意味著你就是所有應用伺服器的專家。這種區別體現在IDE,debugger,build工具,配置管理等等方面。具備某提供商的某項特殊工具的使用經驗,可以在評估該提供商的競爭對手產品時具有一些便利。但是,不要奢望在不同產品之間進行無縫的轉移或銜接。因此,你不得不花費足夠多的時間在熟練掌握這些工具上。



--------------------------------------------------------------------------------

風險7: 設計中沒有充分考慮到可伸縮性和產品效能
專案階段:
設計

受影響的專案階段:
開發、負載測試及成熟化

對系統的影響:
可伸縮性、效能、可維護性

症狀:

無法忍受的速度緩慢
系統給伺服器端增加的沉重負擔,而無法利用到一些聚簇技術。
規避方案:
把精力集中於效能和可伸縮性方面的需求,明確開發中要達到的效能指標。如果你需要每秒50個事務,而你的EJB設計只能提供40個,那麼你就需要考慮替代方案,諸如儲存過程,批處理,或者重新考慮OLTP的設計。

儘可能讓你的提供商加入進來,他們應該非常清楚其產品的強項和弱處在哪裡,然後給你提供最直接的幫助。

備註:
本風險與風險2 (over-engineering)似乎有些衝突。實際上,兩者相互影響。 我對風險2給出的解決方案是,只在絕對必要的情況下才進行構建。而對與效能和可伸縮性,你要預先劃分好什麼是必須要做的。

如果你實現就識別出系統需要非常強的可伸縮性,並把它作為一個比較關鍵的需求,那麼你首先需要選擇一個帶有很強的簇支援及事務型快取的應用伺服器。另外,你應把業務物件設計為EJB,從而可以充分利用伺服器架構的優勢。 XP也沒有問題,你仍然是隻做絕對必要的工作。

我把這樣的觀點看作是一種檢查和平衡的方法。我們只需要最簡單可能性的系統,該系統只提供客戶所需要的功能與行為即可。



--------------------------------------------------------------------------------

風險8: 陳舊的開發過程
專案階段:
開發

影響階段:
穩定化,成熟化

對系統的影響:
可維護性、程式碼質量

症狀:

專案計劃看上去似乎類似於瀑布模型: “首先草構設計,然後在一個很長的週期裡進行開發。”
由於不存在構建(build)過程,每次構建都象是噩夢
構建的日期等於損失開發的日期,因為什麼也沒有做成
在整合以前元件沒有分別被充分地測試過,而整合測試意味著將2個不穩定的元件放在一起,然後檢視堆疊裡的跟蹤結果。
規避方案:
好的軟體方法學將提高你的軟體生命期。此前我已經提到XP方法,你可以在網上找到很多這方面的資料。

備註:
JUnit可以用來進行單元測試,Ant工具可以進行編譯與構建,這2種工具都對XP方法有很好的支援。



--------------------------------------------------------------------------------

風險9: 沒有好的架構方式
專案階段:
開發

影響階段:
開發、穩定化、成熟期

對系統的影響:
可維護性、可伸縮性、程式碼質量

症狀:

在程式碼中使用了很多次的核心庫中發現Bug。
沒有建立日誌標準 -- 於是系統的輸出很難讀取或者解析。
不良的不一致的異常處理。在有些站點中我們甚至可以看到,出錯資訊直接暴露給了終端使用者,例如在使用者在他的購物車核帳時傳送一條SQLException堆疊跟蹤資訊,使用者接著會怎麼做?打電話給資料庫管理員要求對primary key約束進行修補嗎?
以下任務已經被開發者以各種方式處理了無數次了,這些都有必要放在任何構架設計的第一批目標中。 

日誌
異常處理
與資源的連線(資料庫,名字服務等)
構建JSP頁
資料合法性檢查
規避方案:
我是一個輕方法學的信徒和實踐者。我在JavaWorld 上的第一篇文章 -- "Frameworks Save the Day" -- 就是研討在企業Java環境中的架構。即使你已經開始開發了,此時考慮一下架構仍然是值得的。可能你不得不忍受一下重構帶來的異常處理和日誌處理,但從長遠來看還是值得的,這樣即省時間又省錢。

備註:
讓我們想一下在構架中基於元件開發的可重用性的不同等級。第一級別是plumbing,具有0.9以上的可重用比例,也就是說,有90%的專案可以對它重複利用。 服務定義得越詳細,重用比例就越低。換句話說,我需要構建一個會計服務,但要提供這些資源與用法的管理,以便於其它50%專案中可以對它們進行重複利用。但是對那些專案來說,能得到這些資源,那真是太好了!



--------------------------------------------------------------------------------

風險10: 專案計劃和設計基於市場效應,而脫離了技術現實

備註: 不斷有新人加入到Java/EJB的開發領域中來,不理解Java的人數一般比想象中還要多。

專案階段:
所有階段都會受到影響,包括提供商的選擇

影響階段:
所有階段都會受到影響

對系統的影響:
可維護性、可擴充套件性、設計質量、程式碼質量

症狀:

輕率地進行技術決策,認為EJB只是為了行動式處理的方便
選擇提供商的時候沒有隨即進行產品的試用
在專案的生命週期內還需要更換工具
規避方案:
不要輕易相信專案外部的任何人的看法,這些人可能已經有一些既得利益,不要相信提供商的說法(除非你早已經瞭解),也不要相信白皮書。如果你要取得來自真實世界的關於應用伺服器的建議,可以在網上取得。你還可以下載這些工具進行評估,用它們做一些原型,並執行一下其中的樣例。(好的提供商都有這樣的樣例)。

總的來說,為你的專案選擇最好的提供商及工具需要時間,而你可能沒有太多的時間。你可以把選擇範圍限制在3-4個物件,然後用一週時間進行比較和檢驗。最後從中選出比較滿意的工具和產品。

備註:
如果你缺少J2EE經驗,則可能會在專案前期就產生問題。在前期所確定的決策會影響整個過程,並進而影響專案的成功。好的J2EE諮詢專家將能夠幫助你選擇好的提供商,併為設計和開發刻劃出一個好的構形。



--------------------------------------------------------------------------------

僅僅只有這10項風險嗎?

10只是一個特定的數字,顯然,還有更多更多的風險會存在。只是我可以保證的是,如果你克服了所列的各項風險,那麼你的專案會有出色的表現並已打好了成功的基礎。

還有一項需要注意,即沒有任何東西可以代替經驗和計劃。如果你沒有經驗,那麼一定要想辦法取得並積累。千萬不要一邊做專案一邊進行培訓。在開發之前要預先做好充分的準備,最好是在設計以前就進行準備。可以讓你的團隊接受Java/J2EE顧問的指導,並確保這樣的指導能夠傳遞到整個其他的團隊成員。

最後,還有必要提到以下幾點:

軟體工程的外界影響
什麼時候進行單元測試,什麼時候進行整合測試?
設計模式
異常處理
結論
總的說來,以上10大風險是你在企業級Java專案開發過程中將面對的主要困難。我也相信在你的旅程中一定還有更多的陷阱,但我比較確信的是我所提到的風險已經涵蓋了主要的問題。最後讓我們按照優先順序重新列舉一下10大風險: 

沒有真正理解Java, 沒有真正理解EJB, 沒有真正理解J2EE
過度設計(Over-engineering)
沒有將業務規則和邏輯表現形式相分離
沒有在開發環境中進行適當的配置
選擇了錯誤的提供商
不瞭解你的提供商
設計中沒有充分考慮到可伸縮性和產品效能
陳舊的開發過程
沒有好的架構方式
專案計劃和設計基於市場效應,而脫離了技術現實
最後,讓我祝你好運! 


--------------------------------------------------------------------------------

譯後記:

我基本上沒有做過J2EE專案,但仍有足夠勇氣翻譯這樣的文章。在國內軟體公司裡,極端情況下也許到處都是風險,這樣也就無所謂風險了。對於選擇J2EE技術路線,自然會有J2EE特有的風險,因此本文中的風險往往也是特別針對J2EE專案的。另外,對於J2EE專案,我們不應該忽視的一點是,其技術上的風險會更大一些。

相關文章