(零雨其蒙原创,转载请注明)
是惊喜抑或是困顿,在过去的
20
年间
IT
界发生了很多变革,生产力和理论都取得了突飞猛进的发展。这比更早时候的发展更加迅速,
Oreilly
公司画出了一幅从
1954
年
Fortran
到
2003
年
Python2.3.1
出现的程序语言发展的清明上河图。
1990
年
10
月,
Tim Berners-Lee
发明了
WEB
,之后世界变得异常精彩,
1995
年是伟大的一年,第一个用
Perl
语言编写的
CGI
诞生了,
Netscape
发布了
JavaScript
,
Rasmus Lerdorf
发明了
PHP
,
Sun
发明了
Java
,
Matz
发布了
Ruby
。从那一年开始,你可能会发现两件事,一件是
Web
开发会成为未来的主流,一件是软件工业开始在创新和完善中趋同。程序语言是相似的,语法有
C
(
1971
年),
Pascal
(
1970
年),
Basic
(
1964
年)几大风格流派,而程序开发的思想却基本上是
Pascal
之父
Nicklaus Wirth
所言“算法
+
数据结构
=
程序”。
1965
年出现了
OO
理论,
1967
年
Simula
实现了
OO
理论,
1980
年带着
Class
(类)的
C
语言出现,
1983
年,
Bjarne
创造了
C++
。而真正让
OO
开始“飞入寻常百姓家”的却是
Java
,而
2000
年
Delphi
之父
Anders Hejlsberg
产下了第二个孩子——
C#
,
C#
和
.Net Framework
全面模仿
Java
——其实这么说也有失公允,虚拟机的思想来源于
Pascal
,其他优秀的风格来自
C\C++
,而
C#
则借鉴了
C++
、
Java
、
VB
、
Delphi
等语言,其实可以说是借鉴了程序语言发展
50
年的广泛经验。另外对于方法论的研究,软件工程学的研究,也都取得了不小的进步。从
1970
年
Winston Royce
博士引领的瀑布模型到后来改进的
V
模型,到
UP
到
AM
,我看到的是业界的经验越来越丰富,而对于方法的迷信在不断的降低,而务实的方法越来越受到欢迎,从敏捷宣言的“工作的软件胜过面面俱到的文档(
Working software over comprehensive documentation
)”即可看出。在
Java
的世界里,人们乐于讨论各种各样的思想,制定各种各样的标准,而在
Microsoft
的世界里,则都是总结行业数十年经验的产品。
说这些只是为了引出本文的两个基本观点,一是相信业界几十年经验的总结,方法论、模式与反模式、框架、蓝图、产品;二是遵循“循证”原则,不相信任何官样文字,不崇拜任何泥塑偶像,凡事以实际出发,而不是墨守成规的遵循所谓规范。在相信与不相信中取舍是困难的,本文所选的主题是在
.Net
和
J2EE
两大平台中选择其一作为广州港信息化架构平台。正是基于业界数十年发展的经验的总结和“循证”思想,
.Net
和
J2EE
越来越趋同。这意味着只看厂商的宣传和书本的讲解很难做出抉择,而且往往是不可信的。
想要正确理解
J2EE
和
.Net
就必须深入到其背后,了解其产生的背景,盲目崇拜规范或使用产品(
J2EE
归根到底还是使用其产品)就会造成严重的后果,
Rod Johnson
在《
Expert one-on-one J2EE Design and Development
》中指出由于人们过于迷信
Sun
制定的
J2EE
规范,而没有考虑到实际情况(盲目使用分布式计算,不合时宜的使用
EJB
,特别是实体
Bean
)。
促成如今
.Net
和
J2EE
当然还包括
RoR
和
LAMP
群雄割据的原因自然是业界对于软件解决实际问题的呼唤,而这些技术渗透的思想包含业界数十年的经验,
OO
技术(光是信息隐藏就争论了十几年)、中间件技术、
Web
技术、
n
层结构,而如今这些争论越来越趋向于统一,下面分而述之:
n
OO
技术
面向对象绝对是编程思想的一次革新(相对于面向过程的结构化思想),我没有赶上
C/C++
横行的年代(虽然在某些场景下它们依然横行),因此对某些思想上转变时的痛苦感觉并不深刻,尽管核心思想(跟我见过的一些中国的教科书上说的不一样)的转变颇费了一段时间。《
Code Complete
》说学习面向对对象首先要理解
ADT
,而在《编程高手箴言》中我看到了对于重载方法在编译码层次上的实现,并且明显感到作者对面向对象的理解体现在技术本身(这种技术实现的原理),对于
C
程序员甚至是
C++
程序员而言,往往直接操作数据结构和内存等(比如指针和链表),所以理解
ADT
算是思想上的革命了。正如前面所说,
C++
程序员总是能看到
VMT
这样的技术原理,我认为在进行
OO
编程时应该暂时忘掉这些,因为它将阻碍你理解
OO
设计思想。
我认为
OO
的核心是对于对象的理解,而并非重载、继承之类的具体技术,站在对象的角度思考问题是思维方式的变革,是非常苦难的。然而不幸的是,我见过的多数使用
OO
技术的人并未真正理解对象,而只是机械的使用类(
Class
),重载等技术,这些
Class
其实并非真正的类,只不过是堆积大量没有任何实际含义的容器(比如将验证用户帐号信息和保存订单放在一个类里)。没有实际含义的类(有实际含义的类就像
Customer
类中只包含消费者自身的行为,而不应该出现保存订单之类的行为,那应该交给
Order
类)和结构化的程序没有更多本质上的区别,同样是难以维护的(这里主要指程序不是自明含义的)。
业界的实践已经证明了
OO
是设计复杂系统可行的好的方法,而真正用好
OO
并非易事,正确使用设计模式是有效的方式。然而知道设计模式(能背诵
Gof
的
23
种
Design Pattern
)和理解设计模式(这本身已经不容易,因为不了解
OO
的基本技术如接口,继承,多态等并且没编写过相关程序,阅读并理解设计模式和其范例是不可能的)与灵活运用设计模式不是一个层次上的。尽管设计模式是从实践中总结出来的解决特定问题的方法,而且优秀的程序员都是这样进行设计编程的,然而我们身边到处都是不优秀的程序员。
理解
OO
设计思想比理解
J2EE
架构重要的多,正如
Rod Johnson
所说:我们使用
J2EE
实现
OO
设计,而不是让我们的
J2EE
来支配对象设计。使用了
J2EE
平台(实际上是使用了
WebSphere
,
Jboss
这样的产品)并不意味着能解决复杂的企业级问题,关键在于你怎么做。
n
中间件技术
中间件技术起源于
1980
年左右,其作用是屏蔽
OS
的复杂度,为应用程序提供企业级服务,比如事务管理、安全管理、并发控制、分布式管理等,按照
IDC
(
http://www.idc.com
)的分类方法,中间件可分为六类,第一类是终端仿真
/
屏幕转换中间件,第二类是数据库访问中间件,第三类是远程过程调用中间件,第四类是消息中间件,第五类是交易中间件,第六类是对象中间件。
最初的中间件是基于远程过程调用(
RPC
)的,通过远程方法可以透明调用实现分布式的通信计算,虽然这一代的中间件没有
Web
的支持,但是其
RPC
的思想得到了广泛的应用,在后来的中间件中也得到了继承;九十年代初出现了消息中间件,通过消息传递和消息队列的方式实现基于多协议的可靠消息传递机制,主要的产品有
IBM
的
MQSeries
,
BEA
的
MessageQ
;而交易中间件则是致力于管理大型的事务处理的,当前成熟的
BEA
的
Tuxedo
就是其中的代表,交易中间件通过
XA
规范接口与资源管理器进行交互,并且通过二阶段提交协议进行事务管理;正如前面提到的面向对象的中间件是
OO
技术的应用,九十年代初
OMG
提出了以
CCM
为基础的
CORBA
规范,还有就是
Sun
提出的以
EJB
为基础的
J2EE
规范和
Microsoft
提出的
.Net
平台。
n
Web
技术
1990
年
10
月,
Tim BL
在
NeXT
平台上开发出了世界上第一个图形界面的超文本浏览编辑器,名字就叫“
World Wide Web
”,同时
Tim BL
依照
SGML
标准,开发出了
HTML
(
Hypertext Mark-up Language
,超文本标记语言)!
1991
年的
8
月
6
日
(美国时间),
Tim Berners-Lee
在当时的
alt.hypertext
讨论组上正式向全世界介绍了他的
WWW
计划,从那一天开始,
Web
开始走向世界化。
为了满足人民群众日益增长的物质文化需求,
Web
技术不断推陈出新,回顾这段历史是很有意思的,同时也是有意义的,它会让你知道每种技术为何而生,以便更有效的利用它。
1995
年诞生的打响了动态脚本语言的第一炮,随后
1996
年
Microsoft
推出了
ASP
,
1997
年
Sun
推出了
Servlet
,
1998
年又推出了
JSP
,
2003
年
Microsoft
将
ASP
升级为
ASP.Net
。
2005
年出现了
Ajax
。越来越多的基于
Web
的应用系统被创建,从简简单单的以展示内容为主的网站变成了需要处理复杂业务逻辑的大型系统,
Sun
和
Microsoft
采用了几乎相同的手段,来满足这些需求。
J2EE
就是在这样一个大背景下诞生了。
J2EE
主要组成部分有
J2EE
平台,
J2EE
规范(
Platform Specification
),参考实现
(Reference Implementation)
,兼容性测试套件(
Compatibility Test Suite
)和
J2EE
蓝图(
J2EE BluePrints
)。
对于
J2EE
规范,有一个中英文的细节是,
J2EE
规范的“规范”用的词不是
criterion
而是
specification
,我们知道
specification
是指软件过程设计阶段的规格说明书,而
J2EE Specification
就是一个使用
Java2
语言,构建企业级应用系统的设计规格说明书,它包括了整个企业系统的架构,以及各种中间件如何设计,细化到了每个
API
是如何设计的。如果把
J2EE
这个中间件看成一个应用系统,那么二十余年的行业经验就是它的需求(
Require
)文档,
J2EE
规范就是设计(
Design
)文档,而实现(
Implement
)的结果就是
J2EE
平台。需求和设计是由
Sun
完成的,而实现则是由广大中间件厂商完成,这些厂商当然也包括
Sun
自己。
根据
IDC
早期的一份报告显示,企业用户的需求要求各种中间件进行整合,也就是说各种中间件分开来还不能够满足其需求,
J2EE
平台正是这样的一种产物。它首先是一个对象中间件(按照面向对象设计思想设计的,比如
EJB
这样的对象),同时包含了消息中间件(
JMS
),数据库访问中间件(
JDBC
),远程过程调用中间件(
RMI
,
JNDI
),交易中间件(
EJB
,
JTA/JTI
)。
J2EE
是第一个将这些中间件整合在一起的强大的平台,我们使用的就是一个现成的,用
Java
开发的中间件软件,不同的厂商使用同一个规格说明书来生产自己的
J2EE
平台,比如
Sun
自己的
J2EE SDK
,
IBM
的
WebSphere
,
BEA
的
WebLogic
,还有很多开源的实现比如
JBoss
、
Lomoz
等。而且
J2EE
平台也包含针对
Web
系统的内容,
Servlet
和
JSP
。随着技术的发展,大量的新技术也都加入到了这个平台,比如
XML
、
Web Service
等。
J2EE
蓝图包含了对在
J2EE
平台上进行企业级应用系统设计的指导,同时还包括了一个
Demo
程序及相应的文档。在蓝图中
Sun
给出了
J2EE
的分层模型,即表现层、业务逻辑层、持久层和
EIS
层。表现层中主要是
Web
层,当然还可能是其他软件,比如
Swing
程序。我们可以看出
J2EE
部分组件的构成也是根据该模型给出的,比如面向表现层的
JSP/Servlet
,面向业务逻辑层的
Session Bean
,面向持久层的
Entity Bean
,
JDBC
,
JTA
,面向
EIS
层的
JCA
和
JAX-RPC
等。
理解
J2EE
的全貌需要从上面三个宏观方面进行,每个方面都是看
J2EE
的一个角度,它们互相补充。
J2EE
为我们提供很好的解决问题的方法,如果你清楚每种中间件的作用,以及那些时髦的新技术名词,你将很清楚我所说的指什么,在此就不多赘述了。
很好的使用
J2EE
平台为我们服务,就如同
Rod Johnson
所言:我们应该以任务驱动,而不是以
J2EE
技术驱动。因此理解面向对象、理解三层结构、理解
Web
开发、理解中间件技术都是比理解
J2EE
规范、
J2EE
平台、
J2EE
蓝图更重要的事情。特别是
Spring
、
Hibernate
等轻量级框架的出现,
Rod Johnson
、
Martin Fowler
、
Robert Martin
的主张以及敏捷方法的兴起,一种更加务实的态度和做法正在被重视。
Rod Johnson
在自己的三本著作中都在大声批判
J2EE
规范中的一些组件,比如认为
Entity Bean
是彻底的失败,
EJB
是不建议使用的超级复杂的重量级解决方案,
JNDI
也不是每次都要使用,
IoC
比
CMP
更具有明显的优势,并很不给面子的说
J2EE
规范专家组的成员对实际应用并不在行,而应该把这些交给上千成员的社区等,这些都是从实践中得出的结论,而让人兴奋的是
Sun
的专家组已经听取了大家的建议,在
EJB3.0
规范中已经大大的简化了
EJB
,也引入了
IoC
等新的理念。
对于
J2EE
的使用我见过四种人,第一种是根本不了解
J2EE
,以为使用了
WebLogic
、
WebSphere
这样的
J2EE
中间件软件就是使用
J2EE
了,完全没有用到容器提供的各种企业级服务,比如连接池,
JTA
;第二种是根本不理解
J2EE
,完全按照
Sun
给的规范去做,造成了滥用分布式、不恰当的使用
Entity Bean
的情况;第三种是跟着流行走,直接使用
Spring
等框架,完全抛弃了
Sun
的规范;第四种是能够正确看待“正统”
J2EE
和轻量级
J2EE
,能根据需要进行方案的比选。第一种是无知,第二、三种是蛮干,第四种人才是
J2EE Expert
。
在这一部分,我没有一一介绍每种组件,因为已经出版了太多的书籍来介绍这些。重要的是我们看问题的角度。
J2EE
是依托一种面向对象语言——
Java
建立的平台和规范,而
.Net
则是使用多种语言构建的统一的平台。与
Java
的可移植的思想相近,通过将
.Net
平台上所有的语言(使用托管方法)转化成中间语言,然后由
CLR
来解释执行,相当于
J2EE
平台下的
JVM
。
.Net
平台跟
Java
平台的一个区别是
.Net
平台没有把那个规格说明书公开,而是直接由微软自己拿出了产品,而其需求与
J2EE
是一致的,就是为企业用户服务,构建企业级信息系统。因此
.Net
平台也是一个对象中间件产品,也包含消息中间件(
Message Queuing
),数据库访问中间件(
ADO.Net
),远程过程调用中间件(
Remoting
),交易中间件(
Enterprise Service
)。而
Web Service
是
Microsoft
和
IBM
一起提出的,因此
Microsoft
自然也是很早就开始支持
Web Service
的,而且从
.Net Framework 1.1
时就已经是卖点了。
Microsoft
自有一套研究方法,
Microsoft®
解决方案框架 (MSF) 是一种成熟的、系统的技术项目方法,它基于一套制定好的原理、模型、准则、概念、指南,以及来自 Microsoft 的、经过检验的做法。这很像Java阵营常讲的J2EE设计模式、敏捷方法之类的东西,而且他们的共同点都是基于实践经验。Microsoft把自己在软件业闯荡20年的丰富经验和其他合作者的经验再加上在模拟真实环境的实验室的实验结果整合到自己的产品中,于是就有了Visual Studio .Net系列强大的工具,而且他们是统一的,不是东拼西凑而成的。
想要更好的构建.Net平台下的方法与J2EE平台相同,而很多好的实践经验由于已经构建在平台内部,比如code behind风格使得使用MVC架构模式变得容易。但是与J2EE平台相同,构建稳固的、可复用的、易于维护的、具有扩展性和延展性的、安全的、面向对象的系统,依然需要设计者对于OO设计思想的准确把握、对于n层结构的深入理解以及对于任务的透彻掌握,使用.Net平台同样不意味着你一定能设计出好的应用程序。
J2EE
和
.Net
两大平台正在齐头并进,互相借鉴,
2006
年
Sun
推出了
J2EE 5.0
,使用了
J2SE 5.0
的新特性——标注
(Annotation)
,引入了
.Net
平台中的
Metadata
概念,对
EJB
进行了大刀阔斧的改革,去掉了为人诟病的复杂性,就连原来
Rod Johnson
指出的
Entity Bean
只能在
J2EE
容器中测试而造成的困难都被去掉了,现在
Entity Bean
可以像
POJO
一样被测试了。而
Hibernate
也发布了新版本,开始支持
JTA
。而
Spring
推出了
2.0
版,改进了
Spring MVC
等部分,我们可以看出,随着
J2EE
社区
Rod Johnson
以及敏捷社区在实践中发出要简化
J2EE
开发的复杂度的呼声,
J2EE
开始走向简单,而这正是
Microsoft
一贯的做法。而
.Net
也将于
2007
年上半年发布
.Net Framework 3.0
,其中统一了远程服务(
WCF
),工作流(
WF
),桌面
UI
和
Web UI API
(
WPF
),安全验证(
WCS
)。
Microsoft
继续向简化之路迈进,尽可能的让用户没有选择(有选择和没选择都是双刃剑),讲究一致性。我们可以看出
.Net
在不断的增强
Web Service
,更好的整合各种应用系统。
不仅发出感叹,
.Net
和
J2EE
两大平台越走越近,随着时间的推移,或许抉择只需考虑个人偏好了。因此在当下作出两大平台的选择还有些客观的办法,虽然同样是相当困难的。