透明思考


Transparent Thoughts


十年前的Java企业应用开发世界

在2003年用Java编程比现在要更痛苦一些。比如说,J2SE 1.5还没有发布,也就是说一些现在大家认为理所当然的特性,比如泛型容器、staticimport、Annotation,都是不存在的;Integer和int是不能自动转换的;枚举只是整数换了个写法没有任何类型安全机制……我还在2003年第6期《程序员》杂志发表了一篇文章,介绍J2SE1.5的新特性。而在项目里,不管是浙江省财政厅的项目,还是杭州市工商局的项目,我们用的都还是J2SE 1.3。

更大的挑战——或者说,乐趣——是框架乃至编程思想的不统一。几年以后,当Java企业应用开发彻底成熟,所有人都知道SSH(Spring+Struts+Hibernate,后来Struts终于被SpringMVC取代),连培训学校也拿这几样东西来作为就业敲门砖。可是在2003年,MartinFowler那篇“Dependency Injection”还没发表,关于“什么是好的容器框架”还远远没有定论。且不提ApacheAvalon这样的容器——照现在的眼光来看,Avalon根本算不上一个合格的容器,但你必须意识到它是Java 1.3之前的作品,这样才能理解为什么它会存在并进入这个讨论——Spring之外还有PaulHammant和JonTirsen的PicoContainer在与之竞争成为事实标准。而当时还在0.x版本的Spring(当年10月Spring才发布1.0版本),其功能也并不比单纯专注对象容器的Pico丰富。

Web框架的情况更加混乱。Struts被使用最多同时也被诟病最多;RickardOberg刚做出了WebWork,大家还没充分意识到它的好处。更麻烦的是,其时整个J2EE社区并未——像今天这样——达成一个共识说“MVC是好的”,于是其他种种构造Web应用的方式以及相应的框架层出不穷:有人相信Web开发也应该走“组件化”道路,于是有了面向组件的Web框架(例如Tapestry);有人认为Portal才是未来Web的发展方向,于是有了形形色色的Portlet容器(例如JetSpeed);甚至还有人尝试用“XML文档+XSLT转换”的方式来实现Web应用。当年最火的全功能Web框架还是Turbine ,到如今它给我们留下的也就只剩Velocity了——恰恰Velocity所代表的“viewtemplateengine”在当时还没有被广泛接受,更多人仍然习惯于在JSP里直接写上一大堆Java代码。当时有人笑称,每周都会有一个新的Web框架在TSS上发布——其时最具影响力的J2EE网上社区TheServerSide.com被简称“TSS”,由此可见那时的企业软件世界是有多爱三字母缩写词。InfoQ的创始人FloydMarinescu当时还在TSS做内容主管呢。

持久化框架的情况也好不到哪儿去。Hibernate倒是已经发布了2.0版本,不论功能还是性能都已接近成熟;可是Hibernate与ADO之间的争论正在如火如荼地展开着,究竟应该选一个刚开始热门的开源框架还是选一个“标准”也颇让人头疼;同时也别忘了另一边,很多程序员更愿意用简单的SQL来操作数据库,而不是在对象与关系数据的映射中绞尽脑汁;再加上2003年普遍的“XML热病”,真的有很多人相信可以把企业应用中的数据持久化成XML从而抛弃关系型数据库——你也可以说这是NoSQL的早期萌芽,总之当时这些思想只是让事情变得更复杂而已。

当你谈论2003年的J2EE世界时,千万别忘了这里还有EJB。实际上,EJB 2才是当时J2EE的正统——再提醒一下读者们,Spring还在0.x的阶段,RodJohnson那本旗帜般的“withoutEJB”还没写出来呢。曾经有IBM的咨询师来跟我们讨论应用架构,听说我们完全没用EJB时都连连摇头。如果不是石一楹坚持不用EJB,也许我会走上一条相当不同的技术路线。后来我一直对EJB不怎么上手(虽然还翻译过一本与EJB关系不少的书),倒是轻量级J2EE架构接受起来驾轻就熟,不得不说是种运气。

仿佛是嫌事情还不够复杂,那时很多企业对开源软件抱持一种不信任的态度,所有框架都愿意自己开发,似乎只要“not inventedhere”的东西就不可靠——这样的企业现在也有,毕竟数量少多了。这里固然有心态的原因,同时技术上的原因也不应该忽视。J2SE 1.3引入了动态代理(dynamic proxy)技术,以RickardOberg为代表的一帮天才开发者们立即敏锐地意识到:这是一件框架开发的利器——在与JBossGroup决裂之前,Oberg是JBoss的首席架构师,可以说是他一手创造了JBoss;同时他也是AOP和Interception的狂热爱好者,因为他早早地看到了这些元编程技巧在框架开发中的重要意义,而动态代理则正是让Java不依赖于外部的、非标准的代码生成技术(例如AspectJ、CGLib等)实现动态元编程的基础设施。其结果是,从Java1.3开始,很多新的框架显著地变得更优雅、更少侵入性——Java1.3之前的“老”框架,例如Avalon、Turbine,与这些后来者比起来就显得相形见绌。然而这种优雅同时也意味着更难理解其内部运作机制,有时对着一个漂亮的框架就仿佛在看一场精彩的魔术,愉悦之余也难免有些心里犯嘀咕。正处在这场转变之中的企业和团队,希望自己动手开发框架从而获得更多安全感,也是情有可原。

不过这种复杂、混乱与缺乏信心对于程序员来说倒未尝不是好事。短短的几个月时间里,我的项目主管带着我把J2EE Web应用的全套框架——对象容器、持久化、WebMVC——都实现了一遍。这个过程不仅让我的技术水平突飞猛涨,而且还让我交了不少朋友:因为我比较喜欢显摆,做出点东西就在网上谈论,一来二去就结识了一些与我有着同样困惑的同行。在这些“以技术会友”的新朋友之中,最有趣的是一个叫DreamHead的家伙。这人每每写邮件长篇大论洋洋千言,博客也是一副正襟危坐的范儿。我们讨论的主要就是这些基础框架与架构,没想到类似的话题我竟然与他一直讨论了十年。