Character & Report

人物&报道
名人堂 >>>

Eben Moglen
——倡导自由软件运动的法律之手
□ 文 / 倪志刚
 “我是一名历史学家,一

Eben Moglen 回忆说,在耶鲁期间是人生

中最重要的一个方向。随后Moglen应Ri-

名计算机程序员,但是我主要是一个律

中一段很长的黑暗时期,对人生感觉到

chard Stallman的邀请加入FSF担任法律顾

师。我主要做的事情是:通过消除在知识

迷茫。

问,开始了为自由软件开发者提供法律

产权保护法庇护下非法力量从而创建自

时间转到 1991 年在哥伦比亚工作的

帮助的事业。2005 年 2 月 Moglen 协助创

由。” Eben Moglen——GPL的创造者之一,

时候,Moglen 处理了人生中第一个关于

建了
“自由软件法律中心”
(Software Free-

自由软件基金会(FSF) 的法律顾问,在

自由软件的重要案件。这个让 E b e n

dom Law Center),并在其中担任 Public

“Free Software, Not the Other Thing”中

Moglen 一直引以为豪的案例,也是成为

Patent Foundation的一名主管,这个法律

这样写道。

他一生中最重要的一个转折点。当时他

中心无偿为自由软件开发者提供需要的

Eben Moglen 的一生也可以算得上是

在阅读 BBS 时,发现了 P r e t t y   G o o d

法律援助。

具有传奇色彩了。在他 12 岁时就对计算

Privacy,一个由Phil Zimmerman编写的电

基 于 其 程 序 员 与 律 师 的 背 景,

机编程产生了浓厚的兴趣,随后在 1973

子邮件加密程序,程序员出身的 Moglen

Moglen开启了他自由软件法律援助之门,

年,年仅 14 岁的他开始了职业程序员的

对这个软件有非常深刻的印象,同时,作

他说:
“我所付出的时间不会比自由软件

生涯。到了1979 年,他就能够独当一面。

为一名专业的法律工作者,他立即意识

开发者为了改进程序所付出的时间更

在此后的 5年中,他供职于IBM的实验室

到Phil Zimmerman可能会在法律方面遇到

多,我之所以花时间帮助他们是因为:

和研究中心,致力于高级语言的设计与

麻烦,于是他主动给 Zimmerman发邮件,

有些工作必须由程序员来完成,而有些

开发。在此后10多年的程序员生涯中,他

表示愿意无偿提供法律帮助。果然,不久

工作却只能由律师来完成。但是愿意无

积累了足够多的软件开发经验,更重要

后美国政府开始控告Zimmerman,认定他

偿工作的律师比无偿工作的程序员少得

的是,他为另一个目标——成为一名律

将 PGP 软件在互联网上公开的做法是违

太 多 了 。”在 自 由 软 件 法 律 中 心 中,

师,积累到了足够多的学费。

反美国法律的。Eben Moglen 为了大众的

Moglen 和他们的同事一起提供的都是无

利益而帮助了Zimmerman,使得美国政府

偿的服务,对于能进入法律中心的律师

最终撤消了这一诉讼。

要求也比较特殊,除了法律知识外,同

1980 年,Eben Moglen 在Swarthmore
College取得了法津学士学位,并在此期
间获得了文艺评论的“Hicks Prize”。5年

正是这个事件,让Moglen意识到,自

时还要求具备一些程序员的知识,因为

后他又从耶鲁大学取得哲学的硕士和法

由软件的存在和发展以后将会越来越强

他们这些律师需要和程序员打交道,而

律学博士学位。以后的几年里他在纽约

大,并且将会是以后软件最重要的存在

Moglen 认为,只有对代码有着相同理解

联邦地方法院和美国最高法院担任法官

形式之一。也因为 Zimmerman 事件的影

的人,才会不厌其烦的为软件开发者提

助理。1987年他在哥伦比亚法律学校开

响,当时Richard Stallman(FSF的创始人,

供更优质的服务。

始任教,担当副教授教法律学。到了

自由软件之父),联系到Moglen,希望他

也正是由于 Eben Moglen 在自由软件

1993 年,他从耶鲁又取得了一个历史学

能提供法律上的帮助。Moglen 再一次无

上所做的贡献,2003他被授予了EFF Pio-

博士学位,随后一直在哥伦比亚法律学

偿的帮助了 Stallman,协助他起草并创建

neer Award。他也将继续为了捍卫自由软

校担当法律和法律史的教授直到今天。

了 GPL。至此为止,Moglen找到了他人生

件而高举自己的法律之手。

10

程序员

Character & Report

人物&报道

程序天下事 >>>

微软技术

Query)是微软公司正在开发中的一个将
被集成在下一个版本的.NET Framework中
的数据访问模块,它的目的就是最大程

■ 主持人:Kaneboy
涂曙光,微软(中国)有限公司产品技术专家,
博客堂成员。专注于.NET 开发,从事 Office
System、SharePoint 等产品相关的技术支持。

度的统一和简化.NET 开发人员访问各种
数据的方式。实际上,早在去年,LINQ的
开发计划和一些相关的信息就已经被公
开了出来,而在本月,微软公司向外发布

 数据访问,大概是绝大多
数程序员写的最多的功能模块了。软件

失误而产生的 Bug。
3. 没错,就是ORM(对象关系模型)。

了LINQ的一个社区技术预览版
(Community
Technology Preview),代表着现在.NET开

开发发展到今天,开发人员们已经可以

越来越多的开发人员都开始不断的乐此

发人员就可以在 Visual Studio 2005 上领

从各种进行数据访问的方式中进行选择

不疲的寻找着自己喜爱的 ORM 组件,然

略这个未来的产品了。

了,我们不妨想像一下在日常编程工作

后尝试使用它们。有了ORM,我们可以避

LINQ 最具革命性的特性,就是它包

中,我们都是如何进行数据访问的:

免直接编写数据访问代码了,而转由

含了 CLR支持,C# 与 Visual Basic 语言

1. 使用通用的数据库访问接口。数

ORM 组件去访问数据库。像 NHibernate之

的扩展,以及对数据库、对象、XML 等

据库的访问接口从以前的 O D B C ,到

类的社区软件,已经越来越成熟,也拥有

数据源的统一访问方式。我们可以将

OLEDB,再到.NET时代的ADO.NET,经历

了越来越多的使用者。

LINQ 看成是数据访问方式的一个重要革

了多次更新和变革。虽然它是最“原始”、

虽然我们已经拥有了如此多的数据

新,因为它完全不同于 ORM 等组件所采

最“直接”的方式,但同时也的确是被使

访问方式,但它们都有着各自的缺点。直

用的方式,需要在程序项目中引入 ORM

用得最多的方式,而且,Visual Studio 的

接调用数据库访问接口太过繁复,代码

组件然后调用其功能,而是通过直接对

IDE也对ADO.NET的使用提供了越来越好

生成工具太过呆板,ORM 的学习曲线很

编程语言进行数据访问功能上的扩展,

的支持。

高,而且没有统一的标准,产品众多。既

来实现对数据的完全“面向对象”的操

2. 除了手工编写代码来构建数据访

然数据访问已经是几乎所有应用程序都

作。LINQ 对编程语言的改变将最终体现

问模块之外,我们还可以使用一些辅助

不能离开的功能,那为什么不让编程语

在代号为 Orcas 的下个版本 C# 和 Visual

工具来帮助我们完成这项工作。现在已

言自身就具有这个能力呢?也许 Anders

Basic 上。

经存在大量的数据访问代码生成器,来

Hejlsberg 也是这么认为的,于是在他的带

供我们使用。它们不但能提供我们的代

领下,微软开始了 LINQ 的开发计划。

码编写速度,而且可以避免由于人为的

LINQ (.NET Language Integrated

数据库技术

如果你想马上尝试 LINQ ,那么现在
就可以在微软的下载站点上下载到 LINQ
的五月份技术预览版。

技术的进一步支持上。就如同微软什么
新技术总是和.NET一起说一样,Oracle的
RFID 以及它的 Oracle Sensor Edge Server
此次最新发布也和Fusion的中间件技术息

■ 主持人:王翔

息相关。通过把RFID与现有的Oracle工作

分布式异构数据库方面的高级开发工程师。

流产品BPEL Manager集成,将本来在后台
运行的功能,可视化为前台的业务流程,

 上月 SQL Server 2005 发布

press 将大大简化原有报表开发和 Express

大大简化了架构和设计人员对 RFID 技术

Service Pack 1, 同时也更新了对应的Books

数据库引擎管理的工作。对销售版本新

的使用。相信进一步Oracle还会把RFID纳

Online。与以往的安全性更新不同,此次

增内容进行比较就能发现不少内容应该

入其SOA框架考虑。另一方面,本月Oracle

主要集中在新特性的增加上。Express的使

是没有赶在正式发布版时完成的一些特

还大张旗鼓的宣传其数据安全、商务智

用者收益最大的是可以通过 F u l l   T e x t

性;而对于Express的增强则把它推上了应

能和不受限业务的解决方案。

Search作基于表间的词或者短句的检索,

付一般应用较为完整的数据库开发平台。

此外新增的 SSRS BI Studio 和 SSMS Ex-

12

程序员

本月Oracle的消息主要来自于对RFID

Sybase本月带给.NET阵营好消息:其
主要开发工具 PowerBuilder 除将会在安全

Java 技术

S O A 领域下砸下重金 ,连开源领域的
JBoss 也积极投身,那么 SOA的解决方案
如何使用开源技术来实现呢?让我们拭
目以待吧!

■ 主持人:范凯
网络 ID robbin,JavaEye 社区的创始人,开源
软件的积极推动者和倡导人。

Spring Update
Spring 在这两年已经逐渐成为Java企

 本月 Java行业的焦点莫过

R a i l s 这样提供了极强快速开发能力的

业应用的主流框架之一,连JavaOne也不

于 5 月 16 日到 5 月 19 日在美国旧金山

Web 框架得到越来越多的关注,与此同

能忽视Spring 的力量。在本次JavaOne,单

Moscone Center召开的一年一度的JavaOne

时,传统的Web开发快速脚本语言PHP在

单看看 Spring 相关的 t o p i c 数量就知道

大会了。每年的 JavaOne 大会都是对Java

加入面向对象特性之后,在互联网领域

Spring 受欢迎的程度,有 Rod Johnson的

行业一年来发展的总结和未来的展望,

也仿佛重新焕发了青春,当然Java作为目

《Spring Framework Update》,有Keith Donald

JavaOne 2006有哪些值得关注的话题呢?

前企业应用领域开发的王者,自然也不

的《Spring Web Flow》和《The Spring Rich

甘落后。Groovy 就是 Java行业提供快速

Client Project: Effective Desktop Applica-

脚本开发的利器之一。在本次JavaOne大

tion Architecture》,还有 Jonas Boner 的

EJB3.0规范从2004年5月在JCP制订

会,将会演示Groovy结合AJAX 技术进行

《Transparently Clustered Spring》等等。喜

第一稿以来,已经走过了漫长的两年时

快速 Web 开发,引导我们展望 Java快速

间,虽然各个EJB厂商早已迫不及待的推

开发的未来。

EJB3.0 规范的发布

Struts Ti

出了自己的 EJB3 产品,有些厂商甚至有
了 EJB3 的实际项目案例,但是似乎都还
不够名正言顺。随着在本次JavaOne大会

欢 Spring 的朋友一定可以大饱眼福。

SOA in OpenSource
SOA是这几年企业应用领域的热点,

去年,Struts开发团队和 WebWork开
发团队宣布合并,基于 WebWork 的代码

上EJB3.0规范的正式推出,Java企业应用

随着企业信息化建设的基本完成,进行

共同开发下一代Java Web框架……Struts

开发将进入 EJB3 的时代。

各个应用系统的整合和互操作,成为当

T i ,令很多人还记忆犹新吧。在本次

前企业应用亟待解决的问题,而 SOA正

JavaOne,Struts Ti的核心开发人员将介绍

Groovy 简化 Web 应用的开发

是为解决应用系统的互操作和提供更高

Struts Ti 框架的进展,据说 Struts Ti将于

随着这两年IT业界竞争加剧,软件行

层次的应用复用而应运而生的。Java行业

8 月份发布,届时究竟是 Struts Ti,还是

业越来越强调开发的敏捷性,像Ruby on

的巨头们,例如 IBM,BEA 和 Oracle 都在

JSF能够成为Java Web框架的赢家呢?

性、Web Service 和数据仓库部分大大加

行环境的壳,更有利于提高自身形象,况

于以往商业、开源 RDBMS 的 Row Lock-

强外,更是准备在其10.5版本中增加对.

且 Sun 和 Java的渊源也是 MySql 所需要,

ing 技术:Shared Row Locking,通过该技

NET 2.0的全面支持,在其风头最盛的移

虽然 P H P 技术较之初期的纯脚本开发已

术可以在保证基于FK(Foreign Key)的级连

动产品中,
也考虑增加对.NET CF(Compact

经有了很大的进步,但面对为数更为众

表(Master-Detail)环境下,提供DML操作

Framework)的支持。

多的 Java开发人员,MySQL 也是当仁不

更高的并发性,而不仅仅限于以往瓶颈

MySQL 公布了与 Sun 合作进行 OLTP

让的尽量拉拢;Sun需要像MySQL这样的

常常位于 Master 表中的 Row Locking。

Benchmark 的测试结果,声称其称性能要

数据产品来促进其 Solaris 和 Java 产品的

比在Red Hat Linux上快 60%至90%。抛

销售,两家之间的“互补性”显而易见。

开技术的内容,公布这个结果更多的是

PostgreSQL 同时发布其 8.1 版本和

SQLite上个月发布了3.3.5版本,除
了继续 SQL-92的更加符合性修改外,还
提供了期待已久的编译器自动 S t a c k

MySQL和Sun强烈的“技术互补性”需要。

Aqua Data Studio 4.7 。在此版本中,

Overflow 和 Inteer Overflow 的报告功能,

MySQL一直试图树立自己的Enterprise DB

PostgreSQL真正对.NET应用提供了较为完

这些特性将很大程度上改善原有 SQLite

的形象,以至于本月的Web Seminar题目

整的支持,同时在 SMP(多处理器)环境

运行时错误不容易调试的问题,这对于

是All-in-One Enterprise-Grade Support and

下,性能有了较大的提升。顶着“最先进

国内在将 SQLite 作为嵌入数据库集成的

Service,借助于 Sun Solaris这个企业级运

开源数据库”的PostgreSQL开始支持不同

开发团队也是个好消息。

Programmer

13

Character & Report

人物&报道

程序天下事 >>>

软件工程与项目管理

侵占了。
4 月 2 1 日,S y b a s e 在北京举行
PowerDesigner 12 发布会,首席架构师王

■ 主持人:潘加宇

晓昀在会上展示了PowerDesigner 12的新

UMLChina 首席专家,潜心研究和实践 UML/UP
相关技术的应用。

特性,包括Data-Mapping 编辑器,UML2.
0 支持、BPMN 支持、新的报表器以及增
强 ERwin 导入能力等。Interactive Objects

 IBM收购了长期的合作伙伴

得了很多支持,获得了以前未有过的发

公司发布了新版本的 MDA 工具 ArcStyler

BuildForge公司,将把 BuildForge在构建管

展,但离公众的视线似乎变遥远了,关注

5.5,增加了对 JBoss 4、Java 5 和Struts

理方面的技术整合到 Rational 系列软件

点也变宽了,不再象以前那样专,无论是

的支持。国内出品的UML 工具也有亮点,

中。IBM 负责 Rational 营销和战略方面的

社区、电子杂志,还是 Grady Booch的谈

楚凡科技在新版工具 P l a t o   2 0 0 6   f o r

副总裁 Roger Oberg 表示,这是一个很自

话。以前 RationalEdge被当作学习建模的

UML2.0 的发布中,采用了无需安装“绿

然的补充,IBM之前没有自己的构建管理

重要资料来源,现在上面放进了各种各

色软件”的发布方式。当下流氓软件横

软件,而在 BuildForge的客户里,80%也

样的 IBM 产品内容;说起 Rational 的招牌

行,有的用户甚至非绿软不用,这一举动

是 IBM Rational 软件开发平台的用户。调

建模软件,很多人都知道名字叫Rose,但

对鼓励开发人员大胆试用这款工具很有

查机构 Osterman Research在4月份发表了

被 I B M 收购后推出的新版本叫什么名字

好处。

一份调查报告,该调查在美国不同规模

呢?知道的人就少多了。Wendy Boggs和

敏捷开发管理工具厂商VersionOne发

公司的总共352名开发人员中进行,报告

Michael Boggs 为 Rational的各个版本写了

布了最新的敏捷开发管理平台 V1: Agile

指出:在开发团队里构建过程在1个小时

一系列的“Mastering UML with Rational

Enterprise,把支持的范围扩展到项目的所

以上是家常便饭,一半的开发人员还认

****”
(中译本即为《UML 与Rational ****

有涉众,从开发人员、项目经理、主管、

为现在的构建过程比起一年以前时间更

从入门到精通》系列),而自从Rational被

客户到测试人员。例如,可以产生主管级

长了。

并购后推出新版本到现在,Boggs们再也

别的跨项目布告板,可以对客户和市场

没有新的类似“Mastering UML with Ra-

的各种要求排优先级。另一家敏捷工具

Austin Business Journal 上的”IBM, Tivoli

此时也恰逢 IBM 收购 Tivoli 十周年,

tional Software Architect”的书出现。随

厂商 ,获 得 今 年 J o l t 生 产 率 奖 的

—10 years later”一文正面地回顾了Tivoli

着 Borland Together、Enterprise Architect、

TargetProcess 也发布了TargetProcess Suite

被收购后的发展。并购到底是好是坏?

Poseidon、MagicDraw等工具的崛起,Ratio-

1.6,添加了“搜索”、“程序管理”、
“特

Rational 被并购之后,也许从“上层”获

nal Rose时代奠立的用户基础不知不觉被

性管理”等新特性。

嵌入式移动开发

Builder 将不再是一个独立的 IDE,而会成
为Visual Studio 2005的插件。到时候,定
制系统、开发应用程序、调试程序将会在
同一个IDE中完成。现在离Windows CE 6

■ 主持人:马宁
微软最有价值专家,Windows Mobile开发者。

的正式发布还有一段时间,在经历了保
守的 Windows CE 5.0之后,我们的确希
望它能为我们带来更多新的功能。

  本月最大的新闻是 MEDC

CE 从 6.0 开始将会有一个全新的开始。

本次 M E D C 的另一大主角是. N E T

2006 在美国的召开。微软 2006年的重点

Windows CE 6的内核发生了颠覆性

在于 Windows Vista,所以这次 MEDC 更

的变化,以前的CE 只允许同时运行32个

但是从字面上我们就可以了解,这是一

多地侧重于技术的前瞻和新技术的宣传。

进程,每个进程拥有32MB的虚拟内存,而

个比.NET Compact Framework更小的.NET。

本次 MEDC 最重要的事件就是 Windows

Windows CE 6 允许同时运行 3.2 万个进

是由微软将 Smart Personal Object Tech-

CE 6 Beta版本的推出,Windows CE 6的

程,每个进程可以在2GB的虚拟内存空间

nology (SPOT)和 TinyCLR结合起来推出

巨大变化也足以让开发者相信 Windows

中运行。另外,在开发工具方面,Platform

的。目前了解到的只是应用程序的尺寸

14

程序员

MicroFramework,一个完全陌生的名字。

Open Source

C++ 的泛型技术是一样的。不过实现原
理却完全不同。众说周知,C++是利用模
板在编译期推导参数类型来完成。而Py-
thon是动态语言,编译期所做工作极少,

■ 主持人:汤韬

主要都在运行时解决。况且动态语言没

开源爱好者。

有函数参数的静态类型检查 。可以说,
Python的函数天生就具有泛型的特质。所
以,Python中的Generic Functions可以比较

 Guido van Rossum 最近在

惑。而lambda也应该可以找到更好的替换

的概念应该是C++泛型中的“偏特化”特

他的 Blog 里开始了对下一代 Python语言

模型。一年过去了,Guido 在寻找 lamdba

性。即写出一个通用版本函数以及一系

—— Python3000 的一系列讨论。

的替代者方面进展得并不顺利,但可确定

列针对特定参数类型的专有版本。这些

lamdba 会继续存在于 Python3000中。

系列函数可以通过一个内置 register 函数

首先 Python3000 虽然很重要但是不
会是一个革命性的产品。不会像Perl 5升

另一个重要的特性是对Adaptation 或

级到 Perl 6 那样惊天动地,改得遥遥无

Generic Functions 的支持。Adaptation主要

期。它在语法上会出现许多变化,一些内

用在一些需要对对象进行二次包装的场

总的说来,Python 3000 目标在于改

置函数将会被取消。这将意味着,P y -

合(想想针对接口编程,想想 Adapter模

进其对函数式开发范式的支持;吸取现

thon3000 不会完全兼容 2.x 系列的版本。

式)。它可以在运行时将接口(Python中

在 Python 社区中一些优秀框架的设计成

在扔掉了兼容性这套枷锁后,Python3000

将接口描述为协议,而且目前的Python版

果(诸如 PEAK 中的“多方法分派”),提

也许表现得会更加完美。

本中并没有一个明确的Interface之类关键

升Python的设计抽象层次。从而提升Py-

字)和其实现类进行组装。有点类似Java

thon系统的开发效率。

Guido 在去年就曾撰文,声称要去掉

完成组装。运行时,系统自动判定参数类
型,并调用最匹配的一个函数版本。

map/filter/ reduce/ lambda系列内置函数。

中的动态代理,但更加灵活、语法更简

当然,Python3000现在仍然处在一个

它们实际上是Python中关于函数式编程范

洁。看看在 J2EE 中那泛滥成灾的 XML 配

早期讨论阶段,
发布看来要经过漫长的等

式的核心功能。去掉它们的原因在于,

置文件,它的解决方案显然要优雅多了。

待。好在,Python2.x系列的版本仍会持续

Guido 认为通过增强的for语句,可以很轻

Generic Functions是作为Adaptation的

的发展。一些3000中的特性也可能以预览

松的替换掉 map/filter 的功能。而且对于

竞争者出现的。具有 C++ 泛型技术背景

的姿态出现2.x 系列中。Guido 仍然希望

许多没有 LISP 这样语言背景的开发者来

的朋友对这个词应该不会太陌生。从技

Python的升级尽可能平滑的进行,避免犯

说,map/filter 的表达方式常令人感到困

术最终获得效果上看,Generic Functions与

下 Perl 6的愚蠢错误。

在 10K 以下,可以运行在 ARM7的处理器

控,他们之间采用了WiFi进行数据传输。

入式领域一定会越来越强。这次决赛将

上。大家应该还记得微软的Smart Watch,

WiMo可以将照相机抓拍到的图片传输到

于6月23日在微软总部进行,祝愿中国的

其中就使用了 SPOT 的技术。

Pocket PC 上。作者还打算将自己制作

队伍能取得好成绩。

除了 Smart Watch外,这次微软为我

WiMo 的步骤发布到网上。

微软与德信的这次签约对于双方都

们演示了.NET MicroFramework的另一个应

5 月 11 日,参加 Windows Embedded

有好处,与国际大厂不同,国产手机的研

用:SumoRobot。在 MEDC 期间有 42 支队

Student Challenge 2006 决赛的 30 支队伍

发技术掌握在Design House手里,掌握了

伍参加了SumoRobot挑战赛,另外动手实

都已经产生了,中国的参赛队达到了创

手机产业链的研发环节,就等于控制了

验室中也有关于 SumoRobot 的实验,

纪录的 14 支。Windows Embedded Stu-

国产手机的未来技术走向。而在国产手

说到机器人技术,微软的一位老兄

dent Challenge是微软面向在校大学生举办

机销量持续下滑的今天,技术实力不足

最近使用自己的 Windows Mobile 手机制

的嵌入式领域的开发比赛。去年的比赛

已经成为国产手机的致命伤,德信与微

作了一个机器人:WiMo。WiMo的外观一

有四支中国的队伍参加,而这次中国的

软的合作至少可以摆脱手机软件技术方

定会让大家感到可笑,但是人家就是利

队伍已经占据了半壁江山,这说明中国

面的尴尬。从多普达到德信,微软在

用简陋的设备实现了一个功能完善的机

的大学在电子信息领域的水平在逐步提

Windows Mobile的推广上走了一条有中国

器人。WiMo 可以通过 Pocket PC进行遥

高,科技的源动力来自于大学,中国在嵌

特色的道路。

Programmer

15

人物&报道

Character & Report

程序天下事 >>>

【5 月人才快报】英雄难过语言关 外企研发中心高薪难聘英才
进入二季度,IT人才风向标的晴雨表

在与招聘经理的沟通中,总能听到他

上,温度迅速攀升的应该当数跨国公司的

们发表类似的观点:很多技术高手,技术

研发中心。近期CSDN人才频道的热点招

方面非常出色,就是英语不过关,实在没

聘外企包括:微软(ATC BJ,ATC SH,MSN

有办法。大多数企业在招聘技术人才的

T e a m , M S R A )、B E A 中国研发中心 、

时候,都会把他的技术背景作为第一个条

Autodesk中国开发中心、Google中国研发

件,而外企招聘,英语不是最重要但也是

中心等等,都在大量的招聘技术精英,部

次重要的一个条件。从他们的经验来看,

门人数也将有很大的扩充。惠普在5月12

如果说技术高手难觅,那么英语好的技术

日的新闻发布会上, 正式启动了“聚英

高手更难招。

1000”的大型人才招聘活动,将招募1000

而很多技术人员都面临着这样的困惑

名业界精英和专业人才加盟,再次表明了

——自己本身技术能力有很强的优势,有一

惠普全力开拓中国市场的坚定信心。还

定开发经验, 学历背景也在本科以上的水

有类似文思创新这样的软件外包公司,今

平,英语一般都通过了国家6级,甚至GRE和

年预计从 1500 人扩充到 3000 人,大部分

托福考试都有很高的分数,日常英语文档的

都是外派给微软、IBM这样的外企在华的

写作也还可以,唯独口语不过关,不敢开口,

研发中心。热度可见一斑。

这也就成为了他们应聘外企的最大障碍。

【职场百味】担心编程到了 30 岁就要面临转行?
◆ JiangSheng(蒋晟):的确,技术日
新月异,年纪大的人很难跟上,但是一些

能吃青春饭。

◆TechnoFantasy(陈锐):这个我倒是

统分析、测试、顾问和管理。另外,也可

没有很担心。其实现在很多公司都非常

以考虑投身教育行业。

需要很有经验的开发人员来参与到产品
开发和项目中,避免开发中的一些陷阱

吧? 其实在这方面,我个人有一些感触。

等。而且即使转行也应该是一个很自然

程序员的发展,一般是这两种情况:非常

的过程。

努力的做程序,所以一直都是程序员;非

◆ Saucer(思归):在这里几乎没有这

常努力的做程序,其他方面也不错,最后

样的考虑,虽然编程是工作,但也是因为

发展为项目经理。

兴趣在驱动你,失去了兴趣,那么工作大

对于前者,如果是资深程序员,已经

概也无法延续。参加当地的技术会议和或

是程序的顶峰,很少有人能够跟他抢,所

者 MVP 会议的话,你会经常看到头发花

以激励少了,逐渐斗志少了,30岁后精力

白、年迈的程序员。当然这大概不适于国

也少了。加上技术的快速变化,很快会跟

内,环境不同吧。时代在变,这样的趋势

不上年青人。所以程序员会有一个青春

以后也会变的,
虽然我的回答大概useless,

期。即使他学的是最新的技术,也是有一

但谁叫我们处于时代的大变革中呢?

个应用的持续期,过了这个持续期,新的

编者按:三十而立,30岁转行问题已

技术出来,他跟不上了,就成了吃青春

经是众多程序员持续关注的话题。本期

饭。对于后者,很显然,他的精力被杂事

“职场百味”特别精选了CSDN社区“人物

分担了,没有精力做技术,如果他在他掌

接龙”栏目的精彩观点,与读者分享。

16

程序员

排名

最受关注企业
腾讯科技

1

(DZ- 网页 UI 设计)
慧通商务(深圳)有限公司

2

(无线通信算法工程师)
广州网易互动娱乐有限公司

3

(安全工程师系统管理员)
微软中国

4

(Research Software )
北京紫光捷通科技有限公司

5

(SP 产品经理)
北京凌云互动信息技术有限公司

6

(搜索引擎研究员)
毕益辉系统(中国)有限公司[BEA]

7

(SE,Weblogic ,Server,Tuxedo)
北京龙腾阳光科技发展有限公司

8

(WEB 软件工程师)
北京博大正方软件技术有限公司

9

(Linuxc/c++ 开发 Java 工程师)
环达电脑(上海)有限公司

10

(BIOS 工程师)

资 料 来 源 :CSDN 人 才 频 道 5月 企 业 点 击 排 行 ,本
月 共 有 385 家 新 增 企 业 。

握的技术的黄金期得不到转型,他也只

职位也需要经验和技术并重的,例如系

◆ zjcxc(邹建):老不老是心态问题

5 月最受关注企业榜

5 月最受关注职位榜
排名
1

2
3

4
5

6
7

8
9

10

最受关注职位
Java 工程师
(奇虎、伟思拓、网络易联)
WEB 开发高级工程师
(郑州鼎晟、腾讯科技)
.NET 工程师
(掌上通、激动集团)
VC 程序员(游戏)
(杭州畅游网络、北京博大正方)
Delphi 程序员
(慧通商务、北京泰能)
C/C++ 高级开发人员
(福州天下创世、智乐软件)
数据库工程师
(用友华表、中联集团)
搜索引擎开发工程师
(微软中国、阿里巴巴)
信息安全工程师
(联想、网易互动、腾讯)
项目经理
(搜狐公司、成都易我科技、飞拓无限)

资 料 来 源 :CSDN 人 才 频 道 5月 份 职 位 点 击 排 行 ,
本 月 共 有 1360 新 增 职 位 。

■ 栏目策划:CSDN 人才频道 熊妍妍
■ 网址:http://job.csdn.net
■ E-mail:xyy@csdn.net

>>> 网络聚焦

MSDN Magazine

探索开发 WCF 应用程序中的强大实例管理工具
实例管理引用了一系列Windows通讯基础架构的技术用于将消息和服务实例捆绑
起来。理解实例管理对于开发中的可升级、稳定的面向服务的应用程序来说是非常必
要的。本文提供了各种实例管理模型的基本原理,提供了什么时间和如何使用他们的
指导方针,并且讨论了一些相关话题。

在.NET Framework 2.0 中使用 XML 设置为你的应用程序配置参数
应用程序通常都非常复杂。
即便是最简单的软件也总需要大量的设置以存储一些
参数用以实现一些基本的功能。本文将介绍一些用 XML 设置来解决问题的方法。

Visual Studio Magazine

在 ASP.NET 2.0 中自定义安全设置
ASP.NET 2.0 比 ASP.NET 1.1 让用户能够更好的进行文件夹、用户信息的安全
管理,并且在登录的过程中整合自定义码。用户可以很轻松地在自己的网站中利用
ASP.NET 进行安全方面的设置。但是要将代码整合、集中用户的信息、跨越多个站点
进行安全设置的共享、用 ASP.NET 2.0 的菜单控件来实现上述的要求,需要做一些
额外的工作。
使用 XML 让你的文档变得智能
使用 XML 编辑器的特性能够让用户的 XML 文档变得更加智能。从 Visual Studio
2003 开始,Visual Studio 就开始提供 XML 的编辑器,微软在 Visual Studio 2005 中将
这个编辑器进行了升级。

Java Pro

要快?还是要好?
如今的工具变得越来越复杂,
将来的程序员可能要通过训练来快速的开发软件以
满足现在产品的需求而无法将传统计算机科学的课程在相应的时间内掌握牢固。
平衡
问题的两方面,好的代码和快速开发出来的代码,这个问题对于将来的软件开发有很
重要的意义。

JSTL 让 Web 应用程序灵活性性更强
虽然像PHP这样的脚本语言对于那些认为Java不够灵活的那些Web应用程序开发
人员来说是很好的选择,通过正确的设置,你可以用 JSP 标签库做得同样灵活。看过
本文后,可以尝试通过应用JSP标准标签库在一个简单的数据库应用程序中建立连接。

SD Times

SOA:准备好了么?开始吧!
面向服务的架构是 Web 2.0 时代的企业级应用。现在,越来越多的采用 SOA 将
对IT产业产生巨大并且意义深刻的影响,并且会加速IT的产业化进行。在这个转变过
程中,IT 组织将面对几个问题:如何管理自己的 SOA?如何为我的 SOA 付费?
收购 JBoss,红帽有了 SOA 的战略竞争力
红帽希望能成为 SOA工具的提供商。成功收购 JBoss之后,红帽扩展了其原有的
市场范围,同时将立即拥有应用程序服务器和中间件的市场,成为 BEA、IBM的竞争
者,和它们并肩抢夺这块市场份额。

Programmer

17

人物&报道

Character & Report

网络聚焦 >>>

www.Slashdot.org

HD Video 将阻碍互联网的发展?

传输这样的服务进行收费来弥补这部分的价格缺口。

现在有些ISP已经开始担忧大流量的视频将会阻碍互联网
的发展。这也是内容提供商不断抬高价格的原因之一。文章

Google 偏爱小型业务

提出,其实大部分家庭中的互联网应用都是小流量的应用,例

文章通过分析微软、苹果、IBM 等公司后认为,微软的平

如收发电子邮件、浏览网页等等。一旦人们开始在家中像看

台构建在PC上而Google的平台构建在互联网上,但是没有人希

电视那样花费数小时地用网络观看流媒体,那将对并不是为

望能够控制互联网,微软和Google 都不能。而 Google是从一些

此设计的网络产生很大的压力,ISP就要加强网络的承载能力

小 / 中型的业务上获取了大量的收益。这些不仅仅是如何做广

以避免高昂的价格。ISP希望通过向内容提供商的大视频文件

告的重大变革,而且还是如何做业务的重大变革。

www.theserverside.com
1998 年的互联网泡沫卷土重来?
有人认为,现在的互联网业正在重蹈 1998年泡沫的覆辙。

法正是对现在互联网业务泡沫重新膨胀的一种解说,不太可能
是暴发户产生的时候。不过,她的这种说法很快就被大量的反

现在的问题是:互联网已经有了泡沫升腾的迹象,我们又要面

对意见所淹没。随着Web 2.0 的出现,互联网出现了复苏的迹

临一场崩塌么? Flickr 图片共享网站的共同创办人 Caterina Fake

象,并且引发了所谓的互联网公司的第二次革命。这次的泡沫

在他的 blog 中这样写道:现在不是创办公司的好时机。这种说

将会带来怎样的机遇? 1998 年的历史是要在现在重现么?

http://idevnews.com/index.asp
用例:为 VS.NET创建插件

JavaOne 见闻实录

Visual Studio.NET因为其丰富全面的功能结构和方便的用户

在这次 JavaOne大会上,凡是关于SOA和ESB的话题都是热

界面而成为广泛使用的开发工具。但是,有时候想自定义Visual

门。IBM 提供7 个步骤来成功实现SOA的经验。IDN的记者还采

Studio.NET 却不那么容易。在该文中Elementools 的 CEO 以他的

访了 James Gosling、John Crupi以及除 IBM 和 BEA 之外的大型、

洞察力提供给读者透析调整 Visual Studio.NET 以满足用户自己

小型使用Java和对Java感兴趣的公司,听取他们对JavaOne 2006

开发需要的最好方法。

的看法。

www.microsoft-watch.com
DOJ 驳回 Google 对 IE 的抱怨

Office 2007 测试员:开动你的引擎,为 Beta2 做准备

Google 认为微软推出的 IE7 未在搜索市场上进行公平的竞

微软现在正在调整它的服务器为 Office 2007 Beta 2 的下

争,这种不公平竞争的行为是违背了美国的相关法律。DOJ指

载做准备,这预示着下一个测试版本很快就要发布。微软已经

出IE7允许用户可以自行作出选择,他们可以设置任何自己喜爱

给测试员发送了电子邮件,他们并没有计划在 Office 预览的网

的搜索引擎成为默认的搜索引擎(虽然在MSN 中首推的是IE)。

站上发布,而是在 BetaPlace 下载站点上提供。微软还提示这些

DOJ 要求微软必须在 2009 年前提供通信协议信息。

测试人员,他们在安装 Beta 2 之前需要卸载原来的版本。

18

程序员

推荐特色网站内容请发送至:editor@csdn.net

http://news.csdn.net/n/[Date]/[ID].html
No.

Topic

Date

ID

1

NetBeans 挑战 Eclipse 以彼之道还施彼身

20060421

15375

2

全美“50 大好差事”软件工程师排名第一

20060417

14902

3

史玉柱点评中国网游群英:陈天桥做了冤大头

20060420

14517

4

2006 年大学生就业“力”调查:你值多少钱

20060414

13120

5

Google 大举入华 雅虎中国已经悄然变脸

20060414

11188

6

网友撰文揭密:为什么开源杀毒软件这么少?

20060421

10209

7

Web2.0 大潮行将衰退 90% 相关公司可能消失

20060415

9778

8

Oracle、 IBM 、Microsoft 展开“完备产品线大战”

20060420

9756

9

日本游戏业哀鸿遍野 九年萎缩恶梦何时结束?

20060415

9539

10

Firefox 你拿什么和 IE 赌明天呢?

20060427

8798

一位独立软件工程师的困惑 http://www.mypm.net/articles/show_article_content.asp?articleID=9411
摘要:作为一个独立软件工程师,Tim Roberts 被排除在了信息技术服务的外包之外。
谈谈 CRM 中信息技术应用的几个潮流 http://www.mypm.net/articles/show_article_content.asp?articleID=9545
摘要:企业为获得满意的客户关系,当前较流行的思路是通过实施客户关系管理(CRM)项目来实现。
软件工程-软件目的需求开发与管理 http://www.mypm.net/articles/show_article_content.asp?articleID=9217
摘要:需求开发与管理是软件项目中一项十分重要的工作,但是在项目开发工作中,很多人对需求的认识
还远远不够。
对 ERP 项目实施的忠告 http://www.mypm.net/articles/show_article_content.asp?articleID=9533
摘要:ERP 在中国的发展很不顺利,对此,必须看到两个事实和两种发人深省的现象。
案例:软件开发项目的失控 http://www.mypm.net/case/show_case_content.asp?caseID=1885
项目管理的处于失控状态,请问这个项目的问题要主在哪里,应该如何处理?

地址:http://www.codechina.net/resource/gotores.php?articleid=ID 号
ID:150965  FreeBSD 使用大全(第二版) 中文
第 1 章:介绍有关 FreeBSD 计划的各个方面,例如

1.  J2EE 平台架构上开发 CRM 系统设计方案 ID:150780
2.  FreeBSD 5.x 架设管理与应用

ID:150966

3.  全程指导 Linux 下 JAVA 环境配置

ID:150960

第 2 章:描述如何用 Sysinstall 来安装 FreeBSD。

4.  Linux011 的源代码及注释

ID:150949

第 3 章: 介绍 FreeBSD 操作系统的基本命令和功

5.  VB API 函数参考手册(CHM)

ID:150937

能…

6.  C# 语言 ASP.NET 从新手到专家(PDF)

ID:150886

ID:150901  Ajax 应用实例

7.  C/C++ 程序员实用大全

ID:150997

8.  开放源代码知识大全

ID:150948

W e b 应用程序 。该 方 法 的 关 键 在 于 对 浏 览 器 端 的

9.  Eclipse 开发 J2ME 手机程序之简介

ID:150987

JavaScript、DHTML 和与服务器异步通信…

10. Linux 操作系统的内核编译内幕详解

ID:150996

它的历史目标和开发模式等。

Ajax,使用它可以构建更为动态和响应更灵敏的

Programmer

19

人物&报道

Character & Report

网络聚焦 >>>

让您不会错过最 HOT 的信息
文档地址:http://dev.csdn.net/article/ID 前两位 /ID.shtm
论坛地址:http://community.csdn.net/Expert/topic/ID 前四位 /ID.xml

文    档
■ 主题:采用 POI 和 ANTLR 提取 WORD 文档数据
作者:tyrone1979
ID:84014
摘要:POI 是 Apache 开源项目之一,用 Java实现跨平台MS
Word/Excel文档解析。 也就是说可以在非Windows平台提取MS
Word/Excel 文档内容。
本文采用 POI 的一个扩展 Jar 包 tm-extractors_0.4.jar 提取
Word 文档内容。
■ 主题:网络数据包拦截通用技术
作者:iiprogram
ID:83830
摘要:编写 IM DRIVER 在 NDIS 中间层对 MINIPORT(网卡驱
动程序)和协议驱动程序之间的数据包进行拦截的程序非常的
复杂,安装也很麻烦。本人简单的介绍一种更有效的基于NDIS
包拦截技术。
■ 主题:VB 中 String 的用法及原理
作者:tiger119
ID:83943
摘要:在各种不同开发语言中,字符串类型显然是最常见,
也是最常用的。它往往是绊脚石,或者程序中性能的瓶颈。 本
文将分享作者在这方面的体会。
■ 主题:编写高性能 Web 应用程序的 10 个技巧
作者:wangyihust
ID:84364
摘要:使用 ASP.NET 编写 Web 应用程序的简单程度令人不
敢相信。正因为如此简单,所以很多开发人员就不会花时间来
设计其应用程序的结构,以获得更好的性能了。本文将讲述10
个用于编写高性能 Web 应用程序的技巧。

论    坛
■ 主题:C++,谁来拯救你!
作者:supperman_009 (天堂草)
ID:4723104
摘要:在工作了一年之后,默然回首,发现原先酷爱的C++
没有了踪影。一个酷爱C++但是却在用Java的无奈程序员发出
感慨,要使 C++ 再次成为美味,我们应该如何去做呢?
■ 主题:目前最快的 N 皇后问题算法!
作者:IceCraft (心淡情浓)
ID:4709025
摘要:昨天在 google 上有幸找到了一个难得一见的算法,
是我目前见到的最快的皇后问题算法了。它有别于传统的数组
判断模式,而是采用了位运算。
■ 主题:说给应届毕业生的!
作者:podianliangshui
ID:4725975
摘要:我觉得我的同情心在日渐削弱,但是,应届毕业生
们,你们想过这些问题么?你知道你害了谁?
■ 主题:大家来谈谈掌握 Java 的基本功
作者:ITdavid (IT 大卫)
ID:4700006
摘要:Java作为一种编程语言,用它来实现你想要实现的东
西是最重要的,这就要求每个Java程序员平常要多练习,提高
自己的 Java功底。那么,你认为平常都应该练习什么呢?
■ 主题:ADO.NET 老牛拉车?
作者:irvine007
ID:4727120
摘要:一段小程序在VS.NET 2005上用C#重新编写,界面
是弄的华丽了,但是效率低下,1000条数据都没更新完成已经
耗去我 1 分多钟,请问这是怎么回事?如何优化呢?

■ 主题:C++ GUI编程——使用 SmartWin++
作者:iiprogram
ID:84349
摘要:SmartWin++ 是100%标准C++编写的轻量级GUI库,
没有 MFC 那样的宏,你完全可以以C++ 的思维编写 GUI,并且
编译出来的程序很小,支持 OpenGL 以及 OpenCV,这是吸引我
的地方。

20

程序员

■ 主题:转贴【给编程初学者的良言警句】
作者:iamcaicainiao
ID:4722559
摘要:对一个初学者来说,
IT界的技术风潮是不可以追赶的,
而且也没有能力去追赶,我只是觉得如果他们把追赶这些时髦
技术的时间多花一点在基础的课程上应该是可以走得更远的。

Oracle & Starcraft

http://spaces.msn.com/wzwanghai/PersonalSpace.aspx

这个 blog 被作者命名为 Oracle & Starcraft 是因为 Oracle 是作者工作的重要工具,而 Starcraft 是他用来娱乐的游戏。两者对
于作者来说都非常重要。作者创建这个blog 的意义也就是为了记载下对Oracle 新的理解,另外就是分享在 Starcraft中和朋友对
战的乐趣。作者希望在 Oracle 和 Starcraft 方面都能不断的进步。看来这个程序员劳逸结合,生活丰富多彩。
9i&10g btree index split
作者看过 lewis 的经典文章“How High Can You Go?”之后为 lewis 令人叫绝的思路叹服,对其中提到的 10g 对index split
的改进自己动手测试了一把。
auto undo management
Auto undo management 是 oracle 推出代替 manual rollback segment 的工具,Oracle 官方的文档上有介绍它的原理和实现方
法,作者深入探讨了一些官方文档中点到为止的东西。

DBA notes

http://www.dbanotes.net

作者在自己的 blog 中涉及到关于数据库和开源方面的技术感受,也有自己对于业界某些问题产生的思考。
操作系统的革命(Revolution OS)
作者看了半部 Revolution OS,认为它是枯燥而有趣的一部电影。因为片子从头到尾都是对众多顶级黑客的采访,但仔细
看下来却由此找到了很多以前不为人注意的一些关于自由软件运动 / 开源软件运动的被忽略的细节,让作者认为饶有趣味。
歪批 Web 2.0 盈利模式
作者对于雅虎移动产业策略师Russell Beattie 批评Web 2.0 没有自己的盈利模式而发出感慨,在国内来说还是有生财之道的。

布珞阁

http://blog.9zi.com

SWT 的八卦
作者转载的这篇关于 SWT 和 Swing 的论争,不是要激起什么争执,也不是支持哪一方(虽然作者的确是站在 SWT一边),
更不是要攻击 Amy,但是这是一篇有趣的文章,里面的内幕、线人、公司政治、垄断巨头、商界风云……足够拍一出有趣的
电影,并且文章还由此反映了 IBM 对 Swing 的看法和 SWT 的由来,还是非常值得一读。
一个 hi 老的文章
作者看到《为什么Hibernate如此成功!》,被文章提到如何使工作越做越有兴趣,并且让别人加入进来和你同乐而打动,认
为频繁的发布版本和重构,快速的构造软件整体轮廓,逐步求精确实是一种可行的软件产品开发方式,虽然这个思维有些微
软风格。

一起来 - 展现 & 分享 & 协作 -gogo

http://www.i170.com/user/gogo

跳起来看信息安全,安全无所不在。这是作者想在 blog 中表现的想法。他非常热爱自己的安全事业,从网络的安全到软
件系统的安全,作者总能从日常生活中获得灵感,转而应用到这些领域中去。
《达芬奇密码小说》里的 3 个安全设计思想
这是一本时下最流行的小说,而 blog 的作者却从这本小说中看到了许多和安全有关系的东西,受到了安全设计思想的启
发,安全问题确实无处不在。
理解了生活就理解了安全
作者在做过安全一段时间之后,对安全的无限憧憬和神秘的遐想都随着时间和方案逐渐灰飞烟灭了,留下的更多是对国
内安全界的强烈希望和深切担忧。作者通过一个小偷入室行窃的普通例子,将安全防护的每个步骤和应该考虑到的方方面面
阐述得非常容易理解。

Programmer

21

Character & Report

人物&报道
报道 >>>

使 BEA 一次又一次以领先的姿态冲锋在
中间件和 SOA 领域的最前线上。

中间件:
不求大而全,做专业的事
“术业有专攻”,BEA 在自己的领域
内,不求大而全,专注自己最擅长的,终
有所获。
BEA公司创立于1995年,发展初期在
北美、澳洲和欧洲收购软件分销公司,
1996年收购Novell的Texudo,Texudo是分
布式事务处理(TP)的基础结构平台,支
持多种语言。在电信和金融行业的核心
业务上有很好的应用。BEA凭借Texudo获
得了相当好的经济效益,也因为BEA的进
入,Tuxedo脱胎换骨,迅速成为中间件历

BEA: 奔跑的羚羊
在非洲大草原上,羚羊早晨醒来考虑的第一件事,是如
何让自己跑得更快以逃过狮子的追逐。

史上的神话,到现在BEA很大一部分业务
额依然是由 Tuxedo 带来的。
如果说Tuxedo是BEA的发家产品,那
么 WebLogic 系列则是 BEA 的看家之宝。
BEA 公司在 1998 年收购了 WebLogic,并
推出了业界第一个授权使用 J2EE 许可证
的WebLogic Server应用服务器,WebLogic

□ 文 / 肖文

Server 应用服务器不仅使 BEA自己得到了

疑 J2EE应用的人们,使 J2EE应用得到了

飞速的发展,更重要的是征服了那些怀

 BEA是一个中间件厂商,主

2005 年底 BEA eWorld 大会上,SOA

要为客户提供基于 Java 和 C 的大型中间

成为最重要的话题,其实早在5年前,BEA

广泛的部署 。推 出 市 场 后 不 到 一 年 ,

件应用服务器,以前主要产品线有

就开始提倡部署 SOA,期望着有更多的

WebLogic Server就成为业内第一Java应用

WebLogic 系列和 Tuxedo 系列,在去年和

企业能建立这种架构,可当时却孤掌难

服务器。

今年又增加了几条新的产品线,包括基

鸣。如今,SOA已是遍地开花了——IBM、

于 S O A 的 A q u a L o g i c 系列产品,B E A

Oracle、微软这样的“狮子”出现,大力

品,都为BEA赚足了面子,在各项评比中

WebLogic RFID 产品系列,Realtime(实

倡导SOA,大有后来居上之势;最近,BEA

独领风骚,据统计,仅在过去的五年中

时) Server,SIP 服务器等。去年BEA收购

为了扩大其商业产品的影响力与使用普

BEA的产品在各大媒体的评选与基准测试

了几家比较大的公司,也会陆继推出一

遍性,大踏步发展开源(Open Source);

中,在卓越性和性价比方面已经赢得超

些其它新的产品和解决方案。比如

2006 年,BEA又正式推出了Blended战略,

过 60 个奖项。

Plumtree 的 Portal 产品,基于 JDO 的 kodo

提出“商业软件+开源=最适合的解决

2005 年 B E A 又推出了基于 S O A 的

产品(用于支持EJB3等),还拥有基于J2EE

方案”的混合策略,为开发和部署商业应

Aqualogic系列产品,Integration(集成)产

的通用开发平台,Workshop Studio 等。

用提供环境与支持。

品,Portal(企业门户)产品,ALDSP(以前

不论是 Tuxedo 还是 WebLogic系列产

2005年随着客户更高的需求,BEA又推出

BEA公司一直像一只轻灵矫健的羚羊

的Liquid data,现在叫AquaLogic Data Ser-

了客户服务、员工自助服务、无线射频识

在草原上奔跑着,不断给我们带来新的

vices Platform)、SIP Server、Realtime

别(RFID)、WebLogic 服务交付及机构交

技术和好的产品。而这种不断创新的技

Server,以及 Plumtree 的 Portal 产品。

易管理等在内的五个解决方案基础框架。

术和不断适应市场环境的企业发展模式,

22

程序员

论产品线 ,BEA 没有IBM 软件的长 ,

单 IBM WebSphere 一条线就可与 BEA 的

青睐那些有准备的人 ”。

WebLogic 一比高下;论公司规模,BEA

的软件,它们希望在提供软件的同时还
能够得到来自软件公司专业的咨询服务。

解决方案:
另辟蹊径,延长业务线

因为相比于一家企业而言,软件公司面

“软件帝国”之称的微软。但如果单把

如果说过去BEA很长一段时间在描绘

积累了更为深厚的经验,而这些经验对

中间件拿出来 ,
“羚羊”跑在了这些“狮

那个可口的面包,现在它正在让这些期

客户应对变幻莫测的市场是弥足珍贵的。

子”的前面。据《IT产品和服务——2005

待变成现实。

正是看到了这一市场,BEA在2005年一口

比 Oracle 也小了很多,Oracle 当年有收
购 BEA 的气魄;论名气,BEA 也不及有

对的是整个行业,在长期的发展中,它们

年第4季度中国中间件软件市场数据报

2005 年一整年 ,BEA 的市场销售人

告》显示,BEA 公司以25.3 %的市场份

员都似乎陷入一个面粉与面包的故事

无线射频识别(RFID)、WebLogic 服务交

额领跑中国中间件市场。正因为BEA 业

之中了。“从应用角度来讲,任何一个

付及机构交易管理等在内的五个解决方

务线单一或者说专业,所以它能轻灵

软件产品都好像是面粉,但是如果你

案基础框架。

地像羚羊一样快捷地飞奔 。所谓“术业

想吃到可口的面包,中间还需要一系

经过一年的发展,BEA的解决方案框

有专攻”,BEA 在自己的领域内,不求大

列的加工过程,解决方案框架扮演的

架业务有了长足的发展,为了扩大在中

而全,专业做自己最擅长的事

气推出了包括客户服务、员工自助服务、

国的业务,BEA与其合作伙伴一起在

情,终有所获 。10年前,BEA

中国设立了多个解决方案

从 N o v e l l 手中收购了

中心。如果说过去BEA很

Tuxedo ,想必它自己也没

长一段时间在描绘那个

有意识到这款软件会给

可口的面包,那么它现在

自己带来如此多的殊荣

正让这些期待变成现实。

与收获。而1998 年并购的

以RFID解决方案来说,为

WebLogic 产品,经过多年

了充实这一框架的工具

的发展,现在也已经具相

箱,BEA 斥巨资将业界颇

当 规 模 , 从 单 一 的

有名气的 RFID 中间件技术

WebLogic Server 应用服务

提供商ConnecTerra收购,从

器产品发展到了现在包括开

而有效地解决了基础框架通

发平台(WebLogic Platform )、门户

就是这个加工过程的角色。”这个比喻

(WebLogic Portal)、整合(WebLogic

确实有趣也很恰当,解决方案框架是

Integration)在内的等一系列产品。频

BEA在过去一年多来一直努力推广的另

繁的收购让BEA在高端事务处理应用和

一条业务线。

应用服务器市场上得到快速增长,而

对生产IT应用产品的企业来说,任何

BEA正是凭借自己在中间件领域独特的

一个行业的应用都变得越来越复杂化,

眼光,不断揽入机会 ——而“机会总是

企业也不再满足于单纯购买解决点问题

常被人们认为是“花架子”的形象问题。

SOA:
公司不断前进的技术源动力
只要持续不懈的努力,最终会获得
成功,不要轻易放弃。
现在,除 BEA外,IBM、Oracle、微软

大事记

1995 年
BEA 公司成立
1996 年
收购 Novell 公司的 Tuxedo 产品
1997 年
收购 ObjectBroker 和 MessageQ
1998 年

并购WebLogic,发布WebLogic Server

1999 年
发布 eSolution
2000 年
推出 Enterprise JavaBean 2.0
2001 年
发布 WebLogic Integration
2002 年
营业额突破 10 亿美元

2003 年
BEA 中国研发中心成立
2004 年
推出 Beehive Project 开源项目
2005 年
BEA 十年,推出 AquaLogic系列产品
2006 年
发布 Workshop Studio 3.0

Programmer

23

人物&报道

Character & Report

报道 >>>

Workshop 产品,组合推出了 BEA Work-
shop Studio 这一面向J2EE的开发环境。在
不久前举行的EclipseOne大会上,Workshop
S t u d i o   3 . 0 就凭借其能够将 T o m c a t 、
JBoss、Resin甚至 IBM的WebSphere等开源
软件方便地集成应用而荣获了“最佳商
业开发工具”的称号。
最近,BEA又开放了关于Java持久性
API部分的Kodo源代码,该开源项目称为
Open JPA。BEA 开放这一宝贵的源代码,
不但大大扩展了混合开发模式,更表明
了 BEA 在开源领域的坚定决心。

和 SAP 等厂商都在提 SOA 的概念,但能

供更完整的解决方案。为扩大自己对开

BEA这只羚羊始终在奔跑,永远都冲

明显看到的是各家都是站在自己的角度, 源的影响,很多商业的软件公司如 BEA、

在前面。无论前面的路程如何,但可以肯

所提的概念也各不相同。虽然BEA与竞争

IBM 等也加大了对这一领域的支持力度。

定的一点是——它将在理念、技术、产品

对手一起都推出了 S O A 的实质性产品,

商业公司的支持很重要,但并非是开源

上面给我们带来更多的新东西!

但绝大部分客户仍旧持观望态度。况且,

社区必须依靠这一支持才能够发展。经

有时企业要实施 SOA就意味着将此前建

过多年的努力,全球开源社区现在已经

立的系统推倒重来,如此折腾起来,其成

形成了一种良好的自循环体制。Spring 是

本对一个赢利颇高的企业来讲,也是需

这种体制下的产物,现在占有了Java软件

要谨慎考虑的。所以也就有了“SOA是一

开 发 领 域 在框架方面的大部分市场 ;

柄高悬的达摩克利斯之剑”的说法。

JBoss 也是,抢走了商业应用服务器领域

从提出Liquid Computing 再到现在的

的大块市场,虽然最近它被 Redhat 所收

Think Liquid商标,BEA逐渐确定了自己的

购,但这不妨碍它依然是一个成功的开

行动方向,那就是尽管 SOA 是一个高风

源软件。成功的开源模式层出不穷,商业

险的领域,也要坚持以SOA为本,这一气

软件公司从这儿感受到越来越多的压力。

与开发人员一起成长
dev2dev 社区(dev2dev.bea.com.cn)
由 BEA 推出的 dev2dev网站是业界较有
影响力的中间件相关技术交流平台 。秉承

魄着实让人钦佩。付出总会有收获,在连

面对这一形势,BEA 推出了“Blended

续几年的Garnter Group 调查中BEA都是企

Strategy”。“Blended”的中文含义解释为

Developers,For Developers)的原则,dev2dev网

业部署 SOA 的首选品牌。而羚羊毕竟是

“混合”,其实在业界这已不是一个新鲜

站致力于向开发人员、架构设计师、IT 管理

羚羊,奔跑是它的天赋,2005年,BEA又

的词汇,只有 B E A 是旗帜鲜明地把

人员,提供最新的技术、信息和资源。dev2dev

率先推出了方便企业生产、部署 SOA的

“Blended Strategy”提出来作为自己的产

产品—— AquaLogic 系列产品。

在最新的 Workshop Studio 3.0 里,

网上社区是软件开发人员在线交流,分享经
验,解决难题的互动平台。

品宣传口号。而对于“混合”的定义,BEA
有自己的解释——“混合开发是将开源

开源:来自第三世界的压力

B E A 的“源自开发者 ,为了开发者”(B y

软件与商用软件混合在一起,更有效地
开发出满足应用需求的解决方案”。举个

BEA User Group
BEA User Group 是由 BEA 公司支持,由
广大对BEA产品和技术感兴趣的软件开发人
员自发组织起来,线下定期进行技术交流的

Tomcat、JBoss、Resin甚至 IBM的 WebSphere等

简单的例子,很多应用WebLogic Server产

都可以方便地集成应用。

品的公司,同时也在应用Spring 框架,最

了长足发展,自2004年在北京成立第一个组

终的系统是商业产品与开源框架的结合。

织以来,已经开展了十余场活动。其影响范

开源的飞速发展,使得任何一个企
业或者从业人员都不敢轻视。商业软件

为了使自己的“Blended”更加具有说

已经不再是开源世界的敌人,很多情况

服力,BEA通过对另外一个著名的开发工

下他们竞合在一起,各取所长为用户提

具 M7的收购,再加上其原来的WebLogic

24

程序员

活动团体。目前 BEA User Group 在中国得到

围也从北京发展到了上海、青岛、杭州、天
津、广州等城市。
■  责 任 编 辑 :贾 菡  (jiahan@csdn.net)

用程序解析天文
—— SourceForge 最佳推荐项目
□ 编译 / 刘洪洁
 SourceForge.NET是目前影响

空,就像你能用肉眼、双目望远镜或普通

完善的星座目录 (tycho 2) 和望远镜控

最为广泛的开源项目网站,每个月都会

天文望远镜所能看到的一样。
 即便是对于

制。 当我发现7.1版并不具备我所寻找的

从成千上万的项目中评选出一个开源项

那些对天文学毫无兴趣的人来讲,它也

这些东西时, 我决定自己研究人造卫星的

目,授予其每月最佳推荐项目的荣誉。今

是个很有趣的软件。

位置。很感谢Fabien 让我加入这个团队。

年 5月sourceforge.NET的最佳推荐项目是

你为什么编写这个软件?

Stellarium。

是如何开始的?

项目描述

有哪些特定的用户?
每一个对夜空充满好奇的人,还有

Fabien: 一个夏天,我在我父母的住

那些想从计算机中寻找乐趣的人。业余

Stellarium 是个天文学软件,它是免

处偶然发现了一个在线星座目录,之后

的天文学爱好者把我们的软件用于观察

费的、开源的。通过使用这个软件,你可

我就开始用 C + + 编码。我想知道使用

夜空:教师们以及专业的天文学家们把

以在电脑上看见一个立体的、现实的天

OpenGL 能在我的旧Voodoo2 3D立体卡上

它用作教学的辅助工具;一些专业的天

做些什么。

文馆会把它用在比较大的项目上。

Stellarium 项目团队介绍:
项目领导者:

Robert: 在 2002 年的时候,我想发明
一种相对廉价的天象仪,并且它具有一台

你认为有多少人在使用你的软件?

先进的天象仪的全部功能。我有一部低倍

在新版本发布以后达到了一个使用

的针孔投影仪,其功能十分有限。我需要

的高峰。去年三月份我们的月下载次数

      程师,现在致力于 ESA

一种可以根据需要定制和升级的天文软件

第一次突破 10 万,我们大概拥有超过50

       人造卫星“GAIA”
的研究。

来植入这部仪器 (Digitarium  Alpha),但

万的使用者,但是能从中受益的人绝对

教育经历:法国里昂国立应用科学学

是如果自己研制的话,恐怕我难以支付昂

不止这个数量。几乎每个学校都会使用

贵的费用。很幸运,我在Stellarium中找到

我们的软件,因为它免费、功能很强大并

了我正在寻觅的真实感,它有一个直接的

且易于使用。

Fabien Ch é reau
年龄:25
职业和经历:巴黎天文观测所研发工

院,计算机科学专业。
所在地:法国巴黎
主要开发者:
Johan Meuris
Johannes Gajdosik

接口, 而且是开放源码的。最终我成了
Stellarium 的主要开发者之一。
Johan:我是在2004年加入的,当时这

能不能举几个典型的例子说明人
们如何使用你们的软件?

年龄:36

个项目正在寻找免费的星座图画,我非

夏威夷的研究中心使用Stellarium 探究

职业:软件开发人员

常希望自己可以对西方天文学奇迹般的

远古的夏威夷星座,巴黎天文台的天文学

教育经历:数学专业博士

景象做一个描述。目前我在制作网页中

家们用它来进行天文学的授课,还有许多

所在地:奥地利维也纳

找到了自己的价值,我的工作是根据程

教育学家把Stellarium 用在数字天象仪上。

序的需要增加漂亮的图解,因为我不是

你可以在www.digitaliseducation.com网站

一个程序员。

上找到安装了 Stellarium 软件的天象仪。

Robert Spearman
年龄:32
职业:Digitalis Education Solutions

Johannes: 自从 5.0 版问世以后,我

还有一些人自己设计了圆顶室,并且通

教育经历:经济学学士

被夜空的美丽景象吸引住了。很长一段时

过球面镜来设置景象,他们相当于拥有

所在地:美国华盛顿,布雷默顿

间里我都在寻找人造卫星的精确位置、
 更

了自己的虚拟天象仪。法国有个艺术家

公司总经理

Programmer

25

Character & Report

人物&报道
报道 >>>

想把它放在博物馆的多媒体设施里,让

人告诉我他们是如何找到这个不错的免

Johan: 人们只会在自己感兴趣的事

天空和大海的影像共同出现在前景中。

费的天文软件的。从某一时刻起,我收到

情上付出真正的努力。最近,这种现象发

我甚至听说有人想把它安装在电梯里。

更多的电子邮件,以至于我没有时间一

生在开源网站上的 Stellarium 上了,这是

一回复。

一种神奇的用户向导,它不仅仅对程序

是什么让你们意识到这个项目越
来越成功?

本身进行了解释,同时也解释了许多天

曾经最令你们吃惊的是什么?

当 S F 上的统计数字开始增长的时

Fabien:当我发现许多人已经由于工作

候,我们就得知事情进展得很顺利。现在

的需要而使用 Stellarium 软件的时候,我

我们收到了很多采访的邀请,还有一些

很惊讶。事实上这个项目一直都是我的

人想把我们的软件发布在杂志上。好多

嗜好。

文学的概念。
Johannes:Stellarium 已经成为了
SourceForge的 POTM。
R o b e r t :我最惊讶的是,听说过
Stellarium 的教育工作者如此之少,更糟
糕的是,好多人都说他们的学校根本就
不开设天文学课程。让更多的人来了解
这个软件吧!

曾遇到的最大的挑战是什么?
Fabien:在实时内进行一些计算,如物
体位置和天空的发光度,以满足在时间
和空间上的自然衔接。
Johannes:在球面镜透视天象仪中,
出现了球面镜的透视 / 扭曲。
Robert:在时间很紧的情况下进行大
量的代码修改。支持 Windows。

你认为为什么你们的项目已经得
到了大家的普遍认可?
Stellarium界面美观、功能强大、简单
并且实用。对于大多数人来讲易于理解,
随着版本的升级,这种优势越来越明显
了。它非常易用,并且能为你提供更高级
的帮助。很关键的一点是,它是免费的。
一些所谓的专业软件会比较难用,因为
对于普通的初级使用者来讲,它们具有
一些无用的功能。相比之下,Stellarium更
现实、更直观、更稳定。我们在传播天文
学的基本知识,这些知识对于每个人来
讲都很有用,并且我们在用一种引人入
胜的方法来传播。
在每次新的版本发布中我都会发现
重要的步骤。对于目前的版本发布,我们
或多或少在性能的限制和使用的方便性
上做了改进。我希望我们可以在这两个
方面保持平衡。增加新的性能将意味着

26

程序员

增加可用性。在 0.8.0 版本中最新的东
西就是国际化,因为让用户用母语使用
这个程序是十分必要的。在扩大软件应
用范围这个方面,开发者已经清除了一
个很大的障碍。

你们最引以为荣的是什么?
Fabien:我们的项目能用于对孩子们的
科学教育。

所需要的工作时间最少。改写网页,制作
新的布景,或者安装一个wiki,都是非常
迅速的工作,如果需要我做的仅仅是浏

Johan:我在业余时间为Stellarium做设

览技术支持需求或者浏览论坛,我每周

计,最大的收获莫过于我自己对星座更

大概只会花两个小时或者更少的时间。

加熟悉了。这是我做过的影响最广泛的

你们对这个项目有什么期望?
Fabien:为了使它实现真正意义上的多

工作,因为这是一个开源项目。对于一个

你们的开发环境怎么样?

学生来讲,这是非常让人开心的。

Fabien:我用装有LINUX操作系统的笔

语种应用,我花费了很长的时间。我试着
让它适当地支持 gettext,让代码支持多
平台应用简直就是个噩梦,但是现在这
成为了现实!

记本电脑,主要的开发工具是 Kdevelop。

如果可以对这个项目做一些修改,
你最想改变的是什么?
我希望GUI接口更加灵活。我们现在

Johan:我在 W i n d o w s 环境下使用
Wacom画板进行大部分的图形处理工作,
但是最近我在 Ubuntu部分安装了 Inkscape

Johan:我想知道关于星座的其他解
释,要比我们所谓的“天空文化”更完
全。西方关于星座的解释是众所周知
的,但是还有不同的解释,比如来自中

Stellarium 界面美观、功能强大、简单并且实用。对于大多数
人来讲易于理解,随着版本的升级,这种优势越来越明显了。它
非常易用,并且能为你提供更高级的帮助。

国的,波斯的,或玻里尼西亚的看法。地
球另一端的人们是如何认识这些星座

所使用的接口,在某种程度上,是手动

的?他们的看法会为我们提供一个新的

的、静态的。很遗憾,目前我还没有找到

视野。我可以帮助其他的开发者为这些

一种更好的替代品。我还希望做一些可

观点配以图解。

用性说明,对于任何产品来讲,易于使用

我还希望有更多的途径进行配置选

都是最重要的。

择。在一个文本文件中保存着一些有趣
的设置,但是这个文件是只读的,许多用
户被这个问题所困扰,我想他们会很乐
意使用一个更完全的 GUI 接口。
具体的功能如卫星追踪、彗星、X 射
线识别,以及晒片等会非常不错。

作为 SVG 编辑器。

里程碑
这个月我们将发布 Stellarium 0.8.0
版本,它将包含 20 多种语言的翻译,以
及在行星的计算和预测方面的重大改进。

你是如何协调这个项目的?

这也是一个对主要代码进行重组的开始。

这是个自由的工作,所以我们没有
受到任何真正意义上的限制。故障是用
来让人排除的。我们需要一些可以发现
故障并且解决故障的人。

Johannes:对火星大气层的探究,外

其他人可以为你们做些什么?
我们需要开发者们协助处理一些故
障,改进GUI,并且协助进行Windows 和
Mac OS X 操作系统的简化和测试。我们

星/人造卫星的景象,对于小发光体的可

你们是全职做这个项目,还是同

还需要图形专家来创造一些景观和星云

靠描述(mag[-4..-20]),不变形的平滑

时有其他的工作?

的图片,我希望更多的用户能把他们的

的线,tycho2,更迅速的计算,多线程支
持,海王星的人造卫星位置推算,精确的
行星运行轨道,光的传播时间,小行星,
以不同的放大倍数显示多窗口,望远镜
控制,应用多个投射器对天象仪进行多
屏幕甚至多机支持。
Robert:更多种类的语言翻译,在更
多的部件中加上GUI接口。既然我们在创

我们都有工作,或者像Johan的情况,
他还是个学生。
如果兼职做这个项目,你每周在这
个项目上投入多少时间?

以及定制内容放入 Stellarium wiki 中,我
们最希望得到的是来自远古的景象,比
如巨石阵、吉萨和玛雅的遗迹。

Robert:根据具体情况而定,有时候

我们需要有人帮助我们记录这个程

会投入比全职工作还多的时间,有时则

序。我们需要有人帮助我们翻译程序、网

非常少。

页和文件。我们也十分感激论坛上的祝

Fabien:平均每周6-7 小时,
下雨的时候

造脱离地球的视点,那么就有必要用更

会达到最长时间(巴黎的冬天经常下雨)。

多的环、阴影和遮蔽技术来增加它的真

Johan:根据项目的进度而定。我在这

实性。

经验、小工具(景观、脚本和星云图片)

个团队里拥有最舒服的职位,我的职位

贺信息,尽管我们没有时间一一回复。请
在SourceForge的论坛上给我们留言吧,我
们一直都在关注着你们的评论。
■  责 任 编 辑 :贾 菡  (jiahan@csdn.net)

Programmer

27

Character & Report

人物&报道
人物专访 >>>

目的明确地进行系统开发
—— Chuck McManis 谈专用系统
公司来说是可怕的一年。2001年 8月,我
谈到专用系统,人们很容易只想到高曝光度的
消费品,如 iPod和 TiVo。然而,在公司阴暗的数据
中心还躺着许多不那么光鲜漂亮的设备,这些设备
专为可靠出色地完成某一特定任务而制造。
在专用系统开发领域,没有其他工程师比
NetApp(Network Appliance Inc.)的Chuck McManis

离开了 Tut 加入 Network Appliance 公司,
开发提供存储服务的全新架构及模型,
同时还为采用该架构的消费品设备进行
系统架构开发。这项工作促成了 NetApp
在 2002/2003 年收购 Spinnaker Network,
这成为了 NetApp 公司下一代系统的基础
架构。

更 有 经 验 了。加入 NetApp 公司之前,McManis 任
职于 FreeGate公司。该公司由 McManis 与 两 位 同 事 共 同 创 建 ,针对中小

GN-N:您在 FreeGate 使用当时已有的

企 业 市 场 开 发 嵌 入 式 服 务 器 装 置。2001 年 McManis 加入 NetApp 公司,

软件进行装置开发,与您目前在 Network

担 任 高 级 技 术 总 监 ,负 责 推 动 可 伸 缩 性 的 开 发 计 划 。在该职位上,他广

Appliance公司进行的装置开发有什么区别?

泛参与了 NetApp 公 司 针 对 企 业 及 中 小 企 业 用 户 的 NAS(网络附加存储)

CM:非常相似,开发这些装置给我

装置产品线开发。
“我 们 不 是 服 务 器 公 司 ,而是装置(appliance)公司。”

留下的一个深刻印象是 ,您经历的整个

McManis 急于提醒我们。

开发过程和所有应用程序开发相同。基

George Neville-Neil 采访了 McManis。George Neville-Neil 还以编写

本上您都有一个具备某些功能的开发平

网络及操作系统代码为乐,并从中获利。Neville-Neil对专用领域并不陌

台。如果您使用现成的开发平台,那么

生,他有着 1 0 年 多 从 事 嵌 入 式 系 统 开 发 的 职 业 生 涯 。他还和 Marshall

您有几种独立平台可以选择,而不是选

Kirk McKusick共同编著了The Design and Implementation of the FreeBSD
Operating System 一书,该书由 Addison-Wesley Professional公司于2004
年出版发行,他还参与了 FreeBSD 的开发。

择某些单独的功能,获得的是几种功能
的集合。
在FreeGate和NetApp公司的开发过程
中,我们都要进行定制。在FreeGate公司,
定制需求主要涉及到尺寸。我们希望主

GEORGE NEVILLE-NEIL:您在装置开

过于昂贵。FreeGate Gateway装置允许在

板小巧紧凑。在NetApp公司,我们希望拥

发领域,有着丰富的经验。可以告诉我们

企业电话室内使用内置的 ISDN 连接或者

有比传统 x86 个人电脑更多的 I/O 端口。

您是如何领导 NetApp 公司的吗?

T1/E1 连接来进行远程管理(LOM)。该

总的来说,许多第三方厂家精于制造拥

装置提供一整套网络 P O P 邮件、W e b、

有标准个人电脑功能的主板,因此我们

以前曾在 S u n 和施乐公司任职的 J e a n

FTP、DNS、向外VPN、NAT、防火墙,以

拥有众多选择。如果您公开宣布:
“我需

Gasinel 和 Jean-Marc Frailong 一起成立了

及向内NAS功能。当时我担任系统开发总

要有两个以太网接口、六个端口、六个驱

FreeGate公司。当时,试图网络化的小公

监,后来又成了首席架构师,从公司成

动连接器的主板。”许多厂商都会积极地

司面临许多难题,这些难题对于非技术

立,一直干到 2000 年初被 Tut System公

对这种 RFP 需求做出响应。

性的公司来说难以解决(比如小比萨店),

司收购。

CHUCK McMANIS:在 1996 年,我和

同时,向网络服务商(ISP)寻求帮助又

28

程序员

DSL 市场崩盘之后的2001年,对TUT

从软件开发角度来说,90 年代开源
软件运动才刚刚开始。Linux 内核不如现

在庞大,还在继续发展。该行业很少有人

获得一系列标准核心协议,为我们提供

行设置。几个小时后,装置开始运行,这

来自 Sun 和 HP 等有着相关技术背景的系

了所需数据。CIFS 的开源版本是 Samba,

并不是传统模式。

统公司。但是现在在 Network Appliance,

我肯定您对它非常熟悉。一直以来,微软

当我们进入市场的时候,传统SAN供

我们可以找到一些刚毕业的大学生,他

都威胁Samba将指控其专利技术侵权,或

应商(也就是当时的EMC公司)在出售的

们却已经进行了五年的内核开发。

采取其他行动。我们对此也有异议。产品

设备上安装了大量的外部旋钮,您自己

开发需要花费大量时间及资源,如果公

无法进行设置,需要专业人士为用户进

GN-N:就您正在开发的软件平台而

开源代码危及投资,您的确不会希望这

行设置。

言,您最终使用了多少开源软件?进

样做。我们一直积极地为使用过或参考

行新装置开发时,您同时使用哪些软

过的现有开源系统提供共享的更正。我

种模式已经被Linksys公司发挥到了极致。

件呢?

们活跃在 NFS(网络文件系统)社区,帮

Linksys 生产通过 USB 连接的小型网络附

助Linux开发人员开发企业级NFS客户端。

加存储盒。您只需要把设备插上电脑,打

CM:我想有 40% 来自于外部获得的
源代码,60%来自公司内部开发。此外,

同样,我们的操作系统由中断服务

这个比例和我在FreeGate公司时的情况一

例程(interrupt service routine)演化而来,

致,这主要是因为在过去 15 年里,少数

只适用于存储装置开发,因此不需要公

诸如 TCP/IP 堆栈之类的事物,除了增加

开源代码。

了 IPv6 之外,并没有什么真正的变化。
而在其他方面,如微软的磁盘共享
协议CIFS (common Internet file system),
没有对应的开源代码为我们提供满足客
户要求的功能,因此我们几乎是重新内

开Web浏览器门户,就可开始使用了。一
切就是那么简单。这就是简化。
尽管我想您有这样的疑问:使用基
本上与每天重启的个人电脑相同的硬件,
如何实现 99.999% 或者 99.9999%的可

GN-N:当然,那些从事存储装置开发
的厂商也是你们的竞争对手。
CM:对。我肯定 EMC 公司倒是乐意
看看。

部开发了自己的 CIFS 堆栈。
总之,我觉得开源代码利弊参半。一

这种装置模型非常直接。说实话,这

靠性。答案是,硬件并不相同。我们使用
服务器芯片组,以及Intel、AMD以及硬件
专业人士心目中的服务器级设备,而不
是这些公司物美价廉的产品。两者区别
在于内部错误检测量及可设置PCI总线的

GN-N:Network Appliance试图对于所有

数量不同。此外,我们在软件数据保护上

方面,您也许能够抢占先机。另一方面,

专用设备提供 99.999%的可靠性,或者

投资巨大,通过系统内检测码验证,数据

由于代码被控制范围之外的人员修改,

99.999 %的正常运行时间。系统必须随

在从磁盘传输到网络端口的过程中,没

您只能是拾取一点进行修改,保留代码,

时正常运转。您不希望像管理传统BSD或

有遭到破坏或任何形式的修改,从而保

并使之稳定下来,或者聘请人员来吸收

Linux 机器一样管理机器。您必须对现成

护用户数据。

所有更新。如果您正在从事嵌入式装置

软件做多大修改才能实现这一目的呢?

开发,使用诸如Linux或者FreeBSD这样的

CM :我们进行了大量的工作,我要

开源系统并不会给您带来多大好处。

CIFS
GN-N:当您试图实现CIFS时,是否会

零管理

说从第一天开始我们的核心价值观念就

GN-N:与此相关的是零管理目标。同

是简单明了。内部开发系统,判断出哪些

时使用现有软件及自行开发软件对于实

磁盘已经连接到系统,利用这些磁盘构

现该目标有什么挑战?

建RAID阵列,然后再在系统中显示出来,

CM :在系统开发上,我们通过不使

将开发结果加入到开源代码库,以确保

这个过程相当复杂。但是所有复杂问题

用任何现成软件的做法来解决这一难题。

其仍为核心系统的一部分,还是不向外

都针对用户以简单明了的方式进行了封

我们的管理系统完全由公司内部重新编

公布?

装,用户可以根据卷和协议与我们的装

写,部分原因是没有类似于 H e w l e t t -

置进行对话。

Paclard OpenView 这样的系统。作为允许

CM:嗯,视情况而定。一直以来CIFS
面临的问题是,微软从来没有真正认为

因此,当您购买了NetApp装置之后,

插件的开放模式,HP OpenView允许他人

CIFS是开放协议。在早期,我们完成的大

打开装置,您只需要说:
“创建卷”,您就

插入网络管理代码,但行业标准开放存

多数 CIFS 开发都是对网络观察的逆向工

可以创建一个卷。默认情况下,该装置将

储管理系统的开发还是一团空白。

程。我们会说:“哦,那一定是它的工作

选择最佳方案,对所有连接的磁盘进行

但是,我们正在采取一些行动。我们

方式。”

划分,并保存多余空间。这也是我们主要

参加了一个名为 SNIA(存储和网络行业

的优势之一。顾客购买我们的设备并进

协会)的组织,提供一套称为 M a n a g e

后来,Network Appliance从微软授权

Programmer

29

人物&报道

Character & Report

人物专访 >>>

ONTAP 的API,以便使我们的客户,尤其
是非常关注自动执行脚本编写的大客户,
能通过脚本控制文件管理器上任何想要
的设置。
我们发现公司在一定时期会出现分
化。一开始,他们只有系统管理员,当发
展到一定规模后,分化出存储管理员及
数据管理员。存储管理员关注何种存储
硬件在数据中心运行,如何修复问题,
如果诊断健康状况,以及如果扩展存储
硬件。
数据管理员实际上是 D B A 的助手。
这些人或部门主管会说:
“我们需要增加
6TB 主目录空间”或“这个数据库将会达
到 600GB”。他们对数据中心资产负责,
也是联系存储管理员及任何终端用户的
他只知道这 27 个文件管理器用于此类存

纽带。

准确的时间信息。

我们花费了大量时间为这两类人群

储,因此他们喜欢称之为基于策略的管

因此,随着事情不断发展变化,Data

提供管理工具。但是,我要说我们花费的

理,而不是基于个体物理性质的管理。这

ONTAP 也随之不断发展。整个内核只有

大量精力都全部用在了存储管理上。由

很合乎情理吧!

约 50,000 行代码,非常小巧。我想您一
定在大众媒体上见到过许多相关报道,

Louis Selincourt总监领导的整个团队都只
GN-N:是的,有道理,但我希望能更

随着我们向存储网格架构的转变,我们

另外,存储管理从我们一开始研发

进一步了解。我想寻根究源问一下整个

有机会使用开源系统为用户级工具开发

便发生了实质性的变化。在过去,100TB

操作系统层都是您完成的吗?或者你们

提供主机环境。当我们的处理器资源能

的存储量已经非常巨大,而现在我们的

实际上使用的是普通的 Linux 或 BSD 操作

够胜任这些任务时,我想我们及其他公

一些用户存储量达到了 20PB 和30PB。当

系统吗?

司会更多地这样做。

进行存储管理开发。

您部署如此海量的存储时,个人用户不

CM:不,实际上,Data ONTAP 完全

可能了解所有信息的存储位置,谁拥有

是公司内部重新开发的操作系统。有意

这些数据,或者谁需要这些数据。这也是

思的是,该系统由中断服务例程(interrupt

GN-N:那些从 FreeBSD 或 Linux开始开

为什么这些工具对于存储管理员管理所

service routine)演化而来。在 NetApp 刚

发装置的人总有这样的疑问:
“必须去掉

有存储数据至关重要的原因。

成立时,文件管理器还相当简单,它所做

些什么才能正常工作?”我想,您无法通

在管理存储空间时,您会说:
“我想

的所有事情就是等待网络端口传来数据

过 syslog 来运行文件管理器。

要真正高速的磁盘”,而不是“我想要用

包。得到数据包后,文件管理器被唤醒并

CM:在 FreeGate公司,我们实际上一

这六块与 RAID 阵列相连的磁盘为这个人

执行数据包所有指令,完成之后又重新

开始使用的是 Linux,但是Linux发展太迅

建一个卷 。”我们公司的存储应用程序

进入休眠状态。这实际上就是中断服务

猛。众多 Linxu开发人员和频繁的更新让

DFM(Data Fabric Manager)让用户可以

例程功能。

我们很难获得稳定的开发环境。因此我

FreeGate

随着文件管理器功能的增强,我们

们转而使用FreeBSD 2.0和2.1,并取得了

继而该程序会判定哪一个现有文件管理

认为需要开发同时执行其他任务(比如

不错的成果。我们让代码稳定下来。去掉

器上拥有高速磁盘。

DNS)的能力.目前,我们的文件管理器

了多余的部分,得到了一个理想的精简

完成的任务之一就是运行网络时间客户

操作系统。但是,我们发现仍无法跟上

而开发的。存储管理员并不关心您的数

端,进行计时,同时执行按照时钟同步。

FreeBSD 社区的更新速度。FreeBSD社区对

据存储在27个文件管理器中的哪一个上,

比如,进行软件开发的人希望提供非常

漏洞进行修正,并增加新功能。

发出指令说明您希望创建真正高速的卷,

该功能主要是针对大容量存储客户

30

程序员

作为刚起步的小公司,我们无法在
保证整个系统正常运行的同时,及时增
加这些更新。
因此,当我们开始出售 F r e e G a t e
Gateway 产品时,我们主要选择的内核是

程序由用户决定。
一台装置实际上完成单一任务,或
某一类任务。若要完成多进程任务时,线

在内核空间内进行。本质上来说,用户进
程并不存在。它们仅仅是服务的延伸,只
是模式不同。

程数也和装置正在执行的一项任务的实
例数有关。

GN-N:那带来了一个有趣的问题。您

2.1 到 2.8 版本,并且不提供更新。实际

因此,就Solaris而言,您也许根据您

也许会开始从外部添加诸如网络时间客

上,我们没有增加新的处理器,也没有进

支持的用户数或者您允许这些用户运行

户端和CIFS这样的复杂服务,或者增加装

行任何其他增补,因此也不需要更新。当

的最大型应用程序来决定所购买Solaris的

置运行所需但又通常不被视为装置组成

FreeBSD 升级到版本3和版本4时,我们出

版本。Solaris很多功能可以为不同应用程

部分的子系统。在服务器系统中,子系统

售的还是 2.75 版本之类的产品,我们觉

序提供服务。每次登录Solaris,您都可以

也就是一个应用程序。您想要运行NTP监

得这样做并没什么不妥。

获得一个可以执行您所有命令的小环境。

控程序。您想要运行CIFS监控程序。那么

您拥有一个应用程序目录,每次您

如何在装置内解决这些问题,同时确保

GN-N:我想这是非常常见的模式。根

输入Go Oracle,Solaris就会开始装载该程

据我对嵌入式系统的了解,人们会开发

序,转变到 Oracle。然而在存储装置(或

CM:为了实现高速高效,我们通常使

一个装置盒,并且决不会进行任何修改。

者任何其他装置中),它只执行一项任

用单一名称空间。用户可以传递工作指

如果要升级,他们就会作整体改变。

务。就我们公司而言,我们只执行存储

针,这些指针可以在系统内任何位置发

任务。当您执行“登录到装置盒”时,您

挥作用。好的方面是,如果您拥有兼容

实际上并没有真正登录。您所做的只是

Posix 的 API,或者 UNIX Libc 界面,在您

GN-N:是的,完全正确。

向它发出一项服务请求,即要求存储数

的装置操作系统中是运行用户进程还是

CM:它们不是服务器。我常常提醒别

据。您想要装载主目录,或者打开一个

轻量级线程就并不重要。

CM:这些装置盒就是客户端,对吧?

人,我们不是服务器生产公司。我们是装
置公司。

LUN。

彼此没有任何干扰呢?

关键在于,代码中的漏洞将会带来

因此,您真正会有与LUN或者主目录

系统问题。由于只有我们的代码可以调

对话的多路径或者多实例,但是您并不

用内部服务,因此您可以清楚地知道该

GN-N:您想表达一个什么想法?

是要在装置上执行不同任务。在服务器

服务运行的每个代码路径。因此,您可

CM:计算机服务器围绕着程序运行能

操作系统中,用户登录系统,成为一个小

以检查您将使用的服务是否真正地正常

力而设计。内核及库为服务器提供大量

实例,因此所有任务都在用户空间中发

运行。

可通过程序调用的资源,但是运行何种

生。但是在装置操作系统中,所有任务都

■  责 任 编 辑 :贾 菡  (jiahan@csdn.net)

带给中国企业客户更为强大的全新开发体验,

实验室,进行 System z 系列软件开发和相关测

以帮助他们应对当前开发环境下日益复杂且协

试。此外,IBM 还宣布增加 System z9 Enterprise

作化的开发挑战。

Class(IBM System z9 109)服务器新功能,以强

厂商直击
4 月27日,
“2006微软亚洲研究院创新日”
在北京举行,展示微软亚洲研究院多项技术研

近日,全球最大的信息服务公司IBM 与全球

化系统的业务灵活性。IBM System z9 Business Class

究成果。同时,微软公司高级副总裁暨首席技术

最大中文互联网搜索服务提供商百度共同签署一

新产品将大大降低大型主机的门槛,使中小型企

官 Graig Mundie 先生、微软公司全球副总裁暨微

项技术合作备忘录,协作拓展硬盘搜索的应用领

业也可以享受到大型主机黄金般的品质和不可替

软中国研发集团总裁张亚勤博士、微软亚洲研

域,并计划通过更多技术协作为客户带来更大价

代的核心作用。

究院院长沈向洋博士亲临现场,解答微软的创

值。该项合作由IBM 中国研究院与百度共同实施,

新内涵。

2006 年5月 10日,诺基亚移动应用峰会在

通过百度硬盘搜索与 IBM Lotus Notes 的集成, 使

西子湖畔杭州举行,本次峰会的主题为“智能移

 05 月15日,微软(中国)有限公司宣布,

百度硬盘搜索能够索引和搜索 IBM Lotus Notes 的

动应用和服务——新收入的来源”,旨在为来自

正式在中国推出 Microsoft Visual Studio 2005

文档内容,帮助用户从海量资料中快速地找到想

全球的诺基亚论坛PRO开发商和中国及亚太地区

Team Foundation Server 简体中文版。作为微软

要的信息,实现高效信息流通与企业协作。

的客户搭建高效的沟通平台。本次峰会的开发商

创新技术在软件项目开发领域的重要进展,

4 月 27 日,IBM 向全球正式推出专门针对中

展示了来自 IMS,多媒体,游戏以及效率优化领

Microsoft Visual Studio 2005 Team Foundation

端用户、具有突破意义的 IBM System z9 Business

域的创新应用。参加此次峰会的客户包括运营

Server 提供了众多的新增功能与特性 ,致力于

Class 大型主机。IBM同时宣布在上海建立一个新的

商、独立渠道商、内容集成商和服务提供商。

Programmer

31

人物&报道

Character & Report

观点 >>>

程序员创业三关
□ 文 / 韩磊
  当人们还在浩叹第一次网络泡

成败固然不足
以论英雄,然而英
雄却不得不面对可
能的成败。程序员
朋友们在创业的时
候,至少应该突破
三关, 才 算 做 好 了
基本的准备了,不
至于在两三年内大
量倒闭。

意。三大门户成功的要点,在于他们想出办法,

二个春天;从某种意义上看,甚至已经进入了

把流量转化为盈利模式。缺乏有效的模式,流

夏天——热烈但不乏浮躁、兴奋但失之肤浅。

量只是成本。确定有效经营模式、组建有力创

某位投资人声称今年总共有三十亿美金资本进

业团队,是首要任务。

入中国,言下之意,大家都可以甩开膀子大干

第二是管理关。从程序员变成管理者,是

快上,登陆纳市不好说,搞笔钱进来花差花差

艰难的过程。你得明白两件事:一、管理和写程

多半是没问题的。

序一样,是门科学;二、人和计算机不一样,人

另一方面,程序员创业,在中国乃至国外,

有感情、会出错。协调沟通能力,是程序员创业

都不是什么新鲜事儿。我们是那么一群聪明、

必备的素质。曾经眼见一些项目经理,
和手下技

优秀的家伙,大脑发达,点子就像啤酒的泡沫,

术人员通过邮件争辩不休,甚至发展到在Blog

扑腾扑腾直往外冒,天生我才,有什么做不到

上互相嘲讽,这样的管理,可谓彻底失败。另一

的呢?遥想比尔・盖茨当年,西装革履,谈

个极端是,和手下称兄道弟、一团和气,工作被

笑间,多少豪杰灰飞烟灭……

感情所左右,酒肉害了朋友。
管理有那么难吗?

于是我看到,无数公司成立了,眼看他雄

我看未必。只做对公司有利的事,就是根本原

心勃勃,眼看他一败涂地。成败固然不足以论

则。在和你的手下打交道时,请三思:我这么

英雄,然而英雄却不得不面对可能的成败。可

做,对公司有好处吗?对事业有好处吗?如果

惜的是,程序员朋友们在创业的时候,往往没

答案是否定的,那你需要另一个解决方案。

有做好充分准备。据一些资料显示,百分之七

第三是坚持关。一位多次创业不成功的朋

十五的新创公司,会在两、三年内倒闭。笔者

友告诉我,他总结了一条“三年定律”,即任

也曾经见过许多程序员创业失败的个案;成功

何事如果不能坚持三年,则一定失败。诚哉斯

或不成功,有很多因素制约;对于立志创业的

言!另一位朋友说,中国人相信机会,西方人

程序员,至少应该突破三关。

相信方向和时间,虽有些偏激,却也不乏道理。

第一是模式关。你的创业计划,也许起源

许多程序员都属于思维活跃、点子特多的一类

于灵机一动。可惜的是,好点子并不能保证你

人,当有新鲜的想法出来时,他们倾向于放弃

创业成功。我相信多数程序员的点子,尚不至

或冷落手上正在执行的计划。点子复点子,点

于低级到靠软色情、盗版、恶性SEO 等等下作

子何其多,每天新点子,万事成蹉跎。西谚有

手段去骗取广告费的地步,但怎么从点子变成

云,双鸟在林不如一鸟在手;吃到嘴里的鸭子

盈利模式,却是让很多创业者迷惑的事情。在

才是好鸭子,湖里那只鸭子看起来比较肥?也

一些业界聚会上,总听到类似“只要有流量,

许吧,不过,吃了这只鸭子再去涉水抓那只,

总有办法赚钱”之类的说法,在2000年持同样

是不是更有把握呢?

言论的创业者,多数已经成为失败的先烈,因

32

程序员

为他们始终没明白,赚现钱的生意才是好生

沫破灭的时候,互联网已经悄悄迎来了它的第

■  责 任 编 辑 :贾 菡  (jiahan@csdn.net)

Programmer

33

FreeBSD
Character & Report

人物&报道
观点 >>>

为什么 Linux 比 FreeBSD
    更流行?
□ 文 / 合钦桐
两者在应用程度上存在差异的原因是技术 ?还是开源协议? 这似乎都有些道理,
但实际上这些远没有商业追捧来得更直接。

 拿 Linux 和FreeBSD 对比是一件危险的事情,讨论

至今还是保持了程序代码的统一性。而 Linux的情况就不妙了,

的结果往往是引发一场更大规模的争议,挑起者往往得面对被

Redhat、SuSe、Caldera、Debian、Slackware 各自为政,安装方式也

人骂得一无是处的人生,以及内心狂流不止的鲜血,还得装出

是五花八门。用户如果应用不同的Linux,可能会遇见基于图形

一副无所谓的表情对自己说:“走自己的路,由别人去说吧。”

的安装界面、基于字符的安装界面等各种方法,同时,各个发

但如果我们真正去研究 2001 年或更早些时候的文献会发
现,在 2001 年社区力量相对弱小的 FreeBSD 一直想要做的就是
要超越处于少年时代的 Linux。这样看来,既然是超越,就可以
说早在 2001 年或者更早,Linux 已变得比 FreeBSD 更流行了。

行商之间的安装方式还有所差异。用户如果从一种Linux发行版
转到另一种 Linux 发行版,就可能需要学习一个新的安装工具。
FreeBSD是一个操作系统,而不仅仅是一个内核。而Linux只
是一个内核,注定会出现许多不同的 Linux 版本。
架构方面FreeBSD采用所谓的缓冲区缓存读取文件的方式,

Linux 与 FreeBSD 的技术差异
 Linux与FreeBSD在技术上的差异更多地源自于它们的身世,

而Linux采用向其中写入文件的方式。Linux始终自动管理缓冲区
缓存的大小,但其内存管理例程的工作方式与 FreeBSD的不同。

Linux的起源更多地包含了一种黑客精神,许许多多的Linux爱好

此外,几乎所有运行在 Linux 上的程序都有 FreeBSD的移植

者一直在给它加入新的特性。作为一个完整的系统,它还有许

版本。如果没有,FreeBSD上的“Linux Compat”特性支持可以

多GNU的东西。可以说,Linux真正的出生地是社区。与之相反,

让许多 Linux 程序如同本地程序一般在 FreeBSD 上运行。但类似

FreeBSD则由于其UNIX血统而纯粹是从理论团体中走出来的,就

于 Xen 等虚拟技术的崛起,正在削弱 FreeBSD 的这项特性。

算是日后经历了长期的社区发展历程,也没有洗去它身上浓厚
的学院派色彩,而且它的发展还和计算机研究部门联系非常紧

从社区的角度来看,FreeBSD开发模型小得多,但这并不妨
碍 FreeBSD 成为一个速度、安全性都非常棒的操作系统。

密,显然不是黑客们随心所欲的结果。不同

另外FreeBSD的数据包管理得到了彻底改进;二进制和源数

的身世导致了二者性质上的不同,Linux更

据包不再受制于不稳定的数据包管理系统,而这却正是Linux分

象一个长不大的孩子,内核更新很

发时的常见问题。出于安全的考虑,Linux上的日志文件系统在

快,但不同版本之间的兼容

FreeBSD上是不可用的,这些系统中包括Reiser File System(Reiser

性始终存在问题。学院派

FS)和 Journaling File System(JFS)。

的 FreeBSD 尽管给人留下

最后,在对开发者和操作者的帮助方面,FreeBSD文档以简

了死板的印象,但这份死

明的图书形式在Internet 上和纸张上出现,并以令人愉悦和合理

板使得它变得越来越严谨,“坚如磐石”成了 FreeBSD开发者们
不懈追求的目标。

的形式介绍每个系统和系统的每个方面。
从以上的描述中我们不难看出,尽管Linux是一个优秀的操

在安装方法上,FreeBSD由于采用集中式的开发方式,安装

作系统,但如果我们硬要说它在技术上比FreeBSD更优秀,显然

方式比较清晰、直接、高效,但这可能使得那些习惯于图形化

缺乏强有力的证据。因此,说 Linux 比 FreeBSD更流行是由于技

安装方式的用户不习惯。尽管FreeBSD曾被指责为分支过多,但

术原因造成的,同样站不住脚。

34

程序员

有人认为两者在应用程度上存在差异的原因是采用了不同

其竞争对手 HP 和Sun 紧随其后。HP 的64 位服务器使得 Linux在

的开源协议。Linux要求受益人都要付出,而BSD并没有这方面

支持64位技术的启始时间上领先于Windows,Sun在今天已经全

的要求。这似乎有些道理,但远没有商业追捧来得更直接。

面支持 Linux,但就在五年前,Sun对 Linux的支持却只是通过收
购了一家名为 Cobalt 的小公司实现的。

商业追捧是造成流行差异的主因

如果我们硬要追究这些公司选择Linux

研究技术,但不沉溺于技术,是每个技术人员需要牢记的

的原因,我们会发现,这和1992年AT&T

信条。但技术人员总是会认为技术上更为优秀应该占据更多的

与加州大学伯克利分校在BSD版权问题

市场份额,但无情的市场证明,这并不总是正确的。

上的诉讼有关。Linux没有受到这场诉

时至今日,Linux在服务器端和嵌入式端都取得了不俗的成

讼的影响,尽管SCO 公司后来也曾就

绩。表面看来,由于 BSD 家族在嵌入式市场没有作为,这使得

专利问题对Linux进行过诉讼,但不幸

Linux在嵌入式端的表现与FreeBSD的比较毫无意义,但透过Linux

的是他们遇到的对手是老辣的IBM 公司,让这场诉讼不影响到

与 Vxworks 的比较还是能带给我们一些启示。技术方面,嵌入

Linux产业的发展。

式 Linux 先天条件上就落后于Vxworks,Linux从 2.4的内核发展
到 2.6 的内核仅仅用了四年时间,并且新旧版的内核还存在某
些兼容性问题。有时候这种兼容性带来的问题会是灾难性的。

决定 Linux 与 FreeBSD 命运的两场诉讼
FreeBSD 的产生和 UNIX 系统有着千丝万缕的关系。UNIX

这也曾经是 Vxworks 操作系统的开发厂商 Wind River 攻击Linux

最早是在1969年由AT&T Bell实验室的研究人员创造出来的,

的一个理由,但接下来的事情我们谁也没有想到。当注意到

逐渐成为了主流操作系统。虽然 UNIX 由 AT&T创造,但它如

Linux在嵌入式领域的流行已成为不可逆转的趋势时,
Wind River

此流行却并不能完全归功于 AT&T的功劳。现在 UNIX 不是一

甚至一度有开发自己的 Linux 操作系统的念头。

个厂家的单独产品,在它长期的发展过程中形成了多种不同

在桌面领域,Linux与FreeBSD的表现一样糟。由于二者总需

的版本。

要不停地编译,因此注定了二者都更适用于专业用户。用过Suse

在发展初期,AT&T并没有把UNIX 作为它的正式商品,只

Linux10 的人可能都不会反对这个观点,这就是Novell 正在改变

是在实验室内部使用并完善。正是由于 UNIX 是被作为研究项

天平的平衡。曾经的网络操作系统老大Novell把原来开发商业软

目,其他科研机构和大学的计算机研究人员也希望能得到这个

件的全套手段都使了出来。当最初的体验者试用 SuSe Linux10

系统,以便进行自己的研究。AT&T 以分发许可证的方法,对

时,他们可能没注意到一台台摄像机正对着他们,他们的体验

UNIX 仅仅收取很少的费用,大学和研究机构就能获得 UNIX 的

被忠实地记录了下来,以便产品能根据用户体验得到进一步的

源代码以进行研究。这使得 UNIX 操作系统发展迅猛。

改善。不仅如此,Novell 支持的Mono 项目还会使得基于Linux平

到了二十世纪七十年代末,在 UNIX 发展到了版本 6 之后,

台的桌面应用越来越丰富。这还不算完,几天以前,Novell自己

AT&T开始认识到了 UNIX的价值,并成立了系统实验室来继续

又推出了包括Novell Open Enterprise Server、Novell GroupWise工

发展UNIX。因此AT&T一方面继续发展内部使用的UNIX版本7,

作组协作软件、Novell ZENworks Suite跨平台系统管理套件、

一方面由 USL 开发对外正式发行的 UNIX 版本,同时也宣布对

Novell Linux Desktop

UNIX产品拥有所有权。同时加州大学伯克利分校计算机系统研

以及 OpenOffice 的开

究小组(CSRG)也在使用UNIX对操作系统进行研究,由于他们

放工作组套件。在这

的技术受到大学和商业机构的普遍欢迎,因此CSRG中的研究人

种形势下,如果一年

员把他们的 UNIX组成一个完整的 UNIX系统──BSD UNIX,向

以后Linux桌面应用真

外发行。

的成为了企业级桌面

在 AT&T的 UNIX 系统实验室吸收了 BSD UNIX 中已有的各

应用的一种潮流,我一点儿也不会感到惊奇。相反,如果FreeBSD

种先进特性,并结合其本身的特点,推出了 UNIX System V版

处在那样的位置上,才是一件让人大跌眼镜的事情。

本以后,BSD UNIX 和 UNIX System V 形成了当今 UNIX 的两大

作为一个网络操作系统,FreeBSD 的长项显然是在服务器
端。在这一领域,FreeBSD与Linux应用上的差异显然是由于当年

主流,现代的UNIX版本大部分都是这两个版本的衍生产品。这
为日后的市场纷争打下了伏笔。

IBM 公司投入十亿美元支持一个操作系统时,选择了Linux所造

事实上,AT&T的UNIX系统实验室一直关注着BSD的发展,

成的。从此以后,IBM的软、硬件全面支持了 Linux,这又带动

并在1992年,指控一家发行商业BSD UNIX的名为BSDI的公司,

Programmer

35

人物&报道

Character & Report

观点 >>>

违反了 AT&T 的许可权发布自己的 UNIX 版本,并进一步指控

国犹他州联邦地方法院申请了传票。传票要求微软、惠普、Sun、

伯克利计算机系统研究组泄漏了 UNIX 的商业机密。这个官司

Baystar 这四家公司提供包括它们与SCO 交易的详细资料。尽管

影响了很多 UNIX 厂商,使他们不得不从 BSD UNIX 转向 UNIX

来自SCO的声音表明它与IBM的专利之争将在2007年正式打响,

System V,以避免法律问题。以至于当今大多数商业 UNIX版

但此时支持 Linux 的阵营已变得空前强大,没有几家公司愿意

本都是基于 UNIX System V 的。这件有关 UNIX版权的案子直

SCO 真的能在这场斗争中取得利益。于是,为回应 SCO 关于

到 UNIX 系统实验室被AT&T卖给了 Novell公司后才得以解决。

Novell侵犯知识产权的指责,Novell以及SUSE已经向国际商业法

伯克利的CSRG被允许自由发布BSD,但是其中来自于AT&T的

庭提出仲裁请求,阻止 SCO 依据 Caldera、SUSE、Connectiva和

代码必须完全删除。尽管日后的新版本 4.4 BSD Lite 版本已

TurboLinux 之间签订的 Linux 联合协议对 SUSE Linux 知识产权的

不存在法律问题,并且4.4BSD Lite已成为了现代 BSD系统的

主张。该协议规定,SCO 对 SUSE有仲裁权,其版权中包括SUSE

基础版本,但这场诉讼已经注定了日后出现的FreeBSD已丧失

的分让权,任何根据联合Linux中的OSS许可发布的SCO 软件均

了发展的良机。

应维持开源。Novell 已经签署文件来延缓 SCO 的主张,直到仲

类似的事件也曾降临在 Linux 身上。2004 年 3 月,SCO 集

裁结果产生。尽管 S C O 挑起的战争并没有完全结束,但就连

团提出诉讼,认为IBM将 UNIX代码放进了开放源代码中,这搅

Linux的死敌微软都已经默认了将与Linux共存的事实,因此SCO

浑了开放源代码软件的水。接下来,SCO 把这场战火引向了用

取得完胜的希望已是微乎其微了。

户,对汽车配件零售商AutoZone进行了起诉,声称这家汽车配
件零售商由于使用 Linux 而侵害了 SCO 的专利版权。
尽管 SCO 面对的是老谋深算的 IBM,但业界还是有相当的

事实上,Linux 与UNIX 同样存在血缘关系。但同宗的Linux
与FreeBSD的矛盾由来已久,其中的主要原因似乎是当人们提起
开源时,总不免想起Linux,这让Linux抢了FreeBSD太多的风头。

人认为这将限制 Linux用户传播代码的能力。但IBM显然不是当

但对我们来说,如果我们准备选择一个开源平台时,尽管Linux

年的 BSDI公司,几番争斗的结果,是IBM公司反而开始了反攻。

比 FreeBSD 更流行,但 FreeBSD 仍然是一个不错的选择。

IBM 公司于 2006 年 3 月向正在为 IBM 与 SCO 一案举行听证的美

■  责 任 编 辑 :贾 菡  (jiahan@csdn.net)

36

程序员

<<< 感悟

时间缝里

看技术发展
□ 文 / 李菲萍
 “九九年,我认准了 Java

C++ 随着技术的进

大有前途,考 SCJP 认证还考了个全国第

步,C因为类型检查机制

一呢!Java是多好多棒的技术啊!可是,

相对较弱 、缺少支持代

当时在国内都不知道有没有什么用,最

码重用的语言结构等缺

后我还是只好去做 C + + 了!”王勇摇摇

陷的存在,风光难续。作

头,遗憾的说,“过了两年,Java才终于

为第一种面对对象的语

在国内火了起来!”——王勇的Java经历

言,接过C交过来的接力

并不是一个例外,而是中国软件技术发

棒, C++发力狂奔,把

展的一个缩影,国内外的时间差夹缝里

国内外技术的时间差赶

打拼的国内技术精英们的尴尬:早一步

上了10年,只剩下4年的

了是白费,晚一步了便成了跟风。

站在了起飞点上,开始了快速发展。

差距。

不过,值得庆幸的是,回首软件技术

C语言 C语言和Unix可以说是相濡以

为什么一下子能赶上 10 年呢?原因

的发展史,可以明显看到,技术时间差已

沫,它的出现和发展都离不开Unix。Unix

很简单:天时地利人和。天时:C++已经

经越来越短了。照此趋势,王勇的尴尬将

出现后,技术天才们并不满意Unix的笨重

在国际上得到标准化的广泛应用;地利:

不再是悬在程序员头顶的利剑,会随着

简单的低级语言。1972年至1973年间,贝

新兴的中国IT产业热情接纳新兴技术;人

发展湮灭在历史长河里。

尔实验室的 D.M.Ritchie 便在B语言的基

和:国内的技术精英圈的扩大,成为国内

础上捣鼓出了C语言;1973年,K.Thompson

追赶国际先进技术的“加速器”。

过去:蜗牛慢慢爬
Unix 操作系统 Unix 国内起步和国外

和 D.M.Ritchie 两人合作把Unix 的90%以
上用 C 改写,即Unix 第 5 版。从此,C语

现在:“多快好省”的追赶

相差了整整 20 年。这是因为当时的特殊

言开始风靡全世界,成为世界上应用最广

时间翻过漫长的一页,国内的IT产业

国情:80年代前,国内还是处于完全封闭

泛的几种计算机语言之一。历史发展到C

此时已经蓬勃发展起来了,历史钟表的

状态,美国和中国是两个对立的世界,国

语言这里,时间差缩短到14年。

时针开始了加速度转动。

内没有任何的技术积累,也没有任何信

TCP/IP 和Unix 一样,TCP/IP也晚了

Java 早在 1992 年 James Gosling 刚

国外 20 年。1970,ARPANET 主机开始使

秀出 Java 前身 Oak,锋芒之锐便吸引了

60 年代 Unix 在国外初生时,国内计

用TCP/IP的前身网络控制协议(NCP)时,

无数在 C++ 里绕圈的眼球。2000 年起,

算机产业还面目模糊;70 年代 Unix 操作

极少有人意识到十年之后它会席卷全球;

Java便以它“只写一次,随处运行”的特

系统的第一个版本是 1969 年由 Ken Th-

1983年,ARPANET由NCP 转向TCP/IP,其

性脱颖而出,在国外站在了起飞点上 。

ompson在AT&T贝尔实验室实现时,开始

规模迅速膨胀,不久便形成了跨越五大洲

2002年后,随着Java(准确地说,是J2EE)

了起飞,国内还是死水一潭;直到 80 年

的世界上最大的计算机互连网络,而当

在大型企业和政府应用的增加,Java在国

代,Unix 操作系统才开始在中国落地生

时国内才刚刚接触到这个概念。值得庆

外火了两年之后,终于在沉寂的国内突

根,终于,到了 90 年代,随着国外 Unix

幸的是,90年代后,它的发展步伐加速,

然一夜暴红,成为了业界娇宠。

版本问题的解决,国内Unix的发展才终于

发展起飞点不过落后国外 6 年。

息来源, 20年的差距也是当然的了。

历史走到Java这里,
时间差缩短到2年。

Programmer

37

人物&报道

Character & Report

感悟 >>>

发展。越来越多的网站开始

内,敏捷开发在 04 年迈上了起飞点,得

在某些应用中使用这种技术,

到普遍的认可和应用。但在国内尚未出

例如新浪的邮箱和blog,以及

现明确的起飞点。敏捷开发方面的专家

一些新出现的Web 2.0网站。

熊节认为:
“随着中国整个市场经济的深

前后相差不过半年。这时候

化和对全球化贸易的进一步开放,我相

的国内基本不用担心学了本

信更多的企业会需要软件给他们提供必

事用不上,王勇的尴尬已经

不可少的支持,这些企业就会在意敏捷

成为了永远的过去。

方法给他们带来的价值。出于这个原因,

Web 2.0 随着技术的发
展,人们对互联网的要求也
开始提高,Web 1.0 日见过

动态语言 历史发展的趋势很明显;
技术的发展越来越人性化。编程语言也

我愿意预测,在两到三年以后,敏捷方法
会在国内得到广泛的认可与应用。”
Ruby/Rails 早在 1995 年,Ruby 就

气,提倡个性化的Web 2.0在

已经诞生在日本了。但直到 2004 年,

2003 年刚出现便受到各界追

Rails 的出现才改写了 Ruby 的命运,Ruby

捧,它以blog、TAG、SNS、RSS、

突然受到了前所未有的广泛关注。这实

Wiki等应用为核心,这下,网民们终于可

际上是历史的必然,Rails 成功的原因,

以在网上撒开脚丫子跑了。

在于它站在一个合适的历史位置上:它

从一开始笨重的静态语言,转向灵活的

2004年下半年,Web 2.0在国外便开

同时具备了 PHP/Perl 的简洁,以及 J2EE

动态语言。Perl、Python、Ruby在国外刚一

始飞速发展,而国内紧随其后,一夜之间

的规整。所以它一问世便受到企业应用

出现,国内就已经开始跟进,除了“黑客

Web 2.0在国内技术圈里闪亮登场,成为

开发者(尤其是 J2EE 人群)的重视。

级的语言” Perl 相差近5年外,Python、

流行新贵。先是号称向 Web 2.0 转型的

虽然国内对 Ruby的关注在 2005年已

Ruby 都和国外相差不过一年。

猫扑网获得了美国风投AccelPartners的千

经蔚为风气,但若说是“流行”,还根本

.NET IT 界的人说,当你不知道方向

万美元注资;之后是爱赶时髦的搜狐宣

谈不上。更多的开发者和企业仍然对

的时候,就看看微软在做什么。所以.NET

布将搜狐 IT升级到2.0 版本;而“博客中

Ruby/Rails 抱着怀疑与观望的态度。Rails

在国内有天然优良的生长环境,
因为国内

国”更名为“博客网”,更是拿Web 2.0

是一个真正有震撼力的杀手应用,但它

对微软技术一向跟进很紧。
同样是功能强

来说事儿的。

需要一个机缘,先让大家看到它在关键

大的开发平台,
.NET在进入国内的时间基
本和国外同步,发展也一帆风顺。

Web 2.0时代,国内和国外已经站在
了技术追赶战的一条战壕内了。

国外的.NET 技术在2003年进入了高
速起飞点,而国内则在 2005 年也迈上了
起飞点,开始高速发展。
Ajax 如果说.NET 的飞速发展还是因
为微软这个霸头的力量,那么,Ajax的飞

应用中出色的表现,才会有更多的企业
来真正使用它;否则,从J2EE迁徙到Rails
的成本与风险,很多企业都不会敢于和

明天:数风流技术,谁领风骚?

乐于承担。而且,还需要更多的宣传和介

这里并不是要做一个专门的预测,

绍,才会吸引更多的开发者来学习它、掌

是读史鉴今,分析国内目前普遍关注的

握它、尝试它。

几种技术。

速发展则完全是国内技术圈主动追赶出

敏捷开发  历史是

来的。在 2005年2月 Jesse James Garrett

必然性和偶然性结合的

的一篇A New Approach to Web Applica-

产物,敏捷开发也是 。

tions 引出了 AJAX 这个 web 界的新名词,

2001 年,一场叫“敏捷

A j a x 在国外开始受到广泛关注,而后,

宣言”的旋风肆略全球,

Google公司基于AJAX开发出来具有卓越

不可避免的,也席卷到国内技术圈。在国

Ruby/Rails已经被实践证明能够承担

的交互设计和可用性的 Web 应用 GMail、

内外都为死板无效率的项目开发而头疼

企业应用开发的重任,但是否能够继续

Google Maps、Google Suggest,AJAX 便

时,敏捷开发看似不经意的出现,必然引

发展成为主流,也许更多地需要机缘。所

迈上飞速发展起飞点。

起历史的轩然大波。

以,我们也只能拭目以待。

国内在 2005 年下半年也开始了飞速

38

程序员

ThoughtWorks 公司认为,全球范围

■  责 任 编 辑 :贾 菡  (jiahan@csdn.net)

<<< 声音与幽默

成为3G的杀手级应用,但是手机上的社

声音 & 幽默

区网络的确有可能造成大量的应用需求。

尽可能地使用开放源代码是政府的
这是一项长期的投资计划,一夜

Wi-Fi 项目的局面时,Nolle 如是说。

之间不可能看到结果。

政策,
我们和微软有很好的合作关系,

我们是不可知论者,我们和每个人合作。

——微软CEO鲍尔默日前向员工表

我们将为用户提供一种全新的新闻体

——英国中央信息保证中心监定首

示,尽管华尔街对微软数十亿美元的

验,吸引他们将更多时间用于阅读报纸。

长 Harvey Mattinson 对于英国内阁办公室

庞大投资计划持否定态度,但“目前并

——近年来美国报纸发行量持续下

与 IBM 公司正合作测试一种公、民营单

没有缩减投资规模的考虑”,并且在发

滑,各大报纸都希望找到赢回订户的新

位皆可使用的安全开放源代码环境发表

给全体员工的一份备忘中表示,微软

途径。微软和《纽约时报》将于明年初推

的看法。

庞大的项目计划需要投资领域的支持。

出一项新服务,允许用户通过互联网将

Google 之所以敢冒险投资无线领
域,也是为了在消费者的心目中树立

报纸内容下载到平板电脑,并使用微软

这类设备的一个优势是广告可以

“屏幕阅读器”浏览。
《纽约时报》董事会

随着时间而变化,使得报纸不会在上

主席阿瑟・萨尔伯格对此充满信心。

起一种可替代互联网接入的理念。

午出现蜂蜜广告,在晚上不会显示咖
啡广告。

——电信咨询公司CIMI的总裁Thomas

移动企业已经在网络硬件上投资了

—— Agency.com 的常务董事赫尔曼

Nolle 曾经提出过一种观点,他认为Google

大量金钱,可是他们的态度就像是疯狂

斯同样对正在开发中的能够弯曲,而且

是在构建自己的并行互联网,或者用他

地乱枪打鸟,然后希望蒙到一两只一样。

重量仅比一张纸重的电子阅读设备十分

的术语说是在构建“门户网(PortalNet)”。

——研究机构Forrester Research的分析

看好,尽管这样的设备可能只能显示灰

面对Google制定进入无线领域的计划,在

师 Charles Golvin 如此批评现在的移动企业,

色,但它们却可能吸引一些广告代理机

很多大城市,如在旧金山等地竞标一些

他十分怀疑有任何一两项单一的应用可以

构的参与。
“ 并 非 如 此 ,” 程 序 员 说 ,
“在设计一个财务

程序设计

软 件 包 时 ,编 程 人 员 是 作 为 一 个 中 介 者 在 观 念 各
异 的 人 们 之 间 起 作 用 的 :软 件 如 何 操 作 ,报 表 是
什 么 形 式 ,如 何 与 税 法 一 致 等 等 。相 反 一 个 操 作
系 统 不 为 其 外 观 所 限 制 ,当 设 计 一 个 操 作 系 统

编程大师如是说:
“程序被测试时再

嚷 着:
“ 我 昨 天 满 载 而 归 ,但 今 天 的 收 获 会 更 大 。”

时 ,编 程 人 员 只 要 在 机 器 与 人 的 思 维 之 间 寻 找 一

于是,门卫盯他盯得更紧了,但仍一无所获。

种 最 简 单 的 和 谐 就 可 以 了 。这 就 是 为 什 么 操 作 系

改设计方案就太迟了。”

在 展 示 会 的 最 后 一 天 ,门 卫 再 也 抑 制 问:
“大

曾有个人去参加一

盗 先 生 ,” 门 卫 说 ,
“ 我 被 你 搞 糊 涂 了 ,实 在 想 不

次电脑展示会,每天当他

明白。请告诉我,你究竟在偷什么?”

进入展馆时 ,都对门卫说:

曾 经 有 位 编 程 大 师 ,喜 欢 编 写 非 结 构 化 的 程

“ 我 是 个 大 盗 ,这 次

序 。一 位 初 学 者 试 图 模 仿 他 ,也 开 始 编 写 非 结 构

展 示 会 也 在 劫 难 逃 。”

化的程序。
 当这位初学者请大师评价他的进展时,

这番话让门卫坐立

大 师 批 评 了 他 的 做 法 。他 说:
“对一位编程高手适

不 安 ,因 为 里 面 有 价 值 数

合 的 ,对 初 学 者 来 说 并 不 一 定 适 合 。在 超 越 结 构

百 万 美 元 的 电 脑 设 备 ,所
以他紧紧地盯住这个人,

化 之 前 , 你 必 须 先 领 悟 道 。”
曾 经 有 位 程 序 员 被 派 到 IBM的 军 机 大 臣 手 下

但这个人只是从一个展摊

工 作 。 军 机 大 臣 问 程 序 员:“ 设 计 一 个 财 务 软 件

逛到另一个展摊, 嘴里轻

包,和设计一个操作系统,哪一个更容易?”

轻地哼着小曲。
当 这 个 人 出 门 时 ,门 卫 把 他 拉 到 一 边 ,搜 查
他的衣服,但一无所获。
第 二 天 ,这 个 人 又 来 了 ,并 对 着 门 卫 嚣 张 地

“ 操 作 系 统 。” 程 序 员 回 答 说 。
军机大臣立刻发出一种不信任的惊叹,
“与
一 个 复 杂 的 操 作 系 统 相 比 ,一 个 财 务 软 件 包 简 直
是 小 巫 见 大 巫 。” 他 说 。

统 更 容 易 设 计 的 原 因 。”
军 机 大 臣 点 点 头 , 笑 了 。“ 说 来 也 是 。但 要
想检测和纠正其中的错误,哪个更容易呢?”
程序员没有回答。
一 位 经 理 到 编 程 大 师 那 里 ,交 给 他 一 份 有 关
一个新应用程序的需求说明。经理问编程大师:
“如果我分配五个程序员给你干 ,你需要多久能
设计好这个系统?”
“ 那 将 花 费 一 年 的 时 间 。” 大 师 立 刻 回 答 。
“但马上就需要这个系统甚至要求更快!如
果我分配十个程序员给你需要多长时间?”
大 师 皱 了 皱 眉 头 ,“ 那 样 的 话 ,需 要 两 年 。”
“如果我分配一百个程序员给你怎么样?”
大师耸了耸肩膀,
“那么这项设计将永远无
法 完 成 。” 他 说 。
——节选自电子工业出版社即将出版的《编程之道》

Programmer

39

特别策划

42

程序员

Features

程序员开源手册

>>> 

程序员开源手册
□ 策划 / 欧阳璟

在 Internet 上,开源社区的项目就像浩瀚的海洋。那些崇尚开放的程序员常常汇
聚在这片海洋之中,偶尔掀起一阵波澜,或者卷起巨浪。然而就软件而言,却并不
是追捧时尚就可以写出优美代码的,更多时候,是需要汲取这片汪洋中的精华。
精华是什么?对于一个长期面对显示器撰写代码的人来说,最为精华的东
西莫过于他们长时间积累下来的经验。而这些经验通过一行行代码展现出来,
便形成了很多程序员常常使用的程序库、组件包以及软件开发相关的工具。
然而,要在浩如烟海的开源项目中找到自己合意的工具和代码谈何容
易?每一个项目、每一种开发语言、每一个开发过程都是如此的特殊,以
至于我们不得不用很大的精力来寻找适合它们的软件,或者花费一番力气
来自己开发。
为此,本刊编辑部特别策划了这样一组文章,从不同的方向上为读者
打开开源宝库的大门。横向上看,每个程序员都在使用编程语言进行软件开
发,这些语言主要分布在 C/C++、Java、.NET 平台语言,或者是如 Perl、
Python、Ruby 以及Lua这样的动态语言。且不说动态语言高度的灵活性,便于
撰写很多优美的程序库,单是那些传统的编程语言所积累下来的宝贵的经验
和财富,就很值得仔细钻研。而从纵向上看,从需求、设计、建模、开发到配
置管理、持续集成等多方面都有很多优秀的开源工具可供免费使用。
通过本刊专家作者的点评和比较,
兴许可以让你迅速掌握软件开发的神兵利
器,从此开始撰写高质量的代码!

Programmer

43

特别策划

Features

语言“小人乍富”的那几年,也还有

C++ 开源程序库评话

其它不少程序设计语言具有高性能、
可移植、系统开发能力强的特点,决
不是只有 C骨骼特异,貌若天仙。如
果 Pascal 也能借助一个像 UNIX 那样

□ 文 / 孟岩

的开放的幽灵在欧美大学校园里徘
徊,那么我们今天很可能要把 begin
和 end 直接映射到键盘上。如果 IBM

 C语言天生就与开放结

够认识到的是,事实上C语言统治地

不是在 1970 年代极端保守地把一种

缘。大约到1980年代中期,C已经成

位的获得,却也是早期开放软件运

叫做PL/X的语言牢牢地限定在自己

为人类历史上第一种工业级程序设

动的直接结果。多数人在回顾这段

的研究所里,也许整个程序员社群

计世界语。很多人都知道,正是C这

历史的时候,经常会感染中国文人

的图腾就不是贝尔试验室的那两个

样一种世界语的出现 ,才使开源运

的不严肃的浪漫主义史观,喜欢把C

大胡子,而是小沃森实验室里的IBM

动的出现和最初发展成为可能,从

语言的成功归结为汉高祖斩白蛇般

某院士。事实上,C 语言的成功,更

这个意义上讲,说C语言是开源运动

的天赋神格,描述为遥想公瑾当年,

须拜开放软件运动之时势所赐,或

之母并不十分过分。但人们不太能

谈笑间樯橹灰飞烟灭的轻飘飘。在C

者更确切地说,C与开放软件是一对

44

程序员

程序员开源手册

>>> 

共生体,它们相互扶持,相互成就,

更因为可能要面对着暴风雨般的批

看成是语言本身的扩充。在Java、C、

共同成长兴旺,共同创造历史。

评和鄙视。总之,诸多的原因使得开

Perl、Python、Ruby中,一个优秀的应

源文化未能在 C++ 中深深扎根。

用程序开发者在积累一定经验之后,

根深自然叶茂。今天C语言体系
内所拥有的开放资源 ,无论是数量

然而,毕竟C++是一种称霸一时

不难写出高质量的可复用代码。而

和质量,还是丰富性、多样性、创新

的语言,C++社群的规模、强悍和创

在 C++中,这种事情是非常罕见的,

性、可靠性、重要性,都是其它任何

造力,仍然是很多其它新兴语言社

即使是天资卓越、经验丰富的大师

开发技术体系所无法望其项背的。

群难以相比的。特别是在标准C++制

级人物,也需要花费多年的打磨,历

丰富对于开发者是好事,但对于写

定之后,C++编程风格有了明确的指

经几次反复,才能够最终推出受到

资源介绍性文章的作者来说 ,则是

导思路,开源项目也就大大繁荣起

一致认可的可复用程序库。此道之
难,难于上青天,以至于 A n d r e i

然而如果我们对历史作一些细致的调查,我们会发现C语言绝非
有什么天命,而只不过是幸运地扒上了早期开放运动的快车而已。

Alexandrescu 感叹道,十几岁的少年
天才满目皆是,满鬓斑白的优秀程
序库设计者凤毛麟角。而在另一个

绝对的坏事。想要对C语言体系中的

来。虽然时间还不长,但是已经有一

地方,一本C++可复用技术图书的

开放资源做一个介绍 ,哪怕只是一

些令人欣慰的成果。这些成果也就

作者总结道,所谓可复用的C++程

次白描,也决不是一个人、一本书所

构成了写作本文的基本动机和素材。

序库,不可能是设计出来的 ,只可

能容纳的,更远远不是杂志中的一

就重要性而言,开源程序库和

篇文章所能及的。因此在本文中,对

工具集对于 C++ 甚至比对 C 还要重

能是复用出来的。然而,一旦这样
的程序库构造出来并且为人们熟悉,

于 C 语言开放资源的介绍是以一种

要得多。因为实践证明,没有良好的

那么就会大大地简化应用程序的开

蜻蜓点水的姿态进行的。

基础设施支持,C++开发成功的可能

发。这也就是为什么在 2000 年后,

相比之下,C++语言在开源世界

性异乎寻常的低。其根本原因是,用

Bjarne Stroustrup 无数次地呼吁社群

中的分量,与 C 语言比就相去甚远

C++写优秀的程序库非常非常难,而

专注程序库的开发。他很清楚,只

了。作为对照,C++语言在工业界的

一旦有了这样的程序库,在其基础

有程序库能够救 C++,只有程序库

实际地位,如果不是比 C 更重要的

上写应用程序就相当容易了。同时,

能够发展 C++。

话,至少也是与 C 在同一个层次上。

C++ 的特点又要求基础设施的源代

现在我们知道,用来写C++程序

考虑到这一点,在开源领域中两兄

码必须开放,因此,C++程序库对于

库所需要的技术,与用来写C++应用

弟的这种差距就令人感到非常震惊。

开发者来说意义非常重大。

程序所需要的技术存在很大的差别。

如果说在 2000 年以前,由于 C++在

我们可以更进一步探究开源

这已经比较糟糕了。更糟糕的是,一

工业界的统治地位,这种差距对C++

C++ 程序库对于 C++ 开发的重要意

般的 C++ 开发者根本分不清这中间

的影响还不大的话,今天,C++在开

义。用C++编写可复用程序库时所需

的差别,他们在开发中往往既不是

源领域里薄弱的基础就非常要命了。

要的思想方法和技术风格,与用C++

一个称职的程序库开发者,也不是

究其原因,归根到底是因为编写高

编写应用程序时所需要的思想方法

一个单纯的应用开发者。他们一边

质量、可复用而又拳拳服膺的C++程

和技术风格之间存在相当大的差异

想着完成手头的工作 ,一边琢磨如

序库实在是一件太困难的事情。一

和差距。前者所需要的高超技术、丰

何能够写出高质量的基础库和框架,

方面,大量的 C++ 开源项目质量不

富经验和良好的权衡能力,是很少

为万世开太平。

佳,而且经常以一种粗暴的方式要

有人能具备的。在所有程序设计语

认识到这样的事实之后,C++程

求使用者改变自己程序的风格,另

言中,你恐怕找不出第二种语言像

序员应当以更理性的态度来看待自

一方面,一旦有人完成了一个可用

C++那样,对于程序库作者的要求如

己的工作。大部分情况下,你所需要

的C++项目或者程序库,他必须具有

此之高,以至于远远超过了一般“熟

做的是寻找一些可以互相合作的、

极其彪悍的意志才能够咬着牙把这

练”C++开发者的平均水平。在Lisp

稳定可靠的开源程序库,然后在其

样的项目奉献给开源社群——不仅

中,语言、库和程序根本就是一回

基础之上,面向目标,使用尽可能简

因为失去了可能的金钱上的回报,

事,每一个程序员写的代码都可以

朴的技术,专心专意地进行应用开

Programmer

45

特别策划

Features

发,把那些复杂精妙的语言技巧和

肯定有一个网络编程库和一个线程

ACE 需要花费大量的时间和精力,对

“可复用”之类的想法扔到Java国去。

库。然而目前看来,ACE仍然是进行

于有的人来说,这绝对值得。对于另

唯其如此,你才可能更高效地开发

系统和高性能网络编程的首选,其

一些人来说,可能就要想清楚了。

出好的应用软件,而且会逐渐积累

地位在一段时间内不会被撼动。它

和重构出真正可复用的软件。

不但是一个实用的程序库、框架集,

正是基于这样一种认识 ,我以
一种务实而挑剔的眼光,为读者介

而且是一个典范的设计模式应用范
例,非常值得学习。

GUI 库:Qt
传统上Qt被认为是可移植的GUI
库,但实际上 Qt 现在已经是一个比

绍一些C++的开放资源,同时也附带

ACE可以有多种用法。你可以把

介绍一些C语言的相关开发资源。我

它当成可移植的系统开发平台,只

较完整的可移植应用程序框架了,
其中包含了大量的工具,比如正则

的挑选原则如下:

使用其基础设施和 class wrapper,这

表达式、Web 和 Socket 类、2D 和 3D

● 实用。必须是能够解决现实

使你能够站在更高的抽象层次和更

图形、XML 解析、SQL类等,甚至还

问题的开源程序库,徒有虚名、搔首

完备的基础设施之上开发能力和性

包括了一个完整的容器类库 ,不过
其王牌还是GUI。在目前的跨平台GUI

现在在开发者社群中,
“C 语言万寿无疆,C++ 无寿无疆”的说
法得到不少人的支持,其根本原因之一就在于 C++在开源运动中的
地位远逊于 C。

框架中,Qt成熟度最高,已经被一些
大 公 司 应 用 在 关 键 产 品 中。由于
Trolltech对Qt采用的dual license模式,
该产品既可以从开源社区获得支持,

弄姿者皆不录入;
● 可靠。必须经过实践的检验,
被广泛应用。花拳绣腿者不录;
● 先进。风格上比较先进,能
够体现 C++ 的技术优势;

能完全与 C 语言相当的系统应用。

又能够赚取足够的商业利润 ,因此

Douglas Schmidt本人在给我的一封信

其前景也令人比较有信心。

中提到,他非常支持这种简朴的用

Qt 的主要技术特色是其元对象

法。但更多的人恐怕不会停留在这

模型。Q t 实际上使用的并不是标准

个简朴的层次,而是会进而使用ACE

C++,而是标准C++的一个扩展。它

● 开放。有社群的积极支持支

所提供的那些先进的框架,如著名

通过元对象模型扩展 ,实现了著名

持,文档相对齐备,代码开放,允许

的 Reactor/Proactor。这就是ACE的第

的 signal/slot机制,而这一机制也成

讨论和改进;

二个层次,也是发挥效益最大的一

为 Qt 的最大特色和优势。

● 有益。读者可以放心大胆地
使用,并且应当能获得实利。
在这样的背景下,我将下面的
一些开放资源介绍给大家。

系统和网络编程库:ACE

个层次。还有少数的 ACE高级用户,
可以在必要的时候为 ACE 本身添加

与Qt类似的可移植GUI框架还有
wxWidget,FOX 等。

新的构件。
ACE是一个侵入式的程序库。如

分布式对象中间件:ICE

果要使用它,就要改变自己的编程风

ICE 是分布式对象中间件领域里

格来适应 ACE。好在ACE程序的整体

的后起之秀,可以大致地将其视为

看到这个名字,你可能会感到

风格并不怪异,一般的C++程序员很

“改进版”的CORBA。目前应用在一

好笑: 当然,提到系统和网络编程

快就会习惯,并且喜欢上 ACE带来的

些大型项目当中,其中包括波音公

库,除了 ACE 还能有谁?

一些强大的基础设施。但是ACE的庞

司主持的下一代陆军作战系统。

但其实,除了ACE还有很多系统

大规模对于开发者来说,无论是学习

ICE 的一个特别价值是其代码的

和网络编程方面的程序库。比如在

还是使用上都构成严重的负担。有

范例意义。由于ICE 的出现较晚,开

线程库方面,还有 ZThread、boost::

不少针对 A C E 的批评都是在与它的

发者比较系统地运用了新的 C++ 编

thread,如果放大到C/C++领域,还

“重量级”上。另外,ACE的文档虽然

程风格,所以成为了研读C++代码的

有APR,还有CII。在文件和目录操作

比前几年大大丰富了,但是还是很缺

方面,boost 也有相应的组件,而在

乏。一旦出了错,只有 ACE专家才有

其他的分布式中间件体系包括

网络编程方面有 s o c k e t + + ,还有

能力彻底解决。这些都给ACE的应用

第一代的CORBA和DCOM,当然如今

boost::asio,未来的 C++0X 中几乎

和传播带来的阻力。一般来说,学习

的C++/CLI也支持.NET Component。

46

程序员

良好目标。

程序员开源手册

>>> 

正则表达式:boost::regex

别值得一提,这是一个完整、成熟、

一个保守性的GC,Hans-Boehm GC在

正则表达式是编程工作中最强

强大的科学函数库,有 C 语言版本。

性能和功能方面都算是卓越 。特别

有力的工具之一。C++的正则表达式
支持一直以来是一个软肋。大约在
2001年左右,boost中出现了regex库,

是,使用这个GC,你仍然可以delete、

XML:TinyXml
C++ 的 XML 相关库不少,但是

free 来自己管理内存,对于我们编程
习惯的冲击比较小。

初步解决了这个问题 。但是最初的

大部分其实都是C库,使用起来自然

regex 无论是效率还是可靠性方面都

不那么轻便。其中基于 D O M 的有

有一些问题,后来经过了一次大规

TinyXml,基于SAX 的当然是Xerxes。

模的翻修之后,达到了比较完善的

前者小巧快捷,便于使用,适合于做

软件的可配置型提出了越来越高的

程度。

数据交换。后者则是全功能的XML解

要求。传统上只要通过命令行参数

析器。微软平台上的开发者可以使

来配置的系统,现在可能需要越来

用 msxml 组件来进行 XML 编程。

越多的方式和机制。目前越来越受

其它可以选择的替代品还有 C
语言的pcre库,Qt中的QRegExp类等。

另外,XSLT相关的工作可以参

矩阵计算:MTL
自 1995 年以来,C++ 在科学计

配置管理:Lua
随着软件系统越来越复杂,对

欢迎、并且得到越来越多证实的做

考 Xalan 库。这也是一个比较可靠的

法,是将 Lua嵌入到 C/C++程序中,

XML 处理库。

而用 Lua程序作为配置脚本。这种做

算领域当中取得了巨大的突破。这主

法的优势是,Lua 语言强大灵活,可

内存管理:boost::smart_ptr,
Hans-Boehm GC

以适应复杂的配置需求。同时,Lua

使得 C++ 在科学计算的性能方面取
得了巨大的进步,一大批优秀的C++

C/C++ 的内存管理是一个永恒

行速度非常快,可以说是目前解决

科学计算库涌现出来。比如Blitz++,

的话题。一般来说,C++的开发者倾

C/C++ 程序配置管理问题的一个出

POOMA,MTL,Boost::uBLAS。而这

向于自己管理内存。然而,出乎很多

色方案。

其中,MTL 就功能丰富程度、性能、

C++开发者意外的是,近期C++的一

发支持和成熟程度来讲,是比较突出

些领袖人物已经公开宣称,如果不配

的一个,因此可以优先考虑。特别值

备自动内存管理机制,用C++编写安

安全是今天进行C/C++编程无

得一提的是,2002年,MTL 与后来被

全可靠的大型程序是非常困难的。而

法回避和必须重视的问题。然而编

Intel 收购的KAI C++配合,曾经在性

Bjarne Stroustrup也曾经对中国开发者

写安全的应用程序,特别跟网络相

能评测中击败了FORTRAN。

建议,如果没有特别的理由,应该在

关的C/C++应用程序,是一件十分

大型项目中使用自动内存管理工具。

困难的事情。可以说,整个业界目

算领域,但是直到 C99 中加入 restrict

因此,今天的C++开发者应当积极地

前在这个进程上仍然处在“初级阶

关键字,才具有挑战FORTRAN的可能

学习和应用自动内存管理设施。

段”。特别是涉及大量的安全 、密码

要归功于 template技术的高级应用,

C语言也被广泛地运用在科学计

性。不少C语言科学算法库成熟度很

说道自动内存管理 ,比较轻量

便于嵌入 C/C++ 程序,而且编译执

密码及安全:OpenSSL

学相关的算法、规范,如果让开发
者自己来摸索,其工作量和难度达

如果说 C 语言是一把轻快的小匕首,遇谁都是近身猛刺,血溅
一尺,那么这种 C++ 的使用方式无异于左手打铁铸兵,右手挥剑刺
秦,这种精神分裂的状态直接将很多项目变成了既超期超支又质量
低劣的垃圾。

到了不现实的程度。因此必须借助
可靠的相关程序库才有可能提高程
序的安全性。在这方面,OpenSSL是
目前最好的选择,其内容之全面可
靠,已经成为业界标杆。然而,由
于安全编程本身固有的复杂性,即

高,也值得信赖,比如 GSL、Atlas、NR

级的做法是boost::smart_ptr,而激进

使使用 OpenSSL ,开发工作仍然是

等。但是坦率的说,用 C 语言来进行

的做法则是引入完整的 GC 机制。目

非常繁琐的。因此我们也希望能够

科学计算程序设计还是比较辛苦的。

前开源而又比较可靠的GC中,Hans-

尽快看到更简单、更易用的C/C++

Boehm GC 无疑是最受信赖的。作为

安全程序库。

商业级科学计算库中,IMSL 特

Programmer

47

特别策划

Features
一方面 JBoss 最近的巨额并购,

Java 开源生态系统
和框架类库

证明了免费开源产品也能从专业服
务中获得盈利的模式。
另一方面,它们为开源产品真
正进入大型商业公司提供了必须的
商业产品级的质量认证和技术支持
服务。如 SourceLabs公司的认证开源
产品栈 SASH(Spring Axis Struts

□ 文 / 肖桦

Hibernate)。
所以,这类公司并不是人们初时

 Java开源国度的十年

中央公共频道:TheServerSide.com

成就,并不单纯以在SourceForge上的

TheServerSide 是最高级的Java开

项目数量超越 C/C++成为第一这样

源信息流通集散地, 不属于任何官

的数字来计算,而是以一个开源社

方,却做得比任何语言的任何官方

区, 一个生态系统的最终完备来衡

网站都要出色。良好的 Editor制度保

量。每日生活其中的人们可能并不

证了每一条新闻的质量,只要订阅

自觉,但如果爬到山顶回望一下,就

它的新闻聚合,基本可以保证你不

会发现这个生态系统在没有官方的

会错过任何重要的 Java资讯。可

强力规划之下,已完全自由成长进化

能,它也是全球Java开发者订阅

为一个精密运作、繁忙不息的城市:

率最高的 RSS 了。

以为的开源蛀虫,从Jboss.com开始
的备受质疑,到 Spring 的 Interface21
公司的顺利开张可以看到这种转变。
主题索引网站:java-source.net、
SWIK、Manageability
主题索引网站时时绘
制着Java开源世界的地图,
当你需要选型的时候 ,只要
打开相关的主题 ,而不
用在 SourceForge 或

免费的项目 H o s t i n g 服务提供商:
SourceForge和 dev.java.net

JCP 专家组和 JSR 标准

者 Google 麻木的翻

尽管越来越多开

页。最著名的一份

免费的 Hosting 服务是一切存在

发者抱怨JCP 过程的

目录在java-source.

的基础,很难想象没有SourceForge的

缓慢,但就是这样一

net,而国内的open-

开源世界是怎样的。如果追求Java血

个由 Sun 官方、几大

open.com 提供了毫

统的纯正,那还可以选择 Sun的dev.

厂商还有一些独立

不逊色的中文版本。

java.net。Spring 的相关项目 AppFuse

专家如 Hani 组成的,

还有 S W i k . n e t 是

和SpringModules就选择了后者。 在国

在软件世界里独一

SourceLabs 反馈给

内,JavaEye、满江红、JavaScud 和共创

无二的,类似议会

开源社区的一个内

软件提供了同样的服务。

的组织,为散漫的

容丰富的开源 Wiki

开源运动提供了某

网站。

开源厂牌:Apache Jarkarta、JBoss、

种神奇的规范制约

CodeHaus、OpenSymphony 和 Eclipse

和联系枢纽。如果

熟悉独立音乐、喜欢淘打口碟
的同志都熟悉一个名词——厂牌。

生态系统里还有什么?

你关心Java的未来走向,不妨去jcp.

还有每年几次飞来飞去的研讨

org 看看那些即将诞生的 JSR 规范。

会为开源项目开发者提供了见面交

和独立音乐一样,正是厂牌和厂牌

流、互递名片的机会。JavaOne2006

所代表的含义,将一些最重要的项

开源服务提供商:JBoss、SourceLabs、

(java.sun.com/javaone)已经由官方会

目从SourceForge数以十万计的项目中

SpikeSource、Gluecode、Interface21

议 变 成 了 开 源 大 赶 集, 其 他 如

抽取出来,以厂牌的资金来源和内

这类专注于为开源产品提供服

TheServerside 年会(javasymposium.

部助力,始终保持了开源运动中最

务的公司,为开源世界作了至少两

techtarget.com)和欧洲最大的Java研

中坚的力量。

方面的贡献:

讨会 JavaPoils(javapolis.com),更是

48

程序员

程序员开源手册

>>> 

早就由开源唱了主角。
但这也不妨碍会议里经常出现

投入到各种新鲜框架的试用和Hiber-

定了它和 JBoss 一样,绝不止于一个

nate pk Ibatis、Struts vs. Webwork

纯粹的应用服务器这么简单。

IBM、BEA、Oracle 工作人员的身影,

vs. Spring MVC vs. Tapestry 这种永

因为 Java 社区里还有很多忙着为开

无结论的辩论中。

Web Service:XFire、Axis2

源出钱出力出代码的厂商,I B M 对

但在 C#.net 和 Ruby On Rails

Axis 是 J2EE 时代 Web Service 的

Apache资金会、Eclipse的支持有目共

的双重夹击下,大家开始思考社区

事实标准,可惜它和Apache的其他学

睹,又比如ThoughtWorks,不单有很

智力资源分散造成的浪费。终于,在

院派产品一样以复杂繁琐为终极设

多员工是CodeHaus各项目的参与者,

大家都厌倦了 Yet Another MVC

计目标。趁着 Java EE 1.5 推出一系

自己也有专门的 O p e n S o u r c e 站点

Framework 之后,有了 JSF 和 EJB3的

列 Web Service 新规范——如访问

标准,有了Struts 和WebWork主动合

XML 性能大大加强的Stax规范,新的

(opensource.thoughtworks.com)。

Java-XML 绑定方案 JAXB2,简化开

除此之外,还有最为活跃的博客文化,和很多敢于在项目里使
用开源框架甚至最新版本的狂热份子,以及因为使用开源框架而获
得巨大利益的开发者。

发的 Annotation 方案 JSR-181 等,
CodeHaus推出了XFire(xfire.codehaus.
org),一个与 Spring、Pojo 等名词联
系在一起的新一代Web Service框架。

Java EE 快速开发框架:

并成Struts Action2(struts.apache.org/

Spring Framework、Seam、Rife、Grails

struts-action2)的尝试。

Spring Framework占据Java EE 框
架首位已有年头。今年因为Ruby On

SOA、ESB、JBI、ServiceMix
面对这三个未来大热的名词,
国内实际应用的项目还不多 ,但国

应用服务器:JBoss、Geronimo

外已经准备好了充足的开源产品:

Rails 对 Java社群的集体刺激,Spring

传统的应用服务器供应商最近

LogicBlaze 捐献的 Apache ServiceMix

终于多了几个新伙伴,JavaOne2006

食不知味,因为JBoss 与 Geronimo吃

(servicemix.org),IONA捐献的Object

上的快速开发框架分会场多了Seam、

错药似的快速成长。

Rife、Gails、Tails的身影。

Web Celtix(celtix.objectweb.org),

JBoss 除了一改叛逆姿态,第一

CodeHaus 的 mule(mule.codehaus.

其中 JBoss 的 Seam(jboss.com/

时间抢推符合 Java EE 1.5 标准的

org), 还有Sun的OpenESB和JBoss的

products/seam)是 JSF+EJB3,标准得

JBoss 应用服务器,JEMS(JBoss En-

S O A 方案。其中印象最深刻的是

不能再标准,官方得不能再官方的

terprise Middleware System)计划也搞

ServiceMix,又是一次开源社区总动

方案,商标上写着“从良”二字。

得有声有色,规则引擎 JBoss Rules,

员,集成了无数的开源产品。

而 Rife(rifers.org)则是野得不能

工作流引擎 JBoss JBPM,还有JBoss

再野的方案,将 Java EE 各层敲碎了

Portal、JBoss Cache,还有最近收购

重新实现,期望着自己也能重现RoR

的支持异步 Web 服务事务的 JBoss

的神话。

Transcations。

另外,Grails(grails.org)就比较

规则引擎:JBoss Rules
JBoss Rules 的前身 CodeHaus 的
Drools,只是被无奈的称为“最好的

而最近才出现的Apache Geronimo

开源规则引擎产品”,被JBoss招揽后

中规中矩,一手紧持Spring与Hibernate (geronimo.apache.org)是又一个有趣

的华丽变身,使它有了直追ILog的商

这些 Java 开源骄傲,一手以动态的

的集合 ,跑马圈地似的掠夺了

业品质,使Java有了真正意义上的规

Groovy 语言全盘照抄 Ruby On Rails。

CodeHaus、Apache Jarkata的大部分项

则引擎。JBoss Rules 新版的规则语

目,玩票般拼凑在一起居然符合了

法,DSL 语言定义和Eclipse 插件,尤

O R M 与 M V C 方案: J S F 、E J B 3 、

Java EE 1.4 的规范。而且,因为它

其是以Mapping方式而不是语义解释

Hibernate、Struts Action2

采用的拼装式框架,除了拼装应付

进行的DSL 语言定义,使平民团队大

Java EE 规范外,还可以方便的集成

规 模 使 用 规 则 引 擎 的 机 会。到了

与MVC方案了。有那么一阵子,大家

其他的开源项目如Spring Framework,

2007 年,使用规则引擎表达商业逻

可以永不疲倦的将大把大把的时间

如实现 ESB 的 Servicemix 等等,这决

辑的项目可能会和使用Spring、Hiber-

Java 开源中最盛产的就是 ORM

Programmer

49

特别策划

Features

nate一样普通寻常,进一步稳固Java

products/jbossportal) 是从JBoss Nuke

在企业开发领域的位置。

一路走来正正规规的 Portal 系统。
Liferay(liferay.com) 历经EJB2

报表与商业智能报表:Eclipse BIRT、

到 Spring+Hibernate的重大转型后,拥

Pentaho

有庞大的开发者团队和最多的现成

Java的开源报表方案曾经很长一

Compass(compassframework.org)
对 Lucene 应用于企业领域的简化封
装,将商业对象映射到搜索引擎。

Cache 方案:JBoss Cache

Portlet。

段时间被 JasperReport+IReport 的组合

而eXo Platform(exoplatform.org )

Java各式 Cache方案提供的丰富
功能和强大能力,绝对不是HashMap

占据,直到Eclipse生产出可叫板微软

给人印象的是它剑走偏锋的先进系统

可以替代的。随着 EhCache 1.2 也支

CrystalReport的BIRT(eclipse.org/birt)。

架构,还有连我不懂开发的前老板也

持分布式后,JBoss Cache、OSCache、

BIRT 设计报表时以类似DreamWeaver

留意到的开发人员分红计划。

Ehcache 都是不错的选择。其中JBoss

的方式快速设定和拖放,比上一代的

Cache 的功能最是强大,树形结构提

所有报表方案都方便太多了,而且还

工作流引擎:JBpm、OSWorkFlow 、

供了强大的节点分组管理功能,还

支持很多企业级的特性。

Shark

有对事务的支持,当然配置也最复

而即使高端到商业智能报表,

Java的工作流引擎很多,但又和

杂的。

Java仍然能够给出开源的方案,那就

MVC Framework一样,暂时没有一个

是 Pentaho(pentaho.org/)。集成了

Killer级的选择,总要在易用性和完备

脚本语言:Groovy 、JRub、Jython、

Mondrain+JProvit 做 OLAP 分析,BIRT

性 扩 展 性 之 间 做 出 痛 苦 的 决 定,

Rhino

作报表,K e t t l e 作 ETL 工具,基于

JBpm、OSWorkflow、Shark都不错,但

既Groovy之后, Java继续拼命在

JSR168 Portal 的DashBoard,还有De-

又都不是最好。OSWorkflow 使用灵

新版里加入动态语言相关的 JSR,从

sign Studio,业务工作流,报表的SOA

活方便,但有太多不支持,而 JBpm

此可以看到 Java 对于动态语言的决

发布体系。以每月一个版本的速度

和 Shark 虽然完备了,但工作量总让

心。目前Groovy是接近正式版的嫡系

努力地追赶那些天价的商业方案。

接了任务的弟兄高兴不起来。

全面向对象的动态语言,而 JRuby和

Ajax 应用:DWR、Buffalo

AOP 方案:Eclipse AspectJ、Spring

Java的决心,相信脚本语言在Java一

AOP

定会有美好的未来。

Jython暂时的发展未如理想。但看看

DWR(getahead.ltd.uk/dwr)的创
造性在于1.0 版本时创造了JavaScript

Java的AOP方案本来是很典型的

调用服务端Service层对象从而在传统

三国模式,AspectJ、AspectWerkz 和

基于URL 之外定立了一种新的Ajax模

SpringAOP。前两者已经成功合并,

和类库,比如可以作为Java语言官方

式,而 2.0 版本时更实现了反转Ajax

AspectJ的领导人Adrian Colyer转身就

扩展类库的 Apache Jakarta Commons

的推技术,绝对是个天才型的项目。

以切・格瓦拉的姿态,从IBM跳槽到

(jakarta.apache.org/commons),定时

DWR+Dojo 的组合,将是所有新开项

Spring 的Interface21公司,继续他的革

执行任务的 Quartz(opensymphony.

目的一个重要选型。

命工作。等他革命成功之日,Java就

com/quartz),基于Spring 的安全认证

可以拥有一个统一的AOP平台,真正

的Acegi(www.acegisecurity.org)等等。

把AOP大规模应用到普通团队中去。

版面所限,就不逐一介绍了。

而由国人 Micheal Chen 开发的
Buffalo(www.amowa.net/buffalo)

除去上面介绍的,
还有很多框架

项目是另一个同样优秀的Ajax框架。
全文本搜索引擎:Lucene、Compass、
Portal系统:JBoss Porta、Liferay、Exo
platform
JSR-168规范算是一条比较幸福
的规范,有很多的遵从者,下面三个
是比较容易让人想起的:
JBoss Portal(www.jboss.com/

50

程序员

Nutch
Lucene(lucene.apache.org)的存
在一直让 Java程序员笑得很开心。

作者介绍:
肖桦, 网 名 江 南 白 衣 , 专注于
Java 企业应用开发,博客“花
钱的年华”作者(blog.csdn.

Nutch (lucene.apache.org/nutch)

net/calvinxiu ),Pragmatic

是基于Lucene的傻瓜式一站式网页搜

JavaEE KickStart开源项目

索引擎。

SpringSide(springside.org.cn)的发起者。

程序员开源手册

>>> 

直观的看与C++世界、Java社区
的开源最大的不同在于.NET 是一个
多语言的开源态势,C#、VB.NET、
MC++.NET、J#、Cobol.NET、Foxpro
.NET等借助CTS这个抽象层可以互操
作其他语言编写的开源产品,就如当
年 COM借助IDL实现的目的一样。每
每谈及这些,笔者总要向同道们谈谈
MC++.NET,因为较之其他.NET语言
家族成员(包括明星语言C#),它更
为特别,因为它是将原有Unmanaged
世界在.NET环境下完美呈现的使者,
对于积累了10多年的MFC、ATL如果
要重新用C#把他们的结构全部重新
定义一遍,
而且仅仅依靠可怜的IntPtr
这一根稻草几乎是不可能的。

.NET 开源的简单发展过程
.NET 开源虽然起步晚,但是却
发展非常快,加上Interop、MC++.NET
两个粗大的根茎,.NET开源产品的开
发可以充分使用各种既有资源,也
就是说.NET 开源较之 C++ 和 Java的
开源从一开始就不和它们在一个起
跑线上。由微软直接或间接资助的
.NET 社区,gotdotnet、CodeProject 加
上 MSDN Forum 的“三大”构成了

.NET 开源纵览
□ 文 / 王翔

.NET 开源的主要的发布主体,虽然
从网站数量来看,似乎.NET 的社区
和代码交换网站不如 Java 社区那么
多,但是集中的好处也显而易见,毕
竟.NET 标准始终由微软一家维护,
不像Linux、Java、C++同时有来自不
同厂商、不同组织的多个版本。

 .NET 生于乱世、但是

记忆中微软这种倾力打造的开发技

由于C#、MC++.NET、J#和Java

又生逢其时,它是在以微软 DNA 平

术更迭有三次——OLE、COM、.NET,

语言的相似程度非常高,而且具有

台、Java平台、各种动态脚本语言为

而且此次.NET 似乎更为彻底,准备

property、attribute、ref 和out 参数等语

主角的互联网第一次澎湃热潮之后

更为充分,以至于一夜之间几乎所

法特性,使得.NET 语言使用上更为

诞生的,在微软的描述中它是伴随

有的微软产品、服务、开发技术都被

灵活多样,凭借在.NET诞生时Java社

着世界真正开始考虑如何把互联网、

打上了.NET 的标签,就像 90年代中

区已经积累了大量比较成功的开源

互联系统、无线智能系统、嵌入系统

期一样,什么东西突然前面都加上

库和开源框架,几乎是在半年左右

作为商业交换平台的环境下诞生的。

了一个“e-”似的。

的时间里,很多以前熟知的J****,就

Programmer

51

特别策划

Features

有了 N**** 的翻版。
几乎可以这么说,.NET的开源因

的标准样板。
以 DAAB为例,对于多参数数据

列组合不难发现,仅仅第一代的这
组 Application Block 有机集成的话,

为来得比较晚,有了很多前车之鉴,

库存储过程的调用,被简单的转换

对于上层应用开发人员需要的仅仅

所以它一开始就走得非常顺畅。

为 SqlHelper基于 params的一行代码,

是描述业务逻辑了。为了大力推广

◆ Gotdotnet:作为微软的官方站

而且这其中包括的众多扩展性、易

这种“Application Block Based

点,
提供了很多.NET技术的完整的教

用性考虑至今仍被大多数开发团队

Development”的“搭”应用的思想,

材和Workshop,利于系统学习某一个

称道:

MSDN 站点通过 WebCast作了很多专

技术领域;

◆  为了节省开发人员的代码,

门的介绍。可以说.NET 应用的迅速

◆ MSDN Forum:是“三大”中技

SqlHelper以全static方式向外提供服务;

推广和产品化,这些 A p p l i c a t i o n

术支持最为完善的平台,
.NET 的任何

◆ 对于操作相对复杂的存储过

Block 功不可没,即使到现在一般的

开发技术的问题都有自己的专栏,并

程,为了便于使用,支持params方式

.NET 产品中都会发现 DAAB、EMBA

有微软和全球热心开发人员的参与;

顺次传递参数,而每个参数数组的

等的身影。

◆ CodeProject:是最丰富的.NET

开源代码仓库。

自动发现、封装和缓冲机制则透明
地自动完成;

同样微软也在.NET Framework 1.1
时,提供了两个主要的开发框架:
◆ Aggregation Framework Ap-

为了推动.NET 尽快被软件开发人员使用,从.NET Framework 1.1
开始,微软陆续推出了很多知名的 Application Block,这些 block一方面
满足了绝大多数项目的一般公共库要求,
另一方面也利于开源人员在
一个统一公共的基础上,更多的关注于自己在做代码块的技术实现。

plication Block
◆ UIP( User Interface Process

Application Block)
由于微软整个产品线较为完备,
因此很多集成类项目仅仅需要把既有

.NET 开源的现状

◆ 与 Design Guidelines for De-

产品“拼凑”即可,在Aggregation中

由于.NET 完全植根于 Windows

veloping Class Libraries 的100%的符

提供了“Service + Workflow”的完全

平台,所以他的开源库类型非常丰

合性,保证代码块数据访问上尽可

配置化支持,例如一个OA 系统,可

富,从大处来分主要包括 2 个方面:

能的高效。

以按照要求把 Sharepoint 、Word、

◆ 公共代码库和应用框架
◆ 常用第三方工具

开源代码库和应用框架

而 EMAB 中,Design Guideline 中
Exception Handler 的要求更是体现得

Outlook、InfoPath、Excel同过Aggregation
串成一个有机的联动工作流过程。

淋漓尽致,与Java的强制异常机制不

UIP 则是更提供给UI开发人员一

同,.NET 倡导的是“Need to do”,也

个全新的设计思想——“面对快速

其中公共代码库较之 C + + 和

就是说中间层类库不要处理那些你

变化的业务要求,UI是通过运行态的

Java最大的不同在于微软在.NET 早

根本不知道如何处理的异常。EMAB

配置而不是开发态的变异完成”,界

期已经面向开发人员提供了丰富的

中基于“出版/ 预定”模式的结构让

面的布局、控件、控件间的消息过程

开源 Application Block,范围涵盖了

人眼前一亮,而且通过串行化将Web

通过 UIP 这个可以配置的平台完成,

一般应用开发的最常用部分 。其中

Client、Socket Client、Remoting Cli-

通过准解释方式的方式在运行时动

最为大家熟识的莫过于 DAAB(Data

ent 的错误全部收集到服务器端,仅

态地为用户“画”出一个UI来。此外

Access Application Block)和 EMAB

仅向交互客户端提供友好的错误信

其中 ObjectBuilder 的思想,更是催生

(Exception Management Application

息,这种思想对所有.NET 开发人员

了下一代开源公共库的设计。

Block),前者是用来完成最通用的数

都或多或少有所启迪。

据访问任务,后者是完成异常处理。

此后,微软陆续推出了 CMAB

这两个代码块一出现,立即风

(Cache Management Application

靡整个.NET 世界,以笔者所见出了

Block)、Logging Block、Authorization

功能上的支持外,更多的是给了全

and Profile Application Block和Offline

球.NET 开发人员一个如何使用.NET

Block 等第一代 Application,通过排

52

程序员

与此同时开源社区也为.NET 提
供了丰富的开源代码 ,主要包括如
下内容:
◆ 面向网络应用的

C# Ping、IP多播
(IP Multicasting )、
各种ICMP、SNMP、SMTP、POP 开发库

程序员开源手册

>>> 

和 pseudonym67 的 BackPropagation

序提供了基础,它也是笔者见到的

Network;

最早的 Snap-in的MC++.NET封装的

◆  面向 X M L 的(由于. N E T

成功尝试。

Code-Smith:
它使用类似于 ASP.NET 的语法
来生成任意类型的代码或文本。

Framework 本身对XML 技术已经有了

至与具体的运行监控,
由于微软

很不错的封装,因此比较而言,XML

平台有完整的 WMI 环境,且在.NET

NUnit 是为.NET 框架生成的开放

的通用开源库反而相对数量不多)

Framework设计之初已经有了System.

源代码单元测试框架,它是JUnit的演

Marc Clifton的Xml Database、面

Management 的设置,加之MOM 2005

化版。不过由于.NET的 CTS特性,因

向 SAX2 的 XInclude、Eduardo Diaz的

的推出,因此在开源领域反而没有比

此NUnit 使您可以用喜欢的.NET语言

面向 XML-Sign的 Xml-DSig……

较出名的 WMI库。

编写测试用例,从而测试应用程序的

◆ 面向移动和智能设备的

在Chad Z. Hower, a.k.a. Kudzu

◆ NUnit

特定功能。此外,NUnit还提供了一种

主要.NET 开源支持工具

对应用程序进行回归测试的方法。

的Mobile Agents思想影响下,似乎整

正所谓“工欲善其事,必先利其

个.NET Mobile 开源库开发都是在以

器”,说到开源世界的.NET工具,一

由于.NET Framework的类库非常

Agent 模式展开,虽然没有比较出名

般而言以如下
“十种兵器”
最为出名:

丰富,而且较之Java它的语法内容也

的代码库,但是由于在 VS.NET 环境

◆  编辑和开发工具 S n i p p e t

更多,因此使用不当写出低效代码的

中已经捆绑了现成的调试环境,加

Compiler:

◆ FXCop

可能也更大,为此微软提供了Design

上 Offline Application Block,因此可

Snippet Compiler  是一个基于

Guidelines for Developing Class Librar-

以保证在常常中断的环境中 ,业务

Windows的小型应用程序,您可以通

ies(简称Design Guideline),但是作为

的准连续性。

过它来编写、编译和运行代码。如果

不断更新的代码检查知识库,由于条

◆ 面向密码和隐私的

您具有较小的代码段 ,并且您不希

目很多,因此提供了FXCop的自动代

gek_at 的 SharpPrivacy-OpenPGP

望为其创建完整的Visual Studio  .NET

码复查工具,便于项目组尽早把实现

for C# 为 PGP 这个传奇色彩的密码

项目(以 及 伴 随 该 项 目 的 所 有 文

上明显比较差的部分尽快剔除。

算法书写了.NET 的续章。

件),则该工具将很有用。

此外笔者要着重提到微软的
Michel Barnett, 他用了 1000多行的

◆ Regulator ——正则表达式编

写、调试工具:

◆ 反编译工具.NET Reflector

对于很多.NET 学习和开发人员
而言,当面对有一些非常“Cool”特

MC++.NET向.NET的技术狂热爱好者

Regulator 是一种很有特色的工

性的Assembly的时候,往往首先会想

提供了如何将“Integrated Security =

具,能够使生成和测试正则表达式

到的是“他是怎么做的?”,如果幸

SSPI”,实现在初生的Remoting 上。并

变得很容易。由于 RegExp 在.NET 框

运的话.NET Relector会告诉你答案。

且在此之后,包括类似的复杂Struct、

架中受到支持,因此它常常作为基

它主要通过反射机制,通过解析 IL,

Union、Smart Point的封装工作渐渐都

于字符、频率和字符顺序定义字符

然后可以按照您的喜好把答案用C#

采用了他这种“M C + + . N E T - >

串中的模式匹配工具,但是由于VS.

或者 VB.NET 告诉您。

Assembly->C# / VB.NET”的开发

NET本身没有提供方便的RegExp操作

◆ NDoc

模式。

工具,因此 R e g u l a t o r 从被 R o y

对于微软平台开发人员最熟悉
的开发参考莫过于 MSDN和SDK之类

“厂商的大力支持 +开源社区的积极贡献”。
“三大”的各具特色
的有机整体,又为.NET 开源设计、开发人员提供了充沛的灵感和技
术的保证。

的帮助,但是凭心而论写出每个类
的每个方法的详细设计说明文档,
几乎总是一项令人畏惧的任务。不
过.NET 提供了比 javadoc更好地的纯
XML 的注释系统,因此 NDoc就可以

◆ 面向管理的

Osherove放到互联网开始,它就马上

根据开发阶段开发人员的注释,生

Harish Kumar L 的 MMC 封装,

成为很多.NET开发人员的必备工具。

成标准 MSDN 形式的详细开发参考。

为.NET 开发人员开发标准控制台程

◆  基于模板的代码生成工具

从机制上而言 NDoc 同样在使用反射

Programmer

53

特别策划

Features

方式提取到具体的方法、属性的说

为了将这个过程可视化,常常需要

供了一般MIS应用的基本客户端和应

明,它和实际Assembly内二进制的内

将宿主和客户端(甚至包括Proxy)间

用服务器端开发库支持。

容是一致的,因此为后续开发人员

交换的数据 Dump 下来,用来调试应

此外,各个.NET原生的和翻版的

参考提供了准确的第一手开发资料。

用。TCPTrace就是通过把自己当成一

开发库则弥补了其他各个专业领域:

◆ Build 工具 NAnt

个存储转发的 P r o x y 来保留这些

● 

NAnt 是一个基于.NET 的生成工

InBound 和 O u t B o u n d 信息。对于

● 

NHibernate:完成O/R Mapping;
不断更新的NDoc、NAnt、NUnit

具,与VS .NET 不同,它使得项目的

Remoting、Socket、WS(尤其是WSE)

继续为.NET 2.0 开发人员提供必要

Build过程变得非常容易。尤其当大量

的开发人员非常有用。

的工具支持;

开发人员从事单个项目时,不能依
赖于从单个用户的代码来Build, 而且
定期的手工Build也是很繁琐的工作。

众多 Zip、Codec、Networking、

● 

.NET 开源趋势展望

XML……等开发库面向各个具体领域

随着微软的新一代Enterprise Li-

的开发需要。

通过 NAnt 您可以创建每天晚上运行

brary和以Ivar Lumi的集成网络应用层

不过,由于.NET 的版本更新速

的自动生成过程,它可以生成解决

开源开发库的为代表的新一代.NET

度较快,且.NET Framework容量已经

方案、复制文件、运行NUnit 测试、发

开源开发包的出现,不难发现.NET

很大,因此未来.NET 开源出现了与

送电子邮件等等。

开源在 2004 年下半年开始逐步进入

C++和Java不同的发展趋势,基本上

到一个新的阶段,这个阶段的主要

形成了一个渐开曲线:

◆ ASP.NET 版本切换工具——

ASP.NET Version Switcher
当IIS处理请求时,
它会查看正在
请求的文件的扩展名 ,然后基于该

1. 出现了新的开源开发库或者

特征如下:
◆ 更全面的系统化

是新的开源工具;
2. 微软提供了类似的实现,并

早期的开源库一般集中于某个非

Web 站点或虚拟目录的扩展名映射,

常具体的功能,例如:数据访问、缓

作为独立的SDK或者通过SP 提供给.

将请求委派给 ISAPI 扩展或者自己处

冲、SMTP、POP3、XSLT;而第二阶

NET 开发人员;

理该请求。这正是ASP.NET的工作方

段中很多开发库出现聚合现象,例

式;将为所有ASP.NET扩展名注册扩

如:enterprise library 包括了 Cache、

具集成到VS.NET或者是.NET Frame-

展名映射,并将这些扩展名映射导向

Logging 、Data Access 、Security 、

work 中;

aspnet_isapi.dll。但如果安装了 ASP

Exception;Ivar Lumi的网络开发包则包

.NET 1.1——它会将扩展名映射升级

括了SMTP、FTP、ICMP、POP3、Mime、

到新版本的 aspnet_isapi.dll,这时当

DNS等网络应用层的很多基本功能。

在ASP.NET 1.0上生成的应用程序试

3. 微软将这些开发库、开发工

4. 集成的开源库和工具被更深
入的集成;
5. 由于开发环境本身已经提供

◆ 更高的集成度

了更为便利的支持,进一步催生新

图用1.1版运行时,
这会导致错误。

同样,
早期的开源库多数都以独

的开源库和开源工具的产生。

解决该问题,可以将所有扩展名映射

立 API方式对外提供服务,但是随着

在 VSTS中我们已经看到了类似

重新转换到1.0版的 aspnet_isapi.dll,

实施的.NET应用规模越来越大,
可配

CodeSmith、NUnit、FXCop 的替代产

但是由于有18种扩展名映射,
所以手

置化、可监控性、可管理性、安全性

品,也从.NET Framework 2.0 种看

动完成这一工作将很枯燥,这时候只

的要求也逐步加强,以Enterprise Li-

到了串口等众多新的开发库 ,有了

要用ASP.NET Version Switcher做一个

brary为代表的新一代开源库纷纷提功

这些平台级的扩展相信未来.NET 开

简单的设置即可。

能类似 ObjectBuilder 的对象内嵌装配

源领域会更加锦上添花。

◆ 网络调用的简易Dump工具,

TcpTrace
对于.NET平台的网络开发人员,
为了诸如加密、签名、散列、Context

技术,而外围的公共库则按照Plug &
P l a y 的方式允许用户自由的按需选
择,但是所有生成的对象是按照配置
要求在公共库的核心工厂装配好的。

作者介绍:
王翔,分布式异构数据库方面的

传递等要求,会在TCP分组的头部塞

◆ 通用化 + 领域专业化

高级开发工程师,对各种商业数

入一些outbound 的信息,同时分组体

通用化开源库主要包括微软提

据 库 有 较 深 入 的 了 解,也 是 微

也可能是处理过的 InBound 流信息,

54

程序员

供的 Enterprise Library、UIP 2.0,提

软.NET 平台技术方面的专家。

程序员开源手册

>>> 

握主动权,去选择适合自己特点的

自由与开放的数据库

开源软件。主流的开源数据库可供
选择的余地其实很大: M y S Q L 、
Firebird 以及PostgreSQL等等都是当今
使用非常广泛的产品。

□ 文 / 何伟平

同其他开源软件项目一样,每
个产品都有一种开放的软件开发模
式,然而数据库产品却与一般的软
件产品不同。这种不同恰好对应Eric

  如果从有趣一点的角

据库”,则通常是指利用 SQL(结构

Remond 的那篇文章,
“教堂与集市”。

度来看计算机的发展史,就会发现

化查询语言)进行交互的用于数据

其区别就像超市与农贸市场 。超市

整个计算机的进化史是一个不断抽

检索的软件。

里,肉、禽、蛋、菜,包装得好好的,

象重复劳动,减少人为失误的历史:

如果说网络和操作系统是构造

用户只需做熟即可;而开源软件项

从厌倦了给纸带打孔 ,到发明了输

现实中的现代计算机世界的两大基

目的开发模式,更像农贸市场。大家

入输出设备;从厌倦了五花八门的

石,那么数据库就可以称得上是这

会拿着冬大米、柴鸡、柴蛋、鲜鱼、

设备,到创造了操作系统;从厌倦了

个世界中应用软件的基石了。

刚拔下来的蔬菜交易,纯天然、无污

事无巨细的文件检索 ,到数据库乃
至搜索引擎的产生……每一次都极
大地减少了重复劳动 ,降低错误的

染,但没有精加工,需要我们用户自

数据库的开源世界
做了多年的应用开发,因而也

己回家折腾才可口。
从开发的角度来说,开源软件,

发生,极大促进了计算机世界发展,

用了多年的数据库,商业的、开源的

准确说是开源数据库 ,会尽量避免

这些进步是人类想方设法解放自己

——或者叫做自由的 ,对各种数据

“重新发明轮子”,因为开源软件/数

思维的历史。

库也算是稍微有些研究。然而每当

据库的开发人员绝大多数都是“临

在数据库的选择中,常常会面临各

时工”或者“爱好者”,因此开发力

种各样的取舍。

量相对薄弱。比如PostgreSQL数据库

从另一个角度看,计算机的发
展史,也是也是一部查找、检索的历
史。人类面对信息,似乎总是无瑕处

抛开商业数据库昂贵的成本不

的核心开发人员总共只有五、六位,

理,计算机的出现则极大提高了人

说,在今天这个提倡开放的世界中,

所有提交人员也不过十几二十人。

类检索信息的速度,甚至可以说计

自由的软件成为人们更加热衷的话

相比之下,甲骨文数据库的提交者,

算机天生就是为人类检索信息而诞

题。尤其是那些在软件行业中摸爬

光中国就几百。

生的。这个方面用80/20定律并不过

滚打了多年的程序员 ,他们喜欢把

在开源数据库中,很少有开源

分:全世界计算机 80% 的时间里是

数据库会支持裸设备(除非是前身

在做检索的动作。

商业软件,后开源的数据库),因为

而数据库,可以认为是上面说

裸设备之于数据库,就好像数据库

的简化思维和查找这两个要素的

放弃了 O S 提供的文件系统这个轮

交点。

子,重新自己实现一个文件系统。你

我们几乎每个人每天都在使用

不得不考虑不同体系(Intel、IBM、HP、

数据库,在计算机里,离我们最近的

Sun 等),不同平台(Linux、FreeBSD、

数据库不是Excel,不是Access,而是

AIX、HP-UX、Solaris 等)。因此,开

我们天天要用的文件系统 !没错,

源数据库很明智地把这部分工作交

文件系统也是一类数据库,而很多

给了不同的文件系统。

人常用的搜索,不管是 Google 还是

通过开放式的生产环境 ,造就

Yahoo 或者其它搜索引擎,都可以归

出的产品可信度是非常透明的。然

类为某种特殊数据库。而今天的“数

而软件开发者在面临选择的时候,

Programmer

55

特别策划

Features

仍然颇费一番心思。除了考虑自身

既不要写太多代码,也不要搜索和

架构的话,就必须再花一笔不菲的

软件产品或项目的实际情况以外,

学习如何使用特殊软件包。并且SQL

银子去购买类似 RS6000或者Sun/HP

一些重要的特性也是在数据库选型

属于4GL,远比多数计算机语言来得

的小型机,这些硬件以及系统的价

当中非常需要关注的。

简单得多。

格要远比我们用的 AMD 替代品昂贵
(数量级上的差别)。

数据库的易用性奠定基石

应用选择数据库产品

同样是这个项目,公司里一些

在使用数据库过程中,自己最

其实,应用软件需求多变,程序

熟悉PHP的开发人员对特殊存储过程

大的体会就是要提高软件产品的易

往往赶不上需求变化 。选择具有更

有所了解的人很少,为了增加封装

用性。数据库几乎是一个万能的工

多特性的数据库产品 ,就意味着更

层次,以便整个软件的灵活修改(朝

具箱;甚至连很多日常生活的事情,

灵活、可以适应更多不同的开发人

令夕改在软件开发流程中是常见

我都喜欢用数据库处理。比如,因为

员并行。在这个方面,开源的数据库

的),从设计上增加了一个存储过程

工作关系,自己经常需要和国外的

优势明显。

组成的层次。在这种情况下,大多数

同事开会,这个时候时区就成了一

前不久公司的新项目,开始想

同事都不熟悉PL/PGSQL这种存储过

个挺要命的问题了,因为其它国家

使用某商业数据库,然而其昂贵的

程,因而成为开发中的一个难点。但

很多都有夏时制的概念,而对于我

价格让老板产生了动摇,随后开发

是通过使用PostgreSQL支持的PHP写

们来说,并不是很清楚究竟何时他

人员又找到了新问题:由于我们用

存储过程特性,结果是所有开发人

们会切换时区。这时候我通常都会

A M D 架构上的 6 4 位 L i n u x ,针对

员写得那叫一个欢。最后的总结,当

在 PostgreSQL 中做一个这样的查询:

x86_64 架构优化了 OS,而该数据库

然是这个项目得以相当顺利地实施。
因此可以看出,开发人员熟悉

psql -c "select current_timestamp at time zone 'PDT'"

的工具,要比软件本身在项目中起
到的作用更重要。

周围的同事常常要进行数据的

产品竟不支持这个平台,这时开源

统计和运算,比如网站访问的日志

软件的优势就产生了。随后,我们自

分析和统计。记得一个日志分析程

己在这个系统平台上编译了开源产

使用开源数据库和商业数据库

序,要求对每个访问来源的独立IP的

品PostgreSQL,各个方面都比那个商

不太一样,商业数据库往往有非常

访问次数进行统计,同事为求简单,

业数据库效果好。如果当初坚持采

好的外围工具,比如管理工具,监

写了一个脚本,先查询IP,然后用每

用该商业版数据库,并且使用 64 位

控工具,调试工具等等。这些方面,

开源对 DBA 更高的要求

个 IP 遍历日志,求每个 IP 的访问总

在开源数据库来说,是一个薄弱的

数,结果该脚本跑了两天都没跑出

环节。因而,对使用开源数据库的

结果来。看到这个情况,我建议同事

开发人员和管理人员提出了比较高

先把日志做简单格式化处理 ,然后

的要求。

输入到数据库里,创建一些合适的

在使用开源数据库(甚至大部

索引之后,只要跑一个SQL命令,就

分开源软件)的时候,有一个几乎亘

可以跑出来所需要的结果。后来我

古不变的要求,就是至少必须熟悉

们从网络上拷贝数据、解压缩、格式

一种Unix(其实熟悉一种也就都差不

化、输入数据、创建索引、查询并得

多了),并且成为不错的 Unix 系统管

出结果,整个过程只花了不到三个

理员,就目前来说,Linux和BSD系列

小时。

是比较容易获取的两种系统 ,目的

可能有人会说,难道这些事情

就是熟悉这些Unix的文件系统。有这

非数据库干不可? 不错,Perl或者其

样的基础,磁盘和文件相关的代码

它脚本都有相应的程序库处理,但

都可以交给操作系统完成,并集中

是,使用数据库确实更简单——我

力量做更需要做的事情。
(跟应用一

56

程序员

程序员开源手册

>>> 

样,集中精力做自己专注的事情,其

Firebird

实所有软件又何尝不是如此。)而

目前版本是 2.0,源自 Interbase

且,对数据库乃至应用的系统优化

6.0,是著名的 Borland 公司的产品。

起到相当关键的作用。

功能丰富、完整,也久经考验(数据

实际上,数据库的性能优劣,很

库的实现很复杂,一个特性,比如支

大程度上可以通过一些操作系统来

持事务,并不等于你支持了这个特

甄别、分析和解决。比如,整个计算

性,就可以可靠、安全地使用了,还

机里的瓶颈是磁盘IO,因此,如何有

需要很长一段时间的考验)。Firebird

效地提高 IO 速度,减少 IO 量就是提

以前的问题是支持和用户组不够活

升性能的根本之道。在笔者的一个

跃,并且特性开发周期也比较常。这

数据库(PostgreSQL)里,几亿数据

我是一个 PostgreSQL的DBA,因此先

两年明显感觉的这些缺点在逐步弥

量,相当于一个数据挖掘的系统,每

在这里谈谈它:

补,Firebird 的用户圈在逐步壮大。预

次运算都要消耗八九个小时 ,其硬

祝我们有一种新的强大的开源数据

件是一台拥有 8G内存,运行Linux的

PostgreSQL

AMD64。为了提高性能,首先的做法

目前PostgreSQL的版本已经到了

常常是尽量加大内存 。然而再大的

8 . 1 了,支持非常丰富的数据库特

数据库,比如 MDBM 、CloudSpace 、

内存面对这种数据量也是杯水车薪,

性,称之为最先进的开源数据库一

BerkeleyDB 等,这些轻小型的数据库

IO 仍然非常密集。接下来,我仍然从

点不过分。目前稳定版本的特性包

更像是一个散列表(Hash表),简单、

硬件结构上琢磨,先做了RAID10,保

括完整的 ACID 支持、子查询、查询

快速,但是并不是经典的关系型数

证数据安全的同时,增大磁盘IO的带

改写规则、触发器、表空间、表分区

据库在这里就不赘述了。

宽,并单独使用十块 I D E 硬盘组成

等等。PostgreSQL 这个开源项目到今

RAID5 用于存储海量数据,这样整个

年正好十年。其用户目前正在疯涨,

系统的IO子系统性能相对提高了。另

很多商品数据库的用户都在转向使

写作此文,我无意做任何数据

外一个调节是对 L i n u x 内核打补丁

用 P o s t g r e S Q L 。以前很多人认为

库对比,文中所有描述均是基于个

(还是国人的补丁),这在读取磁盘

PostgreSQL速度慢,但是从大量从商

人的经验以及理解,只是一个经验

的时候,可以把当前磁盘块儿后面

业数据库转移过来的用户反馈来看,

的分享。除了极其个人的观点之外,

的几个也一起读进来 ,这样的优化

完全不是那么回事。PostgreSQL有很

文 章 里 大 多 数 语 言 都 将 是“如何

对于数据库类应用非常有用 。因为

稳定的开发队伍,很活跃的用户组

做”,而不是“更好”或者“比较”。

在数据库应用中,很有可能下一次

(包括中国),是一种很有潜力的数

请求的数据就是当前磁盘块后面跟

据库。

着的磁盘块,所以如果内核能预读

其它还有一些特殊类型的开源

写在最后

我相信绝大多数读者拥有足够的智
慧进行分析和判断,也希望读者有
自己的选择。

一部分磁盘到文件系统缓冲 ,那么

MySQL

下次读取就会是在内存里,而不是

目前Mysql的版本是5.0.21,经

磁盘上。

库可以使用。

过漫长的等待之后,Mysql终于开始

作者介绍:
何伟平:Postgresql中文
版文档维护者,《Perl  编

上面唠嗑了半天,其实还是想

了对事务的初步支持。Mysql是一种

程》第三版译者,Linux集

说,这些经验和知识,恐怕是用非开

相对简单、快速的数据库,有着SQL

群管理员及数据库研究人

源数据库一辈子也不可能了解到的。

界面,到了版本 5,开始对事务以及

员和软件开发人员。有近

当然,软件产品的选择没有好坏,但

一些存储过程方面的支持。因为简

十年的软件开发经验,在

我更倾向于让自己多掌握一些。

单,所以Mysql 使用方便,速度也比

金融、工业和互联网等行

较快。支持等方面也非常好。只是最

业有着较长的经历。现供

开源数据库产品简述

近谣传甲骨文有意收购之,不知道

职于某互联网公司,从事大型集群管理以及技

读者看到这里大概可以猜测到,

将来会如何。

术指导方面的工作。

Programmer

57

特别策划

Features
用 Python或是Ruby之类的动态语言,

开放的动态语言兴起之路

所需的代码量往往只有Java的1/10,
这个数字和 C/C++ 相比差距更大。
系统软件和应用软件之间的区
别越来越明显,开发系统软件仍然

□ 文 / 霍炬

需要静态语言,而应用软件和服务
的开发越来越适合采用动态语言。
编写操作系统之类的系统软件仍然

 让我们倒退到 60年代
末,那个计算机的上古洪荒年代。当
时,微处理器诞生不到 10 年,这个

C 比 Lisp 更友好。至于 C 带来的性

要“压榨”计算机性能,而对于应用

能提升,并非他们关注的要点 。

软件,显然缩短开发周期更加重要。

C的诞生是为了编写Unix操作系

新兴的动态语言除了语法简洁

年代的计算机开始大量使用集成电

统,这是第一个可以用来写操作系

外,大量的程序库也降低了动态语

路,小型机开始替代古老的大家伙

统的高级语言。在此之前,所有的语

言的开发难度。成熟的程序库降低

们。一年后,Unix才出现在实验室中,

言都可以看作计算机科学家贡献给

了动态语言的开发难度,反过来,开

而C语言,还需要等待4年才会出现。

其他学科的,C语言是给计算机科学

发难度低又吸引了更多的程序员开

领域自己的礼物。计算机的黄金年

发程序库。一个C++程序员,往往经

代开始了。

过了几年的训练仍然不能开发出可

那个年代,这块神奇的大陆上
活跃着Fortran、Lisp、COBOL、Simula、
BASIC、PL/I、Ada、SQL……但现在

1950年,全世界只有100台计算

用的程序库,动态语言的程序员经

我们惊奇地发现,这些语言仍然好

机,但到了 1990 年,计算机则成了

过几个月的训练就可以编写可复用

好地生存着,所有语言都是带有动

普通办公用品 ——性能越来越高,

的代码了。这些代码往往以开源的

态特性的函数语言态。

硬件成本逐年下降,企业成了软件

形式发布,容易被学习和使用。

1972 年,往往被认为是现在静
态语言年代的开端,这一年中,C语

市场的最大客户。而在企业软件中,

程序库往往决定了一种语言应

性能方面不再像 30 年前那样重要。

用难度,纵观历史,凡是具有优秀程

与此同时,多台服务器的并行

序库的语言生命力都很顽强 ,反之

ARPANET 诞生,Internet 的大幕拉开

处理和分布式处理是开始用于解决

则多销声匿迹。目前几种流行的动

了。随后的10多年中,C++、Pascal之

性能问题。企业应用的瓶颈逐渐出

态语言,都拥有丰富的程序库 ,在

类的静态语言依次登场,逐渐成为

现在逻辑、开发难度和开发维护成

Python 中,不仅具有诸如网络应用、

主流开发语言。

本。而动态语言优势恰好灵活、易于

多线程、图像处理、科学运算之类的

开发和学习 ,尽管其性能不如 C /

库,甚 至 还 拥 有 多 套 不 同 量 级 的

言诞生,Intel 8008 微处理器诞生,

在1972 年之前,所有的语言都

Framework来辅助Web开发。事实上,
任何需要的功能几乎都能找到相对

在 70年代那个内存要以 K计,主频仅有几兆赫兹的年代,硬件极
其昂贵,操作系统和软件对于性能的需求很高,操作系统是计算机的
基础平台,与专业领域的应用不可同日而语。为了性能,程序员们宁
愿使用汇编,但考虑到移植性,C 还是成了他们最喜欢的语言。

稳定的库,大部分程序员仅仅需要
组合这些库就能编写出强大的应用
——这也正是动态语言开发程序代
码量较少的原因之一。
Python、Ruby、Lua、Perl 是四种
颇具代表性的语言,按照一般的看

是 为 了 某 种 专 业 用 途 而 开 发 的,

C++来得那样高效,但是仍然开始受

法,这些语言适合用来黏合不同的

Fortran 为了工程计算,Lisp 用于人

到瞩目,以至于在高性能服务器和

系统和模块,素有“胶水”之称。当

工智能,C O B O L 用于处理商业逻

并行处理的设计思路下,动态语言

然,后来人们发现胶水不仅仅能粘

辑……这些语言的用户往往是各领

的优势如此耀眼,掩盖了其性能上

合其他模块,其本身也具有强大的

域的工程师或科学家,他们不认为

的劣势——完成同样功能的时候,

功能,在性能问题不那么重要的场

58

程序员

程序员开源手册

>>> 

合,动态语言的发挥空间极大。对这

以用做 Shell 脚本的语言之一,许多

Ruby 简单得多,Ruby on Rails风

个时代的程序员来说 ,掌握一种动

系统管理员很喜欢它。尽管近年Perl

头正劲,甚至已经让人说不清是Ruby

态语言很有必要,虽然你不一定能

的风头被 Python 抢去很多,但拥有

和 Rails 到底谁成就了谁,总之,用

够靠单单一种动态语言找到一份喜

CPAN程序库的Perl,仍然是最强大的

Ruby 开发Web应用,非Ruby on Rails

欢的工作,但适时地采用动态语言,

语言之一。

莫属。无论是整个框架的结构还是

一定可以让你的工作简单许多。

在使用这些高级语言的同时,

界面的AJAX支持,Rails都水到渠成。

了解动态语言和常用的程序库

我们常常会遇到很多前人遇到过的

Perl 的 Mason名气很大,也很成

的特点,是开始动态语言编程的第

问题。随后,开源社区将这些可以复

熟,不过开发思想和Perl原本的思路
差距甚大,如果能适应,这倒是个不
错的选择。其实Perl本身就很适合做

动态语言程序员有非常丰富的库资源可用,比起其他语言的开发
者,这是莫大的幸运。
然而,面对这丰富的资源,哪个程序库好用?哪
个程序库或框架更适合你的项目?每个库的特点又是什么 ?要搞清
楚这些问题要颇费一番时间精力 。
幸好在开源社区,有众多参与者的
项目往往不会太差,代码和文档齐备的开放项目都值得一试。

Web开发,只要有FastCGI,利用CPAN
库,大部分应用都能轻松解决了。
Lua 用来做 Web开发有点怪,因
为它毕竟不是为了这个目的设计出
来的。但是也有一个叫做Kepler的项
目提供了 Web 框架,用起来也方便。
不过 Lua最好的用途还是写脚本,何

一步。下面是笔者对几个具有代表

用的问题建成了程序库或者框架,

性的动态语言的了解:

进一步提高了动态语言的开发效率。

必用来做 Web 呢?

GUI 界面库

Python不仅在所有主流操作系统

按照现在的一般开发需求,我们需

上都能运行,而且得到了很多工业

要的程序库通常是这样几类:Web开

控制和嵌入系统的支持,除了各种

发框架、GUI界面库。其他辅助工具,

成熟的大概只有两个:wxWidgets或

Unix-like 的系统,Python还能运行在

至于XML解析、字符串处理函数之类

是 GTK。wxWidgets的可用性和美观

Palm,索尼的游戏机PSP,Nokia的手

大路货,已经俯首皆是,不值得专门

程度都优于 GTK,很受欢迎。

机操作系统 Symbian,风河的嵌入操

介绍了。

能够跨平台的 GUI界面库,比较

wxPython、wxLua、wxRuby都是
不同的语言下对 wxWidgets 的封装,

作系统 VxWork 上。Python 被称做最
强的脚本语言,无论开发Web应用还
是普通应用程序都十分方便。

Web 开发框架

虽然成熟程度不一,但是无一例外,

Web 如此流行,不仅仅是网站,

都受到了开发者欢迎。

Ruby 语言特点类似 Python,但发

企业信息化软件和部分个人桌面网

其它辅助工具的程序库实在太

展相对较慢。Ruby最近因为Rails框架

站也采用了Web界面。Web界面成了

多,每个程序员都有自己喜欢的一

而成为了炙手可热的动态语言,Ruby

和普通 GUI并行的一种选择。如此众

套工具。在这里就不一一列举了,在

on Rails适合企业应用,大量Java用户

多的应用,使Web开发框架变的如此

随后的几篇文章中,您将可以看到

对Rails产生了浓厚兴趣,他们甚至认

重要,几乎所有语言都有了不错的

更多与动态语言相关的内容。

为 Ruby on Rails 会对 Java造成冲击。

Web 开发框架,而且还不止一套。

Lua 小而快速,目前多用来编写

Python的Web开发框架多得足以

游戏引擎所需要的脚本。Lua代码精

让人挑花眼,比较有名的就有类似

巧,比起 Python或Ruby,Lua小得多。

Ruby On Rails 的 Django 和 TurboGear,

霍炬: 爱技术, 喜代码, 尝倾心

暴雪的著名网络游戏魔兽世界的配

模仿 Tomcat 的 webware,轻量级的

于 C,略有小成,而后学各类远

置脚本和插件都是采用 Lua 编写的,

Quixote、karrigell 以及更轻量级、用

古晦涩生动之语言架构及思

这令 Lua 的开发者迅速增加。

Apache 模块实现的 Mod_Python 和

想, 终于杂而不精。建筑专业

Vampire。所有框架都各有特点,当然

出身,混迹 IT 圈,略有所得, 秉分享之志而舞文

Perl 是最古老的动态语言,强于
数据分析和计算,也是Unix平台上可

这也可以换个角度看作各有缺陷。

作者介绍:

弄墨。

Programmer

59

特别策划

Features
Perl 在 Web 应用中的软件

Perl 在 Web 开发中的

我们首先看看在 Web 体系中一
个应用的逻辑结构图,如图 1 所示。

应用和程序库
□ 文 /James Zheng

 Perl(Practical Extrac-

将永远自由下去。你可以在任何合

tion and Report Language)是一种脚

适的场合使用 Perl,只需要遵守一个

本语言。最初由拉里・沃尔(Larry

非常自由的版权。如果你在从事商

Wall)于1987年12月18日发表。Perl

业活动并且还想使用 Perl,尽管用!

借取了 C、Sed、Awk、Shell Scripting

当前 Perl 虽然没有像 S u n 支持

以及很多其他语言的特性。其中最

Java那样有大公司来全面支持它,但

重要的特性是其内部集成的正则表

我们仍然可以看到几乎所有的大公

达式功能以及巨大的第三方代码库

司都在使用Perl。一些知名网站,如:

CPAN。

amazon.com、bbc.com、Yahoo都在使

图 1:一 个 典 型 Web 应 用 的 逻 辑 结 构

Perl语言的思想可以概括为一句

用 Perl开发或者管理他们的网站;与

Perl 在这个应用中,除了是开发

话:
“There's More Than One Way To

此同时,Perl在金融数据处理、生物

的主要工具外,在服务器监控、服务

Do It.”Perl语言直接提供泛型变量、

工程科学等方面,基本上达到无可

器集群等方面的应用也起了不可代

动态数组、Hash表等更加便捷的编程

替代的地位;至于应用软件就更多

替的作用,在这个结构下包含了这

元素。它具有动态语言强大灵活的

了: W e b m i n 、A W s t a t s、M R T G 、

样一些常用的软件:

特性,并且从 C/C++、Basic、Pascal

S p a m a s s a s s i n、M o v a b l e   T y p e、

◆ Apache/Mod_perl/FastCGI:这

等语言中分别借鉴了语法规则,从

Slashcode 都是使用 Perl 编写出来的。

是用来创建Web应用的服务端,尤其

而提供了许多冗余语法。这使得程

当然,眼下我所从事的工作主要集

是Java EE领域,应用服务器常常是极

序员可以忽略计算机内部数据存储、

中在Web应用领域,因此也从一些像

为重要的一个开发部分。然而在使用

类型、处理方法、运算规则、甚至内

服务器监控、服务器集群等相关的

P e r l 开发的环境下,我更喜欢使用

存越界等细节,将精力放在程序逻

应用中了解到了 Perl强大的力量。然

Mod_perl来解决我手边的工作,毕竟,

辑上,Perl也因此获得了write-only的

而,对我来说体会最深的还是CPAN

它更适合于大型Web应用的开发;

“美誉”:因为许多 Perl 程序的代码令

(search.cpan.org)这个 Perl 资源的宝

◆ Oracle/MySQL/other DB:所

人难以阅读,实现相同功能的程序代

库。在这里,你几乎能找到您需要的

有的Web应用都存在数据层,因此在

码长度可以相差十倍百倍。其实Perl

所有应用,这也是其它开源软件没

这个典型的应用中,数据层也是必

同样可以将代码书写得像Python等语

法比较的。

不可少的;

言一样优雅,至少从我手边的项目来

尽管我们常常能够看到Perl社区

◆ Mason/Catalyst:Mason是一种

发布出一些与 Perl 6相关的新闻,但

组件化开发的框架,它专门为大型商

是都只能表示这个语言正在发展,

务类网站所设计。在其官方网站称

Perl 开源的发展与现状

具体的日程还不得而知。不过站在

为“嵌入 Perl 语言到 HTML 的模板技

Perl 早在开源软件的名字(Open

Perl 5 这样一个高度的起点上,相信

术”, 但似乎在这里除了基本的语法

Source)出现之前就已经是一个成功

对于每个Perl的开发人员来说都是足

同 Perl一样外,已经完全不是那种顺

的开源项目了——Perl 是自由的,并

够的。

序型解析的页面语言了。Catalyst 是

看,已能有效防止这种情况了。

60

程序员

程序员开源手册

>>> 

一个优雅的Web应用框架,极为灵活

(MVC)设计模式,它擅长将内容处

又特别简单,这个部分将在后文中详

理、表示和流程控制方面的工作区

细讲述;

分开来交给独立的模块来做 。这种

◆ HTML/XHTML/AJAX:这部分

区分允许你为某一方面的问题修改

与 Perl 无关,不过在一个良好的 Web

代码而不影响解决其它问题的代码。

应用中,大多离不开它们;

这样 Catalyst提升了原来解决Web应

◆ Memcached/Mogilefs:如果你

需要创建一个大型Web应用,并且还
希望它是开源应用,应该能从Internet

¥ catalyst.pl MyApp# output omitted
¥ cd MyApp
¥ script/myapp_create.pl controller
Library::Login

Run
¥ script/myapp_server.pl

现在可以用你喜欢的浏览器或

用方面模块的重用程度。
下面是Catalyst工作的的一个流
程图,见图 2:

者代理程序来访问下面的地址来检
查 Catalyst 的运行状况:http://
localhost:3000/ 和 http://localhost:

上了解到很多与之相关的信息。

3000/library/login/。是不是简单得

在Web开发中常用的Perl模块主

让你难以置信?

要包括:

Perl相关的主要框架还有Mason,

◆ DBI DBD::Oracle DBD::Mysql:

这是一个组件化开发的框架 ,专门

这一部分是数据库操作;

为大型商务类网站所设计。在其官

◆ Net::SMTP,MIME::Lite:这个

方网站称为“嵌入 Perl 语言到 HTML

是邮件方面的;

的模板技术”,但除了基本的语法同

◆  L W P : : X X   U R L : : X X X
图 2:Catalyst 工 作 的 流 程 图

Perl 一样外,已经完全不是顺序型解

Catalyst 比起其他的框架具有更

析的页面语言了 ,您可以去官网

HTML::XXX:这是 Web 操作相关的;
◆ XML::XXX:这些是 XML 操

作方面的;
◆ Image::XX:这些是图形操作

方面的;
◆ CGI:如果您使用 CGI 方式可

能还需要它;
◆ 其它:search.cpan.org 将帮助

你找到您需要的模块。

强的灵活性。除此之外,它还具有一

masonhq.com 看看或来信与我交流。

些特点:

Perl 趋势展望

◆ 多模型、视图和控制;

Perl 在国外的应用相当成熟,在

◆ 可重用组件;
◆ 无限制URL-to-Action调度;

国内则主要是金融数据的处理、生

◆ 对 CGI、mod_perl、Apache::

物工程科学领域。而在IT相关的应用

Request 的支持。
Catalyst 最棒的地方在于它如此

当中,其服务器管理(非Windows服
务器)能力几乎是不可替代的。Perl

简单的实现了这样的灵活性:

将来在国内的发展,将主要集中在

◆ 搭积木似的接口;

两个方面:一个是 Web 开发,随着国

使用能极大提高开发效率。最近我

◆ 自动发现组件;

家支持开源软件发展的步骤加快,

们常常可以看到Ruby on Rails或者是

◆ 常用模块的预定义组件;

将会有更多网站项目使用开放的

Java的 Spring 和 Maypole 被热烈讨论

◆ 内建测试框架;

Perl;另一方面,用户将聚焦在Perl6的

着。相比这些轻量级框架,重量级的

◆ 帮助脚本。

推出与 Catalyst 的完善上。凭借 Perl

框架往往使用起来非常不便 ,而且

如果你希望安装Catalyst并创建

本身强大的能力,它将会为Web开发

缺乏灵活性,因此可以看到,近几年

简单的可运行的应用的过程,可以参

来,一些类似Spring 这样的轻量级框

考下面的方法,这里用到了上面说

架正在日益成为社区的热点话题。

到的辅助脚本:

Perl 在 Web 开发中的新框架
如同任何Web应用一样,框架的

所幸在 Perl的世界中,也存在这

Install
¥ perl -MCPAN -e 'install Bundle::
Catalyst'

用框架,它极为灵活又特别简单。
Catalyst 遵循模型 - 视图 - 控制

作者介绍:
James Zheng,来自成都。服务于一家美国公
司,正在从事基于 Oracle+Perl+Catalyst+

些框架,让程序员省却了很多麻烦。
Catalyst 就是这样一个优雅的 Web应

提供更加完善的解决方案。

Setup

Mason的电子商务平台开发,欢迎更多优秀的
Perl 工程师加到我们的队伍中来。您可以通过
jameswork66@gmail.com与我联系。

Programmer

61

特别策划

Features
单独定义一个XML 文件。同样,借助
强大的动态能力,SQLObject 还拥有
一个Hibernate所远不及的功能,那就
是 SQLObject 的映射类可以在运行时
动态改变自身结构,这也意味着数
据库中的表结构也可以在运行时进
行改变。总之,对Hibernate略有了解
的开发者均能迅速理解 SQLObject。
虽然我一直认为 SQLObject 还远
未能将 Python 的动态能力发挥到极
致。不过这却是一个良好的开始。也
许我们可以在不久将来看到更多更
具新意的 O/R mapping 工具。

Python 库简介
□ 文 / 汤韬

TurboGear
自 RoR(Ruby on Rails)在 Web 开
发领域一夜成名后,在其它语言社
区,跟风之作也如雨后春笋一般涌
现出来。虽然TurboGear并非刻意模仿
RoR 之作,不过它确确实实借着 RoR
流行潮流得到更多人的重视。

 “俗话”说:库即是语
言,语言即是库。由此可见拥有一套
高质量、具备良好可复用库对于一

需考虑库的各种兼容性问题。Python
社群对于库的重视可见一斑。
即便是拥有如此多的标准库。

与 RoR相同,TurboGear也是一个
轻量级Web开发套件,通过几个命令
行工具能够快速生成以数据库为核

门通用开发语言来说有多重要。这

这也似乎未能阻止Python社群的开发

心的基本框架代码。典型的 R o R 思

也的难怪“C + + 老爹”B j a r n e

者们天马行空般的思维。借助于动

想!这和许多开源框架的原则一样

Stroustrup 逢人就大倒苦水:C++的库

态语言简洁、优雅、灵活的表达能

——“避免重新发明轮子”。TurboGear

还是太少,C++社群需要开发更多高

力,这些第三方的库经常展现出令

的 Web 控制层使用 CherryPy;持久层

质量的库出来!

人赞叹的想象力。

使用 SQLObject;模板使用 Kid;AJAX

还好,为Python语言开发一套质

好吧,现在让我们在庞大的Py-

使用 MochiKit。几乎所有的重要的功

量不错的库的复杂程度远没有 C++

thon库选取点滴,也许它能带给我们

能组件都源自第三方。TurboGear自身

来得复杂。而且Python社区同样也深

一些另类的思考。

更像一个黏合剂,把所有的功能组

知库的重要性。结果就是Python的发
行版即奉上超过300个的标准库(这
还不包括专门针对 Mac 机的 50 余个
库,谁让那小子另类呢)。

合在一起,并能够形成力量的倍增。

SQLObject
SQLObject 可以看做是 Python 领

4Suite

域的 Hibernate。它也是目前 python社

虽然 Python 标准库提供了 XML

300 多个库中,绝大部分具备跨

区中最为成熟方便的O/R mapping工

处理工具,但是它只提供一些基本

平台能力(*NIX/Windows)。这些库

具。和Hibernate相比,SQLObject 利用

功能。如果你想获得更为强大的XML

覆盖了开发的方方面面,Python语言

了动态语言的独有特性,通过灵活使

处理能力,4Suite是一个更好的选择。

的用户可以在一个典型命令行环境

用继承、灵活使用 MetaData能力,能

4Suite被称为XML 工具中“内行

下(比如Linux Shell),仅仅利用标准

够快速方便定义直接在程序中定义

的选择”。除了最基本的Dom-Like和

库即可完成绝大部分工作,同时无

映射类,不用像 Hibernate中那样还需

SAX-Like 处理库外,4Suite 还提供

62

程序员

程序员开源手册

>>> 

XInclude,XPointer,XLink,XPath,

步网络服务器(所以它也被成为Py-

升整个应用的性能,在某些环境中

XUpdate 用于XML 文档的查询、更新

thon中ACE,如果你还不知道什么是

甚至能将速度提升一个数量级。

操作等等;提供XSLT完整处理能力。

ACE,那么看看前面关于C++库的文

虽然Psyco还不能视为一个真正

4Suite不光功能强大,性能也相

章),这是目前为止性能最好的网络

意义上的 JIT 的引擎,也无法像 Java

当不错。这主要是得益于其核心代

处理模型。也许是非阻塞异步处理

中的 JIT 那样提供完全透明的服务。

码部分采用C完成。这在需要处理大

的天生复杂性所致,Twisted 几乎是

但我们仍然要为Psyco的发展感到振

量 XML 文档的地方,4Suite实在是一

我所见过的最复杂,最难用的Python

奋。目前,在其最新版本中,只需两

个完美的选择。

库。Twisted 的使用者需要面对大量

行代码的添加,就能使你的程序充

新的概念和新的模式 ,这一点上和

分使用 Psyco,从而提升性能。

Pyro

ACE 倒颇有几分相似。

wxPython

Pyro 的全称是“Python Remote

陡峭的学习曲线,阻碍了很多

Objects”。按照字面即可理解 Pyro 的

人掌握 Twisted 库。这也许是想要获

在许多人眼里,动态语言/脚本

功能:提供远程对象。Pyro 为Python

得高性能所付出的必要代价 。难怪

语言一般仅适合完成命令行或 WEB

语言提供异常简洁的 RPC 解决方案。

O’REYLLI在其出版的关于Twisted的

的工作,而在桌面开发方面实在是

书的封面引用了一只九头怪蛇,还

丑陋不堪。而 wxPython 的出现无疑

真是贴切。

是给这种偏见以有力的回击。

其实 Python 语言中不乏一些更
加通用的远程调用方案,例如都是
基于 XML 的 XMLRPC和 SOAP。那么

w x P y t h o n 实际上发展多年的

Pyro这样的单纯的Python远程调用方

C++ 框架 wxWindow (现已更名为

案具有什么样的优势呢?那就是性

w x W i d g e t s)的 P y t h o n 封装。而

能与易用性。

wxWindow的目标是建立一个跨平台

由于动态语言具有强大反射能

的 GUI 框架。wxWindow 现已能在

力,因此实现对象序列化对于Python

Windows/Unix/Mac 上良好运行。自

来说简直易如反掌。对象的序列化

然wxPython也能横跨上述几个平台。

在 Python中被称为 pickle,这是许多
Python应用的核心机制。Pyro 也正是

wxPython 使用的原生窗口。这就

Psyco

意味着使用wxPython 开发的GUI 和操

充分利用 pickle 的威力,在网络间提

赞美Python的好话可以说一箩筐,

作系统本地 GUI 系统在界面外观上没

供远程对象的调用。它的性能要远

那么它的缺点是什么?这还用问吗,当

有任何区别。如果和Java中GUI库对比

远超过使用 XML 对远程对象进行编

然是性能。
性能——已经成为Python根

一下,就可以发现,wxPython 更加类

码 / 解码。同时,它在接口调用设计

深蒂固的老毛病了。不要说和C++/

似 SWT 而不是Swing。因为SWT也是

上也非常简洁。在服务器端和客户

Java/C#这样的语言相比,即使是和它

使用的原生窗口,想想Eclipse 的界面

端只需 2、3 行代码就完成对象的封

的同门兄弟们——Ruby、Perl、PHP 这

有多漂亮就知道原生窗口的优势了。

装与调用,远比SOAP来得简单轻松。

样的脚本语言相比,Python的性能依然

虽然不少C++爱好者对wxWindow

是最糟糕的。
Python的设计者们似乎仅

框架的设计颇有微词,不过在经过

仅在乎语言机制的完美,几乎不考虑性

Python的封装后,没有了指针、没有了

Twisted
上个月,Zope 3.2发布,
在这个最

能。CPythony 引擎已经发展了这么多

MFC时代的事件机制,wx框架的易用

新版中, 一个重要的变化就是:使用

年,查看其源代码,性能优化代码少之

性获得了极大提升。这也是Python的另

了近十年的处理Web请求的网络框架

又少。对象引用模型至今还在使用引

一个巨大魅力所在。

代码被放弃,取而代之是以Twisted 为

用计数器的方式,至于发展一个 JIT 引

核心实现的代码。据称这样可以改善

擎,算了吧,不要指望了。

系统性能以及可扩展性。于是Twisted
库再一次成为了人们关注的焦点。
Twisted 的核心概念是非阻塞异

作者介绍:
汤韬,OSDN(www.osdn.net.

还好,Psyco 的出现,带给我们

cn)网站开发主管,对 Linux以及

了一线希望。Psyco 通过将运行中字

开源技术拥有广泛兴趣,喜好

节码编译为二进制代码从而大幅提

Python、Ruby 等动态语言。

Programmer

63

特别策划

Features
gruff是基于Rmagick的图表生

● 

成工具。产生的图像颇具Apple设计

快车寻宝之旅

风格,还支持多种配色模板;
gnuplot 是同名用于科学统计

● 

图表绘制工具的 Ruby 接口。
◆ Html/XML 解析工具

□ 文 / 银昊

rubyful_soup 和 Ruby 自带的

● 

REXML 不同,它把XML结构映射成自
然的对象层次和 hash方便使用。
◆ 工具库

 自去年开始在北美Ruby

态的,对象可以在运行时决定外界

on Rails 和Ajax逐渐成为热门的两大

的消息请求改如何处理而不是直接

压缩文件、U R I 、C S V 格式文本、

IT流行名词。Ruby on Rails(简称RoR

传递给方法。也许过于强大总是伴

StringIO)
提供了简洁一致的操作接口;

或Rails)作为新一代Web应用开发框

随着风险,Matz曾经这样解释Ruby的

架,以其整合性,简化配置,避免重

设计哲学:“一把锋利的刀也许会割

复及快速反馈的设计理念确立了Web

伤手指,但总比钝的好。”

框架设计的新标准并吸引众多模仿
者。但是对Rails本身依然存在不少争
论,很大程度上是因为Rails是建立在
Ruby这个颇为“另类”的语言之上的。

缘起

rio 为各种IO需求(文件,目录,

● 

rake类似make和Ant 的任务管

● 

理工具,但是配置更灵活简单。
◆ Web 模板

RedCloth实现了Textile风格模

● 

工欲善其事必先利于器
有人说Perl的强大源于其CPAN,

板渲染而 BlueCloth实现了 Markdown
风格。这两个名字真是有趣。

作为一脉相承的 Ruby 也有自己一套

◆ Web 服务器

优雅的包管理系统:Gems。Gems的包

● 

Mongrel 相比 Rails 自带的纯

依托 www.rubyforge.org 管理。你可

Ruby 服务器 Webrick 速度快很多并支

R u b y 由松本行弘

以在 Rubyforge 上浏览分类目录寻找

持并发,有望成为 Ruby 的 Tomact。

( M a t z,M a t s u m o t o

需要添加的包,然后只需在命令行

如果没有恰好出了 Rails 这个杀

Yukihiro)于 1993 年创

下执行 gem install 包名① 即可,

手级应用,Ruby现在很可能依然默默

造,之后因为英语文档缺乏,仅在日

Gems 系统会自动连接服务器更新目

无闻。Rails 到底有那些神通呢?

本国内流行。直到2000年Programming

录并下载安装你所指定的包 ,当某

Ruby(俗称 Pickaxe book)第一版的出

些被依赖的包需要安装时亦会提醒。

版,Ruby真正在全球范围引起关注。

相信使用Debian、Gentoo和FreeBSD的

◆   消灭了冗余的 X M L 配置;

虽然发展历史较短,但其继承自Perl

朋友一定会觉得 Gems 很顺手。

◆  提供了代码生成脚本, 用于

的灵活性和自Smalltalk的动态面向对
象特性已经吸引了如 Martin Flower,

这里和大家分享一些我自己常
用的 gem 包:

Dave Thomas, Andrew Hunt,David

◆ 数据库驱动

Heinemeier Hansson(简称DHH,Rails

● 

创造者)等大师和天才的钟爱。
Ruby的设计遵循“最小惊讶”原
则,可读性非常好,感觉就像自然英

mysql② ,sqlite3-ruby, postgre-

pr,名字不言而喻。然而,并不是所
有的 Ruby库都是通过gem方式安装,
需要从 Rubyforge下载获取。

语。API经常可以猜出来,而命名参

◆ 图形库

数和默认参数值的运用(尤其在Rails

● 

Rmagick 是非常优秀的图像处

中)免除了经常复查API文档或者死

理库,需要另外安装 ImageMagick 或

记参数顺序的麻烦。Ruby的面向对象

GraphicsMagick。该库常被用于生成缩

特性是彻底的,同时Ruby也是高度动

略图这样的任务;

64

程序员

◆ 提供了即装即用的整套MVC

开发架构;

快速搭建(scaffold)和测试;
◆ Generator在生成代码的同时

会生成相应测试骨架;
◆ 开发环境为快速反馈提供支

持;代码即改即见结果;
◆ Rails 划分了开发、测试、部

署三个环境;
◆ Rails让用户使用声明式的领

域语言(DSL)快速建模、开发;
◆ 1.0新功能Migration提供分布

式数据库版本同步;
◆ 1.1新功能RJS提供了纯Ruby

程序员开源手册

>>> 

慢,比有 VM 又有 JIT 的 Java就更不

与 Ruby 及 RoR 相关的常用资源
国内网站

提了。

●  www.ruby-cn.org 国内

Ruby 先驱
●  www.railscn.com 聚集了一批 Rails 爱好者,来自国内国外香港台湾
●  forum.javaeye.com  其中的 RoR 版块集中了一些行业经验丰富的专家

◆  工具支持: 大部分人还在用

高级编辑器(Textmate、Jedit、Vim、
Emacs)开发 Ruby或 Rails。同时新的

国外网站
●  www.ruby-doc.org Ruby

文档集散地
●  rubyquiz.com Ruby 每周一题汇总
●  www.rubyonrails.org Rails 主站,文档,wiki,源码
●  rails.techno-weenie.net Rails 问答
●  www.ruby-forum.com Ruby、Rails 邮递列表 Web 界面
●  www.bigbold.com/snippets/tags/rails Rails 代码片段库

方式构建 Ajax 应用。
Rails 的核心 API自去年 4月开始
就趋于稳定,而不久前的1.1版本发
布后“大多数人大多数情况用的功
能”都已实现,所以核心开发小组的
重点将放到开发更多插件以满足

◆ Ruby 和Rails 非常英语化,无

论语法还是 API设计。虽然这和Ruby
发源在日本的事实似乎矛盾 ,不管
怎么说非英语国家的人要适应需要

acts_as_threaded,用来设计论

跨越一点障碍。

● 

坛回复层次结构;

◆  虽然越来越多的人⑤ 认同

还有些插件用来增强 Active-

Ruby 和 Rails 在开发速度、响应能力

● 

Record 的验证功能和错误信息。

和生产力提升上的不俗表现 ,但因

◆ 搜索引擎

“一部分人有时用到的功能”上。Rails
的插件体系类似于 Gems,管理十分

Lucene;

方便。Rails 插件并没有 Rubyforge 那

● 

发者自己的Subversion版本服务器上。

进步神速。

后可以用来做 workflow 吧;

● 

样统一的管理站点,一般都是放在开

IDE如基于Eclipse的RDT和RadRails也

为多数项目为时尚短 ,还无法确认

acts_as_ferret ,基于 Apache

长远的可维护状况。
◆ DHH 不希望 Rails 进入主流,

a c t s _ a s _ s e a r c h a b l e, 基于

而是像 Apple 那样,充满创新,为人

HyperEstraier;

人所向往的非主流。当然在北美主

◆  国际化插件: R u b y 本身对

流的定义也许就是Java+外包,还有

好在我们依然可以随时获得最新的插

Unicode 的支持比较简陋,好在Rails的

很多下班后不想继续编程的人的稳

件目录:在 Rails 项目下执行 r ub y

几个插件
(Gloc,Globalize, Localization)

定工作。

script\plugin discover同步插

都在不断完善。

件源。不过您最好先从Rails wiki上的

◆ 最后Rails至少给别的开发社

◆ Engines ④ 是一类特殊的插件,

区一些启发:越早获得反馈越好,减

plugin 目录找到所需:http://wiki.

和 plugin 只包含代码不同,engine 可以

少滥用 XML,DRY(Don’t Repeat

rubyonrails.org/rails/pages/Plugins,然

包含MVC三个层面,
是重量级的组件。

Yourself)。

后再用 ruby scri pt\plugin

◆ 其他插件

install 插件名安装。目前,Rails已

● 

有上百个各种插件,几乎每过几天就

● 

能看见新的插件更新。下面是一些有

杀手。

Rspec,下一代测试工具,assert

趣的插件:
◆ ActiveRecord 是 Rails 中代码量

注释

theme_support是用来换肤的;

轻车上轨路漫漫

等宽字体表示命令,斜体表示变量

粗体表示 gem 包名

DHH, Pursuit of Beauty: http://

media.rubyonrails.org/presentations/
pursuitofbeauty.pdf

最大的一个模块,也是Rails“美就是

◆ 因为在全球范围发展历史较

http://rails-engines.org

生产力”思想③ 的集中体现,往往加一

短,Ruby 类库依然不足,虽然由于

Martin Flower EvaluatingRuby http:/

句话到类里就能添加一大堆功能。自

Rails 的关系和 Web 相关的库有越来

/martinfowler.com/bliki/EvaluatingRuby.html

然相应的数据模型插件也层出不穷:

越多,在非 Web领域仍然颇为局限。

acts_as_taggable,一句话就给

● 

模型添加了很酷的 tag 功能;
acts_as_state_machine,很有趣

● 

◆  国际化的问题: 实际上只要

作者介绍:

页面、程序、数据库统一都用 utf-8

银昊,生于海上,现漂泊于枫叶

编码、显示和储存都没有问题。

之国, 在某创业公司从事数据

的插件,当对象有复杂状态时可以

◆  速度:Ruby 还是基于解释器

用这个定义状态切换规则,也许以

的,速度比基于虚拟机的 Python 要

分析应用设计开发。偶遇Rails
半年有余,不时窃喜之。

Programmer

65

特别策划

Features
8. 能方便地利用表和动态元机

一颗璀璨的月光宝石

制实现基于原型(prototype-based)的

—— Lua

模块机制,从而更好地支持开发大型

面向对象模型;
9. 从 5.1 版开始提供了完善的
的应用程序。
Lua的语法类似Pascal和Modula,

□ 文 / 邓际锋

但更加简洁,所有的语法产生式规
则(EBNF)不过才 60 几个。熟悉 C 和
Pascal的程序员一般只需半个小时便

 1993 年在巴西里约热

构,称为表(table),它类似key-value

可将其完全掌握。而在语义上Lua则

内卢天主教大学(Pontifical Catholic

关联数组,可以用任何类型的值作

与 Scheme 极为相似,它们完全共享

University of Rio de Janeiro in Brazil)诞

为 key和value。提供了一致且富有表

上述的 1、3、4、6点特性, Scheme

生了一门编程语言,发明者是该校的

达力的表构造语法,使得Lua很适合

的continuation与协程也基本相同只是

三位研究人员,他们给这门语言取了

描述复杂的数据;

自由度更高。最引人注目的是,两种

个浪漫的名字——Lua。
Lua从一开始就是作为一门方便
嵌入( 其它应用程序) 并可扩展的轻
量级脚本语言来设计的,因此它一

3. 函数是一等类型,支持匿名函

语言都只提供唯一一种数据结构:

数和正则尾递归(proper tail recursion);

Lua的表和Scheme的列表(list)。正因

4.

支持词法定界( l e x i c a l

scoping)和闭包(closure);

为如此,有人甚至称 Lua 为“只用表
的 Scheme”。

直遵从着简单、小巧、可移植、快速

5. 提供thread类型和结构化的协

相比 Java、Python、Perl,Lua的

的原则,官方实现完全采用 ANSI C

程(coroutine)机制,在此基础上可方便

开源工具和库可能并不算多 ,但其

编写,能以C程序库的形式嵌入到宿

实现协作式多任务;

中不乏优秀之作。以下介绍的资源

主程序中。Lua的每个版本都保持着
开放源码的传统,不过各版采用的

6. 运行期能编译字符串形式的
程序文本并载入虚拟机执行;

许可协议并不相同,自 5.0 版(最新

7. 通过元表(metatable)和元方

版是 5 . 1 ) 开始它采用的是著名的

法( m e t a m e t h o d )提供动态元机制

MIT 许可协议。正由于上述特点,所

(dynamic meta-mechanism),从而允许

以 Lua在游戏开发、机器人控制、分

程序运行时根据需要改变或扩充语

布式应用、图像处理、生物信息学等

法设施的内定语义;

均可在 http://lua-users.org/wiki/
LuaAddons 上找到,而且绝大多数都
遵循着与 Lua 相同的许可协议。

Kepler
Kepler 是一个简单且轻量的 Web
开发平台(但这并不意味着只能用它

各种各样的领域中得到了越来越广

来开发简单的应用),支持用Lua撰写

泛的应用。其中尤以游戏开发为最,

Web 程序,因此相当易学易用,并且

许多著名的游戏,比如 Escape from

能较方便地应用在一些资源受限的

Monkey Island、World of Warcraft、

系统中。由于使用ANSI C和Lua进行

大话西游,都采用了Lua来配合引擎

开发,所 以 它 能 移 植 到 任 何 支 持

完成数据描述、配置管理和逻辑控

ANSI C 的平台上。

制等任务。
作为一门过程型动态语言, L u a
有着如下的特性:
1. 变量名没有类型,值才有类

Kepler由多个Lua扩展库组成,包
括 CGILua、LuaSocket、LuaFileSystem、
Copas、LuaSQL、LuaLDAP、LuaExpat、
LuaXMLRPC、LuaSOAP 、LuaZip 、

型,变量名在运行时可与任何类型

Xavante 等,它们可大致分为核心库

的值绑定;

和功能支撑库两部分 。其中核心是

2. 语言只提供唯一一种数据结

66

程序员

CGILua 和 LuaSocket,后者负责 TCP/

程序员开源手册

>>> 

的Lua GUI程序在许多平台上都能顺
畅地运行。

Pluto
虽然Lua中的表能通过表构造器
以Lua代码的形式保存到文件中从而
实现持久化,但当数据之间有着复
杂的引用关系,并且存在循环引用、
共享引用等特殊情况时,这个任务
就变得相当困难与繁琐了。Pluto 持
久化库能够为用户解决这个难题。
在它的帮助下程序员可以将任意复
杂的表数据保存到特殊格式的二进
制文件中以待将来恢复,库会自动
处理循环引用之类的情况。
除表之外,Pluto还支持函数(确
切地说是闭包)、thread的持久化,这

wxLua

UDP sockets 的操作,前者则可以创

流行网
络 游 戏“ 魔
兽 世 界 ”的
插件与脚本
都 是 使 用
Lua 撰 写

种能力非常有意义。大家都知道程

建动态页面并处理web表单上的输入

GUI是开发人员花费气力比较大

序调试中的一个基本动作就是复现

数据。K e p l e r 通过 C G I L u a 起动器

的一个领域,因此简化GUI程序的编

(launcher)使得 W e b 服务器能执行

写一直是广大程序员的努力方向。

CGILua和Web程序并与之通信。目前

随着脚本语言的兴起 ,将动态、灵

难精确地构建出完全一致的运行环

的版本已经包括适合 CGI、FastCGI、

活、易用的脚本语言引入到GUI开发

境。而利用Pluto对函数和thread的持

Apache、IIS、Tomcat、Zope 的CGILua

中是一种非常有价值的尝试 。由于

久化能力,我们可以把bug发生时程

起动器,因此用Lua 开发的Web程序

复杂的 G U I 布局需要大量的描述信

序的完整运行环境保存下来 ,今后

可以在这些种类的服务器中自由迁

息,所以比起其它脚本来,既适合编

就可凭此方便地复现 bug。另外一个

移,只要同时安装上对应的CGILua起

程又适合描述数据的Lua语言在构建

重要应用是游戏进度的保存 。实现

动器。

GUI 上就具有独特的优势。

游戏逻辑的Lua脚本的运行状态能随

bug,但很多时候bug产生的条件是非
常复杂的,依赖很多因素,开发者很

LuaFileSystem 是对标准 Lua 库中

wxWidgets是一个著名的跨平台

时写入到文件中留待将来恢复,这

文件读写功能的补充 ,它提供了一

C + +   G U I 库,w x L u a 在 L u a 与

使得在任何时间点保存游戏成了一

种可移植的方法来访问系统的目录

wxWidgets之间架起了一座桥梁,通

件非常容易的事情。

结构和文件属性。Copas则是一个基

过它 L u a

于协程的服务调度器。Xavante 是一

wxWidgets 的所有功能。wxLua基本

个用Lua开发的支持HTTP 1.1的Web

将 wxWidgets 的类体系映射到了 Lua

LuaCOM 是一个支持 Lua 与符合

服务器,它直接支持CGILua而无需起

(基于原型) 的对象模型中,这使得

COM规范的组件对象(确切一点说是

动器。

程序员能以基于对象或面向对象的

自动化对象)进行交互的扩展库。所

风格来开发 wxLua 程序。一个 Lua脚

谓交互包括了两个方面,首先是允

访问、X M L 解析、LDAP 、S O A P 、

本的撰写、运行、测试和修改可以非

许 Lua 程序使用 COM 对象。LuaCOM

XMLRPC、ZIP 文件操作等功能,用户

常快速,这无疑大大提高了GUI程序

支持注册在系统注册表中的 COM 对

如果只需要其中的某些功能 ,可以

的开发效率,因此wxLua非常适合快

象的动态实例化,也支持动态访问

抽出相关组件( 及其所依赖的组件)

速原型的构造。另外,Lua本身以及

运行中的对象。在LuaCOM的帮助下,

来使用。

wxWidgets良好的可移植性使得相应

调用COM对象方法就象调用普通Lua

其它的组件提供了 S Q L 数据库

代码几乎可以调用

LuaCOM

Programmer

67

特别策划

Features

函数一样,存取属性也与存取表的

tolua 本身不是一个Wrapper,但

返回到那一点。在标准 Lua 中,协程

字段类似,同时它还负责Automation

它是一个 Wrapper 代码自动生成器。

的挂起与恢复是不允许跨越 C 函数

数据类型与 L u a 数据类型的自动转

它使用一种称为包(package)的文件

调用边界的。Coco 使用了一些依赖

换。有了这些特性,Lua程序操作COM

来描述要导入到 Lua 环境中的常量、

于特定系统的特性,因此在移植程

对象就变得容易多了,再加上Lua天

变量、函数、类和方法,这种文件按

序时要特别注意。

生的动态性,这无疑使其成了一门

照简化了的 C++ 头文件格式编写。

非常灵活的组件装配语言。

使用时首先让 tolua 解析包文件以生

ChunkSpy

交互的另外一个方面就是支持

成含有相应胶水代码的C/C++源文

Lua的虚拟机字节码指令集并非

用Lua来实现(自动化)组件对象并提

件。然后将生成的源文件编译并与

语言定义的一部分,因此官方没有

供给外部客户使用。LuaCOM同时支

那些具体实现功能的目标模块链接

提供文档。用户可以通过查看源代

持进程内和进程外组件,它提供了

起来。

码来获取信息,但这毕竟不方便。

一些辅助函数来处理注册、对象实

tolua虽然自动产生胶水代码,但

ChunkSpy 是一个Lua虚拟机字节

例化这类事情,从而简化了相关工

需另外撰写描述文件,所以仍然不够

码反汇编器,可以将一个二进制Lua

作。由于LuaCOM实际上是根据Lua的

方便。其它一些 Wrapper 库则利用

代码块输出为非常易读的各种格式

表来构造一个 COM 对象,所以我们

C++模板元编程技术来自动生成合适

(详细或简略、带或不带源程序)的

可 以 做 一 些 非 常 有 趣 的 事 情 :在

的连接代码,从而避免了额外的描述

字节码汇编文件。而且它还支持交

userdata数据类型(代表不属于 Lua世

文件,比如使用boost 库的 luabind。

互式的反汇编,用户在敲入一行代
码后立刻就能看到对应的字节码指

Lua在葡萄牙语里代表美丽的月亮。事实证明它没有糟蹋这个优
美的单词,Lua语言正如它名字所预示的那样成长为一门简洁、优雅
且富有乐趣的语言。

令。ChunkSpy的作者写过一篇详细的
介绍 Lua5 虚拟机指令的文章,名为
《A No-Frills Introduction to Lua 5 VM
Instructions》,在项目主页上能找到

界的数据结构)和动态元机制的支持

LuaJIT

它。这篇文章现在已经针对最新的

下,Lua能通过表访问各种各样的外

Lua 非常高效,它运行得比许多

L u a 5 . 1 做了更正 。另外,他还是

部数据,包括C++ 对象、C结构或者

其它脚本(如 Perl、Python、Ruby)都

Yueliang 项目的开发者,这个项目采

CORBA 对象等等;LuaCOM可以很方

快,这点在第三方的独立测评中得

用Lua语言本身来实现Lua。从项目名

便地将代表这些数据的表包装成一

到了证实。尽管如此,仍然会有人不

来看,作者应该是个华人。

个 COM 对象给外部使用,从而使得

满足,他 们 总 觉 得“嗯,还不够

那些老迈的应用程序和库无需太多

快!”。LuaJIT 就是一个为了再榨出

努力就能跻身于 COM 世界。

一点速度的尝试,它利用 JIT编译技

另外一些库与工具还包括

术把Lua代码编译成本地机器码后交

LuaEDIT、LuaEclipse、VS’05LuaLangPack

tolua

其它

由 CPU直接执行。LuaJIT测评报告表

(它们都是IDE或IDE插件),LuaWrapper、

直接用C实现某些功能,然后将

明,在浮点运算、循环和协程的切换

CaLua、CPB、CppLua(Wrapper 库),

相应的函数导入到Lua中是很常见的

等方面它的加速效果比较显著,但

LuaProfiler(性能测量工具)等,读者可

做法。不过尽管Lua 提供了与 C语言

如果程序大量依赖C编写的函数,那

以在lua-user.org 与luaforge.net 网站上

交互的 API,但用户必需手工进行繁

么运行速度便不会有什么改进。目

找到它们以及其它有用资源。

琐的Lua栈(用于与C交换数据)操作,

前 LuaJIT 只支持 X86 CPU。

作者介绍:

而且还需注意两种语言数据类型的

LuaJIT 中包括一个名为 Coco 的

正确转换。难怪有人说使用 Lua 的 C

库,用户可以单独使用它。Coco 为C

邓际锋,程序员,研究兴趣为程序设计方法学以

API 就象在使用汇编语言一样。为了

函数提供了真正的协程能力 ,用户

及如何为儿童和非技术人员构建富有乐趣的可

减轻程序员的负担,一些 C / C + +

能在 C 函数内部的任何一点将协程

编程工具。
您可以通过soloist.deng@gmail.com

Wrapper 应运而生。

挂起,然后在将来用协程恢复操作

68

程序员

与他联系。

程序员开源手册

>>> 

司常用的一组过程工具,以及在敏

敏捷方法中的开源工具

捷项目中使用这些工具的些许经验。
从我的角度看来,敏捷方法最
为重要、也最立竿见影的部分当属

□ 文 / 熊节

测试驱动与持续集成 ,我们的工具
之旅就从这两件事情开始。

  也许由于软件行业固

而这种思路,与敏捷方法是不谋而合的。

有的“高科技”特性(或者说,软件

再加上,推崇敏捷方法的那些“实用主

单元测试:JUnit(以及 mock)

人固有的顾影自怜),软件项目的管

义程序员”们往往也正是开源社群的积

在敏捷开发的工具箱里,JUnit

理和过程控制中从来就不缺少形形色

极分子,所以适用于敏捷项目的开源过

很可能是最广为人知 、也最受到重

色的工具。在一些大型的、
“正规的”

程工具尤其容易找到也就不足为奇了。

视的一个,当然它也当得起这样的

软件企业中 ,配置管理要通过

敏捷的开发者们是幸福的,因为他

殊荣。若论出身,JUnit 是由Kent Beck

ClearCase,软件设计要使用Rose画出

们拥有众多优秀的开源工具可供选择;

与 Erich Gamma 两人共同创造的。若

一大堆精美的图形,压力测试要用

敏捷的开发者们又是痛苦的,因为他们

论影响,由它引入的“红条 / 绿条”

LoadRunner 来跑……当软件公司的老

必须在乱花渐欲迷人眼的工具丛中找出

更是影响深远。

板们痴迷于“形式化管理”与漂亮的

适合自己的一组工具栈,并将它们与自

“红条 / 绿条”不仅仅是一个测

报表和文档时,这些昂贵的商业工具

己的管理策略糅合成一个完整的开发过

试成功与失败的标记 ,它们构成了

着实在他们那里得到了不少的青睐。

程。本文将为读者介绍 ThoughtWorks 公

敏捷开发中最基本的韵律:
“编写测

幸运的是,越来越多的软件开发
者和老板开始意识到,软件项目采用
的方法没有一定之规,
不同的项目、

同的团队需要选择不同的开发方法。
而工具,则如同三棱镜般折射出方法
学的身影——用着微软的TeamSystem
就很难不遵循微软推荐的最佳实践,
同样RUP 在没有Rational 工具支持的情
况下也难以实施。于是,选择开发过
程工具,很大程度上就成了选择开发
方法的一个副产品。
对于身处激烈需求变更风暴之
中的企业应用开发者 ,如何步步紧
跟客户的真实需求、如何确保时刻
为客户提供最大价值是他们每天冥
思苦想的问题。此时注重交流反馈、
以客户价值为驱动的各种敏捷开发
方法就成为了他们自然而然的选择。
而有趣的是,开源的过程工具也大
多与敏捷方法最为适应。看似偶然,
其实却有其道理:开源项目更少受
到种种政治因素的影响,生存的环
境又有更多的不确定性,因此也更
加强调时刻保证最大化的客户价值。

图 1:各 种 各 样 的 Green Bars

Programmer

69

特别策划

Features

试 -红条-编写代码-绿条-重构”,

优点在于它的震撼性:成百上千个

这五个简单的步骤确保了每一个思

test case运行起来,只见Web页面不

Selenium的名字还有个有趣的由

绪都有单元测试作为记录,每一段

断地在屏幕上闪过,模拟着各种各

来:在Selenium 出现之前,最著名的

代码都有单元测试保证它的质量,

样的用户操作,最后生成一张庞大

Web 应用功能测试工具当属 Mercury

整个软件项目始终朝着价值最大化、

的报表,背景是令人平静愉悦的淡

Quanlity Center,但那是个商业工具,

质量最优化的方向前进。而红条与

绿色。即便对于全然对于不懂技术

功能强大却也价格不菲,常常让开

绿条,则清晰直观地指出你当前所

的管理者或客户,这一过程的心理

发者们又爱又恨。所以,自己动手开

在位置,以及下一步应该做的工作。

效果也是不言而喻的。

发开源功能测试工具的ThoughtWorker

当我说 JUnit 的时候,我意指的

在没有使用 Selenium之前,很多

台是 J2EE 还是.NET 或者 Rails。

们把这个工具叫做 S e l e n i u m ——

是整个 xUnit 家族。虽然运行在不同

人都认为Web界面是无法测试驱动、

“Mercury”有“水银”的意思,而

平台、不同语言,它们拥有同一组无

也无需测试驱动的。但此时我们就

“Selenium”(硒元素)恰好是专解汞

法错认的特征:红条 /

常常遇到这样的困境:客户认为页

绿条、

TestCase/TestSuite……这也让开发者

面上的一句话应该这样写,开发者

们无论走到哪里总可以感到放心。

却认为客户三天前的意见是另一样,

中毒的特效药。

构建脚本:Ant vs. Maven

不过还有一个催化剂可以让这

认真回想起来却又没人能记得三天

现在你已经用 JUnit 记下了所有

种化学变化来得更加强烈,那就是

前到底说过什么。如果说 JUnit 单元

设计思路,也用Selenium记下了所有

mock 框架。以 EasyMock 和 JMock 为

测试记录了开发者对于软件的设计

功能需求。你还需要让所有测试案

代表的 mock 框架,其作用是模拟被

思路,那么Selenium就记录了客户对

例都能自动运行,这样才能频繁地

测对象之外的相关对象,从而实现

于软件功能的要求,并时时验证客

验证所有测试仍然顺利通过 。这时

对象之间的解耦合,达到真正意义

户的要求仍然得到满足。

Ant 就来到了你的手边。由Apache组

上的“单元测试”。奇妙的是,当你

Selenium 的用法有很多种。你可

织开发,又有多年实践检验,Ant 已

把mock框架放入测试驱动实践中时,

以把它放在构建流程之外,由客户

经积累了大量实用的插件,几乎所

开发过程就会引导着你得到低耦合、

定期检验软件的功能是否符合需求;

有常用的任务都有对应的插件可以

模块化的设计,因为你很难为一组

你也可以让它作为构建流程的一部

完成。而且在Ant 脚本中可以直接调

紧密耦合的类编写测试,而 mock 框

分,用它来驱动功能的开发,形成一

用 Java类中插入 C# 代码),也就是

架则让你愿意采用IoC模式分离出更

个更大范围的“红-绿-重构”循环。

说你实际上可以用 Ant 来做任何事。

多的类来承担各自的责任。在.NET

除了编写 H T M L 格式的测试脚本之

和 Ruby 等主要平台上,也有类似的

外,Selenium还支持编程驱动的模式,

来完成整个构建流程:从编译源代

mock 框架可供选择。

可以用程序代码来编写可复用的测

码,到打包应用,到部署服务器,到

试案例。而且整个 S e l e n i u m 是用

初始化数据库,再到执行测试并生

功能测试:Selenium

JavaScript 和HTML编写的,这也就意

成测试报告,只需一个指令就可以

抛开所有的技术考量,单凭直

味着你可以轻松地将其融入任何一

全部完成。类似的构建工具在 C /

觉来说,我个人认为Selenium最大的

个web应用,不管开发这个应用的平

C++的世界早已存在,那就是著名的

不过最通常的用法,还是用Ant

make,不过 Ant 来得更加简单易用。
作为后起之秀的 Maven 比之 Ant
最大的优势在于它内建了更多对J2EE
项目(尤其是web 项目)的支持,以
及更多项目管理相关的功能 。像单
元测试、创建报表等在Ant 中用插件
实现的功能,在Maven中都有内建的
支持。甚至很多开源项目的网站都
图 2:Selenium 也 采 用 了 红 条 / 绿 条 的 界 面 设 计

70

程序员

是用Maven直接生成的。但以笔者愚

程序员开源手册

>>> 

见,Maven强大的功能更适合开源软

pair每隔15分钟到半小时(最多不超

个敏捷团队来说,最重要的事情莫

件这样组织松散的项目,对于一般

过 1 小时)就会提交自己最新的代

过 于 建 立 有 效 的 交 流 渠 道。 在

的企业应用 Ant 已经足够了。

码,一个项目组每天通常会生成数

ThoughtWorks,每个项目都有自己的

不过在进入了Ruby/Rails的世界

十个修订版本。即便不算其中无法

wiki,开发者、项目经理、客户……

之后,笔者感觉Ant 和Maven都有一

成功构建的版本,通常每周也能收

所有的项目涉众都会把自己的收获

个共同的缺陷:它们的构建脚本都

获上百个构建版本。察看每个构建

与心得记录在wiki上,以便大家分享

采用 XML 编写,因此代码量相当巨

版本对应的报表,就是项目管理者

和交流。

大,并且也不易理解。相比之下,Rake

有效掌握项目进度的最佳途径。

直接用 Ruby 来编写构建脚本,反倒
显 得 更 加 简 洁 易 用。也 许 相 比 于

开源的wiki很容易找到,我在这
里不必多说。我唯一想要介绍的,是

持续集成:CruiseControl

这个叫做 TiddlyWiki的小东西。这是

X M L ,我们还需要找到另一种更适

我们刚才已经提到 ,在开发者

一个完全用HTML和JavaScript编写的

合描述“软件构建”这一任务的领域

不断提交的修订版本中,有一部分

wiki,使用它甚至不需要服务器,你

专用语言。

是无法成功构建的,原因就是在版

只要在本地打开这个 HTML文件,就

本控制系统上运行着一个忠实的看

可以开始写你的wiki了。你所写的内

版本控制:CVS vs. Subversion

门人:持续集成工具。它们的代表就

容同样会被保存在这个 H T M L 文件

任何一个多人开发的项目都必

是由ThoughtWorks员工开发和维护的

中,并且还提供了修改跟踪的能力。

CruiseControl。

使用这个wiki,你可以把整个文档放

须有版本控制系统——即便一个人
开发,也需要版本控制系统来提供

CruiseControl的任务非常简单:

备份和恢复的支持。由于有全面的

每当有人提交了新的文件到代码库,

到你的版本控制系统中,不需要为
它做任何额外的配置。

测试作为保障,敏捷方法提倡采用

它就把整个项目签出(check-out)到

另外,别忘了一个最重要的工

“所有人拥有所有代码”的代码所有

一个测试环境,然后执行项目的构

具:纸卡片——你可以随便写,用任

权形式,这也就意味着时常会出现

建脚本,完成整个构建流程,并运行

何颜色写,可以画任何你想画的图,

两个人同时修改一份文件的情况,

所有测试。如果这一切都顺利通过,

可以用任何顺序来排列粘贴它们,

在一些配置文件上这种情况出现得

CruiseControl就会生成一个新的构建

可以任意移动,可以随时加上注释,

更加频繁。因此,敏捷开发所使用的

版本;否则,构建失败,所有人都不

谁都知道怎么使用它们。你甚至还

版本控制系统最好不要采用文件级

允许再签出或提交任何代码 ,直到

可以撕掉它们,优质的纸卡片撕起

的锁定——这正是VSS缺省的锁定方

造成破坏失败的人把问题解决掉,

来有一种特别的手感 ……好吧,纸

式,不过我们也可以通过配置来改

让构建重新成功为止。

卡片不是软件,通常也不免费,但你

变锁定方式。而开源的选择,则是
CVS 与 Subversion(简称 SVN)。

这个部分的内容,可以参见下

知道怎么得到它们。

一篇文章。

写在最后

CVS 与SVN 存在着一些差异,不
过作为开发者的我们通常不必介意

介绍了我们常用的工具之后,

这些区别。值得注意的一点是,当出

相信读者已经知道:要实践敏捷开

现文件冲突时,SVN会强迫用户首先

发,可以从哪些工具开始入手。最后

消解冲突,然后才能将文件提交到

我还有一个忠告要给我亲爱的读者:

代码库。另外,每当有人成功提交新

不要被工具绑住你的手脚。每个项

文件之后,SVN会为整个项目生成一
个新的修订版本(revision),而不是

目、每个团队都是独一无二的,它们
图 3:红 灯 / 绿 灯 , 构 建 结 果 一 目 了 然

需要自己独一无二的方法,而你需

像 C V S 那样为每个文件单独记录修

知识共享:Wiki,尤其是

要针对项目和团队的情况选择适当

订版本,这也让版本控制变得更加

TiddlyWiki

的工具和适当的使用方式。这不是

容易。
在一个敏捷项目中 ,每个开发

“敏捷宣言”中清楚地写着:“个
体与交互胜于过程与工具”。对于一

一件容易的事,但愿这篇小文能给
你提供一个好的起点。

Programmer

71

特别策划

Features
确保了每个开发者的修改被正确有
序地保存,当每个开发者想要提交

使用开源工具
进行持续集成

自己的修改的之前,必须首先确保
上一个人所提交的修改被成功集成,
才能提交自己的代码。
开源社区为我们提供了非常优
秀的持续集成工具,CruiseControl、
CruiseControl .NET已成为广泛使用而

□ 文 / 黄亮

且非常成熟的持续集成工具 ,而持
续集成所需要的自动化构建工具和
版本管理工具如 Ant、NAnt、SVN 也
已经是非常成熟。

  每个开发过软件的人

证原有功能的完整。

CruiseControl &
CruiseControl .NET

都能体会到,软件开发绝非一帆风

也许读者会有疑问:“你说的只

顺,每个人开发出来的代码绝对不

是一种理想状况罢了 ,但是怎么能

会魔术般的自己组合在一起 ,当新

够做到这一点,谁有能力来及时地

谈到持续集成工具就不能不谈

的功能加入到原有软件中的时候,

告诉我们哪里有问题 ?持续集成这

谈 CruiseControl(cruisecontrol.

往往不小心破坏了原有的功能,引

个想法不错,但怎么样能够做到持

sourceforge.net)。CruiseControl可谓持

入了一些bug,当老的bug被修复的时

续集成?”其实持续集成的难点主

续集成工具中的龙头老大,也可以

候,又往往会导致其他bug的产生。当

要在于,在新的功能加入的时候,如

说是第一个成熟的开源持续集成工

小组成员们完成了自己所负责的模

何来判断整个系统功能仍然完整;

具。该工具由 ThoughtWorks 公司开

块,等到最后来一起集成的时候,他

出错或者成功,谁来告诉我,如何告

发,并将其开源,同时提供了丰富的

们可能已经做好了修复集成问题的

诉我;当大家一起协作的时候,如何

文档支持(http://confluence.public.

心理准备。这一切,都是每个开发人

保证每个人都能够准确地被告知而

thoughtworks.org/display/CC/Home)。

员的切肤之痛。那么,问题到底出在

不会发生混乱。

哪了?

CruiseControl非常完美的实现了

首先,确保整个系统功能完整

一个持续集成工具所需要具备的所有

从开发者的角度来看,
毕竟谁也

性的手段就是测试,如果我们对所

功能,它集成了包括SVN、CVS、VSS、

不想经历那种当发现自己的修改破坏

有的功能都有完整的测试,那么当

StarTeam、ClearCase 等在内的十几种

了原有的功能之后而恼火的感受。

新的功能引入的时候 ,如果某些原

版本管理工具,内建地支持了 Ant 、
NAnt、Maven、Maven2等自动化构建

如果每个开发人员都能够享受到方便并且保证新加入的功能不
会影响原有的功能,我们的整个软件过程就能够以一个稳步可靠的
步伐,持续增量的向前行进。

工具,并且通过执行shell命令的方式
间接支持几乎所有其他构建工具如
Make,Jam等。你可以设置CruiseControl
以多种方式运行系统的集成,既可以
在每次有新的代码修改提交时自动运

谈到这里,聪明的读者应该能

有的测试失败,就说明新的修改破

行,也可以让它定时运行。在运行完

够想到,刚才我们所说的就是前面

坏了原有的功能。其次,持续集成工

后,CruiseControl可用允许你使用各种

最开始提到的持续集成。持续集成

具将告诉我们集成是否成功 ,持续

方式报告运行的结果,包括发送电子

通俗地说就是持续地 、频繁地进行

集成工具通过运行整个系统中的测

邮件、使用ftp、rss、jabber、scp 等工

集成,每当有新的修改加入的时候,

试,根据测试的结果来通知开发者,

具报告结果,也可以让你自动化地在

修改的作者能够被及时地告知他的

哪些测试失败导致的集成失败。在

运行完后将整个系统打包、部署。它

修改是否在引入新的功能的同时保

多人协作的情况下,版本控制工具

甚至允许你在运行完成后根据结果成

72

程序员

程序员开源手册

>>> 

功与否播放不同的音乐或电影,及时

而,并不是只有Java程序才能用它来

buildpatterns.com/trac/wiki/

地告诉大家。

进行持续集成,
CruiseControl可以用来

DamageControl)的出现大概不会让大

做任何语言编写的系统的持续集成,

家感到奇怪,它是一个用Ruby写成的

可以将 CruiseControl配置为每次有新

例如 C++ 程序员就可以使用make或

持续集成工具,也是由ThoughtWorks

的修改时运行所有集成工作 ,这样

jam,配合SVN 火车CVS来进行持续集

公司开发的一个开源产品。

当 你 提 交 你 的 修 改 以 后 ,

成,使用CppUnit 、mockpp等工具编写

DamageControl区别于CruiseControl

CruiseControl会自动地将代码库中的

测试。尽管如此,还是诞生了一些在

的一个显著特性是它提供了一个用

新的修改更新到一个事先指定的地

特定平台上运行的持续集成工具,

Ruby on Rails框架写成的Web管理应

方,然后按照你的配置准备测试数

CruiseControl.NET 就是其中一个例子。

用程序,用户可以很简单的使用这个

在实际开发过程中 ,开发人员

据,编译、运行系统中的所有测试。

CruiseControl.NET
(http://ccnet.

web 程序来配置持续集成项目。凭借

开发人员可以使用 W e b 方式通过

thoughtworks.com)运行在.NET平台

着这个简单的Web管理程序,用户可

CruiseControl附带的一个 Web 程序查

上,采用.Net 框架实现,在实现了几

方便的建立一个持续集成项目,并可

看运行的结果,这个结果页面会告

乎所有的 CruiseControl的功能的基础

以配置运行策略、版本管理、运行结

诉大家该次build是否成功或失败,如

上,提供了对于Windows平台和.NET

果的查看方式等,

果失败,大家也可以看到失败的错

编程更多更友好的支持。

CruiseControl里,需要手动修改一个

误信息,也可以告诉你在某一段时

CruiseControl.NET 的一个特点是

而不用像在

xml配置文件来完成集成项目配置。

间之内所运行的集成的统计信息。

它集成了对 Visual Studio .NET 和

尽管DamageControl 目前还处于开

根据配置,CruiseControl可以显示几

MSBuild 的支持。用户可以将 Visual

发状态,它已经逐渐被广泛应用起来,

乎集成过程中每个环节出现的错误,

Studio .NET工程的sln文件指定给它,

由于它使用Ruby写成的,所以自然会成

例如编译错误、JUnit 测试运行错误、

让它运行其中的 build、rebuild和clean

为 Ruby 项目的首选工具。它的安装也

checkstyle 代码风格检查错误,以及

等功能。在 NAnt 出现之前,几乎所

比较简单,用户可以直接从Damage-

功能测试、集成测试错误等。当其他

有开发人员在都是使用Visual Studio

Control项目的SVN代码库中check out出

人想要提交他们的修改之前 ,都应

.NET 来管理他们的.NET 项目的。这

源代码,稍加配置就可以运行了。

改事先查看CruiseControl的结果页面,

样,CruiseControl.NET 可以支持对原

DamageControl还实现了一个非

如果当前 CruiseControl没有在运行,

有 Visual Studio .NET 工程的持续集

常酷的功能:AppCasting。该功能能

并且上一次运行结果为成功 ,才能

成,而用户也既可以使用 NAnt 或者

够让你将你运行完持续集成后得到

提交自己的修改,在提交后,还要保

Visual Studio .NET 来管理整个项目

的系统交付给对你的系统感兴趣的

证新的一轮集成成功完成,才算完

的构建。MSBuild是Visual Studio 2005

人。当 某 一 次 集 成 运 行 完 毕 后 ,

成了自己的工作。

项目的标准格式,CruiseControl.NET

DamageControl会使用一些工具如Ruby

CruiseControl具备很好的扩展能

对其的内建支持可以使大家很容易

Gems、Apt、Maven repository 等将你

力,目前已经有很多为CruiseControl编

地将 Visual Studio 2005 的项目放到

的系统打包,然后在它自己的RSS里

写的插件。eXtreme Feedback Devices

CruiseControl.NET 中去。

面加上一条消息表明新的系统已经

(XFDs)(http://www.artima.com/
weblogs/viewpost.jsp?thread=67492)

被成功构建了。这样,任何订阅了该

DamageControl

就是一个很有意思的插件,该插件的

在 Ruby 成为一种新的流行时尚

一个功能就可以将CruiseControl的运行

的今天, DamageControl
(http://dev.

结果用一个外接的红绿灯显示出来,
如果build成功就亮绿灯,如果失败就

CruiseControl
附 带 的 web
应用, 用于
报告每次的
集成结果

RSS的人就可以及时的知道某一个项
目的进展情况,并且在有新的集成
成功运行完成后得到最新被构建的
系统以及相关的发布信息。
谈完了这些持续集成工具,我

亮红灯,以 次 来 让 开 发 人 员 们 对

们有必要来看看自动化构建工具,

CruiseControl的 build结果。

这些工具在持续集成中同样扮演着

CruiseControl是用 Java语言编写

非常重要的角色,可以这么说,持续

的,并且可以运行在各种平台上,然

集成工具就像一个指挥,而真正完

Programmer

73

特别策划

Features

成工作需要依靠这些自动化的构建

你自己实现的功能来进行数据库

使用的动态语言,并且拥有非常丰

工具。正是这些工具的存在,是我们

schema 的自动构建和测试数据的刷

富的程序库。所以利用 Rake,你几

可以自动化的完成编译源码 、运行

新,进行数据库 schema 的迭代化升

乎可用很方便的完成所有你碰到的

测试、打包系统、部署应用等所有这

级,使用Ant,你还可以自动启动你

任务,甚至包括使用计算机的串口

些我们在集成中需要完成的工作。

的浏览器,并在上面运行用Selenium

进行通信,这样你就可以使用外部

目前在这方面已经有很多非常成熟

或 Watir等工具写成的功能和集成测

硬 件 来 显 示 你 的 持 续 集 成 结 果。

的开源工具,比如古老的Make,鼎鼎

试。Ant 对这些任务的自动化运行的

Ruby 内置的正则表达式支持和强大

有名的Ant和它在.NET世界中的兄弟

支持,使得我们的自动化的持续集

的文本处理能力使得某些工作可以

NAnt、用 Ruby 写就的 Rake 等等。在

成成为可能。要知道,自动化是持续

变得非常简单,比如配置文件的管

下面的内容中,我将挑选其中的几

集成的一个非常重要的特性 ,项目

理等。

个工具进行一些介绍。

构建的自动化也是实现持续集成的

Rake 不仅支持Ruby项目的构建,
也同时支持其他语言写成的项目的

持续集成是现代软件工程中的一件利器,任何一个软件项目,
不论是上百人的大项目还是个人项目,持续集成都能让你的软件开
发过程更加稳定高效

构建。Martin Fowler的个人网站上有
一篇非常不错的文章介绍 R a k e :
http://martinfowler.com/articles/
rake.html。 借助于Ruby的程序库集中
管理机制,Rake 的安装也非常的简

Ant & NAnt

一个重要前提。毕竟,我们不可能期

单,通过 R u b y 的程序包管理软件

Ant可以说是非常有名的一个自

望每次都手动地在集成过程中执行

gem,只要一行命令就能自动地从远

动化构建工具了,其在.NET 世界中

某些工作,如此是不能保证我们能

程服务器上下载并安装最新的Rake。

的兄弟 NAnt 也已获得了广泛应用。

够反复快速并且持续地进行集成的。

Ant凭借其使用简单和良好的跨平台

小结

目前的 A n t 已经很成熟,它在

特性已经博得了诸多程序员的青睐。

1.6 版本中引入的 macro 、import 、

它不仅是 Java 应用开发中的首选工

subant等特性进一步方便了我们组织

一个非常重要的规则。我们在前面所

具,用户也可以用它来做自己的工

自动化构建脚本,使我们的脚本更

讨论的这些开源软件,已经为我们实

作自动化,例如转换 DocBook 文档、

简单、清晰和有组织。NAnt 作为.Net

现持续集成提供了非常成熟的技术支

编译 Tex 文档等。有关 Ant 的介绍已

平台下的专有工具,对.NET 平台下

持;相反,商业软件在这些领域中确

经是数不胜数,我在这里也不想做

的开发提供了许多支持,有兴趣的

极少有所建树。我想正是由于这些工

过多重复。只是就项目中可能用到

朋友可以到它们各自的网站上面获

具的诸多作者对程序开发过程需求的

的 Ant 的一些特性做一些介绍。

得更详细的信息。

敏锐细致的把握,才导致了这些优秀

在持续集成过程中 ,我们往往

的开源工具的诞生,而开源软件的免

Rake

需要做以下一些工作:编译代码、代
码风格检查、运行测试、打包应用、

Rake 是一个用 Ruby 写就的自动

部署应用、运行功能和集成测试等。

化构建工具,目前已经逐渐被更多

所有的这些工作都可以使用Ant来完

的人所了解,它其实是一个用Ruby语

成。开源社区已经为Ant 贡献了数不

言写成的DSL(领域专有语言)。Rake

清的 Task来扩充Ant 的功能。我们可

的构建脚本本身就是Ruby程序,因此

以使用 JUnit 和 Testng 任务来运行测

它能够充分利用 Ruby 语言的强大功

试,通过 checkstyle 提供的任务来进

能,在Rake脚本中,你可以使用Ruby

行 Java代码风格检查,使用 Tomcat

语言的全部功能和程序库,来完成

等提供的任务来自动化地启动和停

你的任务。

止服务器并部署应用程序,或者用

74

程序员

持续集成是敏捷开发方法中的

Ruby 是一个非常强大而且易于

费、开放源代码本质更加凸现了这些
工具的价值。

作者介绍:
黄亮,西安交通大学毕业,2005
年加入 ThoughtWorks,对反垃
圾 邮 件 系 统 略 有 研 究 ,闲暇时
喜欢电脑游戏,是敏捷开发的
忠实程序员。

>>> 需求分析

铅笔和纸最有效,而不是电脑
—温伯格需求访谈实录
□ 整理 / 潘加宇
理解客户的真正需求
 对于捕获需求,要记住,这
不是技术层面的事情,而是关于一方怎
样能理解另一方的问题。需求分析人员
首先要理解这一点,即使在对方没有意
识到的情况下。要理解从未有过的需求,
理解人们到底要什么,你的工作就是要
帮助他们找到真正所需要的。客户自己
通常是无法做到的。如果需求分析时牵
涉到不止一人,那一定会有不同的意见
出现,这时候还要帮助他们自己去解决
相互间的异议。例如,业务经理希望系统
速度很快,部门经理则关注成本。这里就
隐含着一个意思:他们可能没有足够的
资金来建一个快速的系统。您怎么能知

语里时常发生。我们有个很好的词叫需

道真正的需求是要系统快还是要成本低

求想法(Requirement Idea)。有人说我要

第四是要给需求排时间表。比如我

呢?开始你是不可能知道的。如果自己

一个快速的系统,要系统能够完成此项

们要构建一个功能但不是在发布第一轮

直接做这个决定,就会犯错。你所能做的

任务。其实这只是个需求的想法,你并不

产品时构建,那现在就不把它作为需求。

就是说服他们必须自己把这个问题先解

真正知道他们要什么,他们付得起什么

决掉。捕获需求非常有用的一个方式是:

样的价格,以及最终构建的系统是什么

当客户说要什么的时候,你可以去看看

样子等。比如说“用户友好”就只是一个

系统的用户是怎样做这件事的。例如客

想法或者连想法都谈不上。

户说要系统有很快的速度,你就可以去

接下来就是澄清需求 。我们有个词

需求。

很多时候需求根本没有变
人们常说需求改变了,这是不对的。
需求根本就没有变,而是一开始工作没
有做好,没有得到所有的需求,所以看起

看看系统用户真正需要多快才合适。当

叫需求候选(Requirement Candidate)。

来仿佛变了。我们曾为一家石油公司做

你看到用户在做这件事情的速度时,可

当有人说要“用户友好”的系统,这不

咨询工作,一家非常大的公司。构建的系

能会发现他们没法工作得那么快。这时

能成为需求,因为它是不清晰的 ,需求

统是有关他们所有购买的支付事宜的。

即使客户想要,这个需求也是不符合现

要明确。这时可以把“用户友好”叫做

要保证准时支付,不被欺骗等等。他们花

“需求候选”。我们有一定数量的需求候

了 2500 万美金构建这个系统,最后把我

选,有些能做,有些不能做,有些可以

叫去看是不是做好了。我发了个邮件告

道中文里怎么样,但英文我们说需求这

同时做,还有些甚至所有的都可以做 ,

诉他们公司所有人将就这件事开一个会,

个词时可能谈论的是完全不同的事,因

但可能负担不起。然后我们再进入决策

如果他们想讨论这个系统的话就应该来

为用同一个词有时会发生混淆。这在英

的过程,决定哪些需求候选成为真正的

开会。他们认为这傻极了,因为所有来开

实和客观规律的。
另外就是要辨别。这非常有用。不知

Programmer

75

管理&实践

Management & Practices

需求分析 >>>

会的人他们都认识,再把他们聚在一起

是 50 年来的基本法则。

生涯里,从没见过所谓能够准确无误理

开会只是浪费时间。但这时有人敲门进

以美国为例,现在我的客户会雇用

解客户需求的人。我们可以一丝不差地

来了,以前没人见过他。他是公司的审

人类学家或社会学家,像需求团队一样

编程,但永远不可能一丝不差地知道人

计,工作就是保证一切都是正确的,但在

工作。那他们是怎么做的呢?他们去观

们要什么。所以只要需求过程一开始,就

整个系统构建的过程中他们从未和他谈

察人们,使用系统的人们,研究他们是怎

要意识到我们永远不可能准确无误地捕

过。当他走进会议室,提出了各种各样新

么使用系统的。每个过程都是持续的,从

获到需求。当您构建系统时,你会不断地

变更是必然的。在我 50年的计算机生涯里,从没见过所谓能
够准确无误理解客户需求的人。我们可以一丝不差地编程,但永
远不可能一丝不差地知道人们要什么。

发现不同的需求。在软件开发过程中要
把这点加进去,这很有用。大家可能听说
过敏捷编程,这种方法是说系统建了一
点儿,你就去和客户确认:这是你要的
吗?他们说不完全是,这里有些不一样,

的需求,都是从来没有听说过的。其中一

来没有停止的时候,因为人总是在变的,

忘了告诉你这件事,然后你再回去做出

些需求非常困难,甚至必须要抛弃整个

变化就是人们在明天做的事情。一个简

些不一样的东西。如果你的过程是要完

系统。是需求改变了吗?不是的。需求一

单的例子,你的用户是喜欢用菜单还是

全准确地理解客户需求,你一定会犯错。

直在那儿,只是他们从没有去问他,没有

用快捷键来建立一个档案,许多系统现

事情不可能一次搞定,一定会变化。

很好地使用系统思维,需求工作没有做

在都构造成能够记录这一点的形式。如

有一种应对需求变更的方法,那就

好。所以,在做需求时我们要确认已经预

果人们改变了工作方式,系统也可以改

是需求管理。你将需求存放在一个地

计到了所有对这系统会有要求的人。如

变,这是需求的更高层次。也就是说这个

方,和你管理代码的方式一样,用同样

果不是的话,就一定会有没有预料到的

需求是要求系统可以随人们的改变而改

的方法来控制变化,这就需要有一个需

东西出现。

变。如果不能,比如Google的竞争对手开

求文档系统。记得我们构建美国空间追

始了什么新的东西,Google 就要作出回

踪系统时,我们服务的对象——政府的

应,这些是没有办法预计的。

代理机构,总是不断地要求变更。然后

另外,你必须要明白有些人是你必
须要去了解的。例如,政府会变更法律,
这时你也就要跟着变。不然你不知道政

另外还可以通过模拟来预见需求。

我们开始注意到上周才提出的变更,到

府将会对你怎么样。而这些事情你总是

在建系统之前, 先假设我们就是这个系

一周后可能又要改回原样。我们的控制

可以从过去中了解到的。你需要做系统

统。通常在新系统开发之前把人都聚在

方法之一就是做任何变更前先暂时扣在

的评估,问问过去发生了什么样的变化。

一个房间里。每个人扮演系统的一个角

手里 2周,如果2 周后他们不再变,我们

我们有一些银行需要向政府报告银行交

色,我做记录客户订单的软件,你是计算

再处理它。

易的情况,他们构建了系统,但在过去的

的,你是负责发货的,还有人是负责现金

总的来说,我们当时做的就是告诉

10~15 年的时间里,都没人要去看政府

和支票记录追踪的,还有人做不同的客

客户变更对他们而言是有成本的。如果

对报告的要求变了多少回。在美国,立法

户。在一个地方,在很短时间内,人们可

你的客户可以无休止地提出变更,一点

者每两年都会修改法律,甚至修改了银

以看到系统是怎么工作的,这样就可以

成本也没有,那么你不可能管理好你的

行法。银行的人很意外,只能修改系统。

用系统思维来避免犯严重的错误。因为

需求。做工程需求分析时有两件事很重

他们怎么能预见到这些变化呢?况且每

之前你只看到各个部分,对于他们之间

要:每个需求都包括它的成本和是否值

两年就会变。这种变化就是系统的需求。

怎样一起工作没有认识。有时可以做电

得我们去做。这种成本必须是客户能理

未来是来自过去的,你研究了过去,就可

脑模拟,比如各种交通阻塞的情况,去发

解的。在我和政府一起工作的案例里,我

以得到更多的不可预见的需求。你可以

现长龙的起源在哪里等等。这些事情人

们有同样的问题。他们坐在办公室里,想

看在你的银行过去一年发生了什么,或

们可能不太愿意投入地去做,因为它很

到什么好主意就说“好吧,我们要做这

者其他银行,或者其他业务的情况,或者

花费时间和金钱。

个、那个”。我们说这可得花掉上百万美

网络的变化等。做好准备,我们知道会再
发生什么,因为在过去发生过的将来还
会再发生。这就是最好的预见未来需求
的方法。总的来说,软件容易被改变,这

76

程序员

元,但对于他们来说这是不起作用的,因

如果需求真的变了,要学会
聪明地对待
变更是必然的。在我 50 年的计算机

为他们花的是纳税人的钱,而只要我们
把他们的好主意放到了系统里,他们就
成了英雄。我们做的是当有人提出需求

>>> 需求分析

铅笔和纸最有效,而不是电脑
—温伯格需求访谈实录
□ 整理 / 潘加宇
理解客户的真正需求
 对于捕获需求,要记住,这
不是技术层面的事情,而是关于一方怎
样能理解另一方的问题。需求分析人员
首先要理解这一点,即使在对方没有意
识到的情况下。要理解从未有过的需求,
理解人们到底要什么,你的工作就是要
帮助他们找到真正所需要的。客户自己
通常是无法做到的。如果需求分析时牵
涉到不止一人,那一定会有不同的意见
出现,这时候还要帮助他们自己去解决
相互间的异议。例如,业务经理希望系统
速度很快,部门经理则关注成本。这里就
隐含着一个意思:他们可能没有足够的
资金来建一个快速的系统。您怎么能知

语里时常发生。我们有个很好的词叫需

道真正的需求是要系统快还是要成本低

求想法(Requirement Idea)。有人说我要

第四是要给需求排时间表。比如我

呢?开始你是不可能知道的。如果自己

一个快速的系统,要系统能够完成此项

们要构建一个功能但不是在发布第一轮

直接做这个决定,就会犯错。你所能做的

任务。其实这只是个需求的想法,你并不

产品时构建,那现在就不把它作为需求。

就是说服他们必须自己把这个问题先解

真正知道他们要什么,他们付得起什么

决掉。捕获需求非常有用的一个方式是:

样的价格,以及最终构建的系统是什么

当客户说要什么的时候,你可以去看看

样子等。比如说“用户友好”就只是一个

系统的用户是怎样做这件事的。例如客

想法或者连想法都谈不上。

户说要系统有很快的速度,你就可以去

接下来就是澄清需求 。我们有个词

需求。

很多时候需求根本没有变
人们常说需求改变了,这是不对的。
需求根本就没有变,而是一开始工作没
有做好,没有得到所有的需求,所以看起

看看系统用户真正需要多快才合适。当

叫需求候选(Requirement Candidate)。

来仿佛变了。我们曾为一家石油公司做

你看到用户在做这件事情的速度时,可

当有人说要“用户友好”的系统,这不

咨询工作,一家非常大的公司。构建的系

能会发现他们没法工作得那么快。这时

能成为需求,因为它是不清晰的 ,需求

统是有关他们所有购买的支付事宜的。

即使客户想要,这个需求也是不符合现

要明确。这时可以把“用户友好”叫做

要保证准时支付,不被欺骗等等。他们花

“需求候选”。我们有一定数量的需求候

了 2500 万美金构建这个系统,最后把我

选,有些能做,有些不能做,有些可以

叫去看是不是做好了。我发了个邮件告

道中文里怎么样,但英文我们说需求这

同时做,还有些甚至所有的都可以做 ,

诉他们公司所有人将就这件事开一个会,

个词时可能谈论的是完全不同的事,因

但可能负担不起。然后我们再进入决策

如果他们想讨论这个系统的话就应该来

为用同一个词有时会发生混淆。这在英

的过程,决定哪些需求候选成为真正的

开会。他们认为这傻极了,因为所有来开

实和客观规律的。
另外就是要辨别。这非常有用。不知

Programmer

75

管理&实践

Management & Practices

需求分析 >>>

会的人他们都认识,再把他们聚在一起

是 50 年来的基本法则。

生涯里,从没见过所谓能够准确无误理

开会只是浪费时间。但这时有人敲门进

以美国为例,现在我的客户会雇用

解客户需求的人。我们可以一丝不差地

来了,以前没人见过他。他是公司的审

人类学家或社会学家,像需求团队一样

编程,但永远不可能一丝不差地知道人

计,工作就是保证一切都是正确的,但在

工作。那他们是怎么做的呢?他们去观

们要什么。所以只要需求过程一开始,就

整个系统构建的过程中他们从未和他谈

察人们,使用系统的人们,研究他们是怎

要意识到我们永远不可能准确无误地捕

过。当他走进会议室,提出了各种各样新

么使用系统的。每个过程都是持续的,从

获到需求。当您构建系统时,你会不断地

变更是必然的。在我 50年的计算机生涯里,从没见过所谓能
够准确无误理解客户需求的人。我们可以一丝不差地编程,但永
远不可能一丝不差地知道人们要什么。

发现不同的需求。在软件开发过程中要
把这点加进去,这很有用。大家可能听说
过敏捷编程,这种方法是说系统建了一
点儿,你就去和客户确认:这是你要的
吗?他们说不完全是,这里有些不一样,

的需求,都是从来没有听说过的。其中一

来没有停止的时候,因为人总是在变的,

忘了告诉你这件事,然后你再回去做出

些需求非常困难,甚至必须要抛弃整个

变化就是人们在明天做的事情。一个简

些不一样的东西。如果你的过程是要完

系统。是需求改变了吗?不是的。需求一

单的例子,你的用户是喜欢用菜单还是

全准确地理解客户需求,你一定会犯错。

直在那儿,只是他们从没有去问他,没有

用快捷键来建立一个档案,许多系统现

事情不可能一次搞定,一定会变化。

很好地使用系统思维,需求工作没有做

在都构造成能够记录这一点的形式。如

有一种应对需求变更的方法,那就

好。所以,在做需求时我们要确认已经预

果人们改变了工作方式,系统也可以改

是需求管理。你将需求存放在一个地

计到了所有对这系统会有要求的人。如

变,这是需求的更高层次。也就是说这个

方,和你管理代码的方式一样,用同样

果不是的话,就一定会有没有预料到的

需求是要求系统可以随人们的改变而改

的方法来控制变化,这就需要有一个需

东西出现。

变。如果不能,比如Google的竞争对手开

求文档系统。记得我们构建美国空间追

始了什么新的东西,Google 就要作出回

踪系统时,我们服务的对象——政府的

应,这些是没有办法预计的。

代理机构,总是不断地要求变更。然后

另外,你必须要明白有些人是你必
须要去了解的。例如,政府会变更法律,
这时你也就要跟着变。不然你不知道政

另外还可以通过模拟来预见需求。

我们开始注意到上周才提出的变更,到

府将会对你怎么样。而这些事情你总是

在建系统之前, 先假设我们就是这个系

一周后可能又要改回原样。我们的控制

可以从过去中了解到的。你需要做系统

统。通常在新系统开发之前把人都聚在

方法之一就是做任何变更前先暂时扣在

的评估,问问过去发生了什么样的变化。

一个房间里。每个人扮演系统的一个角

手里 2周,如果2 周后他们不再变,我们

我们有一些银行需要向政府报告银行交

色,我做记录客户订单的软件,你是计算

再处理它。

易的情况,他们构建了系统,但在过去的

的,你是负责发货的,还有人是负责现金

总的来说,我们当时做的就是告诉

10~15 年的时间里,都没人要去看政府

和支票记录追踪的,还有人做不同的客

客户变更对他们而言是有成本的。如果

对报告的要求变了多少回。在美国,立法

户。在一个地方,在很短时间内,人们可

你的客户可以无休止地提出变更,一点

者每两年都会修改法律,甚至修改了银

以看到系统是怎么工作的,这样就可以

成本也没有,那么你不可能管理好你的

行法。银行的人很意外,只能修改系统。

用系统思维来避免犯严重的错误。因为

需求。做工程需求分析时有两件事很重

他们怎么能预见到这些变化呢?况且每

之前你只看到各个部分,对于他们之间

要:每个需求都包括它的成本和是否值

两年就会变。这种变化就是系统的需求。

怎样一起工作没有认识。有时可以做电

得我们去做。这种成本必须是客户能理

未来是来自过去的,你研究了过去,就可

脑模拟,比如各种交通阻塞的情况,去发

解的。在我和政府一起工作的案例里,我

以得到更多的不可预见的需求。你可以

现长龙的起源在哪里等等。这些事情人

们有同样的问题。他们坐在办公室里,想

看在你的银行过去一年发生了什么,或

们可能不太愿意投入地去做,因为它很

到什么好主意就说“好吧,我们要做这

者其他银行,或者其他业务的情况,或者

花费时间和金钱。

个、那个”。我们说这可得花掉上百万美

网络的变化等。做好准备,我们知道会再
发生什么,因为在过去发生过的将来还
会再发生。这就是最好的预见未来需求
的方法。总的来说,软件容易被改变,这

76

程序员

元,但对于他们来说这是不起作用的,因

如果需求真的变了,要学会
聪明地对待
变更是必然的。在我 50 年的计算机

为他们花的是纳税人的钱,而只要我们
把他们的好主意放到了系统里,他们就
成了英雄。我们做的是当有人提出需求

想法时,用这样的方式让他们个人付出

你们也看。几年前我参与了CA公司在夏

使用。简单的项目不应该用很多的工具

成本:如果你要我们考虑你的主意,你就

季奥运会的工作,构建一个记者使用的

或者软件来捕获需求。

要坐下来和我们一起工作,直到我们有

信息系统。当我们建成那个系统的时候,

一旦你对需求有了很好的理解,
当然

了清晰的需求候选。如果你不愿意花时

人们会带着变更需求的想法来找我们。

可以将它们放到电脑里,这样更容易管

间来和我们说清楚确切要的是什么,我

想法很好,但是我们只能拒绝,因为只要

理,或者做些小的更改。你从纸和铅笔开

们就不会把它作为需求。这是控制变更

奥运会开始,系统就结束了。至少在4年

始,
有时对于一些系统或者项目来讲这就

的一个根本依据。你不得不让人们在要

内,没有人会再用到这个系统。这是非常

足够了。我有的客户在项目里放一块大

求变更时有一定的成本,不然他们就会

高成本的系统,因此我们在系统的很早

板,加上几张纸就是所有要用的东西。项

变来变去。

阶段就对需求的变更订下了非常严格的

目最多有两周,1个月或者6周就结束了,

我记忆里有这样一家公司,他们的

规则。但另外的情形下你可能需要在整

把所有东西都输入电脑里太浪费时间。

业务是把灌装程序转换到另外的灌装机

个项目中都安排需求变更,这可能会持

对于大一些的项目,有了基本想法之后,

上,让同样的程序在新机器上做同样的

续多年。

可以放在电脑里,根据事情的规模而定。

事情。他们说就要做这个,让新程序和
旧程序做一样的事,不要增加,也不删
除任何东西,需求非常准确完整。在这

如果项目在全世界好几个国家进行,你

铅笔和纸最有效,而不是电脑
记录需求最有效的工具是铅笔和纸,

应该使每一个人都可以得到它,可以放
在服务器上,这样每个人都可以访问。我

种情况下,就可以告诉客户精确的成本

我喜欢用即时贴,或者用胶带把纸贴到

没有说铅笔和纸是唯一可以使用的工具,

和完成程序所需要的确切时间。如果客

桌子上,有时是地板上。我们把每个想法

只是它的是最开始要使用的,也是最简

户说我要做成一样的系统,只有有一点

写在一张纸上,放在地板上,移动它们,

单的工具。

点不同,这时候需求就会不确定了。通

把它们放在一起看,把相似或相矛盾的

常大多数情况就是这样的。极端的情况

放在一起,和人们交谈,就用这些纸片工

是甚至要到了系统构建好你才知道需求

作,澄清问题。最糟的就是用电脑,尤其

我认为需求分析师要善于倾听,擅

是什么。例如,假设你在互联网上开始

是最开始的时候。如果这样做可就大错

长沟通,在写作上清晰易懂。你也许只是

做卖玩具的生意,你从前没有做过这样

特错了,太复杂了。它在你和你要获得需

一个可怜的软件开发人员,而面对的可

的系统,所以不可能在做之前就得到确

求的人中间平添一道阻碍。

能是高层的大老板,非常严厉又精明,你

需求分析师应该具备的技能

切的需求。只有在真正投入其中之后才

另外的工具是,你要让

要能够和他们交谈。你

明白业务是怎样。这时你可以有一个样

你的耳朵保持工作状态,要

要在不懂的时候说我不

板需求。

听仔细,听清楚。也就是说

知道而不去猜。这种个

你要听清别人说什么。程序

人技能不是每个人都擅

不把任何事情完全确定下来,因为只有

员常常在寻找需求时认为

长的。你必须要能和人

当系统开始使用后才会有新的需求。许

他们要告诉客户,说服他们

们打交道。如果你不擅

多或者大多数的系统构建永远不会结束, 什么才是他们想要的,但这

长这些就不要做需求的

在整个需求过程中不断会有新的需求。

不是他的工作 。需求是倾

工作,让更有这方面的

50年前,我们使用瀑布过程,在设计或写

听,听清楚别人说什么,确

特长的人去做。在做需

代码之前把一切东西都做好。现在就不

认他们理解自己在说什么。

求时,我还会去找那些

会总是这样的情况了。你的软件过程必

做好了这件事才轮到我们

写作好的人。我的新书

须计划成在进行中随时都会有新的需求

开始说:你不能同时做这个

(Weinberg on Writing:

和澄清工作。每向世界发布一件产品,只

和那个等等。这些就是需求的工具。其它

the Fieldstone Method)就是有关写作的。

是此阶段需求的结束。一有新产品,系统

任何工具我都不会去用。有些不一样的

我发现这个圈子里的人们在写作上没有

就要变化。必须就计划成这样,时刻都要

地方就是,有些人用卡片,有些人不同事

很好的练习。如果他们不能用中文写得

将变化在项目中的成本计算在内,因为

情用不同颜色的纸,这都可以,但不要搞

很清楚,就做不好需求的工作。以上是我

每做一次变更都需要花一些时间。

得太复杂了。这也许不是你愿意听到的,

建议需求分析师去发展的技能。

因为做事情时总希望有个软件工具可以

■  责 任 编 辑 :霍 泰 稳  (htw@csdn.net)

我们无论做什么都要很容易更改,

现在正在进行冬奥会,我想在中国

Programmer

77

Management & Practices

管理&实践
项目实践 >>>

一个项目团队的敏捷之旅
□ 文 / 莫映
近日,欣闻首届“敏捷中国日”
开发者大会将于六月初召开 ,这无
疑是中国敏捷开发者的一件大事。
敏捷方法历经数年传布 ,以其注重
实效的特质,已渐入人心,并开始焕
发出勃勃生机。不少一线团队更是
早已将其用诸实际 ,并从中获益良
多。本文讲述了一个团队改进的故
事,取自笔者近期接触的一个真实
项目。希望能对那些关注敏捷方法
如何应用于实际项目的读者有所帮
助。文中采用的敏捷实践主要来自
极限编程(Extreme Programming),读
者可以从近期出版的《解析极限编
程(第二版)中文版》中找到有关极
限编程的详细介绍。

一直捉襟见肘,因此真正的大规模开发

待改进。改进需要时间,在有限时间内还

直到最近才展开,客户对此却毫不知情。

要将部分精力投入到团队改进上,这无

先说说系统:整个系统由三个模块

疑增加了难度系数。好在通过与包括管

构成,其中一个基于第三方系统开发,并

理人员在内的所有成员的沟通中,我了

且有一部分工作被外包了出去;另一个

解到,大家对团队改进的必要性和紧迫

则迫于进度压力,沿用了来自其他项目

性都有所认同。这在一定程度上为团队

的一个遗留系统,虽然系统设计混乱,代

改进工作的开展创造了条件。

码维护困难,但是以往的运行记录良好;
最后一个模块则要从头做起。
再说说团队:由于项目中要用到
Struts、Spring 和 iBatis 框架,而成员们对

开始着手规划第一个迭代周期。

这些框架的熟悉程度还不够。好在先期

◆  为了让这个复杂而棘手的问题尽

已为他们做了简短的培训,通过一个迷

量简单,同时也为了使我们能在力所能

你教学项目,大家在短期内已经掌握了

及的范围内做得更好,我将大部分精力

如何使用“SSI”的基本技能。不过,从

集中于指导团队实现系统的三分之一功

我对他们代码的复查情况来看,成员们

能,就是从头做起的那个模块。同时,这

的编码习惯尚有欠缺。代码中随处可见

也为我们赢得了更多团队改进的时间。

的“Bad Smell”让人不禁心生忧虑。

背景

第一个迭代周期
在和团队成员进行短暂磨合后,我

◆   为了尽量打消包括项目经理在

看上去这是个风险颇大的项目:

内的团队成员们对项目进度的疑虑,

不久前我接触到一个项目团队,
并且

◆  我们真正能够控制的部分,其实

我将“迭代计划”作为团队改进的第一

作为开发过程的跟踪者介入了其中。在

只占整个系统的三分之一。团队中每个成

个“故事”
(极限编程中的概念 )。从目

我进入项目时,需求调研已于先期完成,

员对能否如期完成预定的功能都没有把

前现状来看,相信这是团队改进最迫

部分模块的开发工作也已由程序员自发

握,当项目经理问及系统能否如期交付

切需要的,同时也是实施难度和阻力

地开始了。但是,因为向客户承诺的项目

时,我很坦白的回答说:目前还不知道。

相对较低 ,最有望获得成功的 。考虑到

启动时间是在一个月多前,而部门人手

◆  团队成员有待历练,团队过程有

成员对敏捷方法还较为陌生,我并不

78

程序员

急于将诸如持续集成、测试先行一类
听起来很“酷”的敏捷实践放到团队的

取主动的心情是可以理解的。

价值最大化。

不过,在决定加班前,也许我们可以

“加班事件”让我联想到另一件事:

让事情变得明朗化一点:项目经理或业

某些组织中,时常会对加班加点的员工

◆  作为一项辅助措施,我让程序员

务分析师根据客户的商业价值将复杂的

给予表彰,并将这样的先进事迹广为传

在开发期间每天都向代码库提交当天完

问题域分割成一系列“用户故事”,然后

播。凭心而论,作为加班者,这毫无疑问

成的工作,然后在次日复查所有昨天的

由程序员负责将故事细分成任务并估算

是他辛勤劳动应得的回报。只是,将这样

代码。通过一个叫 Jupiter 的代码复查工

时间,估算的过程也是业务观点和技术

的事作为典范加以宣传却是有悖于极限

具,我把藏在代码中的“Bad Smell”逐

观点彼此调和的过程。经过这道工序之

编程的价值观的:极限编程更加鼓励精

一找出,并告知相关责任人。这么做的目

后,含糊不清的问题在充分沟通中被逐

力充沛的工作,因为这是对他人尊重的

的是希望通过一段时间的持续复查,在

渐澄清,人们的恐惧心理在很大程度上

体现。假如延长工时可以让项目不至失

一定程度上矫正开发者的编码习惯。在

也得到了缓解。

控,我们可以选择加班。但如果不是这

改进计划中。

目前还无法要求程序员彼此互查的情况

为了赶进度,人们经常会打两张牌:

样,休息其实是尊重自己和他人的最好

下,复查工作毫无疑问落到了我的肩上。

时间和人员。在有限的时间里增加工作

方式。对自己身体的透支可能会毁掉未

不过,常人在一天内完成的工作不会太

时间,就是加班;而增加人手在《人月神

来数天的工作,这对你和团队都是不利

多,因此以天为单位来复查代码还算轻

话》中已经被证明是不可靠的。有趣的

的。疲惫不堪的人很难意识到,自己正在

松。更重要的是,
“Bad Smell” 一旦出现,

是,我就真的经历过一个“堆人式”的项

增加整个项目的风险。

会在至多一天的时间内被发现,这样的

目。伴随项目的延期,不断有人填补进

反馈速度应该是足够敏捷了。在实际实

来,团队规模最多时有近二十人。可惜那

施过程中,我发现程序员的响应速度很

时我尚不知敏捷为何物。

插曲二:形同虚设的 Wiki 公告
在第一个迭代周期里我犯了一个错

快,当通知他们复查结果后,一般都能在

其实,敏捷团队的手里还有第三张

误。为了把项目现状及时反馈给团队内

半天到一天的时间内完成所有的代码修

牌:当现有资源不足以完成所有用户故

外,我用Wiki开了一个项目专区,将分解

改。当然,起初“复查——修改——再复

事时,而且团队士气也向我们发出警

的用户故事、进度预估,还有团队的日常

查——再修改”的反馈十分频繁。有时,

告,试图通过增加工作时间来追赶进度

公告贴到了上面。我相信公示是必要的,

我甚至因为不厌其烦的打搅他们而觉得

已经变得十分危险时,不妨在当前的迭

这体现了极限编程中的沟通和反馈。选

很不好意思。还好大家都很理解,在迭代

代周期里有选择地完成一部分故事。这

择 Wiki的初衷,则是因为我的个人偏爱。

周期快结束时,成员们对代码复查的效

么做的前提是:要有一个对当前问题域

但事实证明,这样的电子化手段并没有

果都还算满意。

的分解,并形成经过估算的故事。接下

起到预期的效果。除了习惯查看 Wiki 最

来的工作就像是在超市买东西:货价上

近更新或者订阅RSS的员工外,其他人根

插曲一:加班
在迭代开始后的第一个周五,团队
召开会议。为加快进度,决定周末加班
(当时迭代计划还没做好)。听到这个消

为了赶进度,人们经常会打两张牌:时间和人员。在有限的
时间里增加工作时间,就是加班;而增加人手在《人月神话》中
已经被证明是不可靠的。

息,成员们的情绪明显有些糟糕,阴郁的
气氛笼罩着团队。

的商品中,有些是你要买的必需品,有

本不会主动去浏览Wiki。于是,对那些不

也许很多团队都已习惯加班这样的

些则不是,有些是你很想要,但又超出

了解项目现状的人而言,摆在他们眼前

极端做法了,听起来这似乎应该是极限

预算开支的。当你走到超市出口准备买

的依然是个黑箱。后来,我吸取教训,改

编程的实践,“极端”的英文不就是 ex-

单时,假如兜里的钱不够支付你挑选的

用了常人更容易接受的沟通方式——邮

treme 吗。做出加班的决定,很大程度上

全部商品,那么很简单,你需要重新考

件,还有直接的面对面交谈。这个教训让

归因于人们对未知事物的恐惧心理和缺

虑哪些该买,哪些不该买。在这一点上,

我再一次明白,在敏捷团队中为何会有

乏明确有效的反馈机制。大家对团队的

我们也许应该向勤俭持家的女士们学

一面“故事墙”:将富含信息的内容以一

开发现状和项目进度都心里没底,因此,

习:学会如何精挑细选,在聪明的花掉

种常人更习惯的形式,摆在显眼之处,体

在前途未卜的情况下,尽量往前赶以争

兜里“钞票”的同时,让“购买物品”的

现了很好的人性化。

Programmer

79

管理&实践

Management & Practices

项目实践 >>>

经历。单元测试还有很多好处,在开始实
践测试驱动开发之后,这种好处还会提
升到更高的层次。但对于一个原本就对
单元测试不“感冒”的人而言,这无疑是
一个非常实在的起点。另一次,一位结对
者问我:为什么每回我都喜欢改完一小
段代码并且确认无误后就往CVS提交,而
他却喜欢做完所有修改后一次性提交。
这是灌输敏捷思想的好时机:对一个习
惯了敏捷思维的人而言,迭代和小幅前
进的原则会很自然的体现在他的日常行
事之中,即使这并没有被明确的定义为
某项敏捷实践。
◆ 通过结对,
可以鼓励充分的沟通,

并且更细粒度的把握项目风险。在上一个
迭代周期,团队中有时会发生这样的事:
结对编程模拟场景 

当我走到某位程序员身边询问进展时,他
告诉我
“遇到了一个问题”,而这个问题也

第二个迭代周期

这样的安排看起来有些不合理,不过这

许已经困扰了他一天。在习惯开周会的团

经过上一个迭代周期,团队对计划游

并不影响总体进度。我们甚至能安排出

队中,问题恐怕会被延误得更久:所有问

戏已经较为熟悉了,因此在开始新周期

一定的时间,将某些延期任务交给团队

题都将被堆积到周五的会议上来讨论,即

时,迭代计划进展得很顺利。在完成故事

成员自己来完成。当我们将项目进度再

使问题在周一就已经发生了。按照极限编

估算后,我和程序员们一起坐在会议室

次以图表反馈给项目经理时,他在给大

程的观点:谈话的嗡嗡声是团队健康的标

里,在白板上讨论哪些故事先实现,哪些

家的回复中表示:非常满意。

志,沉默只会使风险堆积。一天下午,在

应该放到后面。然后将讨论结果绘制成

项目的稳步进展让我有了更多机会

和一位程序员热烈讨论过后,我终于说服

图,并通过邮件发送给项目经理和部门主

能将精力投入到团队改进中来。本次迭

了他,用户想要的也许不是将当前报表页

管。团队内外都有一些非常关注项目进展

代中,我开始尝试结对编程,方法是:每

面导成 Word 文档,而是生成一份打印稿。

的人,同时他们也拥有决策权,这些决策

天投入大半天时间和几乎团队中的每个

如果没有这样的沟通,也许会有大段时间

往往事关团队的成败。为了消除VIP 们对

程序员结对。虽然这种“车轮战”式的结

被浪费在实现这个从未得到证实的功能

进度的疑虑和恐慌,将团队内部口头讨论

对有些特别,但却是经过慎重考虑的:

上。另一次结对经历则是我和一位程序员

的结果适时地以非正式文档的形式反馈出

◆ 我希望通过这样的形式,为成员

一起完成了一个大模块的代码迁移,这次

去是非常有必要的。没错,就是文档,这

们示范好的开发实践,同时不失时机的

结对的目的在于“Double Check”
:一个人

是人们熟悉的一种沟通手段,不过仅是用

灌输敏捷思想。言传身教的效果往往要

在操作键盘时,另一个人监督操作的正确

于沟通之用,刚好够用就行。

比纸上谈兵来得好。有一次,一位程序员

性。这样,我们可以及时发现迁移过程中
不小心引入的错误。

进入第二个迭代周期,团队的开发

告诉我,运行在他本机的系统出现了一

速度渐趋稳定。当我在迭代中期评估项

个诡异的错误,从异常堆栈来看应该是

◆ 充分沟通可以减少孤独感,而结

目进展时,欣喜的发现,一切都在有条不

某个iBatis DAO 类的问题,可是经过无数

对则形式化的强调了沟通。对于沉默寡

紊的按计划进行,团队的工作气氛也变

次费时的部署和服务器启停后,依然没

言的团队成员,我个人很怀疑他能在这

得轻松起来。虽然,个别次要任务因为某

有找到症结。此时,我不失时机的为他示

个团队待多久。

些不可控的因素导致了延期——某些开

范了一个单元测试,原因很快就被找到

◆ 团队成员自身还没有足够的结对

发任务是由团队外的人员承担的,而他

了——Spring配置文件里有个很隐蔽的错

经验,为了让结对更有效率,两位结对者

们正深陷于另一个项目,自顾不暇——

误。对他而言,这是一次“印象深刻”的

中必须有一位能主导结对的过程。

80

程序员

一句题外话,有些人也许对结对存

会去响应请求。但是很多时候,有的“实

员学习不容易自学的知识,示范有效的

在误解,认为它妨碍了个人的私有空间。

例”也许要同时响应多个请求,而响应完

实践,也要对整个过程负责,保持团队在

其实,结对并不意味着不能独立思考,需

毕后又会马上被安排处理其他的请求,

可承受的节奏下工作,并持续改进。最

要时大家可以坐到一起,不需要时也可

因而池里永远都是空的,员工们得不到

后,作为教练的一项重要工作还包括:找

以回到各自的私人空间。理想的敏捷团

充分的修整。更有甚者,有的“实例”还

出知道答案的人,并把信息及时传达给

队对工作空间会有一定要求,比如敞开

未处理完当前请求,就会被“调度逻辑”

有权力做出决策的人。

的没有隔板的办公桌,但即便现实环境

重新分配,以响应别的请求。在这样的氛

有限制,也没什么大不了。相反,如果认

围下,人们只是满足于每个个体都在忙

同结对的价值,人们反而会更加珍惜在

于敲打键盘的虚幻效率,而忽略了应该

软件开发不仅是程序员的活动,缺

让员工尽量与熟悉和信任的同事在一起

少了对所有参与人的利害平衡,无论对

工作,也忽略了这种随意切换带来的高

项目还是团队本身,都将是危险的。技术

昂代价(比如时间和精力的浪费,也许这

人员对敏捷方法情有独钟往往是从重构、

项目中期,曾有位出差归来的程序

可以换来两天的休息日,而非加班)。也

测试驱动这些明显带有浓厚技术色彩的

员中途加入团队。可是分配给他相应任

许将人比作可以随意调配的资源本来就

实践开始的。但是要想获得成功,只关注

务后还不到一周,他又被调到了别的项

是个错误。从这个意义上讲,人力资源

这些还不够。在敏捷方法的受众里,有些

目。于是,原本安排与他结对的程序员, (Human Resource)一词,至少在计算机领

人也许不能为开发做出贡献,但他们的

花了大约两天的工作交接和沟通时间都

观点对团队的成功却很重要,比如:项目

“恶劣”环境下的结对机会。

插曲三:人员更迭

域恐怕是一种误导。

被白白的浪费了。此外,还有一种常见现
象是“单人多任务”,比如有些成员还同
时承担着其他项目的工作。敏捷方法的

更开阔的视野

经理、测试人员、客户代表。项目进展期

故事还在继续
文章即将结束,不过项目仍在继续,

间,我们要时刻注意协调技术观点与业
务观点的矛盾。此外,要想保证项目的成

观点认为:工作内容的频繁切换即不利

也许这样的敏捷实践案例就是我们不少

功,我们还要将视野扩大到团队以外。有

于团队的整体感和连续性,也不利于生

项目团队每天的真实写照。作为尾声,这

时,组织机构中主管人员所做的决策往
往会对团队产生很大的影响。如果漠视
或回避这些影响,恰恰就是漠视和回避
充分有效的沟通。经验告诉我们,在敏捷
方法的实施中,最大的困难在于:你需要
用事实来说服别人接受你的方式,尤其
是那些拥有决策权力的人。只有所有人
都有一致认同的价值观,敏捷方法才能
最大限度的发挥价值。

作者简介
莫映,北京慧点科技开发有限公司

产效率。这让我联想到一些组织中时常

里还有些话要对读者说:

Java 用户组(www.bjug.org)核

发生的一类现象,我把它称为“被池化的
人”。想必读者对数据库连接池不会陌
生:作为一种创建代价高昂的资源,数据

产品研发中心技术经理 ,北京

教练的作用
我们可以发现,在团队改进中,教练

库连接一般会被预先实例化并放入池中, 的角色至关重要。就如读者在故事中看
一旦数据库访问请求到来,就会有池中

到的,我的职责是:发现团队改进的机

的实例来响应。类似的,某些组织中,人

会,并引导大家尝试解决问题;当团队在

们即被看作是一种可被池化的资源。当

压力驱使下做事时,提醒他们做简单的

有项目“请求”到来时,池中“实例”就

事情;既要有足够的技能来教导团队成

心成员,同时也是满江红开放技术
研究组织(www.redsaga.com)
成员。有多年软件从业经验,对极
限编程和敏捷方法颇有心得,并参
与和指导了多个软件团队的敏捷实
践,取得了较好的效果。
■  责 任 编 辑 :霍 泰 稳  (htw@csdn.net)

Programmer

81

Management & Practices

管理&实践
项目实践 >>>

轻松实现软件产品的国际化
—浅谈多语言带来的可用性问题
□ 文 / 刘大鹏
 这篇稿子早在半年前就开

坚持看到最后,相信读者也不见得喜欢

决方案是双字节甚至多字节 Unicode的编

始在头脑中酝酿了,但是却迟迟没有下

吧!因为如果在内容中不能很好的突出

码和界面支持。

笔。原因有二:一是这个命题实在太大,

文章要意,这本身就是种不友好的用户

微软甚至有一个庞大的机构和部门在负

体验!但是最后经过和编辑的交流,还

语言和本地化不仅仅是简单的静态翻译。

责国际化(Internationalization)、全球化

是决定暂时从几个主要的方面做个重点

多语言和本地化过程是一个庞大的系统

(Globalization)和本地化(Localization)的

的说明,以点带面,抛砖引玉,便于使一

工程,需要由多方面、跨学科的团队进行

2. 从具体执行和管理角度来讲,多

工作,并且在MSDN上长期在线解决相关

些还不是很清楚国际化多语言软件产品 (如可用性专家、本地化工程师、专业翻

的问题。况且由于杂志本身的篇幅所限

的战略意义和正确实施方式的软件企业、 译人员,集成项目经理,发布测试管理人

和我们需要重点阐述易用性的出发点,

工程师们,能够快速的了解国际化软件

我们只能要么对其做大而全的乃至长篇

产品的设计和开发方法,同时也希望借

3. 从易用性测试和产品架构设计角

大论的叙述,要么专注在某些具体的点

此提高大家对于多语言带来的易用性问

度讲,良好的多语言和本地化支持是一

面来做透彻深入的说明;其二是希望能

题的认识。

个重要的可用性检测指标,因为它体现

员,界面工程师等)。

够开辟技术类杂志新的文风,因为就个

首先我们先明确几个概念和观点:

了我们产品界面中出现的文字和字符是

人的体验来说,很少能够坚持把一篇掺

1. 从具体技术实现角度来讲,到目

否具有相当的可读性和一致性水平——

杂着各色代码和充斥着行业术语的文章

前为止,国际化多语言软件的最优化解

即是否清晰可读、可见能够正确表述功

82

程序员

能和传达给用户有用的信息,并且符合

如果企业沟通软件出现了软件界面上或

用户的操作和认知习惯。

者中英文文字由于不可读造成互相不兼

软件国际化和多语言的最高境界就

容,那么可想而知后果是什么,这可能导

是很好的本地化。近年来随着国际化和

致一个季度的预算和销售都可能会受到

本地化需求的不断出现和生产力水平的

影响,数以千万资金可能遭受损失……

提高,国外大型国际化软件常常需要发

什么是 Unicode?
为什么要使用 Unicode?

创业型企业,而失去了做大做强的机会。

布几十种语言的本地化版本,但是对于

Unicode provides a unique number for every character,

应用场景二

为每个字符都指出定了一个唯一码

亚洲表形意字体的处理,显然我们国内

当前欧美市场上普遍流通的软件产

的研发企业更加有利,因此我国自主研

no matter what the program,  不 论 在 任 何 程 序

品大多数属于国际化软件产品,而我们

发或者开发海外项目支持多语言的软件

no matter what the language.  不 论 在 任 何 语 言

国内自主研发的软件产品却大多还没有

和产品本地化都具有非常大的发展潜力。

考虑或很少考虑产品国际化问题和支持

并且可喜的是,我国的一些软件本地化

多语言版本,但是欧美市场上的软件产

公司凭借为欧美国软件公司长时间提供

工业领域的巨头如 A p p l e 、H P 、I B M 、

品、尤其企业应用软件又大多根据西方

中文软件本地化服务,已经与客户形成

Microsoft、Oracle、SAP、SUN,Sybase、

的标准和作业习惯进行开发和定制,那

了互相信赖的客户关系和取得了长足的

Unisys 等许多知名公司广泛采用和推广;

么国内的企业是不是一定要“娶”一个

经验,所以国内软件企业自主研发的国

从开发语言和平台角度讲也有越来越多 “洋媳妇 ”而找罪受呢?最直接的案例

际化和本地化软件产品无疑会在近年开

的脚本和编程语言开始支持这一标准,

便是如同十年前盛行的 ERP 一般,投入

始展露头脚,融合于国际化的趋势之中,

如:XML 、JAVA、JavaScript 、LDAP 、

和产出不成正比、周期工期冗长,最终

成为未来的中坚力量。

CORBA、WML 等。同时它也被越来越多

导致严重整合问题;或者买了个看似成

的主流操作系统内置,如:Windows XP。

熟的国外中间件进行二次开发。但是又

这里需要说明的是,它的出现意味着一

有多少企业的市场变化能够等到软件整

那么软件产品的国际化和多语言的

个划时代产品的来临,因为微软从这一

合的“功德圆满”?这其间抛开企业自

历史有多久了呢?以我们最为熟知的国

刻起第一次真正把国际多语言版本操作

身的开发成本和项目管理不说,单就一

际化软件产品成功典范——“微软制造”

系统全球同步发布!

个本地化问题就足够让人头疼,因为本

为例,在微软最早提出windows软件平台

地化并不仅仅是界面和语言上的本地

国际化和本地化的观点的人究竟是谁

最终目的,全球产品的可用性!即在产品

化,还应该包括用户体验的量身定做,

呢?几经追溯,我们发现了一些有趣的

的各种不同语言的版本中为用户提供一致

而买来的半成品却往往不会为我们考虑

结果,那就是身为国人并且曾经担任微

的外观、风格、功能和用户体验。因为随

这些!

软中国区总裁的唐骏先生对于Windows多

no matter what the platform,不 论 在 任 何 平 台

— — 引 自   Unicode.org

目前,Unicode 的技术标准已经被 IT

国际化、全球化主要是为了实现一个

多语言需求的产生和广泛应用

着世界的不断变化,国际文化之间的大融

既然市场需求如此巨大和强烈,为

语言和本地化、尤其是亚洲表形表意版

合,国内外企业之间的并购和合作,国内

什么却很少有人试水一跳?这里原因当

本(韩文、中文和日文等)做出了贡献;

公司跨国业务的发展等,这些企业用户都

然很多:一是国内软件企业的项目管理

另外就是在Windows国际化应用开发领域

希望在世界的任何角落都能够有一致的人

水平相对还比较低和缺少国际化的眼光:

久负盛名的神秘人物Dr. International(后

机交互使用体验,快速获取商业价值。这

很少企业愿意放弃目前短期项目和直接

来查证为 Nadine Kano 博士)。首先让我们

里包括用户母语和外来语言的融会贯通,

的利益去做些长远的规划,所以我们纵

深入了解一下具体的细节,以下是引自

企业文化之间的无缝对接!

然有着世界上数量最为庞大优秀的技术

微软前中国区总裁唐骏先生的一段自述:

人才群体和资源成本优势,观悉近代计

“1993 年 4 月,唐骏博士后毕业,用

算机和软件发明以及世界性通用标准的

卖专利的8万美元开了三家公司:一家做

应用场景一
比如说联想在收购了 IBM 个人 PC 部

拟定,以至于在全球范围内取得广泛影

软件、一家做文化经纪、一家做法律事务

门之后,国内的销售总监需要在第一时

响的软件产品我们几乎还没有;二是归

服务。后来当唐骏已经有几十万美元身

间了解在美国研发部门的最新产品情况

其原因并不是专业技术人才的缺少,而

价的时候,他突然关闭所有公司,决定去

和性能指标现状,那么频繁的实时沟通

是缺乏对于远景有规划能力并且可以洞

微软做程序员每年领几万美元的年薪。

和企业内部文件交换便必不可少,但是

悉国际形式、拥有资本运做能力的产品

但是他后来说“我发现我的企业做不大,

Programmer

83

管理&实践

Management & Practices

项目实践 >>>

我做事情就喜欢将事情做大。”随即唐骏

www.microsoft.com/globaldev/default.

从洛杉矶跑到西雅图对微软说,
“只要让

mspx 的“坐诊”博士 International 十几年

我进微软,让我干什么都行。”随后他被

来一直兢兢业业的回答关于本地化和国

分到 Windows NT开发组做程序员,当时

际化的问题,而对于他的贡献大家如果

正值1994年。
(这个日期和Dr International

有兴趣的话可以认真的阅读他的著作并

出版 Developing International Software 第

且到网络上查看,但是至于与唐骏的渊

一版的时间几乎吻合,不知道两者之间

源就无从考证了。

是否存在必然的联系?)”

图 3:Windows 95/98/Me 下 无 法 正 常 地 示多语言

具体的集成方式有哪些?

“微软当年开发多语言版本的原有思
路是:先开发英文版,然后再将英文版移
植到其他语言版本中去,所以当时移植
一个中文版甚至需要几十个工程师花一

这无疑意味着如果使用目前利用

虽然我现在已经不是职业的程序员, Windows API开发的多语言国际化软件产
但是使用Delphi开发新产品的快速交互原

品可能会牺牲一些Windows 95/98/Me的

Delphi 的 Windows 应 用 开 发

需 要 第 三 方 插 件 (Plugins) 支 持 , 如 TnTUnicodeControl

年半到两年时间!刚进微软几个月的唐

Php, Java…

需要相应的官方或者第三方类库

骏一开始便觉得这种办法很愚蠢。在他

VC.net…

看来,Windows在开发的时候,就应该基

编 译 器 内 置 对 于 Unicode 的 支 持
( 在 这 里 我 们 主 要 讨 论 基 于 Windows 的 应 用 )

于双字节,这样其他语言的版本软件就

形一直是我的最爱,因为它有着丰富灵活

用户,但是无论如何,我们已经尽可能满

可以和英文版几乎同时推出了。微软总

的语法和强大的可视化编程界面,并且提

足了 80% 以上的用户,而且从未来的趋

部当时采纳了唐骏的建议,NT 工作组的

供可插入式的第三方支持控件,这可能也

势来看,这种取舍也是必须的——如果

700多名程序员要么听唐骏讲解《如何写

是 Delphi得以被普遍认可和应用的主要原

花很大力气去解决一个几乎被淘汰的低

国际版本的操作系统》,要么看唐骏写的

因。这里先来介绍一下由TntWare 提供的

版本平台问题,也是得不偿失的,毕竟微

《国际版操作系统开发手册》。这此之后,

Delphi第三方插件TnTUnicode Controls 来迅

软也在鼓励用户不断升级。对于这一点

速快捷的开发多语言应用。

感兴趣的朋友可以看看目前几个主流的

唐骏又直接负责 Windows 日文、韩文和
中文版的开发,带领有30多人的团队。虽

Unicode 应用,如现在炙手可热的 VoIP产

然刚开始的时候Windows3.1中文版比英

品 Skype就是使用 TnTUnicode开发支持多

文版晚了一年半,到了后来,中文版和英
文版几乎可以同时推出!……”

图 1:  Delphi 环 境 下 的 TnTUnicode 控 件

语言的国际化软件,在Windows XP使用

但是不幸的是,Windows 平台对于

环境中,我们甚至可以自己增加本地化

注意,这里唐骏提到的是双字节,已

Unicode 的支持是非常有限的,所以利用

的语种,但是在Windows 98环境下界面

经不是普通意义上的单字节ASCII码,而

Windows API 封装的控件也不能脱离厄

可就不堪设想了。

且虽然当时 Unicode 在 1991 年就已经发

运,目前只支持一些32-bit 和64-bit的主

明和出现,但是一直都没有在大型的系

流操作系统,如Windows NT/2000/XP/

统和软件产品中得到普遍应用,而唐骏

2003等。以下是利用TnTUnicode开发的同

恰逢 1994年进入微软,所以按照这个时

一个应用程序的对话框在不同的操作平

间推断唐骏的自述显然是有一定说服力

台上的体现:

的,那么唐骏也很有可能是在微软较早
考虑运用Unicode技术提供全球同步多语
言版本的人之一。同时也可能为

图 4:Delphi 开 发 设 计 支 持 Unicode 的 对 话 框

Microsoft Press出版社出版的《Developing
International Software》一书做出过很大
的贡献,这也就难怪他会获得微软授予
的最高荣誉——比尔・盖茨总裁杰出奖

图 5: 在 VC.net 编 译 器 中 内 置 的 Unicode 支 持

两次之多了。
后者就是微软官方网站 h t t p : / /

84

程序员

在 Microsoft 的.net 开发环境中对于
图 2: Windows 2000 或者以上版本正确地显示多语言

Unicode 的支持更为深入和集成,只需要

在项目的编译设置中选择相应的字符集

Windows NT来说意味着什么。

设置- Use Unicode Character Set 就可以
自动引入 Unicode 的支持,在这里就不再
赘述。而对于多语言具体的开发设计方
案则可以查阅下面的内容。

的解决方案,当然,我们阐述的仅仅是基

解决方案二的描述和示意图

本的原理,事实上的方案会异常的庞大

上一种方法最大的不利之处就是需

和复杂,并且非常具体,甚至于对于同一

要大量的重复工作并且耗费大量的人力

个Message Box的提示语句进行多语言字

和物力,而本方法的主要思想

解决方案实例

版本进行扩展,这基本上就是微软目前

符串的处理。

是把界面文字资源和与核心

在应用程序和软件国际化产品设计

代码无关的资源相分离,尽量

中实现多语言界面,即MUI(Mutli- Lan-

减少多语言资源对于功能代

guage User Interface)的方案可能有很多

码的影响,而对于语言的切换

种,但是基本上每种解决方法都是下面

在 DLL 中做适当的 Code Page

这几种方法的变种:

的切换处理,这样一来就可以有对于核

Out Application.exe English.dll

Chinese.dll

Japanese.dll

多语言界面的可用性测试

◆  为每个语言版本编译一个相应的

心代码并不了解的本地化工程师,甚至

二进制资源文件,从形态上看是一个完

是经过培训的翻译人员维护这个DLL,把

通过正确有效的多语言解决方案开

整 Execute文件。

注意力和焦点集中到界面语言和语法问

发设计了具体的应用之后,我们还需要

◆  设计开发一个支持并包含多语言

题,相对降低了成本并减少了工作的失

经过不断的版本更新,从Beta发布直到正

资源的动态链接库(DLL)但并不涉及程

误。但是这种方法并非没有缺点:这种方

式版本。这里最重要的环节当然是可用

序核心代码的二进制文件。

法实现的前提是把语言资源和核心代码

性测试,而多语言界面的测试与软件核

◆  对应每种语言版本都设计开发一

分离的很好,但是对于一个正在成长中

心功能特性测试并不相同,可以称作国

个或一组相对应的资源动态链接库

的软件产品显然是不现实的,而且可能

际化测试和本地化测试:如用户界面一

会给程序员带来一定的困扰。

致性测试检查和语言翻译质量检视、界

(DLL )并不涉及程序核心代码的二进制
文件。

面术语和专有名词的一致性等等。因此
这里需要有懂得测试方法的本地化工程

解决方案一的描述和示意图

师或易用性测试人员,通过严格的、不断
Chinese.Res

这种方法是在 Unicode标准出现之前
所普遍采用的传统的多语言解决方案,
也就是当时唐骏所提出的认为比较愚蠢

的 Checklist 进行比对和分析,周而复始,
迭代完成。由此可见,多语言软件产品是
系统的工程,而最终解决的问题却毫无

Our Application.exe

的方法。因为它需要对不同的语言版本

疑问的是界面语言用户体验的一致性,

进行翻译之后,单独对于特定语言版本

Res.Dll

甚至是全球用户体验的一致性!

应用程序进行文字资源翻译和重新编译

作者简介

工作,这样的做法对于一个小型的工程
English.Res

和应用尚且需要非常大的工作量并且会
占用大量的磁盘空间。最重要的是还会

Japanese.Res

刘大鹏,易用性

解决方案三的描述和示意图

和交互设计研

带来版本的维护问题:如果一个翻译字

这种方法应该说是对于上一种方法

究和交流平台

符串发生了改变就需要对全部的工程重

的自然延伸,而且从实际应用和管理角

ChinaHCI.Org

新编译,那么可想而知对于当时庞大的

度应该是最为科学和合理的方式,它并

网站创始人,

不是把所有的语言包都整个封

美国 ACM 人机

装在一个资源文件中,而是把

交互特别兴趣小

他们相对物理分开,这样一来
便可以针对于大型软件系统不
同的模块有针对性的进行多语
English.exe

Chinese.exe

Japanese.exe

言处理,并且方便对新的语言

组 SIGCHI及 UPA(易用性专业协会)
成员,具 有 丰 富 的 行 业 背 景 和 嵌 入
式系统易用性设计经等。
■  责 任 编 辑 :霍 泰 稳  (htw@csdn.net)

Programmer

85

Management & Practices

管理&实践
项目实践 >>>

微软软件设计规范书撰写技巧
—软件开发项目管理案例解说系列 (三)
□ 文 / 栾跃
 在上一期(06年第5期)的

被总结在设计规范书里,规范书里

《程序员》杂志里有关软件开发项目管

没有的则不该开发。有这样的明

理的系列文章中,我以自己曾经从

确定义,能帮助开发团队避免无

事过的开发微软嵌入式操作系统的

效开发,也能帮助测试团队建立

项目管理作为案例,讲解了制定开

有的放矢的测试计划。

发项目计划的一些关键管理概念和

◆    它为整个开发团队提

实践指南,包括项目时间表的制定

供一个可以共同参照的统一标

流程、如何确定每个开发阶段的

准:任何功能开发上有疑问的,

里程碑、如何制定衡量是否达到

都以设计规范书所总结的要求

开发里程碑的终结标准等等。文

为准来解决。同时,其它各种

章中还提到完善的软件开发项目

有 关 的 项 目 计 划,如 测 试 计

管理要求管理人员在制定项目的

划、文件编辑计划、可用性计

执行计划时间表的同时,还要同

划、本地化计划等各种计划 ,都

时照顾到体现软件本身的设计计

以产品的设计规范书作为它们的计

划,而这个设计计划是用软件的设计规

划准则。

范书(也叫 Design Specification,或简称

功能设计规范书是整个设计构思的中心。

Spec)来总结的。

所以它是整个软件开发项目的中心指南

项目参加人员提供一个对功能设计进行

◆    它为项目的赞助者、客户以及

在这篇系列文章里,我来进一步讲

文件,也可以说它是开发计划安排的基

审核、对照和解决问题的共同讨论点和

解软件设计规范书的撰写,包括可供借

石,因为它为其它的开发计划提供一个

对证:开发团队的成员以它为标准来协

鉴的撰写模版提纲、如何总结使用界面

参照的标准。

商对设计的建议和意见、对设计提出疑

的设计、如何总结出错信息等,以及微软

首先,作为软件开发者,应该充分意

问等等;另外,客户对设计规范书的审核

在这方面的良好企业文化传统。如果能

识到在开发之前将软件的使用功能的设

的认可与通过,则表示他同意了被总结

够使你的开发团队在项目计划阶段也采

计先进行全面的总结,并以文档作记录

了的所需要开发的功能的范围,同时也

用类似的设计计划,对推动你们的开发

的重要性。不同的开发者和开发团队对

表示他同意了不要求开发规范书里没有

成功会有很多好处。

如何进行这样的使用功能的总结有很多

总结的功能。

不同的习惯和方法,但是不管采用何种

软件设计规范书的撰写提纲
功能规范书是整个开发团队用来进
行设计交流的最主要的文件和手段。它

那么,一个完整的设计规范书应该

方法,将所需要开发的各种使用功能的

包含那些内容呢 ?对不同的开发项目,

设计用文件固定下来,会为软件开发带

设计规范书的着重点和范围当然会有些

来巨大的好处:

不同,但从总体上来说,如果能对以下这

陈述、归纳、总结了一个软件产品或系统

◆  就像为盖房子提供一个蓝图那

些内容都有明确的定义和总结,在很大

中所有的功能设计的具体细节。在一个

样,Spec 为整个软件的功能开发提供一

程度上能帮助开发团队明确理解功能的

软件产品或系统最终完成和成型之前,

个完整的规划:需要开发的功能应该都

设计和开发的目标:

86

程序员

软件产品设计规范书的撰写提纲和模版
1. 文 件 的 梗 概 和 介 绍 :

是,使用界面在被使用的过程中各个控
制组件应该如何反应、软件应该如何给

 总 结 : 在 设 计 规 范 书 的 开 头 , 对 整 个 开 发 项 目 做 个 总 结 。 用 简 单 几 个 段 落 从 宏 观 的 角 度 对 整 个

项目的目的和它所开发的功能做一个描述。

使用者准确的回馈、使他们能够完成必

 范 围 : 说 明 设 计 规 范 文 件 所 叙 述 的 范 围 , 包 括 文 件 中 各 个 部 分 的 内 容 大 纲 。

要的使用方案(也叫 User Scenarios,即

 读 者 : 简 要 地 描 述 阅 读 和 理 解 此 份 设 计 规 范 文 件 的 读 者 , 及 其 必 要 的 前 提 和 知 识 背 景 。

软件功能使用的过程和顺序)去解决具

 文 件 的 修 订 历 史 : 注 明 这 份 文 件 自 初 稿 后 的 所 有 修 订 历 史 , 包 括 修 订 日 期 、 改 动 的 内 容 和 理 由 、

谁作的修改,以及修改内容的页数。

体的问题,开发工程师们事先就有一个
可参照的准确的“蓝图”。要是没有这样

2. 开 发 项 目 的 目 标 : 用 段 落 文 字 总 结 以 下 内 容 :

 远 景 : 总 结 整 个 开 发 项 目 的 远 景 , 也 就 是 开 发 的 战 略 目 的 或 目 标 的 定 义 。

 设 计 目 标 : 陈 述 开 发 的 结 果 所 需 要 解 决 的 具 体 问 题 , 以 及 为 达 到 这 些 目 的 所 做 的 相 关 功 能 设 计

的概述性总结。

详细的设计,开发工程师可以临时发挥
去任意开发 。那样开发出来的结果也许

 项 目 理 由 的 辩 护 : 说 明 为 什 么 需 要 进 行 这 个 项 目 、 开 发 这 个 功 能 或 产 品 。  

有时是可以满足要求的,但在很多情

 项 目 的 客 户 和 合 作 者 : 列 出 项 目 开 发 出 的 结 果 所 要 服 务 的 具 体 客 户 , 以 及 项 目 进 程 中 所 要 依 赖

况下往往是无法满足要求而造成浪费

的合作伙伴、包括企业内部其它部门的合作者和企业外部的合作者。

 项 目 的 风 险 以 及 成 功 的 依 赖 者 : 列 出 整 个 项 目 所 面 临 或 可 能 会 遇 到 的 风 险 。

 项 目 进 度 的 里 程 碑 : 用 表 格 的 方 式 将 整 个 项 目 的 里 程 碑 详 细 地 列 出 来 , 并 对 每 个 里 程 碑 完 成 结

束的衡量标准做总结陈述。

的无谓开发。合理的软件开发的项目
管理,就是要尽量减少和避免这种无
谓的劳动和浪费,而要使每个被开发

 使 用 方 案 和 系 统 流 程 图 : 用 逻 辑 图 或 其 它 图 像 来 说 明 系 统 的 数 据 处 理 的 流 程 、 各 种 组 件 单 元 之

间怎样互相配合来提供所设计的功能,注明各种数据的输入、输出、和处理等等。

出来的功能、每个使用界面的组成部

 3. 功 能 需 求 的 总 结 : 在 这 一 章 里 详 细 列 出 软 件 所 有 应 该 开 发 的 功 能 。 每 个 功 能 应 该 有 相 对 应 的

分,都有它们明确的目的、都是为了保

客户使用方案为基础。最好的方法是用表格逐步列出产品必须支持的使用方案,以及每个使用方

证使用方案的完满执行而起到它们的

案所依赖的功能。
4. 功 能 的 具 体 设 计 : 在 这 一 章 里 详 细 总 结 和 列 出 软 件 所 有 功 能 的 具 体 设 计 。 对 每 个 具 体 的 设 计 进
行详细的陈述,并配上所需要的图像进行解释。对每个具体的设计进行包括以下内容的详细陈述:

 所 提 供 的 功 能 、 性 能 或 其 它 服 务 。

 使 用 界 面 的 解 说 , 包 括 软 件 总 体 的 运 行 界 面 的 框 架 、 不 同 的 视 窗 的 功 能 、 菜 单 (Menu) 、 工 具 条

作用,设计规范书中明确无误的界面设
计总结就是关键。
下面我仍用自己在微软进行过的嵌入

(Tools Bar)以 及 按 键 (Buttons), 状 态 条 (Status Bar), 图 释 (Icon), 以 及 每 个 对 话 框 (Dialog

式操作系统工具的开发项目管理作为案例,

Box)的 设 计 和 形 象 , 产 品 的 徽 标 (Logo) , 启 动 画 面 (Splash Screen) 等 等 。 它 们 还 应 该 包 括 每 个
控制键和输入时段的使用法、系统的反应和回馈的行为,以及每个出错的信息、格式、和具体的
文字,等等。

 产 品 使 用 说 明 (Online help) 的 设 计 、 连 接 、 内 容 要 求 。

5. 设 计 的 考 虑 因 素 : 总 结 其 它 设 计 中 必 须 满 足 的 要 求 :

 运 行 平 台 的 要 求 : 此 产 品 或 系 统 对 运 行 环 境 的 各 种 要 求 , 如 操 作 平 台 、 硬 件 、 网 络 连 接 、 使 用

规章等等。

 性 能 要 求 及 可 以 接 受 的 衡 量 的 准 则 , 以 及 对 产 品 安 装 的 功 能 、 安 全 性 、 国 际 化 和 地 方 化 的 要 求

等等。
6. 开 发 时 间 表 : 列 出 该 项 目 的 开 发 时 间 表 、 对 每 一 具 体 开 发 任 务 所 需 的 人 力 及 时 间 的 初 步 估 计 ,
及所有的项目里程碑。
7.  项目成功所依赖的因素:总结所有可以估计到的外在制约因素,特别要写明哪些因素是该项目成

图 1: 目 标 设 计 原 型 图

功所依赖的,如特别的人才、设备 、所需的技术、某些外部团队的支持或必须完成的组件等等。
8. 未解决的问题:总结和列出所 有 尚未解决的问题,或有待近一步调查商讨才能定出答案的有关设
计方案和计划,及任何与客户尚未达成一致的事项, 等等 。
结尾页:设计规范书通过的签字— — 当设计文件最后审核通过后 ,各团队领导和客户代表在此签字。

来举例说明如何设定明确的界面设计。
从图1中你可以看到,使用界面的设
计不仅要显示界面看起来应该是什么样,

制定明确的界面设计

面的设计必须要有明确的定义和说明。

更要有对各个界面的控制组件的行为和

除了按照上面所讲的特定的模版来

设定明确的界面设计指的是,软件

回馈进行详细的解释,比如“按了这个键

进行设计规范书的撰写,以保证很多重

的使用界面应该在软件开发之前都已经

后会发生什么……”、“在这个对话框里

要的东西不至于被忘记或遗漏、使得从

设计好了,并在设计规范书中进行详细

输入数据后会发生什么……”等等。有这

事设计的项目经理和开发团队的成员们

的总结和解说,这样开发团队的开发工

样详细的图像解释,不仅开发工程师们

不得不去思考和解决相关的一系列问题, 程师们在进行程序开发时就有一个明确

有开发的依据,测试工程师们也能够根

另一个重要的帮助提高软件开发功能规

无误的参照,不仅知道开发出来的软件

据这些具体的要求进行测试方案的制定,

范书质量的关键是,所有软件的使用界

的使用界面应该是怎样的,更重要的

文档编辑们也能够根据这些具体的界面

Programmer

87

管理&实践

Management & Practices

项目实践 >>>

行为来撰写使用说明书。这也是为什么

结。这样在设计规范书进行团队审核的

成一些非常荒唐可笑的出错信息被加入

详细的界面设计对完整的设计规范书那

时候可以很方便地进行逐条讨论,而这

到产品中去,而常常成为业界的笑柄。最

么重要的原因。

样的格式又可以为开发工程师们提供一

有名的一些可笑的出错信息包括“Y o u

图2是另外一个类似的例子,你可以

目了然的参照。下页图3是设计图像配上

just did something you shouldn’t do.”

看到这里是两个 Tree View 列表的界面

文字解说的例子(我将原来的英文产品

设计。如同上面举例的概念一样,这里

设计附上翻译便于阅读)。

对Tree View中具体的细节也要做说明,
包括图标、文字显示、按键等。用类似
这样界面设计的图画,再配上对很多具

(你刚做了个不该做的事),
“An unknown
error has occurred”
(一个不知怎么回事的
错误发生了),“A catastrophic error is

不要忽视出错信息的设计

going to happen”(像大灾难似的错误将

在软件设计中,我们不可避免地要

要发生了)等等。现在微软从事界面设计

体的界面的细节加以说明的图示文字,

碰到对各种可能出现的错误,如使用者

的团队还有一个专门刊登记录所有这些

能使设计的概念很容易被开发人员理

所犯的错误以及软件本身的缺陷带来的

可笑的出错信息的网站,叫做“UI Hall of

解,并使他们在开发时注意到这些重要

系统错误等,提供回馈的出错信息(Error

Shame”(令人羞愧的界面设计大展览),

的细节。这是一种极为有效的设计总结

Message,也叫错误信息)的设计。明确有

将全公司各个产品团队任何被发现的荒

方法。

效的出错信息设计,也必须是完整的设

唐出错信息设计登在上面,以此告诫所

当然,在设计规范书里对这样的界

计规范书所应该包括的内容。出错信息

有开发者们不要忽视出错信息的设计。

面设计光有图画是不够的,对每个界面

设计的好坏,直接影响到一个软件的可

下面这个出错信息对话框就是其中的展

设计的组成部分还应该再配上具体的文

用性,所以是任何软件开发者应该重视

出之一:
“呃哟糟糕,也许会出现个问题。

字解说。最有效的方法是将每个界面的

的设计因素之一。

还要继续下去吗?”

组成部分标明它们的重要性和优先权的

在微软的产品团队,我们的界面设

(Priority)划分、每个组成部分的名字、以

计对出错信息的质量非常重视,因为以

及具体的行为细节,用列表的形式做总

前微软有的产品对这方面不够重视,造

对任何出错信息的设计,都应该按
照下面这个设计原则来进行:

  出错信息首先应该向使用者明确

说明,究竟发生了什么问题或错误;

 出错信息应该向使用者解释是何种

原因造成了出错,即到底是因为使用者的
错误使用还是系统本身的问题造成了问题;

  出错信息还应向使用者提示,应

该采取什么样的措施或纠正的步骤,来
纠正错误或避免错误,使得使用者可以
继续使用软件。
所有的出错信息的设计必须通过设计
规范书进行全面的记录和总结,然后在程
序开发时开发工程师要根据这些设计来开
发。也就是说,任何出错信息都必须是事
先设计好的,而不应该由程序编写者心血
来潮似地任意加入到软件中去。在开发过
图 2:Treeview 列 表 界 面 设 计

88

程序员

程中要是发现有新的出错信息需要加入产

的质量控制、项目的执行与驱动的管理
指南等内容展开讨论。如果要进一步学
习具体的关于开发管理的实践指南,可
图 像 界 面 设 计 总 结 — —  状 态 条( Status Bar) 的 功 能 设 计
里程碑

M1

图像界面组成部分

界面的使用和反馈行为

Filed 1: 普 通 的 状 态 文 字

 默 认 值 文 字 : 可 正 常 使 用

 其 它 时 候 显 示 此 设 计 规 范 中 其 它 地 方 所 指 定 的 工 具 的

以参考由我所著的《软件开发项目管理》
一书。该书可在各地新华书店以及网上
书店如第二书店(www.dearbook.com)等
购得。

状态文字
在检测其它依赖组件以及操作系统镜像生成时候,每当
M3

Filed 2: 渐 进 显 示 条

工具需要有 2 秒以上的等待时间时,显示渐进显示条。

作者简介

操作系统镜像的总数显示应该是:

M2

 当没有一个镜像设计被装载在工具中 ,不显示任何数字 。

栾跃是微软总部产品

Filed 3: 显 示 操 作 系 统 镜 像

 当 一 个 操 作 系 统 的 设 计 镜 像 被 装 载 在 工 具 中 后 , 显 示

部门具有多年项目管

的大小总数

以兆为单位的、带一个小数点的、非压缩的操作系统镜

理经验的华人项目经

像的大小总数。
显示目前工具所连接的数据库:
M4

Filed 4: 显 示 所 连 接 的 数 据
库的名字

 当 工 具 刚 启 动 时 , 还 没 有 数 据 库 连 接 上 时 , 不 显 示 任

何数字。

图 3: 软 件 界 面 的 设 计 用 图 像 加 文 字 解 说

行,在对设计规范书经过修改、加入新的

十年的高科技产品开
发和项目管理的经验。曾任摩托罗拉

 当 一 旦 连 接 上 数 据 库 后 , 显 示 数 据 库 连 的 名 字 。

品,
加入的过程同样要按照设计的要求进

理之一,具有在美二

中去的最有效方法。
上面一文对软件开发项目管理的设计

设计之后,才能进行程序的改动。严格的

规范书的撰写指南作了一个简单的介绍。

管理方法是避免荒唐可笑的文字混进产品

接下来的几期中,我会就软件开发项目

的产品经理。98年加入了微软,先后
负责了 ActiveSync 3.0和嵌入式操
作系统 XPE等产品开发的项目管理。
目前栾跃是微软总部中国事务办公室
的首席项目经理。
■  责 任 编 辑 :霍 泰 稳  (htw@csdn.net)

Programmer

89

Management & Practices

管理&实践
管理工具 >>>

XP团队管理的利器
— XPlanner
□ 文 / 俞黎敏
XPlanner 的意义

 在软件项目实际开发的过

XPlanner是一个基于Web的XP团队项目

程中,总是会碰到客户提出新的需求,而

计划管理和跟踪的工具。XP 独特的开发概

XPlanner 是专门为XP 团队设计的项

且经常会要求变更需求。死亡之旅到最

念如用户故事User Story、迭代Iteration、任务

目管理跟踪工具,很多人已经了解并

后期限却因进度问题而交付不了,或者

Task等,XPlanner都提供了相应的支持,支持

在实施这一软件开发方法,但真正使

是交付给客户的系统里问题多多。开发

XP 开发流程,并解决利用XP 思想来开发项

用恰当的 XP 管理工具来管理日常的软

人员流动率高,一个人写的程序其他人

目过程中所碰到的问题。在XPlanner里,你

件开发,手工方式还是比较常用的 ,而

接手过来很难看懂,改起来就更加困难;

可以简化计划编制模型,可以对敏捷开发

且极限编程的介绍中,也很少提及到

每天不知道到底能够完成多少个需求,

中的必要元素如迭代、用户故事及任务进

管理方面的工具,好像一切都需手工

需求什么时候才能真正完成,早就习惯

行记录与跟踪,还可以对没有完成的用户

去做,如整个房间或白板上贴满用户

了加班;每个人在项目里独立开发自己

故事再次迭代。而在团队沟通方面,用

故事卡。XPlanner 的出现可能会解决人

的模块,很少也很难相互学习,老是做重

XPlanner只需要一个邮件就可以完成分布式

们对X P日常项目管理工具的使用方面的

复的开发;重用性的东西积累为零,每个

协作,还可以跟踪团队和个人工作时间,甚

问题。

项目都得重新发明轮子;开发人员的总

而生成团队工作效率表和个人工时报表,

体水平提不上去;程序员不愿意写文档,

这些对技术能力很强而管理能力偏弱的技

统能和 IDE 结合起来,那么将对提高开

写出的文档也经常不能真实地反映实际

术经理们来说绝对是一个福音。XPlanner比

发效率有很大的帮助。开发人员无需

情况;公司项目接得很多,但开发成本也

较吸引人的特点就是它的灵活与可扩展性, 打开管理系统,执行各种操作。只要打

增加得很快,开发效率上不去,生产力总

比如你可以非常容易地将项目与迭代导出

开 I D E 工具,就可以看到所有的信息,

是徘徊不前……。是否能有一种工具可

成 XML、MPX、PDF等通用文件,支持TWiki

开发人员也不会忘记自己的任务。可

以帮助技术经理们解决这些问题呢?

风格的文本格式化与外部工具集的扩展,

喜的是已经有 I D E 工具支持 X P l a n ne r

另外还提供SOAP接口,方便地与其它系统

了,I n t e l l i J   I D E A 有个插件,可以与

集成与扩展等等。XPlanner 遵循分层架构进

XPlanner 整合起来 ,更好地管理和开发

XPlanner 是什么?

行开发。最底层为数据层,
持久数
据是存储在MySQL 等数据库中,

图 1:XPlanner 工 具

90

程序员

在日常的开发中,如果一个管理系

XP 项目。
市面上的软件开发管理工具很多,

并通过JDBC 进行访问;第二层为

如 Project、Rational RequisitePro 等,但这

ORM 层,同样XPlanner也是采用现

些商用的软件价格不菲,小公司小团队

在流行的Hibernate ORM 引擎来进

的承受力有限。XPlanner是基于 Java的开

行数据对象映射,而不是直接通

源项目,给开发者带来了更大的方便,可

过JDBC进行访问数据库操作数据

以通过定制CSS来改变表现,定制图表的

的;第三层是领域对象,
业务层处

大小等。而且如果你对目前版本的功能

理项目、迭代、用户故事、任务的

有所建议,可以及时地进行反馈甚至参

领域对象,并提供给表现层,
通过

与他们的项目中去,如果你的时间与精

JSP、Tags进行展现;第四层则是表现层。

力许可的话。

XPlanner 的使用
安装很简单,这里不做详细介绍,想

息。这有些像上下班打卡一样,小组成员

通过 XPlanner 这个工具,可以实现

每完成一个分解的任务后,就去“打卡”

上文所提到的多个方面,并且紧密配合

进一步了解XPlanner的朋友可以到Google

一下,这也是一种工作的促进,实时呈现

极限编程思想。但在项目中采用

或者百度搜索一下。下面我以“使用

工作进度。这个迭代结束了,就可以将它

XPlanner 是一个开始 ,在此基础上我们

XPlanner”为主题通过一个项目对它进行

结束。XPlanner提供将未完成的用户故事

还可以利用单元测试框架 、集成测试 、

简要说明。

转到其它迭代里面去的方法,用户故事

BUG 跟踪管理等工具来组合出一套适合

里的任务没有完成也可以将之移到别的

自己项目组的管理平台。目前在开源社

用户故事里或者其它迭代周期里去。

区里,相关的软件都可以容易地得到。

首先,创 建 一 个 项 目: 可以采用
TWiki- 样式的文本格式进行描述项目的
内容,这样在最后展现出来的内容相对
来说比较活泼一点,同时设置所要连接
Wiki 的地址,使得可在XPlanner里链接到
Wiki 进行技术交流。

在项目中采用 XPlanner 是一个开始,在此基础上我们还可以
利用单元测试框架、集成测试、BUG 跟踪管理等工具来组合出一
套适合自己项目组的管理平台。

创建用户并授权:可以根据 XPlanner
所提供的 Excel 模板输入用户的信息,然

可以在项目一级和迭代一级进行导

对于项目经理来说,一般既是管理

后把前四行删除,再另存为.csv 格式的

出,生成Project 格式的任务表,完整地显

人员,又是教练,而且是开发人员,然

文件后进行批量导入,比较方便。可以在

示出上下级与任务的层级关系,任务完

后凝聚着几个小组成员在周围进行项目

创建用户时就按项目直接授予他应有的

成情况也可以在里面体现,并且把人员

实施。全局上关注的就是每天跟踪迭代

角色,或设置为系统管理员,也可以在今

资源也进行导出,还是比较方便的;美中

过程中的用户故事进度情况,细节上就

后管理用户时再进行相应的项目授权不

不足的是不能够按任务的顺序显示,并

得追踪到每个成员的当前任务完成情

同的角色,XPlanner 里的角色有 None、

体现前后关系即前置任务,TWiki样式的

况,对比分析查找问题,跟踪进度,解

Viewer、Editor、Admin。

描述与备注仍是原样输出。任务准确按

决开发过程中遇到的一些问题,调配资

时或超时完成的会显示任务完成提示,

源,协助项目内外交流沟通反馈,积极

但提前完成的却不会,

推动项目前进。在用户故事搜集与每次

创建迭代:进入刚才创建的项目,开
始创建第一个迭代,设置迭代的开始时
间与结束时间,这样在迭代结束之后可
以进行统计,对比分析迭代预估时间的
准确性。
创建用户故事:进入迭代,就可以创

迭代提交产品经过用户试用后所提出的

给项目管理人员带来的好处
一直在思考如何提高管理与开发的

新需求的基础上,进行分析并做出优先
级排序。

水平,也在逐步地开始实施XP极限编程。

总结

建用户故事,指定客户、跟踪者、状态、

但如何能更好地运用发挥极限编程的威

优先级,当然重要的是根据在用户那挖

力是件比较棘手的事情,如何调动大家

XPlanner 作为一款专业的开源的 X P

掘到的需求进行优先级设置,1为最高级

的积极性,让一个项目组的所有人员更

项目管理工具,还可以整合Wiki,默认支

别。可以通过模板进行批量导入。

好地参与到项目中来,是一个项目成败

持 Very Quick Wiki,它的安装和配置也

的关键问题。

很简单,详细信息请参考 http://www.

分解任务:进入某个用户故事,把它
分解为一个个小任务,指定任务类型、任

项目组成员包括客户、项目经理、开

vqwiki.org/,所有的这一切都是为了更

务接受者、估计的时间等。重复以上各步,

发设计人员、测试人员、界面设计人员

这样,就把项目的第一次迭代里的用户故

等。每个部分的人对项目关心的内容和

事及故事分解的任务创建完成,接下来就

角度是不同的,例如:客户关心最终的产

是要记得启动这次的创建迭代,然后小组

品是否简单易用;项目经理关心开发进

俞黎敏,广东力维软件有限公司项目

各成员根据分解的任务开始执行。

度;开发人员关心技术的积累和从中获

经理,在电力行业从事五年多软件开

得的成就感;测试人员关心在哪里可以

发与管理工作,目前任 C S D N 网站

在分派自己的任务里,填写任务执行的

展开自己的测试,可以获得最新的源程

Java 版大版主。个人 Blog为 iAMin.

开始时间、结束时间、报告时间以及结对

序,问题解决了没有,是否可以进行再测

BlogDriver.com(超越黎明)。

成员等,并添加一些任务的相关注释信

试确认等。

完成任务: 以接受任务的用户登录,

好地使用 XP 进行项目开发。

作者简介

■  责 任 编 辑 :霍 泰 稳  (htw@csdn.net)

Programmer

91

Management & Practices

管理&实践
新视点 >>>

《程序员》杂志在 2006 年第 5 期上对浪潮软件做了相关的报道,引起了读者很大的兴趣。Loushang是浪潮软件基于
J2EE 规范开发的业务基础平台,经过多年的发展,取得了长足的进步。从本期开始,本刊将邀请浪潮软件的技术
专家以 Loushang 平台为例,在“新视点”栏目介绍业务平台相关的知识与大家分享,敬请关注。

澄清对 MDA 的误解与误用
□ 文 / 孙向晖
引言
 MDA是OMG在2002年初确

原始需求失真,最后开发的系统不是客
户想要的系统;

更要说明的是,由于验证周期越来
越短,最终用户(或者业务专家)可以快

定的战略方向。然而,时隔多年,即使在

◆ 开发层次多,费时费力;

速、真实得看到可运行的系统,可以及时

技术日新月异的今天,MDA 在业界依然

◆ 初始模型被肢解,系统到了一定

做出响应和反馈,更增加了他们参与开

算得上前沿技术。在社区里我们可以听
到这样或者那样的声音,有些源于 MDA
概念的误解,有的是对应用 MDA 过程中
产生的困惑,当然也不乏呐喊助威声。
有争鸣总是件好事。
笔者所在的团队,从事 MDA 理论的

复杂程度后,维护成本太高;
◆ 需求变更后,软件更改繁琐,难

发的兴趣。有了业务专家积极参与的项
目,距离成功就更近了一步。

以快速适应需求变化;
◆ 开发过程对技能的要求和团队成

员的实际技能出入太大;
……

实战化和 MDA 工具的开发工作已经 3 年

MDA,更注重 Model 的作用
MDA 的英文全称是 Model-Driven
Architecture。如果你在看到“Model”而联
想到了用 Rose 或者 Magic Draw 画出来的

有余。对于MDA在提高软件开发效率、增

UML 图,那么,再次恭喜,

强软件可移植性、可维护性以及改善和

你又一次“曲解”了MDA。

提升团队成员协同工作能力方面,略有

不错,大部分的

心得。希望借助这篇文章抛砖引玉,与关

MDA 工具厂商都支持基

心 MDA 的同行们交流、共享。

于UML的XMI交换,但请
不要忘了 OMG对 UML的

MDA,更强调人的价值
一位同事,在早期听到过这样一种

定义:
图 1:Loushang MDA 开 发 方 式 在 项 目 实 战 中 的 作 用 范 围

说法,
“有了MDA,程序员就失业了”,结

The Unified Modeling
Language (UML) is a

果,忧郁得辗转反侧,不得入眠。我相信,

在图 1 中我们可以看出:

graphical language for visualizing, specifying,

很多人也听说过类似的宣传,如果你真

MDA的开发过程,仍然需要“人”的

constructing, and documenting the artifacts

的相信了,恭喜,你已经成功得“歪曲”

参与,只不过,MDA对参与人员的职责

of a software-intensive system. The UML

了 MDA 的真正本质。

角色和能力要求 ,有了更明确的规定。

gives you a standard way to write a

其实 MDA 并不是要颠覆传统的开发

程序员仍然是存在的,只不过是他的价

system's blueprints, covering conceptual

方法(但确实是一个很大的改善和升

值作用越来越少了。那些“不用了”的

things such as business processes and sys-

华),而是针对传统开发方法上的一些典

程序员,其实是被解放出来,做更专注

tem functions, as well as concrete things

型问题提出了比较好的解决之道而已。

化的工作,比如蜕变成MDA工具的开发

such as classes written in a specific pro-

传统的开发方法,主要存在以下问题:

人员或者向架构师,领域建模专家方面

gramming language, database schemas, and

发展等。

reusable software components.

◆ 验证周期长,经过多层传递造成

92

程序员

简而言之,UML只是一种可视化建模
的语言,而我们应该重点关心的是用这
种语言来建模的那个“模型”
(Model)本
身。也就是说,模型驱动的真正含义是
“模型”,而不是“驱动”。
从不同的角度看去,会有不同的模
型,而在众多模型中,
“领域模型”占据
了其中最为重要的位置。任何一本讲开
发过程和开发方法的书,都会郑重提出
“保持与 Domain Expert 的交流”,MDA 方
面的书籍也不例外。我们之所以这么热
切得需要业务专家的参与,其实是为了

图 2: 某 咨 询 公 司 关 于 一 个 职 责 分 层 的 图 示

提炼更好的领域模型。
个人力资源系统来办理人员入职手续。

个模型存在或者是有遗留系统存在的大

在领域语境中应用 MDA

现在,令 HR 主管头痛的事情,是处理人

型项目中,这个问题尤其突出,因此,有

既然领域模型如此重要,那么是不

员的离职、退休问题,因此“上马一个人

必要把模型适用的边界划分出来。一般

是花费数个月时间绘制了一张网状的领

力资源系统”背后的业务内涵就是要解

采用的划分方法有两个:上下文环境

域模型大图,就算大功造成了呢?其实

决 HR 主管的业务疾痛。而不是谁是第一

这只是领域建模中的 50%,即使使用这

步就认为谁是重要的。

样的大图,也不会有人认为你可以悠闲
得完成 MDA 实现,相反,团队成员会认
为你已经疯了。

(Context)和子系统(SubSystem)。

小结

MDA 的开发过程就是让用户或者业
务专家,更加关注业务核心价值。

本文不是对 MDA 进行学术研究,我

◆ 职责分层

的目标是利用 MDA (或者其他的开发方

要想有效得应用 MDA ,我们可以借

做过数据仓库实现的人,会有这样

法)来解决业务和开发过程中的问题。

助若干领域建模的技巧和方法,来提高

一种常识:要把数据进行划分,比如分为

MDA 在开发过程中,对“生产力的解放”

项目成功率:

从不改变的、偶尔改变的、经常变化的

是大家有目共睹的,而针对领域语境进

◆ 优先关注核心价值

等。另外要认真思考模型中的概念之间

行精细建模将会在更大的程度上发挥

我在提供咨询服务时,曾经问过很

的相互依赖关系,它们之间的变动速率

MDA 的作用。

多团队同样的一个问题 ,“如果你的客

以及导致领域各个部分发生变化的来源,

户要求上马一个人力资源系统,你认为

以界定领域的自然层次,这就是领域建

应该先实现哪部分?”得到的答案大致

模技术中的职责分层。

都是相同的,“入职”。如果再深究得出

职责分层并不是IT界的产物,它属于

此答案的基本思路,也会是惊人的一

领域建模技巧。在我看到的若干国际知

致,“因为增加人员是人员管理中的第

名的咨询公司的报告中,经常会用到职

一个步骤”。

责分层的图示。在 IBM 的 SOA 解决方案

这个问题的答案或许是对的。但其

作者简介
孙向晖:儿子小名
“豆豆”,常被人称为
“豆豆他爹”。1998年
开始步入 IT行业,现
就职于浪潮软件技
术研究中心技术管

中,我也亲切地看到了职责分层的应用。

理部。负 责 指 导 内 部 团 队 和 合 作 伙

思考问题的出发点却是个不折不扣的错

这无疑是在说明,这种思维方式的共通

伴开展基于 Loushang框架的OOAD

误。它错就错在 “要准确回答这个问题

之处。

开 发 和 开 发 过 程 管 理。目 前 专 注 于

的关键,不是‘你认为’,而是‘你凭什

◆ 边界

研究和实践MDA/UP/UML/SCM等

么认为’”。

即使是看待同样一个事物,因为观

相 关 技 术 在 团 队 中 的 大 规 模 应 用,

目前的人才市场,供大于求,企事业

察者站的角度和立场不同,最后得到的

对 产 品 化 的 软 件 项 目 管 理 、需求管

单位更是人满为患。搞信息化已经这么

角度也是不同的。这个角度和立场,也影

理和配置管理略有心得。

多年了,每一个单位或多或少已经有一

响我们的做事和思考问题方式。在有多

■  责 任 编 辑 :霍 泰 稳  (htw@csdn.net)

Programmer

93

Management & Practices

管理&实践
管理圈 >>>

激发IT团队的

和谐特质
□ 策划 / 霍泰稳

 “和谐”现在成为一个越

队都有自己的难处,在沟通过程中也

为了了解当前研发团队内部的沟通

来越时髦的词汇,建设和谐性社会、和

各有自己的技巧,如何应用这些技巧

现状,我们在CSDN网站上开展一个短期

谐性社区等等。在我们所关注的 IT 领

或者注意事项去管理自己的团队,是

的调查,两天内调查人数就突破千人,充

域,虽然在研发过程中多以小团队出

每个管理人员必须要面对的问题。

分说明我们的开发人员对这一话题的关

现,但麻雀虽小,五脏俱全 ,和谐与否

本期我们邀请了百度公司人力资源高

注。因为个人经历不同,处在不同环境下

在很大程度上也影响着团队的工作效

级总监鲁灵敏,现代卓越集团副总经理周

的人对数据也会有不同的理解,在这里

率,比如前一段时间网上盛传的 E M C

浩宇,亿讯国际高级顾问王晓毅及浙江正

我们不对调查数据做深入剖析,请读者

邮件门事件,只是因为一个邮件最终

元智慧公司的开发部长张武等四位在团队

朋友自己去解读,也欢迎在 CSDN 网站

导致 E M C 的企业形象大为受损,两位

管理上颇有经验的专家就“如何激发IT团

《程序员》读者社区就这一问题继续展开

当事人总裁和秘书双双离职。每个团

队的和谐特质”这个问题进行评点。

94

程序员

讨论……

工作热情。当然,对这些失败,我们会像

能“容忍失败”才更有发展

对待那些成功的经验一样,会去总结去
学习,以给后来人一种提醒,在遇到类似

文 / 鲁灵敏(百度公司人力资源高级总监)

的情况时避免重蹈覆辙。
一个成功的团队与它的领导人或者

在百度公司里面评判一个团

IT 研发领域,只有不断地鼓励

说管理者是分不开的。那么领导在维护

队是否合格的时候,我们首先会考

创新,容忍创新过程中的失

团队的发展时,应该注意的是什么呢?

察这个团队的氛围是不是融洽的。

败,才能更大地激发出员工的

首先我认为是要以身作则,严格要求自

其实在我们的团队里面,尤其是研

潜力。举例来说,从前我们有

己,所谓“上梁不正下梁歪”说的就是这

发团队里面是没有等级概念的,无

个员工接手了一项分布式检索

个道理。第二就是一定要有成文的制度

论你是CTO、技术总监还是项目经

系统的设计和开发,简单来说

与目标。在百度内部,考核员工时是以结

理,大家的地位都是一样的。讨论

主要是仿照Cache机制,把需要

果为导向的,就是说团队成员要明白自

问题的时候,我们只看重事情的对与错。

的检索结果放到距离用户近的机器上,

己的目标是什么。有了目标,员工才能从

比如在讨论会上,一个新来的员工提出了

以提高用户的访问速度。这个想法是很

中了解应该将力量正确地用在什么地方。

一个巧妙的解决问题的办法,那么大家都

好的,而且当索引库几个月不更新时,效

这样,目标是明确的,领导又是以身作则

会去支持他,在这个办法的基础上再去细

果也会比较明显。但是用户的检索通常

的,有这两点的保证,这个团队就不会差

化。所以说百度的研发团队是一个非常严

是动态的,在快速更新的情况下,实际应

到哪儿去。另外需要注意的一点,就是团

谨的或者说学术气氛很浓的组织。

用中占用的资源太多,而且还有可能限

队本身的文化要与整个企业的价值观保

制其它的应用。最终这个项目放弃了。但

持一致。我们很难去改变个人的价值观,

这儿很有发展的一个原因是我们的“容

公司并没有因这件事情而责备这名员工,

但是可以改变他们的行为,时间长了,行

忍失败”文化。在一个团队里,特别是在

相反还肯定了他的成绩,维护了员工的

为就会变成良好的习惯。

另外很多百度的研发工程师认为在

作为管理者,在团队中应该时刻注意
了解成员的最新状态和绩效,要达到这个

强调执行力,尊重不同的价值观

目的就需要创建良好的沟通环境和加强团
队建设,
以下两个方面是特别需要注意的:
倾听使工作事半功倍:不同的沟通

文 / 王晓毅(远航通信息技术有限公司副总经理兼 CTO)

形式适用于不同文化。强调团队精神的

鼓励合作 、共享与主观能动

英国人不友好,而是他们在接

公司倾向于征询意见,共同参与。而强调

性。管理者以开放的心态让大

待客人时比较正式,不像国内

个人绩效或单兵作战能力的公司喜欢叙

家积极参与团队讨论,但在形

那么让人一见如故。所以不能

述说服模式。独裁者喜欢指令式的沟通,

成决策后要有坚决一致的执行

武断地认为一个群体内的所有

而民主者倾向于征询意见的沟通。虽不

力。我曾经将
“理解的要执行,

人在任何时候都有同样的行为

能说那种沟通形式更好,但对于IT行业,

不理解的在执行中理解”写入

举止。正确的方式是把表现作

精英中内秀者较多,强调团队征询意见

团队文化制度中。当然领导的

为行为而不是评价来描述。目

的方式更容易取得信息接收者的好感。

胸怀更是一把衡量领导力的永恒标尺。

前国内雇员对来自日本、新加坡或者台

另外,倾听更是一个领导需要注意的方

随着全球化,不同地域的种族语言

湾地区的领导排斥感比较强,认为他们

面,善于倾听,将使你更了解你的下属并

文化冲突也摆在我们面前。置身于此中

善于政治和高压手腕。但其实如果我们

做出正确的决策。

的我们每一个人在沟通中都要特别注意

了解了其文化,就会看到他们身上敬业

群体智慧,强调执行力:团队建设不

不同种族文化的内涵和背景。我有个同

和工作层级感较强的一面。相反,来自这

是空话,更不是请客吃饭。创造团队良好

事被派到英国工作,结果很不顺心,回来

些地区的雇主有时会认为大陆员工比较

的沟通氛围和公平环境是团队领导的首要

给大家反馈说英国人很冷漠,比较难接

浮躁,而事实上大陆员工只是更注重自

职责。将团队绩效和个人绩效统一起来,

触。但后来我和他沟通后才了解到不是

尊自由和个体发展的需求。

Programmer

95

管理&实践

Management & Practices

管理圈 >>>

我们经常听到“沟通从心开始”这句
广告语,暂不论为什么广告商会选择此

团队建设“以和为贵”

言做宣传,但这句话本身却道出了“和谐
团队建设”的真谛。作为管理者,不了解
直接下属的真实想法是非常可怕的事情,

          文 / 张武(浙江正元智慧科技有限公司副总工程师兼开发部长)

而作为被管理者,不领会上司的真实意

几次专门的时间,找每个团队

只要不是因为对管理的不满离

图,也很难做到事半功倍的境界。作为软

成员面对面或通过网络沟通一

开团队的,这种离开就不是我们

件开发团队的领头人,我希望团队中既

段时间来的工作感受、生活状

的失败。

有“绵羊”也有“狮子”,不论是做具体

况、职业生涯打算等,以了解

的项目还是讨论如何展开项目,都希望

其思想动向。对于完成较好的

业比起来,由于文化背景不同,

团队成员都能够各抒己见,但一旦确定

工作给予充分的肯定,不足之

所以沟通时要格外注意一些。外

了行动的基本准则,每个团队成员就必

处给予真诚的提醒和引导,鼓

资企业可能更强调通过上下级

须按准则行动。蛮干的狮子是不受欢迎

励他们抓住机会去谋取更大的发展,哪

的服从关系来体现管理者的优越感,以

的,最终也将被逐出团队。

怕是需要离职才能达到。所以我们团队

及自认为卓越的管理才能和所谓的海外

在人才流动频繁的IT企业,特别是软

的成员在离开团队时,总会显得依依不

工作经历。国内的企业则更强调团队成

件开发团队中,由于生活背景、工作经

舍,甚至会主动跟我们探讨离职后发展

员彼此之间的情感依赖、团队凝聚力,更

历、思想观念等情况的不同,各种冲突的

的利弊和在别的团队中做事需要注意的

尊重每个团队成员的建议,更在乎“和为

存在是正常的。一年之中我们都会安排

地方。我对自己的管理成败有一个标准,

贵”的民族情结。

另外外资企业和国内的企

华,通过沟通达成共识,既保证执行力,

如何构建和谐的 IT 团队

也保护好团队成员可贵的创造性,实现
良性互动。作为团队成员,应该尊重团

文 / 周浩宇(现代卓越集团副总经理)

队领导的决策,提供建设性建议,争取
最佳结果。

毫无疑问,在竞争空前激

织有行之有效的评估团队

另外,对于一个成熟的研发团队,定

烈的今天,人才已经成为决定

成员性格、喜好、工作方式

期的技术与管理培训也是必要的。在关

各软件组织能否成功的关键要

评估的工具。

注了上述方面之后,我相信如果再面临

素,而由高素质人才所组成的

明确责任,重视配合:

沟通中的矛盾等问题,领导自然会冷静

团队能否高效配合也成为开发

因为可以持续改进,工作规

思考,积极沟通,将自己关注的方面、倾

项目成功的焦点。对于大多数

则和责任归属的具体细节

向的工作方式以恰当的沟通方式传达给

IT 组织的领导者来说,如何构

就显得不是那么的重要,关

团队成员;而团队成员也自然会在得到

建和谐高效的开发团队都是一

键在于对其达成共识,获得

尊重的前提下充分考虑领导的需求,提

个令人头疼的课题。根据这些年的经验,

认同,尽快从无法可依做到有法可依。

供建设性的建议。前一段时间发生的EMC

我认为应该着重考虑如下几个方面:

另外无论多么完美的流程方法,都无法

邮件门事件只是 IT 业界发展过程中的一

保障项目的成功 。只有团队通力配合,

个小小事件,希望它能给广大IT从业者带

队的基础,如果人选错了,管理得再

才能真正胜人一筹。要做到这一点,团

来一丝启发,不再仅仅站在自己的角度

好,很可能最终还是竹篮打水的结局。

队从上到下所有人员都应该注重考虑他

为自己的需求摇旗呐喊,而是更为关注

最佳的团队成员必须具有高超的专业

人的需求。

如何实现团队协作。只要把“沟通无极

选择合适的人员:这是建立和谐团

技能和职业素养,最好还能和团队领

互相尊重,讲究礼仪:无论工作关系

限”时刻摆在心中,你就最有可能实现自

导拥有相同的价值取向。虽然不同价

如何,大家都是平等的人。因此应该互

己的思路,在实现组织、团队需求的前提

值取向会加大差异性,但通常也会加

相尊重。团队领导应该尊重团队成员的

下顺理成章地最大化自己的利益。

大冲突和失败的可能性。这需要 IT 组

思路,尽可能吸取团队成员思路中的精

■  责 任 编 辑 :霍 泰 稳  (htw@csdn.net)

96

程序员

高效开发的

个技巧
□ 文 / 徐荣胜

 我从设计第一个商用软件

组织从制度上加以约束。对于还没有正

到今天已快八年,从事项目管理工作也

常融入团队的新聘人员,需要一个阶段

另外,设计之前的预先测试,不可能

已三年有余。回首这些年的从业经历,期

的考查期,由于代码中隐含着技术保密

面面俱到,还有开发人员本身的差异性

间不但尝尽了开发中苦乐甘甜的各种滋

及安全内容,所以不得不加以预防。

也很大,有些开发人员对某项技术很熟

味,在看待软件及评价软件工作者的观
念上也几经转变。记得刚入这行时,曾

境来尝试 。

悉,但有些开发人员可能很陌生。对于陌

未雨绸缪,学会技术探索

生的技术千万不要拿项目来边学习边测

是无比的崇拜求伯君、朱崇君等软件英

由于技术障碍而延误项目工期的先

试,这包括组件、数据结构、算法等。如

雄,而如今“软件英雄”一词却似乎已

例也不算少,其中既有对技术需求评估

果先前未经实践应用而只停留在理论认

抛至脑后,意识及言语中出现频率最高

的过于乐观,也有开发人员的麻痹心态

识的阶段,可以单独另外建立一个测试

的词汇却成了“软件团队”。为了软件团

或者冒险心理所引发的。比如当一个组

工程,专门对陌生技术进行模拟测试,等

队,可以说倾注了所有精力,许多同行

件升级后,未经测试而直接置入实际项

测通可行之后,再搬迁至实际工程(当然

肯定也身有感受。经过了在这一行的多

目中,可能是开发人员觉得凭着自己多

复制、引用都行)。如果直接在实际工程

年奋战,闲暇时想给自己的工作经历做

年的设计经验以及对此组件先前的认识,

中测试应用,或多或少的会留下无用代

个总结,同时也能给同行中的新手提供

坚信能够马上使用。孰不知有的升级并

码或破坏代码整洁性,因为在尝试的过

借鉴,于是把平时的点滴经验积累成篇

非只是停留在修正小错误的层面上,而

程中很少能顺利的一路过关斩将,势必

展现给大家。

可能对结构、接口、甚至实现机理也进行

会有频繁改动,有的改动甚至是漫无目

开放代码,提倡资源共享
在我所管理的每一个开发团队里,
都要求开发人员开放各自的开发成果,

刚入这行时,曾是无比的崇拜求伯君、朱崇君等软件英雄,而
如今“软件英雄”一词却似乎已抛至脑后,意识及言语中出现频
率最高的词汇却成了“软件团队”。

有用的源代码都需要集中存放在 CVS 代
码资源库中,所有的模块对开发人员全
部是开放式的。因为代码库是开发人员

修正。当然有如此大变化的不是很多,但

智慧的结晶,看看彼此间的代码,能提高

所谓不怕一万就怕万一,要保障项目的

整体开发水平,特别是对新来的职员,更

成功,不可疏忽任何小节。

是一个非常好的借鉴前人经验的过程。

的,难免会破坏原本写好的的部分代码。

每日整合,精确整体进度

一般的,在系统分析师作项目分析

每一个软件项目,一般都有好几个

更有价值也富有趣味性的是,通过开发

时,就应该安排部分开发人员对即将

开发人员,较大的项目还可能是好几个

人员之间交错的代码浏览,有时还犹如

应用的技术进行预先测试了,这既有

开发组一起参与设计。在这样的环境下,

白盒测试,代码浏览者会无意中发现代

对新技术的探究 ,也有对久未使用的老

多个人一起投入设计的时候,难免会出

码中隐藏的错误。

技术的热身。对决定着软件核心 、体系

现步调不一致,甚至某些成员在设计上

但面对目前越来越严峻的技术保密

架构等的测试更需要提前进行,在作

会背离整体要求的情况。为了减少某些

及安全问题,需要对相关的部门和团队

技术可行性研究时,应该模拟简单环

成员设计偏差所带来的损失,只有尽早

Programmer

97

管理&实践

Management & Practices

管理圈 >>>

代码易读,崇尚多用原则

把每个人的设计成果拿出来,整合构建

有相当数量的专业界面策划美工人员,

在一起。而且这个构建的过程是不断重复

十人以下的团队一般有一至两名界面设

在软件度量上,经常把代码行作为

的,整合的代码是不断累积的。即便上次

计师足够了,在分工上好多界面设计师

衡量软件规模的标准之一,正由此,有些

构建很成功,也难以保证当前的设计都很

同时也可以参与文档编辑和产品包装。

程序员经常以为自己写过的代码行数可

正常,为此就需要重复构建。每天下班前

“视觉冻结”一词引自马魁尔的《微

以作为资历或能力的证明。其实不然,软

构建一次,是比较常见的做法。下班前每

软研发致胜策略 》,意思是说在开发后

件是由众多代码通过一定的逻辑堆积而

个人的工作都有一个小段落了,不会引起

期,界面就固定不动了。这样做能使手册

成的,而非机械可见物的形体堆积,量大

写了一半的算法,为整合编译过去的程序

文档可以定稿,以便手册也能尽快与客

并不代表功大。

而不得不注释掉正常的一段代码。

户见面。在开发后期这样做的确很有必

我经常在程序设计小组会上强

或许有人认为,频繁整合会浪费很

要,否则也容易引起文档编辑人员和开

调 代 码 要 以“易 读、易用、多用 ”为

多时间。其实不然,虽然每天得花上半个

发人员的内部矛盾,如果有必须进行的

原则 。

小时左右的时间整合,一星期累积也就

界面更改,开发人员应该及时与文档编

两三个小时。如果你的小组在一星期之

辑人员沟通。

内只整合一次,唯一的一次整合未必能

易读这一点很好理解,学过程序语
言的人都明白,不过易读强调的是能让
人家容易读懂你的程序,所以在一个团

在半天之内成功。更为严重的是,如果

重视重构,但不可过频

队里一般都要求一致的代码风格,包括

有一个开发人员的设计偏离了方向,不

重构就是在不改变外在行为的前提

注释、命名、空格等,有时还考虑代码整

仅是浪费他自己一星期的时间,可能会

下,对程序的内部结构做出调整、修改,

导致其他人的工作无法继续,只得先等

以改善性能、减少隐含的错误。成功的重

易用,一般指一些公共的函数库,能

他纠正。

构,花很小的代价,就能给软件注入新的

够很方便地供他人调用。其中涉及到的

生机,从而延长软件的生命周期。

有,参数的初始化,对象的创建、释放,

从项目进度的角度来看,
也只有经完

洁美观。

全整合的半成品软件才能充分地体现整

重构的好处显而易见,能使老牛变快

体进度。否则无法把握每个人所写的部

车,能让软件更加稳定。也正因为,好多

多用,一方面指执行概率,比如一个

分代码是否真正满足项目的需求,更无

程序员都沉迷于重构,今天写明天构,频

公共的函数被别人调用次数越多,说明

从真正知道能否和其他人无缝结合。所

率过高,最终延误进度。我理解每一位程

这个函数的价值越大;另一方面指生命

以,如果认为每个人完成了90%的工作,

序员对代码的成就感,也理解一个善于创

周期,比如一个软件经过无数次的重构

整体完成量就是90%,那是绝对的错误,

新的程序员,每当回头看原来写的程序

或者升级,其中的一段代码还是被原样

真正的结果或许只有50%,或者更少。

时,总会发现许多不足。
(这个不足并非说

保留(当然觉得好才保留),说明这段代

原先分析不到位、设计没规划好,而是等

码的价值就大。

关注界面,适时视觉冻结
开发人员往往沉迷于代码质量以及

有了一定的经验积累,或通过其它途径学

函数的健壮性等。

所以,多用才是重点 ,其最能体现

到新知识之后,会觉得原来做的不够好。)

代码的价值,也是评价程序员优劣的

程序功能,不注重界面的友好,包括界面

但是重构是需要有计划的,一般而言普通

标准。

布局的杂乱、表现不直观、提示信息的不

的项目计划里是不含有重构日程安排的,

完全、有歧义或过于专业,以及操作繁琐

除非是纯粹的重构项目计划。

等。好多软件原本内核功能做的不错,却

当然,不让原始设计和重构并行,也

作者简介
徐荣胜,宁波一号网络科技有限公

因操作界面不友善而失败,或者重新返

并不是生搬硬套的,比如在项目开发中,

司总经理,多年来一直从事企业及

工。Windows的成功也得益于界面友好,

如果某个常用函数不加以重构,调用的

财务信息化、政务电子化的研发管

能让一个没接触过电脑的人很容易学会

地方速度明显过慢,就该考虑及时采取

理。对新型软件工程思想以及软件

上网。我们做的软件何不考虑让客户也

动作了。一般的,不是为迫切解决错误,

过程改进有较深刻的认识,长期致

能快速的学会使用呢?开发人员要学会

而对其它地方影响面又较少的代码,如

立于培养软件团队、改进软件工程

换位思考,设计的时候,多想想开发的软

果项目时间不宽余就不应该重构(或者

文化的研究和管理, 曾在专业技术

件是给谁用的,要站在使用者的角度来

更确切地说是设计与重构并行),应以进

看待这个软件。有条件的项目团队中,要

度里程计划为重。

98

程序员

期刊发表论文数篇。
■  责 任 编 辑 :霍 泰 稳  (htw@csdn.net)

>>> SUN 征文

特性并把这个构件放到一个特定的地方,

(4)BoxLayout2 布局管理器:它是

持以上2款IDE的全部功能;4种编译器及各

这个构件就不仅仅会收到一个位置协调的

Swing 标准包中javax.swing.BoxLayout 布

自特有的编译选项:Borland Make、Borland

消息,并且会记住为什么它会被抓取。例

局管理器的一个包裹类,允许你通过查

Make(JB8)
、Project javac、javac;智能单步、

如,如果它被抓取同另外一个构件的左边

看器的选择,间接使用BoxLayout的功能。

智能源码、智能交换;多线程调试;内置混

对齐,这个时候该构件会始终保持它们的

BoxLayout 将几个组件组合在一起,以水

淆打包;JBuilder的调试环境可谓傲视群伦,

左对齐格式,即使它们的绝对位置发生了

平或者垂直的方式排列,窗口大小调整

开发纯java 程序时,使用起来十分方便。

改变。

时,组件大小不会随着改变。

NetBeans中有双路编辑——使用一个可

(5)OverLayOut2 布局管理器:它是

视化设计器和一个文本编辑器。一些可视化

Swing 标准包中 java.swing.OverLayout 布

设计器已经实现了这种方式。但是NetBeans

局管理的包裹类,允许你通过察看器的

IDE使用保护模块来防止用户编辑代码。

选择,间接使用 OverLayout 的功能。

三.WEB 与 J2EE 开发
JSP、Servlet
NetBeans支持Servlet 2.4和JSP 2.0。
支持使用 Tomcat 5 部署和调试两层 J2EE

Eclipse的 Visual Editor

GUI 小结

1.4 和 1.3 应用程序。以下是 NetBeans 为

Visual Editor是一个开源的 Eclipse 编

GUI设计部分,我更喜欢NetBeans,相

Web应用程序开发提供的便利:内置Tomcat

辑器。它同 JDT、PDE 等其它 Eclipse 的工

信很多用户也跟我一样,因为用起来真

服务器支持;生成和维护部署容易的内

具项目一样,是一个全新的Eclipse工具项

的很方便。

容,包括添加到项目中的 Servlets进行注

目。它可以进行可视化的编辑Java GUI程

曾看见有人说,在拖拽组件时,却不

序,也能编辑可视化的Java Bean组件。它

能更改代码,觉得很别扭。其实我觉得受

打包、部署指令的Ant 脚本。该脚本使开

能与 Eclipse的Java Editor集成在一起,当

保护的双路编辑才是应该推崇的方法,

发者无需手动将文件移动到服务器;用

在 Visual Editor中编辑图形界面时,会立

这也是对 IDE完美工作的一种保证。

于编辑 Servlets、JSP、HTML 和标签库的

即反馈到 Java Editor中的代码,反之亦
然,即无保护的双路编辑。
Visual Editor支持Swing 和AWT的可视

册;生成与维护具有编译、清除、测试、

代码自动完成和帮助;提供“编译JSP”命

二.编译、运行、调试、打包
本节将比较三个平台在编译、运行、

令,使用这一命令可以帮助开发者在部
署前检测JSP 文件的错误,不管这些错误

Java组件开发。由于这个Framework设计的

调试、打包几个必要开发步骤中的具体

出现在编译过程中还是 J S P 文件向

具有通用性,它也可以很容易的实现C++

表现。

Servlets 转换过程中;提供全面的调试支

或其它语言下可视化开发。其将来的版本
(从 1.0 开始),将会支持SWT的开发。

NetBeans
在代码行开头点击即可设置 / 取消

持,包括“步进JSP 文件”以及“跟踪HTTP
请求”;大量的 Web 模板:JSP、Servlet、

Visual Editor目前支持所有的传统的

断点;支持条件断点、单步执行等流程控

Filter、Web应用侦听器、标签库描述、标

布局管理器。另外,SWT Designer也是流

制功能;支持局部变量、监视、堆栈显示等

签、标签处理、Web Service、消息处理、

行的 GUI 编辑器,不过是收费的。

功能;支持会话、线程的查看及修改;提

Web客户端等;描述文件web.xml可视化

JBuilder 的布局管理器

供了完善的远程调试功能;基于Ant,可

编辑器;监测 HTTP 事务处理。

除了经典的布局管理器外,JBuilder

通过脚本支持调试。

提供了五个方便的布局管理器,它们是:
(1)XYLayout 布局管理器:组件所在

E c l i p s e 在不安装 L O M B O Z 或者
MyEclipse 的情况下编写 Web 应用程序真

Eclipse

是麻烦之极。首先你需要手动安装Tomcat

的位置通过相对于左上角坐标确定,其大

带有专用的 D e b u g 视图并能自动切

或者其他服务器,然后在Eclipse 中配置;

小通过宽度和长度确定,当窗口大小发生

换;其Debug 的功能和Delphi 的Debug比较

接下来编写代码,再更改web.xml文件做

变化时,组件的位置和大小保持原位。

相似,Inspect 、Watch等应有尽有;支持反

部署。最后很可能因为配置不好的原因,

(2)PaneLayout 布局管理器:通过百

汇编、内存、堆栈、寄存器显示等高级功

无法启动或者部署Web服务器。好在对web

分比规定组件所占容器空间,当用户界

能;支持会话、线程的查看及修改;似乎

.xml编辑时也是可视化的。

面调整时,组件的大小也会相应调整。

无远程调试;可根据模块的需求扩展。

(3)VerticalFlowLayout 布局管理器:
它和FlowLayout 类似,只不过它以垂直而
非水平的方式排列组件。

JBuilder一体化的解决办法倒是很好,
并且通过 OpenTools 框架支持很多种Web

JBuilder
高度集成,十分丰富的调试环境,支

服务器。当然也需要手动安装这些服务
器,并且添加这些服务器的 Lib到你的项

Programmer

123

Product & Application

产品&应用
SUN 征文 >>>

目中。JBuilder还为各种部署文件提供了

应用服务;能够利用强大的Java调试器调

方便的编辑工具:

混淆的级别越高,混淆的力度就越大。

试正在运行的服务器端代码(JSP&EJB)

Mobility Pack提供了可视化用户界面

l web.xml:Web Module DD Editor

通过使用 Wizard 和代码生成器提高开发

设计器,开发者可以用鼠标拖拽的方式

l struts-config.xml:Struts Config Editor

效率;创建Web服务客户端的WSDL形式

设计应用程序的用户界面,通过流程控

l faces-config.xml:Faces Config Editor

的文件。

制器实现界面之间的跳转,而不用编写

另外JBuilder也对Jsp和Servlet提供监
听器,监视各种事件的发生。
JBuilder 提供了最为完善的Web 开发
环境,其次 Netbeans 功能也十分丰富。

L o m b o z 适用的服务器有:Apache

任何代码。无线连接向导是Mobility Pack

Tomcat,JBOSS,JOnAS,Resin,Orion,JRun,

另一新特性,能方便快速的开发出端到

Oracle IAS,BEA WebLogic Server和 IBM

端的企业级应用程序,服务器端只提供

WebSphere 等。

需要导出的服务类,Netbeans IDE会自动
生成服务器端的 Servlet 以及客户端用于

EJB/J2EE

三种平台对框架的支持比较

连接网络的代码。虽然上述两个功能使

NetBeans
从 N e t B e a n s   I D E   4 . 1 版本开始 ,
NetBeans 提供创建和编辑 EJB 丰富的向导

框架名称

NetBeans 5.5

Eclipse 3.x

JBuilder 2005

Struts
Hibernate

支持,向导,文档丰富
Nbxdoclet 支 持 , 5.5 加
入数据库结构和实体类

MyEclipse 良 好 支 持
Hibernate Syn 支 持

支持,向导,文档丰富
手动配置

和编辑器。
NetBeans 5.0提供以下针对企业开发
的支持:建立和编辑EJB的可视化编辑器;
控制 CMP 和实体 Bean 关系的可视化编辑

Spring

的相互生成和向导
支持,向导,文档丰富

Spring plugin 4 Eclipse

手动配置
Spring for JBuilder2005 OpenTools

Cocoon
JSF

暂没找到直接支持
支持,向导,文档丰富

Lepido 支 持
JSF Tool Project 支 持

支持,向导,文档丰富
支持,向导,文档丰富

器;通过鼠标点击就可以在Web模块中加

用起来非常方便,但是缺乏灵活性,你很

小 结

入对 EJB 的调用;完整的组装、部署、运
行和调试企业应用程序的支持;注册和

对于J2EE 开发,Eclipse 的各种支持是

测试Web Service;通过鼠标点击就可以在

对全面和及时的,但是否成熟,则未必。并

Web模块或EJB中加入对Web Service的调

且开发者经常被成堆的插件弄得头昏脑胀。

难再更改开发工具为你自动生成的代码。

Eclipse 和 EclipseME
不仅要下载安装 EclipseME插件,还

用;由EJB或者Java类自底向上的建立Web

NetBeans的最新版本提供了对最新标

要安装 WTK,并且在 Eclipse环境中配置。

Service;由WSDL文件自顶向下的建立Web

准,如EJB 3.0 的支持,并且内置对常见

使用 E c l i p s e 搭建 J 2 M E 的开发环境比

Service;可以导入其他 IDE的J2EE项目,前

框架支持。这说明,现在完全能够全面转

Netbeans IDE 稍显复杂。事实上,管理

提是其与 BluePrints标准兼容。

向 NetBeans。

Eclipse 的各种插件已经让开发者头疼不
已,有些插件的更新还很难保证。

Eclipse与 Lomboz
Lomboz 是Eclipse 的一个主要的开源插
件(open-source plug-in),Lomboz 插件能

四.J2ME 开发
NetBeans Mobility

JBuilder 和 WTK

Netbeans IDE和 Mobility Pack 提供的

从JBuilder 9版本开始,Borland将WTK

够使Java开发者更好的使用Eclipse去创建,

项目管理功能非常出色,将目标平台、应

直接集成到了开发工具内。如果使用以

调试和部署基于J2EE的 Java应用服务器。

用程序描述符、编译运行、混淆、签名等

前版本的 J B u i l d e r,那么需要首先安装

Lomboz 的主要功能有:使用 HTML,

功能集成在了一起。开发者只需要选中

MoblieSet 插件。

Servlets,JSP 等方式建立 Web 应用程序;

项目,右键选择属性即可配置上述选项。

J S P 的编辑带有高亮显示和编码助手、

值得注意的一点是,当项目中使用了图

JSP 语法检查;利用Wizard创建Web应用、

片或者媒体文件等资源的时候,应该在

其实,各种开发工具只是以自己的

EJB 应用和 EJB 客户端测试程序;支持部

“库和资源”选项中讲资源文件所在的文

方式对 M I D P 应用程序的开发进行了封

署 EAR、WAR和 JAR;利用xDoclet 开发符

件夹添加到“捆绑的库和资源”中。避免

装, MIDP应用程序的开发流程都是一样。

合 EJB 1.1、2.0和 3.0的应用;能够实现

在 Java 程序中访问资源的时候抛出空指

事实已经证明,除了使用手机供应商自

端口对端口的本地和远程的测试应用服

针异常。Mobility Pack 还直接集成了

己的套件外(如 Nokia Toolkit),WTK 和

务;能够支持所有的有可扩展定义的Java

Proguard 混淆器,可以设置混淆的级别,

NetBeans Mobility的用户最多——这方面

124 程序员

小 结

Product & Application

产品&应用
工具点评  >>>

增的图形共有:Class Diagram、Composite
Structure Diagram、Component Diagram、

高手过招,各有千秋

Deployment Diagram、Use Case Diagram、
Activity Diagram、State Machine Diagram、
Sequence Diagram 以及 Communication
Diagram 等九张图。比较起 UML 2.0的规

—— UML 工具比较分析

格所制订的十三张图,分别少了 Object
Diagram、Package Diagram 、Interaction
Overview Diagram 以及 Timing Diagram 四

□ 文 /Ringle

张图。
不过如果我们详细观察 UML 2.0 的

“工欲善其事,必先利其
器”,学习UML没有好的工具帮忙,往往

对!不要怀疑,这三个产品的价格
的差距大约是 20 倍。

gram 与Package Diagram的基本Diagram其
实就是 Class Diagram,只是在这两张图

会让开发者半途而废,甚至会因为不易
使用的开发工具,而误认为 UML是一个

规则,我们就可以发现,其实Object Dia-

对 UML 2.0 的支持分析

中,其分别表达了 Package间的相依关系

非常困难学习的“技术”。殊不知UML只

图 1 是 OMG 所定义的 UML 十三张图

是一种“语言”,就和学习中文、英语一

的分类(参考自Unified Modeling Language:

我们可以使用 Class Diagram 来绘制这两

样,学习 UML并不困难,只要了解UML

Superstructure, Version 2, p. 660)。

张图形。

的语法以及知道 UML 的适用时机,UML
自然手到擒来。当然,如果有一套容易
上手的 UML 开发工具,学习 UML的困难
度更是大幅降低。
在本文中,我们将评比三个不同的

以下,我们将针对上述的三个软件,
分别说明其对于UML 2.0 规范的支持。

以及Object 之间的关系。因此,在RSA中,

至于 Interaction Overview Diagram 也
是类似的状况,在UML 2.0的规则中,其

IBM 的RSA:与Borland Together都是

基本的图形是Activity Diagram,因此,我

建构在Eclipse平台上,必须要先建立一个

们同样也可以利用 Activity Diagram 来绘

UML 2.0 的项目,才能绘制 UML 的图形。

制 Interaction Overview Diagram。至于时

UML工具——IBM公司的Rational Software

序图,虽然在 RSA 中的 Communication

Architect(以下简称 RSA)、Borland 公司的

Diagram 可以表达时序图中的LifeLine,但

Together Architect(以下简称Together)以及

是其余的相关的 UML 组件都缺乏,因此,

Sparx Systems 公司的 Enterprise Architect

RSA 并无法完整表达时序图。

Corporation Edition(以下简称EA)。评比的

因此要在 RSA 中绘制完整的十三张
UML 2.0规范图,还是比较困难的,开发

标准会从以下两个面向来分别评估:

人员必须要很清楚地知道这十三张图各

l 对 UML 2.0 的支持;
l 文件产生机制

图 2:RSA 的 UML 2.0 项 目 操 作 画 面

整篇文章中,我们会分成两大部分,
针对这三套软件在上述两方面的操作进

和 Eclipse 的操

行说明,并且在每一个部分的最后,都会

作相类似,在RSA的

用表格对三个软件进行综合评比。开始

操作画面中,左边是

介绍之前,先就价钱做个评比说明,根据

项目区,右边则是所

三家公司的产品标准售价,其价格的比

有可以使用的工具

较表如表 1:

区。在RSA中可以新
表 1: 三 套 软 件 的 价 格 表

公司

产品

IBM
Rational Software Architect
Borland
Together for Eclipse Architect Edition
Sparx Systems Enterprise Architect Corporate Edition

126 程序员

价 格 (美 元 )
5500
5000
239

图 1:UML 2.0 规 范 的

>>> 工具点评

自特性,才能找到适当的图形进行绘制。

则无法绘制。

大的不同。因为它本身是一个独立的程

在 R S A 中,开发人员可以轻松地将

大体上,Borland Together在UML 2.0

序,其操作方式不会受到其他影响。在整

Sequence Diagram 转成 Communication

的支持上主要是缺少了上述的两张图;

个开发环境中,右方是工具区,左方则是

Diagram,反之亦然。延续了之前Rose的特

实际的操作上,Borland Together延续了以

整个 P r o j e c t 相关的各种不同的界面

性,可以说是RSA中最让人赞赏的部分。

往 Together 的操作方式,对 Together 的老

(View)。所有的 U M L 图形将会放置在

用户来说,不会有太大的困扰。

Project View 中。和Together类似的,当指

最后是 MDA 的机制,在 RSA 中提供
三种转换机制,分别是UML →Java、UML

此外,Together在Sequence Diagram与

定到一个特定 Type的Diagram 时,左方的

→ C++、UML → EJB,由于 RSA是建置在

Communication Diagram的互转上,提供一

Toolbox 会停留在该 Diagram 对应的 Pallet

Eclipse 上,因此,其转换为Java或EJB时,

个很有趣的机制,你可以根据一张相同

上,这在操作上是非常方便的。

能够非常顺畅地跟Eclipse的Java或是J2EE

的Interaction Diagram,指定利用“Sequence

项目结合,这也是 RSA 一向的强项。

Diagram”或“Communication Diagram”来
表现,这个想法非常有趣,也说明了这两

Borland 的 Together:跟 RSA相同,

张图是同一个事物的不同形式。

在 Borland Together 中要新增 UML 2.0 的

至于根据 UML 产生 Source Code,则

Diagram,也必须要在 Eclipse 的环境中新

必须要采用不同的项目。如果要产生Java

增一个 UML 2.0 的项目。

的代码,必须选用“Java Modeling”项目,
当你在该项目中建立Class时,Together都
图 4:EA 的 操 作 画 面

会自动产生一个Java Class,当该Class的
属性或是操作有所变动时,会立刻反映
到程序中。这和TogetherJ是完全相同的。

图 3:Borland Together 的 操 作 画 面

图 4 中央对话框为 EA 支持的 U M L
2.0 的Diagram 。除了RSA 及Together 支

此外,T o g e t h e r 仍然保有过去

持的九张 Diagram 外,EA 也支持其余四

TogetherJ 的重要功能,也就是可以利用

张 D i a g r a m ;另外,还支持非标准的

Sequence Diagram 产生 Implement 的代码,

Analysis Diagram 。因此,若单从对UML

相同地,也可以由代码反转回 Sequence

2.0 的 支 持 来 说 ,E A 算 是 最 完 整 的

Diagram。这算是Together 的一大特点,也

工具。

是它与其它两个产品竞争的最大优势。
跟RSA不同,Borland Together操作界

对Sequence Diagram与Communication
Diagram 的转换,EA 没有提供任何功能,

面与先前的版本类似。针对每一张不同

Sparx Systems 的 E A 是这三个软

这算是 EA中比较弱的一环。对于MDA的

类型的UML Diagram,可以使用的工具都

件中最轻薄的。采用了Stand Alone的AP,

支持。EA 做得非常弹性,开发者可以利

不同,如图3右方的“Pallets”绘图模版。

安装时不需要先安装 JRE 及Eclipse。在其

用Script语法自行定义Transformation Rule。

另外跟 RSA 类似的是在 Borland Together

中绘制UML Diagram也相对简单。只要在

在 EA 中提供 C#、EJB、Java、DDL、XSD

中,同样地也只支持 UML 2.0 中的九张

EA 中新增一个项目,其自然就会把所有

以及 Web Service 等标准的转换机制,开

图( 如图 3 左红色方框部分) ,P a c k a g e

UML Diagram 要绘制的相关环境准备好。

发者可以将同一个 PIM的Model转换为各

Diagram、Object Diagram、Interaction Over-

EA 的操作和前面的两个软件有相当

种不同平台的 PSM Model。

view Diagram 以及 Timing Diagram都不能
表 2:对 UML 2.0 的 支 持 分 析

直接由 Borland Together 中选取。
如前文所说,Package Diagram 以及

项目

RSA

对 UML 2.0 十 三 张 Diagram 的 支 持

不 支 持 Timing Diagram 不 支 持 T i m i n g
Diagram、Interaction

Sequence Diagram与 Communication
Diagram 的 互 转 机 制
MDA 机 制

提供

Overview  Diagram
提供

不提供


两种


两种


九种
没有

Object Diagram 都可以使用 Class Diagram
来绘制,相同地,在Borland Together中你
也可以利用 Class Diagram 来绘制这两张
图。至于 Interaction Overview Diagram 以
及 Timing Diagram,在 Borland Together中

支持的程序语言
Sequence Diagram转 换 为 程 序 代 码
对 于 IDE 接 口 的 整 合 度

Together

EA
支持十三张
Diagram

Programmer

127

>>> Java

Apache Shale 是 Struts framework 系列中的最新产品,它通过
JavaServer Faces 可以进行组件化的表示层开发。我们首先从 Shale 的对
话管理器、验证和 JNDI 服务开始。

Apache Shale 引领
JavaServer Faces 再上新台阶
□ 张钢  涂耀旭
 在 Struts 时代,Struts 是 MVC2 框架。凭借其设计

u AJAX:AJAX 所支持的服务器端服务

的优雅性、简单性和健壮性,使得Java开发人员中的一大部分

u Spring、Tiles 与 Clay 框架整合及可重用的视图

都热衷于用 Struts 进行表示层开发。但是,从构思产生Struts到

u 测试:基于 JUnit 测试所使用的 Mock 对象和基类

现在已经 5 年了,它已经开始出现衰老的征兆。其所沿用的统
一的请求处理引擎,使得它难于定制和扩展,而JSF则建立在灵

开始下载 Shale

活、可变的事件处理引擎的基础上。其次,Struts 未能像 AJAX

简单提一下Shale下载是因为它还处于测试阶段。您需要使

那样增加对声明性工作流、
一致性验证框架或新兴技术的支持,

用来自http://cvs.apache.org/builds/struts/nightly/struts-shale/

这已经导致 Struts在新的开发项目上沦为逐渐没落的角色。

的 nightly builds(令人激动的东西!)。

不管怎样,在 JSF发展壮大的时候,Struts开发团队是不会
袖手旁观的。由业界精英组成的Struts团队重新打造自己,并开
始创建可以补充和丰富JSF的服务,而不是试图直接与之竞争。
他们想将一件美好的事情(JSF)做得更好。
开发成果就是 Apache Shale,一个构建在JSF优势之上的框

下载以下四个文件,在它们的名字中含有最近的日期(这
些文件的名字将根据您下载它们时的日期而改变):
u shale-framework-YYYYMMDD.{tar.gz,zip}——包含核心

Shale 框架的二进制和源代码;
u shale-starter-YYYYMMDD.{tar.gz,zip}——包含基于Shale

架。(我不知道这个团队为什么选择 Shale 这个名字,Merriam-

的应用程序和Apache Ant作为构建工具而使用的模板目录结构;

Webster 将其定义为某种易分裂的岩石。)Shale提供的组件化服

u shale-blank-YYYYMMDD.war——包含Shale Web应用程

务使您可以根据需要而有选择地使用。这些服务各种各样,从
简单的带有一些额外函数的支持bean(Shale的视图控制器),到
完整的 Web 页面导航引擎(Shale 的对话管理器)。
Shale为JSF带来了很多特性,这不是一篇文章所能说完的,

序示例,显示当前的日期和时间;
u shale-dependencies-YYYYMMDD.zip——包含基于Shale的

应用程序所需要的支持 JAR 库。
以下是在 2006 年 3 月 8 日当天最新的 Shale 下载:

因此本文只关注于 Shale的对话管理器、验证、Java命名和目录
接口(JNDI)服务。这些服务将能让您很好地理解Apache Shale的
多样性、简单性、灵活性及其能力。
访问 Shale 的特性页获得以下 Shale 服务的全部说明:
u 视图控制器:带有预定义事件的 JSP 支持 bean

shale-framework-20060308.zip
shale-starter-20060308.zip
shale-blank-20060308.war
shale-dependencies-20060308.zip

接下来我们为假想的 Shale Launch Party来创建一个Web注

u 验证:客户端和服务器端验证

册应用程序,其中使用了Shale的对话管理器、JNDI和验证服务。

u JNDI:JSP 对 web.xml 中属性的访问

立即下载这个示例应用程序。

u 对话管理器:由XML 配置文件驱动的Web向导(工作流)
u 应用程序管理器:一个用来拦截所有HTTP请求的应用级

控制器

解压缩下载文件。这会创建一个“launch-party”文件夹,
其中包含有“lib”和“src”文件夹,以及 Apache Ant构建文
件。“src”文件夹包含项目所使用的 Java和 JSP 源文件;“lib”

Programmer

99

技术

Technology

Java >>>

文件夹是空的。Build.xml 和 default.properties 可以在 launch-

支付和设置电子邮件和平信首选项。图 1显示了这个应用程序

party 文件夹下找到,是Apache Ant构建文件。Build.xml有不

的 UML 状态图。

同的Ant 构建任务,用于清空和创建目录 、将文件复制到构建

应用程序有两个向导:
“Create New Registration”和“Process

文件夹、编译和创建 war 文件、部署到 Tomcat 等。我特别喜

Payment”。
“Create New Registration”主要用于收集和处理注册

欢“dist”任务,它与其他多数文件一样,也用于创建可部署

信息,而“Process Payment”只接受付款。“Process Payment”

的 war 文件。

自身独立,您可能会从其他包含“Create New Registration”的

在开始执行这些 Ant 任务前,您需要完成以下两个步骤:

向导中使用它。这里的巧妙之处就是“Process Payment”,虽然

1、将 launch-party\default.properties 中“shale.dir”的值更

它处理“Create New Registration”的大部分内容,但是只要不

改为 Shale 安装目录。

破坏它们所共享的过渡值,它们可以各自不受限制地修改。在

2、将 shale-dependencies-YYYYMMDD.zip 解压缩文件复制
到 launch-party\lib 文件夹。
在您要更进一步时,请确保满足“软件要求”框中的先决
条件。一旦设置完成,您就要准备开始 Apache Shale Services。

本例中,
“Process Payment”被设计为提供只使用信用卡的支付
方法。然而,您可以更改它来提供其他支付形式(支票、PayPal、
易货等)而不需要更改“Create New Registration”。这就是我们
都喜欢的关注点分离。
回头看图 1的 UML 图,在Create New Registration和Process

软件要求
u Apache Ant 1.6.5
u Apache Tomcat 5.5.15
u Apache Shale
u Java Standard Edition JDK 1.4 或更高版本
u Java Standard Edition JRE 1.4 或更高版本
u 如果您想要使用最新版本,JDK和 JRE 1.6-beta也可以

Payment 过程中用户历经下列活动:
1.Create New Registration
l 用户 ID:用户提供电子邮件地址(这就是用户 ID)

密码、全名和电话号码;
l 注册:系统使用上面提供的信息注册该用户;
l

电子邮件首选项:用户设置电子邮件首选项并可以

选择使用“Process Payment”向导支付;
l 平信首选项:用户设置平信首选项;

用对话管理器创建向导
Apache Shale 通过它的对话管理器为创建基于 Web 的向导
助一臂之力。对话管理器分两个部分:
1.dialog-config.xml配置文件,指定不同页面和Java类如何
基于其过渡值连接在一起。
2.在 JSP 或 Java函数调用中由 JSF Command UI 控件(JSF
的<h:button/>和<h:link/>的操作值)返回的值。
为了学习如何使用对话管理器,我们来探讨 Launch Party
Registration应用程序。这个应用程序是一个典型的“previous-
next”向导,一步步指示用户完成注册过程。用户注册、可选

l 保存首选项:最后,系统保存所有首选项并退出应

用程序。
2.Process Payment
l 信用卡:用户提供信用卡信息;
l 处理信用卡:系统处理上面提供的信息;
l 致谢:不用多说了!

清单1显示了示例应用程序使用的dialog-config.xml文件。
如果您将其与图 1 并排比较,您会注意到两者之间接近平行。
...
<dialogs>
<!—  New Registration Dialog — >
    <dialog name="Create New Registration" start="User ID">
    <transition outcome="start" target="User ID"/>
     <transition outcome="exit" target="Exit"/>
<!—  User Name — >
  <view name="User ID" viewId="/userid.jsp">
    <transition outcome="next" target="Register"/>
  </view>
<action name="Register" method=
                 "#{registrationBean.createNewRegistration}">
        <transition outcome="success" target=
         "Email Preferences"/>
      </action>

图 1:Launch Party Application 状 态 图

100 程序员

    <view name="Email Preferences" viewId=
        "/emailPreferences.jsp">
      <transition outcome="next" target="Snail Preferences"/>

>>> Java
       <transition outcome="payNow" target="Payment"/>
    </view>
     <subdialog name="Payment"  dialogName="Process Payment">
      <transition  outcome="next" target=
        "Email Preferences"/>
       <transition  outcome="cancel" target="Email Preferences"/>
    </subdialog>
    <view name="Snail Preferences" viewId=
        "/snailPreferences.jsp">
      <transition outcome="previous" target=
       "Email Preferences"/>
      <transition outcome="finish" target=
       "Save Preferences"/>
    </view>
    <action name="Save Preferences" method=
     "#{preferencesBean.save}">
      <transition  outcome="success" target="Exit"/>
    </action>
    <end name="Exit" viewId="/goodBye.jsp"/>
  </dialog>
<!—  Take Payment Dialog — >
  <dialog name="Process Payment" start="Credit Card">
...
  </dialog>

...
  <h:commandButton id="next" action="next" value="Next >>"/>
  <h:commandButton id="exit" action="exit"
    immediate="true" value="Exit"/>
</h:form>
...

清单3. userid.jsp显示了带有Action属性的commandButton
Action在您需要调用Java对象的函数时被使用。Action Java
类可以是 POJO 或 ViewController (另一个 Shale特性)。就像JSP
中的 CommandUI,这些Java函数也需要返回一个String 值。清单
4 显示了 POJO RegistrationBean 返回的 String“success”:
...
public class RegistrationBean

    ...
    public String createNewRegistration()
    {
        return "success";
    }
...

清单 4. 显示 createNewRegistration函数返回值的
</dialogs>

RegistrationBean java类
清单 1. dialog-config.xml

View 和 Action实质上都返回 String 结果。这些 String 值被

dialog-config.xml 文件使用<dialog>节点“Create New

Apache Shale对话管理器的Transition结构使用。Transition将View

Registration”和“Process Payment”表示向导。这些<dialog>节

和 Action返回值映射到下一个目标View 或 Action。可以在对话

点的任何一个都包含视图(如用户 ID)、操作(如注册)、过渡

级或局部状态级(View或Action)定义Transition。当Transition不

和每个对话的终端节点。

能匹配从 View 或 Action到局部 Transition的 String 结果时,Shale

您可以在操作中提示对话框,通过让命令按钮返回dialog:

引擎将使用对话级 Transition。清单 5 显示 userid.jsp 返回的next

XXXX,这里的XXXX 是在dialog-config.xml文件中定义的对话

和exit 的值是如何通过User ID的局部过渡和对话的全局过渡进

框名称。“Create New Registration”对话框在用户单击start.jsp

行映射的。“Next”是在View 级上进行局部映射,而“Exit”是

(如下面清单 2 中所示)中的 commandButton时启动。注意这个

在对话框级上进行映射的:

对话的名称是”dialog:Create New Registration”:
...
<h:commandButton id="startNewRegistration" action="dialog:Create
New Registration"  value="Start New Registration>>"/>
...

清单 2. start.jsp 中 dialog:Create New Registration的 Action值
让我们来检查<dialog>的每一个组成部分,即<view> 、
<action>、<transition>和<end>结构。当您请求通过表示技术
(为了简便,假定JSP 就是表示技术)指引用户交互时,将使用
视图。这些JSP 都是支持JSF的,这意味着它们使用HTML和Core
JSF 标签库。通过 Apache Shale引擎的 Command UI控件(JSF的

...
<dialog name="Create New Registration" start="User ID">
   ...
     <transition outcome="exit" target="Exit"/>
    <!—  User Name — >
     <view name="User ID" viewId="/userid.jsp">
       <transition outcome="next" target="Register"/>
     </view>
     <action name="Register" method=
        "#{registrationBean.createNewRegistration}">
       <transition outcome="success" target=
        "Email Preferences"/>
     </action>
...

<h:button/>和<h:link/>的action属性),它们会将String值返回
给 Apache Shale 引擎。清单 3 显示 userid.jsp 中操作值为 next 和

清单 5. userid.jsp 返回的“Next”和“Exit”值的Transition

exit 的两个按钮:

终端节点指示对话结束。当遇到END 时,对话管理器的内
部引擎知道弹出对话框。Shale建议通过这个来理解对话管理器

...
<h:form id="userid" onsubmit="return validateForm(this);">

本身。

Programmer

101

技术

Technology

Java >>>

如果不讨论自成体系的subDialogs,关于对话管理器的任何
讨论都不会完整,示例应用程序中完成这一任务的是“Process
Payment”对话。在注册过程中,用户可以选择是否付款(这并
不 是 我 们 所 有 人 都 希 望 的 )。当 用 户 明 确 选 择 这 样 做 时 ,
“Process Payment”开始起作用。
清单 6 显示这一切是如何协同工作的。

调用“Process Payment”对话时,subDialog处理“Process Payment”
返回的结果。
对话管理器的所有特性都存在对话域状态信息。示例应用
程序在emailPreferences.jsp中使用这一特性,这里值被保存在由
对话管理器管理的“#{dialog.data.receiveEmail}”和“#{dialog.
data.alternateEmail}”属性中,一旦用户处于对话之外,这些值
将会在域中消失。

...
<dialogs>

保持用户经过验证

<!—  New Registration Dialog — >
  <dialog name="Create New Registration" start="User ID">
        ...
    <subdialog name="Payment"  dialogName="Process Payment">
      <transition  outcome="next" target="Email Preferences"/>
       <transition  outcome="cancel" target="Email Preferences"/>
   </subdialog>
       ...
  </dialog>
<!—  Take Payment Dialog — >
  <dialog name="Process Payment" start="Credit Card">
    <view name="Credit Card" viewId="/creditcard.jsp">
      <transition outcome="submit" target=
        "Process Credit Card"/>
      <transition outcome="cancel" target="Exit"/>
    </view>
     <action name="Process Credit Card" method=
       "#{paymentBean.processCreditCard} ">
       <transition  outcome="success" target=
         "Thank You For Payment"/>
     </action>
   <view name="Thank You For Payment"
      viewId="/thankYouForPayment.jsp">
     <transition outcome="next" target="Exit"/>
   </view>
   <end name="Exit"/>

如果您想让用户使用向导更舒适,应该使他们在客户端和
服务器端保持一致。下面介绍 Shale 验证:
使用 S t r u t s 时,可以通过重写 A c t i o n F o r m 中的验证
(ActionMapping、HttpServletRequest)或在 XML 配置文件中声明
ActionForm 字段的验证来提交服务器端验证。在Struts中,确保
服务器端和客户端一致性验证是困难的,如果可能的话,客户
端验证将通过 DynaValidatorForm 消极地完成。
JSF对Validations的支持略好一点。JSF通过它的javax.faces.
validator.Validator接口、<f:validator/>标签和faces-config.xml配
置文件设置提供一个可插入的验证框架。它提供三种指定的验
证,即DoubleRangeValidator、LongRangeValidator和LengthValidator。
尽管这是一个好的开始,但这与您在真实世界应用程序中可能
遇到的验证类型相差甚远。
JSF 也似乎完全忽略了客户端验证。虽然服务器端验证是
完全必要的,但是有辨别地使用客户端验证,通过减少与服务
器往返的行程,可以提高应用程序的性能,甚至可以改善用户
体验。
JSF 做得好的地方就是它允许您增加您自己的验证。Shale

 </dialog>

利用了这个扩展性(利用 Apache Commons Validator框架)提

</dialogs>

供以下附加的服务器端和客户端组件:
u Credit Card

清单 6. Subdialog 和 Process Payment 对话

u Date

注意“Create New Registration”中的 subDialog是如何调用

u Email

“Process Payment”对话框的。
在“Process Payment”对话的终端节点中,
“Exit”缺少viewId
属性。因此,当“Credit Card”和“Thank You For Payment”视

u Generic
u ISBN
u URL

图分别返回“cancel”和“next”结果时,它们通过“Exit”返回
到“Create New Registration”对话中的 subDialog。
“Create New

这只是一个开头,当 Shale 成熟时可望看到更多的验证。

Registration”中的 subDialog“Payment”节点接着通过它定义的

Launch Party应用程序在userid.jsp和creditcard.jsp中使用了

事务来处理这些结果。这些过渡都通过“cancel”和“next”到

几种 Shale验证。清单7显示了在userid.jsp中所使用的电子邮件

达“Email Preferences”。

验证。所有其他验证都遵循相似的模式:

“Create New Registration”和“Process Payment”之间唯一
的联系就是,当“Create New Registration”对话中的 subDialog

102 程序员

...
<%@include file="messages.jspf"%>

>>> Java
...
<h:form id="userid" onsubmit="return validateForm(this);">
<h:outputText value="*** DEBUG MODE ***" rendered="#{jndi.
debugMode}"/>
...
<h:outputText value="* Email Address:"/>
<h:inputText id="email" value="#{registrationBean.email}">
  <s:commonsValidator type="required" message=
    "#{launchPartyMessages.EMAIL_REQUIRED}"   client=
     "true" server="true"/>
   <s:commonsValidator type="email" message=
     "#{launchPartyMessages.EMAIL_INVALID}"   client=
     "true" server="true"/>
</h:inputText>
<h:message for="email" styleClass="errors"/>
...
<s:validatorScript functionName="validateForm"/>
...

清单 7. userid.jsp 中的 Email Validation
userid.jsp 中的 email address字段是必需的,它必须是合法
的电子邮件地址格式。清单7使用两个<s:commonsValidator/>
标签,一个类型是“required”,另一个类型是“email”。客户端
和服务器端验证都被启用。
客户端验证需要<s:validatorScript/>,它生成在JSP页面中
进行运行时验证的 JavaScript 函数,在 h:form 标签中,onsubmit
函数设置为使用由<s:validatorScript/>创建的验证函数。
通过在 userid.jsp顶部巧妙地包含messages.jspf,用户违规

WEB-INF/web.xml 中定义的属性和资源值的访问。简单地说,
这意味着 Apache Shale 可以使用以下功能:
u 您可以使用web.xml中的<env-entry>来定义环境项的值,

当“#{jndi.XXXX}”表达式(这里XXXX是web.xml 中的项名称)
在 JSP 或它的支持bean 中被使用时,Shale会提供对它们的访问。
u 您可以使用web.xml中的<resource-ref>定义资源,Shale

将在动态创建资源时根据定义进行值绑定。
Launch Party应用程序使用第一个特性来决定一个应用程序
是否以调试模式运行。debugMode环境项在web.xml(如清单10
所示)中定义,然后在所有的 JSP 页面中使用:
...
<env-entry>
    <description>
       Flag indicating whether we run in debug mode
    </description>
    <env-entry-name>debugMode</env-entry-name>
    <env-entry-value>true</env-entry-value>
    <env-entry-type>java.lang.Boolean</env-entry-type>
</env-entry>
...

清单 10. Web.xml 中的 ebugMode环境项
注意所有 JSP 页面中的<h:outputText value="*** DEBUG
MODE ***" rendered="#{jndi.debugMode}"/>。

时显示的消息将从 LaunchPartyMesssages.properties 文件得到。
LaunchPartyMessages.properties 是一个普通的资源包,包含
了错误消息的键 / 值对(如清单 8 所示)。这个文件位于com/
techyatra/shale 文件夹下,这也是 Launch Party 应用程序的 Java
包的文件夹。

结束语
本文只是露出冰山一角。Shale 的全部能力将给基于 JSF的
Web 应用程序带来很大的好处。例如,Clay集成为JSF应用程序
提供了组件化的JSP 页面。我相信Shale将实现JSF所能做的,正
如 Struts 实现 MVC2 一样。

# Launch Party ResourceBundle properties file
...
EMAIL_REQUIRED=Email address is required
EMAIL_INVALID=Email address is invalid
...
Listing 8. LaunchPartyMessages.properties File in com/techyatra/
shale
Messages.jspf contains declaration of variable launchPartyMessages
using JSF's <f:loadBundle/> tag as shown in Listing 9 below.
...
<f:loadBundle var="launchPartyMessages"
        basename="com.techyatra.shale.LaunchPartyMessages"/>
...

参考资料:
JavaServer Faces (JSF) 是一种用于构建Web应用
程序的标准 Java 框架。它提供了一种以组件为中心来开发
Java Web用户界面的方法,从而简化了开发。JavaServer
Faces 已经引起了广大 Java/Web开发人员的兴趣。
“企业
开发人员”和 Web 设计人员将发现 JSF 开发可以简单到只

清单 9. Messages.jspf

需将用户界面(UI) 组件拖放到页面上,而“系统开发人员”

Shale Validation代码在org/apache/shale/validator/validator-

将发现丰富而强健的 JSF API 为他们提供了无与伦比的功

rules.xml中具体给出,该文件可以在shale-core.jar文件中找到。

能和编程灵活性。JSF 还通过将良好构建的模型 - 视图 - 控

仔细阅读它,它是相当引人入胜的!

制器(MVC)设计模式集成到它的体系结构中,确保了应用程
序具有更高的可维护性。如果您觉得需要更深入了解 JSF,

直接连接到 JNDI
JNDI提供应用程序所需的大量目录服务访问。Apache Shale
的 JNDI模块不是一个非常广泛的 JNDI实现。它只集中提供对/

推荐访问官方网址:
http://java.sun.com/j2ee/javaserverfaces/
http://www.jcp.org/en/jsr/detail?id=127

Programmer

103

技术

Technology

微软技术 >>>

在《P/Invoke 之实用篇》一文(发表于《程序员》2005 年 4 月刊)中,我们知道
了如何使用 P/Invoke,那 P/Invoke 在背后到底做了哪些事情,让它可以具有如此的
魔力,让已有的代码库乖乖的听话从事呢?在本文中,我们将进一步揭开 P/Invoke
的神秘面纱,让它不再神秘,也让我们可以更好的发挥 P/Invoke 的巨大威力。

深入解析 P/Invoke
□ 文 / 刘华军
概述
CLI在设计的时候就已经考虑到了与已有的代码进行交互操
作的问题,而且这种交互操作要尽可能的简单。你所要做的只
是为要调用的代码创建一个 DllImport 函数声明,运行时库将会
处理所有余下的工作,就像下面这样:
   [DllImport("kernel32.dll")]
   public static extern bool Beep(int frequency, int duration);

上面这段 C# 函数声明会发出 Beep 的系统调用,在带有
kernel32.dll的平台上将会成功调用,而在不带有该dll的其他平台

3.ϵͳĿ¼£¨Ê¹ÓÃGetSystemDirectory()º¯Êý»ñÈ¡µÄĿ¼£©£»
4.16λµÄϵͳĿ¼£»
5.WindowsĿ¼£¨Ê¹ÓÃGetWindowsDirectory()º¯Êý»ñÈ¡µÄ
Ŀ¼£©£»
6.ÔÚPATH»·
¾³±äÁ¿ÖÐÁгöµÄĿ¼¡£
不过,现实总不是那么简单。事实上,系统目录指的是
%WINDIR%\system32,Windows 9X平台上则是%WINDIR%\system,
16 位的系统目录一般是 %WINDIR%\system,不过在Windows
9X 平台上它不会作为一个单独的搜索目录。

上将会抛出一个MissingMethodException异常。正像我开始所说的

另外,在Windows Server 2003 和Windows XP SP1 上,通

那样,够直接了吧。你还能想出比这个更简单的调用方法吗?

过注册表项目HKEY_LOCAL_MACHINE\System\CurrentControlSet

在这里有三个问题需要解决:

\Control\Session Manager\SafeDllSearchMode可以对以上的顺序

1.ÔÚDllImportÉùÃ÷ÖÐÖ¸¶¨¿âÎļþ£»

进行调整。如果值为1(默认值),那么当前目录将在系统目录

2.È·¶¨ÐèÒªµ÷Óõĺ¯Êý£»

和 Windows目录之后搜索。这是出于安全性的考虑(以免特洛

3.¾ø´ó¶àÊýµÄÒÑÓдúÂ붼Ï൱¸´ÔÓ£¬ÐèÒª´«µÝ×Ö·
û´®¡¢½á

伊木马会抢在正常的系统文件前加载,比如,OLE32.DLL),不

¹¹£¬Ò²Ðí
»¹ÒªÉæ ¼°µ½ÄÚ´æ¹ÜÀí¡-¡已有的代码看起来就像一头难以驯服的怪兽,而交互层
(interop layer)则必须要处理这一切的复杂性,让这头怪兽乖乖

过这样做的结果就是把上述的搜索顺序变成了: 1, 3, 4, 5, 2, 6,
在调试程序的时候如果碰到这方面的问题,不妨考虑一下这种
情况。

听话。
下面还是让我们从头说起。

库文件名称
知道在哪里搜索库文件只是问题的开始,还必须要知道哪

库文件的处理方式

个库文件是需要加载的。不同的平台有不同的命名方式。

运行时库如何找到DllImport属性指定的库文件?这个问题

不过.NET 从一诞生,目标就是跨平台的,如果在不同的平

是与平台密切相关的,我们目前只关心Windows 平台,所以下

台上,对应函数的库文件名不一样怎么办?比如GTK+ 在Win-

面的讨论都基于 Windows 平台,请大家注意。

dows 下的库文件名为:libgtk-win32-2.0-0.dll,而在Unix 下的

Windows平台载入DLL文件使用的是LoadLibrary 函数,在载
入程序需要的 DLL 时会按照下面的顺序进行查找:
¼ÓÔØÓ¦
1.
ÓóÌÐòµÄĿ¼£»
2.µ±Ç°Ä¿Â¼£»

104 程序员

同一个库文件名为:libgtk-x11-2.0.so。那应该如何才能写出
跨平台工作的 P/Invoke 代码呢?回答很干脆,不能。因为在.
NET 中没有提供指定平台相关的库文件名称的标准方式。
不过,Mono提供了解决这个问题的扩展方式——库名称映

>>> 微软技术

射机制。库名称映射可以通过两个地方的配置文件来实现,一

新你的程序集,由于以上原因,显而易见你的程序集将是非常

个是 ¥prefix/etc/mono/config 的 XML 文件,另一个是每一个

难以维护的。

assembly的.config 文件,在与assembly相同的目录下。这些文件

内存分配

都包括了<dllmap/>元素,映射了输入库文件名(在 DllImport
中声明的库文件名)和实际的与平台相关的库文件名。比如:

托管和非托管内存在考虑的时候应该完全独立开。托管内
存是完全由GC管理的内存堆中分配的,而非托管内存则是其他

      <configuration>
         <dllmap dll="libgtk-win32-2.0-0.dll"
            target="libgtk-x11-2.0.so" />
      </configuration>

形式分配的内存:ANSI C 的内存池通过mallco 分配的内存、自
定义的内存池,以及不在 CLI 实现范围内分配的内存堆(比如
LISP 或者 Scheme 的内存堆)。

与.NET 不同,Mono 允许.dll 装配件有自己的.config 文件,
不过只能用于库文件名称映射机制。

使用 C#的fixed语句可以锁定托管堆的一个段,这样可以
使得我们不必担心 GC 会回收我们传递给非托管代码操作的内
存。不过,这需要完全由程序员来小心控制。

调用非托管代码
非托管代码的调用主要是由DllImport属性所指定的方法完

将类和结构封送为本地代码的伪过程如下:
1.
ÔËÐÐʱ¿â·
ÖÅäÒ»¿é·
ÇÍйÜÄڴ棻

成的。CLI 运行时库在这当中做了比你所能看到的多得多的工

Í
2.
йÜÀàµÄÊý¾Ý±»¿½±´µ½Õâ¿éÄÚ´
æÖУ»

作。从概念上来说这个过程其实非常简单,首先加载DllImport

3.
µ÷Ó÷
ÇÍйܺ¯Êý£¬½«·
ÇÍйÜÄڴ棨²»ÊÇÍйÜÄڴ棩µÄÐÅ

属性指定的库,然后找到指定的函数(通过GetProcAddess()),

Ï¢´«µÝ¸ø·
ÇÍйܺ¯Êý¡£Ö®ËùÒÔ±ØÐëÒªÕâÑù×öÊÇÈ·
±£·
ÇÍйܺ¯Êý

最后调用函数。

ÔÚµ÷ÓõĹý³ÌÖÐÎÞÐèµ£ÐÄGCµÄÓ°Ïì
£»£¨²¢²»ÊÇ˵ÍêÈ«²»ÐèÒªµ£

不过,要查找的函数名如何确定呢?默认情况下,使用的

ÐÄGCµÄÓ°Ïì
£¬µ±·
ÇÍйܺ¯ÊýÐèÒª»Øµ÷ÔËÐпâµÄʱºò£¬ÎÒÃÇ»¹

是托管代码的名称;另外可以设置DllImport 属性的EntryPoint 字

ÊDz»µÃ²»¿¼ÂÇGCµÄÓ°Ïì
£¬Áí
Í⣬·ÇÍйܴúÂëÔÚÔËÐÐʱ£¬³ÌÐò

段,使用该字段的字符串值进行查找。不过,这里使用的字符

ÖÐÆäËû²¿·
ֵĶàÏß³Ì
´úÂëÒ²»áµ¼ÖÂGC¡
££©

串是兼容 C 语言的 ABI 函数形式的,在一些平台上,需要在字
符串前加上一个前导的下划线。

4.·
ÇÍйÜÄÚ´æ±»¿½±´»ØÍйÜÄÚ´æ¡£
在这里有一个地方需要注意:上面所说的内存管理过程是

不过需要注意的是这里的兼容性是假设的,如果对于那些

由.NET 控制的,也就是说你无法控制运行时库怎样分配封送

不兼容 C 语言的 ABI 函数形式的类库,将很难直接调用,比如

的内存,或者这块内存能持续使用多长时间。这一点非常重

没有使用 extern "C"标志的C++库。另外,一些C语言的ABI函

要。如果运行时库封送了一个字符串,那么被封送的字符串只

数形式的变体是允许的,比如函数的调用方式

能在调用过程中使用。非托管代码无法保证这块内存引用的有

(CallingConvention)的不同形式。默认的调用方式是与平台相关

效性,这块内存将会在调用结束后被释放掉。不注意这一点可

的。在Windows系统中,StdCall是默认方式,绝大多数的Win32

能会导致一些奇怪的现象发生,比如内存访问违例和进程异常

API 都使用这种方式,而在 Unix 平台下,Cdecl 是默认方式。

中止。

如果你确定需要调用 C++ 代码,你有两个选择:
(1) 在 C++ 函数前加上 extern "C",让它们看起来(至少
在二进制接口这层是这样)是C 函数,而且使用编译器支持的
调用方式;
(2) 没有使用 extern "C",不过使用了编译器支持的调用

内存管理
在大多数 P/Invoke和封送的过程中,我们都可以忽略内存
管理的问题,不过对于返回值,CLI所做的一些默认处理必须予
以考虑。

方式。这种方式是不推荐的,如果你这么做了,那么你必须将

CLI设定在特定的情况下CLI运行时库要负责释放由非托管

DllImport 属性的 EntryPoint 字段设为 C + + 的编译后函数名

代码分配的内存。而返回值就属于这些情况中的一种,这使得

(mangled function name),也就是类似于_Z6getpidv这样晦涩难

返回值成为控制内存分配 / 回收的一个边界。

懂的天书。你可以通过编译器自带的工具,比如OBJDUMP.EXE

CLI还设定在CLI和非托管代码之间传递的所有内存都是通

来获取你的函数名。不过需要提醒的一点是这些天书名称是与

过一个公用内存分配器来分配的。开发人员没有选择使用哪个

编 译 器 相 关 的,所 以 在 不 同 的 平 台 上 需 要 不 同 的 程 序 集

内存分配器的权利。对于托管代码,Marshal.AllocCoTaskMem方

(assembly),而且每当你更换 C++ 编译器之后,你同时需要更

法用来分配内存,Marshal.FreeCoTaskMem 则用来释放 Marshal.

Programmer

105

技术

Technology

微软技术 >>>

AllocCoTaskMem方法分配的内存,而Marshal.ReAllocCoTaskMem

的话,那么可能也是不安全的。当非托管内存是由不同的系统

用来重新划分所分配的内存大小。

来处理的就可能出现这种情况,比如Python、Ruby、Lisp等等。

因为类是通过引用传递,返回的是指针,运行时库认为它

如果非托管内存是由垃圾回收机制来管理的,那么在非托管内

必须释放这些内存,以避免内存泄漏。因此,就发生了下面这

存执行垃圾回收的时候,System.IntPtr并不会同时更新,这样的

一串事件:

结果就是造成内存内容被破坏。

1.ÍйܴúÂëµ÷Ó÷ÇÍйܺ¯Êý£¬·µ»ØÁËÖ¸Õ룬¸ÃÖ¸ÕëÖ¸Ïò·
Ç

看看下面给出的非托管 API:

ÍйÜÄÚ´
æÖеÄÒ»¸ö·
ÇÍйܽṹ£»
2.ÏàÓ¦
µÄÍйÜÀàµÄʵÀý¹¹Ôì
Íê³É£¬·
ÇÍйÜÄÚ´æ µÄÄÚÈݱ»·
â
ËÍ
µ½ÍйÜÀàʵÀýµ±ÖУ»
3.·
ÇÍйÜÄÚ´æ±»ÔËÐÐʱ¿âµ÷ÓÃMarshal.FreeCoTaskMem·
½
·¨ÊÍ·Å¡£

   typedef void* HANDLE;
   bool CreateItem (HANDLE *item);
   void DestroyItem (HANDLE item);
   int GetInfo (HANDLE item);

“类型安全”的 C# 封装形式象下面这样:

那么Marshal.AllocCoTaskMem,Marshal.ReAllocCoTaskMem和
Marshal.FreeCoTaskMem具体又是如何实现的呢?答案是与平台
相关的。在Windows系统下,使用的是COM任务内存分配器(通
过 CoTaskMemAlloc,CoTaskMemReAlloc和 CoTaskMemFree 三个
COM API 实现)。

   struct Item {
      [DllImport ("library")]
      public static unsafe extern
         bool CreateItem (out Item* item);
      [DllImport ("library")]
      public static unsafe extern void DestroyItem (Item* item);

尽量避免封送
虽然上面一再提到了封送,而且看起来P/Invoke离开了封
送这个信使就根本无法与非托管的世界产生联系,但是封送并
不是灵丹妙药,永远记住一点:封送其实往往意味着拷贝数据。
封送之所以可能成为问题的根源,是因为数据传输本身就非常
复杂,而又极易耗费时间。另外,如果数据未知或者可能改变
的话,它也可能不拷贝数据,
后者的一个很好的例子是 GTK+库。GTK+是一套面向对象
的工具库集合,用 C 语言写成。和所有的面向对象库一样,它

      [DllImport ("library")]
      public static unsafe extern int GetInfo (Item* item);
   }
   class ExampleUsage {
      public static unsafe void Main ()
      {
         Item* item;
         Item.CreateItem (out item);
         int n = Item.GetInfo (item);
         System.Console.WriteLine ("item count: {0}",
            n.ToString());
         Item.DestroyItem (item);
      }
   }

有数不清的派生类,每一个派生类都有不同的大小,而且类实

这样是类型安全的是因为你不能传递任意的内存位置给这

例通常是通过指针访问的。同样,因此在托管和非托管内存之

些静态的以 Item 指针作为参数的函数,你必须传递一个指向

间封送整个类就没有其他选择了,拷贝是不行的,只能采用同

Item 结构的指针。这并不是类型安全过于严苛,而是为了将意

样的方式来访问。

外的内存崩溃降低到最低限度。不过这里最大的问题是它使用

另外的例子是使用“不透明的”数据类型,这里的“不透
明的”指的是数据类型完全通过指针来进行传递,数据类型的
内部信息没有任何东西是公开的。这方面一个最典型的例子就
是 Win32 API 中的句柄,它无处不在,却又让你毫不知情。
在C#中有两种方式来处理这种情况:
“类型安全”的方式,
通过使用指针和“unsafe”关键字来实现;以及CLS兼容的方式,
通过使用 System.IntPtr来表示 void 指针。
在这两种情况下,托管和非托管内存的区别非常清楚。托
管内存保持类型安全,而非托管内存则不一定(因为 System.
IntPtr是用来指向非托管内存的,这就没有办法保证它指向的是
有意义的数据类型)。
需要注意的是如果“非托管”内存自身具有垃圾回收机制

106 程序员

了“unsafe”的代码,因此不能在其他的.NET语言中使用,比如
Visual Basic .NET 和 JavaScript。
上述代码的 CLS 兼容版本则使用 System.IntPtr来指向非托
管内存。这看起来很像是Marshal类在与非托管内存交互时所做
的那样:
   class Item {
      [DllImport ("library")]
       public static extern
         bool CreateItem (out System.IntPtr item);
      [DllImport ("library")]
       public static extern void DestroyItem (System.IntPtr item);
      [DllImport ("library")]
      public static extern int GetInfo (System.IntPtr item);

>>> 微软技术
   }
   class ExampleUsage {
      public static unsafe void Main (){
         System.IntPtr item = null;
         Item.CreateItem (out item);
         int n = Item.GetInfo (item);
         System.Console.WriteLine ("item count: {0}",
            n.ToString());
         Item.DestroyItem (item);
      }
   }

这样做的不安全之处在于它很容易在不经意间滥用指针。
比如如果你使用的是两个不同的库,并且用 System.IntPtr来对
它们进行了封装,那么很有可能把一个库分配的对象传递给另
一个库导出的函数,而CLR运行时库并不会捕捉到这个错误,当
错误出现的时候,将直接使你的“unsafe”的 C# 代码崩溃。

      // frees resources of h
      [DllImport ("...")]
      static extern void DeleteHandle (IntPtr h);
       ̄C() {
         DeleteHandle(h);
      }
      public void m() {
         OperateOnHandle(_handle);
         // no further references to _handle
      }
   }
   class Other {
      void work() {
         C c = new C();
         c.m();
         // no further references to c.
         // c is now eligable for collection.
      }
   }

不过,在大多数托管代码不与P/Invoke代码交互的情况下
这并不成其为问题,你只需要用托管的封装类来与非托管代码
来交互,并且向你的托管代码提供一个看起来更自然的接口就

考虑一下这种情况:Other.work 调用了c.m,而c.m又调用
了非托管代码C.OperateOnHandle。注意Other.work已经不再使用
c 了,所以 c 已经符合被回收的条件了,并且被放到了 GC的终

可以了。

止化队列(finalization queue)中。

GC 安全的 P/Invoke 代码
在上面描述的封装代码中同样存在着一个问题:用户代码
和运行时库的垃圾收集器(GC)之间的竞争。
.NET 使用的 GC 相当聪明,它知道相关的所有类型,可以
分别出一个看起来像是指针的整数和一个实际的指针。它知道
所有栈分配的变量以及这些变量的生存范围。不过GC对非托管
代码内部的一切则是一无所知,这样就可能出现这样一种让人
感到尴尬的情况:GC可能会在一个类实例的某个方法还在执行
的时候把它给回收掉。
这怎么可能?你也许会说。但事实就是这样,如果这个方
法不再使用类的实例成员,而且也没有其他代码使用,那么GC
就可能回收这个类。毕竟,如果没有谁在使用实例成员,而且
也没有谁使用类实例,那么谁还会在乎这个实例是不是被回收
了呢?
不过对于非托管代码就不是这么简单了,尤其是它还认为
这个类实例可用的情况就更麻烦了。同样,如果这个类有终止
函数(finalizer),它也会在其他方法正在执行的时候就不合时宜

这样做一般来说是合理的,
如果不考虑非托管代码的影响,
上面的非托管代码 C.OperateOnHandle 还在使用实例 c的一个成
员,可是 GC 不知道,也不可能知道这一点。
上面的场景描述了前面所说的可能性,虽然看起来很不可
能。C.DeleteHandle将会在C.OperateOnHandle还在执行的时候就
被 GC 的终止化线程(finalization thread)调用。
可以想象非托管代码并不喜欢这样的情况出现,因为这将
会是进程中可能出现的主要问题,包括可恶的段错误
(segmentation fault)。实际上在.NET 1.0 的一个注册表封装类
中就存在着一个与这个非常类似的 bug。
那如何避免这个问题呢?问题的关键在于IntPtr,一旦你使
用了IntPtr,GC就无法知道你的类是否还在被使用。我们需要用
HandleRef 来代替 IntPtr。HandleRef 是一个包含有类引用的结构,
同时可以和指针值一样使用。
接下来,
还要在P/Invoke代码中用HandleRefs参数来代替IntPtr
参数。而且,HandleRefs对于运行时库和GC系统来说是很特别的,
在封送操作中它会被“折叠(collapse)
”到一个IntPtr中。

的冒出来。

正确的释放资源

看看下面这个例子:

在避免封送的同时,你的托管代码将直接面对非托管内存
   class C {
      // handle into unmanaged memory, for an
         unmanaged object
      IntPtr _handle;

和其它资源。这意味着你的责任更加重大,需要考虑的事情更
多,而在这些事情当中,大多数都会让你的托管代码出这样那
样的问题,比如异常,和随之而来的复杂性。因为任何函数都

      // performs some operation on h
      [DllImport ("...")]
      static extern void OperateOnHandle (IntPtr h);

可能抛出异常,所以确保正确的释放资源就成了你需要慎重考
虑的事情。

Programmer

107

技术

Technology

微软技术 >>>

正如前面所建议的那样,确保资源能被正确释放的一个简
单方法是将资源封装到一个有终止函数的类当中,终止函数能

   using System;
   // for HandleRef, DllImport
   using System.Runtime.InteropServices;

够最终释放资源。
不过这种方法存在两个问题,而这两个问题都与垃圾收集
器有关:
1. 垃圾收集器无法深入到非托管内存中去,它只能处理托
管内存。因此,如果你要处理大量的非托管内存(比如图像或
者视频数据),GC 所能看到只是指向这些数据的 IntPtr,而不是
托管代码中容纳的非托管内存的实际大小。所以,GC也就不知
道需要执行这样一个回收,因为这里没有任何“内存压力”—
—内存不足,需要执行回收来获得更多的内存。不过这个问题
在.NET 2.0 中已经被 System.GC.AddMemoryPressure(long)方法部分
的解决了,该方法用来告诉GC一个托管对象指向了多大的非托
管内存,这样就提高了 GC 的启发式智能(heuristics);
2. 对于被回收的对象,.NET 的垃圾收集器不会执行对象的

   sealed class UnmanagedResource : IDisposable
   {
      [DllImport ("...")]
      private static extern IntPtr CreateResource ();
      [DllImport ("...")]
      private static extern
         void DeleteResource (HandleRef handle);
      // Use a HandleRef to avoid race conditions;
      private HandleRef _handle;
      public UnmanagedResource ()
     {
         IntPtr h = CreateResource ();
         _handle = new HandleRef (this, h);
     }
      // Provide access to 3rd party code
      public HandleRef Handle {
         get {return _handle;}
     }

终止函数。相应的做法是,对象的代龄被提升(p r o m o t e d   a
generation),对想的终止函数将会在下次这一代被回收的时候执
行。比如,如果一个有终止函数的第 0代对象符合被收集的条
件(也就是说,没有对象引用它),该对象的代龄被提升,被放
到第 1 代的终止化队列中。下次当第 1 代被回收的时候,对象
的终止函数才被执行。
问题2是一个真正的麻烦,
这是因为回收频率与代龄数字是
成反比例的。第0代(通常)的回收频率通常是第1代的 10倍,
而第 1代又是第2代的10倍。第2代一般很少被回收,这些通常
是一些长期存在的对象,往往与应用程序的存在时间一致。
假定最快的情况下一个被终止的对象在两次收集之后被回
收了,一次是第 0 代,一次是第 1 代(大概在 10 次左右的第 0
代收集之后),但这两次收集之间可能会相隔很长的一段时间,
然后终止函数才被执行。再考虑一下终止函数并没有保证会一
定被执行,即使程序退出也不一定会,所以看起来太过依赖资
源处置和回收的终止函数并不是个好主意。

      // Dispose of the resource
      public void Dispose ()
     {
         Cleanup ();
         // Prevent the object from being placed on the
         // finalization queue
         System.GC.SuppressFinalize (this);
     }
      // Finalizer provided in case Dispose isn't called.
      // This is a fallback mechanism, but shouldn't be
      // relied upon (see previous discussion).
       ̄UnmanagedResource ()
     {
         Cleanup ();
     }
      // Really dispose of the resource
      private void Cleanup ()
     {
         DeleteResource (Handle);
         // Don't permit the handle to be used again.
         _handle = new HandleRef (this, IntPtr.Zero);
     }
   }

幸运的是在.NET类库当中有一个很简单的方式来帮助我们
确保资源可以被很快的释放:

经常可以看到 IDisposable 的示例是作为一个虚方法 virtual

1. 实现 System.IDisposable 接口;

Dispose(bool)出现,然后Dispose和终止函数再委托到它,和上

2. 在结束使用资源的时候调用Dispose。Dispose的实现需要

面所用 Cleanup() 方法相反。提供一个虚函数和一个没有密封

完成两件事情:
(1) 释放资源;
(2) 调用SuppressFinalize。SuppressFinalize告诉GC不要再调

(non-sealed)的类实际上说明会有,甚至可以说希望有派生的
子类,不过这样做并不是好主意。
再说一遍,这并不是好主意!还是因为垃圾收集器。当一

用对象的终止函数,
让对象可以在第一次回收的时候就被释放,

个对象的代龄被提升之后,
所有它引用的对象的代龄也被提升。

而不用再考虑那让人捉摸不定的延迟了。

所以如果你的终止对象包括了其他对象的一个ArrayList,包括这

实现的样例见下面的代码:
   // for IntPtr, IDisposable

108 程序员

个ArrayList,它所容纳的所有对象,以及那些对象的所有引用都
将被提升,可以想象的事,这将是一个潜在的巨大的数字。

>>>  .NET

编写数据库访问代码是一项重复且费时的工作,因为现在有了可重用的 Enterprise
Data Access Application Block,您再也不必编写这类代码了。

.NET 2.0 中的企业访问数据块
□ 何志刚

 ADO.NET提供了许多丰富的功能,可用于以多种
方式检索和显示数据,但是即使具有这种灵活性,有时开发人

过添加包含特定于数据库的功能或提供现有数据库的自定义实
现的新数据库类型,您可以扩展应用程序块。

员还是会发现自己在重复编写同样的代码。例如,所有数据驱

Microsoft已经重新设计了Data Access Block的2.0版本,以

动的应用程序都需要访问数据库。您需要编写代码连接到数据

利用新的 ADO.NET 2.0 功能。您可以从 MSDN 下载 EntLib Data

库,打开连接,执行动态的 SQL 或存储过程,获取结果,然后

Access Block。

关闭连接。换句话说,这是在您开发的几乎所有应用程序中都

使用 Data Access Block

必须编写的“管道”代码,即便它没有为核心业务用户增添任
何价值。

为了成功地使用Data Access Block,您需要完成下列步骤:

通常,各种应用程序中的此种代码间的惟一区别在于SQL

1.添加一个对解决方案中Microsoft.Practices.EnterpriseLibrary.

语句或存储过程名、命令参数和连接字符串。只要您可以把这

Common.dll和Microsoft.Practices.EnterpriseLibrary.Data.dll组合的

些变量参数化,您就可以把大部分管道代码抽象为可重用的

引用。具体方法是使用"Add Reference" 选项,然后导航到<Drive

类,然后跨多个应用程序应用这些类。这是值得花时间去做的

Name>:\Program Files\Microsoft Enterprise Library January 2006\bin

工作——但是不值得您亲自动手,因为 Microsoft(在社区的支

文件夹;

持下)已经在其 Enterprise Library (也叫做 EntLib) Application

2.给web.config 或app.config文件添加必需的配置项。为此

Block 中为您完成了此项工作。本文介绍了 EntLib Data Access

目的,
您需要在根<configuration>元素下添加以下<configSections>

Block,并给出了一些例子来说明如何使用它来编写健壮的数据

元素;

访问代码。

Enterprise Data Access Block
Data Access Block 帮助开发人员完成了开发数据库应用程
序时最常见的任务。通过提供一组封装好的方法,Data Access
Block极大地简化了用于访问数据库的最常用方法。每个方法都

<configSections>
<section
name="dataConfiguration"
type="Microsoft.Practices.
EnterpriseLibrary.Data.
Configuration.
DatabaseSettings,
Microsoft.Practices.
EnterpriseLibrary.Data" />
</configSections>

包含检索适当数据所需的逻辑,并管理数据库连接。另外,Data
Access Block 是数据库不可知的(database-agnostic)
;它对ADO
.NET 2.0中的代码进行了补充,能够让您编写可以跨不同关系
数据库使用的数据访问代码——同时无需重新编写代码。这些
类包含的代码为诸如参数处理和游标之类的功能提供了特定于
数据库的实现。
Data Access Block 还为 SQL Server 和 Oracle 数据库提供了
特定的派生类。另外,GenericDatabase类允许您使用应用程序块
和任何配置好的ADO.NET 2.0 DbProviderFactory对象。最后,通

接着,
您还要添加<dataConfiguration> <configuration>元素,
如下所示:
 <dataConfiguration
 defaultDatabase="AdventureWorksDB"/>

在这个例子中,我已经把AdventureWorks 标记为默认数据
库,在<connectionStrings>元素下单独声明:
<connectionStrings>
<add

Programmer

109

技术

Technology

.NET >>>
name="AdventureWorksDB"
providerName=
"System.Data.SqlClient"
connectionString=
"server=localhost;
database=AdventureWorks;
UID=user;PWD=word;" />
</connectionStrings>

3.为 Data Access Block 导入核心 Microsoft.Practices.

         gridEmployees.DataBind();
       }
     }
  </script>

上述代码首先调用了DatabaseFactory类的CreateDatabase()方
法,以包含 D a t a b a s e 对象的一个实例。正如其名称所示,
DatabaseFactory 这个类包含用于创建 Database 对象的工厂方法。
CreateDatabase()方法是一个重载方法,如上所示,当您调用该

EnterpriseLibrary.Data命名空间;
4.针对上述命名空间中的类开始编写代码。

方法参数较少的版本时,它就会返回一个默认数据库。要设置
默认数据库,您需要把defaultDatabase属性值指派给Web.config

使用 Database 对象
只要使用 Data Access Block,您就必须首先处理 Database
类。Database类代表数据库本身,它提供一些方法(参见表1),

文件中正确的数据库配置键,该文件如下所示:
   <dataConfiguration
     defaultDatabase="AdventureWorksDB"/>

您可以使用这些方法对数据库执行 CRUD(Create、Read、Update

获得 D a t a b a s e 对象的一个实例之后,您就可以调用

和 Delete,即创建、读取、更新和删除)操作,并可以使用这些

GetSqlStringCommand()方法构造 ADO.NET 2.0 DbCommand 对

方法在数据库上执行 CRUD 操作。

象的一个实例。之后,您通过带有传入参数 D b C o m m a n d 的

方法

说明

ExecuteDataSet

执 行 一 次 SQL 查 询 或 一 个 存 储 过 程 ,然 后 以 Dataset

ExecuteNonQuery

对象的形式返回结果。
执 行 一 次 SQL查 询 或 一 个 存 储 过 程 ,然 后 返 回 相 关 记
录的数目。

ExecuteReader
ExecuteScalar
LoadDataSet
UpdateDataSet

Database.ExecuteReader()方法执行SQL。使用浏览器导航到该页
面。因为该方法将返回的 DbDataReader 绑定到一个 GridView 控
件,您将会看到类似于图 1 的输出:

执行一次 SQL查询或一个存储过程 ,然后以IDataReader
对象的形式返回结果。
执 行 一 次 SQL查 询 或 一 个 存 储 过 程 ,然 后 返 回 结 果 集
中第一行的第一列。
执 行 一 个 命 令 ,然 后 给 现 有 的 DataSet添 加 一 个 新 的
DataTable。
通 过 执 行 正 确 的 INSERT、UPDATE和 DELETE语 句 ,
同 步 数 据 库 的 DataSet 内 容 。
表 1:Database 类 方 法

既然现在您对于 Database 类的各个方法已经有了基本的了
解,接下来我将提供一些例子,用于演示如何使用这个类。

执行返回 DbDataReader 的查询
我将从一个简单的例子开始。您将在 AdventureWorks 数据
库上执行一个简单的SQL语句,然后获得DbDataReader对象形式

图 1:绑 定 一 个 DbDataReader。该 页 面 显 示 将 由 ExecuteReader()方 法 返
回 的 DbDataReader 对 象 绑 定 到 一 个 GridView 控 件 的 结 果 。

的结果,然后您可以把这个对象绑定到一个ASP.NET页面中的
GridView 控件上。清单 1 中包含了完整的页面代码。下面是
Page_Load 脚本:
    <script runat="server">
     void Page_Load(object sender, EventArgs e)
    {
       Database db = DatabaseFactory.CreateDatabase();
       string sqlCommand = "Select " + "EmployeeID,
         NationalIDNumber," + "LoginID, Title from " +
         "HumanResources.Employee ";
       DbCommand dbCommand = db.GetSqlStringCommand
         (sqlCommand);
       using (IDataReader reader = db.ExecuteReader(
         dbCommand))
      {
         gridEmployees.DataSource = reader;

110 程序员

执行返回 DataSet 的 SQL 查询
Database类提供一种数据库不可知的方法,
这意味着您可以
跨多个关系数据库(比如 SQL Server、Oracle 等等)使用该类。
然而,它还包含特定于数据库的类,比如 SqlDatabase(派生自
Database类),它代表一个SQL Server数据库,还有OracleDatabase,
它让您可以在 Oracle 数据库上编程。当单独为受支持的数据库
之一编程时,您应该使用特定于数据库的类。
注意:SqlDatabaseºÍ
OracleDatabaseÀ඼²»Ì
ṩ¾²Ì¬·½·¨£¬
Äú±ØÐë´´½¨Ò»¸öʵÀý²ÅÄÜʹÓÃËüÃÇ¡
£ÒÔÏ
ÂÒ³Ãæ´úÂë˵Ã÷ÁËÈçºÎ
ʹÓÃSqlDatabaseÀàÔÚAdventureWorksÊý¾Ý¿âÉÏ
Ö´ÐÐSQL²éѯ¡
£

>>>  .NET

   <%@ Page Language="C#" %>
   <%@ Import Namespace="System.Data" %>
   <%@ Import Namespace="System.Data.Common" %>
   <%@ Import Namespace= "Microsoft.Practices.
     EnterpriseLibrary.Data" %>
   <%@ Import Namespace= "Microsoft.Practices.
     EnterpriseLibrary.Data.Sql" %>
   <script runat="server">
     void Page_Load(object sender, EventArgs e)
     {
       string connString = System.Web.Configuration.
         WebConfigurationManager.ConnectionStrings
         ["AdventureWorksDB"].ConnectionString;
       SqlDatabase db = new SqlDatabase(connString);
       string   sqlCommand = "Select " + "EmployeeID,
         NationalIDNumber," + "LoginID, Title from " +
         " HumanResources.Employee ";
       DbCommand dbCommand = db.GetSqlStringCommand
         (sqlCommand);
       DataSet dst = db.ExecuteDataSet(dbCommand);
       gridEmployees.DataSource = dst.Tables[0].DefaultView;
       gridEmployees.DataBind();
     }
   </script>
   <html xmlns="http://www.w3.org/1999/xhtml" >
   <head runat="server">
     <title>Executing a SQL Select Statement to retrieve
       a DataSet</title></head>
     <body>
     <form id="form1" runat="server">
       <div><asp:GridView runat="server"
           ID="gridEmployees" /></div>
     </form>
   </body>
   </html>

该方法接受DbCommand 对象作为一个输入参数。为了显示出此
方法的优点,我将利用一个叫做GetEmployeeNationalID的存储过
程,该存储过程带有一个 E m p l o y e e I D 参数,可返回雇员的
NationalID 值。该存储过程声明如下:
   Create Procedure GetEmployeeNationalID
     @EmployeeID int
   AS
     Select NationalIDNumber
       from HumanResources.Employee
       Where EmployeeID = @EmployeeID

以下ASP.NET页面代码节选显示了调用GetEmployeeNationalID
存储过程所需的代码:
 <script runat="server">
     void Page_Load(object sender,
       EventArgs e)
     {
       int employeeID = 1;
       Database db =
         DatabaseFactory.CreateDatabase();
       string sqlCommand = "GetEmployeeNationalID";
       DbCommand dbCommand =
         db.GetSqlStringCommand(sqlCommand);
       dbCommand.CommandType =
         CommandType.StoredProcedure;
       db.AddInParameter(dbCommand,
        "EmployeeID", DbType.Int32, 1);
       string nationalID = (string)
         db.ExecuteScalar(dbCommand);
       Response.Write("NationalID : " + nationalID + "<br>");
     }
   </script>

×÷Õß×¢ÊÍ£ºÄúµ¼ÈëµÄÃüÃû¿Õ¼ä(Imports)ºÍ±¾Î
ÄÖÐÀý×ÓÓàÏÂ
²¿·
ÖµÄÒ³ÃæHTML´
úÂëÀàËÆÓÚÇ°ÃæµÄÀý×Ó£¬ËùÒÔÎÒÔÚʣϵÄÀý

首先,代码使用AddInParameter()方法给DbCommand对象添

×ÓÖкöÂÔÁËËüÃÇ¡£È»¶ø£¬Äú¿ÉÒÔÏ
ÂÔØʾÀý´úÂëÀ´
»ñµÃÍêÕûµÄʾ

加了 EmployeeID 输入参数。注意,EmployeeID 参数没有带 @ 前

ÀýÒ³
Ãæ¡
£

缀,这就是通常指示一个 SQL Server的存储过程参数的做法—

您应该从使用WebConfigurationManager类从Web.config文件

—这也是 Data Access Block以前版本的工作方式。在Data Ac-

获得连接字符串开始,然后提供该连接字符串作为SqlDatabase

cess Block 的这个新版本中,Database 类是一般性的,不需要指

类构造器的一个参数。有了 SqlDatabase 类的一个实例之后,您

定特定于数据库的前缀,比如@ 符号和问号。ExecuteScalar()方

就可以把它当作一般的Database类来使用,因为SqlDatabase类是

法执行存储过程并返回 N a t i o n a l I D,代码使用脚本结尾处的

从 Database 类继承的。例如,SqlDatabase类还公开了一些方法,

Response.Write()语句将此 ID 显示在客户端上。

比如GetSqlStringCommand()和ExecuteDataSet(),通过这些方法,

执行返回单个行的存储过程

您可以获得一个 DbCommand 对象的实例,执行SQL查询,并以
DataSet对象的形式返回结果。尽管前面的例子使用的是SELECT
SQL 语句,您可以使用一个存储过程轻松执行相同的操作。

有时候,您需要检索一个行,而不是一组行。您可以使用
存储过程以一组输出参数的形式返回单个行,而不是以DataSet
或 DataReader 的形式返回。为此,您应该使用 Database 类的

执行存储过程以获得单个项
有时候,您可能希望通过一个存储过程或一次SQL查询只
获得一项。例如,插入新的一行到数据库中之后,您可能希望
将新插入的值返回给使用者。
为此,Database 类提供了一个叫做 ExecuteScalar()的方法,

ExecuteNonQuery()方法。作为 DbCommand 准备工作的一部分,
您需要给DbCommand 对象添加输出参数。下面给出该存储过程
的声明:
Create Procedure GetEmployeeDetails
     @EmployeeID int,

Programmer

111

技术

Technology

.NET >>>
     @NationalIDNumber nvarchar(15)
       OUTPUT,
     @LoginID nvarchar(256) OUTPUT,
     @Title nvarchar(50) OUTPUT
   AS
     Select @NationalIDNumber =
       NationalIDNumber,
       @LoginID = LoginID,
       @Title = Title from
       HumanResources.Employee
     Where EmployeeID = @EmployeeID
   GO

可以帮您满足这个愿望,因为它提供了一个 D a t a b a s e .
CreateConnection() 方法,允许您获得一个对 ADO.NET 2.0
DbConnection对象的引用。通过使用 DbConnection对象,您可以
获得一个对 D b T r a n s a c t i o n 变量的引用,具体方法是调用
BeginTransaction()方法,然后将返回值赋给一个DbTransaction变
量。接下来,通过分别在执行成功或失败时调用 Commit()或
Rollback()方法。您可以轻松控制事务的行为。下面的伪代码说
明了如何在一个事务的作用域内执行多个存储过程。

通过提供一组高度可重用的类在数据库执
行操作,EntLib Data Access Block 能让您免于
编写重复性的数据库访问管道代码。
以下Page_Load 代码执行GetEmployeeDetails存储过程,并

   Database db =
     DatabaseFactory.CreateDatabase();
   //Two operations, one to add the order
   //and another to add order details
   string sqlCommand = "InsertOrder";
   DbCommand orderCommand =
   db.GetStoredProcCommand(sqlCommand);

以输出参数的形式返回NationalIDNumber、LoginID和Title col-
umn值。
  <script runat="server">
    void Page_Load(object sender, EventArgs e)
    {
       int employeeID = 1;
       Database db = DatabaseFactory.CreateDatabase();
       string sqlCommand ="GetEmployeeDetails";
       DbCommand dbCommand = db.GetSqlStringCommand
         (sqlCommand);
       dbCommand.CommandType =
         CommandType.StoredProcedure;
       db.AddInParameter(dbCommand,
         "EmployeeID", DbType.Int32, 1);
       db.AddOutParameter(dbCommand, "NationalIDNumber",
          DbType.String, 15);
       db.AddOutParameter(dbCommand, "LoginID",
          DbType.String, 256);
       db.AddOutParameter(dbCommand, "Title",
          DbType.String, 50);
       db.ExecuteNonQuery(dbCommand);
       Response.Write("NationalID : " +
         db.GetParameterValue(dbCommand,
         "NationalIDNumber") + "<br>");
       Response.Write("Login ID : " +
         db.GetParameterValue(dbCommand,
         "LoginID") + "<br>");
       Response.Write("Title : " + db.GetParameterValue(
         dbCommand, "Title") + "<br>");
    }
   </script>

   //Add InsertOrder parameters
   sqlCommand = "InsertOrderDetails";
   DbCommand orderDetailsCommand =
   db.GetStoredProcCommand(sqlCommand);
   //Add InsertOrderDetails parameters
   using (DbConnection connection =
     db.CreateConnection())
   {
     connection.Open();
     DbTransaction transaction =
       connection.BeginTransaction();
     try
     {
       //Execute the InsertOrder
       db.ExecuteNonQuery(orderCommand,
         transaction);
       //Execute the InsertOrderDetails
       db.ExecuteNonQuery(orderDetailsCommand,
         transaction);
       //Commit the transaction
       transaction.Commit();
     }
     catch
     {
       //Roll back the transaction.
       transaction.Rollback();
     }
   }

绝大多数处理工作出现 using块中。这个块使用BeginTransaction
()方法启动事务,并使用Commit()或Rollback()方法提交或回滚

在上面的代码中,您使用了 D b C o m m a n d 对象的

事务。

AddOutParameter()方法来添加输出参数。在执行存储过程之后,
您只要使用 DbCommand 对象的GetParameterValue()方法来获取
输出参数即可。

结束语
通过本文您了解到,通过提供一组高度可重用的类在数据
库执行操作,EntLib Data Access Block 能让您免于编写重复性

用于执行多次更新的事务代码块
有时候,您不仅想在一个数据库上执行多项操作,而且希
望能在一个事务的作用域内执行它们。EntLib Data Access Block

112 程序员

的数据库访问管道代码。通过这些类的使用,您可以根除应用
程序中的误差、bug和打字错误,并把主要精力放在应用程序的
核心业务逻辑上,从而提高工作效率。

>>>  数据库

本文内容来自于胡百敬即将出版的最新著作《SQL Server 2005
数据库开发详解》,这是国内第一本全面、深入分析 SQL Server数据
库开发和管理的原创著作。

迈向大型数据库
□ 文 / 胡百敬

  从笔者 15年前跑单帮,一个人接小案子编写学

图再攀高峰。期待一扫一般市场上对数据库产品的品牌认知。

校学籍成绩数据库、机构法人的会员数据库到如今规划跨国企

工欲善其事,必先利其器。我们从 SQL Server 2005 提供

业集团的数据仓库,数据库技术随着软硬件飞快成长,从十几

的做大型数据库的产品特征来谈,或许可以让你知道向大型数

Mega 已经膨胀到数十 Tera,膨胀了百万倍。数据是企业营运的

据库蜕变的需求。

资产,是决策品质的关键,随着网络、人机界面、多媒体、串
接集成技术的发展和成熟,各公司团体都将轻易地累积大量数
据。所以如何有效、妥善地处理数据将是IT人员要深思的问题。

化繁为简,开发管理界面一致化
数据库的功能与开发越来越多样化,学习曲线随之陡峭。我

数据库系统要可大可久,规划设计至为重要。Sizing rule 为

们需要更一致的学习与使用经验。SQL Server将多项管理工作集

何?如何取舍需求?如何分区数据存放?如何兼具安全性、
可扩

成到以 Visual Studio 2005 为基础的”SQL Server Management

充性、
稳定性?灾难复原计划为何?人员教育训练计划为何?不

Studio”。以往的”SQL Server Enterprise Manager”、
“分析管理员”、

要随意开始,一旦累积数据,撰写了成千上万程序代码访问既定
的数据结构,届时要再修改以强化前述的各方面就为时已晚了。
在设计数据库时,从细节做起,注意每个字段数据格式的
精准,2字节整数够用,就不要用4 字节整数。常查询的字段要

“SQL Query Analyzer”、“MDX Sample Application”

“报表管理
员”等工具一起整合到新的“SQL Server Management Studio”内,
并提供更广泛而深入的报表,显示数据库当下各方面的信息。
程序设计师与数据库管理师只需要熟悉一个界面,就可以

建索引。除了三阶正规划外,为了性能数据表要横向或纵向分

管理并测试所有相关的功能。
并在该工具提供方案管理的能力,

区,或是为了有效查询做反正规划。访问数据表时,要通过存

以项目管理T-SQL、MDX、DMX、XML/A等语言编写的各Script

储过程(Stored Procedure)、视图(View)或自定义函数(User De-

档,提供一致的编辑、访问、执行、测试环境。

fined Function)而不要直接访问数据表。在设计阶段模拟数据,

除了程序开发可以用 Visual Studio 2005 外,转换数据的

掌握使用方式做压力测试等等,诸多细节上深思熟虑的规划设

SSIS、报表设计的 Report Designer、Report Builder 所需的 Report

计,才是大型数据库的成功关键。而这都是以训练有素的专业

Model、Analysis Service 的 Cube、Dimension、Mining Model之设

人员,协作无间的团队默契为基础,好的产品仅提供了舞台。

计与测试等,都可以在 Visual Studio 2005 内完成。

10 年前开始接触微软的 SQL Server,一路走来规划设计各

而 Visual Studio 2005新加入的Team System,让软件各生命

种数据库应用,看着它从部门、局部、单一的小系统迈向集团

周期上的各种活动,如:分析、设计、开发、测试、维护等,都

数据仓库,从中小型企业进入大型企业核心系统,不管金融、电

可在 Visual Studio 集成环境内完成,大一统的荣景真让人兴奋。

信、制造、医疗、政府等各大领域,都有将 SQL Server引进关
键系统的成功案例。
SQL Server 从7.0 版脱胎换骨,摆脱Sybase在 Unix 平台设计上
的束缚,开始善用 Windows NT 的核心技术,而在2000 版本时大

引擎强化,更增效率、稳定与安全性
核心引擎是一切的基础,SQL Server 2005大多数的新功能
都与其有关,更新的功能很多,仅稍举数例如下:

放异彩攻城掠地。
2005年10月再次推出了全面性改版的 SQL Server

面对大型信息系统,设计时首重分区。不管是分区用户、分

2005,不管是在引擎核心部分,还是新兴的商业智能领域,都力

区应用程序功能以及分区数据存放等,都需要详加规划。在这

Programmer

113

技术

Technology

数据库 >>>

个版本中SQL Server新增数据分割的功能(Partitioning),加强对
原始超大数据表与索引的数据分区,水平分区数据表与索引,

了程序编写的弹性。
一致化数据库对象与中间层的程序编写模型。将.NET 的

指定个别的数据区块使用不同的文件及文件群组。当用户要访

Common Language Runtime(CLR)直接集成到SQL Server 2005的

问部分数据时,SQL Server 最佳化引擎可以根据数据的实例摆

数据库引擎中,让存储过程、用户自定义函数、触发程序、用

放,找出最佳的执行计划,而不至于大海捞针。

户自定义数据类型以及汇总函数可以通过.NET的语言,如Visual

多人同时访问数据时的事务级别管理,此版新增 Snapshot
隔离级别,让查询数据的用户在其他人也同时更改同一笔记录
时,可以访问该笔记录先前完成事务的版本。此项功能提供多

Basic.NET 或 C# 等等来编写① ,并且直接与 SQL Server 引擎执
行在同一个程序中,以提升运行性能。
应用系统的架构工程师现在有更大的想象空间,让系统分

人同时访问时更大的延伸性。让读取数据的人不影响修改数据

析师和程序设计师等人可以使用相通的分析设计技巧与工具,

的人,修改数据的人不影响读取数据的人。

如对象导向分析设计、程序编写风格、.NET Framework类等,来

备份时,支持映射的备份集合,减轻备份媒体自身损毁所
造成的意外伤害。

延伸 SQL Server 的功能。
由于是数据库引擎内置.NET执行环境,因此若将所有的商

新增在线还原功能,当你用文件群组备份时,可以在复原

业逻辑都搬进到 SQL Server 势必大幅增加服务器的负担,因此

某个数据库时,只要主档完成还原,便可以访问已经复原完成

仍要慎选程序逻辑的执行位置。一般来说若应用与数据适合结

的部分数据,而不必等到数十 Tera 的复原工作完成。

合在一起,例如节省网络来回的负荷,数据与运算需要统整管

SQL Server 2005针对高可获得性(High Availability)提供了

理等,才将程序集成到服务器中。在细心评估后,若觉得放在

与丛集(cluster) 服务器不一样的解决方案
Redundant Database Technology(RDT)。它延
伸log shipping的能力,让主要的SQL Server
实例有问题时 ,自动转换到备援的 S Q L

集成.NET CLR 引擎到 SQL Server 核心,让程序设计师可以
通过自己所熟悉的.NET 语言来开发 SQL Server 内的对象,延伸
了程序编写的弹性。

Server。而它最大的好处是使用一般标准的
电脑硬件和存储装置,不像以往群集解决
方案需要特殊的共享存储组件,因此不会受限于要连接到共用

数据库引擎是最佳的设计,而后才把组件放入到数据库执行,

的存储装置,而让备援系统有距离上的限制。

应用的巧妙存乎一心。

提供在线维护索引,让索引结构通过 DDL 变更的当下,用

另外,在数据库核心编写程序需要格外严谨,毕竟以往若

户依然可以对数据表或群集索引做新增、修改和删除的操作。

前端程序写得不好,在例外状况发生时只会造成几个人的系统

SQL Server 2005可以针对数据定义语言(DDL)创建触发程

有问题,但若在数据库服务器上执行不稳定,或是有安全疑虑,

序,也就是用户执行Create、Alter、Drop、Update Statistics 等语

将会拖累到全部数据库服务器的用户,尤其在大型数据库服务

法时也会启动触发程序。你可以此来做一些管理的记录,限制

器上,可能还有其他系统同时执行,到时连累的是许多其他系

或监控用户所执行的 DDL 语法。

统的用户,因此程序开发者和数据库管理员不可不慎。

有系统地以视图表显示各种元数据管理信息(Metadata)。以
往直接提供系统数据表的方式不再。而查看元数据时,也结合
了用户的权限,让无权使用某些对象的用户在查阅元数据时,

原生支持 XML
现今应用程序在交换数据或存储设置时,大多采用XML格式。在

将看不到这些对象。另外,在此版本新增了一组 sys.dm_开头

以往我们可能将XML数据以文件的方式存放在硬盘目录结构上,然后

的系统视图表,以提供 SQL Server 当下运行的动态数据,让你

把该文件相关的管理信息放入到关系式数据库内。
在操作XML数据时,

可以观察该数据库实例的资源使用状况。

一方面通过SQL查询语法在数据库内找到相关的XML文件;一方面用
程序语言调用DOM(Document Object Model)对象来访问解析XML。

大幅提升可编程的能力

当编写这类程序时,开发人员要同时学习 T-SQL 和 XPath
语言,ADO.NET或其他数据库访问对象以及XML DOM对象类。

集成.NET
集成.NET CLR引擎到SQL Server核心,让程序设计师可以
通过自己所熟悉的.NET 语言来开发SQL Server 内的对象,延伸

114 程序员

若XML 文件数据很大,由于没有索引结构,用DOM解析的性能
往往不佳。同时,备份数据需要既备份数据库内的metadata,又
要备份文件系统上的 XML,而安全管控也更为复杂。

>>>  数据库

由于 ANSI SQL 2003标准的要求,未来关系式数据库皆可
当作XML 格式的数据来源与集中存储的地方。SQL Server 2005

来整理索引也可改成 ALTER INDEX 语法来完成。
上述总总代表着学习 SQL Server各项功能以及T-SQL语法

遵循并延伸该标准,让存放数据的模型可
以延伸到 XML 格式。在数据定义方面新增
XML 数据类型(每笔记录最长 2GB),你可
以用来定义数据字段或是类型变量。该类

程序设计师通过集成在 T-SQL内的 XQuery语法,混合关系式
数据字段与 XML 数据一起显示与维护,前端统一通过 ADO.NET
2.0 访问,让应用程序的开发技术单一且完整。

型除了自动要求符合 XML well form 定义
外,并可通过 XML Schema 验证 XML 数据
的正确性,并通过扩充XPath语言而成的XQuery查询语言来查询

时更一致,而通过T-SQL语法可以更简单,更有效率地完成复

和修改 XML 数据。以XML View 将关系式数据转成XML 层次结

杂的数据处理工作。不会让你在做不同功能时,需要熟悉风格

构的视图方式,并以专属的 XML 索引格式提升查询性能。

完全不同的 DBCC 指令或是存储过程。

以SQL Server 2005当作XML 的存储区,可让两种类型数据
有一致的管理机制,提供相同的备份、还原、安全控管等规范。

SQL Server 2005 Integration Services

以相同的管理工具做到上述工作,简化了系统的架构设计。程

大型数据库往往需要性能好功能多的 ETL 工具辅助,以收

序设计师通过集成在T-SQL内的XQuery 语法,混合关系式数据

集各方数据,并提供数据给各方。SQL Server 2005采用全新设

字段与XML 数据一起显示与维护,前端统一通过ADO.NET 2.0 访

计架构,不再延续前版的DTS功能。工作流程(work flow)与数

问,让应用程序的开发技术单一且完整。

据流程(data flow)分开的运行模式兼具弹性和性能。支持循环
容器,让你可以轻易地在工作流程中设计For/While Loop或For

增强 Transact-SQL
T-SQL 语言一直都是使用SQL Server 服务的基本,若你不熟
悉 T-SQL,那我就不太相信你会使用SQL Server。此版SQL Server
更大幅增加该语言的功能,由于引擎新增了非常多的对象与功

Each Loop等商业逻辑。以管线与临时数据结构重新设计数据转
换流程,这让数据处理的工作负担可以大幅落在SSIS所执行的
机器上,减轻数据库服务器在数据转换工作上的负荷。
全面改革以.NET为主,如集成开发环境,封装设计与编写延

能,例如支持.NET、XML、提供Web Service、通过Broker Services

伸功能等,都基于.NET 相关技术。不管是通过VB.NET来编写工

创建信息导向的数据处理平台、利用 DDL 触发程序或Event No-

作流程的“执行Script工作”
;或数据转换流程内的“Script原件”,

tification 监控、增加证书(Certificate)和加密机制等等,而要与SQL

亦或在封装外部以.NET语言参照SSIS提供的类,
开发集成的应用

Server 沟通时,主要的语言又是T-SQL,自然需在SQL Server 2005

程序。整体的类架构清楚明了,能大幅提升程序化的能力。

加入了大量的T-SQL 语汇,以定义或访问上述的新增功能。

结语

同时T-SQL语言本身也增强了数据处理的能力,例如取得
记录结果排名函数,有 RANK、DENSE_RANK、ROW_NUMBER 和

什么是 SQL Server 2005 整体功能的最佳实现方式?这需要

NTILE等。支持递归数据访问的Common Table Expression(CTE)、

市场的验证和经验的累积,
需要大家审慎地斟酌原有应用程序的

结构化错误处理(TRY……CATCH)、增加新的操作符如 PIVOT、

需求,并搭配组合在新的SQL Server 2005 架构与功能中,不断

UNPIVOT,以编写枢纽分析汇总运算。另外,通过APPLY可以将

试验和实践,相信通过大家的努力,最后一定能实现。

数据表函数(Table Value Function TVF)返回的多笔记录与查询结

¢Ù

ÔÚ.NET¼ ܹ¹ÖУ¬³ÌÐòÓï
ÑÔµÄÑ¡
Ôñ²»ÖØÒª£¬Ö»ÒªÊ¹
ÓÃÄãÏ°¹ßµÄÓï
ÑÔ

果相乘展开,也就是可以在SELECT语法中将每一笔记录的某个

·ç¸ñ¼ ´¿É¡
£²»¹ÜÊÇVisualBasic¡
¢C#ÄËÖÁÓÚÆ äËûµÄÓïÑÔ£¬¶¼¿ÉÒÔÓÃÀ´
׫д

或某些字段值当作参数传给APPLY操作符之后衔接的TVF函数,

SQL Server2005µÄ×é¼ þ¡£

TVF 通过该参数取得的多笔记录返回后,配上 SELECT语法原先

作者简介:

该笔记录所选择的字段,形成多笔记录乘积的结果。
另外,让T-SQL的语法更一致化,以往许多要通过系统存储
过程、DBCC等命令才能完成的工作,现在也能改以CREATE、ALTER、
DROP 等标准语法来完成。例如以往通过sp_addlogin、sp_adduser等系
统存储过程来创建登录帐号和数据库用户,
现今都可以通过标准的
CREATE语法来创建,而修改和删除亦是如此。以往通过DBCC指令

胡百敬,现 任 台 湾 恒 逸 资 讯 有 限 公 司 特 约
培训讲师,台湾微软等多家大型企业技术顾问。
为数据库领域资深专家,专注于.NET 技术、数
据库和商业智能系统的分析设计。是台湾《Run!
PC》等多家 IT 杂志的专栏作家。

Programmer

115

技术

Technology

软件调试 >>>

如何调试 Windows 子系统的
服务器进程(CSRSS.EXE)
□ 文 / 张银奎

 Windows 环境子系统进程(CSRSS.EXE,简称

二个参数是该进程的EPROCESS结构指针;第三个参数指向的是

CSRSS)是Windows 子系统的服务器进程。尽管从 NT4开始,窗

进程的映像名称;第四个参数指向的是包含解释信息的字符串。

口管理(包括屏幕输出、用户输入和消息传递)和 GDI 的主体

使用WinDbg进行内核调试或分析DUMP文件可以观察这些信息。

实现移入到内核(win32k.sys)中,但CSRSS仍然是Windows子

尽管 CSRSS 在Windows 系统中地位重要,但关于它的介绍

系统的灵魂,它监管着系统内运行着的所有Windows进程和线

却如凤毛麟角。就连著名的Windows内幕一书对它的介绍也如

程,每个进程在创建后都要到它这里注册登记后方能运行,退

蜻蜓点水。微软的文档中也从未见过关于 CSRSS原理和设计的

出时也要到此报告注销。除了掌管着各个进程的“生死存亡”,

正式介绍,在MSDN中搜索一下,找到的大多都是与CSRSS有关

CSRSS在桌面管理、终端登录、控制台管理、HardError报告和DOS

的系统故障信息。因此,可以说CSRSS是Windows世界中被“保

虚拟机等方面也起着重要作用。总之,把 CSRSS 称为Windows

密”的最好的模块之一。这种神秘性使得很多 Windows领域的

系统的“大内总管”不算为过。CSRSS 身担如此多的重任,所

老将也不大熟悉 CSRSS 这个名字,更不知道它长什么样,有时

以 Windows 系统真的离不开它,如果尝试强行杀死 CSRSS进程

竟还以为它是病毒呢。不过不管你是否熟悉它,CSRSS 始终在

(使用kill或其它工具),那么系统便会以蓝屏(BSOD,Blue Screen

每一个 Windows 系统(不包括 3.X 或更早的Windows)中运行

Of Death)结束(图 1),

着,而且起着不可替代的作用。
那么是不是真的没有必要了解CSRSS呢?NO,因为其地位
的重要性,要了解某些 Windows 机制(如进程管理、控制台窗
口、用户态调试、HardError等),探索它又变得无法回避。
没有文档,没有代码,如何了解 CSRSS呢?对于这样的难
题,调试跟踪无疑是最佳利刃,然而这也不是件容易的事。
首先,因为CSRSS 是 Windows系统的关键进程,关乎系统
安全之大计,所以缺省状态下,系统是禁止CSRSS被调试的。另
外对于Windows 2000或之前的版本,CSRSS是调试子系统的一
部分,所以如果不启动特别选项,调试对话也是无法建立和工
作的。
其次,不要以为这个大内总管很悠闲,在一个典型的Win-
dows XP 系统中,CSRSS 通常有十几个工作线程在打理着系统

图 1:CSRSS 意 外 退 出 会 导 致 系 统 蓝 屏 终 止 ( BSOD)

的日常工作,虽然它们总共占用的CPU资源通常也就在1~2%
左右,使用pstat 观察一下(表 1),你会发现它们大多都是在忙

从图 1中可以看到,蓝屏的停止码(StopCode)为F4,好时

碌着的,模式切换次数很高,说明它们频繁奔走在内核态和用

髦的代号,
不过在这里的含义是CRITICAL_OBJECT_TERMINATION

户态之间。更严重的是,当我们在调试器调试 CSRSS 时,那么

——“生死攸关的”系统对象被终止!停止码后面括号中是

中断到调试器必然导致 CSRSS 进程被挂起(Windows系统还不

BSOD 的参数,第一个参数‘3’代表被终止的是进程对象;第

允许以线程为单位建立调试会话),
那么它的所有线程也就被挂

116 程序员

>>>  软件调试

使用 G f l a g s 工具,直接执行

表 1 使 用 PSTAT 工 具 观 察 CSRSS 的 各 个 线 程 状 态
tid*

pri

Ctx Swtch

StrtAddr

User Time

Kernel Time

State

gflags/r +20000或者通过图形界面

4d4

15

1624

75B6DCD6

0:00:00.000

0:00:00.040

Wait:LpcReply

选中‘Enable debugging of Win32

4d8
4dc
4e0

13
14
14

23414
243342

75B6DA56
75B441F0
75B437E2

0:00:00.010
0:00:04.346
0:00:00.000

0:00:03.965
0:00:02.343
0:00:00.000

Wait:UserRequest
Wait:LpcReceive
Wait:LpcReceive

Subsystem’(见图 2)。

4ec
4f0
4f4

14
15
15

243133
79992071
8187110

75B441F0
75B69C8A
75B69C8A

0:00:04.516
0:00:00.000
0:00:00.000

0:00:02.113
0:01:00.747
0:01:03.130

Wait:LpcReceive
Wait:UserRequest
Wait:UserRequest

能生效。但由于我们后面的操作还

524
3ec
63c

14
15
15


1120152

75B69C8A
75B619D7
75B693B6

0:00:00.000
0:00:01.381
0:00:00.000

0:00:00.000
0:00:05.497
0:00:00.000

Wait:UserRequest
Wait:UserRequest
Wait:UserRequest

筹安排合适进行重新启动。

bac
ee8
E5c

14
14
14

241767
349
212007

75B441F0
75B619D7
75B441F0

0:00:04.416
0:00:00.090
0:00:03.505

0:00:02.353
0:00:00.050
0:00:01.912

Wait:LpcReceive
Wait:UserRequest
Wait:LpcReceive

ac4
404
cd8

14
14
13

165710
166136
165864

75B441F0
75B441F0
75B441F0

0:00:02.784
0:00:02.874
0:00:03.144

0:00:02.353
0:00:01.922
0:00:01.552

Wait:LpcReceive
Wait:LpcReceive
Wait:LpcReceive

Windows 系统来调试另一个 Win-

908
e6c

14
14

166196
14254

75B441F0
75B441F0

0:00:02.753
0:00:00.140

0:00:01.422
0:00:00.050

Wait:LpcReceive
Wait:LpcReceive

步来做:

* 各 列 的 含 义 :tid,线 程 ID;pri,线 程 的 优 先 级 ;Ctx Switch,模 式 切 换;StrtAddr,起 始 地 址;User Time,
在 用 户 态 运 行 的 时 间 ;Kernel Time, 在 内 核 态 运 行 的 时 间 ;State, 线 程 状 态 。

需要重新启动系统以上改动才

要重新启动系统,所以大家可以统
解决第二个问题的方法是使用
两个 Windows 系统,即使用一个
dows系统中的CSRSS。这需要分两

第一步,使用WinDbg工具在两
个Windows系统间建立内核调试对
话。WinDbg是微软公司的免费调试

起了,于是整个Windows 便如凝固了一样,我们也就无法继续
在上面做任何事了。

工具,可以从微软网站免费下载,链接如下:
http://www.microsoft.com/whdc/devtools/debugging/

Pid(进城ID):4cc;pri(优先级)
:13;Hnd(句柄)
:895;Pf(Page
Fault,内存页交换次数)
:104959;Ws(工作集)
:10980K csrss.exe。
解决第一个问题的方法是通过修改Windows的全局标志来
启用对 CSRSS的调试。全局标志是一个 32位的整数,每一位对
应一个选项。控制CSRSS调试的标志位叫FLG_ENABLE_CSRDEBUG,
其所在位对应的 16进制数是 0x20000。通过以下两种方法之一
可以设置FLG_ENABLE_CSRDEBUG标志(你应该有管理员权限)

直接修改注册表,将如下表键中的GlobalFlag
(REG_DWORD)
值,将其当前值与 0x20000 做或运算。
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control
\Session?Manager

default.mspx
两个 W i n d o w s 系统可以是物理上的两台 P C 上的两个
Windows;或者使用一台电脑利用Virtual PC来安装第二个Win-
d o w s 系统。如果使用两台 P C ,那么可以使用串口线(N u l l
Modem)或1394(FireWire)线建立连接;如果使用Virtual PC,那
么可以利用管道模拟串口连接。对于前一种方法,WinDbg的帮
助文件有非常详细的说明,不再赘述。对于如何使用Virtual PC
或 VMWare 进行内核调试,请参考以下链接中的文章:
http://advdbg.org/blogs/advdbg_system/articles/130.aspx
第二步,在被调试的 Windows 系统(debuggee)中,使用
NTSD 调试 CSRSS。NTSD 是 WinDbg软件包中包含的另一个调试
工具,它支持命令行下工作,还支持通过内核调试会话将输入
和输出定向到另一台机器上,我们正是利用这一功能来在第二
台Windows(debugger)中控制NTSD实现对CSRSS的调试。NTSD
支持复杂的命令行选项,对于我们的用途,其命令行应该为:
   ntsd -d -g -G -o -pd -p <CSRSS 进 程 ID>

-d 表示将输入和输出(通过 DbgPrint)定向到另一个Win-
dows 中的 WinDbg 中;-g 表示忽略被调试进程的初始断点,如
果不加此开关,那么将NTSD附加到 CSRSS进程的第一个breakin
断点会导致被调试系统僵死;-G表示忽略进程终止时的最后一
个断点;-o 表示调试被调试进程启动的子进程;-pd表示调试
器应该自动与被调试进程分离;-p 用来指定被调试进程的进程
图2

ID。注意WinDbg的帮助文件说CSRSS 的进程ID总为-1,这对于

Programmer

117

技术

Technology

软件调试 >>>

Windows 2000 和其后的 Windows 都不再成立。不过因为NTSD
提供了一个简洁的方法,只要使用—选项就是调试 CSRSS。所
以在成功建立内核调试后,只要在被调试机上切换到WinDbg目
录,然后输入 NTSD --。
如果一切顺利,输入NTSD --后,在调试机上应该收到类
似如下的信息,笔者使用的环境是两台机器安装的都是Win-
dows XP(SP1),WinDbg 的版本为 6.6。
*** wait with pending attach

Executable search path is:
ModLoad: 4a680000 4a684000
ModLoad: 77f50000 77ff7000
ModLoad: 75b40000 75b4a000
ModLoad: 75b50000 75b5e000
ModLoad: 75b60000 75ba6000
ModLoad: 77d40000 77dcc000
ModLoad: 77e60000 77f46000
ModLoad: 77c70000 77cb0000
ModLoad: 77dd0000 77e5d000
ModLoad: 78000000 78086000
ModLoad: 75e90000 75f37000

图 3:CSRSS 进 程 显 示 的 LSASS 被 杀 界 面

因是当 CSRSS弹出这个HardError时,系统已经启动了关机程序,
C:\WINDOWS\system32\csrss.exe
C:\WINDOWS\System32\ntdll.dll
C:\WINDOWS\system32\CSRSRV.dll
C:\WINDOWS\system32\basesrv.dll
C:\WINDOWS\system32\winsrv.dll
C:\WINDOWS\system32\USER32.dll
C:\WINDOWS\system32\KERNEL32.dll
C:\WINDOWS\system32\GDI32.dll
C:\WINDOWS\system32\ADVAPI32.dll
C:\WINDOWS\system32\RPCRT4.dll
C:\WINDOWS\System32\sxs.dll

此时我们按 F12 也不能激发调试功能了。
图 4 是CSRSS 显示的另一种界面,当某个应用程序内出现未
处理异常时,
系统的缺省异常处理器
(UnhandledExceptionFilter函数,
位于KERNEL32.DLL)
会通过调用NtRaiseHardError()这个未公开的系
统服务将错误报告给系统,内核服务在通过 LPC 发给 CSRSS,于
是 CSRSS显示出如下这个对话框。触发这个机制的方法就是随便
写一个小程序,内部做个非法操作而且不加任何异常保护。

看到以上信息,说明NTSD已经成功附加(attach)到CSRSS
进程了;NTSD也与调试机上的WinDbg成功建立了连接。上面
的信息是 CSRSS进程中的各个模块:NTDLL.DLL是所有Win-
dows 程序都离不开的系统支持库;CSRSRV.DLL、BASESRV.
DLL和WINSRV.DLL是CSRSS进程用来真正实施系统服务的三

图 4:CSRSS 弹 出 的 应 用 程 序 内 出 现 未 处 理 异 常 错 误 ( Windows 2000)

个服务模块;USER32.DLL 、KERNEL32.DLL 、GDI32.DLL 和

当这个对话框出现时,按下 F12 可以成功将 CSRSS 中断到

ADVAPI32.DLL是Windows子系统模块,包含了大多数文档化

调试器。但是因为 Windows XP下,CSRSS启动 Dr. Watson(华

了的Win32 API的入口;RPCRT4.DLL用来实现远程过程调用;

生医生)来显示 HardError(见面如图 5 所示),所以这个方法只

SXS.DLL用来实现多个版本的 Assembly(DLL)在系统内共存

有在 Windows 2000(或更早)中有效。

(Side-by-Side)。
接下来要解决的一个问题是,
如何将CSRSS中断到调试器?
对于普通的用户态或内核调试,这是个微不足道的问题,但是
对于现在的特别环境,这却有点棘手。在调试机上试图中断,但
这会中断到内核调试模式,不是我们希望的通过WinDbg来控制
NTSD。因为NTSD在被调试机上没有界面,所以在被调试机上也
无法控制命令它把CSRSS 中断。WinDbg 的帮助文件中说,类似
这样的问题应该事先有计划好的方法在被调试进程中产生异常,
这不太容易。最后一种方法是如果CSRSS有用户界面,那么先将
其切换到前台,然后通过按通用的F12热键将其中断到调试器。

图 5:在 Windows XP中 ,CSRSS 会 启 动 Dr. Watson进 程 来 显 示 HardError

CSRSS 还有别的界面么?有。图 6 显示了 CSRSS 的另一种
UI,大家一看便认得了。只要在用光盘安装一个软件的某一步

所以现在的问题是唤出CSRSS的界面,然后将其“擒获”到

时,取出光盘,然后再点继续便可以触发它了。为了不损坏光

调试器。CSRSS有界面么?答案是肯定的。图3所示的窗口就是

驱和光盘,建议大家使用 Virtual PC做这个操作,只要点 File文

CSRSS 弹出的,在冲击波病毒(微软安全公告号MS04-011)猖

件菜单中的Install or Update Virtual Machine Additions启动安装,

獗的那段日子(2004年 4 月)大家可能没少见到这个界面。弹

然后再选 CD菜单中的 Release CD。如果没安装 Virtual PC的话,

出这个界面的方法很简单,只要强行杀掉 LSASS(Local Secu-

请大家谨慎操作,或者不要做这个实验了,后面我们会揭晓比

rity Authority Subsystem Service)进程就可以了。

这更简单的方法。

但是利用这个 CSRSS 界面显然代价太大,而且不可行。原

118 程序员

将图 5所示的对话框切换到前台(有输入焦点),然后按下

>>>  软件调试

F12键。这时观察调试机中的WinDbg,如果出现类似图6所示的

以从其它机器上复制过来(只需要复制前面列出的那些模块的

情形,那么便成功将 CSRSS 进程中断到调试器了。

符号文件就可以了,注意保持目录结构不变)。笔者的做法是从
另一台机器上将WINSRV、CSRSS、CSRSRV等文件的调试符号复
制到被调试机的 C:\Symbols 目录下。
准备好调试符号文件后,需要将其根目录设置给NTSD,这

图 6:CSRSS 显 示 的 缺 盘 通 知

只要在 Input 提示符后输入.sympath c:\symbols 便可以了。然
后需要通过.reload 命令使其生效。

下面仔细看一下图 7 所示的调试界面。首先注意,命令输

接着,再次输入k命令,会发现刚才的警告没有了,而且这

入区与普通的内核调试和用户态调试都不同,Input 提示符专门

次的函数调用序列与刚才的也大相径庭。这次才是正确的结果,

用于表示 WinDbg 在代理另一个调试器的输入。对于我们的情

因为我们按F12 键,Windows 子系统的内核部分接收到此热键,

况,输入到这里的命令会送给另一台机器上的NTSD调试器。另

然后触发了CSRSS中的SrvActivateDebugger服务,
SrvActivateDebugger

一点要说明的是,检查图 7 中的进程 ID(1d0),它应该与被调

检查到要调试的就是自己,便调用DbgBreakPoint 中断到调试器。

试机上的 CSRSS 进程的进程 ID 是一致的。

可见正确设置调试符号对于调试的重要性!
0:010> k

ChildEBP RetAddr
0120fec4 75b7a179 ntdll!DbgBreakPoint
0120fed0 75b44443 winsrv!SrvActivateDebugger+0x1a
0120fff4 00000000 CSRSRV!CsrApiRequestThread+0x253

有了调试符号以后,可以观察到很多 DLL 中没有输出的内
部函数,比如使用 x winsrv!* 可以列出 WINSRV.DLL 中的所有
图 7:CSRSS 被 中 断 到 调 试 器

现在可以尝试输入一些简单的命令了,比如lm列出进程内
的模块(结果与前面的清单类似)
;输入 ̄*可以列出CSRSS进程
内的所有线程。

符号,其中包含了很多负责重要职责的变量和例程,寥举数例:
u

winsrv!SrvExitWindowsEx:Windows子系统退出,关

机使用;
u

winsrv!ConsoleInputThread:控制台窗口的输入线

但是此时,还有一个问题要解决,就是调试符号。注意图

程,如果使用线程控制命令将其挂起~<线程序号> n(先使用

7 中有一行 ERROR信息,这是 WinDbg在提醒我们没有找到合适

 ̄* 列出所有线程,通常有2个这样的线程),那么控制台窗口就

的调试符号。

不响应了,移动也不能;

输入 k 命令显示函数调用栈,也会得到与此相关的警告:
ChildEBP RetAddr
WARNING: Stack unwind information not available. Following frames
may be wrong.
0120fed0 75b44443 ntdll!DbgBreakPoint
0120fff4 00000000 CSRSRV!CsrValidateMessageString+0x3d3

u

winsrv!UserHardError:用来弹出HardError的函数,通

常调用winsrv!UserHardErrorEx,再使用winsrv!MessageBoxTimeoutW
真正弹出对话框;
u

winsrv!HandleMouseEvent:处理控制台窗口的鼠标输入。

看到这里大家是否发现什么了呢?既然控制台窗口的输入

如何设置调试符号呢?对于普通的情况,WinDbg的文档中有比

直接与CSRSS进程相关,那么当控制台窗口在前台时,按F12热

较详细的介绍。但我们现在要做的是在WinDbg的代理输入中为NTSD

键能否将 CSRSS 进程中断到调试器呢?答案是肯定的,而且这

设置调试符号,WinDbg 的文档中没有关于此的介绍。尝试通过!

是最方便的方法。

symfix 命令自动设置微软的调试符号服务器,会得到如下错误:
0:010> !symfix
!symfix
Network paths are disallowed, symbol server is not available.
Set your symbol path to a symbol tree on the local machine.

试图设置从局域网上映射的驱动器,也会得到这种“不允
许网络路径”的错误警告。看来只能在本地安装符号文件了。可
以选择从微软的网站上免费下载你所需版本的调试符号,也可

最后要说明的是,CSRSS 代表的是 Client/Server Runtime
Server Subsystem,即客户 / 服务器(运行时)子系统:相对于
Windows子系统中的所有普通进程来说,CSRSS进程是服务器进
程,其它进程是客户;在 CSRSS进程内部,WINSRV、CSRSRV和
BASESRV 是三个重要的服务模块,这些服务的调用者是客户;
对于其它子系统,Windows子系统在 Windows中也有着不可缺
少的服务器身份……

Programmer

119

技术

Technology

智慧擂台 >>>

移动内存算法
□ 文 / 刘鑫

本期的问题是:
对于有 K个元素的数组int a[K]={....};写一个高效算法将
数组内容循环左移 m 位
比如:int a[6] ={1,2,3,4,5,6},循环左移 3 位得到结果

<m,定义 i1=((k-m)+i0)%k,i2=((k-m) + i1)%k……ix =
((k-m) + ix-1)%k。当 ix=i0 时循环终止。此时有i0 = ix =
((k-m) + ix-1)%k = ……=(x(k-m)+i0)%k。
因为我们知道 0=<i0<m,所以有 0 = x(k-m)%k,也就

{456123},

是说,x(k-m) = yk,因为我们是遇到第一个x(k-m) = yk就

要求:

终止,显然等号左右的值就是 k-m 和 k 的最小公倍数。根据数

1.不允许另外申请数组空间,但可以申请少许变量;

论知识,我们知道,k,m,k-m 这三个数有最大公约数 q,使

2.不允许采用每次左移。

得 k=aq,m=bq,k-m=cq,a,b,c 三个数两两互质。进而推出
x = a,y = c。也就是说,这个递归过程会经历 a 步。如果 k

这是一个有趣的问题,有朋友给出过一个很简单的解法:

和 m互质,a=k,递归过程会遍历整个区间。那么,它可以完成

1.将整个数组倒排;

对整个区间的移动操作。而如果k 和 m的最大公约数q>1呢?

2.将前 k-m 个元素和剩下的 m 个元素分别倒排。

在这里有一个现象,任意两个 i,它们的差要么是 0,要么是 k

这个算法需要对每个数组元素做两次写操作,具体而言是

和 m 的最大公因是 q 的整倍数。有兴趣的朋友可以尝试证明一

2n 次堆变量写操作和 n 次栈变量写操作(因为倒排时调用交换

下。因为我们知道整个过程一共 a 步,k=aq,那么,i到 ix 的序

算法需要一个中间变量),有没有一种方法,只对数组元素进行

列会形成一个步长为q 的等差序列。所以,我们要移动整个0到

一次写操作就完成移动?

k-1 区间,应该对 0 到 q-1 的元素应用这个递归算法。

最直观的想法,就是从第一个元素开始,把它一步移动到

这样的算法只需要一次堆变量写操作,但是因为需要一个

最终的目的位置,而该位置原有的元素的值取出,移动到它的

中间变量储存移动的元素,需要2n 次栈变量写操作。再加上计

新位置。递归进行这个步骤。

算目的地址,每次移动时所需的计算量略大于两次倒排,但是

首先,我们在数学上很容易理解,这是一个一一对应的映
射,绝不会在一个位置上出现两次移动。所以不会出现移动的
递归过程中途指向了已经移动过的元素。
那么,这个递归过程唯一的终止条件就是,当前移动的元
素,目的位置是移动过程的起始位置。
有兴趣的朋友不妨在纸上推演一下这个过程,并不复杂。

在堆变量操作方面提高了效率。
本次大部分合格的参赛作品都采用了冒泡算法,
通过两两交
换邻接元素来移动数组。
有朋友还在来信中说明冒泡排序是线性
复杂度。这是错误的。冒泡法是 o(n2)的,比起前面两种算法,冒
泡的效率太过低下。很多朋友在m大于或小于k/2 时采用的不同
的左 / 右位移代码,其实只要理清了算法,不必要做此判断。只

多试验几种组合,细心的朋友也许会发现,这个递归过程有时

有一位ID为njwind 的朋友想到了利用数论知识。虽然他的代码还

候可以遍历整个数组,有时候则会跳过若干元素。这其中有没

达不到实用标准,但是这应该是本次比赛最好的作品了:

有什么规律?
如果按照元素的索引下标标示元素,0到k-1中的任意元素

#include <stdio.h>
#include <stdlib.h>
#define Len 6

i,会移动到什么位置?
如果 i小于 m,它会移动到k-m+i,否则,它的新位置是i-
m。这个过程其实可以统一在一个算式下:
对于任意的 i,它的新位置 i' = ((k - m) + i )%k。
那么,我们可以定义这个循环链:取整数 i0,使得 0=<i0

120 程序员

/* 求 最 大 公 约 数 的 函 数  */
int CommonFactor(int m,int n){
  int tmp;
  if(m<n)  {
      tmp = m; m = n; n = tmp;
  }
  tmp = m % n;

>>>  智慧擂台
  while(tmp != 0) {
    m = n;  n = tmp;  tmp = m % n;
  }
  return n;

void display(int *pa){
   int i;
   printf("array: ");
   for(i=0;i<Len; i++)    printf("%d ",pa[i]);
   printf("\n");

void swap(int *n1, int *n2){
    int tmp;
    tmp = *n1;  *n1 = *n2;  *n2 = tmp;

/* *p 数 据 指 针 , aLen: 数 据 长 度 , k: 左 循 环 位 数  */
void LeftRotation(int *p, int aLen, int k){
   int i,tmp,factor;
   k = k % aLen;
   if ( k == 0) return;
   k = aLen - k;
   factor = CommonFactor(aLen, k);
   if (factor == 1){
     i = 0;
     do{
         i = (i+k)%aLen;
         swap(p, p + i ) ;
     } while(i != 0);
   }
   else {
       for (i = 0;i < factor; i++){
         tmp = i;
         do{
             tmp = (tmp+k)%aLen;
             swap(&p[i], p + tmp ) ;
         } while(tmp != i);
       }
   }

int main(int argc, char *argv[]) {
  int i,k,a[Len]={1,2,3,4,5,6};
  for(i=0;i<8;i++){
      for( k = 0; k<Len ;k++)  /* 数 组 赋 值  */
         a[k] = k+1;
      k = i;  display(a);
      printf("Len: %d, left rotation: %d\n",Len,k);
      LeftRotation(a,Len,k);
      display(a);   printf("---------------\n");
 }
  system("PAUSE");  return 0;

以下是用 C++ 实现的一次移动算法代码,并进行了泛化,

template<typename T,typename U>
void Carry(T point[], const U & len, const U & m){
    U start = 0,p = 0;
    T pv;
    U hloc = HCF(len, m);
    U step = len - m;
    for (U i = 0; i<hloc; i++) {
        p = i; start = p; pv = point[p] ;
        do {
            p = (step+p)%len;
            std::swap(point[p] , pv);
        }while(p != start);
    }
};

用迭代器实现的区间移动,可以应用于 STL 容器等场合:
template<typename iterT,typename U>
void Carry(iterT &iter, const U & len, const U & m) {
    iterT nb = iter + (len-m);
    iterT p;
    iterT start = point;
    iterT pm = point + m;
    iterator_traits<iterT>::value_type pv;
    U hloc = HCF(len, m);
    for (U i = 0; i<hloc; i++) {
        p = point + i;
        start = p; pv = *p ;
        do {
            if (p < pm)
                p = nb + (p - point);
            else
                p -= m;
            std::swap(*p , pv);
        }while(p != start);
    }
};

代码中使用了 std::swap 函数来交换变量值,这个函数在
<algorithm>中。另外为了析取迭代器的值,我使用了<iterator>
中的iterator_traits操作。有兴趣的朋友不妨编写一个适用于普通
指针的偏特化版本。
两步倒排算法的实现很简单,在这里就不写出来了。重点
是采用一个足够简单的交换和计算中界的代码。这样的功能,C
风格的代码就可以做到足够好了。
有些朋友认为直接改变索引就可以重排数组,对于某些高
级语言,例如 Python中的内置线性容器list,这是可以的。但是

使之可以适用于不同的类型,包括用不同整型变量表示k,m等

在C/C++中,数组和链表是不同的概念,数组是内存堆中的连

参数的应用:

续块,不可以用这种方法来对待。对于C/C++程序,我们经常

求最大公因数,辗转相除,可以应用于任何求最大公因式/
数的场合,只要参数类型支持求余和赋值:
template<typename intT>
intT HCF(const intT & x, const intT & y) {
    intT a = x, b = y, r = a%b;
    while(r != 0) {
        a = b; b = r; r = a%b;
    }
    return b;
};

要直接操作内存,要关注算法的复杂度,这并不是缺点,相反,
无论高级的虚拟机语言有多少好处,总需要有底层的技术来管
理内存,用尽可能高效的算法处理面向硬件的问题。否则,用
什么来开发虚拟机呢?这个算法问题实际上在内存管理,例如
虚拟机的实现方面,就有很大意义。在虚拟机内存管理中,我
们面对的总是不够快的 CPU和不够大的内存,需要有一个高效
的算法来移动虚拟机管理的数据。对于Java或 C#程序员,这
个过程通常是透明的,但是这不表示它不存在。而默默支撑起

区间移动,支持任何类型的数组:

虚拟机的,正是这些 C/C++ 代码。

Programmer

121

>>> SUN 征文

特性并把这个构件放到一个特定的地方,

(4)BoxLayout2 布局管理器:它是

持以上2款IDE的全部功能;4种编译器及各

这个构件就不仅仅会收到一个位置协调的

Swing 标准包中javax.swing.BoxLayout 布

自特有的编译选项:Borland Make、Borland

消息,并且会记住为什么它会被抓取。例

局管理器的一个包裹类,允许你通过查

Make(JB8)
、Project javac、javac;智能单步、

如,如果它被抓取同另外一个构件的左边

看器的选择,间接使用BoxLayout的功能。

智能源码、智能交换;多线程调试;内置混

对齐,这个时候该构件会始终保持它们的

BoxLayout 将几个组件组合在一起,以水

淆打包;JBuilder的调试环境可谓傲视群伦,

左对齐格式,即使它们的绝对位置发生了

平或者垂直的方式排列,窗口大小调整

开发纯java 程序时,使用起来十分方便。

改变。

时,组件大小不会随着改变。

NetBeans中有双路编辑——使用一个可

(5)OverLayOut2 布局管理器:它是

视化设计器和一个文本编辑器。一些可视化

Swing 标准包中 java.swing.OverLayout 布

设计器已经实现了这种方式。但是NetBeans

局管理的包裹类,允许你通过察看器的

IDE使用保护模块来防止用户编辑代码。

选择,间接使用 OverLayout 的功能。

三.WEB 与 J2EE 开发
JSP、Servlet
NetBeans支持Servlet 2.4和JSP 2.0。
支持使用 Tomcat 5 部署和调试两层 J2EE

Eclipse的 Visual Editor

GUI 小结

1.4 和 1.3 应用程序。以下是 NetBeans 为

Visual Editor是一个开源的 Eclipse 编

GUI设计部分,我更喜欢NetBeans,相

Web应用程序开发提供的便利:内置Tomcat

辑器。它同 JDT、PDE 等其它 Eclipse 的工

信很多用户也跟我一样,因为用起来真

服务器支持;生成和维护部署容易的内

具项目一样,是一个全新的Eclipse工具项

的很方便。

容,包括添加到项目中的 Servlets进行注

目。它可以进行可视化的编辑Java GUI程

曾看见有人说,在拖拽组件时,却不

序,也能编辑可视化的Java Bean组件。它

能更改代码,觉得很别扭。其实我觉得受

打包、部署指令的Ant 脚本。该脚本使开

能与 Eclipse的Java Editor集成在一起,当

保护的双路编辑才是应该推崇的方法,

发者无需手动将文件移动到服务器;用

在 Visual Editor中编辑图形界面时,会立

这也是对 IDE完美工作的一种保证。

于编辑 Servlets、JSP、HTML 和标签库的

即反馈到 Java Editor中的代码,反之亦
然,即无保护的双路编辑。
Visual Editor支持Swing 和AWT的可视

册;生成与维护具有编译、清除、测试、

代码自动完成和帮助;提供“编译JSP”命

二.编译、运行、调试、打包
本节将比较三个平台在编译、运行、

令,使用这一命令可以帮助开发者在部
署前检测JSP 文件的错误,不管这些错误

Java组件开发。由于这个Framework设计的

调试、打包几个必要开发步骤中的具体

出现在编译过程中还是 J S P 文件向

具有通用性,它也可以很容易的实现C++

表现。

Servlets 转换过程中;提供全面的调试支

或其它语言下可视化开发。其将来的版本
(从 1.0 开始),将会支持SWT的开发。

NetBeans
在代码行开头点击即可设置 / 取消

持,包括“步进JSP 文件”以及“跟踪HTTP
请求”;大量的 Web 模板:JSP、Servlet、

Visual Editor目前支持所有的传统的

断点;支持条件断点、单步执行等流程控

Filter、Web应用侦听器、标签库描述、标

布局管理器。另外,SWT Designer也是流

制功能;支持局部变量、监视、堆栈显示等

签、标签处理、Web Service、消息处理、

行的 GUI 编辑器,不过是收费的。

功能;支持会话、线程的查看及修改;提

Web客户端等;描述文件web.xml可视化

JBuilder 的布局管理器

供了完善的远程调试功能;基于Ant,可

编辑器;监测 HTTP 事务处理。

除了经典的布局管理器外,JBuilder

通过脚本支持调试。

提供了五个方便的布局管理器,它们是:
(1)XYLayout 布局管理器:组件所在

E c l i p s e 在不安装 L O M B O Z 或者
MyEclipse 的情况下编写 Web 应用程序真

Eclipse

是麻烦之极。首先你需要手动安装Tomcat

的位置通过相对于左上角坐标确定,其大

带有专用的 D e b u g 视图并能自动切

或者其他服务器,然后在Eclipse 中配置;

小通过宽度和长度确定,当窗口大小发生

换;其Debug 的功能和Delphi 的Debug比较

接下来编写代码,再更改web.xml文件做

变化时,组件的位置和大小保持原位。

相似,Inspect 、Watch等应有尽有;支持反

部署。最后很可能因为配置不好的原因,

(2)PaneLayout 布局管理器:通过百

汇编、内存、堆栈、寄存器显示等高级功

无法启动或者部署Web服务器。好在对web

分比规定组件所占容器空间,当用户界

能;支持会话、线程的查看及修改;似乎

.xml编辑时也是可视化的。

面调整时,组件的大小也会相应调整。

无远程调试;可根据模块的需求扩展。

(3)VerticalFlowLayout 布局管理器:
它和FlowLayout 类似,只不过它以垂直而
非水平的方式排列组件。

JBuilder一体化的解决办法倒是很好,
并且通过 OpenTools 框架支持很多种Web

JBuilder
高度集成,十分丰富的调试环境,支

服务器。当然也需要手动安装这些服务
器,并且添加这些服务器的 Lib到你的项

Programmer

123

Product & Application

产品&应用
SUN 征文 >>>

目中。JBuilder还为各种部署文件提供了

应用服务;能够利用强大的Java调试器调

方便的编辑工具:

混淆的级别越高,混淆的力度就越大。

试正在运行的服务器端代码(JSP&EJB)

Mobility Pack提供了可视化用户界面

l web.xml:Web Module DD Editor

通过使用 Wizard 和代码生成器提高开发

设计器,开发者可以用鼠标拖拽的方式

l struts-config.xml:Struts Config Editor

效率;创建Web服务客户端的WSDL形式

设计应用程序的用户界面,通过流程控

l faces-config.xml:Faces Config Editor

的文件。

制器实现界面之间的跳转,而不用编写

另外JBuilder也对Jsp和Servlet提供监
听器,监视各种事件的发生。
JBuilder 提供了最为完善的Web 开发
环境,其次 Netbeans 功能也十分丰富。

L o m b o z 适用的服务器有:Apache

任何代码。无线连接向导是Mobility Pack

Tomcat,JBOSS,JOnAS,Resin,Orion,JRun,

另一新特性,能方便快速的开发出端到

Oracle IAS,BEA WebLogic Server和 IBM

端的企业级应用程序,服务器端只提供

WebSphere 等。

需要导出的服务类,Netbeans IDE会自动
生成服务器端的 Servlet 以及客户端用于

EJB/J2EE

三种平台对框架的支持比较

连接网络的代码。虽然上述两个功能使

NetBeans
从 N e t B e a n s   I D E   4 . 1 版本开始 ,
NetBeans 提供创建和编辑 EJB 丰富的向导

框架名称

NetBeans 5.5

Eclipse 3.x

JBuilder 2005

Struts
Hibernate

支持,向导,文档丰富
Nbxdoclet 支 持 , 5.5 加
入数据库结构和实体类

MyEclipse 良 好 支 持
Hibernate Syn 支 持

支持,向导,文档丰富
手动配置

和编辑器。
NetBeans 5.0提供以下针对企业开发
的支持:建立和编辑EJB的可视化编辑器;
控制 CMP 和实体 Bean 关系的可视化编辑

Spring

的相互生成和向导
支持,向导,文档丰富

Spring plugin 4 Eclipse

手动配置
Spring for JBuilder2005 OpenTools

Cocoon
JSF

暂没找到直接支持
支持,向导,文档丰富

Lepido 支 持
JSF Tool Project 支 持

支持,向导,文档丰富
支持,向导,文档丰富

器;通过鼠标点击就可以在Web模块中加

用起来非常方便,但是缺乏灵活性,你很

小 结

入对 EJB 的调用;完整的组装、部署、运
行和调试企业应用程序的支持;注册和

对于J2EE 开发,Eclipse 的各种支持是

测试Web Service;通过鼠标点击就可以在

对全面和及时的,但是否成熟,则未必。并

Web模块或EJB中加入对Web Service的调

且开发者经常被成堆的插件弄得头昏脑胀。

难再更改开发工具为你自动生成的代码。

Eclipse 和 EclipseME
不仅要下载安装 EclipseME插件,还

用;由EJB或者Java类自底向上的建立Web

NetBeans的最新版本提供了对最新标

要安装 WTK,并且在 Eclipse环境中配置。

Service;由WSDL文件自顶向下的建立Web

准,如EJB 3.0 的支持,并且内置对常见

使用 E c l i p s e 搭建 J 2 M E 的开发环境比

Service;可以导入其他 IDE的J2EE项目,前

框架支持。这说明,现在完全能够全面转

Netbeans IDE 稍显复杂。事实上,管理

提是其与 BluePrints标准兼容。

向 NetBeans。

Eclipse 的各种插件已经让开发者头疼不
已,有些插件的更新还很难保证。

Eclipse与 Lomboz
Lomboz 是Eclipse 的一个主要的开源插
件(open-source plug-in),Lomboz 插件能

四.J2ME 开发
NetBeans Mobility

JBuilder 和 WTK

Netbeans IDE和 Mobility Pack 提供的

从JBuilder 9版本开始,Borland将WTK

够使Java开发者更好的使用Eclipse去创建,

项目管理功能非常出色,将目标平台、应

直接集成到了开发工具内。如果使用以

调试和部署基于J2EE的 Java应用服务器。

用程序描述符、编译运行、混淆、签名等

前版本的 J B u i l d e r,那么需要首先安装

Lomboz 的主要功能有:使用 HTML,

功能集成在了一起。开发者只需要选中

MoblieSet 插件。

Servlets,JSP 等方式建立 Web 应用程序;

项目,右键选择属性即可配置上述选项。

J S P 的编辑带有高亮显示和编码助手、

值得注意的一点是,当项目中使用了图

JSP 语法检查;利用Wizard创建Web应用、

片或者媒体文件等资源的时候,应该在

其实,各种开发工具只是以自己的

EJB 应用和 EJB 客户端测试程序;支持部

“库和资源”选项中讲资源文件所在的文

方式对 M I D P 应用程序的开发进行了封

署 EAR、WAR和 JAR;利用xDoclet 开发符

件夹添加到“捆绑的库和资源”中。避免

装, MIDP应用程序的开发流程都是一样。

合 EJB 1.1、2.0和 3.0的应用;能够实现

在 Java 程序中访问资源的时候抛出空指

事实已经证明,除了使用手机供应商自

端口对端口的本地和远程的测试应用服

针异常。Mobility Pack 还直接集成了

己的套件外(如 Nokia Toolkit),WTK 和

务;能够支持所有的有可扩展定义的Java

Proguard 混淆器,可以设置混淆的级别,

NetBeans Mobility的用户最多——这方面

124 程序员

小 结

Product & Application

产品&应用
工具点评  >>>

增的图形共有:Class Diagram、Composite
Structure Diagram、Component Diagram、

高手过招,各有千秋

Deployment Diagram、Use Case Diagram、
Activity Diagram、State Machine Diagram、
Sequence Diagram 以及 Communication
Diagram 等九张图。比较起 UML 2.0的规

—— UML 工具比较分析

格所制订的十三张图,分别少了 Object
Diagram、Package Diagram 、Interaction
Overview Diagram 以及 Timing Diagram 四

□ 文 /Ringle

张图。
不过如果我们详细观察 UML 2.0 的

“工欲善其事,必先利其
器”,学习UML没有好的工具帮忙,往往

对!不要怀疑,这三个产品的价格
的差距大约是 20 倍。

gram 与Package Diagram的基本Diagram其
实就是 Class Diagram,只是在这两张图

会让开发者半途而废,甚至会因为不易
使用的开发工具,而误认为 UML是一个

规则,我们就可以发现,其实Object Dia-

对 UML 2.0 的支持分析

中,其分别表达了 Package间的相依关系

非常困难学习的“技术”。殊不知UML只

图 1 是 OMG 所定义的 UML 十三张图

是一种“语言”,就和学习中文、英语一

的分类(参考自Unified Modeling Language:

我们可以使用 Class Diagram 来绘制这两

样,学习 UML并不困难,只要了解UML

Superstructure, Version 2, p. 660)。

张图形。

的语法以及知道 UML 的适用时机,UML
自然手到擒来。当然,如果有一套容易
上手的 UML 开发工具,学习 UML的困难
度更是大幅降低。
在本文中,我们将评比三个不同的

以下,我们将针对上述的三个软件,
分别说明其对于UML 2.0 规范的支持。

以及Object 之间的关系。因此,在RSA中,

至于 Interaction Overview Diagram 也
是类似的状况,在UML 2.0的规则中,其

IBM 的RSA:与Borland Together都是

基本的图形是Activity Diagram,因此,我

建构在Eclipse平台上,必须要先建立一个

们同样也可以利用 Activity Diagram 来绘

UML 2.0 的项目,才能绘制 UML 的图形。

制 Interaction Overview Diagram。至于时

UML工具——IBM公司的Rational Software

序图,虽然在 RSA 中的 Communication

Architect(以下简称 RSA)、Borland 公司的

Diagram 可以表达时序图中的LifeLine,但

Together Architect(以下简称Together)以及

是其余的相关的 UML 组件都缺乏,因此,

Sparx Systems 公司的 Enterprise Architect

RSA 并无法完整表达时序图。

Corporation Edition(以下简称EA)。评比的

因此要在 RSA 中绘制完整的十三张
UML 2.0规范图,还是比较困难的,开发

标准会从以下两个面向来分别评估:

人员必须要很清楚地知道这十三张图各

l 对 UML 2.0 的支持;
l 文件产生机制

图 2:RSA 的 UML 2.0 项 目 操 作 画 面

整篇文章中,我们会分成两大部分,
针对这三套软件在上述两方面的操作进

和 Eclipse 的操

行说明,并且在每一个部分的最后,都会

作相类似,在RSA的

用表格对三个软件进行综合评比。开始

操作画面中,左边是

介绍之前,先就价钱做个评比说明,根据

项目区,右边则是所

三家公司的产品标准售价,其价格的比

有可以使用的工具

较表如表 1:

区。在RSA中可以新
表 1: 三 套 软 件 的 价 格 表

公司

产品

IBM
Rational Software Architect
Borland
Together for Eclipse Architect Edition
Sparx Systems Enterprise Architect Corporate Edition

126 程序员

价 格 (美 元 )
5500
5000
239

图 1:UML 2.0 规 范 的

>>> 工具点评

自特性,才能找到适当的图形进行绘制。

则无法绘制。

大的不同。因为它本身是一个独立的程

在 R S A 中,开发人员可以轻松地将

大体上,Borland Together在UML 2.0

序,其操作方式不会受到其他影响。在整

Sequence Diagram 转成 Communication

的支持上主要是缺少了上述的两张图;

个开发环境中,右方是工具区,左方则是

Diagram,反之亦然。延续了之前Rose的特

实际的操作上,Borland Together延续了以

整个 P r o j e c t 相关的各种不同的界面

性,可以说是RSA中最让人赞赏的部分。

往 Together 的操作方式,对 Together 的老

(View)。所有的 U M L 图形将会放置在

用户来说,不会有太大的困扰。

Project View 中。和Together类似的,当指

最后是 MDA 的机制,在 RSA 中提供
三种转换机制,分别是UML →Java、UML

此外,Together在Sequence Diagram与

定到一个特定 Type的Diagram 时,左方的

→ C++、UML → EJB,由于 RSA是建置在

Communication Diagram的互转上,提供一

Toolbox 会停留在该 Diagram 对应的 Pallet

Eclipse 上,因此,其转换为Java或EJB时,

个很有趣的机制,你可以根据一张相同

上,这在操作上是非常方便的。

能够非常顺畅地跟Eclipse的Java或是J2EE

的Interaction Diagram,指定利用“Sequence

项目结合,这也是 RSA 一向的强项。

Diagram”或“Communication Diagram”来
表现,这个想法非常有趣,也说明了这两

Borland 的 Together:跟 RSA相同,

张图是同一个事物的不同形式。

在 Borland Together 中要新增 UML 2.0 的

至于根据 UML 产生 Source Code,则

Diagram,也必须要在 Eclipse 的环境中新

必须要采用不同的项目。如果要产生Java

增一个 UML 2.0 的项目。

的代码,必须选用“Java Modeling”项目,
当你在该项目中建立Class时,Together都
图 4:EA 的 操 作 画 面

会自动产生一个Java Class,当该Class的
属性或是操作有所变动时,会立刻反映
到程序中。这和TogetherJ是完全相同的。

图 3:Borland Together 的 操 作 画 面

图 4 中央对话框为 EA 支持的 U M L
2.0 的Diagram 。除了RSA 及Together 支

此外,T o g e t h e r 仍然保有过去

持的九张 Diagram 外,EA 也支持其余四

TogetherJ 的重要功能,也就是可以利用

张 D i a g r a m ;另外,还支持非标准的

Sequence Diagram 产生 Implement 的代码,

Analysis Diagram 。因此,若单从对UML

相同地,也可以由代码反转回 Sequence

2.0 的 支 持 来 说 ,E A 算 是 最 完 整 的

Diagram。这算是Together 的一大特点,也

工具。

是它与其它两个产品竞争的最大优势。
跟RSA不同,Borland Together操作界

对Sequence Diagram与Communication
Diagram 的转换,EA 没有提供任何功能,

面与先前的版本类似。针对每一张不同

Sparx Systems 的 E A 是这三个软

这算是 EA中比较弱的一环。对于MDA的

类型的UML Diagram,可以使用的工具都

件中最轻薄的。采用了Stand Alone的AP,

支持。EA 做得非常弹性,开发者可以利

不同,如图3右方的“Pallets”绘图模版。

安装时不需要先安装 JRE 及Eclipse。在其

用Script语法自行定义Transformation Rule。

另外跟 RSA 类似的是在 Borland Together

中绘制UML Diagram也相对简单。只要在

在 EA 中提供 C#、EJB、Java、DDL、XSD

中,同样地也只支持 UML 2.0 中的九张

EA 中新增一个项目,其自然就会把所有

以及 Web Service 等标准的转换机制,开

图( 如图 3 左红色方框部分) ,P a c k a g e

UML Diagram 要绘制的相关环境准备好。

发者可以将同一个 PIM的Model转换为各

Diagram、Object Diagram、Interaction Over-

EA 的操作和前面的两个软件有相当

种不同平台的 PSM Model。

view Diagram 以及 Timing Diagram都不能
表 2:对 UML 2.0 的 支 持 分 析

直接由 Borland Together 中选取。
如前文所说,Package Diagram 以及

项目

RSA

对 UML 2.0 十 三 张 Diagram 的 支 持

不 支 持 Timing Diagram 不 支 持 T i m i n g
Diagram、Interaction

Sequence Diagram与 Communication
Diagram 的 互 转 机 制
MDA 机 制

提供

Overview  Diagram
提供

不提供


两种


两种


九种
没有

Object Diagram 都可以使用 Class Diagram
来绘制,相同地,在Borland Together中你
也可以利用 Class Diagram 来绘制这两张
图。至于 Interaction Overview Diagram 以
及 Timing Diagram,在 Borland Together中

支持的程序语言
Sequence Diagram转 换 为 程 序 代 码
对 于 IDE 接 口 的 整 合 度

Together

EA
支持十三张
Diagram

Programmer

127

>>> 新书上架

《程序员》每月精选上市新书,由编辑和业界专家亲自点评。诚邀读者推荐新书!

新书上架
《C #入门经典(第 3 版)》
出版社:清华大学出版社
本书全面介绍了 C# 编程的所有知识,共分为 5 篇:第 1 篇介绍了 C# 语言的所有内容,从基
础知识到面向对象的技术,应有尽有;第 2 篇介绍如何用 C# 编写 Windows 应用程序,如何部署它
们;第 3 篇描述 Web 应用程序的开发、Web 服务和 Web 应用程序的部署;第 4 篇是介绍在应用程序
中如何使用数据,包括存储在硬盘文件上的数据、以 XML 格式存储的数据和数据库中的数据;第
5 篇讲述使用 C# 和.NET Framework 的一些额外方式,包括程序集、属性、XML 文档、网络和 GDI+ 图形编程。
本书适合于想学习使用.NET Framework 编写 C# 程序的初级读者,和已了解.NET 1.0,而想学习.NET 2.0 和
Visual Studio 2005最新功能的读者。如果非要给该书提点意见,那么我希望再版时用纸稍加考究。

《Java 程序设计语言(第 4 版英文版)》
出版社:人民邮电出版社
本书由 Java 之父 James Gosling 和另外两位顶级专家联袂撰写,针对最新版本 Java 5.0 进
行了全面更新,凝聚了大师们多年的实践经验和独具的真知灼见。书中全面系统地介绍了 Java 各
主要包(java.lang.*;java.util 和 java.io )中的大多数类,以内容丰富的示例对这些类的工作原
理进行了深入剖析,而且还超越语言特性之外,突出强调了当今开发高质量 Java程序的最佳实践。

适合 Java程序员掌握和深入理解 Java语言及其类库参考。

《编程卓越之道》
出版社:电子工业出版社
本书提供了作者积累的关于卓越编程的真知灼见。
弥补了计算机科学和工程课程中被忽略的一
个部分——底层细节,而这正是构建卓越代码的基石。具体内容包括:计算机数据表示法,二进制
数学运算与位运算,内存组织与内存访问,数据类型及其表示,布尔逻辑与数字设计,CPU体系结
构,CPU 指令集的体系结构,内存体系与内存组织,计算机系统如何与外界通信等。
本书将教你写出让你引以为豪的代码;能够给同行留下深刻印象的代码;能够让客户满意、乐于使用的代码;能够
让人们(客户,你的老板,等等)不惜花大价钱来获得的代码。
简而言之,《编程卓越之道》系列将论述如何编写出卓越超凡,让其他程序员敬畏的软件。

《UML 和模式应用(原书第 3 版)》
出版社:机械工业出版社
本书是面向对象分析和设计(OOA/D)的实用指南,阐述了迭代开发相关方面的内容,使你
能一步一步地实现从需求到编码的全过程。通过本书,你将学习如何应用设计模式,包括流行的
GoF 模式和 GRASP 模式。GRASP 模式表达了对象设计中职责分配的基本原则。本书的结构和重
点建立在作者多年教授和培训成千上万学生掌握 OOA/D 的经验之上,它提供了一个精炼的、已证
明的和高效率的掌握 OOA/D 的学习方法,使你在阅读和学习上的投资得到优化。书中详尽地说明一个案例,以便实际
地说明整个 OOA/D 过程,并深入讨论问题的棘手细节,这是一个实际的练习。本书还说明如何将对象设计工件映射成
Java 代码。
本书适合熟悉OOA/D但希望学习UML表示法、
应用模式的读者,或者希望加强和提高自己的分析和设计技能的读者。

Programmer

133