看上去很美 --OOafarian對play!框架的幾點(diǎn)看法
Posted on 2008-12-31 22:08 mingj 閱讀(5350) 評論(14) 編輯 收藏 所屬分類: framework 框架
play! framework 是一個面向小型網(wǎng)站開發(fā)的 rails-like 的 Java 框架,不僅在目錄結(jié)構(gòu)上,在系統(tǒng) skeleton 生成上,也把 rails 學(xué)了個七七八八。最近和同事也在做一個 rails style 的 Java Web 應(yīng)用開發(fā)框架,參考了 rails 的很多 feature,但更多的是按照自己的開發(fā)理念和哲學(xué)思想“拿來” rails 里面有借鑒意義的思想。面對號稱 rails-like 的 play! framework,這幾天身在海灘上,于是花了一些時間好好研究了 play! 的源代碼一番。“看上去很美”,是讀完代碼后腦海中第一下涌現(xiàn)出來的想法,我承認(rèn)我是OOafarian。
play! framework 5個“酷”的東西,看上去很美,但這些大都是建立在對 Java class 文件 hack 的基礎(chǔ)上的。以 JPAModel 為例,任何它的子類 model 都是可以使用 rails style 的語法:User.findAll()。表面上看和 activerecord 的語法一樣的,但實(shí)際上 play! 是通過在 JPAModel 里面定義這些靜態(tài)方法,默認(rèn)實(shí)現(xiàn)是拋出 RuntimeException,然后在 classloader 載入子類 class 文件的時候,通過增強(qiáng)每個 model class,使之具有這樣類型安全的類方法。且不說這樣實(shí)現(xiàn)是多么暴力和對開發(fā)人員不可理解,這與 rails 的實(shí)現(xiàn)是完全不一樣的。ruby 因?yàn)槭翘峁┝?class 的繼承體系,使得類方法也成為可以 override 的 class 類的實(shí)例方法,但是 Java 不提供 class 的繼承和覆蓋:這是 Java 的優(yōu)勢也是劣勢。有人說這是語言的天性,但其實(shí)語言也是人們對世界進(jìn)行抽象建模的一種折射,也反映的是人們的世界觀和哲學(xué)思想。如果是我,如果依舊選擇 Java 來做,我更傾向于保留 Java 的靜態(tài)方法的優(yōu)勢和優(yōu)雅,通過模式或者設(shè)計方法使之具有類似于動態(tài)語言的靈活性。這也是我和幾位同事一致的看法。
那么,從一位受 OO 和 pattern 熏陶很深的 Java 程序員看來,看上去很美的 play! framework 華麗的袍子下有多少虱子呢?待我細(xì)細(xì)數(shù)來:
1. controller 里面充斥的 static void 方法,不 OO,不 testable,完全是過程化的代碼。作者也是說了:
The Java code from the Controller class isn't really Object Oriented : it's mainly some procedural code.
當(dāng)然,過程化還是面向?qū)ο螅@個爭論不是今天才有,不同的人在不同的上下文情景下都會選擇最適合自己的開發(fā)方式。但是,作為受 OO 熏陶很深的我,這是不可接受的。
2. view 的 render 實(shí)現(xiàn)是繼承自 RuntimeException。記得很早之前,還有人爭論 Exception 作為程序出口和條件判斷分支的使用,但自《Effective Java》一書以及其他編碼風(fēng)格介紹的書籍出來之后,這樣的爭論早已不知何處。Exception 和 Error 會有自己適合的場所,也有它們自己的正確含義,被濫用可不是它們的錯。我想,即使是 JVM 被優(yōu)化得性能完全不用考慮了,這樣的處理思路也是不可以被團(tuán)隊成員理解、認(rèn)同和接受的吧?
3. 暗地里修改代碼,使用自己的classloader來大量增強(qiáng)或者修改class,甚至反編譯 class。這樣就導(dǎo)致很多增強(qiáng)的東西都是框架來強(qiáng)制性加入的,開發(fā)人員沒有辦法進(jìn)行測試,也沒有辦法修改默認(rèn)的實(shí)現(xiàn)。也許有人會覺得這樣也挺好,覺得這樣也夠用,那也 OK。但是如果這些都建立在拋棄 Java 強(qiáng)大的靜態(tài)類型安全,強(qiáng)大的 IDE 支持,強(qiáng)大的社區(qū)支持的基礎(chǔ)之上,我是不能接受。
當(dāng)然,play! framework 也是體現(xiàn)了一些很新穎的創(chuàng)新。比如使用 Http Server 來取代 J2EE Server,甚至是 Application Server。又比如通過動態(tài)編譯代碼來實(shí)現(xiàn) hot swap。還比如使用 java.lang.instruments API 來定位 Exception 的位置。這些創(chuàng)新在一定程度上減輕了 Java web 應(yīng)用開發(fā)過程中的“重”,給開發(fā)人員帶來“輕”的感覺。但是,如果這些需要付出 Java 社區(qū)積累到幾天的成果,完全重頭再來,我想我會寧愿選擇 ruby on rails。
當(dāng)我們選擇了 Java,我們看重的是強(qiáng)大的靜態(tài)安全,看重的是強(qiáng)大的 IDE 支持和社區(qū)支持。雖然這些會給開發(fā)過程帶來一定的“重”,但是米蘭昆德拉說過,
可是,沉重便真的悲慘,而輕松便真的輝煌嗎?
最沉重的負(fù)擔(dān)壓得我們崩塌了,沉沒了,將我們釘在地上。可是在每一個時代的愛情詩篇里,女人總渴望壓在男人的身軀之下。也許最沉重的負(fù)擔(dān)同時也是一種生活最為充實(shí)的象征,負(fù)擔(dān)越沉,我們的生活也就越貼近大地,越趨近真切和實(shí)在。
相反,完全沒有負(fù)擔(dān),人變得比大氣還輕,會高高地飛起,離別大地亦即離別真實(shí)的生活。他將變得似真非真,運(yùn)動自由而毫無意義。
rails 之所以能輕,是因?yàn)樗?runit,有 rspec 來作為它的安全網(wǎng),使之不會偏離方向。而 Java 也可以變得很輕,但這個輕卻絕不是以拋棄 Java 的優(yōu)勢作為代價的。這也是我和幾位同事在做 rails style 的 Java web 應(yīng)用開發(fā)框架的過程中一直堅持的,希望到時能展現(xiàn)給大家一個高效率而有符合編程哲學(xué)的好框架。