淺談J2EE開發 之 高效的方法

directray發表於2010-11-20

上次說到了J2EE開發中穩定的代價,也就是效能下降以及開發者的學習成本以及學習曲線。今天來說說J2EE開發中的高效。要理解高效,首先要明白高效是什麼意思,只有在同一個大前提下才能明白在討論什麼,不然的話,南轅北轍了。

首先,高效是建立在穩定的基礎上的,其次,高效是在符合業務邏輯的基礎上,最後,高效不僅僅體現在程式跑的快上。

第一位的,自然是一些最基本的開發技巧。比如說,用StringBuffer,不要頻繁開關資料庫連線。這些東西在任何一本書上都可以查到。本質上是減少CPU指令,從而減少執行耗時。這裡提一句,在JDK5及以上的版本里,String類用加法連線的話,除了不好看以外,已經沒什麼問題了。Sun的編譯器會編譯成StringBuilder實現。這個東西是StringBuffer的執行緒不安全版本。換言之,如果同時有兩條指令操作同一個StringBuilder的例項,那就要看運氣才知道結果了。執行緒安全,就慢,因為同步。執行緒不安全,就快,因為不同步。至於要同步還是不同步,並不是一概而論的。

同步或者不同步,本身是針對方法或者物件說的,也就是所謂的加鎖。這裡不討論各種鎖的實現,比如自旋鎖之類。那麼,何時用同步,何時用不同步呢?

要回答這個問題,首先要明白同步和不同步的用途,也就是說,什麼時候用同步,什麼時候不用同步。首先從道理上來說,對同一個物體,對它的操作應該是排隊進行的。也就是說,先進行操作一,再進行操作二。換一個說法就是,操作一沒有宣告自己完成之前,操作二不得進行行動,這個就是同步。同步的好處很明顯,能避免很多由於同時訪問同一個物件帶來的麻煩。比如操作一會從籃子裡拿出來一個雞蛋,操作二要對籃子裡的雞蛋計數。如果兩者相差很短,短到手剛伸進籃子裡,還沒拿出來的時候就開始計數了,那麼最終結果就是匪夷所思的。等兩個操作都結束了,雞蛋明明少了一個了,可是計數的人卻說,我明明數的要多一個。

這就是不同步帶來的問題。

從上面的例子看起來,貌似什麼時候都要同步才行,一旦不同步就要冒風險。其實這句話從某種意義上來說是對的,不同步的確是有風險的。但是,這不是絕對的,不是百分之一百存在的。如果非同步有風險,那為什麼沒有被明令禁止?這就說明非同步還是有一定的用武之地的。那麼什麼時候可以使用非同步操作呢?

不會改變物體狀態的操作可以非同步進行。比如說,一個操作是稱重量,一個操作是數個數。我們假設雞蛋只有一層沒有重疊,而且數雞蛋的人不近視(- -#),那你倆一起幹活好了啊。你數雞蛋就數唄,稱重量的你就稱唄。因為稱完重量不需要拿一個出來煮了吃,數雞蛋的也不會數完了摸一個回家做荷包蛋,操作前操作後總數都不變,那麼就一起來好了。

切換到實際開發場景裡的話,增刪改查裡,查詢可以非同步操作,也就是不等待上一個查詢完,下一個查詢即可跟上。但是如果牽涉到其他三個操作,那麼必須同步。因為不管是INSERT還是UPDATE還是DELETE,都會有很大可能改變資料庫記錄的狀態。實際上,我上面說的這些內容在資料庫裡有個專用名詞,叫隔離級別,有興趣的話可以去查檢視,深入瞭解一下。如果在開發中能遵守上述條款的話,會減少很多莫名其妙的問題。

第二位就要輪到開發技能以外的技能了。也就是使用者好用。

一個簡單的例子。使用者去CDM上存錢。銀行A的方案是,使用者每一步操作都要輸入密碼,存入卡里之前要使用者確認三遍數目,最後存完了還要放歌給使用者聽。銀行B的方案是第一步輸入密碼,然後存入卡里之前讓使用者確認一次總數,最後使用簡短的聲音提示使用者操作完成。

也許您會笑,哪有這麼羅嗦的銀行CDM啊。呵呵,是的,這個場景是我誇張出來的,的確不會有人設計這種系統。但是話說回來,在很多專業系統的研發過程中,專業人員和開發人員往往會陷入兩個很奇妙的問題裡。專業人員對業務無比熟練,基本上是閉著眼睛都可以說出來。開發人員是對程式設計無比熟練,技巧無所不用其極。但是還有一方面,他們對於對方的領域是陌生的,於是乎,專業人員往往會亂指揮開發人員幹活,而開發人員設計的操作步驟也會搞的專業人員頭暈腦脹。系統越專業越陽春白雪,這種問題越多越普遍,因為實在是太難懂了。

我們可以試想一下,讓我們去開發宇宙飛船的管理系統,卻不給我們足夠的專業培訓,那麼結果會是什麼?要麼做出來不能用,要麼做出來勉強能用了,NASA的人會吐血而亡,因為實在是太繁瑣了,和平常的工作步驟完全不是一回事啊。也許平時工作,大家總結出來一些習慣做法和高效的做法,只需要三步就可以解決問題,開發人員不知道,根據書本上的東西來,一下子變成了三十步乃至三百步,那麼這是不是也造成了系統的效能低下呢?無論如何,操作三個步驟的耗時都比操作六個步驟的耗時少吧?

再看回上面的CDM的例子,估計銀行B的客戶錢存完,飯都吃完了,銀行A的客戶才剛存完錢吧。那麼,你程式碼寫的再好,又有什麼用?

最後一點,也是最不容易做到的,就是架構上的調整。這一點牽涉到非常多的環節,也不是一個小程式設計師能夠完成和控制的。所以,這裡僅僅做一些簡單的說明,具體內容等到後面會有具體章節來講的。首先要避免表結構設計的不合理,比如說明明可以放在一個表裡的資料,結果給丟到十七八個表裡去了,那隻好SELECT XXX LEFT JOIN XXX,這肯定不行。還有就是不要把需要經常通訊的程式放在不同的網段裡,要知道通過路由的層層盤剝以後,資料包丟包率是非常高的,儘量放在一個路由器下甚至是一臺機器上吧。

關於高效的問題,先說這麼多吧。最近比較忙,所以更新有點慢,不要著急哦。下一次會談到易用這個問題。

相關文章