中国开发网: 论坛: 程序员情感CBD: 贴子 180556
haitao
Why“J2EE Without EJB”
Why“J2EE Without EJB”
第1 章
为什么要“J2EE Without EJB”
传统的J2EE 架构方案得到的结果常常无法让人满意:过于复杂的应用程序、令人失望
的性能、难以测试、开发和维护成本高昂。
事情原本不必这样的。对于绝大多数应用程序,原本应该有更好的选择。在本书中,我们
将向读者介绍一种更加简单、而又不失强大的架构方案。这种方案有作者多年的J2EE 经验作为
支撑,并且使用了诸如控制反转(Inversion of Control,IoC)和AOP 等较新的技术。它用更加
轻量级、更加灵活的基础设施取代了EJB,并因此受益良多。本书作者和其他很多人已经在很
多真实应用中使用了这种架构方案,并且得到了比传统架构更理想的结果。
下面,我们就来简单看看相关的主题。在后面的章节中,我们还将深入讨论这些主题。
聚光灯下的EJB
和绝大多数同行一样,当我第一次看到EJB 时,它所许诺的美景令我激动不已。那时,
我深信它就是企业中间件的不二法门。可是,时至今日,我的观点早已发生了变化,而促
成这种变化的正是我本人和众多同行的亲身经验。
时移世异,自从EJB 规范成型以来,很多事情已经变了样:
EJB 规范中的一些部分已经过时。譬如说,J2SE 1.3 引入的动态代理(dynamic proxy)
就直接对EJB 采用的容器代码生成机制提出了置疑。拥有动态代理之后,真的还有必
要为每个EJB 实现好几个源文件吗?
EJB 和RMI 之间那种传统的紧密关系也开始显得有些不合时宜,这一方面是因为web
services 的迅速发展,另一方面是因为人们发现:很多时候EJB 只需要本地接口。在大
多数时候,EJB 扮演着一种重量级的对象模型,而这样的对象模型是不需要提供远程
访问能力的。
expert one-on-one J2EETM Development without EJB 中文版
第1 章为什么要“J2EE Without EJB” 2
EJB 最善于实现业务对象分布的体系结构,然而这种体系结构究竟有多大程度的普遍
性,如今看来是相当值得怀疑的。
从人们使用EJB 的情况也可以看出EJB 的优缺点。大多数开发者和架构师仅仅使用无
状态session bean(SLSB)和(如果需要异步调用的话)message-driven bean(MDB)。
EJB 容器为支持SLSB 而提供的服务相当简单,这也就是说,对于这些应用程序来说,
整个EJB 容器的高昂成本很难说是合理的。
尽管EJB 已经存在了五年之久、并且在很多J2EE 项目中得到应用,但是很显然,由于
它的复杂性,很多开发者仍然没有真正理解它。譬如说,我所面试过的很多开发者都
无法正确地说出EJB 容器如何处理异常,自然也就更不清楚容器异常处理与事务管理
之间的关系了。
为了解决EJB 存在的问题,EJB 规范也在变得日益复杂。如今,EJB 规范是如此繁复
冗长,几乎没有哪个开发者或者架构师有时间去通读它,更不用说是理解它了。就像
应用程序一样,如果技术规范变得日益复杂,并且需要不断地加入一些权宜之计,通
常就说明存在一些根本性的问题。
EJB 是如此复杂,这也就意味着使用EJB 的开发效率会相对较低。有不少工具力图解
决这个问题,从“企业”IDE 到XDoclet 和其他代码生成工具,不一而足。但这些工具
只能把复杂性暂时掩盖起来,而且采用这些工具也会增加开发成本。
严格的单元测试和测试驱动开发(Test Driven Development,TDD)正在日益变得流行
——这也是情理之中的。人们清楚地看到:大量使用EJB 的应用程序很难测试。用测
试先行(test first)的方法开发EJB 应用需要做很多工作,因此,应当从根本上尽量减
少应用代码对EJB 容器的依赖。
对于EJB 致力解决的中间件问题,面向方面的程序设计(Aspect Oriented Programming,
AOP)的飞速发展为我们指出了一条更为强大——并且很可能更为简单——的解决之
道。从某种意义上,AOP 可以看作EJB 核心概念的更为广泛的应用,然而AOP 还远
不止是EJB 潜在的替代品,它还有更多的潜力可挖。
在大多数时候,源代码级的元数据属性(就像.NET 中所使用的那样)可以非常优雅地
取代基于XML 的部署描述符——从EJB 1.1 起,我们就一直在跟这些冗长的XML 文
件周旋。EJB 3.0 似乎已经开始朝着这个方向努力了,但它背负着如此沉重的历史包袱,
需要走的路还很长。
经验还表明,EJB 往往招致更高的开发成本,并且提供的利益也并不像它最初所鼓吹
的那么丰富。在使用EJB 的过程中,开发者们遇到了很多棘手的问题。根据我们的经验,
EJB 的失败之处主要有以下几点:
EJB 并非降低复杂度所必须的,它倒是引入了很多新的复杂度。
作为一种持久化机制,entity bean 的尝试是彻底失败的。
与其他J2EE 技术(例如servlet)相比,使用EJB 的应用程序更加缺乏不同应用服务器
之间的可移植性。
尽管EJB 承诺提供高度可伸缩性,然而EJB 系统的性能常常不够理想,而且EJB 也并不
是获得可伸缩性所必须的。尽管很难得到准确的统计数据,但实际经验告诉我们:有相当
一部分项目正是因为过度使用EJB 而不得不重新进行架构设计,甚至是彻底失败。
EJB 可能让简单的事情变得困难。譬如说,Singleton 设计模式(或者与之类似的创建
型模式)就很难在EJB 环境下实现。
expert one-on-one J2EETM Development without EJB 中文版
J2EE 还剩什么3
所有这些问题都表明:在着手使用EJB 之前,有必要细致分析它究竟能提供哪些价值。
我希望本书能为你提供必要的工具,帮助你冷静而有效地完成这项分析。
在第5 章里,我们将深入讨论EJB 及其存在的问题。现在,我们先来看看J2EE 的现状
和发展趋势,以及本书能为你提供哪些帮助。
J2EE 还剩什么
也许你要问了:“没了EJB,J2EE 还剩什么呢?”
答案是:还有很多很多。J2EE 远不止是EJB 而已。然而,很多J2EE 开发者并不这样
想,要是让他们看见你案头上摆着这本书,他们恐怕要颇有微词了。不过,如果平心静气
地分析一下EJB 做了什么、J2EE 又做了什么,我们就会发现:EJB 其实仅仅是J2EE 的一
小部分而已,整个J2EE 的图景比起EJB 要大得多、也重要得多。
从本质上来说,J2EE 就是一大堆标准化的企业级服务——例如命名和目录服务
(JNDI)、为异构的事务性资源提供的标准事务管理接口(JTS 和JTA)、连接遗留系统的标
准机制(JCA)、资源池、线程管理等的集合体。J2EE 真正的威力在于这些服务,它对这些
服务的标准化对于整个行业非常有益。
另一方面,EJB 使开发者能够通过一个特定的组件模型使用这些有价值的服务,它仅仅是
使用这些服务的手段之一。即便没有EJB,我们照样能够使用JNDI、JTA、JCA、资源池……
以及其他所有的J2EE 服务。我们可以编写代码直接使用它们(这并不像乍看上去那么可怕),
也可以借助久经考验的库和框架来使用它们——后者是更好的做法,因为这些库和框架不仅可
以让我们摆脱使用J2EE 服务的复杂度,而且也不会招致EJB 所带来的复杂度。
在EJB 容器所提供的服务之中,只有很少的几样是EJB 独有的。而且即便对于这些EJB
独有的服务,也有很好的替代品。譬如说:
entity bean 是J2EE 唯一的数据访问组件,同时也是J2EE 最饱受非议的部分。有很多
非J2EE 的产品可以很好地取代entity bean,例如Hibernate 和JDO。在某些应用中,JDBC
会是更好的选择。
容器管理的事务(Container Managed Transaction,CMT):在J2EE 的版图中,EJB 是
唯一享受声明性事务管理待遇的。这是一项极有价值的服务。不过在第8 章和第9 章
中读者将会看到:借助AOP,我们同样可以获得声明性事务管理的能力。CMT 是架设
在J2EE JTA 服务之上的一个薄层。要想替换应用服务器的全局事务管理机制是非常困
难(而且非常不明智)的,但在这个机制上开发一个CMT 的替代品可就容易多了。
业务对象的线程池缓存(thread pooling):如果只提供web 界面(以及通过servlet 引
擎支持web services 客户端)的话,我们通常不需要这项服务,因为web 容器已经提供
了线程池缓存,没必要在业务对象层再提供一次。只有在要通过RMI/IIOP 为远程客户
端应用提供支持时,我们才会需要线程池缓存,此时EJB 方不失为一种良好而简单的
技术选择。
expert one-on-one J2EETM Development without EJB 中文版
第1 章为什么要“J2EE Without EJB” 4
(与前一点相关)业务对象的线程管理:EJB 容器提供了线程管理的能力,开发者可
以将EJB 看作单线程组件来实现。照我的经验,这是高估了无状态服务对象——最有
用的一种EJB——的价值。说到底,EJB 尽管可以把问题掩盖在EJB façade 之下,但
它终归无法回避所有与线程相关的复杂性。实际上,正如读者将在第12 章看到的,有
比EJB 更好的线程管理方案可供选择。
只有在提供远程调用(remoting)这件事上,EJB 是标准J2EE 架构中唯一的实现方式。
不过,正如我们将要看到的,只有在RMI/IIOP 远程调用的领域里,EJB 才算得上一种出色
的实现技术;对于web services 远程调用,有比EJB 更好的选择。
越来越多的人开始认识到:EJB 试图解决太多的问题,其中很多问题本不应该由它来解决
的。就拿O/R映射来说吧,这是一个复杂的问题,EJB则提供了一个复杂而糟糕的解决方案(entity
bean)。一些核心问题在entity bean 这里直接遭到了忽视,譬如“如何把带有继承体系的对象映
射到关系数据库”——entity bean 根本就不允许继承。要是EJB 规范的设计者们能把这些问题
留给在对象持久化领域更有经验的人,而不是自己硬着头皮解决,那该有多好。
EJB 不是J2EE 的全部。即便使用没有EJB 的J2EE,我们也无须重新发
明轮子——我们不必重新实现J2EE 已经提供的服务,只是改变使用它们的
方式而已。
站在十字路口的J2EE
在J2EE 的整个发展历程中,现在正是一个至关重要的时刻。从很多方面来说,J2EE 都
是一个伟大的成功:它成功地在从前没有标准的地方建立了标准;它大大提升了企业级软件
的开放程度;并且它得到了整个行业和开发者的广泛认可。
另一方面,我感觉J2EE 在一些方面已经开始捉襟见肘。J2EE 应用开发的成本通常很高。
J2EE 应用项目至少和从前的非J2EE 项目一样容易失败——如果不是更容易失败的话。这样
的失败率高得让人难以接受。在这样的失败率之下,软件开发几乎变成了碰运气。而在J2EE
遭遇失败的场景中,EJB 通常都扮演着重要的角色。
J2EE 在易用性方面存在着严重的问题。正如我在前面说过的,J2EE 应用往往很复杂,
而它们原本可以不必这么复杂的。对于J2EE web 应用(例如Sun Java Pet Store),情况尤为明
显:很多web 应用都遭遇了毫无必要的过度工程。
J2EE 仍然是一门相当年轻的技术,它不够完美也是情理之中的。现在,我们应该认真考
量它究竟在哪些地方使用、在哪些地方不那么适用,然后才能扬长避短。由于J2EE 涵盖了很
多东西,这也就意味着我们需要找出J2EE 中的哪些部分提供了最多的价值、哪些部分只是补
充性的基础设施。
J2EE 社群不断地向着更简单的解决方案、更少使用EJB的方向发展。我的前一本书Expert
One-on-One J2EE Design and Development(2002 年)就是朝着这个方向迈出的坚实一步,本
书则在定义和推广这些解决方案的道路上又迈出了一步。请注意,致力于推广这些解决方案
的并非我孤身一人。Rickard Oberg 和Jon Tirsen(Nanning AOP 框架的作者)等J2EE 技术社
群的先锋已经向人们揭示了基于AOP 的解决方案是多么强大而简洁。从Core J2EE Patterns
expert one-on-one J2EETM Development without EJB 中文版
前行的路5
第二版的修订中我们不难看出,就连Sun 也无法在这一波浪潮中免疫:书中已经开始提倡使
用普通Java 对象。
J2EE 和EJB 的很多问题都源自它们“以规范为驱动”的本质。历史告诉我们:最成功的
标准都是从实践中发展..出来的,而不是由哪个委员会创造出来的。OMG 和CORBA 的例子已
经让我们看到了“规范先行”的危险性:OMG 成立的目标就是要创造一个分布式对象的标准,
在超过300 家企业的参与之下,它历尽千辛万苦才制订出一个复杂的规范。和大多数委员会
制订的规范一样,开发者的易用性几乎从来没有被考虑过,于是我们得到了一个极度晦涩难
用的编程模型。自然,这样的规范也不可能得到广泛的接受。
在某种意义上,J2EE 是现有中间件技术的发展演化,因为它所解决的很多问题正是我们
在1990 后期就已经耳熟能详的——那时J2EE 尚处于构思阶段。譬如说,无状态session bean
实际上照搬了一种久经实践检验、早已证明了自己价值的组件形式:带有声明性事务管理的
服务对象。早在EJB 1.0 规范问世之前,像微软事务服务器(Microsoft Transaction Servcer,
MTS)之类的中间件就已经提供了此类组件。J2EE 也努力有所创新,然而它的创新常常是从
制订新规范开始,而不是首先在真实的应用中检验这些技术,结果这样的创新大多以失败而
告终。有状态...session bean 就是这样的一个例子:这是EJB 引入的一种新的、尚未得到实践检
验的组件形式。五年时间过去了,它仍然难堪重任:状态的复制带来了很多微妙棘手的问题,
所以大多数架构师总是尽量避免使用有状态session bean。
在我看来,J2EE 这种“以规范为驱动”的现状很快就会发生改变,这是一件好事。我并
不认为J2EE 陷入了一种“无政府”的混乱状态,但我同样无法相信开发者们会不假思索地采
用J2EE 规范中的每一项新特性、而不去考虑其他的替代品——尤其是来自开源社群的替代
品。如果希望开发者遵循J2EE 规范,那么J2EE 规范首先必须是一个实用、易用的规范。
这里有一个关键问题:技术的最终使用者——应用开发者、负责开发项目的项目经理、
以及最终使用这些应用程序的人——才是最值得关注的。然而,在应用开发第一线看来一目
了然的事实,对于那些呆在委员会里制订规范的人们来说未必总是那么一目了然的。
前行的路
本书的主旨不是要质疑EJB,而是找到一条前行的道路。在书中,我们将为读者提供
架构原则、可用的代码,以及具有立竿见影之效的实作建议。
本书所推荐的道路始终针对一组成功项目的核心价值——我把它们称为“主旋律”。检
验一个体系结构是否合理、判断一种实现选择是否合适,都要看它是否符合这一组主旋律。
主旋律
本书的中心旋律是:
简单
高产
面向对象为本
expert one-on-one J2EETM Development without EJB 中文版
第1 章为什么要“J2EE Without EJB” 6
业务需求至上
重视经验过程
重视可测试性
下面,我们就来简单讨论一下这几项核心价值。
简单
这世界上的确有...简单的问题,软件的架构和实现也应该尽量保持简单。正如我一直提
到的,J2EE 项目常常遭受过度工程,这很大程度上是因为我们先入为主地认为J2EE 应用
需要那么复杂。但情况并非总是如此,在某些领域,J2EE 架构师们常常过高地估计了需求
的复杂程度,例如:
数据库的分布。很多应用只需要使用一个数据库,这也就意味着它们不需要JTA、两
阶段提交或者XA 事务。此时,这些高级特性都会招致不必要的性能损失,并且提高
系统的复杂度。
多种客户端。应用程序需要一个web 界面,这是理所当然的,但很多J2EE 架构师却一
厢情愿地认为应用程序还必须支持远程Swing 客户端。“J2EE 应用理应能够支持多种
客户端”的想法在不少人的脑子里已经根深蒂固了。(说实话,多亏一位审稿人在审
阅我以前的书稿时指出,我才意识到:需要支持多种客户端的情况其实并不常见。这
也促使我更多地在本书中描述自己曾经参与过的真实项目的情况,而不是沉湎于一些
不切实际的想象。)
按照J2EE 的正统思想,我们根本不允许客户有如此简单的需求。我们这些J2EE 架构
师凭自己的学识就知道:客户的业务早晚会变得复杂起来,那时我们提前叫客户掏钱购买
的复杂架构就能派上用场了。
这种想法有两个问题:首先,是否让系统变得如此复杂不应该由作为架构师和开发者
的我们来决定,因为买单的人不是我们;其次,即便系统最终变得如此复杂,我们又怎么
知道一开始将它们考虑进来就能节约成本呢?说不定,等到有需求的时候再修改架构还会
更节约呢。实际上,很可能永远不会出现这样的需求;即便它们真的出现了,我们也可以
逢山开路遇水架桥。譬如说,最终要访问我们的应用程序的远程客户端可能是在Windows
平台上运行的C#或者VB .NET 程序,要为这些程序提供远程服务,基于EJB 的远程调用
体系结构就不一定是最好的选择。XP(eXtreme Programming,极限编程)的核心教义之一
就是:很多时候,越是节约成本,就越能开发出高质量的软件;不要试图预先解决所有能
想到的问题。
我们应该尽量降低架构的复杂度,只为现实的(和合理的可预见的)需
求提供支持,不要试图预先把所有的问题都考虑进去。但是,在力求简单的
同时,有必要多留意架构的设计质量,以保证未来能够对其进行重构,使其
能够应对更加复杂的需求。对架构的重构不像重构代码那么简单,但既然我
们不希望面对新的需求时被迫修改大量代码,就必须重视架构的重构。
拥有一个具有伸缩性的简单架构是至关重要的。毕竟,我们没办法裁减EJB 这样复杂
的架构来适应简单的需求。
expert one-on-one J2EETM Development without EJB 中文版
前行的路7
照我的经验,使J2EE 项目具备架构重构能力的关键在于:
遵循良好的OO 设计法则,并且始终针对接口编程、而非针对类编程。这是经典图书
Design Patterns 教给我们的基本常识,可惜人们常常忽视了这一点。
将EJB 之类的技术隐藏在普通Java 对象背后。
本书所讨论的架构方法和框架使得开发者能够更容易地实践这些原则。
生产率
软件的生产率是一个极其重要的问题,但J2EE 的正统思想常常忽视了这一点。
J2EE 在提升生产率方面的记录并不漂亮。J2EE 开发者常常要用大把的时间来与API
和复杂的部署问题周旋,而这些时间本应该用来处理业务逻辑的。和使用CORBA 的日子
比起来,J2EE 的生产率有所提高,但仍然不能令人满意。在这些被浪费的时间中,有很大
部分都是与EJB 相关的。
本书所推荐的方案有相当高的生产率,这在很大程度上是因为这些方案比较简单,省
却了很多不必要的负担。
OO
当然了,我们要OO。不过,既然Java 是一种相当好的OO 语言,难道J2EE 应用不是
天生就面向对象的吗?
它们应该是,但实际上很多J2EE 应用仅仅是“EJB 应用”或者“J2EE 应用”,而不是
OO 应用。很多常见的J2EE 实践和模式过于轻率地背弃了面向对象的原则。
OO 的设计比具体的技术(例如J2EE)要更加重要。我们应该尽量避免
让技术上的选择(例如J2EE)妨碍我们使用真正的OO 设计。
让我们来看两个例子,看看很多J2EE 是如何背弃了OO 的原则:
使用带有远程接口的EJB,以便分布业务对象。设计一个业务对象带有远程接口、具
备分布能力的应用程序,这是对OO 的严重破坏。出于性能的考虑,带有远程接口的
组件必须提供粗粒度的接口,以避免频繁的调用。另外,它们还需要以传输对象或者
值对象的形式传递输入和输出参数。的确有...一些应用必须提供分布式的业务对象,但
大多数应用并不需要这样做,它们最好是让业务对象呆在自己应该在的地方。使用分
布式对象的问题并非EJB 一家独有的,EJB 不是第一个分布式对象技术,也不会是最
后一个。这个问题之所以总是和EJB 联系在一起,是因为组件的分布恰好是EJB 处理
得比较好的几件事之一——也许好得过头了。
认为持久对象不应该包含任何行为。很长时间以来,这一直是J2EE 开发者不容置疑的
信条,包括我本人也曾经信奉过它——自从Expert One-on-One J2EE Design and
Development 出版之后,我的思想发生了一些转变,这就是其中的转变之一。实际上,
J2EE 开发者们之所以有这样的信念,更多的是因为entity bean 在技术上的严重缺陷,
而不是因为什么所谓的设计原则。仅仅暴露getter 和setter(例如,通过getter 和setter
expert one-on-one J2EETM Development without EJB 中文版
第1 章为什么要“J2EE Without EJB” 8
暴露持久化数据)的对象不是真正的对象,一个真正的对象理应把针对自己状态的行
为动作封装起来。使用entity bean 会促使开发者把这种缺陷看作一种规范的做法,因
为entity bean 中的业务逻辑很难测试,而且不可避免地与特定的持久化策略捆绑在一
起。(譬如说,如果在entity bean 中编写了大量业务逻辑,那么很显然,为了获得足
够高的性能,唯一的办法就是使用SQL 和JDBC 访问关系型数据,这是一种典型的需
要重构的做法。)在这里,更好的方案是使用JDO 或者Hibernate 之类的透明持久化技
术,因为它们可以让持久对象成为真正的对象,在其中放置更多的业务逻辑,而不会
使这些业务逻辑对持久化细节有过多的依赖。
一旦你发现自己正在编写一个“不是真正对象” ——也就是说,只有
一些用于暴露数据的方法——的对象,你就应该想想自己为什么要这样做、
是否有更好的选择。
遵循OO 原则自有其价值。运用合理的话,OO 可以带来非常高的代码复用率和非常优
雅的设计。
在本书中,我们会一直牢记OO 的价值。我们会努力向读者展示:如何让一个J2EE 应
用成为一个真正的面向对象应用。
需求至上
应用架构应该由业务需求来驱动,而不是以技术为目标,这本来应该是显而易见的事。可
惜,在J2EE 这里,情况似乎并非总是如此。J2EE 开发者们常常凭空想出一些需求,例如:
需要同时支持多个数据库,此前我们已经讨论过这个问题了;
要求能够毫无成本地移植到别的应用服务器;
要求能够轻松地移植到别的数据库;
支持多种客户端。
这些都是潜在的...业务需求,但它们是不是真实的...需求?这就需要具体情况具体分析。
使用其他技术(例如.NET)的开发者通常并不需要操心这些空想的需求,这也就是说:J2EE
开发者们仅仅因为他们的技术选择——而不是客户的需求——就耗费了更多的精力。
J2EE 让很多在其他技术中不可能做到的事情成为了可能,这是J2EE 的一大优势,但
同时也是一个潜在的危险,因为它常常会让我们忘记:尽管我们可以做到所有这些事,但
做每件事都是需要成本的。如果没有一个足够好的理由,我们不应该让客户承担所有这些
成本。
经验过程
我的妻子是一位医生。近年来,一种名叫循证医学(Evidence-Based Medicine,EBM)
的模式对医生们的工作产生了很大的影响。按照这种模式,治疗决策需要在很大程度上参
考医学研究的证据。而在此之前,医生们通常都是根据患者的状况和不同的选择在以前的
expert one-on-one J2EETM Development without EJB 中文版
前行的路9
结果来决定哪种治疗方案的。
尽管EBM 对医学实践的影响未必全都是积极的,但类似这样的经验方法无疑值得软件
开发者们学习。
我们的IT 行业很大程度上是由时尚和激情来驱动的。我几乎每天都在听到不同的人们
重复着那些他们无法验证其正确性的观点(例如“EJB 应用天生就比不使用EJB 的应用更
具可伸缩性”),或者重复着一些根本没有真实证据能够提供支持的宗教信仰(例如“.NET
不是一个可靠的企业级平台”)。而这也就意味着人们常常是凭着一种固执在架构企业级系
统。总之,他们知道什么是最佳方案——然而,并没有足够的证据能够证明这一点。
对于这种情况,或许最好的办法就是“问问电脑”(这个说法来自另一位技术作家Randy
Stafford)。在耗费太多的钱和时间在我们所推荐的体系结构上面之前,我们应该始终“问问
电脑”对这个体系结构究竟怎么想。
在迭代式方法中,这种做法被总结为可执行架构(来自RUP)、垂直切片(vertical slice)
或者穿刺方案(来自XP)。不管叫什么名字,总之是要尽快搭建一个完整的、可执行的示例
应用,以尽量减少采用采用此架构的风险。在RUP 这里,这一过程的目标是找出风险性最大
的架构问题,以最大程度地降低风险;在XP 这里,这个过程则是由核心用户故事(user story)
来驱动的。不管怎样,这一过程必须与实际需求紧密相关。如果采用敏捷开发流程,那么我
们会很自然地创建一个垂直切片,所以就没有必要单独强调这一过程了。当垂直切片建立起
来之后,我们就可以在它的基础上验证架构选择是否合理。其中重要的衡量标准包括:
性能。这个架构能满足非功能性的需求吗?这很有可能成为J2EE 应用的症结。有很多
项目存在棘手的性能问题,如果没有早期的垂直切片,我们常常要到最后一分钟才能
发现这些问题。
采用的难度。开发者在这个架构上耗费的时间和成本是否与实现的需求成比例?用它
开发出的产品的复杂度是否与需求的复杂度成比例?采用这个架构的开发过程是可重
复的吗?或者需要某种魔法才能获得成功?
可维护性。在这个垂直切片的基础上增加新的功能困难吗?一个新手花多少时间可以
理解这个应用的架构和实现、并投入有效的开发?
非常遗憾,很多项目并没有进行这样的风险缓解。更糟糕的是,很多广受推荐的J2EE
架构实际上是由技术规范或者厂商来推动的,它们并没有在真实的生产环境中证明自己,
所以它们不值得信任。
不仅不要相信这些技术架构,也不要相信我们或者别的任何人。请为你
的应用搭建一个垂直切片,根据你的关键需求去考察它。“问问电脑”哪个
架构最适合你的需求。
你的需求也许是独一无二的,但本书中介绍的架构已经在很多项目中获
得了成功,并且已经证明自己能够制造出优秀的系统。所以,不妨把它作为
你的第一个考察对象。
expert one-on-one J2EETM Development without EJB 中文版
第1 章为什么要“J2EE Without EJB” 10
可测试性
在最近几年中,测试先行的开发(test first development)日益流行,而且通常都能收
获令人满意的结果。然而,是否能够编写有效的单元测试不仅取决于开发者为此投入的时
间和精力,还取决于应用程序的高层架构。在本书中,我会反复强调:应用架构理当让开
发者能够轻易地编写有效的单元测试。而这正是EJB 最大的缺陷之一:由于对EJB 容器
依赖过重,在EJB 中编写的业务逻辑非常难测试。
难以测试的代码通常也难以修改、难以在不同环境下复用、难以重构。可测试性是
敏捷(agile)项目的基本要素。本书所介绍的J2EE 架构方案很适合敏捷项目使用,我
们也会常常讨论关于敏捷的话题。
在第14 章,我们还会详细讨论关于可测试性的问题。
轻量级框架和容器
每个应用程序都需要一些基础设施,拒绝使用EJB 并不意味着拒绝EJB 所采用的基础
设施解决方案。我们当然不想回到1990 年代后期、EJB 出现之前的状况:为了开发一个复
杂的Java 企业级应用,人们必须亲手实现资源池缓存、线程管理、服务定位、数据访问层
等等基础设施。
本书将向读者展示:如何利用现有的框架提供这些基础设施服务。我们相信,对于成
功的J2EE 项目,这些替代EJB 的基础设施是不可或缺的。因此,介绍轻量级容器的功能和
用法就成为了本书的核心内容之一。
回顾2003 年,这样的“轻量级”容器如同雨后春笋般层出不穷,它们提供了管理业务
对象和企业级服务的能力,而不必求助于沉重的EJB 基础设施。这也反映出一个事实:越
来越多的人正在朝着更简单、更轻量的J2EE 解决方案努力。很多这样的框架——例如
Spring、PicoContainer 和Nanning——都来自繁荣的Java 开源社群。在第5 章,我会更加详
细地谈论这个话题。
除了开源产品之外,也有很多商业产品——例如Mind Electric 公司的GLUE web services
产品——在其他领域提供了比EJB 更为轻量级的解决方案,例如远程调用。
Spring框架
如果没有可用的、在真实产品中经过考验的代码来展示我们介绍的架构方案,我们就
不可能写出这本书。
Spring框架(http://www.springframework.org)是一个流行的开源产品,它的作用
是为J2EE应用常见的问题提供简单、有效的解决方案。2003 年,Expert One-on-One J2EE
Design and Development一书不同寻常地以一个完整而有发展前途的应用框架作为示例,随
后,从该书的示例代码中发展出了Spring项目。Spring有一个兴旺蓬勃的开发者和用户社群,
并日益变得强大而可靠,质量远远超过任何我独自开发的东西。(本书的合作者Juergen
Hoeller是Spring项目的领导者之一,他为项目社群的建设作出了无法估量的贡献。)在Spring
项目中,基础框架的设计甚至早于Expert One-on-One J2EE Design and Development的写作,
它们来自我过去几个商业项目的经验。
在构思之初,我们并没有打算让Spring 成为EJB 的替代品,但它确实为普通Java 对象
提供了强大、可测试的功能实现(例如声明性事务管理),让很多开发者能够在很多项目中
避免使用EJB。
expert one-on-one J2EETM Development without EJB 中文版
我们还应该使用EJB 吗11
Spring 并不是唯一一个这样的项目。在本书中所介绍的设计,鲜有专属于Spring 的。
譬如说,我们建议使用AOP 来解决一些常见的企业级问题,除了Spring 之外还有好几个别
的开源AOP 框架可供选择。
大量使用具有产品级质量的开源代码,这是本书最大的独特之处。绝大多数J2EE 书籍
都会提供一些代码示例,但很可惜,这些代码的价值非常有限,因为它们所展示的都是出
于教学目的而大大简化了的问题。如果读者试图在真实应用中使用这些代码,他很快就会
遇到麻烦。所以,使用一个具体的框架——即便并非所有读者都将使用这个框架——来阐
释作者的观点,这种做法只适合用于介绍简单得失去真实意义的解决方案,因为惟其如此,
才能把整个解决方案放进书中。
Spring 为体系结构重构提供了绝佳的支持。譬如说,你可以在应用架构中加入带有本
地接口的EJB,也可以给业务对象添加AOP 支持,而不必修改任何一行调用代码——当然,
你必须遵循基本的编程原则:针对接口编程,而不是针对类编程。
我们还应该使用EJB 吗
EJB 仍然有它的位置。本书介绍了一种比EJB 更简单、生产率更高的架构方案,它适
用于很多J2EE 应用。但是,我们不会声称这种方案是J2EE 的万灵药。
在Expert One-on-One J2EE Design and Development 一书中,我不止一次
提到过“帕累托法则”。这个法则也常常被称为“80/20(或者90/10)法则”,
也就是说:花比较少(10%—20%)的力气就可以解决大部分(80%—90%)
的问题,而要解决剩下的少部分问题则需要多得多的努力。在软件架构这里,
这个法则告诉我们:架构的价值在于为常见的问题找到好的解决方案,而不
是一心想要解决更复杂也更罕见的问题。
EJB 的问题就在于它违背了“帕累托法则”:为了满足少数情况下的特殊要求,它给大
多数使用者强加了不必要的复杂性。比如说,也许只有10%的应用需要分布式的业务对象,
然而EJB 的基础结构却与对象分布紧密相关。EJB 2.1 以及此前的entity bean 被设计为与数
据存储机制无关,但绝大多数J2EE 应用都使用关系数据库,因此它们能够从entity bean 的
存储机制无关性中得到的利益微乎其微。(“各种数据存储介质之间的可移植性”在理论上
很有价值,但在实际应用中就未必如此了。而且,尽管声称提供了这种可移植性,但在对
象数据库这里,entity bean 的表现也无法令人满意。访问对象数据库的最佳途径仍然是使用
它们自己提供的API,或者JDO 之类的解决方案。)
对于那些真正需要对象分布的应用,EJB 仍然是上佳之选——尤其是当它们完全用Java
实现、或者用IIOP 作为通信协议时。不过,这种应用比人们通常想象的要罕见得多。
对于需要大量使用异步消息的应用,EJB也是不错的解决方案,因为用message driven
bean处理异步消息非常有效——而且相当简单。1
1 译者注:时至今日,EJB在处理异步消息方面的优势也受到了来自轻量级阵营的挑战。Apache组织属下的Jakarta Commons
Messenger是一个轻量级的、基于POJO的JMS消息框架,使用这个框架可以——如MDB那般——轻松地发送和消费JMS消息,而它
所需的运行环境仅仅是J2EE web容器。目前Commons Messenger项目仍处于沙箱(sandbox)阶段,但它(或者类似的其他产品)进
入真实应用仅仅是个时间问题。读者可以在Hhttp://jakarta.apache.org/commons/sandbox/messenger/H找到
这个项目的相关信息。
expert one-on-one J2EETM Development without EJB 中文版
第1 章为什么要“J2EE Without EJB” 12
EJB 能够真正为项目提升价值的典型例子或许就是金融中间件应用。金融应用中的处
理过程常常需要耗费大量的时间和计算能力,比起业务处理本身的开销,远程调用的开销
常常倒是可以忽略不计的了。而且,金融中间件也通常是面向消息的,很适合使用MDB。
我相信,这样的应用就是那真正复杂的10%。
当然,也许还有强大的政治因素....(而非技术因素)促使人们使用EJB,这已经不在本书
的讨论范围之内了。照我的经验,赢得政治斗争通常比赢得技术斗争要困难得多。在这方
面,你需要的老师是是马基雅维利2,而不是我。
我相信EJB 是一种正在逐渐衰退的技术,不出三年它就会进入弥留阶段,尽管EJB 3.0
竭力改进也于事无补。但本书关注的是帮助你马上着手搭建企业级应用,所以如果EJB
能够很好地应对你眼下的需求,我就会建议你使用EJB——但只是当下暂且使用而已。
小结
在本章中,我们大致浏览了一下本书后面章节将要详细讨论的各个主题。
从J2EE 诞生之初,EJB 就一直被视为J2EE 平台的核心,但我们认为这是一个误解。
EJB 有它的位置,但对于大多数应用来说,不使用EJB 会是更好的选择。J2EE 远不止是EJB,
EJB 只是使用J2EE 服务的途径之一。因此,拒绝EJB 决不意味着放弃J2EE。
我们相信轻量级容器(例如Spring 框架)能够更好地组织应用代码、更好地使用J2EE
提供的服务。在本书中,我们将详细介绍这种架构方案。
我们相信业务需求和基本的OO 常识——而非具体的实现技术——应该是项目和架构
的驱动力。
在下一章中,我们将更详细地讨论本章所指出的核心价值,随后再进入关于应用架构
和具体技术的讨论。
2 译者注:马基雅维利(Niccolo Machiavelli,1469~1527)是文艺复兴时期的意大利政治思想家、历史学家和军事理论家。
他的政治科学名著《君主论》以不受感情和伦理约束的冷静客观态度指出了君主的治国之道,因此常常被认为是“为达
目的不择手段”的政治诡道——也即所谓“马基雅维利主义”——的代表。
expert one-on-one J2EETM Development without EJB 中文版
我的blog:http://szhaitao.blog.hexun.com & http://www.hoolee.com/user/haitao
--以上均为泛泛之谈--
不尽牛人滚滚来,无边硬伤纷纷现 人在江湖(出来的),哪能不挨刀(总归是要的)
网络对话,歧义纷生;你以为明白了对方的话,其实呢?

您所在的IP暂时不能使用低版本的QQ,请到:http://im.qq.com/下载安装最新版的QQ,感谢您对QQ的支持和使用

相关信息:


欢迎光临本社区,您还没有登录,不能发贴子。请在 这里登录