Professional Documents
Culture Documents
名人堂 >>>
Eben Moglen
——倡导自由软件运动的法律之手
□ 文 / 倪志刚
10 程序员
人物&报道 Character & Report
程序天下事 >>>
微软技术 Query)是微软公司正在开发中的一个将
被集成在下一个版本的.NET Framework中
的数据访问模块,它的目的就是最大程
■ 主持人:Kaneboy
涂曙光,微软(中国)有限公司产品技术专家, 度的统一和简化.NET 开发人员访问各种
博客堂成员。专注于.NET 开发,从事 Office 数据的方式。实际上,早在去年,LINQ的
System、SharePoint 等产品相关的技术支持。
开发计划和一些相关的信息就已经被公
开了出来,而在本月,微软公司向外发布
数据访问,大概是绝大多 失误而产生的 Bug。 了LINQ的一个社区技术预览版
(Community
数程序员写的最多的功能模块了。软件 3. 没错,就是ORM(对象关系模型)。 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 的开发计划。 就可以在微软的下载站点上下载到 LINQ
码编写速度,而且可以避免由于人为的 LINQ (.NET Language Integrated 的五月份技术预览版。
数据库技术 技术的进一步支持上。就如同微软什么
新技术总是和.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作基于表间的词或者短句的检索, 付一般应用较为完整的数据库开发平台。 Sybase本月带给.NET阵营好消息:其
此外新增的 SSRS BI Studio 和 SSMS Ex- 本月Oracle的消息主要来自于对RFID 主要开发工具 PowerBuilder 除将会在安全
12 程序员
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-
EJB3.0 规范的发布 脚本开发的利器之一。在本次JavaOne大 tion Architecture》,还有 Jonas Boner 的
EJB3.0规范从2004年5月在JCP制订 会,将会演示Groovy结合AJAX 技术进行 《Transparently Clustered Spring》等等。喜
第一稿以来,已经走过了漫长的两年时 快速 Web 开发,引导我们展望 Java快速 欢 Spring 的朋友一定可以大饱眼福。
间,虽然各个EJB厂商早已迫不及待的推 开发的未来。
出了自己的 EJB3 产品,有些厂商甚至有 Struts Ti
了 EJB3 的实际项目案例,但是似乎都还 SOA in OpenSource 去年,Struts开发团队和 WebWork开
不够名正言顺。随着在本次JavaOne大会 SOA是这几年企业应用领域的热点, 发团队宣布合并,基于 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框架的赢家呢?
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们再也 别的跨项目布告板,可以对客户和市场
此时也恰逢 IBM 收购 Tivoli 十周年, 没有新的类似“Mastering UML with Ra- 的各种要求排优先级。另一家敏捷工具
Austin Business Journal 上的”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时代奠立的用户基础不知不觉被 性管理”等新特性。
14 程序员
Open Source C++ 的泛型技术是一样的。不过实现原
理却完全不同。众说周知,C++是利用模
板在编译期推导参数类型来完成。而Py-
thon是动态语言,编译期所做工作极少,
■ 主持人:汤韬 主要都在运行时解决。况且动态语言没
开源爱好者。 有函数参数的静态类型检查 。可以说,
Python的函数天生就具有泛型的特质。所
以,Python中的Generic Functions可以比较
Guido van Rossum 最近在 惑。而lambda也应该可以找到更好的替换 的概念应该是C++泛型中的“偏特化”特
他的 Blog 里开始了对下一代 Python语言 模型。一年过去了,Guido 在寻找 lamdba 性。即写出一个通用版本函数以及一系
—— Python3000 的一系列讨论。 的替代者方面进展得并不顺利,但可确定 列针对特定参数类型的专有版本。这些
首先 Python3000 虽然很重要但是不 lamdba 会继续存在于 Python3000中。 系列函数可以通过一个内置 register 函数
会是一个革命性的产品。不会像Perl 5升 另一个重要的特性是对Adaptation 或 完成组装。运行时,系统自动判定参数类
级到 Perl 6 那样惊天动地,改得遥遥无 Generic Functions 的支持。Adaptation主要 型,并调用最匹配的一个函数版本。
期。它在语法上会出现许多变化,一些内 用在一些需要对对象进行二次包装的场 总的说来,Python 3000 目标在于改
置函数将会被取消。这将意味着,P y - 合(想想针对接口编程,想想 Adapter模 进其对函数式开发范式的支持;吸取现
thon3000 不会完全兼容 2.x 系列的版本。 式)。它可以在运行时将接口(Python中 在 Python 社区中一些优秀框架的设计成
在扔掉了兼容性这套枷锁后,Python3000 将接口描述为协议,而且目前的Python版 果(诸如 PEAK 中的“多方法分派”),提
也许表现得会更加完美。 本中并没有一个明确的Interface之类关键 升Python的设计抽象层次。从而提升Py-
Guido 在去年就曾撰文,声称要去掉 字)和其实现类进行组装。有点类似Java thon系统的开发效率。
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的愚蠢错误。
Programmer 15
人物&报道 Character & Report
程序天下事 >>>
【5 月人才快报】英雄难过语言关 外企研发中心高薪难聘英才
进入二季度,IT人才风向标的晴雨表 在与招聘经理的沟通中,总能听到他
上,温度迅速攀升的应该当数跨国公司的 们发表类似的观点:很多技术高手,技术
5 月最受关注企业榜
研发中心。近期CSDN人才频道的热点招 方面非常出色,就是英语不过关,实在没
排名 最受关注企业
聘外企包括:微软(ATC BJ,ATC SH,MSN 有办法。大多数企业在招聘技术人才的 腾讯科技
1
(DZ- 网页 UI 设计)
T e a m , M S R A )、B E A 中国研发中心 、 时候,都会把他的技术背景作为第一个条
慧通商务(深圳)有限公司
2
Autodesk中国开发中心、Google中国研发 件,而外企招聘,英语不是最重要但也是 (无线通信算法工程师)
广州网易互动娱乐有限公司
中心等等,都在大量的招聘技术精英,部 次重要的一个条件。从他们的经验来看, 3
(安全工程师系统管理员)
门人数也将有很大的扩充。惠普在5月12 如果说技术高手难觅,那么英语好的技术 微软中国
4
日的新闻发布会上, 正式启动了“聚英 高手更难招。 (Research Software )
北京紫光捷通科技有限公司
1000”的大型人才招聘活动,将招募1000 而很多技术人员都面临着这样的困惑 5
(SP 产品经理)
北京龙腾阳光科技发展有限公司
年预计从 1500 人扩充到 3000 人,大部分 托福考试都有很高的分数,日常英语文档的 8
(WEB 软件工程师)
都是外派给微软、IBM这样的外企在华的 写作也还可以,唯独口语不过关,不敢开口, 北京博大正方软件技术有限公司
9
(Linuxc/c++ 开发 Java 工程师)
研发中心。热度可见一斑。 这也就成为了他们应聘外企的最大障碍。
环达电脑(上海)有限公司
10
(BIOS 工程师)
【职场百味】担心编程到了 30 岁就要面临转行? 资 料 来 源 :CSDN 人 才 频 道 5月 企 业 点 击 排 行 ,本
月 共 有 385 家 新 增 企 业 。
◆ JiangSheng(蒋晟):的确,技术日 握的技术的黄金期得不到转型,他也只
5 月最受关注职位榜
新月异,年纪大的人很难跟上,但是一些 能吃青春饭。
排名 最受关注职位
职位也需要经验和技术并重的,例如系 ◆TechnoFantasy(陈锐):这个我倒是 Java 工程师
1
统分析、测试、顾问和管理。另外,也可 没有很担心。其实现在很多公司都非常 (奇虎、伟思拓、网络易联)
WEB 开发高级工程师
以考虑投身教育行业。 需要很有经验的开发人员来参与到产品 2
(郑州鼎晟、腾讯科技)
◆ zjcxc(邹建):老不老是心态问题 开发和项目中,避免开发中的一些陷阱 .NET 工程师
3
(掌上通、激动集团)
吧? 其实在这方面,我个人有一些感触。 等。而且即使转行也应该是一个很自然
VC 程序员(游戏)
程序员的发展,一般是这两种情况:非常 的过程。 4
(杭州畅游网络、北京博大正方)
努力的做程序,所以一直都是程序员;非 ◆ Saucer(思归):在这里几乎没有这 Delphi 程序员
5
(慧通商务、北京泰能)
常努力的做程序,其他方面也不错,最后 样的考虑,虽然编程是工作,但也是因为
C/C++ 高级开发人员
发展为项目经理。 兴趣在驱动你,失去了兴趣,那么工作大 6
(福州天下创世、智乐软件)
16 程序员
>>> 网络聚焦
使用 XML 让你的文档变得智能
使用 XML 编辑器的特性能够让用户的 XML 文档变得更加智能。从 Visual Studio
2003 开始,Visual Studio 就开始提供 XML 的编辑器,微软在 Visual Studio 2005 中将
这个编辑器进行了升级。
要快?还是要好?
Java Pro
如今的工具变得越来越复杂,
将来的程序员可能要通过训练来快速的开发软件以
满足现在产品的需求而无法将传统计算机科学的课程在相应的时间内掌握牢固。
平衡
问题的两方面,好的代码和快速开发出来的代码,这个问题对于将来的软件开发有很
重要的意义。
SOA:准备好了么?开始吧!
SD Times
面向服务的架构是 Web 2.0 时代的企业级应用。现在,越来越多的采用 SOA 将
对IT产业产生巨大并且意义深刻的影响,并且会加速IT的产业化进行。在这个转变过
程中,IT 组织将面对几个问题:如何管理自己的 SOA?如何为我的 SOA 付费?
Programmer 17
人物&报道 Character & Report
网络聚焦 >>>
www.Slashdot.org
www.theserverside.com
http://idevnews.com/index.asp
www.microsoft-watch.com
18 程序员
推荐特色网站内容请发送至:editor@csdn.net
http://news.csdn.net/n/[Date]/[ID].html
一位独立软件工程师的困惑 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 号
Programmer 19
人物&报道 Character & Report
网络聚焦 >>>
文 档 论 坛
■ 主题:C++,谁来拯救你!
■ 主题:采用 POI 和 ANTLR 提取 WORD 文档数据
作者:supperman_009 (天堂草)
作者:tyrone1979
ID:4723104
ID:84014
摘要:在工作了一年之后,默然回首,发现原先酷爱的C++
摘要:POI 是 Apache 开源项目之一,用 Java实现跨平台MS
没有了踪影。一个酷爱C++但是却在用Java的无奈程序员发出
Word/Excel文档解析。 也就是说可以在非Windows平台提取MS
感慨,要使 C++ 再次成为美味,我们应该如何去做呢?
Word/Excel 文档内容。
本文采用 POI 的一个扩展 Jar 包 tm-extractors_0.4.jar 提取
■ 主题:目前最快的 N 皇后问题算法!
Word 文档内容。
作者:IceCraft (心淡情浓)
ID:4709025
■ 主题:网络数据包拦截通用技术
摘要:昨天在 google 上有幸找到了一个难得一见的算法,
作者:iiprogram 是我目前见到的最快的皇后问题算法了。它有别于传统的数组
ID:83830 判断模式,而是采用了位运算。
摘要:编写 IM DRIVER 在 NDIS 中间层对 MINIPORT(网卡驱
动程序)和协议驱动程序之间的数据包进行拦截的程序非常的
■ 主题:说给应届毕业生的!
复杂,安装也很麻烦。本人简单的介绍一种更有效的基于NDIS
作者:podianliangshui
包拦截技术。
ID:4725975
摘要:我觉得我的同情心在日渐削弱,但是,应届毕业生
■ 主题:VB 中 String 的用法及原理 们,你们想过这些问题么?你知道你害了谁?
作者:tiger119
ID:83943 ■ 主题:大家来谈谈掌握 Java 的基本功
摘要:在各种不同开发语言中,字符串类型显然是最常见,
作者:ITdavid (IT 大卫)
也是最常用的。它往往是绊脚石,或者程序中性能的瓶颈。 本
ID:4700006
文将分享作者在这方面的体会。
摘要:Java作为一种编程语言,用它来实现你想要实现的东
西是最重要的,这就要求每个Java程序员平常要多练习,提高
■ 主题:编写高性能 Web 应用程序的 10 个技巧 自己的 Java功底。那么,你认为平常都应该练习什么呢?
作者:wangyihust
ID:84364 ■ 主题:ADO.NET 老牛拉车?
摘要:使用 ASP.NET 编写 Web 应用程序的简单程度令人不 作者:irvine007
敢相信。正因为如此简单,所以很多开发人员就不会花时间来 ID:4727120
设计其应用程序的结构,以获得更好的性能了。本文将讲述10 摘要:一段小程序在VS.NET 2005上用C#重新编写,界面
个用于编写高性能 Web 应用程序的技巧。 是弄的华丽了,但是效率低下,1000条数据都没更新完成已经
耗去我 1 分多钟,请问这是怎么回事?如何优化呢?
■ 主题:C++ GUI编程——使用 SmartWin++
作者:iiprogram ■ 主题:转贴【给编程初学者的良言警句】
ID:84349 作者:iamcaicainiao
摘要:SmartWin++ 是100%标准C++编写的轻量级GUI库, ID:4722559
没有 MFC 那样的宏,你完全可以以C++ 的思维编写 GUI,并且 摘要:对一个初学者来说, IT界的技术风潮是不可以追赶的,
编译出来的程序很小,支持 OpenGL 以及 OpenCV,这是吸引我 而且也没有能力去追赶,我只是觉得如果他们把追赶这些时髦
的地方。 技术的时间多花一点在基础的课程上应该是可以走得更远的。
20 程序员
Oracle & Starcraft http://spaces.msn.com/wzwanghai/PersonalSpace.aspx
布珞阁 http://blog.9zi.com
SWT 的八卦
作者转载的这篇关于 SWT 和 Swing 的论争,不是要激起什么争执,也不是支持哪一方(虽然作者的确是站在 SWT一边),
更不是要攻击 Amy,但是这是一篇有趣的文章,里面的内幕、线人、公司政治、垄断巨头、商界风云……足够拍一出有趣的
电影,并且文章还由此反映了 IBM 对 Swing 的看法和 SWT 的由来,还是非常值得一读。
一个 hi 老的文章
作者看到《为什么Hibernate如此成功!》,被文章提到如何使工作越做越有兴趣,并且让别人加入进来和你同乐而打动,认
为频繁的发布版本和重构,快速的构造软件整体轮廓,逐步求精确实是一种可行的软件产品开发方式,虽然这个思维有些微
软风格。
Programmer 21
人物&报道 Character & Report
报道 >>>
使 BEA 一次又一次以领先的姿态冲锋在
中间件和 SOA 领域的最前线上。
中间件:
不求大而全,做专业的事
“术业有专攻”,BEA 在自己的领域
内,不求大而全,专注自己最擅长的,终
有所获。
BEA公司创立于1995年,发展初期在
北美、澳洲和欧洲收购软件分销公司,
1996年收购Novell的Texudo,Texudo是分
布式事务处理(TP)的基础结构平台,支
持多种语言。在电信和金融行业的核心
业务上有很好的应用。BEA凭借Texudo获
得了相当好的经济效益,也因为BEA的进
入,Tuxedo脱胎换骨,迅速成为中间件历
史上的神话,到现在BEA很大一部分业务
22 程序员
单 IBM WebSphere 一条线就可与 BEA 的 青睐那些有准备的人 ”。 的软件,它们希望在提供软件的同时还
WebLogic 一比高下;论公司规模,BEA 能够得到来自软件公司专业的咨询服务。
比 Oracle 也小了很多,Oracle 当年有收 解决方案: 因为相比于一家企业而言,软件公司面
购 BEA 的气魄;论名气,BEA 也不及有 另辟蹊径,延长业务线 对的是整个行业,在长期的发展中,它们
“软件帝国”之称的微软。但如果单把 如果说过去BEA很长一段时间在描绘 积累了更为深厚的经验,而这些经验对
中间件拿出来 ,
“羚羊”跑在了这些“狮 那个可口的面包,现在它正在让这些期 客户应对变幻莫测的市场是弥足珍贵的。
子”的前面。据《IT产品和服务——2005 待变成现实。 正是看到了这一市场,BEA在2005年一口
年第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在过去一年多来一直努力推广的另 SOA:
繁的收购让BEA在高端事务处理应用和 一条业务线。 公司不断前进的技术源动力
应用服务器市场上得到快速增长,而 对生产IT应用产品的企业来说,任何 只要持续不懈的努力,最终会获得
BEA正是凭借自己在中间件领域独特的 一个行业的应用都变得越来越复杂化, 成功,不要轻易放弃。
眼光,不断揽入机会 ——而“机会总是 企业也不再满足于单纯购买解决点问题 现在,除 BEA外,IBM、Oracle、微软
大事记
1995 年 1999 年 2003 年
BEA 公司成立 发布 eSolution BEA 中国研发中心成立
1996 年 2000 年 2004 年
收购 Novell 公司的 Tuxedo 产品 推出 Enterprise JavaBean 2.0 推出 Beehive Project 开源项目
1997 年 2001 年 2005 年
收购 ObjectBroker 和 MessageQ 发布 WebLogic Integration BEA 十年,推出 AquaLogic系列产品
1998 年 2002 年 2006 年
并购WebLogic,发布WebLogic Server 营业额突破 10 亿美元 发布 Workshop Studio 3.0
Programmer 23
人物&报道 Character & Report
报道 >>>
但绝大部分客户仍旧持观望态度。况且, 社区必须依靠这一支持才能够发展。经
有时企业要实施 SOA就意味着将此前建 过多年的努力,全球开源社区现在已经
立的系统推倒重来,如此折腾起来,其成 形成了一种良好的自循环体制。Spring 是
本对一个赢利颇高的企业来讲,也是需 这种体制下的产物,现在占有了Java软件
要谨慎考虑的。所以也就有了“SOA是一 开 发 领 域 在框架方面的大部分市场 ;
柄高悬的达摩克利斯之剑”的说法。 JBoss 也是,抢走了商业应用服务器领域
从提出Liquid Computing 再到现在的 的大块市场,虽然最近它被 Redhat 所收
与开发人员一起成长
Think Liquid商标,BEA逐渐确定了自己的 购,但这不妨碍它依然是一个成功的开
行动方向,那就是尽管 SOA 是一个高风 源软件。成功的开源模式层出不穷,商业 dev2dev 社区(dev2dev.bea.com.cn)
由 BEA 推出的 dev2dev网站是业界较有
险的领域,也要坚持以SOA为本,这一气 软件公司从这儿感受到越来越多的压力。
影响力的中间件相关技术交流平台 。秉承
魄着实让人钦佩。付出总会有收获,在连 面对这一形势,BEA 推出了“Blended
B E A 的“源自开发者 ,为了开发者”(B y
续几年的Garnter Group 调查中BEA都是企 Strategy”。“Blended”的中文含义解释为 Developers,For Developers)的原则,dev2dev网
业部署 SOA 的首选品牌。而羚羊毕竟是 “混合”,其实在业界这已不是一个新鲜 站致力于向开发人员、架构设计师、IT 管理
人员,提供最新的技术、信息和资源。dev2dev
羚羊,奔跑是它的天赋,2005年,BEA又 的词汇,只有 B E A 是旗帜鲜明地把
网上社区是软件开发人员在线交流,分享经
率先推出了方便企业生产、部署 SOA的 “Blended Strategy”提出来作为自己的产
验,解决难题的互动平台。
产品—— AquaLogic 系列产品。 品宣传口号。而对于“混合”的定义,BEA
有自己的解释——“混合开发是将开源 BEA User Group
24 程序员
用程序解析天文
—— SourceForge 最佳推荐项目
□ 编译 / 刘洪洁
Programmer 25
人物&报道 Character & Report
报道 >>>
曾遇到的最大的挑战是什么?
Fabien:在实时内进行一些计算,如物
体位置和天空的发光度,以满足在时间
和空间上的自然衔接。
Johannes:在球面镜透视天象仪中,
出现了球面镜的透视 / 扭曲。
Robert:在时间很紧的情况下进行大
量的代码修改。支持 Windows。
你认为为什么你们的项目已经得
到了大家的普遍认可?
Stellarium界面美观、功能强大、简单
并且实用。对于大多数人来讲易于理解,
随着版本的升级,这种优势越来越明显
了。它非常易用,并且能为你提供更高级
的帮助。很关键的一点是,它是免费的。
一些所谓的专业软件会比较难用,因为
对于普通的初级使用者来讲,它们具有
一些无用的功能。相比之下,Stellarium更
现实、更直观、更稳定。我们在传播天文
学的基本知识,这些知识对于每个人来
讲都很有用,并且我们在用一种引人入
胜的方法来传播。
在每次新的版本发布中我都会发现
重要的步骤。对于目前的版本发布,我们
或多或少在性能的限制和使用的方便性
上做了改进。我希望我们可以在这两个
方面保持平衡。增加新的性能将意味着
26 程序员
增加可用性。在 0.8.0 版本中最新的东 你们最引以为荣的是什么? 所需要的工作时间最少。改写网页,制作
西就是国际化,因为让用户用母语使用 Fabien:我们的项目能用于对孩子们的 新的布景,或者安装一个wiki,都是非常
这个程序是十分必要的。在扩大软件应 科学教育。 迅速的工作,如果需要我做的仅仅是浏
用范围这个方面,开发者已经清除了一 Johan:我在业余时间为Stellarium做设 览技术支持需求或者浏览论坛,我每周
个很大的障碍。 计,最大的收获莫过于我自己对星座更 大概只会花两个小时或者更少的时间。
加熟悉了。这是我做过的影响最广泛的
你们对这个项目有什么期望? 工作,因为这是一个开源项目。对于一个 你们的开发环境怎么样?
Fabien:为了使它实现真正意义上的多 学生来讲,这是非常让人开心的。 Fabien:我用装有LINUX操作系统的笔
语种应用,我花费了很长的时间。我试着 记本电脑,主要的开发工具是 Kdevelop。
让它适当地支持 gettext,让代码支持多 如果可以对这个项目做一些修改, Johan:我在 W i n d o w s 环境下使用
平台应用简直就是个噩梦,但是现在这 你最想改变的是什么? Wacom画板进行大部分的图形处理工作,
成为了现实! 我希望GUI接口更加灵活。我们现在 但是最近我在 Ubuntu部分安装了 Inkscape
Johan:我想知道关于星座的其他解
释,要比我们所谓的“天空文化”更完 Stellarium 界面美观、功能强大、简单并且实用。对于大多数
全。西方关于星座的解释是众所周知 人来讲易于理解,随着版本的升级,这种优势越来越明显了。它
的,但是还有不同的解释,比如来自中 非常易用,并且能为你提供更高级的帮助。
国的,波斯的,或玻里尼西亚的看法。地
球另一端的人们是如何认识这些星座 所使用的接口,在某种程度上,是手动 作为 SVG 编辑器。
的?他们的看法会为我们提供一个新的 的、静态的。很遗憾,目前我还没有找到
视野。我可以帮助其他的开发者为这些 一种更好的替代品。我还希望做一些可 里程碑
观点配以图解。 用性说明,对于任何产品来讲,易于使用 这个月我们将发布 Stellarium 0.8.0
我还希望有更多的途径进行配置选 都是最重要的。 版本,它将包含 20 多种语言的翻译,以
择。在一个文本文件中保存着一些有趣 及在行星的计算和预测方面的重大改进。
的设置,但是这个文件是只读的,许多用 你是如何协调这个项目的? 这也是一个对主要代码进行重组的开始。
户被这个问题所困扰,我想他们会很乐 这是个自由的工作,所以我们没有
意使用一个更完全的 GUI 接口。 受到任何真正意义上的限制。故障是用 其他人可以为你们做些什么?
具体的功能如卫星追踪、彗星、X 射 来让人排除的。我们需要一些可以发现 我们需要开发者们协助处理一些故
线识别,以及晒片等会非常不错。 故障并且解决故障的人。 障,改进GUI,并且协助进行Windows 和
Johannes:对火星大气层的探究,外 Mac OS X 操作系统的简化和测试。我们
星/人造卫星的景象,对于小发光体的可 你们是全职做这个项目,还是同 还需要图形专家来创造一些景观和星云
靠描述(mag[-4..-20]),不变形的平滑 时有其他的工作? 的图片,我希望更多的用户能把他们的
的线,tycho2,更迅速的计算,多线程支 我们都有工作,或者像Johan的情况, 经验、小工具(景观、脚本和星云图片)
持,海王星的人造卫星位置推算,精确的 他还是个学生。 以及定制内容放入 Stellarium wiki 中,我
行星运行轨道,光的传播时间,小行星, 如果兼职做这个项目,你每周在这 们最希望得到的是来自远古的景象,比
以不同的放大倍数显示多窗口,望远镜 个项目上投入多少时间? 如巨石阵、吉萨和玛雅的遗迹。
控制,应用多个投射器对天象仪进行多 Robert:根据具体情况而定,有时候 我们需要有人帮助我们记录这个程
屏幕甚至多机支持。 会投入比全职工作还多的时间,有时则 序。我们需要有人帮助我们翻译程序、网
Robert:更多种类的语言翻译,在更 非常少。 页和文件。我们也十分感激论坛上的祝
多的部件中加上GUI接口。既然我们在创 Fabien:平均每周6-7 小时,
下雨的时候 贺信息,尽管我们没有时间一一回复。请
造脱离地球的视点,那么就有必要用更 会达到最长时间(巴黎的冬天经常下雨)。 在SourceForge的论坛上给我们留言吧,我
多的环、阴影和遮蔽技术来增加它的真 Johan:根据项目的进度而定。我在这 们一直都在关注着你们的评论。
实性。 个团队里拥有最舒服的职位,我的职位 ■ 责 任 编 辑 :贾 菡 (jiahan@csdn.net)
Programmer 27
人物&报道 Character & Report
人物专访 >>>
目的明确地进行系统开发
—— Chuck McManis 谈专用系统
公司来说是可怕的一年。2001年 8月,我
离开了 Tut 加入 Network Appliance 公司,
谈到专用系统,人们很容易只想到高曝光度的
开发提供存储服务的全新架构及模型,
消费品,如 iPod和 TiVo。然而,在公司阴暗的数据
同时还为采用该架构的消费品设备进行
中心还躺着许多不那么光鲜漂亮的设备,这些设备
系统架构开发。这项工作促成了 NetApp
专为可靠出色地完成某一特定任务而制造。
在 2002/2003 年收购 Spinnaker Network,
在专用系统开发领域,没有其他工程师比
这成为了 NetApp 公司下一代系统的基础
NetApp(Network Appliance Inc.)的Chuck McManis
架构。
更 有 经 验 了。加入 NetApp 公司之前,McManis 任
网络及操作系统代码为乐,并从中获利。Neville-Neil对专用领域并不陌 台。如果您使用现成的开发平台,那么
28 程序员
在庞大,还在继续发展。该行业很少有人 获得一系列标准核心协议,为我们提供 行设置。几个小时后,装置开始运行,这
来自 Sun 和 HP 等有着相关技术背景的系 了所需数据。CIFS 的开源版本是 Samba, 并不是传统模式。
统公司。但是现在在 Network Appliance, 我肯定您对它非常熟悉。一直以来,微软 当我们进入市场的时候,传统SAN供
我们可以找到一些刚毕业的大学生,他 都威胁Samba将指控其专利技术侵权,或 应商(也就是当时的EMC公司)在出售的
们却已经进行了五年的内核开发。 采取其他行动。我们对此也有异议。产品 设备上安装了大量的外部旋钮,您自己
开发需要花费大量时间及资源,如果公 无法进行设置,需要专业人士为用户进
GN-N:就您正在开发的软件平台而 开源代码危及投资,您的确不会希望这 行设置。
言,您最终使用了多少开源软件?进 样做。我们一直积极地为使用过或参考 这种装置模型非常直接。说实话,这
行新装置开发时,您同时使用哪些软 过的现有开源系统提供共享的更正。我 种模式已经被Linksys公司发挥到了极致。
件呢? 们活跃在 NFS(网络文件系统)社区,帮 Linksys 生产通过 USB 连接的小型网络附
CM:我想有 40% 来自于外部获得的 助Linux开发人员开发企业级NFS客户端。 加存储盒。您只需要把设备插上电脑,打
源代码,60%来自公司内部开发。此外, 同样,我们的操作系统由中断服务 开Web浏览器门户,就可开始使用了。一
这个比例和我在FreeGate公司时的情况一 例程(interrupt service routine)演化而来, 切就是那么简单。这就是简化。
致,这主要是因为在过去 15 年里,少数 只适用于存储装置开发,因此不需要公 尽管我想您有这样的疑问:使用基
诸如 TCP/IP 堆栈之类的事物,除了增加 开源代码。 本上与每天重启的个人电脑相同的硬件,
了 IPv6 之外,并没有什么真正的变化。 如何实现 99.999% 或者 99.9999%的可
而在其他方面,如微软的磁盘共享 GN-N:当然,那些从事存储装置开发 靠性。答案是,硬件并不相同。我们使用
协议CIFS (common Internet file system), 的厂商也是你们的竞争对手。 服务器芯片组,以及Intel、AMD以及硬件
没有对应的开源代码为我们提供满足客 CM:对。我肯定 EMC 公司倒是乐意 专业人士心目中的服务器级设备,而不
户要求的功能,因此我们几乎是重新内 看看。 是这些公司物美价廉的产品。两者区别
部开发了自己的 CIFS 堆栈。 在于内部错误检测量及可设置PCI总线的
总之,我觉得开源代码利弊参半。一 GN-N:Network Appliance试图对于所有 数量不同。此外,我们在软件数据保护上
方面,您也许能够抢占先机。另一方面, 专用设备提供 99.999%的可靠性,或者 投资巨大,通过系统内检测码验证,数据
由于代码被控制范围之外的人员修改, 99.999 %的正常运行时间。系统必须随 在从磁盘传输到网络端口的过程中,没
您只能是拾取一点进行修改,保留代码, 时正常运转。您不希望像管理传统BSD或 有遭到破坏或任何形式的修改,从而保
并使之稳定下来,或者聘请人员来吸收 Linux 机器一样管理机器。您必须对现成 护用户数据。
所有更新。如果您正在从事嵌入式装置 软件做多大修改才能实现这一目的呢?
开发,使用诸如Linux或者FreeBSD这样的 CM :我们进行了大量的工作,我要 零管理
开源系统并不会给您带来多大好处。 说从第一天开始我们的核心价值观念就 GN-N:与此相关的是零管理目标。同
是简单明了。内部开发系统,判断出哪些 时使用现有软件及自行开发软件对于实
CIFS 磁盘已经连接到系统,利用这些磁盘构 现该目标有什么挑战?
GN-N:当您试图实现CIFS时,是否会 建RAID阵列,然后再在系统中显示出来, CM :在系统开发上,我们通过不使
将开发结果加入到开源代码库,以确保 这个过程相当复杂。但是所有复杂问题 用任何现成软件的做法来解决这一难题。
其仍为核心系统的一部分,还是不向外 都针对用户以简单明了的方式进行了封 我们的管理系统完全由公司内部重新编
公布? 装,用户可以根据卷和协议与我们的装 写,部分原因是没有类似于 H e w l e t t -
CM:嗯,视情况而定。一直以来CIFS 置进行对话。 Paclard OpenView 这样的系统。作为允许
面临的问题是,微软从来没有真正认为 因此,当您购买了NetApp装置之后, 插件的开放模式,HP OpenView允许他人
CIFS是开放协议。在早期,我们完成的大 打开装置,您只需要说:
“创建卷”,您就 插入网络管理代码,但行业标准开放存
多数 CIFS 开发都是对网络观察的逆向工 可以创建一个卷。默认情况下,该装置将 储管理系统的开发还是一团空白。
程。我们会说:“哦,那一定是它的工作 选择最佳方案,对所有连接的磁盘进行 但是,我们正在采取一些行动。我们
方式。” 划分,并保存多余空间。这也是我们主要 参加了一个名为 SNIA(存储和网络行业
后来,Network Appliance从微软授权 的优势之一。顾客购买我们的设备并进 协会)的组织,提供一套称为 M a n a g e
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 完全
可能了解所有信息的存储位置,谁拥有 是公司内部重新开发的操作系统。有意 FreeGate
这些数据,或者谁需要这些数据。这也是 思的是,该系统由中断服务例程(interrupt GN-N:那些从 FreeBSD 或 Linux开始开
为什么这些工具对于存储管理员管理所 service routine)演化而来。在 NetApp 刚 发装置的人总有这样的疑问:
“必须去掉
有存储数据至关重要的原因。 成立时,文件管理器还相当简单,它所做 些什么才能正常工作?”我想,您无法通
在管理存储空间时,您会说:
“我想 的所有事情就是等待网络端口传来数据 过 syslog 来运行文件管理器。
要真正高速的磁盘”,而不是“我想要用 包。得到数据包后,文件管理器被唤醒并 CM:在 FreeGate公司,我们实际上一
这六块与 RAID 阵列相连的磁盘为这个人 执行数据包所有指令,完成之后又重新 开始使用的是 Linux,但是Linux发展太迅
建一个卷 。”我们公司的存储应用程序 进入休眠状态。这实际上就是中断服务 猛。众多 Linxu开发人员和频繁的更新让
DFM(Data Fabric Manager)让用户可以 例程功能。 我们很难获得稳定的开发环境。因此我
发出指令说明您希望创建真正高速的卷, 随着文件管理器功能的增强,我们 们转而使用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:为了实现高速高效,我们通常使
一个装置盒,并且决不会进行任何修改。 者任何其他装置中),它只执行一项任 用单一名称空间。用户可以传递工作指
如果要升级,他们就会作整体改变。 务。就我们公司而言,我们只执行存储 针,这些指针可以在系统内任何位置发
CM:这些装置盒就是客户端,对吧? 任务。当您执行“登录到装置盒”时,您 挥作用。好的方面是,如果您拥有兼容
实际上并没有真正登录。您所做的只是 Posix 的 API,或者 UNIX Libc 界面,在您
GN-N:是的,完全正确。 向它发出一项服务请求,即要求存储数 的装置操作系统中是运行用户进程还是
CM:它们不是服务器。我常常提醒别 据。您想要装载主目录,或者打开一个 轻量级线程就并不重要。
人,我们不是服务器生产公司。我们是装 LUN。 关键在于,代码中的漏洞将会带来
置公司。 因此,您真正会有与LUN或者主目录 系统问题。由于只有我们的代码可以调
对话的多路径或者多实例,但是您并不 用内部服务,因此您可以清楚地知道该
GN-N:您想表达一个什么想法? 是要在装置上执行不同任务。在服务器 服务运行的每个代码路径。因此,您可
CM:计算机服务器围绕着程序运行能 操作系统中,用户登录系统,成为一个小 以检查您将使用的服务是否真正地正常
力而设计。内核及库为服务器提供大量 实例,因此所有任务都在用户空间中发 运行。
可通过程序调用的资源,但是运行何种 生。但是在装置操作系统中,所有任务都 ■ 责 任 编 辑 :贾 菡 (jiahan@csdn.net)
4 月27日,
“2006微软亚洲研究院创新日” 作化的开发挑战。 Class(IBM System z9 109)服务器新功能,以强
Programmer 31
人物&报道 Character & Report
观点 >>>
程序员创业三关
□ 文 / 韩磊
当人们还在浩叹第一次网络泡 为他们始终没明白,赚现钱的生意才是好生
沫破灭的时候,互联网已经悄悄迎来了它的第 意。三大门户成功的要点,在于他们想出办法,
二个春天;从某种意义上看,甚至已经进入了 把流量转化为盈利模式。缺乏有效的模式,流
夏天——热烈但不乏浮躁、兴奋但失之肤浅。 量只是成本。确定有效经营模式、组建有力创
某位投资人声称今年总共有三十亿美金资本进 业团队,是首要任务。
入中国,言下之意,大家都可以甩开膀子大干 第二是管理关。从程序员变成管理者,是
快上,登陆纳市不好说,搞笔钱进来花差花差 艰难的过程。你得明白两件事:一、管理和写程
多半是没问题的。 序一样,是门科学;二、人和计算机不一样,人
另一方面,程序员创业,在中国乃至国外, 有感情、会出错。协调沟通能力,是程序员创业
都不是什么新鲜事儿。我们是那么一群聪明、 必备的素质。曾经眼见一些项目经理,
和手下技
优秀的家伙,大脑发达,点子就像啤酒的泡沫, 术人员通过邮件争辩不休,甚至发展到在Blog
扑腾扑腾直往外冒,天生我才,有什么做不到 上互相嘲讽,这样的管理,可谓彻底失败。另一
的呢?遥想比尔・盖茨当年,西装革履,谈 个极端是,和手下称兄道弟、一团和气,工作被
笑间,多少豪杰灰飞烟灭…… 感情所左右,酒肉害了朋友。
管理有那么难吗?
“
于是我看到,无数公司成立了,眼看他雄 我看未必。只做对公司有利的事,就是根本原
” 创业成功。我相信多数程序员的点子,尚不至
于低级到靠软色情、盗版、恶性SEO 等等下作
手段去骗取广告费的地步,但怎么从点子变成
盈利模式,却是让很多创业者迷惑的事情。在
或冷落手上正在执行的计划。点子复点子,点
子何其多,每天新点子,万事成蹉跎。西谚有
云,双鸟在林不如一鸟在手;吃到嘴里的鸭子
才是好鸭子,湖里那只鸭子看起来比较肥?也
一些业界聚会上,总听到类似“只要有流量, 许吧,不过,吃了这只鸭子再去涉水抓那只,
总有办法赚钱”之类的说法,在2000年持同样 是不是更有把握呢?
言论的创业者,多数已经成为失败的先烈,因 ■ 责 任 编 辑 :贾 菡 (jiahan@csdn.net)
32 程序员
Programmer 33
FreeBSD
人物&报道 Character & Report
观点 >>>
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 的长项显然是在服务器 主流,现代的UNIX版本大部分都是这两个版本的衍生产品。这
端。在这一领域,FreeBSD与Linux应用上的差异显然是由于当年 为日后的市场纷争打下了伏笔。
IBM 公司投入十亿美元支持一个操作系统时,选择了Linux所造 事实上,AT&T的UNIX系统实验室一直关注着BSD的发展,
成的。从此以后,IBM的软、硬件全面支持了 Linux,这又带动 并在1992年,指控一家发行商业BSD UNIX的名为BSDI的公司,
Programmer 35
人物&报道 Character & Report
观点 >>>
36 程序员
<<< 感悟
时间缝里
看技术发展
□ 文 / 李菲萍
Programmer 37
人物&报道 Character & Report
感悟 >>>
38 程序员
<<< 声音与幽默
成为3G的杀手级应用,但是手机上的社
区网络的确有可能造成大量的应用需求。
声音 & 幽默
尽可能地使用开放源代码是政府的
这是一项长期的投资计划,一夜 Wi-Fi 项目的局面时,Nolle 如是说。 政策,
我们和微软有很好的合作关系,
但
之间不可能看到结果。 我们是不可知论者,我们和每个人合作。
——微软CEO鲍尔默日前向员工表 我们将为用户提供一种全新的新闻体 ——英国中央信息保证中心监定首
示,尽管华尔街对微软数十亿美元的 验,吸引他们将更多时间用于阅读报纸。 长 Harvey Mattinson 对于英国内阁办公室
庞大投资计划持否定态度,但“目前并 ——近年来美国报纸发行量持续下 与 IBM 公司正合作测试一种公、民营单
没有缩减投资规模的考虑”,并且在发 滑,各大报纸都希望找到赢回订户的新 位皆可使用的安全开放源代码环境发表
给全体员工的一份备忘中表示,微软 途径。微软和《纽约时报》将于明年初推 的看法。
庞大的项目计划需要投资领域的支持。 出一项新服务,允许用户通过互联网将
报纸内容下载到平板电脑,并使用微软 这类设备的一个优势是广告可以
Google 之所以敢冒险投资无线领 “屏幕阅读器”浏览。
《纽约时报》董事会 随着时间而变化,使得报纸不会在上
域,也是为了在消费者的心目中树立 主席阿瑟・萨尔伯格对此充满信心。 午出现蜂蜜广告,在晚上不会显示咖
起一种可替代互联网接入的理念。 啡广告。
——电信咨询公司CIMI的总裁Thomas 移动企业已经在网络硬件上投资了 —— Agency.com 的常务董事赫尔曼
Nolle 曾经提出过一种观点,他认为Google 大量金钱,可是他们的态度就像是疯狂 斯同样对正在开发中的能够弯曲,而且
是在构建自己的并行互联网,或者用他 地乱枪打鸟,然后希望蒙到一两只一样。 重量仅比一张纸重的电子阅读设备十分
的术语说是在构建“门户网(PortalNet)”。 ——研究机构Forrester Research的分析 看好,尽管这样的设备可能只能显示灰
面对Google制定进入无线领域的计划,在 师 Charles Golvin 如此批评现在的移动企业, 色,但它们却可能吸引一些广告代理机
很多大城市,如在旧金山等地竞标一些 他十分怀疑有任何一两项单一的应用可以 构的参与。
“ 并 非 如 此 ,” 程 序 员 说 ,
“在设计一个财务
软 件 包 时 ,编 程 人 员 是 作 为 一 个 中 介 者 在 观 念 各
程序设计 异 的 人 们 之 间 起 作 用 的 :软 件 如 何 操 作 ,报 表 是
什 么 形 式 ,如 何 与 税 法 一 致 等 等 。相 反 一 个 操 作
系 统 不 为 其 外 观 所 限 制 ,当 设 计 一 个 操 作 系 统
编程大师如是说: 嚷 着:
“ 我 昨 天 满 载 而 归 ,但 今 天 的 收 获 会 更 大 。” 时 ,编 程 人 员 只 要 在 机 器 与 人 的 思 维 之 间 寻 找 一
“程序被测试时再 于是,门卫盯他盯得更紧了,但仍一无所获。 种 最 简 单 的 和 谐 就 可 以 了 。这 就 是 为 什 么 操 作 系
改设计方案就太迟了。” 在 展 示 会 的 最 后 一 天 ,门 卫 再 也 抑 制 问:
“大 统 更 容 易 设 计 的 原 因 。”
曾有个人去参加一 盗 先 生 ,” 门 卫 说 ,
“ 我 被 你 搞 糊 涂 了 ,实 在 想 不 军 机 大 臣 点 点 头 , 笑 了 。“ 说 来 也 是 。但 要
次电脑展示会,每天当他 明白。请告诉我,你究竟在偷什么?” 想检测和纠正其中的错误,哪个更容易呢?”
进入展馆时 ,都对门卫说: 曾 经 有 位 编 程 大 师 ,喜 欢 编 写 非 结 构 化 的 程 程序员没有回答。
“ 我 是 个 大 盗 ,这 次 序 。一 位 初 学 者 试 图 模 仿 他 ,也 开 始 编 写 非 结 构 一 位 经 理 到 编 程 大 师 那 里 ,交 给 他 一 份 有 关
展 示 会 也 在 劫 难 逃 。” 化的程序。
当这位初学者请大师评价他的进展时, 一个新应用程序的需求说明。经理问编程大师:
这番话让门卫坐立 大 师 批 评 了 他 的 做 法 。他 说:
“对一位编程高手适 “如果我分配五个程序员给你干 ,你需要多久能
不 安 ,因 为 里 面 有 价 值 数 合 的 ,对 初 学 者 来 说 并 不 一 定 适 合 。在 超 越 结 构 设计好这个系统?”
百 万 美 元 的 电 脑 设 备 ,所 化 之 前 , 你 必 须 先 领 悟 道 。” “ 那 将 花 费 一 年 的 时 间 。” 大 师 立 刻 回 答 。
以他紧紧地盯住这个人, 曾 经 有 位 程 序 员 被 派 到 IBM的 军 机 大 臣 手 下 “但马上就需要这个系统甚至要求更快!如
但这个人只是从一个展摊 工 作 。 军 机 大 臣 问 程 序 员:“ 设 计 一 个 财 务 软 件 果我分配十个程序员给你需要多长时间?”
逛到另一个展摊, 嘴里轻 包,和设计一个操作系统,哪一个更容易?” 大 师 皱 了 皱 眉 头 ,“ 那 样 的 话 ,需 要 两 年 。”
轻地哼着小曲。 “ 操 作 系 统 。” 程 序 员 回 答 说 。 “如果我分配一百个程序员给你怎么样?”
当 这 个 人 出 门 时 ,门 卫 把 他 拉 到 一 边 ,搜 查 军机大臣立刻发出一种不信任的惊叹,
“与 大师耸了耸肩膀,
“那么这项设计将永远无
他的衣服,但一无所获。 一 个 复 杂 的 操 作 系 统 相 比 ,一 个 财 务 软 件 包 简 直 法 完 成 。” 他 说 。
第 二 天 ,这 个 人 又 来 了 ,并 对 着 门 卫 嚣 张 地 是 小 巫 见 大 巫 。” 他 说 。 ——节选自电子工业出版社即将出版的《编程之道》
Programmer 39
特别策划 Features
42 程序员
>>> 程序员开源手册
程序员开源手册
□ 策划 / 欧阳璟
在 Internet 上,开源社区的项目就像浩瀚的海洋。那些崇尚开放的程序员常常汇
聚在这片海洋之中,偶尔掀起一阵波澜,或者卷起巨浪。然而就软件而言,却并不
是追捧时尚就可以写出优美代码的,更多时候,是需要汲取这片汪洋中的精华。
精华是什么?对于一个长期面对显示器撰写代码的人来说,最为精华的东
西莫过于他们长时间积累下来的经验。而这些经验通过一行行代码展现出来,
便形成了很多程序员常常使用的程序库、组件包以及软件开发相关的工具。
然而,要在浩如烟海的开源项目中找到自己合意的工具和代码谈何容
易?每一个项目、每一种开发语言、每一个开发过程都是如此的特殊,以
至于我们不得不用很大的精力来寻找适合它们的软件,或者花费一番力气
来自己开发。
为此,本刊编辑部特别策划了这样一组文章,从不同的方向上为读者
打开开源宝库的大门。横向上看,每个程序员都在使用编程语言进行软件开
发,这些语言主要分布在 C/C++、Java、.NET 平台语言,或者是如 Perl、
Python、Ruby 以及Lua这样的动态语言。且不说动态语言高度的灵活性,便于
撰写很多优美的程序库,单是那些传统的编程语言所积累下来的宝贵的经验
和财富,就很值得仔细钻研。而从纵向上看,从需求、设计、建模、开发到配
置管理、持续集成等多方面都有很多优秀的开源工具可供免费使用。
通过本刊专家作者的点评和比较,
兴许可以让你迅速掌握软件开发的神兵利
器,从此开始撰写高质量的代码!
Programmer 43
特别策划 Features
语言“小人乍富”的那几年,也还有
其它不少程序设计语言具有高性能、
□ 文 / 孟岩 的开放的幽灵在欧美大学校园里徘
徊,那么我们今天很可能要把 begin
和 end 直接映射到键盘上。如果 IBM
C语言天生就与开放结 够认识到的是,事实上C语言统治地 不是在 1970 年代极端保守地把一种
缘。大约到1980年代中期,C已经成 位的获得,却也是早期开放软件运 叫做PL/X的语言牢牢地限定在自己
为人类历史上第一种工业级程序设 动的直接结果。多数人在回顾这段 的研究所里,也许整个程序员社群
计世界语。很多人都知道,正是C这 历史的时候,经常会感染中国文人 的图腾就不是贝尔试验室的那两个
样一种世界语的出现 ,才使开源运 的不严肃的浪漫主义史观,喜欢把C 大胡子,而是小沃森实验室里的IBM
动的出现和最初发展成为可能,从 语言的成功归结为汉高祖斩白蛇般 某院士。事实上,C 语言的成功,更
这个意义上讲,说C语言是开源运动 的天赋神格,描述为遥想公瑾当年, 须拜开放软件运动之时势所赐,或
之母并不十分过分。但人们不太能 谈笑间樯橹灰飞烟灭的轻飘飘。在C 者更确切地说,C与开放软件是一对
44 程序员
>>> 程序员开源手册
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++ 无寿无疆”的说 框架中,Qt成熟度最高,已经被一些
法得到不少人的支持,其根本原因之一就在于 C++在开源运动中的 大 公 司 应 用 在 关 键 产 品 中。由于
地位远逊于 C。 Trolltech对Qt采用的dual license模式,
该产品既可以从开源社区获得支持,
弄姿者皆不录入; 能完全与 C 语言相当的系统应用。 又能够赚取足够的商业利润 ,因此
● 可靠。必须经过实践的检验, Douglas Schmidt本人在给我的一封信 其前景也令人比较有信心。
被广泛应用。花拳绣腿者不录; 中提到,他非常支持这种简朴的用 Qt 的主要技术特色是其元对象
● 先进。风格上比较先进,能 法。但更多的人恐怕不会停留在这 模型。Q t 实际上使用的并不是标准
够体现 C++ 的技术优势; 个简朴的层次,而是会进而使用ACE C++,而是标准C++的一个扩展。它
● 开放。有社群的积极支持支 所提供的那些先进的框架,如著名 通过元对象模型扩展 ,实现了著名
持,文档相对齐备,代码开放,允许 的 Reactor/Proactor。这就是ACE的第 的 signal/slot机制,而这一机制也成
讨论和改进; 二个层次,也是发挥效益最大的一 为 Qt 的最大特色和优势。
● 有益。读者可以放心大胆地 个层次。还有少数的 ACE高级用户, 与Qt类似的可移植GUI框架还有
使用,并且应当能获得实利。 可以在必要的时候为 ACE 本身添加 wxWidget,FOX 等。
在这样的背景下,我将下面的 新的构件。
一些开放资源介绍给大家。 ACE是一个侵入式的程序库。如 分布式对象中间件:ICE
果要使用它,就要改变自己的编程风 ICE 是分布式对象中间件领域里
系统和网络编程库:ACE 格来适应 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 程序员
>>> 程序员开源手册
Programmer 47
特别策划 Features
一方面 JBoss 最近的巨额并购,
证明了免费开源产品也能从专业服
和框架类库 商业产品级的质量认证和技术支持
服务。如 SourceLabs公司的认证开源
产品栈 SASH(Spring Axis Struts
□ 文 / 肖桦 Hibernate)。
所以,这类公司并不是人们初时
Java开源国度的十年 中央公共频道:TheServerSide.com 以为的开源蛀虫,从Jboss.com开始
成就,并不单纯以在SourceForge上的 TheServerSide 是最高级的Java开 的备受质疑,到 Spring 的 Interface21
项目数量超越 C/C++成为第一这样 源信息流通集散地, 不属于任何官 公司的顺利开张可以看到这种转变。
的数字来计算,而是以一个开源社 方,却做得比任何语言的任何官方
区, 一个生态系统的最终完备来衡 网站都要出色。良好的 Editor制度保 主题索引网站:java-source.net、
量。每日生活其中的人们可能并不 证了每一条新闻的质量,只要订阅 SWIK、Manageability
自觉,但如果爬到山顶回望一下,就 它的新闻聚合,基本可以保证你不 主题索引网站时时绘
会发现这个生态系统在没有官方的 会错过任何重要的 Java资讯。可 制着Java开源世界的地图,
强力规划之下,已完全自由成长进化 能,它也是全球Java开发者订阅 当你需要选型的时候 ,只要
为一个精密运作、繁忙不息的城市: 率最高的 RSS 了。 打开相关的主题 ,而不
用在 SourceForge 或
免费的项目 H o s t i n g 服务提供商: JCP 专家组和 JSR 标准 者 Google 麻木的翻
SourceForge和 dev.java.net 尽管越来越多开 页。最著名的一份
免费的 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 程序员
>>> 程序员开源手册
用开源框架甚至最新版本的狂热份子,以及因为使用开源框架而获 CodeHaus推出了XFire(xfire.codehaus.
Programmer 49
特别策划 Features
nate一样普通寻常,进一步稳固Java products/jbossportal) 是从JBoss Nuke Compass(compassframework.org)
在企业开发领域的位置。 一路走来正正规规的 Portal 系统。 对 Lucene 应用于企业领域的简化封
Liferay(liferay.com) 历经EJB2 装,将商业对象映射到搜索引擎。
报表与商业智能报表:Eclipse BIRT、 到 Spring+Hibernate的重大转型后,拥
Pentaho 有庞大的开发者团队和最多的现成 Cache 方案:JBoss Cache
Java的开源报表方案曾经很长一 Portlet。 Java各式 Cache方案提供的丰富
段时间被 JasperReport+IReport 的组合 而eXo Platform(exoplatform.org ) 功能和强大能力,绝对不是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和
Jython暂时的发展未如理想。但看看
Ajax 应用:DWR、Buffalo AOP 方案:Eclipse AspectJ、Spring Java的决心,相信脚本语言在Java一
DWR(getahead.ltd.uk/dwr)的创 AOP 定会有美好的未来。
造性在于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 的安全认证
而由国人 Micheal Chen 开发的 可以拥有一个统一的AOP平台,真正 的Acegi(www.acegisecurity.org)等等。
Buffalo(www.amowa.net/buffalo) 把AOP大规模应用到普通团队中去。 版面所限,就不逐一介绍了。
项目是另一个同样优秀的Ajax框架。
全文本搜索引擎:Lucene、Compass、 作者介绍:
Portal系统:JBoss Porta、Liferay、Exo Nutch 肖桦, 网 名 江 南 白 衣 , 专注于
50 程序员
>>> 程序员开源手册
直观的看与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 开源的主要的发布主体,虽然
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 plication Block
开始,微软陆续推出了很多知名的 Application Block,这些 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 中 Outlook、InfoPath、Excel同过Aggregation
◆ 常用第三方工具 Exception Handler 的要求更是体现得 串成一个有机的联动工作流过程。
淋漓尽致,与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),前者是用来完成最通用的数 都或多或少有所启迪。 与此同时开源社区也为.NET 提
据访问任务,后者是完成异常处理。 此后,微软陆续推出了 CMAB 供了丰富的开源代码 ,主要包括如
这两个代码块一出现,立即风 (Cache Management Application 下内容:
靡整个.NET 世界,以笔者所见出了 Block)、Logging Block、Authorization ◆ 面向网络应用的
功能上的支持外,更多的是给了全 and Profile Application Block和Offline C# Ping、IP多播
(IP Multicasting )、
球.NET 开发人员一个如何使用.NET Block 等第一代 Application,通过排 各种ICMP、SNMP、SMTP、POP 开发库
52 程序员
>>> 程序员开源手册
Programmer 53
特别策划 Features
方式提取到具体的方法、属性的说 为了将这个过程可视化,常常需要 供了一般MIS应用的基本客户端和应
明,它和实际Assembly内二进制的内 将宿主和客户端(甚至包括Proxy)间 用服务器端开发库支持。
容是一致的,因此为后续开发人员 交换的数据 Dump 下来,用来调试应 此外,各个.NET原生的和翻版的
参考提供了准确的第一手开发资料。 用。TCPTrace就是通过把自己当成一 开发库则弥补了其他各个专业领域:
◆ Build 工具 NAnt 个存储转发的 P r o x y 来保留这些 ● NHibernate:完成O/R Mapping;
NAnt 是一个基于.NET 的生成工 InBound 和 O u t B o u n d 信息。对于 ● 不断更新的NDoc、NAnt、NUnit
具,与VS .NET 不同,它使得项目的 Remoting、Socket、WS(尤其是WSE) 继续为.NET 2.0 开发人员提供必要
Build过程变得非常容易。尤其当大量 的开发人员非常有用。 的工具支持;
开发人员从事单个项目时,不能依 ● 众多 Zip、Codec、Networking、
赖于从单个用户的代码来Build, 而且 .NET 开源趋势展望 XML……等开发库面向各个具体领域
定期的手工Build也是很繁琐的工作。 随着微软的新一代Enterprise Li- 的开发需要。
通过 NAnt 您可以创建每天晚上运行 brary和以Ivar Lumi的集成网络应用层 不过,由于.NET 的版本更新速
的自动生成过程,它可以生成解决 开源开发库的为代表的新一代.NET 度较快,且.NET Framework容量已经
方案、复制文件、运行NUnit 测试、发 开源开发包的出现,不难发现.NET 很大,因此未来.NET 开源出现了与
送电子邮件等等。 开源在 2004 年下半年开始逐步进入 C++和Java不同的发展趋势,基本上
◆ ASP.NET 版本切换工具—— 到一个新的阶段,这个阶段的主要 形成了一个渐开曲线:
ASP.NET Version Switcher 特征如下: 1. 出现了新的开源开发库或者
当IIS处理请求时,
它会查看正在 ◆ 更全面的系统化 是新的开源工具;
请求的文件的扩展名 ,然后基于该 早期的开源库一般集中于某个非 2. 微软提供了类似的实现,并
Web 站点或虚拟目录的扩展名映射, 常具体的功能,例如:数据访问、缓 作为独立的SDK或者通过SP 提供给.
将请求委派给 ISAPI 扩展或者自己处 冲、SMTP、POP3、XSLT;而第二阶 NET 开发人员;
理该请求。这正是ASP.NET的工作方 段中很多开发库出现聚合现象,例 3. 微软将这些开发库、开发工
式;将为所有ASP.NET扩展名注册扩 如:enterprise library 包括了 Cache、 具集成到VS.NET或者是.NET Frame-
展名映射,并将这些扩展名映射导向 Logging 、Data Access 、Security 、 work 中;
aspnet_isapi.dll。但如果安装了 ASP Exception;Ivar Lumi的网络开发包则包 4. 集成的开源库和工具被更深
.NET 1.1——它会将扩展名映射升级 括了SMTP、FTP、ICMP、POP3、Mime、 入的集成;
到新版本的 aspnet_isapi.dll,这时当 DNS等网络应用层的很多基本功能。 5. 由于开发环境本身已经提供
在ASP.NET 1.0上生成的应用程序试 ◆ 更高的集成度 了更为便利的支持,进一步催生新
图用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工具, 技术,而外围的公共库则按照Plug &
TcpTrace P l a y 的方式允许用户自由的按需选
作者介绍:
对于.NET平台的网络开发人员, 择,但是所有生成的对象是按照配置
为了诸如加密、签名、散列、Context 要求在公共库的核心工厂装配好的。 王翔,分布式异构数据库方面的
54 程序员
>>> 程序员开源手册
握主动权,去选择适合自己特点的
开源软件。主流的开源数据库可供
自由与开放的数据库 选择的余地其实很大: M y S Q L 、
Firebird 以及PostgreSQL等等都是当今
使用非常广泛的产品。
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'" 的工具,要比软件本身在项目中起
到的作用更重要。
周围的同事常常要进行数据的 产品竟不支持这个平台,这时开源
统计和运算,比如网站访问的日志 软件的优势就产生了。随后,我们自 开源对 DBA 更高的要求
分析和统计。记得一个日志分析程 己在这个系统平台上编译了开源产 使用开源数据库和商业数据库
序,要求对每个访问来源的独立IP的 品PostgreSQL,各个方面都比那个商 不太一样,商业数据库往往有非常
访问次数进行统计,同事为求简单, 业数据库效果好。如果当初坚持采 好的外围工具,比如管理工具,监
写了一个脚本,先查询IP,然后用每 用该商业版数据库,并且使用 64 位 控工具,调试工具等等。这些方面,
个 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,经
何伟平:Postgresql中文
磁盘上。 过漫长的等待之后,Mysql终于开始
版文档维护者,《Perl 编
上面唠嗑了半天,其实还是想 了对事务的初步支持。Mysql是一种 程》第三版译者,Linux集
说,这些经验和知识,恐怕是用非开 相对简单、快速的数据库,有着SQL 群管理员及数据库研究人
源数据库一辈子也不可能了解到的。 界面,到了版本 5,开始对事务以及 员和软件开发人员。有近
当然,软件产品的选择没有好坏,但 一些存储过程方面的支持。因为简 十年的软件开发经验,在
我更倾向于让自己多掌握一些。 单,所以Mysql 使用方便,速度也比 金融、工业和互联网等行
较快。支持等方面也非常好。只是最 业有着较长的经历。现供
Programmer 57
特别策划 Features
用 Python或是Ruby之类的动态语言,
所需的代码量往往只有Java的1/10,
58 程序员
>>> 程序员开源手册
Programmer 59
特别策划 Features
Perl 在 Web 应用中的软件
我们首先看看在 Web 体系中一
应用和程序库
□ 文 /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 应 用 的 逻 辑 结 构
60 程序员
>>> 程序员开源手册
在Web开发中常用的Perl模块主 3000/library/login/。是不是简单得
要包括: 让你难以置信?
◆ DBI DBD::Oracle DBD::Mysql: Perl相关的主要框架还有Mason,
◆ Net::SMTP,MIME::Lite:这个 为大型商务类网站所设计。在其官
◆ L W P : : X X U R L : : X X X 的模板技术”,但除了基本的语法同
图 2:Catalyst 工 作 的 流 程 图 Perl 一样外,已经完全不是顺序型解
HTML::XXX:这是 Web 操作相关的;
◆ XML::XXX:这些是 XML 操 Catalyst 比起其他的框架具有更 析的页面语言了 ,您可以去官网
◆ Image::XX:这些是图形操作 些特点:
方面的; ◆ 多模型、视图和控制; Perl 趋势展望
◆ CGI:如果您使用 CGI 方式可 ◆ 可重用组件; Perl 在国外的应用相当成熟,在
Programmer 61
特别策划 Features
单独定义一个XML 文件。同样,借助
强大的动态能力,SQLObject 还拥有
一个Hibernate所远不及的功能,那就
是 SQLObject 的映射类可以在运行时
动态改变自身结构,这也意味着数
据库中的表结构也可以在运行时进
行改变。总之,对Hibernate略有了解
的开发者均能迅速理解 SQLObject。
虽然我一直认为 SQLObject 还远
未能将 Python 的动态能力发挥到极
致。不过这却是一个良好的开始。也
许我们可以在不久将来看到更多更
具新意的 O/R mapping 工具。
TurboGear
□ 文 / 汤韬 现出来。虽然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个的标准库(这 SQLObject
还不包括专门针对 Mac 机的 50 余个 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 程序员
>>> 程序员开源手册
Programmer 63
特别策划 Features
● gruff是基于Rmagick的图表生
成工具。产生的图像颇具Apple设计
风格,还支持多种配色模板;
64 程序员
>>> 程序员开源手册
Programmer 65
特别策划 Features
8. 能方便地利用表和动态元机
一颗璀璨的月光宝石
制实现基于原型(prototype-based)的
面向对象模型;
9. 从 5.1 版开始提供了完善的
—— Lua
模块机制,从而更好地支持开发大型
的应用程序。
Lua的语法类似Pascal和Modula,
66 程序员
>>> 程序员开源手册
的Lua GUI程序在许多平台上都能顺
畅地运行。
Pluto
虽然Lua中的表能通过表构造器
以Lua代码的形式保存到文件中从而
实现持久化,但当数据之间有着复
杂的引用关系,并且存在循环引用、
共享引用等特殊情况时,这个任务
就变得相当困难与繁琐了。Pluto 持
久化库能够为用户解决这个难题。
在它的帮助下程序员可以将任意复
杂的表数据保存到特殊格式的二进
制文件中以待将来恢复,库会自动
处理循环引用之类的情况。
除表之外,Pluto还支持函数(确
切地说是闭包)、thread的持久化,这
UDP sockets 的操作,前者则可以创 wxLua 流行网 种能力非常有意义。大家都知道程
络 游 戏“ 魔
建动态页面并处理web表单上的输入 GUI是开发人员花费气力比较大 兽 世 界 ”的 序调试中的一个基本动作就是复现
插件与脚本
数据。K e p l e r 通过 C G I L u a 起动器 的一个领域,因此简化GUI程序的编 bug,但很多时候bug产生的条件是非
都 是 使 用
(launcher)使得 W e b 服务器能执行 写一直是广大程序员的努力方向。 Lua 撰 写 常复杂的,依赖很多因素,开发者很
CGILua和Web程序并与之通信。目前 随着脚本语言的兴起 ,将动态、灵 难精确地构建出完全一致的运行环
的版本已经包括适合 CGI、FastCGI、 活、易用的脚本语言引入到GUI开发 境。而利用Pluto对函数和thread的持
Apache、IIS、Tomcat、Zope 的CGILua 中是一种非常有价值的尝试 。由于 久化能力,我们可以把bug发生时程
起动器,因此用Lua 开发的Web程序 复杂的 G U I 布局需要大量的描述信 序的完整运行环境保存下来 ,今后
可以在这些种类的服务器中自由迁 息,所以比起其它脚本来,既适合编 就可凭此方便地复现 bug。另外一个
移,只要同时安装上对应的CGILua起 程又适合描述数据的Lua语言在构建 重要应用是游戏进度的保存 。实现
动器。 GUI 上就具有独特的优势。 游戏逻辑的Lua脚本的运行状态能随
LuaFileSystem 是对标准 Lua 库中 wxWidgets是一个著名的跨平台 时写入到文件中留待将来恢复,这
文件读写功能的补充 ,它提供了一 C + + G U I 库,w x L u a 在 L u a 与 使得在任何时间点保存游戏成了一
种可移植的方法来访问系统的目录 wxWidgets之间架起了一座桥梁,通 件非常容易的事情。
结构和文件属性。Copas则是一个基 过它 L u a 代码几乎可以调用
于协程的服务调度器。Xavante 是一 wxWidgets 的所有功能。wxLua基本 LuaCOM
个用Lua开发的支持HTTP 1.1的Web 将 wxWidgets 的类体系映射到了 Lua LuaCOM 是一个支持 Lua 与符合
服务器,它直接支持CGILua而无需起 (基于原型) 的对象模型中,这使得 COM规范的组件对象(确切一点说是
动器。 程序员能以基于对象或面向对象的 自动化对象)进行交互的扩展库。所
其它的组件提供了 S Q L 数据库 风格来开发 wxLua 程序。一个 Lua脚 谓交互包括了两个方面,首先是允
访问、X M L 解析、LDAP 、S O A P 、 本的撰写、运行、测试和修改可以非 许 Lua 程序使用 COM 对象。LuaCOM
XMLRPC、ZIP 文件操作等功能,用户 常快速,这无疑大大提高了GUI程序 支持注册在系统注册表中的 COM 对
如果只需要其中的某些功能 ,可以 的开发效率,因此wxLua非常适合快 象的动态实例化,也支持动态访问
抽出相关组件( 及其所依赖的组件) 速原型的构造。另外,Lua本身以及 运行中的对象。在LuaCOM的帮助下,
来使用。 wxWidgets良好的可移植性使得相应 调用COM对象方法就象调用普通Lua
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在葡萄牙语里代表美丽的月亮。事实证明它没有糟蹋这个优 令。ChunkSpy的作者写过一篇详细的
美的单词,Lua语言正如它名字所预示的那样成长为一门简洁、优雅 介绍 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 的 作者介绍:
68 程序员
>>> 程序员开源手册
司常用的一组过程工具,以及在敏
敏捷方法中的开源工具 捷项目中使用这些工具的些许经验。
从我的角度看来,敏捷方法最
为重要、也最立竿见影的部分当属
□ 文 / 熊节 测试驱动与持续集成 ,我们的工具
之旅就从这两件事情开始。
也许由于软件行业固 而这种思路,与敏捷方法是不谋而合的。
有的“高科技”特性(或者说,软件 再加上,推崇敏捷方法的那些“实用主 单元测试:JUnit(以及 mock)
人固有的顾影自怜),软件项目的管 义程序员”们往往也正是开源社群的积 在敏捷开发的工具箱里,JUnit
理和过程控制中从来就不缺少形形色 极分子,所以适用于敏捷项目的开源过 很可能是最广为人知 、也最受到重
色的工具。在一些大型的、
“正规的” 程工具尤其容易找到也就不足为奇了。 视的一个,当然它也当得起这样的
软件企业中 ,配置管理要通过 敏捷的开发者们是幸福的,因为他 殊荣。若论出身,JUnit 是由Kent Beck
ClearCase,软件设计要使用Rose画出 们拥有众多优秀的开源工具可供选择; 与 Erich Gamma 两人共同创造的。若
一大堆精美的图形,压力测试要用 敏捷的开发者们又是痛苦的,因为他们 论影响,由它引入的“红条 / 绿条”
LoadRunner 来跑……当软件公司的老 必须在乱花渐欲迷人眼的工具丛中找出 更是影响深远。
板们痴迷于“形式化管理”与漂亮的 适合自己的一组工具栈,并将它们与自 “红条 / 绿条”不仅仅是一个测
报表和文档时,这些昂贵的商业工具 己的管理策略糅合成一个完整的开发过 试成功与失败的标记 ,它们构成了
着实在他们那里得到了不少的青睐。 程。本文将为读者介绍 ThoughtWorks 公 敏捷开发中最基本的韵律:
“编写测
幸运的是,越来越多的软件开发
者和老板开始意识到,软件项目采用
的方法没有一定之规,
不同的项目、
不
同的团队需要选择不同的开发方法。
而工具,则如同三棱镜般折射出方法
学的身影——用着微软的TeamSystem
就很难不遵循微软推荐的最佳实践,
同样RUP 在没有Rational 工具支持的情
况下也难以实施。于是,选择开发过
程工具,很大程度上就成了选择开发
方法的一个副产品。
对于身处激烈需求变更风暴之
中的企业应用开发者 ,如何步步紧
跟客户的真实需求、如何确保时刻
为客户提供最大价值是他们每天冥
思苦想的问题。此时注重交流反馈、
以客户价值为驱动的各种敏捷开发
方法就成为了他们自然而然的选择。
而有趣的是,开源的过程工具也大
多与敏捷方法最为适应。看似偶然,
其实却有其道理:开源项目更少受
到种种政治因素的影响,生存的环
境又有更多的不确定性,因此也更
加强调时刻保证最大化的客户价值。 图 1:各 种 各 样 的 Green Bars
Programmer 69
特别策划 Features
试 -红条-编写代码-绿条-重构”, 优点在于它的震撼性:成百上千个 台是 J2EE 还是.NET 或者 Rails。
这五个简单的步骤确保了每一个思 test case运行起来,只见Web页面不 Selenium的名字还有个有趣的由
绪都有单元测试作为记录,每一段 断地在屏幕上闪过,模拟着各种各 来:在Selenium 出现之前,最著名的
代码都有单元测试保证它的质量, 样的用户操作,最后生成一张庞大 Web 应用功能测试工具当属 Mercury
整个软件项目始终朝着价值最大化、 的报表,背景是令人平静愉悦的淡 Quanlity Center,但那是个商业工具,
质量最优化的方向前进。而红条与 绿色。即便对于全然对于不懂技术 功能强大却也价格不菲,常常让开
绿条,则清晰直观地指出你当前所 的管理者或客户,这一过程的心理 发者们又爱又恨。所以,自己动手开
在位置,以及下一步应该做的工作。 效果也是不言而喻的。 发开源功能测试工具的ThoughtWorker
当我说 JUnit 的时候,我意指的 在没有使用 Selenium之前,很多 们把这个工具叫做 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 格式的测试脚本之 不过最通常的用法,还是用Ant
和 Ruby 等主要平台上,也有类似的 外,Selenium还支持编程驱动的模式, 来完成整个构建流程:从编译源代
mock 框架可供选择。 可以用程序代码来编写可复用的测 码,到打包应用,到部署服务器,到
试案例。而且整个 S e l e n i u m 是用 初始化数据库,再到执行测试并生
功能测试:Selenium JavaScript 和HTML编写的,这也就意 成测试报告,只需一个指令就可以
抛开所有的技术考量,单凭直 味着你可以轻松地将其融入任何一 全部完成。类似的构建工具在 C /
觉来说,我个人认为Selenium最大的 个web应用,不管开发这个应用的平 C++的世界早已存在,那就是著名的
make,不过 Ant 来得更加简单易用。
作为后起之秀的 Maven 比之 Ant
最大的优势在于它内建了更多对J2EE
项目(尤其是web 项目)的支持,以
及更多项目管理相关的功能 。像单
元测试、创建报表等在Ant 中用插件
实现的功能,在Maven中都有内建的
支持。甚至很多开源项目的网站都
图 2:Selenium 也 采 用 了 红 条 / 绿 条 的 界 面 设 计 是用Maven直接生成的。但以笔者愚
70 程序员
>>> 程序员开源手册
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 程序员
>>> 程序员开源手册
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程序,因此
黄亮,西安交通大学毕业,2005
以使用 JUnit 和 Testng 任务来运行测 它能够充分利用 Ruby 语言的强大功
年加入 ThoughtWorks,对反垃
试,通过 checkstyle 提供的任务来进 能,在Rake脚本中,你可以使用Ruby
圾 邮 件 系 统 略 有 研 究 ,闲暇时
行 Java代码风格检查,使用 Tomcat 语言的全部功能和程序库,来完成 喜欢电脑游戏,是敏捷开发的
等提供的任务来自动化地启动和停 你的任务。 忠实程序员。
止服务器并部署应用程序,或者用 Ruby 是一个非常强大而且易于
74 程序员
>>> 需求分析
铅笔和纸最有效,而不是电脑
—温伯格需求访谈实录
□ 整理 / 潘加宇
理解客户的真正需求
对于捕获需求,要记住,这
不是技术层面的事情,而是关于一方怎
样能理解另一方的问题。需求分析人员
首先要理解这一点,即使在对方没有意
识到的情况下。要理解从未有过的需求,
理解人们到底要什么,你的工作就是要
帮助他们找到真正所需要的。客户自己
通常是无法做到的。如果需求分析时牵
涉到不止一人,那一定会有不同的意见
出现,这时候还要帮助他们自己去解决
相互间的异议。例如,业务经理希望系统
速度很快,部门经理则关注成本。这里就
隐含着一个意思:他们可能没有足够的
资金来建一个快速的系统。您怎么能知 语里时常发生。我们有个很好的词叫需 需求。
道真正的需求是要系统快还是要成本低 求想法(Requirement Idea)。有人说我要 第四是要给需求排时间表。比如我
呢?开始你是不可能知道的。如果自己 一个快速的系统,要系统能够完成此项 们要构建一个功能但不是在发布第一轮
直接做这个决定,就会犯错。你所能做的 任务。其实这只是个需求的想法,你并不 产品时构建,那现在就不把它作为需求。
就是说服他们必须自己把这个问题先解 真正知道他们要什么,他们付得起什么
决掉。捕获需求非常有用的一个方式是: 样的价格,以及最终构建的系统是什么 很多时候需求根本没有变
当客户说要什么的时候,你可以去看看 样子等。比如说“用户友好”就只是一个 人们常说需求改变了,这是不对的。
系统的用户是怎样做这件事的。例如客 想法或者连想法都谈不上。 需求根本就没有变,而是一开始工作没
户说要系统有很快的速度,你就可以去 接下来就是澄清需求 。我们有个词 有做好,没有得到所有的需求,所以看起
看看系统用户真正需要多快才合适。当 叫需求候选(Requirement Candidate)。 来仿佛变了。我们曾为一家石油公司做
你看到用户在做这件事情的速度时,可 当有人说要“用户友好”的系统,这不 咨询工作,一家非常大的公司。构建的系
能会发现他们没法工作得那么快。这时 能成为需求,因为它是不清晰的 ,需求 统是有关他们所有购买的支付事宜的。
即使客户想要,这个需求也是不符合现 要明确。这时可以把“用户友好”叫做 要保证准时支付,不被欺骗等等。他们花
实和客观规律的。 “需求候选”。我们有一定数量的需求候 了 2500 万美金构建这个系统,最后把我
另外就是要辨别。这非常有用。不知 选,有些能做,有些不能做,有些可以 叫去看是不是做好了。我发了个邮件告
道中文里怎么样,但英文我们说需求这 同时做,还有些甚至所有的都可以做 , 诉他们公司所有人将就这件事开一个会,
个词时可能谈论的是完全不同的事,因 但可能负担不起。然后我们再进入决策 如果他们想讨论这个系统的话就应该来
为用同一个词有时会发生混淆。这在英 的过程,决定哪些需求候选成为真正的 开会。他们认为这傻极了,因为所有来开
Programmer 75
管理&实践 Management & Practices
需求分析 >>>
76 程序员
>>> 需求分析
铅笔和纸最有效,而不是电脑
—温伯格需求访谈实录
□ 整理 / 潘加宇
理解客户的真正需求
对于捕获需求,要记住,这
不是技术层面的事情,而是关于一方怎
样能理解另一方的问题。需求分析人员
首先要理解这一点,即使在对方没有意
识到的情况下。要理解从未有过的需求,
理解人们到底要什么,你的工作就是要
帮助他们找到真正所需要的。客户自己
通常是无法做到的。如果需求分析时牵
涉到不止一人,那一定会有不同的意见
出现,这时候还要帮助他们自己去解决
相互间的异议。例如,业务经理希望系统
速度很快,部门经理则关注成本。这里就
隐含着一个意思:他们可能没有足够的
资金来建一个快速的系统。您怎么能知 语里时常发生。我们有个很好的词叫需 需求。
道真正的需求是要系统快还是要成本低 求想法(Requirement Idea)。有人说我要 第四是要给需求排时间表。比如我
呢?开始你是不可能知道的。如果自己 一个快速的系统,要系统能够完成此项 们要构建一个功能但不是在发布第一轮
直接做这个决定,就会犯错。你所能做的 任务。其实这只是个需求的想法,你并不 产品时构建,那现在就不把它作为需求。
就是说服他们必须自己把这个问题先解 真正知道他们要什么,他们付得起什么
决掉。捕获需求非常有用的一个方式是: 样的价格,以及最终构建的系统是什么 很多时候需求根本没有变
当客户说要什么的时候,你可以去看看 样子等。比如说“用户友好”就只是一个 人们常说需求改变了,这是不对的。
系统的用户是怎样做这件事的。例如客 想法或者连想法都谈不上。 需求根本就没有变,而是一开始工作没
户说要系统有很快的速度,你就可以去 接下来就是澄清需求 。我们有个词 有做好,没有得到所有的需求,所以看起
看看系统用户真正需要多快才合适。当 叫需求候选(Requirement Candidate)。 来仿佛变了。我们曾为一家石油公司做
你看到用户在做这件事情的速度时,可 当有人说要“用户友好”的系统,这不 咨询工作,一家非常大的公司。构建的系
能会发现他们没法工作得那么快。这时 能成为需求,因为它是不清晰的 ,需求 统是有关他们所有购买的支付事宜的。
即使客户想要,这个需求也是不符合现 要明确。这时可以把“用户友好”叫做 要保证准时支付,不被欺骗等等。他们花
实和客观规律的。 “需求候选”。我们有一定数量的需求候 了 2500 万美金构建这个系统,最后把我
另外就是要辨别。这非常有用。不知 选,有些能做,有些不能做,有些可以 叫去看是不是做好了。我发了个邮件告
道中文里怎么样,但英文我们说需求这 同时做,还有些甚至所有的都可以做 , 诉他们公司所有人将就这件事开一个会,
个词时可能谈论的是完全不同的事,因 但可能负担不起。然后我们再进入决策 如果他们想讨论这个系统的话就应该来
为用同一个词有时会发生混淆。这在英 的过程,决定哪些需求候选成为真正的 开会。他们认为这傻极了,因为所有来开
Programmer 75
管理&实践 Management & Practices
需求分析 >>>
76 程序员
想法时,用这样的方式让他们个人付出 你们也看。几年前我参与了CA公司在夏 使用。简单的项目不应该用很多的工具
成本:如果你要我们考虑你的主意,你就 季奥运会的工作,构建一个记者使用的 或者软件来捕获需求。
要坐下来和我们一起工作,直到我们有 信息系统。当我们建成那个系统的时候, 一旦你对需求有了很好的理解,
当然
了清晰的需求候选。如果你不愿意花时 人们会带着变更需求的想法来找我们。 可以将它们放到电脑里,这样更容易管
间来和我们说清楚确切要的是什么,我 想法很好,但是我们只能拒绝,因为只要 理,或者做些小的更改。你从纸和铅笔开
们就不会把它作为需求。这是控制变更 奥运会开始,系统就结束了。至少在4年 始,
有时对于一些系统或者项目来讲这就
的一个根本依据。你不得不让人们在要 内,没有人会再用到这个系统。这是非常 足够了。我有的客户在项目里放一块大
求变更时有一定的成本,不然他们就会 高成本的系统,因此我们在系统的很早 板,加上几张纸就是所有要用的东西。项
变来变去。 阶段就对需求的变更订下了非常严格的 目最多有两周,1个月或者6周就结束了,
我记忆里有这样一家公司,他们的 规则。但另外的情形下你可能需要在整 把所有东西都输入电脑里太浪费时间。
业务是把灌装程序转换到另外的灌装机 个项目中都安排需求变更,这可能会持 对于大一些的项目,有了基本想法之后,
上,让同样的程序在新机器上做同样的 续多年。 可以放在电脑里,根据事情的规模而定。
事情。他们说就要做这个,让新程序和 如果项目在全世界好几个国家进行,你
旧程序做一样的事,不要增加,也不删 铅笔和纸最有效,而不是电脑 应该使每一个人都可以得到它,可以放
除任何东西,需求非常准确完整。在这 记录需求最有效的工具是铅笔和纸, 在服务器上,这样每个人都可以访问。我
种情况下,就可以告诉客户精确的成本 我喜欢用即时贴,或者用胶带把纸贴到 没有说铅笔和纸是唯一可以使用的工具,
和完成程序所需要的确切时间。如果客 桌子上,有时是地板上。我们把每个想法 只是它的是最开始要使用的,也是最简
户说我要做成一样的系统,只有有一点 写在一张纸上,放在地板上,移动它们, 单的工具。
点不同,这时候需求就会不确定了。通 把它们放在一起看,把相似或相矛盾的
常大多数情况就是这样的。极端的情况 放在一起,和人们交谈,就用这些纸片工 需求分析师应该具备的技能
是甚至要到了系统构建好你才知道需求 作,澄清问题。最糟的就是用电脑,尤其 我认为需求分析师要善于倾听,擅
是什么。例如,假设你在互联网上开始 是最开始的时候。如果这样做可就大错 长沟通,在写作上清晰易懂。你也许只是
做卖玩具的生意,你从前没有做过这样 特错了,太复杂了。它在你和你要获得需 一个可怜的软件开发人员,而面对的可
的系统,所以不可能在做之前就得到确 求的人中间平添一道阻碍。 能是高层的大老板,非常严厉又精明,你
切的需求。只有在真正投入其中之后才 另外的工具是,你要让 要能够和他们交谈。你
明白业务是怎样。这时你可以有一个样 你的耳朵保持工作状态,要 要在不懂的时候说我不
板需求。 听仔细,听清楚。也就是说 知道而不去猜。这种个
我们无论做什么都要很容易更改, 你要听清别人说什么。程序 人技能不是每个人都擅
不把任何事情完全确定下来,因为只有 员常常在寻找需求时认为 长的。你必须要能和人
当系统开始使用后才会有新的需求。许 他们要告诉客户,说服他们 们打交道。如果你不擅
多或者大多数的系统构建永远不会结束, 什么才是他们想要的,但这 长这些就不要做需求的
在整个需求过程中不断会有新的需求。 不是他的工作 。需求是倾 工作,让更有这方面的
50年前,我们使用瀑布过程,在设计或写 听,听清楚别人说什么,确 特长的人去做。在做需
代码之前把一切东西都做好。现在就不 认他们理解自己在说什么。 求时,我还会去找那些
会总是这样的情况了。你的软件过程必 做好了这件事才轮到我们 写作好的人。我的新书
须计划成在进行中随时都会有新的需求 开始说:你不能同时做这个 (Weinberg on Writing:
和澄清工作。每向世界发布一件产品,只 和那个等等。这些就是需求的工具。其它 the Fieldstone Method)就是有关写作的。
是此阶段需求的结束。一有新产品,系统 任何工具我都不会去用。有些不一样的 我发现这个圈子里的人们在写作上没有
就要变化。必须就计划成这样,时刻都要 地方就是,有些人用卡片,有些人不同事 很好的练习。如果他们不能用中文写得
将变化在项目中的成本计算在内,因为 情用不同颜色的纸,这都可以,但不要搞 很清楚,就做不好需求的工作。以上是我
每做一次变更都需要花一些时间。 得太复杂了。这也许不是你愿意听到的, 建议需求分析师去发展的技能。
现在正在进行冬奥会,我想在中国 因为做事情时总希望有个软件工具可以 ■ 责 任 编 辑 :霍 泰 稳 (htw@csdn.net)
Programmer 77
管理&实践 Management & Practices
项目实践 >>>
一个项目团队的敏捷之旅
□ 文 / 莫映
一直捉襟见肘,因此真正的大规模开发 待改进。改进需要时间,在有限时间内还
近日,欣闻首届“敏捷中国日”
直到最近才展开,客户对此却毫不知情。 要将部分精力投入到团队改进上,这无
开发者大会将于六月初召开 ,这无
先说说系统:整个系统由三个模块 疑增加了难度系数。好在通过与包括管
疑是中国敏捷开发者的一件大事。
构成,其中一个基于第三方系统开发,并 理人员在内的所有成员的沟通中,我了
敏捷方法历经数年传布 ,以其注重
且有一部分工作被外包了出去;另一个 解到,大家对团队改进的必要性和紧迫
实效的特质,已渐入人心,并开始焕
则迫于进度压力,沿用了来自其他项目 性都有所认同。这在一定程度上为团队
发出勃勃生机。不少一线团队更是
的一个遗留系统,虽然系统设计混乱,代 改进工作的开展创造了条件。
早已将其用诸实际 ,并从中获益良
码维护困难,但是以往的运行记录良好;
多。本文讲述了一个团队改进的故
最后一个模块则要从头做起。 第一个迭代周期
事,取自笔者近期接触的一个真实
再说说团队:由于项目中要用到 在和团队成员进行短暂磨合后,我
项目。希望能对那些关注敏捷方法
Struts、Spring 和 iBatis 框架,而成员们对 开始着手规划第一个迭代周期。
如何应用于实际项目的读者有所帮
这些框架的熟悉程度还不够。好在先期 ◆ 为了让这个复杂而棘手的问题尽
助。文中采用的敏捷实践主要来自
已为他们做了简短的培训,通过一个迷 量简单,同时也为了使我们能在力所能
极限编程(Extreme Programming),读
你教学项目,大家在短期内已经掌握了 及的范围内做得更好,我将大部分精力
者可以从近期出版的《解析极限编
如何使用“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”
:一个人
是人们熟悉的一种沟通手段,不过仅是用 灌输敏捷思想。言传身教的效果往往要 在操作键盘时,另一个人监督操作的正确
于沟通之用,刚好够用就行。 比纸上谈兵来得好。有一次,一位程序员 性。这样,我们可以及时发现迁移过程中
进入第二个迭代周期,团队的开发 告诉我,运行在他本机的系统出现了一 不小心引入的错误。
速度渐趋稳定。当我在迭代中期评估项 个诡异的错误,从异常堆栈来看应该是 ◆ 充分沟通可以减少孤独感,而结
80 程序员
一句题外话,有些人也许对结对存 会去响应请求。但是很多时候,有的“实 员学习不容易自学的知识,示范有效的
在误解,认为它妨碍了个人的私有空间。 例”也许要同时响应多个请求,而响应完 实践,也要对整个过程负责,保持团队在
其实,结对并不意味着不能独立思考,需 毕后又会马上被安排处理其他的请求, 可承受的节奏下工作,并持续改进。最
要时大家可以坐到一起,不需要时也可 因而池里永远都是空的,员工们得不到 后,作为教练的一项重要工作还包括:找
以回到各自的私人空间。理想的敏捷团 充分的修整。更有甚者,有的“实例”还 出知道答案的人,并把信息及时传达给
队对工作空间会有一定要求,比如敞开 未处理完当前请求,就会被“调度逻辑” 有权力做出决策的人。
的没有隔板的办公桌,但即便现实环境 重新分配,以响应别的请求。在这样的氛
有限制,也没什么大不了。相反,如果认 围下,人们只是满足于每个个体都在忙 更开阔的视野
同结对的价值,人们反而会更加珍惜在 于敲打键盘的虚幻效率,而忽略了应该 软件开发不仅是程序员的活动,缺
“恶劣”环境下的结对机会。 让员工尽量与熟悉和信任的同事在一起 少了对所有参与人的利害平衡,无论对
工作,也忽略了这种随意切换带来的高 项目还是团队本身,都将是危险的。技术
插曲三:人员更迭 昂代价(比如时间和精力的浪费,也许这 人员对敏捷方法情有独钟往往是从重构、
项目中期,曾有位出差归来的程序 可以换来两天的休息日,而非加班)。也 测试驱动这些明显带有浓厚技术色彩的
员中途加入团队。可是分配给他相应任 许将人比作可以随意调配的资源本来就 实践开始的。但是要想获得成功,只关注
务后还不到一周,他又被调到了别的项 是个错误。从这个意义上讲,人力资源 这些还不够。在敏捷方法的受众里,有些
目。于是,原本安排与他结对的程序员, (Human Resource)一词,至少在计算机领 人也许不能为开发做出贡献,但他们的
花了大约两天的工作交接和沟通时间都 域恐怕是一种误导。 观点对团队的成功却很重要,比如:项目
被白白的浪费了。此外,还有一种常见现 经理、测试人员、客户代表。项目进展期
象是“单人多任务”,比如有些成员还同 故事还在继续 间,我们要时刻注意协调技术观点与业
时承担着其他项目的工作。敏捷方法的 文章即将结束,不过项目仍在继续, 务观点的矛盾。此外,要想保证项目的成
观点认为:工作内容的频繁切换即不利 也许这样的敏捷实践案例就是我们不少 功,我们还要将视野扩大到团队以外。有
于团队的整体感和连续性,也不利于生 项目团队每天的真实写照。作为尾声,这 时,组织机构中主管人员所做的决策往
往会对团队产生很大的影响。如果漠视
或回避这些影响,恰恰就是漠视和回避
充分有效的沟通。经验告诉我们,在敏捷
方法的实施中,最大的困难在于:你需要
用事实来说服别人接受你的方式,尤其
是那些拥有决策权力的人。只有所有人
都有一致认同的价值观,敏捷方法才能
最大限度的发挥价值。
作者简介
莫映,北京慧点科技开发有限公司
我们可以发现,在团队改进中,教练 研究组织(www.redsaga.com)
生:作为一种创建代价高昂的资源,数据
成员。有多年软件从业经验,对极
库连接一般会被预先实例化并放入池中, 的角色至关重要。就如读者在故事中看
限编程和敏捷方法颇有心得,并参
一旦数据库访问请求到来,就会有池中 到的,我的职责是:发现团队改进的机
与和指导了多个软件团队的敏捷实
的实例来响应。类似的,某些组织中,人 会,并引导大家尝试解决问题;当团队在
践,取得了较好的效果。
们即被看作是一种可被池化的资源。当 压力驱使下做事时,提醒他们做简单的
有项目“请求”到来时,池中“实例”就 事情;既要有足够的技能来教导团队成 ■ 责 任 编 辑 :霍 泰 稳 (htw@csdn.net)
Programmer 81
管理&实践 Management & Practices
项目实践 >>>
轻松实现软件产品的国际化
—浅谈多语言带来的可用性问题
□ 文 / 刘大鹏
这篇稿子早在半年前就开 坚持看到最后,相信读者也不见得喜欢 决方案是双字节甚至多字节 Unicode的编
始在头脑中酝酿了,但是却迟迟没有下 吧!因为如果在内容中不能很好的突出 码和界面支持。
笔。原因有二:一是这个命题实在太大, 文章要意,这本身就是种不友好的用户 2. 从具体执行和管理角度来讲,多
微软甚至有一个庞大的机构和部门在负 体验!但是最后经过和编辑的交流,还 语言和本地化不仅仅是简单的静态翻译。
责国际化(Internationalization)、全球化 是决定暂时从几个主要的方面做个重点 多语言和本地化过程是一个庞大的系统
(Globalization)和本地化(Localization)的 的说明,以点带面,抛砖引玉,便于使一 工程,需要由多方面、跨学科的团队进行
工作,并且在MSDN上长期在线解决相关 些还不是很清楚国际化多语言软件产品 (如可用性专家、本地化工程师、专业翻
的问题。况且由于杂志本身的篇幅所限 的战略意义和正确实施方式的软件企业、 译人员,集成项目经理,发布测试管理人
和我们需要重点阐述易用性的出发点, 工程师们,能够快速的了解国际化软件 员,界面工程师等)。
我们只能要么对其做大而全的乃至长篇 产品的设计和开发方法,同时也希望借 3. 从易用性测试和产品架构设计角
大论的叙述,要么专注在某些具体的点 此提高大家对于多语言带来的易用性问 度讲,良好的多语言和本地化支持是一
面来做透彻深入的说明;其二是希望能 题的认识。 个重要的可用性检测指标,因为它体现
够开辟技术类杂志新的文风,因为就个 首先我们先明确几个概念和观点: 了我们产品界面中出现的文字和字符是
人的体验来说,很少能够坚持把一篇掺 1. 从具体技术实现角度来讲,到目 否具有相当的可读性和一致性水平——
杂着各色代码和充斥着行业术语的文章 前为止,国际化多语言软件的最优化解 即是否清晰可读、可见能够正确表述功
82 程序员
能和传达给用户有用的信息,并且符合 如果企业沟通软件出现了软件界面上或 创业型企业,而失去了做大做强的机会。
用户的操作和认知习惯。 者中英文文字由于不可读造成互相不兼 软件国际化和多语言的最高境界就
容,那么可想而知后果是什么,这可能导 是很好的本地化。近年来随着国际化和
什么是 Unicode? 致一个季度的预算和销售都可能会受到 本地化需求的不断出现和生产力水平的
为什么要使用 Unicode? 影响,数以千万资金可能遭受损失…… 提高,国外大型国际化软件常常需要发
布几十种语言的本地化版本,但是对于
Unicode provides a unique number for every character,
Programmer 83
管理&实践 Management & Practices
项目实践 >>>
我做事情就喜欢将事情做大。”随即唐骏 www.microsoft.com/globaldev/default.
从洛杉矶跑到西雅图对微软说,
“只要让 mspx 的“坐诊”博士 International 十几年
我进微软,让我干什么都行。”随后他被 来一直兢兢业业的回答关于本地化和国
分到 Windows NT开发组做程序员,当时 际化的问题,而对于他的贡献大家如果
正值1994年。
(这个日期和Dr International 有兴趣的话可以认真的阅读他的著作并
出版 Developing International Software 第 且到网络上查看,但是至于与唐骏的渊
一版的时间几乎吻合,不知道两者之间 源就无从考证了。
是否存在必然的联系?)” 图 3:Windows 95/98/Me 下 无 法 正 常 地 示多语言
Microsoft Press出版社出版的《Developing
International Software》一书做出过很大
的贡献,这也就难怪他会获得微软授予
的最高荣誉——比尔・盖茨总裁杰出奖 图 5: 在 VC.net 编 译 器 中 内 置 的 Unicode 支 持
84 程序员
在项目的编译设置中选择相应的字符集 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
和应用尚且需要非常大的工作量并且会 刘大鹏,易用性
占用大量的磁盘空间。最重要的是还会 解决方案三的描述和示意图 和交互设计研
带来版本的维护问题:如果一个翻译字 这种方法应该说是对于上一种方法 究和交流平台
不是把所有的语言包都整个封 美国 ACM 人机
交互特别兴趣小
装在一个资源文件中,而是把
组 SIGCHI及 UPA(易用性专业协会)
他们相对物理分开,这样一来
成员,具 有 丰 富 的 行 业 背 景 和 嵌 入
便可以针对于大型软件系统不
式系统易用性设计经等。
同的模块有针对性的进行多语
English.exe Chinese.exe Japanese.exe 言处理,并且方便对新的语言 ■ 责 任 编 辑 :霍 泰 稳 (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
项目实践 >>>
对任何出错信息的设计,都应该按
照下面这个设计原则来进行:
● 出错信息首先应该向使用者明确
说明,究竟发生了什么问题或错误;
● 出错信息应该向使用者解释是何种
原因造成了出错,即到底是因为使用者的
错误使用还是系统本身的问题造成了问题;
● 出错信息还应向使用者提示,应
该采取什么样的措施或纠正的步骤,来
纠正错误或避免错误,使得使用者可以
继续使用软件。
所有的出错信息的设计必须通过设计
规范书进行全面的记录和总结,然后在程
序开发时开发工程师要根据这些设计来开
发。也就是说,任何出错信息都必须是事
先设计好的,而不应该由程序编写者心血
来潮似地任意加入到软件中去。在开发过
图 2:Treeview 列 表 界 面 设 计 程中要是发现有新的出错信息需要加入产
88 程序员
的质量控制、项目的执行与驱动的管理
指南等内容展开讨论。如果要进一步学
习具体的关于开发管理的实践指南,可
图 像 界 面 设 计 总 结 — — 状 态 条( Status Bar) 的 功 能 设 计 以参考由我所著的《软件开发项目管理》
里程碑 图像界面组成部分 界面的使用和反馈行为
一书。该书可在各地新华书店以及网上
● 默 认 值 文 字 : 可 正 常 使 用
M1 Filed 1: 普 通 的 状 态 文 字 ● 其 它 时 候 显 示 此 设 计 规 范 中 其 它 地 方 所 指 定 的 工 具 的
书店如第二书店(www.dearbook.com)等
状态文字 购得。
在检测其它依赖组件以及操作系统镜像生成时候,每当
M3 Filed 2: 渐 进 显 示 条 工具需要有 2 秒以上的等待时间时,显示渐进显示条。 作者简介
操作系统镜像的总数显示应该是:
● 当没有一个镜像设计被装载在工具中 ,不显示任何数字 。 栾跃是微软总部产品
Filed 3: 显 示 操 作 系 统 镜 像 ● 当 一 个 操 作 系 统 的 设 计 镜 像 被 装 载 在 工 具 中 后 , 显 示 部门具有多年项目管
M2
的大小总数 以兆为单位的、带一个小数点的、非压缩的操作系统镜
理经验的华人项目经
像的大小总数。
理之一,具有在美二
显示目前工具所连接的数据库:
● 当 工 具 刚 启 动 时 , 还 没 有 数 据 库 连 接 上 时 , 不 显 示 任 十年的高科技产品开
M4 Filed 4: 显 示 所 连 接 的 数 据
何数字。 发和项目管理的经验。曾任摩托罗拉
库的名字
● 当 一 旦 连 接 上 数 据 库 后 , 显 示 数 据 库 连 的 名 字 。
的产品经理。98年加入了微软,先后
图 3: 软 件 界 面 的 设 计 用 图 像 加 文 字 解 说 负责了 ActiveSync 3.0和嵌入式操
品,
加入的过程同样要按照设计的要求进 中去的最有效方法。 作系统 XPE等产品开发的项目管理。
目前栾跃是微软总部中国事务办公室
行,在对设计规范书经过修改、加入新的 上面一文对软件开发项目管理的设计
的首席项目经理。
设计之后,才能进行程序的改动。严格的 规范书的撰写指南作了一个简单的介绍。
管理方法是避免荒唐可笑的文字混进产品 接下来的几期中,我会就软件开发项目 ■ 责 任 编 辑 :霍 泰 稳 (htw@csdn.net)
Programmer 89
管理&实践 Management & Practices
管理工具 >>>
XP团队管理的利器
— XPlanner
□ 文 / 俞黎敏
90 程序员
XPlanner 的使用 息。这有些像上下班打卡一样,小组成员 通过 XPlanner 这个工具,可以实现
安装很简单,这里不做详细介绍,想 每完成一个分解的任务后,就去“打卡” 上文所提到的多个方面,并且紧密配合
进一步了解XPlanner的朋友可以到Google 一下,这也是一种工作的促进,实时呈现 极限编程思想。但在项目中采用
或者百度搜索一下。下面我以“使用 工作进度。这个迭代结束了,就可以将它 XPlanner 是一个开始 ,在此基础上我们
XPlanner”为主题通过一个项目对它进行 结束。XPlanner提供将未完成的用户故事 还可以利用单元测试框架 、集成测试 、
简要说明。 转到其它迭代里面去的方法,用户故事 BUG 跟踪管理等工具来组合出一套适合
首先,创 建 一 个 项 目: 可以采用 里的任务没有完成也可以将之移到别的 自己项目组的管理平台。目前在开源社
TWiki- 样式的文本格式进行描述项目的 用户故事里或者其它迭代周期里去。 区里,相关的软件都可以容易地得到。
内容,这样在最后展现出来的内容相对
来说比较活泼一点,同时设置所要连接 在项目中采用 XPlanner 是一个开始,在此基础上我们还可以
Wiki 的地址,使得可在XPlanner里链接到 利用单元测试框架、集成测试、BUG 跟踪管理等工具来组合出一
Wiki 进行技术交流。 套适合自己项目组的管理平台。
创建用户并授权:可以根据 XPlanner
所提供的 Excel 模板输入用户的信息,然 可以在项目一级和迭代一级进行导 对于项目经理来说,一般既是管理
后把前四行删除,再另存为.csv 格式的 出,生成Project 格式的任务表,完整地显 人员,又是教练,而且是开发人员,然
文件后进行批量导入,比较方便。可以在 示出上下级与任务的层级关系,任务完 后凝聚着几个小组成员在周围进行项目
创建用户时就按项目直接授予他应有的 成情况也可以在里面体现,并且把人员 实施。全局上关注的就是每天跟踪迭代
角色,或设置为系统管理员,也可以在今 资源也进行导出,还是比较方便的;美中 过程中的用户故事进度情况,细节上就
后管理用户时再进行相应的项目授权不 不足的是不能够按任务的顺序显示,并 得追踪到每个成员的当前任务完成情
同的角色,XPlanner 里的角色有 None、 体现前后关系即前置任务,TWiki样式的 况,对比分析查找问题,跟踪进度,解
Viewer、Editor、Admin。 描述与备注仍是原样输出。任务准确按 决开发过程中遇到的一些问题,调配资
创建迭代:进入刚才创建的项目,开 时或超时完成的会显示任务完成提示, 源,协助项目内外交流沟通反馈,积极
始创建第一个迭代,设置迭代的开始时 但提前完成的却不会, 推动项目前进。在用户故事搜集与每次
间与结束时间,这样在迭代结束之后可 迭代提交产品经过用户试用后所提出的
以进行统计,对比分析迭代预估时间的 给项目管理人员带来的好处 新需求的基础上,进行分析并做出优先
准确性。 一直在思考如何提高管理与开发的 级排序。
创建用户故事:进入迭代,就可以创 水平,也在逐步地开始实施XP极限编程。
建用户故事,指定客户、跟踪者、状态、 但如何能更好地运用发挥极限编程的威 总结
优先级,当然重要的是根据在用户那挖 力是件比较棘手的事情,如何调动大家 XPlanner 作为一款专业的开源的 X P
掘到的需求进行优先级设置,1为最高级 的积极性,让一个项目组的所有人员更 项目管理工具,还可以整合Wiki,默认支
别。可以通过模板进行批量导入。 好地参与到项目中来,是一个项目成败 持 Very Quick Wiki,它的安装和配置也
分解任务:进入某个用户故事,把它 的关键问题。 很简单,详细信息请参考 http://www.
分解为一个个小任务,指定任务类型、任 项目组成员包括客户、项目经理、开 vqwiki.org/,所有的这一切都是为了更
务接受者、估计的时间等。重复以上各步, 发设计人员、测试人员、界面设计人员 好地使用 XP 进行项目开发。
这样,就把项目的第一次迭代里的用户故 等。每个部分的人对项目关心的内容和
作者简介
事及故事分解的任务创建完成,接下来就 角度是不同的,例如:客户关心最终的产
是要记得启动这次的创建迭代,然后小组 品是否简单易用;项目经理关心开发进 俞黎敏,广东力维软件有限公司项目
Programmer 91
管理&实践 Management & Practices
新视点 >>>
澄清对 MDA 的误解与误用
□ 文 / 孙向晖
引言 原始需求失真,最后开发的系统不是客 更要说明的是,由于验证周期越来
MDA是OMG在2002年初确 户想要的系统; 越短,最终用户(或者业务专家)可以快
定的战略方向。然而,时隔多年,即使在 ◆ 开发层次多,费时费力; 速、真实得看到可运行的系统,可以及时
技术日新月异的今天,MDA 在业界依然 ◆ 初始模型被肢解,系统到了一定 做出响应和反馈,更增加了他们参与开
算得上前沿技术。在社区里我们可以听 复杂程度后,维护成本太高; 发的兴趣。有了业务专家积极参与的项
到这样或者那样的声音,有些源于 MDA ◆ 需求变更后,软件更改繁琐,难 目,距离成功就更近了一步。
概念的误解,有的是对应用 MDA 过程中 以快速适应需求变化;
产生的困惑,当然也不乏呐喊助威声。 ◆ 开发过程对技能的要求和团队成 MDA,更注重 Model 的作用
有争鸣总是件好事。 员的实际技能出入太大; MDA 的英文全称是 Model-Driven
笔者所在的团队,从事 MDA 理论的 …… Architecture。如果你在看到“Model”而联
实战化和 MDA 工具的开发工作已经 3 年 想到了用 Rose 或者 Magic Draw 画出来的
有余。对于MDA在提高软件开发效率、增 UML 图,那么,再次恭喜,
强软件可移植性、可维护性以及改善和 你又一次“曲解”了MDA。
提升团队成员协同工作能力方面,略有 不错,大部分的
心得。希望借助这篇文章抛砖引玉,与关 MDA 工具厂商都支持基
心 MDA 的同行们交流、共享。 于UML的XMI交换,但请
不要忘了 OMG对 UML的
MDA,更强调人的价值 定义:
一位同事,在早期听到过这样一种 图 1:Loushang MDA 开 发 方 式 在 项 目 实 战 中 的 作 用 范 围
The Unified Modeling
说法,
“有了MDA,程序员就失业了”,结 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 主管的业务疾痛。而不是谁是第一 (Context)和子系统(SubSystem)。
这只是领域建模中的 50%,即使使用这 步就认为谁是重要的。
样的大图,也不会有人认为你可以悠闲 MDA 的开发过程就是让用户或者业 小结
得完成 MDA 实现,相反,团队成员会认 务专家,更加关注业务核心价值。 本文不是对 MDA 进行学术研究,我
为你已经疯了。 ◆ 职责分层 的目标是利用 MDA (或者其他的开发方
要想有效得应用 MDA ,我们可以借 做过数据仓库实现的人,会有这样 法)来解决业务和开发过程中的问题。
助若干领域建模的技巧和方法,来提高 一种常识:要把数据进行划分,比如分为 MDA 在开发过程中,对“生产力的解放”
项目成功率: 从不改变的、偶尔改变的、经常变化的 是大家有目共睹的,而针对领域语境进
◆ 优先关注核心价值 等。另外要认真思考模型中的概念之间 行精细建模将会在更大的程度上发挥
我在提供咨询服务时,曾经问过很 的相互依赖关系,它们之间的变动速率 MDA 的作用。
多团队同样的一个问题 ,“如果你的客 以及导致领域各个部分发生变化的来源, 作者简介
户要求上马一个人力资源系统,你认为 以界定领域的自然层次,这就是领域建
孙向晖:儿子小名
应该先实现哪部分?”得到的答案大致 模技术中的职责分层。
“豆豆”,常被人称为
都是相同的,“入职”。如果再深究得出 职责分层并不是IT界的产物,它属于
“豆豆他爹”。1998年
此答案的基本思路,也会是惊人的一 领域建模技巧。在我看到的若干国际知
开始步入 IT行业,现
致,“因为增加人员是人员管理中的第 名的咨询公司的报告中,经常会用到职
就职于浪潮软件技
一个步骤”。 责分层的图示。在 IBM 的 SOA 解决方案
术研究中心技术管
这个问题的答案或许是对的。但其 中,我也亲切地看到了职责分层的应用。 理部。负 责 指 导 内 部 团 队 和 合 作 伙
思考问题的出发点却是个不折不扣的错 这无疑是在说明,这种思维方式的共通 伴开展基于 Loushang框架的OOAD
误。它错就错在 “要准确回答这个问题 之处。 开 发 和 开 发 过 程 管 理。目 前 专 注 于
的关键,不是‘你认为’,而是‘你凭什 ◆ 边界 研究和实践MDA/UP/UML/SCM等
么认为’”。 即使是看待同样一个事物,因为观 相 关 技 术 在 团 队 中 的 大 规 模 应 用,
目前的人才市场,供大于求,企事业 察者站的角度和立场不同,最后得到的 对 产 品 化 的 软 件 项 目 管 理 、需求管
Programmer 93
管理&实践 Management & Practices
管理圈 >>>
激发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
管理圈 >>>
98 程序员
>>> SUN 征文
Programmer 123
产品&应用 Product & Application
SUN 征文 >>>
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的规
表 1: 三 套 软 件 的 价 格 表
公司 产品 价 格 (美 元 )
IBM Rational Software Architect 5500
Borland Together for Eclipse Architect Edition 5000
Sparx Systems Enterprise Architect Corporate Edition 239 图 1:UML 2.0 规 范 的
126 程序员
>>> 工具点评
Programmer 127
>>> Java
Apache Shale 引领
JavaServer Faces 再上新台阶
□ 张钢 涂耀旭
Programmer 99
技术 Technology
Java >>>
<!— 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>
<view name="Email Preferences" viewId=
"/emailPreferences.jsp">
图 1:Launch Party Application 状 态 图 <transition outcome="next" target="Snail Preferences"/>
100 程序员
>>> Java
<transition outcome="payNow" target="Payment"/> ...
</view> <h:commandButton id="next" action="next" value="Next >>"/>
<h:commandButton id="exit" action="exit"
<subdialog name="Payment" dialogName="Process Payment"> immediate="true" value="Exit"/>
<transition outcome="next" target= </h:form>
"Email Preferences"/> ...
<transition outcome="cancel" target="Email Preferences"/>
</subdialog>
清单3. userid.jsp显示了带有Action属性的commandButton
<view name="Snail Preferences" viewId= Action在您需要调用Java对象的函数时被使用。Action Java
"/snailPreferences.jsp">
<transition outcome="previous" target= 类可以是 POJO 或 ViewController (另一个 Shale特性)。就像JSP
"Email Preferences"/>
<transition outcome="finish" target= 中的 CommandUI,这些Java函数也需要返回一个String 值。清单
"Save Preferences"/>
</view>
4 显示了 POJO RegistrationBean 返回的 String“success”:
<action name="Save Preferences" method= ...
"#{preferencesBean.save}"> public class RegistrationBean
<transition outcome="success" target="Exit"/> {
</action> ...
public String createNewRegistration()
<end name="Exit" viewId="/goodBye.jsp"/> {
</dialog> return "success";
}
<!— Take Payment Dialog — > ...
<dialog name="Process Payment" start="Credit Card"> }
...
</dialog>
清单 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”:
...
... <dialog name="Create New Registration" start="User ID">
<h:commandButton id="startNewRegistration" action="dialog:Create ...
New Registration" value="Start New Registration>>"/> <transition outcome="exit" target="Exit"/>
...
<!— User Name — >
清单 2. start.jsp 中 dialog:Create New Registration的 Action值 <view name="User ID" viewId="/userid.jsp">
<transition outcome="next" target="Register"/>
让我们来检查<dialog>的每一个组成部分,即<view> 、 </view>
<action>、<transition>和<end>结构。当您请求通过表示技术 <action name="Register" method=
"#{registrationBean.createNewRegistration}">
(为了简便,假定JSP 就是表示技术)指引用户交互时,将使用 <transition outcome="success" target=
视图。这些JSP 都是支持JSF的,这意味着它们使用HTML和Core "Email Preferences"/>
</action>
JSF 标签库。通过 Apache Shale引擎的 Command UI控件(JSF的 ...
<h:button/>和<h:link/>的action属性),它们会将String值返回
给 Apache Shale 引擎。清单 3 显示 userid.jsp 中操作值为 next 和 清单 5. userid.jsp 返回的“Next”和“Exit”值的Transition
终端节点指示对话结束。当遇到END 时,对话管理器的内
exit 的两个按钮:
部引擎知道弹出对话框。Shale建议通过这个来理解对话管理器
...
<h:form id="userid" onsubmit="return validateForm(this);"> 本身。
Programmer 101
技术 Technology
Java >>>
如果不讨论自成体系的subDialogs,关于对话管理器的任何 调用“Process Payment”对话时,subDialog处理“Process Payment”
讨论都不会完整,示例应用程序中完成这一任务的是“Process 返回的结果。
Payment”对话。在注册过程中,用户可以选择是否付款(这并 对话管理器的所有特性都存在对话域状态信息。示例应用
不 是 我 们 所 有 人 都 希 望 的 )。当 用 户 明 确 选 择 这 样 做 时 , 程序在emailPreferences.jsp中使用这一特性,这里值被保存在由
“Process Payment”开始起作用。 对话管理器管理的“#{dialog.data.receiveEmail}”和“#{dialog.
清单 6 显示这一切是如何协同工作的。 data.alternateEmail}”属性中,一旦用户处于对话之外,这些值
将会在域中消失。
...
<dialogs>
保持用户经过验证
<!— New Registration Dialog — >
如果您想让用户使用向导更舒适,应该使他们在客户端和
<dialog name="Create New Registration" start="User ID">
...
服务器端保持一致。下面介绍 Shale 验证:
<subdialog name="Payment" dialogName="Process Payment"> 使用 S t r u t s 时,可以通过重写 A c t i o n F o r m 中的验证
<transition outcome="next" target="Email Preferences"/>
<transition outcome="cancel" target="Email Preferences"/> (ActionMapping、HttpServletRequest)或在 XML 配置文件中声明
</subdialog>
... ActionForm 字段的验证来提交服务器端验证。在Struts中,确保
</dialog>
服务器端和客户端一致性验证是困难的,如果可能的话,客户
<!— Take Payment Dialog — >
端验证将通过 DynaValidatorForm 消极地完成。
<dialog name="Process Payment" start="Credit Card"> JSF对Validations的支持略好一点。JSF通过它的javax.faces.
<view name="Credit Card" viewId="/creditcard.jsp">
<transition outcome="submit" target= validator.Validator接口、<f:validator/>标签和faces-config.xml配
"Process Credit Card"/>
<transition outcome="cancel" target="Exit"/> 置文件设置提供一个可插入的验证框架。它提供三种指定的验
</view>
证,即DoubleRangeValidator、LongRangeValidator和LengthValidator。
<action name="Process Credit Card" method= 尽管这是一个好的开始,但这与您在真实世界应用程序中可能
"#{paymentBean.processCreditCard} ">
<transition outcome="success" target= 遇到的验证类型相差甚远。
"Thank You For Payment"/>
</action> JSF 也似乎完全忽略了客户端验证。虽然服务器端验证是
<view name="Thank You For Payment" 完全必要的,但是有辨别地使用客户端验证,通过减少与服务
viewId="/thankYouForPayment.jsp">
器往返的行程,可以提高应用程序的性能,甚至可以改善用户
<transition outcome="next" target="Exit"/>
</view> 体验。
<end name="Exit"/> JSF 做得好的地方就是它允许您增加您自己的验证。Shale
</dialogs>
供以下附加的服务器端和客户端组件:
u Credit Card
“Process Payment”对话框的。 u Generic
在“Process Payment”对话的终端节点中,
“Exit”缺少viewId u ISBN
属性。因此,当“Credit Card”和“Thank You For Payment”视 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”之间唯一 ...
<%@include file="messages.jspf"%>
的联系就是,当“Create New Registration”对话中的 subDialog
102 程序员
>>> Java
...
WEB-INF/web.xml 中定义的属性和资源值的访问。简单地说,
<h:form id="userid" onsubmit="return validateForm(this);">
这意味着 Apache Shale 可以使用以下功能:
<h:outputText value="*** DEBUG MODE ***" rendered="#{jndi.
debugMode}"/> u 您可以使用web.xml中的<env-entry>来定义环境项的值,
...
<h:outputText value="* Email Address:"/> 当“#{jndi.XXXX}”表达式(这里XXXX是web.xml 中的项名称)
<h:inputText id="email" value="#{registrationBean.email}">
<s:commonsValidator type="required" message=
在 JSP 或它的支持bean 中被使用时,Shale会提供对它们的访问。
"#{launchPartyMessages.EMAIL_REQUIRED}" client= u 您可以使用web.xml中的<resource-ref>定义资源,Shale
"true" server="true"/>
<s:commonsValidator type="email" message= 将在动态创建资源时根据定义进行值绑定。
"#{launchPartyMessages.EMAIL_INVALID}" client=
"true" server="true"/> Launch Party应用程序使用第一个特性来决定一个应用程序
</h:inputText>
<h:message for="email" styleClass="errors"/> 是否以调试模式运行。debugMode环境项在web.xml(如清单10
...
所示)中定义,然后在所有的 JSP 页面中使用:
<s:validatorScript functionName="validateForm"/>
...
...
<env-entry>
清单 7. userid.jsp 中的 Email Validation <description>
Flag indicating whether we run in debug mode
userid.jsp 中的 email address字段是必需的,它必须是合法 </description>
的电子邮件地址格式。清单7使用两个<s:commonsValidator/> <env-entry-name>debugMode</env-entry-name>
<env-entry-value>true</env-entry-value>
标签,一个类型是“required”,另一个类型是“email”。客户端 <env-entry-type>java.lang.Boolean</env-entry-type>
</env-entry>
和服务器端验证都被启用。 ...
客户端验证需要<s:validatorScript/>,它生成在JSP页面中
清单 10. Web.xml 中的 ebugMode环境项
进行运行时验证的 JavaScript 函数,在 h:form 标签中,onsubmit
注意所有 JSP 页面中的<h:outputText value="*** DEBUG
函数设置为使用由<s:validatorScript/>创建的验证函数。
MODE ***" rendered="#{jndi.debugMode}"/>。
通过在 userid.jsp顶部巧妙地包含messages.jspf,用户违规
时显示的消息将从 LaunchPartyMesssages.properties 文件得到。
结束语
LaunchPartyMessages.properties 是一个普通的资源包,包含
本文只是露出冰山一角。Shale 的全部能力将给基于 JSF的
了错误消息的键 / 值对(如清单 8 所示)。这个文件位于com/
Web 应用程序带来很大的好处。例如,Clay集成为JSF应用程序
techyatra/shale 文件夹下,这也是 Launch Party 应用程序的 Java
提供了组件化的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 JavaServer Faces (JSF) 是一种用于构建Web应用
Messages.jspf contains declaration of variable launchPartyMessages
using JSF's <f:loadBundle/> tag as shown in Listing 9 below. 程序的标准 Java 框架。它提供了一种以组件为中心来开发
...
<f:loadBundle var="launchPartyMessages"
Java Web用户界面的方法,从而简化了开发。JavaServer
basename="com.techyatra.shale.LaunchPartyMessages"/> Faces 已经引起了广大 Java/Web开发人员的兴趣。
“企业
...
开发人员”和 Web 设计人员将发现 JSF 开发可以简单到只
清单 9. Messages.jspf 需将用户界面(UI) 组件拖放到页面上,而“系统开发人员”
Shale Validation代码在org/apache/shale/validator/validator- 将发现丰富而强健的 JSF API 为他们提供了无与伦比的功
仔细阅读它,它是相当引人入胜的! 制器(MVC)设计模式集成到它的体系结构中,确保了应用程
序具有更高的可维护性。如果您觉得需要更深入了解 JSF,
推荐访问官方网址:
直接连接到 JNDI
http://java.sun.com/j2ee/javaserverfaces/
JNDI提供应用程序所需的大量目录服务访问。Apache Shale
http://www.jcp.org/en/jsr/detail?id=127
的 JNDI模块不是一个非常广泛的 JNDI实现。它只集中提供对/
Programmer 103
技术 Technology
微软技术 >>>
深入解析 P/Invoke
□ 文 / 刘华军
概述 3.ϵͳĿ¼£¨Ê¹ÓÃGetSystemDirectory()º¯Êý»ñÈ¡µÄĿ¼£©£»
CLI在设计的时候就已经考虑到了与已有的代码进行交互操 4.16λµÄϵͳĿ¼£»
作的问题,而且这种交互操作要尽可能的简单。你所要做的只 5.WindowsĿ¼£¨Ê¹ÓÃGetWindowsDirectory()º¯Êý»ñÈ¡µÄ
是为要调用的代码创建一个 DllImport 函数声明,运行时库将会 Ŀ¼£©£»
处理所有余下的工作,就像下面这样: 6.ÔÚPATH»·
¾³±äÁ¿ÖÐÁгöµÄĿ¼¡£
不过,现实总不是那么简单。事实上,系统目录指的是
[DllImport("kernel32.dll")]
public static extern bool Beep(int frequency, int duration); %WINDIR%\system32,Windows 9X平台上则是%WINDIR%\system,
16 位的系统目录一般是 %WINDIR%\system,不过在Windows
上面这段 C# 函数声明会发出 Beep 的系统调用,在带有
kernel32.dll的平台上将会成功调用,而在不带有该dll的其他平台 9X 平台上它不会作为一个单独的搜索目录。
1.ÔÚDllImportÉùÃ÷ÖÐÖ¸¶¨¿âÎļþ£» 进行调整。如果值为1(默认值),那么当前目录将在系统目录
和 Windows目录之后搜索。这是出于安全性的考虑(以免特洛
2.È·¶¨ÐèÒªµ÷Óõĺ¯Êý£»
3.¾ø´ó¶àÊýµÄÒÑÓдúÂ붼Ï൱¸´ÔÓ£¬ÐèÒª´«µÝ×Ö·
û´®¡¢½á 伊木马会抢在正常的系统文件前加载,比如,OLE32.DLL),不
¹¹£¬Ò²Ðí
»¹ÒªÉæ ¼°µ½ÄÚ´æ¹ÜÀí¡-¡- 过这样做的结果就是把上述的搜索顺序变成了: 1, 3, 4, 5, 2, 6,
在调试程序的时候如果碰到这方面的问题,不妨考虑一下这种
已有的代码看起来就像一头难以驯服的怪兽,而交互层
(interop layer)则必须要处理这一切的复杂性,让这头怪兽乖乖 情况。
听话。
下面还是让我们从头说起。 库文件名称
知道在哪里搜索库文件只是问题的开始,还必须要知道哪
库文件的处理方式 个库文件是需要加载的。不同的平台有不同的命名方式。
不过.NET 从一诞生,目标就是跨平台的,如果在不同的平
运行时库如何找到DllImport属性指定的库文件?这个问题
是与平台密切相关的,我们目前只关心Windows 平台,所以下 台上,对应函数的库文件名不一样怎么办?比如GTK+ 在Win-
1.
¼ÓÔØÓ¦
ÓóÌÐòµÄĿ¼£» NET 中没有提供指定平台相关的库文件名称的标准方式。
不过,Mono提供了解决这个问题的扩展方式——库名称映
2.µ±Ç°Ä¿Â¼£»
104 程序员
>>> 微软技术
射机制。库名称映射可以通过两个地方的配置文件来实现,一 新你的程序集,由于以上原因,显而易见你的程序集将是非常
个是 ¥prefix/etc/mono/config 的 XML 文件,另一个是每一个 难以维护的。
assembly的.config 文件,在与assembly相同的目录下。这些文件
都包括了<dllmap/>元素,映射了输入库文件名(在 DllImport 内存分配
中声明的库文件名)和实际的与平台相关的库文件名。比如: 托管和非托管内存在考虑的时候应该完全独立开。托管内
存是完全由GC管理的内存堆中分配的,而非托管内存则是其他
<configuration>
形式分配的内存:ANSI C 的内存池通过mallco 分配的内存、自
<dllmap dll="libgtk-win32-2.0-0.dll"
target="libgtk-x11-2.0.so" /> 定义的内存池,以及不在 CLI 实现范围内分配的内存堆(比如
</configuration>
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 函数,而且使用编译器支持的 在大多数 P/Invoke和封送的过程中,我们都可以忽略内存
调用方式; 管理的问题,不过对于返回值,CLI所做的一些默认处理必须予
(2) 没有使用 extern "C",不过使用了编译器支持的调用 以考虑。
方式。这种方式是不推荐的,如果你这么做了,那么你必须将 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:
ÍйÜÄÚǽÖеÄÒ»¸ö·
ÇÍйܽṹ£»
typedef void* HANDLE;
2.ÏàÓ¦
µÄÍйÜÀàµÄʵÀý¹¹Ôì
Íê³É£¬·
ÇÍйÜÄÚ´æ µÄÄÚÈݱ»·
â
ËÍ
µ½ÍйÜÀàʵÀýµ±ÖУ» bool CreateItem (HANDLE *item);
void DestroyItem (HANDLE item);
3.·
ÇÍйÜÄÚ´æ±»ÔËÐÐʱ¿âµ÷ÓÃMarshal.FreeCoTaskMem·
½ int GetInfo (HANDLE item);
·¨ÊÍ·Å¡£
“类型安全”的 C# 封装形式象下面这样:
那么Marshal.AllocCoTaskMem,Marshal.ReAllocCoTaskMem和
struct Item {
Marshal.FreeCoTaskMem具体又是如何实现的呢?答案是与平台
[DllImport ("library")]
相关的。在Windows系统下,使用的是COM任务内存分配器(通
public static unsafe extern
过 CoTaskMemAlloc,CoTaskMemReAlloc和 CoTaskMemFree 三个 bool CreateItem (out Item* item);
[DllImport ("library")]
尽量避免封送 public static unsafe extern int GetInfo (Item* item);
虽然上面一再提到了封送,而且看起来P/Invoke离开了封 }
送这个信使就根本无法与非托管的世界产生联系,但是封送并 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);
后者的一个很好的例子是 GTK+库。GTK+是一套面向对象 }
}
的工具库集合,用 C 语言写成。和所有的面向对象库一样,它
有数不清的派生类,每一个派生类都有不同的大小,而且类实 这样是类型安全的是因为你不能传递任意的内存位置给这
例通常是通过指针访问的。同样,因此在托管和非托管内存之 些静态的以 Item 指针作为参数的函数,你必须传递一个指向
间封送整个类就没有其他选择了,拷贝是不行的,只能采用同 Item 结构的指针。这并不是类型安全过于严苛,而是为了将意
样的方式来访问。 外的内存崩溃降低到最低限度。不过这里最大的问题是它使用
另外的例子是使用“不透明的”数据类型,这里的“不透 了“unsafe”的代码,因此不能在其他的.NET语言中使用,比如
明的”指的是数据类型完全通过指针来进行传递,数据类型的 Visual Basic .NET 和 JavaScript。
内部信息没有任何东西是公开的。这方面一个最典型的例子就 上述代码的 CLS 兼容版本则使用 System.IntPtr来指向非托
是 Win32 API 中的句柄,它无处不在,却又让你毫不知情。 管内存。这看起来很像是Marshal类在与非托管内存交互时所做
在C#中有两种方式来处理这种情况:
“类型安全”的方式, 的那样:
通过使用指针和“unsafe”关键字来实现;以及CLS兼容的方式, class Item {
通过使用 System.IntPtr来表示 void 指针。
[DllImport ("library")]
在这两种情况下,托管和非托管内存的区别非常清楚。托 public static extern
bool CreateItem (out System.IntPtr item);
管内存保持类型安全,而非托管内存则不一定(因为 System.
[DllImport ("library")]
IntPtr是用来指向非托管内存的,这就没有办法保证它指向的是 public static extern void DestroyItem (System.IntPtr item);
有意义的数据类型)。
[DllImport ("library")]
需要注意的是如果“非托管”内存自身具有垃圾回收机制 public static extern int GetInfo (System.IntPtr item);
106 程序员
>>> 微软技术
} // frees resources of h
[DllImport ("...")]
class ExampleUsage { static extern void DeleteHandle (IntPtr h);
public static unsafe void Main (){
System.IntPtr item = null;  ̄C() {
Item.CreateItem (out item); DeleteHandle(h);
int n = Item.GetInfo (item); }
System.Console.WriteLine ("item count: {0}",
n.ToString()); public void m() {
Item.DestroyItem (item); OperateOnHandle(_handle);
} // no further references to _handle
} }
}
这样做的不安全之处在于它很容易在不经意间滥用指针。 class Other {
比如如果你使用的是两个不同的库,并且用 System.IntPtr来对 void work() {
C c = new C();
它们进行了封装,那么很有可能把一个库分配的对象传递给另 c.m();
// no further references to c.
一个库导出的函数,而CLR运行时库并不会捕捉到这个错误,当 // c is now eligable for collection.
}
错误出现的时候,将直接使你的“unsafe”的 C# 代码崩溃。 }
不过,在大多数托管代码不与P/Invoke代码交互的情况下
考虑一下这种情况:Other.work 调用了c.m,而c.m又调用
这并不成其为问题,你只需要用托管的封装类来与非托管代码
了非托管代码C.OperateOnHandle。注意Other.work已经不再使用
来交互,并且向你的托管代码提供一个看起来更自然的接口就
c 了,所以 c 已经符合被回收的条件了,并且被放到了 GC的终
可以了。
止化队列(finalization queue)中。
这样做一般来说是合理的,
如果不考虑非托管代码的影响,
GC 安全的 P/Invoke 代码
上面的非托管代码 C.OperateOnHandle 还在使用实例 c的一个成
在上面描述的封装代码中同样存在着一个问题:用户代码
员,可是 GC 不知道,也不可能知道这一点。
和运行时库的垃圾收集器(GC)之间的竞争。
上面的场景描述了前面所说的可能性,虽然看起来很不可
.NET 使用的 GC 相当聪明,它知道相关的所有类型,可以
能。C.DeleteHandle将会在C.OperateOnHandle还在执行的时候就
分别出一个看起来像是指针的整数和一个实际的指针。它知道
被 GC 的终止化线程(finalization thread)调用。
所有栈分配的变量以及这些变量的生存范围。不过GC对非托管
可以想象非托管代码并不喜欢这样的情况出现,因为这将
代码内部的一切则是一无所知,这样就可能出现这样一种让人
会是进程中可能出现的主要问题,包括可恶的段错误
感到尴尬的情况:GC可能会在一个类实例的某个方法还在执行
(segmentation fault)。实际上在.NET 1.0 的一个注册表封装类
的时候把它给回收掉。
中就存在着一个与这个非常类似的 bug。
这怎么可能?你也许会说。但事实就是这样,如果这个方
那如何避免这个问题呢?问题的关键在于IntPtr,一旦你使
法不再使用类的实例成员,而且也没有其他代码使用,那么GC
用了IntPtr,GC就无法知道你的类是否还在被使用。我们需要用
就可能回收这个类。毕竟,如果没有谁在使用实例成员,而且
HandleRef 来代替 IntPtr。HandleRef 是一个包含有类引用的结构,
也没有谁使用类实例,那么谁还会在乎这个实例是不是被回收
同时可以和指针值一样使用。
了呢?
接下来,
还要在P/Invoke代码中用HandleRefs参数来代替IntPtr
不过对于非托管代码就不是这么简单了,尤其是它还认为
参数。而且,HandleRefs对于运行时库和GC系统来说是很特别的,
这个类实例可用的情况就更麻烦了。同样,如果这个类有终止
在封送操作中它会被“折叠(collapse)
”到一个IntPtr中。
函数(finalizer),它也会在其他方法正在执行的时候就不合时宜
的冒出来。
正确的释放资源
看看下面这个例子:
在避免封送的同时,你的托管代码将直接面对非托管内存
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;
够最终释放资源。
sealed class UnmanagedResource : IDisposable
不过这种方法存在两个问题,而这两个问题都与垃圾收集 {
[DllImport ("...")]
器有关: private static extern IntPtr CreateResource ();
1. 垃圾收集器无法深入到非托管内存中去,它只能处理托
[DllImport ("...")]
管内存。因此,如果你要处理大量的非托管内存(比如图像或 private static extern
void DeleteResource (HandleRef handle);
者视频数据),GC 所能看到只是指向这些数据的 IntPtr,而不是
// Use a HandleRef to avoid race conditions;
托管代码中容纳的非托管内存的实际大小。所以,GC也就不知 private HandleRef _handle;
道需要执行这样一个回收,因为这里没有任何“内存压力”— public UnmanagedResource ()
—内存不足,需要执行回收来获得更多的内存。不过这个问题 {
IntPtr h = CreateResource ();
在.NET 2.0 中已经被 System.GC.AddMemoryPressure(long)方法部分 _handle = new HandleRef (this, h);
}
的解决了,该方法用来告诉GC一个托管对象指向了多大的非托
// Provide access to 3rd party code
管内存,这样就提高了 GC 的启发式智能(heuristics); public HandleRef Handle {
2. 对于被回收的对象,.NET 的垃圾收集器不会执行对象的 get {return _handle;}
}
终止函数。相应的做法是,对象的代龄被提升(p r o m o t e d a
// Dispose of the resource
generation),对想的终止函数将会在下次这一代被回收的时候执 public void Dispose ()
{
行。比如,如果一个有终止函数的第 0代对象符合被收集的条 Cleanup ();
件(也就是说,没有对象引用它),该对象的代龄被提升,被放 // Prevent the object from being placed on the
到第 1 代的终止化队列中。下次当第 1 代被回收的时候,对象 // finalization queue
System.GC.SuppressFinalize (this);
的终止函数才被执行。 }
问题2是一个真正的麻烦,
这是因为回收频率与代龄数字是 // Finalizer provided in case Dispose isn't called.
// This is a fallback mechanism, but shouldn't be
成反比例的。第0代(通常)的回收频率通常是第1代的 10倍, // relied upon (see previous discussion).
而第 1代又是第2代的10倍。第2代一般很少被回收,这些通常  ̄UnmanagedResource ()
{
是一些长期存在的对象,往往与应用程序的存在时间一致。 Cleanup ();
}
假定最快的情况下一个被终止的对象在两次收集之后被回
// Really dispose of the resource
收了,一次是第 0 代,一次是第 1 代(大概在 10 次左右的第 0 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() 方法相反。提供一个虚函数和一个没有密封
完成两件事情: (non-sealed)的类实际上说明会有,甚至可以说希望有派生的
(1) 释放资源; 子类,不过这样做并不是好主意。
(2) 调用SuppressFinalize。SuppressFinalize告诉GC不要再调 再说一遍,这并不是好主意!还是因为垃圾收集器。当一
用对象的终止函数,
让对象可以在第一次回收的时候就被释放, 个对象的代龄被提升之后,
所有它引用的对象的代龄也被提升。
而不用再考虑那让人捉摸不定的延迟了。 所以如果你的终止对象包括了其他对象的一个ArrayList,包括这
实现的样例见下面的代码: 个ArrayList,它所容纳的所有对象,以及那些对象的所有引用都
将被提升,可以想象的事,这将是一个潜在的巨大的数字。
// for IntPtr, IDisposable
108 程序员
>>> .NET
编写数据库访问代码是一项重复且费时的工作,因为现在有了可重用的 Enterprise
Data Access Application Block,您再也不必编写这类代码了。
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,并给出了一些例子来说明如何使用它来编写健壮的数据 元素;
访问代码。 <configSections>
<section
name="dataConfiguration"
Enterprise Data Access Block type="Microsoft.Practices.
EnterpriseLibrary.Data.
Data Access Block 帮助开发人员完成了开发数据库应用程 Configuration.
DatabaseSettings,
序时最常见的任务。通过提供一组封装好的方法,Data Access Microsoft.Practices.
Block极大地简化了用于访问数据库的最常用方法。每个方法都 EnterpriseLibrary.Data" />
</configSections>
包含检索适当数据所需的逻辑,并管理数据库连接。另外,Data
Access Block 是数据库不可知的(database-agnostic)
;它对ADO 接着,
您还要添加<dataConfiguration> <configuration>元素,
.NET 2.0中的代码进行了补充,能够让您编写可以跨不同关系 如下所示:
数据库使用的数据访问代码——同时无需重新编写代码。这些 <dataConfiguration
defaultDatabase="AdventureWorksDB"/>
类包含的代码为诸如参数处理和游标之类的功能提供了特定于
数据库的实现。 在这个例子中,我已经把AdventureWorks 标记为默认数据
Data Access Block 还为 SQL Server 和 Oracle 数据库提供了 库,在<connectionStrings>元素下单独声明:
特定的派生类。另外,GenericDatabase类允许您使用应用程序块 <connectionStrings>
和任何配置好的ADO.NET 2.0 DbProviderFactory对象。最后,通 <add
Programmer 109
技术 Technology
.NET >>>
name="AdventureWorksDB" gridEmployees.DataBind();
providerName= }
"System.Data.SqlClient" }
connectionString= </script>
"server=localhost;
database=AdventureWorks;
UID=user;PWD=word;" /> 上述代码首先调用了DatabaseFactory类的CreateDatabase()方
</connectionStrings>
法,以包含 D a t a b a s e 对象的一个实例。正如其名称所示,
EnterpriseLibrary.Data命名空间; CreateDatabase()方法是一个重载方法,如上所示,当您调用该
4.针对上述命名空间中的类开始编写代码。 方法参数较少的版本时,它就会返回一个默认数据库。要设置
默认数据库,您需要把defaultDatabase属性值指派给Web.config
使用 Database 对象 文件中正确的数据库配置键,该文件如下所示:
只要使用 Data Access Block,您就必须首先处理 Database <dataConfiguration
defaultDatabase="AdventureWorksDB"/>
类。Database类代表数据库本身,它提供一些方法(参见表1),
您可以使用这些方法对数据库执行 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 的
方法 说明 Database.ExecuteReader()方法执行SQL。使用浏览器导航到该页
ExecuteDataSet 执 行 一 次 SQL 查 询 或 一 个 存 储 过 程 ,然 后 以 Dataset
面。因为该方法将返回的 DbDataReader 绑定到一个 GridView 控
对象的形式返回结果。
ExecuteNonQuery 执 行 一 次 SQL查 询 或 一 个 存 储 过 程 ,然 后 返 回 相 关 记 件,您将会看到类似于图 1 的输出:
录的数目。
ExecuteReader 执行一次 SQL查询或一个存储过程 ,然后以IDataReader
对象的形式返回结果。
ExecuteScalar 执 行 一 次 SQL查 询 或 一 个 存 储 过 程 ,然 后 返 回 结 果 集
中第一行的第一列。
LoadDataSet 执 行 一 个 命 令 ,然 后 给 现 有 的 DataSet添 加 一 个 新 的
DataTable。
UpdateDataSet 通 过 执 行 正 确 的 INSERT、UPDATE和 DELETE语 句 ,
同 步 数 据 库 的 DataSet 内 容 。
表 1:Database 类 方 法
110 程序员
>>> .NET
该方法接受DbCommand 对象作为一个输入参数。为了显示出此
<%@ Page Language="C#" %>
<%@ Import Namespace="System.Data" %> 方法的优点,我将利用一个叫做GetEmployeeNationalID的存储过
<%@ Import Namespace="System.Data.Common" %>
<%@ Import Namespace= "Microsoft.Practices. 程,该存储过程带有一个 E m p l o y e e I D 参数,可返回雇员的
EnterpriseLibrary.Data" %>
<%@ Import Namespace= "Microsoft.Practices. NationalID 值。该存储过程声明如下:
EnterpriseLibrary.Data.Sql" %>
Create Procedure GetEmployeeNationalID
<script runat="server"> @EmployeeID int
void Page_Load(object sender, EventArgs e) AS
{ Select NationalIDNumber
string connString = System.Web.Configuration. from HumanResources.Employee
WebConfigurationManager.ConnectionStrings Where EmployeeID = @EmployeeID
["AdventureWorksDB"].ConnectionString;
SqlDatabase db = new SqlDatabase(connString);
string sqlCommand = "Select " + "EmployeeID,
以下ASP.NET页面代码节选显示了调用GetEmployeeNationalID
NationalIDNumber," + "LoginID, Title from " + 存储过程所需的代码:
" HumanResources.Employee ";
DbCommand dbCommand = db.GetSqlStringCommand
(sqlCommand); <script runat="server">
DataSet dst = db.ExecuteDataSet(dbCommand);
gridEmployees.DataSource = dst.Tables[0].DefaultView; void Page_Load(object sender,
gridEmployees.DataBind(); EventArgs e)
} {
</script> int employeeID = 1;
Database db =
<html xmlns="http://www.w3.org/1999/xhtml" > DatabaseFactory.CreateDatabase();
<head runat="server"> string sqlCommand = "GetEmployeeNationalID";
<title>Executing a SQL Select Statement to retrieve DbCommand dbCommand =
a DataSet</title></head> db.GetSqlStringCommand(sqlCommand);
dbCommand.CommandType =
<body> CommandType.StoredProcedure;
<form id="form1" runat="server"> db.AddInParameter(dbCommand,
<div><asp:GridView runat="server" "EmployeeID", DbType.Int32, 1);
ID="gridEmployees" /></div> string nationalID = (string)
</form> db.ExecuteScalar(dbCommand);
</body> Response.Write("NationalID : " + nationalID + "<br>");
}
</html>
</script>
×÷Õß×¢ÊÍ£ºÄúµ¼ÈëµÄÃüÃû¿Õ¼ä(Imports)ºÍ±¾Î
ÄÖÐÀý×ÓÓàÏÂ
²¿·
ÖµÄÒ³ÃæHTMLú́ÂëÀàËÆÓÚÇ°ÃæµÄÀý×Ó£¬ËùÒÔÎÒÔÚʣϵÄÀý 首先,代码使用AddInParameter()方法给DbCommand对象添
×ÓÖкöÂÔÁËËüÃÇ¡£È»¶ø£¬Äú¿ÉÒÔÏ
ÂÔØʾÀý´úÂëÀ´
»ñµÃÍêÕûµÄʾ 加了 EmployeeID 输入参数。注意,EmployeeID 参数没有带 @ 前
ÀýÒ³
Ãæ¡
£ 缀,这就是通常指示一个 SQL Server的存储过程参数的做法—
比如GetSqlStringCommand()和ExecuteDataSet(),通过这些方法,
您可以获得一个 DbCommand 对象的实例,执行SQL查询,并以 执行返回单个行的存储过程
DataSet对象的形式返回结果。尽管前面的例子使用的是SELECT 有时候,您需要检索一个行,而不是一组行。您可以使用
获得一项。例如,插入新的一行到数据库中之后,您可能希望 的声明:
将新插入的值返回给使用者。 Create Procedure GetEmployeeDetails
@EmployeeID int,
为此,Database 类提供了一个叫做 ExecuteScalar()的方法,
Programmer 111
技术 Technology
.NET >>>
@NationalIDNumber nvarchar(15)
可以帮您满足这个愿望,因为它提供了一个 D a t a b a s e .
OUTPUT,
@LoginID nvarchar(256) OUTPUT, CreateConnection() 方法,允许您获得一个对 ADO.NET 2.0
@Title nvarchar(50) OUTPUT
AS DbConnection对象的引用。通过使用 DbConnection对象,您可以
Select @NationalIDNumber =
NationalIDNumber, 获得一个对 D b T r a n s a c t i o n 变量的引用,具体方法是调用
@LoginID = LoginID,
@Title = Title from
BeginTransaction()方法,然后将返回值赋给一个DbTransaction变
HumanResources.Employee 量。接下来,通过分别在执行成功或失败时调用 Commit()或
Where EmployeeID = @EmployeeID
GO Rollback()方法。您可以轻松控制事务的行为。下面的伪代码说
明了如何在一个事务的作用域内执行多个存储过程。
通过提供一组高度可重用的类在数据库执
Database db =
行操作,EntLib Data Access Block 能让您免于 DatabaseFactory.CreateDatabase();
编写重复性的数据库访问管道代码。
//Two operations, one to add the order
//and another to add order details
string sqlCommand = "InsertOrder";
以下Page_Load 代码执行GetEmployeeDetails存储过程,并 DbCommand orderCommand =
db.GetStoredProcCommand(sqlCommand);
以输出参数的形式返回NationalIDNumber、LoginID和Title col-
//Add InsertOrder parameters
umn值。 sqlCommand = "InsertOrderDetails";
DbCommand orderDetailsCommand =
<script runat="server"> db.GetStoredProcCommand(sqlCommand);
void Page_Load(object sender, EventArgs e) //Add InsertOrderDetails parameters
{ using (DbConnection connection =
int employeeID = 1; db.CreateConnection())
Database db = DatabaseFactory.CreateDatabase();
string sqlCommand ="GetEmployeeDetails"; {
DbCommand dbCommand = db.GetSqlStringCommand connection.Open();
(sqlCommand); DbTransaction transaction =
dbCommand.CommandType = connection.BeginTransaction();
CommandType.StoredProcedure; try
db.AddInParameter(dbCommand, {
"EmployeeID", DbType.Int32, 1); //Execute the InsertOrder
db.AddOutParameter(dbCommand, "NationalIDNumber", db.ExecuteNonQuery(orderCommand,
DbType.String, 15); transaction);
db.AddOutParameter(dbCommand, "LoginID", //Execute the InsertOrderDetails
DbType.String, 256); db.ExecuteNonQuery(orderDetailsCommand,
db.AddOutParameter(dbCommand, "Title", transaction);
DbType.String, 50); //Commit the transaction
db.ExecuteNonQuery(dbCommand); transaction.Commit();
Response.Write("NationalID : " + }
db.GetParameterValue(dbCommand, catch
"NationalIDNumber") + "<br>"); {
Response.Write("Login ID : " + //Roll back the transaction.
db.GetParameterValue(dbCommand, transaction.Rollback();
"LoginID") + "<br>"); }
Response.Write("Title : " + db.GetParameterValue(
dbCommand, "Title") + "<br>"); }
}
绝大多数处理工作出现 using块中。这个块使用BeginTransaction
</script>
()方法启动事务,并使用Commit()或Rollback()方法提交或回滚
事务。
在上面的代码中,您使用了 D b C o m m a n d 对象的
AddOutParameter()方法来添加输出参数。在执行存储过程之后,
您只要使用 DbCommand 对象的GetParameterValue()方法来获取 结束语
通过本文您了解到,通过提供一组高度可重用的类在数据
输出参数即可。
库执行操作,EntLib Data Access Block 能让您免于编写重复性
用于执行多次更新的事务代码块 的数据库访问管道代码。通过这些类的使用,您可以根除应用
程序中的误差、bug和打字错误,并把主要精力放在应用程序的
有时候,您不仅想在一个数据库上执行多项操作,而且希
望能在一个事务的作用域内执行它们。EntLib Data Access Block 核心业务逻辑上,从而提高工作效率。
112 程序员
>>> 数据库
本文内容来自于胡百敬即将出版的最新著作《SQL Server 2005
数据库开发详解》,这是国内第一本全面、深入分析 SQL Server数据
库开发和管理的原创著作。
迈向大型数据库
□ 文 / 胡百敬
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)。它延
集成.NET CLR 引擎到 SQL Server 核心,让程序设计师可以
伸log shipping的能力,让主要的SQL Server 通过自己所熟悉的.NET 语言来开发 SQL Server 内的对象,延伸
实例有问题时 ,自动转换到备援的 S Q L
了程序编写的弹性。
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 若XML 文件数据很大,由于没有索引结构,用DOM解析的性能
集成.NET CLR引擎到SQL Server核心,让程序设计师可以 往往不佳。同时,备份数据需要既备份数据库内的metadata,又
通过自己所熟悉的.NET 语言来开发SQL Server 内的对象,延伸 要备份文件系统上的 XML,而安全管控也更为复杂。
114 程序员
>>> 数据库
Programmer 115
技术 Technology
软件调试 >>>
116 程序员
>>> 软件调试
ntsd -d -g -G -o -pd -p <CSRSS 进 程 ID>
-d 表示将输入和输出(通过 DbgPrint)定向到另一个Win-
dows 中的 WinDbg 中;-g 表示忽略被调试进程的初始断点,如
果不加此开关,那么将NTSD附加到 CSRSS进程的第一个breakin
断点会导致被调试系统僵死;-G表示忽略进程终止时的最后一
个断点;-o 表示调试被调试进程启动的子进程;-pd表示调试
器应该自动与被调试进程分离;-p 用来指定被调试进程的进程
ID。注意WinDbg的帮助文件说CSRSS 的进程ID总为-1,这对于
图2
Programmer 117
技术 Technology
软件调试 >>>
*** wait with pending attach
… 因是当 CSRSS弹出这个HardError时,系统已经启动了关机程序,
Executable search path is:
ModLoad: 4a680000 4a684000 C:\WINDOWS\system32\csrss.exe 此时我们按 F12 也不能激发调试功能了。
ModLoad: 77f50000 77ff7000 C:\WINDOWS\System32\ntdll.dll
ModLoad: 75b40000 75b4a000 C:\WINDOWS\system32\CSRSRV.dll 图 4 是CSRSS 显示的另一种界面,当某个应用程序内出现未
ModLoad: 75b50000 75b5e000 C:\WINDOWS\system32\basesrv.dll
ModLoad: 75b60000 75ba6000 C:\WINDOWS\system32\winsrv.dll
处理异常时,
系统的缺省异常处理器
(UnhandledExceptionFilter函数,
ModLoad: 77d40000 77dcc000 C:\WINDOWS\system32\USER32.dll
位于KERNEL32.DLL)
会通过调用NtRaiseHardError()这个未公开的系
ModLoad: 77e60000 77f46000 C:\WINDOWS\system32\KERNEL32.dll
ModLoad: 77c70000 77cb0000 C:\WINDOWS\system32\GDI32.dll 统服务将错误报告给系统,内核服务在通过 LPC 发给 CSRSS,于
ModLoad: 77dd0000 77e5d000 C:\WINDOWS\system32\ADVAPI32.dll
ModLoad: 78000000 78086000 C:\WINDOWS\system32\RPCRT4.dll 是 CSRSS显示出如下这个对话框。触发这个机制的方法就是随便
ModLoad: 75e90000 75f37000 C:\WINDOWS\System32\sxs.dll
写一个小程序,内部做个非法操作而且不加任何异常保护。
看到以上信息,说明NTSD已经成功附加(attach)到CSRSS
进程了;NTSD也与调试机上的WinDbg成功建立了连接。上面
的信息是 CSRSS进程中的各个模块:NTDLL.DLL是所有Win-
dows 程序都离不开的系统支持库;CSRSRV.DLL、BASESRV.
DLL和WINSRV.DLL是CSRSS进程用来真正实施系统服务的三 图 4:CSRSS 弹 出 的 应 用 程 序 内 出 现 未 处 理 异 常 错 误 ( Windows 2000)
118 程序员
>>> 软件调试
F12键。这时观察调试机中的WinDbg,如果出现类似图6所示的 以从其它机器上复制过来(只需要复制前面列出的那些模块的
情形,那么便成功将 CSRSS 进程中断到调试器了。 符号文件就可以了,注意保持目录结构不变)。笔者的做法是从
另一台机器上将WINSRV、CSRSS、CSRSRV等文件的调试符号复
制到被调试机的 C:\Symbols 目录下。
准备好调试符号文件后,需要将其根目录设置给NTSD,这
只要在 Input 提示符后输入.sympath c:\symbols 便可以了。然
图 6:CSRSS 显 示 的 缺 盘 通 知
后需要通过.reload 命令使其生效。
下面仔细看一下图 7 所示的调试界面。首先注意,命令输 接着,再次输入k命令,会发现刚才的警告没有了,而且这
入区与普通的内核调试和用户态调试都不同,Input 提示符专门 次的函数调用序列与刚才的也大相径庭。这次才是正确的结果,
用于表示 WinDbg 在代理另一个调试器的输入。对于我们的情 因为我们按F12 键,Windows 子系统的内核部分接收到此热键,
况,输入到这里的命令会送给另一台机器上的NTSD调试器。另 然后触发了CSRSS中的SrvActivateDebugger服务,
SrvActivateDebugger
一点要说明的是,检查图 7 中的进程 ID(1d0),它应该与被调 检查到要调试的就是自己,便调用DbgBreakPoint 中断到调试器。
试机上的 CSRSS 进程的进程 ID 是一致的。 可见正确设置调试符号对于调试的重要性!
0:010> k
k
ChildEBP RetAddr
0120fec4 75b7a179 ntdll!DbgBreakPoint
0120fed0 75b44443 winsrv!SrvActivateDebugger+0x1a
0120fff4 00000000 CSRSRV!CsrApiRequestThread+0x253
Programmer 119
技术 Technology
智慧擂台 >>>
移动内存算法
□ 文 / 刘鑫
120 程序员
>>> 智慧擂台
while(tmp != 0) {
m = n; n = tmp; tmp = m % n; template<typename T,typename U>
} void Carry(T point[], const U & len, const U & m){
return n; U start = 0,p = 0;
} T pv;
U hloc = HCF(len, m);
void display(int *pa){ U step = len - m;
int i; for (U i = 0; i<hloc; i++) {
printf("array: "); p = i; start = p; pv = point[p] ;
for(i=0;i<Len; i++) printf("%d ",pa[i]); do {
printf("\n"); p = (step+p)%len;
} std::swap(point[p] , pv);
}while(p != start);
void swap(int *n1, int *n2){ }
int tmp; };
tmp = *n1; *n1 = *n2; *n2 = tmp;
}
用迭代器实现的区间移动,可以应用于 STL 容器等场合:
/* *p 数 据 指 针 , aLen: 数 据 长 度 , k: 左 循 环 位 数 */
void LeftRotation(int *p, int aLen, int k){
int i,tmp,factor; template<typename iterT,typename U>
k = k % aLen; void Carry(iterT &iter, const U & len, const U & m) {
if ( k == 0) return; iterT nb = iter + (len-m);
k = aLen - k; iterT p;
factor = CommonFactor(aLen, k); iterT start = point;
if (factor == 1){ iterT pm = point + m;
i = 0; iterator_traits<iterT>::value_type pv;
do{ U hloc = HCF(len, m);
i = (i+k)%aLen; for (U i = 0; i<hloc; i++) {
swap(p, p + i ) ; p = point + i;
} while(i != 0); start = p; pv = *p ;
} do {
else { if (p < pm)
for (i = 0;i < factor; i++){ p = nb + (p - point);
tmp = i; else
do{ p -= m;
tmp = (tmp+k)%aLen; std::swap(*p , pv);
swap(&p[i], p + tmp ) ; }while(p != start);
} while(tmp != i); }
} };
}
} 代码中使用了 std::swap 函数来交换变量值,这个函数在
int main(int argc, char *argv[]) {
int i,k,a[Len]={1,2,3,4,5,6}; <algorithm>中。另外为了析取迭代器的值,我使用了<iterator>
for(i=0;i<8;i++){
for( k = 0; k<Len ;k++) /* 数 组 赋 值 */ 中的iterator_traits操作。有兴趣的朋友不妨编写一个适用于普通
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"); 是采用一个足够简单的交换和计算中界的代码。这样的功能,C
}
system("PAUSE"); return 0; 风格的代码就可以做到足够好了。
}
有些朋友认为直接改变索引就可以重排数组,对于某些高
以下是用 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;
} 们面对的总是不够快的 CPU和不够大的内存,需要有一个高效
return b;
}; 的算法来移动虚拟机管理的数据。对于Java或 C#程序员,这
个过程通常是透明的,但是这不表示它不存在。而默默支撑起
区间移动,支持任何类型的数组:
虚拟机的,正是这些 C/C++ 代码。
Programmer 121
>>> SUN 征文
Programmer 123
产品&应用 Product & Application
SUN 征文 >>>
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的规
表 1: 三 套 软 件 的 价 格 表
公司 产品 价 格 (美 元 )
IBM Rational Software Architect 5500
Borland Together for Eclipse Architect Edition 5000
Sparx Systems Enterprise Architect Corporate Edition 239 图 1:UML 2.0 规 范 的
126 程序员
>>> 工具点评
Programmer 127
>>> 新书上架
《程序员》每月精选上市新书,由编辑和业界专家亲自点评。诚邀读者推荐新书!
新书上架
《C #入门经典(第 3 版)》
出版社:清华大学出版社
《编程卓越之道》
出版社:电子工业出版社
本书提供了作者积累的关于卓越编程的真知灼见。 弥补了计算机科学和工程课程中被忽略的一
个部分——底层细节,而这正是构建卓越代码的基石。具体内容包括:计算机数据表示法,二进制
数学运算与位运算,内存组织与内存访问,数据类型及其表示,布尔逻辑与数字设计,CPU体系结
构,CPU 指令集的体系结构,内存体系与内存组织,计算机系统如何与外界通信等。
本书将教你写出让你引以为豪的代码;能够给同行留下深刻印象的代码;能够让客户满意、乐于使用的代码;能够
让人们(客户,你的老板,等等)不惜花大价钱来获得的代码。
简而言之,《编程卓越之道》系列将论述如何编写出卓越超凡,让其他程序员敬畏的软件。
本书是面向对象分析和设计(OOA/D)的实用指南,阐述了迭代开发相关方面的内容,使你
能一步一步地实现从需求到编码的全过程。通过本书,你将学习如何应用设计模式,包括流行的
GoF 模式和 GRASP 模式。GRASP 模式表达了对象设计中职责分配的基本原则。本书的结构和重
点建立在作者多年教授和培训成千上万学生掌握 OOA/D 的经验之上,它提供了一个精炼的、已证
明的和高效率的掌握 OOA/D 的学习方法,使你在阅读和学习上的投资得到优化。书中详尽地说明一个案例,以便实际
地说明整个 OOA/D 过程,并深入讨论问题的棘手细节,这是一个实际的练习。本书还说明如何将对象设计工件映射成
Java 代码。
本书适合熟悉OOA/D但希望学习UML表示法、 应用模式的读者,或者希望加强和提高自己的分析和设计技能的读者。
Programmer 133