﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>IT博客-Joinclass Inc-随笔分类-技术专题</title><link>http://www.cnitblog.com/tilan/category/4337.html</link><description>软件开发 软件配置 项目管理 软件工程</description><language>zh-cn</language><lastBuildDate>Mon, 26 Sep 2011 09:40:40 GMT</lastBuildDate><pubDate>Mon, 26 Sep 2011 09:40:40 GMT</pubDate><ttl>60</ttl><item><title>一个老工程师给年轻工程师的十大忠告</title><link>http://www.cnitblog.com/tilan/archive/2007/12/09/37526.html</link><dc:creator>Joinclass Inc</dc:creator><author>Joinclass Inc</author><pubDate>Sun, 09 Dec 2007 09:24:00 GMT</pubDate><guid>http://www.cnitblog.com/tilan/archive/2007/12/09/37526.html</guid><wfw:comment>http://www.cnitblog.com/tilan/comments/37526.html</wfw:comment><comments>http://www.cnitblog.com/tilan/archive/2007/12/09/37526.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cnitblog.com/tilan/comments/commentRss/37526.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/tilan/services/trackbacks/37526.html</trackback:ping><description><![CDATA[<div id=postmessage_1235418 style="FONT-SIZE: 10pt">[1]好好规划自己的路，不要跟着感觉走！根据个人的理想决策安排，绝大部分人并不指望成为什么院士或教授，而是希望活得滋润一些，爽一些。那么，就需要慎重安排自己的轨迹。从哪个行业入手，逐渐对该行业深入了解，不要频繁跳槽，特别是不要为了一点工资而转移阵地，从长远看，这点钱根本不算什么，当你对一个行业有那么几年的体会，以后钱根本不是问题。频繁地动荡不是上策，最后你对哪个行业都没有摸透，永远是新手！<br>[2]可以做技术，切不可沉湎于技术。千万不可一门心思钻研技术！给自己很大压力，如果你的心思全部放在这上面，那么注定你将成为孔乙己一类的人物！适可而止为之，因为技术只不过是你今后前途的支柱之一，而且还不是最大的支柱，除非你只愿意到老还是个工程师！<br>[3]不要去做技术高手，只去做综合素质高手！在企业里混，我们时常瞧不起某人，说他&#8220;什么都不懂，凭啥拿那么多钱，凭啥升官！&#8221;这是普遍的典型的工程师的迂腐之言。8051很牛吗？人家能上去必然有他的本事，而且是你没有的本事。你想想，老板搞经营那么多年，难道见识不如你这个新兵？人家或许善于管理，善于领会老板意图，善于部门协调等等。因此务必培养自己多方面的能力，包括管理，亲和力，察言观色能力，攻关能力等，要成为综合素质的高手，则前途无量，否则只能躲在角落看示波器！技术以外的技能才是更重要的本事！！从古到今，美国*本，一律如此！<br>[4]多交社会三教九流的朋友！不要只和工程师交往，认为有共同语言，其实更重要的是和<a onclick="javascript:tagshow(event, '%C6%E4%CB%FB');" href="javascript:;" target=_self>其他</a>类人物交往，如果你希望有朝一*当老板或高层管理，那么你整*面对的就是这些人。了解他们的经历，思维习惯，爱好，<a onclick="javascript:tagshow(event, '%D1%A7%CF%B0');" href="javascript:;" target=_self>学习</a>他们处理问题的模式，了解社会各个角落的现象和问题，这是以后发展的巨大的本钱，没有这些以后就会笨手笨脚，跌跌撞撞，遇到重重困难，交不少学费，成功的概率大大降低！<br>[5]知识涉猎不一定专，但一定要广！多看看其他方面的书，金融，财会，进出口，税务，法律等等，为以后做一些积累，以后的用处会更大！会少交许多学费！！<br>[6]抓住时机向技术管理或市场销售方面的转变！要想有前途就不能一直搞<a onclick="javascript:tagshow(event, '%BF%AA%B7%A2');" href="javascript:;" target=_self>开发</a>，适当时候要转变为管理或销售，前途会更大，以前搞技术也没有白搞，以后还用得着。搞管理可以培养自己的领导能力，搞销售可以培养自己的市场概念和思维，同时为自己以后发展积累庞大的人脉！应该说这才是前途的真正支柱！！！<br>[7]逐渐克服自己的心里弱点和性格缺陷！多疑，敏感，天真（贬义，并不可爱），犹豫不决，胆怯，多虑，脸皮太薄，心不够黑，教条式思维。。。这些工程师普遍存在的性格弱点必须改变！很难吗？只在床上想一想当然不可能，去帮朋友守一个月地摊，包准有效果，去实践，而不要只想！不克服这些缺点，一切不可能，甚至连项目经理都当不好--尽管你可能技术不错！<br>[8]工作的同时要为以后做准备！建立自己的工作环境！及早为自己配置一个工作环境，装备电脑，示波器（可以买个二手的），仿真器，编程器等，业余可以接点活，一方面接触市场，培养市场感觉，同时也积累资金，更重要的是准备自己的产品，咱搞技术的没有钱，只有技术，技术的代表不是学历和证书，而是产品，拿出象样的产品，就可技术转让或与人合作搞企业！先把东西准备好，等待机会，否则，有了机会也抓不住！<br>[9]要学会善于推销自己！不仅要能干，还要能说，能写，善于利用一切机会推销自己，树立自己的品牌形象，很必要！要创造条件让别人了解自己，不然老板怎么知道你能干？外面的投资人怎么相信你？提早把自己推销出去，机会自然会来找你！搞个个人主页是个好注意！！特别是培养自己在行业的名气，有了名气，高薪机会自不在话下，更重要的是有合作的机会...<br>[10]该出手时便出手！永远不可能有100%把握！！！条件差不多就要大胆去干，去闯出自己的事业，不要犹豫，不要彷徨，干了不一定成功，但至少为下一次冲击积累了经验，不干永远没出息，而且要干成必然要经历失败。不经历风雨，怎么见彩虹，没有人能随随便便成功！</div>
<br><img src ="http://www.cnitblog.com/tilan/aggbug/37526.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/tilan/" target="_blank">Joinclass Inc</a> 2007-12-09 17:24 <a href="http://www.cnitblog.com/tilan/archive/2007/12/09/37526.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>初步搭建yui-ext开发环境</title><link>http://www.cnitblog.com/tilan/archive/2007/11/07/35975.html</link><dc:creator>Joinclass Inc</dc:creator><author>Joinclass Inc</author><pubDate>Wed, 07 Nov 2007 06:09:00 GMT</pubDate><guid>http://www.cnitblog.com/tilan/archive/2007/11/07/35975.html</guid><wfw:comment>http://www.cnitblog.com/tilan/comments/35975.html</wfw:comment><comments>http://www.cnitblog.com/tilan/archive/2007/11/07/35975.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cnitblog.com/tilan/comments/commentRss/35975.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/tilan/services/trackbacks/35975.html</trackback:ping><description><![CDATA[<p>如果看过yui-ext的例子，相信大家很想把它用在实际项目中去，我这两个星期都在研究它，国内几乎没有资料，只能从http://www.jackslocum.com的论坛找，我现在简单介绍一下我的实际开发环境：</p>
<p>我的项目原来的开发环境是Struts+Spring1.2.8+Hibernate3.1.2，现在要把页面的jsp+jstl，和Struts的Action转换成yui-ext的Ajax页面，简单实现数据列表、翻页和添加、修改、删除等功能。</p>
<p>1. 数据交换，要从Struts环境的Action通过request对象传递数据给jsp页面，如果用Ajax，比较常用的是XML转换和Json转换，我选择了Json，因为用json-lib包可以在java端用很方便的把对象转换成Json格式，在页面可以调用脚本eval()转换成javascript的数组对象。</p>
<p>1) json-lib转换java对象(下载json-lib:http://json-lib.sourceforge.net) <br>Action例子：(example.do)代码中加入： <br>response.setContentType("text/xml;charset=utf-8"); <br>JSONArray jsonArray = JSONArray.fromObject(list); <br>response.getWriter().print("{datalist:" + jsonArray + "}"); <br>return null; <br>简单说明：把action的return mapping改成null,因为现在使用response对象进行数据传递，fromObject(list)中的list包括就是页面需要调用显示的数据，可以是其他java对象，String、bean或Map。</p>
<p>2) JSONDataModel调用Action(example.do) <br>yui-ext通过JSONDataModel.js把json格式转换成javascript的数组对象 <br>js例子： <br>var schema = { <br>root: 'datalist', <br>id: 'nothing', <br>fields: ['a','b', 'c', 'd']</p>
<p>dataModel= new YAHOO.ext.grid.JSONDataModel(schema); <br>dataModel.load('http://xxx/example.do');</p>
<p>说明：schema的root参数要和action传递的json数据头list对应，这里new JSONDataModel后，JSONDataModel会把example.do返回的json数据转换成dataModel的数组，JSONDataModel继承于LoadableDataModel，JSONDataModel只复杂转换json数据，其他由继承的类实现，这是yui-ext的特点，你可以自己写DataModel继承父类，转换自己的数据格式，yui-ext提供了JSONDataModel和XMLDataModel两种数据格式转换。</p>
<p>3) 使用grid显示dataModel数据 <br>js例子： <br>var grid = new YAHOO.ext.grid.Grid('example-grid', dataModel, colModel); <br>grid.render(); <br>jsp页面例子： <br>&lt;div id="example-grid" style="border: 1px solid #cccccc; overflow: hidden; width: 535px; height: 225px;"&gt;&lt;/div&gt; <br>说明：colModel的使用看example，grid绑定dataModel后，在页面的&lt;Div&gt;显示grid。 <br></p><img src ="http://www.cnitblog.com/tilan/aggbug/35975.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/tilan/" target="_blank">Joinclass Inc</a> 2007-11-07 14:09 <a href="http://www.cnitblog.com/tilan/archive/2007/11/07/35975.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>应用maven的感想 </title><link>http://www.cnitblog.com/tilan/archive/2007/10/29/35541.html</link><dc:creator>Joinclass Inc</dc:creator><author>Joinclass Inc</author><pubDate>Mon, 29 Oct 2007 08:28:00 GMT</pubDate><guid>http://www.cnitblog.com/tilan/archive/2007/10/29/35541.html</guid><wfw:comment>http://www.cnitblog.com/tilan/comments/35541.html</wfw:comment><comments>http://www.cnitblog.com/tilan/archive/2007/10/29/35541.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.cnitblog.com/tilan/comments/commentRss/35541.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/tilan/services/trackbacks/35541.html</trackback:ping><description><![CDATA[使用maven2一段时间了，我基本把我自己能够迁移的project都转换为maven2 project，以下是我的一点感想。<br><br>（原作者温少，转载请注明）<br>
<h2>乱世盼英雄</h2>
<br>现在的软件开发，比过去的软件开发要复杂得多。包括在参与开发的人数、代码规模、复杂的需求、依赖包的复杂性、使用到更多的技术、多个项目之间的复杂依赖关系。<br><br>现在的开发人员，要掌握的技术要比过去的开发人员要多，不是现在的开发人员比以前的开发人员本身更优秀，而是拥有更多的资料、更多的学习机会、更多更大规模的时间，同时软件行业也在发展。说一句题外话，老程序员，如果不与时俱进，靠老本，是无法和新一代程序员竞争的，当然，老程序员，拥有更多的经验，掌握新技术的速度更快，这又是另外一回事。<br><br>开发人员掌握的技术更复杂了，项目用得的技术自然也是更复杂，例如一个web项目，可能使用到很多技术，面向对象、泛型、or-mapping、依赖注入（spring-framework）、全文检索（lucene）、数据库、集群、工作流、web service等等。<br><br>由于使用了多种技术，这些技术可能是JDK提供的，也可能是第三方开源组织提供的，或者不同的商业公司提供的。<br><br>于是出现了一个新的难题，就是包依赖复杂性。以前，你很难想象你的代码依赖数十个不同开源组织、商业公司提供的库。例如，我们经常使用的log4j、junit、easymock、ibatis、springframework，每个组件都有悠久的历史，存在不同的版本，他们之间版本还有依赖关系。<br><br>项目依赖的复杂性，经常的，一个较大部门有10-30个项目是常事，项目之间有不同版本的依赖关系，部门与部门之间的项目也存在复杂的版本依赖关系。<br><br>Eclipse本身提供Project的依赖，但是简单的依赖显然解决不了问题。例如Project B依赖Project A，Project A依赖第三方的jar包abc-1.0.jar，那么需要在两个项目的lib下都存放abc-1.0.jar，这产生冗余，当Project数量多起来，这个冗余就产生了管理问题，如果需要将abc-1.0.jar升级为abc-1.1.jar，则需要在两个Project中同时修改，如果Project数量达到10个以上，而且是不同项目组维护的项目，这个就是非常麻烦的事情。而且Project A修改依赖，为啥需要Project B也作相应的修改呢？<br><br>需要解决此问题，就需要在Project A的包中描述其依赖库的信息，例如在META-INFO记录所以来的abc-1.0.jar等。Eclipse的plug-in拥有类似的方案，但是这样一来，就使得开发Project B的项目组，需要把Project A的代码从源代码库中check out出来。在依赖链末端的项目组是很惨的。<br><br>由于Project数量众多，关系复杂，dailybuild的ant脚本编写成了很麻烦的事情，使用Project依赖的方式，更加使得编写dailybuild ant script是非常痛苦的事情。<br><br>当然也可以不使用project依赖的方式，而使用artifact lib的依赖方式，但是artifact lib的依赖方式，就是同时修改多个project，互相调试时带来了痛苦。<br><br>在以前，我们面临这些问题时，唯一的感觉就是，这事情TMD的太麻烦，几乎是失控了。<br><br>maven的出现，解决这种问题看到了希望。maven出现的原因就是，现在的开发管理复杂度达到了一定程序，需要专门的开发管理工具，这样的工具需要涵盖开发的各个阶段，包括工程建立、配置依赖管理、编译、测试、产生分析报告、部署、产生制品等阶段。目前，各个阶段的工具都存在，但是不是集成的，对使用带来了很大麻烦。maven集成了这些工具，提高了统一的环境，使得使用更简单。<br><br>现在maven非常流行了，apache上所有java project都已经build by maven，其他跟进的开源项目非常多，例如mule、hibernat等等，商业公司也很多在采用，sun公司提供有maven2 repository。<br><br>现在，2007年，如果你还没采用maven project，你可能需要思考一下，是否你使用了不恰当的方式管理的代码，或者你落伍了？<br>
<h2>maven的一些常用任务</h2>
compile 编译代码<br>test 运行单元测试<br>package 打包代码<br>site 产生报告，例如java doc、junit的通过率报告和覆盖率报告、findbugs的分析报告等等。<br>assembly 使用需求产生assembly，例如把生成一个程序目录，包括bin、config、lib、logs，把依赖包放在lib中。<br>deploy 部署制品到repository中。<br><br>这些都是常用的任务，在以前编写脚本很麻烦，现在在maven中，一切都是很简单，需要仔细设置时功能又强大到令人惊叹，例如site的fml，assembly。<br><br>
<h2>maven资源库</h2>
maven官方提供了一个常用lib的资源库，包括apache的所有java项目，开源常用的基本都能够找到，例如mule、c3p0、easymock、hibernate、springframework、json等等，版本齐全，任你挑选。<br><br>可以部署本地资源库代理提高下载速度。使用maven proxy。<br><br>
<h2>maven体系结构</h2>
<br>maven使用plug-in的体系，使用很好的自动更新策略，本身用到的jar都是lazy download的，可以指定download的repository。这样，初始下载的maven是一个很小的程序，使用的时候从本地的资源库或者本地代理资源库高速下载lib。maven的插件体系，充分利用了internet的资源丰富和局域网的高速带宽，使用本地repository时，可以享受到每秒钟数M的下载速度，感觉就是，人生真是美妙！<br><br>elcipse的plug-in体系，就不是那么好用了，我们使用eclipse的find and install功能下载或者更新插件时，慢如蜗牛，依赖缺失时的烦恼，更新一个plug-in，可能耗费你数个小时，第三方的plug-in的下载服务器可能更慢，例如subversive的plugin-in，有一次我花了两天还没下载好，只好使用下载工具下载好，copy到plug-in目录下。此时，我们总是感叹，人生总是有很多烦恼事啊！<br><br>相比之下，高下立判！在此我不是说eclipse的plug-in体系结构设计不好，eclipse的插件体系非常优秀，但是还有很大改进空间！<br><img src ="http://www.cnitblog.com/tilan/aggbug/35541.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/tilan/" target="_blank">Joinclass Inc</a> 2007-10-29 16:28 <a href="http://www.cnitblog.com/tilan/archive/2007/10/29/35541.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>IBM WebSphere Application Server 诊断和调优(一)续 </title><link>http://www.cnitblog.com/tilan/archive/2007/08/20/32112.html</link><dc:creator>Joinclass Inc</dc:creator><author>Joinclass Inc</author><pubDate>Mon, 20 Aug 2007 06:25:00 GMT</pubDate><guid>http://www.cnitblog.com/tilan/archive/2007/08/20/32112.html</guid><wfw:comment>http://www.cnitblog.com/tilan/comments/32112.html</wfw:comment><comments>http://www.cnitblog.com/tilan/archive/2007/08/20/32112.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/tilan/comments/commentRss/32112.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/tilan/services/trackbacks/32112.html</trackback:ping><description><![CDATA[<p>个人体会： <br>IBM的WAS服务器使用难度上，也许比BEA的WLS服务器难10倍，学习成本很高，我05年末几乎花了两个月时间在它上面，天天研究那几本红皮书，测试。IBM的红皮书质量真的非常不错，但太多了。</p>
<p>WAS是定位在大型企业应用，集群系统。它的cell--&gt;node--&gt;server，profiles架构以及server上的cluster做得还挺强大的。但是，也许99%的用户都用不到，而且它的cell--&gt;node--&gt;server架构在WLS的domain--&gt;server类似，但WLS非常易用。不过对于大型网站的前端http server，IBM自己加工的那个apache，和WAS配合还是挺好的。</p>
<p>在部署方面，WAS比WLS烦琐得多，虽然也支持命令行和自动部署，但比WLS难，因为发布一个app，大概要更新18个xml配置文件，n个步骤，手动更改配置文件几乎不现实，而WLS只需要把package丢过去就ok了，production环境下也只要控制台选择一下就ok了。在WAS下，我碰到一次是，集群同步时出错，下次几个server都启动不起来，手动修改serverindex.xml等相关文件才搞定，幸好那只是测试环境。</p>
<p>我用JProfiler监测WAS和WLS，WAS运行一段时间后，当时我那个环境启动了300多个thread，而WLS只启动50多个，而且WAS启动一般三分钟，而WLS可能半分钟。</p>
<p>另外，一般IBM的WAS运行在AIX、小型机环境下，而小型机的内存可能有个8G，这时候，最好是把WAS做成纵向分布式，也就是说，一个AIX上安装两个WAS。这个我当初也不明白，现在有体会了，因为这样比较好利用内存，因为JVM的heap设置过大并不好，很影响GC性能。还有，可能你的实际的应用怎么都不可能超过2G的heap。</p>
<p>给大家推荐几本WAS部分用到的IBM红皮书吧，他对我摆平我们这个大项目的WAS问题非常有帮助，我只推荐我仔细读过的、认为最值得看的，它们都可以在ibm红皮书网站下载： <br>《WebSphere Application Server V6 System Management &amp; Configuration.pdf》：WAS教材 <br>《WebSphere Application Server V6 Planning and Design WebSphere Handbook Series.pdf》：WAS教材高级版本，怎么去规划WAS。 <br>《WebSphere Version 6 Web Services Handbook Development and Deployment.pdf》：Web Services教材，对Web Services本身讲解也很深入浅出。 <br>《WebSphere Application Server V6 Security Handbook.pdf》：WAS安全必备书籍 <br>《WebSphere Application Server V6 Problem Determination for Distributed Platforms.pdf》：WAS出问题了，看它吧。不过，这本书太初级，恐怕出了问题，它70％都不能帮你解决，还是去找IBM技术支持吧。</p>
<p>建议：WAS出问题了，一定要耐心研读红皮书，了解WAS的原理，盲目尝试往往都得不偿失，因为你做点改动，启动重启一次都要5分钟，重启20多次，一般一天时间就过去了，也就是说你只能知道有20个不行的尝试，但也许还有100个不行的尝试等着你，呵呵。总之，尝试你永远都不知道真正为什么会出错。</p>
<p>忘了，一定深入了解WAS里面的Classloader原理，这对你部署过程中出问题非常有帮助，譬如xml找不到，log打印不出来呀，我曾经也是饱受折磨。用好它，必须有深厚的理论基础，它不是给普通开发人员用的，反正我认为他的易用性是很失败的。</p><img src ="http://www.cnitblog.com/tilan/aggbug/32112.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/tilan/" target="_blank">Joinclass Inc</a> 2007-08-20 14:25 <a href="http://www.cnitblog.com/tilan/archive/2007/08/20/32112.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>IBM WebSphere Application Server 诊断和调优(一) </title><link>http://www.cnitblog.com/tilan/archive/2007/08/20/32110.html</link><dc:creator>Joinclass Inc</dc:creator><author>Joinclass Inc</author><pubDate>Mon, 20 Aug 2007 05:48:00 GMT</pubDate><guid>http://www.cnitblog.com/tilan/archive/2007/08/20/32110.html</guid><wfw:comment>http://www.cnitblog.com/tilan/comments/32110.html</wfw:comment><comments>http://www.cnitblog.com/tilan/archive/2007/08/20/32110.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cnitblog.com/tilan/comments/commentRss/32110.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/tilan/services/trackbacks/32110.html</trackback:ping><description><![CDATA[<p>近段时间，我们项目中用到的WebSphere应用服务器(WAS)，但在客户的production环境下极不稳定，经常宕机。给客户造成非常不好的影响，同时，也给项目组很大压力。为此，我们花了近一个月时间对其诊断，现在基本上稳定了，需要继续观察一段时间。现在我主要将工作做一个阶段性的总结。 <br>我们的产品环境是：WAS6.0＋DB2 8.1＋AIX5.3＋RS/6000。在该产品环境下，出现的问题非常多，现象如下： <br>WAS经常不稳定、宕机几乎一天一次，经常报告OutOfMemory(内存泄漏吗？NO)。 <br>DB2连接数过大，有时把DB2撑死，有时也把AIX撑死。 <br>AIX虚拟内存报错、分页报错、IO也报错、还有很多其它莫名奇妙的错。</p>
<p>总是，每次问题发生的现象和理论上的总是不一致，导致我们不知道从何入手，也无从检测自己的优化参数。咨询过多次IBM技术支持，只解决了某些局部问题。 <br>虽然问题依然存在，但我想，解决问题的思路、特别是理论基础，还是有一些规律和原则。</p>
<p>对于WAS这块，我近段时间的主要时间集中在以下几个方面(时间顺序)： <br>1、Java性能监测工具：Jprofiler，也用到Jprobe。后来发现Jprofiler在AIX下几乎不可用。 <br>2、IBM Java虚拟机和WAS技术细节，特别是IBM JVM的GC原理，我发现它和sun、bea的差别很大。 <br>3、IBM的heap分析器Heap Analyzer、GCCollector。这两个事后监测工具非常实用，特别是我们的产品运行环境，非测试环境。 <br>4、某些Application的怀疑和诊断。 <br>5、AIX诊断，我几乎没有这个能力，只能常规监测一下，需另请高人。</p>
<p>我打算将本文分成以下几个部分总结： <br>JVM原理、IBM JVM的GC策略和调优。 <br>Jprofiler和IBM工具的实际体会 <br>WAS的诊断体会和AIX调优</p>
<p>下面开始主题吧，可能比较零碎，另外，开始的理论篇基本上看书都可以，我只是总结一下，再添加一些自己的理解。</p>
<p>以下是我参考的最重要的两本电子书和一些网站： <br>《Inside Java Vrtual Machine》:半部分有约四章我认为非常棒，其它章节可能意义不大。 <br>《The Java Virtual Machine Specification, 2nd》：前半部分有两三章很不错，不过可以对照上一本书看。 <br>sun的hotspot虚拟机技术：<a href="http://java.sun.com/javase/technologies/hotspot/" target=blank><u><font color=#0000ff>http://java.sun.com/javase/technologies/hotspot/ </font></u></a><br>BEA的JRockit虚拟机技术：<a href="http://edocs.bea.com/jrockit/geninfo/genintro/index.html" target=blank><u><font color=#0000ff>http://edocs.bea.com/jrockit/geninfo/genintro/index.html </font></u></a>JVM技术文档入口，虚拟机理论，内存泄漏诊断等的索引页。 <br>IBM诊断资料：<a href="http://www-128.ibm.com/developerworks/java/jdk/diagnosis/" target=blank><u><font color=#0000ff>http://www-128.ibm.com/developerworks/java/jdk/diagnosis/</font></u></a> 上面有一个500多页的pdf文档，对IBM JVM技术和诊断讲解很深入。</p>
<p>我不得不提的是，在查资料这块，BEA和Sun都有很好的官方文档和论坛支持，并且官方文档导航非常好。虽然IBM的诊断资料也不少，但需要搜索，其搜索是很痛苦的。而且，IBM官方论坛很差。如果用IBM的产品出问题，切记：找IBM技术支持，千万不要蒙着头搞！反正它们的产品很少免费。说实话，它们的技术支持还是挺负责的，一般会为你推荐很多support资料，而该资料往往都在developerworks网站上，属于support那个频道，但你就是搜不着。</p>
<p><strong>Java虚拟机规范概要</strong> <br>研究Java虚拟机，首先要了解Sun的Java虚拟机规范。现在，该实现版本很多，如比较有名的Sun、IBM、BEA、Apple、HP、MS、Apache Harmony。它们都实现了JVM规范，但有各自扩展。譬如，针对IBM虚拟机的堆碎片导致OutOfMemory（OOM），在Sun的虚拟机上就不会发生。Sun的JVM有maxPermSize的概念，IBM就没有，如果你设置这个参数，虚拟机根本就启动不了。 <br>比较有意思的是，学Java，就一定要了解各种规范，这和MS的风格很不一样。Sun总是在定义一些规范，实现都留给各厂商。我们除了理解规范本身外，一定要理解规范和实现之间的关系，譬如JDBC规范和JDBC驱动的关系，它们是怎么组合到一起的。要是你用过php的xml解析库，或db函数，就会体会深刻，它们可没有什么规范可言，所以每个数据库厂商的db函数用法都不一样。我推荐大家研读一下HSQLDB的jdbc和Tomcat的servlet相关实现，因为我认为它们还是比较好懂的。 <br>JVM规范只是定义一个虚拟机该做什么，但它并没有要求你该怎么做。例如我们最常见的Servlet规范，在该规范中，有HttpServletRequest、HttpServletResponse，HttpSession等接口，但它们的实现都留给了各个容器厂商。遗憾的是，规范留下的空白，会把我们这些开发人员给整惨了：容器间移植有时候就是恶梦。譬如J2EE并没有SSO规范，但它很重要，我以前专门针对它做过WebSphere AppServer和Weblogic AppServer的SSO项目，差别还是不小，不过还是有点共通，那就是都遵循JAAS规范。</p>
<p><strong>JVM的结构</strong> <br>从功能上分，Java虚拟机主要由六个部分组成，可以分成三类： <br>第一类：JVM API：就是我们最常用的Java API，它是开发人员和Java交互的入口，它主要是JAVA_HOME/jre/lib下的运行时类库rt.jar和编译相关的tools.jar</p>
<p>第二类：JVM内部组件 <br><strong>类装载器</strong>(ClassLoader)：将Byte Array的 .class文件装载、链接和初始化。 <br><strong>内存管理</strong>(Memory Managent)：为对象分配内存，以及释放内存。后者就是垃圾回收Garbage Collector（GC）。由于JVM最复杂的、最影响性能的就是GC，所以内存管理一般就指垃圾回收。 <br><strong>诊断接口</strong>(Diagostics Interface)：这主要体现在JVMTI(jdk1.4下的JVMPI和JVMDI)，它主要用来诊断程序的问题和性能，一般提供给工具厂商实现。如eclispe IDE下的debug功能，Jprofiler性能调优工具。 <br><strong>类解释器</strong>(Interpreter)：解释装载进虚拟机的class对象，包括JIT等特性相关。</p>
<p>第三类：平台相关接口(Platform Interface)：主要为了跨操作系统平台重用JVM代码，不过，它和我们开发人员关系不大。</p>
<p>在以上六个组件中，我们开发人员最关心的是<strong>ClassLoader</strong>和<strong>GC</strong>，用Java做系统框架、容器和它们密切相关。做业务系统时一些基础代码也和它们打交道，譬如最常用的Class.forName(),Thread.currentThread.getContextClassLoader()。我们仔细想想，为什么是上面两个问题？因为，它和我们class的整个生命周期最为相关：怎么将一个class和相关class加载进来，class实例什么时候创建，什么时候被销毁？ <br>所以，下面的部分我们要专门讨论这些问题。</p>
<p><strong>ClassLoader</strong> <br>JVM主要有三类ClassLoader：Bootstrap、Extention、Application，该三类ClassLoader从上到下是分级(hierarchy)结构，遵循代理模型(Delegation Model)。 <br>Tip：大家可以看看sun.misc.Launcher的源码，Bootstrap和Extention就在该文件里。该src可以在sun的网站上下载该压缩包，约60M(jdk-1_5_0-src-scsl.zip)，它不在jdk自带的那个src.zip里。</p>
<p>Bootstrap ClassLoader：也称为primordial(root) class loader。主要是负责装载jre/lib下的jar文件，当然，你也可以通过-Xbootclasspath参数定义。该ClassLoader不能被Java代码实例化，因为它是JVM本身的一部分。</p>
<p>Extention ClassLoader：该ClassLoader是Bootstrap classLoader的子class loader。它主要负责加载jre/lib/ext/下的所有jar文件。只要jar包放置这个位置，就会被虚拟机加载。一个常见的、类似的问题是，你将mysql的低版本驱动不小心放置在这儿，但你的Web应用程序的lib下有一个新的jdbc驱动，但怎么都报错，譬如不支持JDBC2.0的DataSource，这时你就要当心你的新jdbc可能并没有被加载。这就是ClassLoader的delegate现象。常见的有log4j、common-log、dbcp会出现问题，因为它们很容易被人塞到这个ext目录，或是Tomcat下的common/lib目录。</p>
<p>Application ClassLoader：也称为System ClassLoaer。它负责加载CLASSPATH环境变量下的classes。缺省情况下，它是用户创建的任何ClassLoader的父ClassLoader，我们创建的standalone应用的main class缺省情况下也是由它加载(通过Thread.currentThread().getContextClassLoader()查看)。 <br>我们实际开发中，用ClassLoader更多时候是用其加载classpath下的资源，特别是配置文件，如ClassLoader.getResource()，比FileInputStream直接。</p>
<p>ClassLoader是一种分级(<strong>hierarchy</strong>)的代理(<strong>delegation</strong>)模型。 <br>Delegation：其实是Parent Delegation，当需要加载一个class时，当前线程的ClassLoader首先会将请求代理到其父classLoader，递归向上，如果该class已经被父classLoader加载，那么直接拿来用，譬如典型的ArrayList，它最终由Bootstrap ClassLoader加载。并且，每个ClassLoader只有一个父ClassLoader。 <br>Class查找的位置和顺序依次是：Cache、parent、self。 <br>Hierarchy：上面的delegation已经暗示了一种分级结构，同时它也说明：一个ClassLoader只能看到被它自己加载的classes，或是看到其父(parent) ClassLoader或祖先(ancestor) ClassLoader加载的Classes。 <br>在一个单虚拟机环境下，标识一个类有两个因素：class的全路径名、该类的ClassLoader。</p>
<p>我碰到的一个典型的例子是：在做WAS的SSO开发时，由于我们的类是由WAS在启动时加载，该ClassLoader比下面的部署的Applicaton的ClassLoader的级别高。所以，在我们自己的类中没法用到应用程序的连接池，必须自建。 <br>代理模型是Java安全模型的保证。譬如，我们自己写一个String.java，并且编译、package到自己的java.lang包下。按照代理模型，当前线程的ClassLoader会将其代理到父ClassLoader，父ClassLoader(最终会是Bootstrap)会找到rt.jar下的String.class，也就是说我们的String.class不会捣乱。</p>
<p><strong>自定义ClassLoader</strong> <br>我们前面说过，自定义ClassLoader的缺省父ClassLoader是Application ClassLoader。一般的应用开发用不到它，但我们最好理解。因为在内存泄漏查找、应用程序部署出问题时，很多都和它有关。 <br>譬如，内存泄漏是怎么产生的？这就涉及到ClassLoader和Class的生命周期。我曾经碰到这样一个问题：我们的程序用到了Webwork和Spring框架，当部署到Tomcat下时没有任何问题，但部署到WAS下，报告找不到Webwork的xml的DTD文件，而且Spring的日志也总是失效。Why？因为解析xml dtd时，用的是IBM的Xerces，不是我们的。而Spring日志问题是因为应用程序用的是WAS的Common-log.jar，而不是我们的。将应用的ClassLoader从默认的Parent-First，改成Parent-Last就可以解决，不过我们项目中用到其它库，又发生了其它问题。</p>
<p>一般来说，用到自定义ClassLoader有三种情况： <br>1、应用框架可以自己控制Classes的目录，并且自动部署。 <br>我读过Jive公司的Wildfire(著名的即时通讯服务器)，它自己有一套应用框架，非常灵活，遵循该框架插件规范的的第三方的plug-in放置在指定目录可以自动部署，实现某些扩展功能，如文件传输、语音聊天。 <br>2、区分用户代码 <br>这被广泛应用在Servlet容器和类似容器，譬如EJB Container设计中，大家看到Tomcat下有common、server、share三个目录吧(ClassLoader顺序从左到有)，另外也有用户应用的WEB-INF目录，它是我们自己开发的。 <br>3、允许Classes卸载 <br>如果没有自定义的ClassLoader，那么我们自己应用中的classes永远都不能被卸载，因为这些类被Application ClassLoader加载后cache起来了，我们的classes一直对该ClassLoader有引用，而该系统级的ClassLoader永远都不会被卸载，除非JVM shutdown了。JSP和Servlet的动态部署就用到这个特性。</p>
<p>待续.......</p>
<p>Note: 还有JVM运行时(Runtime)架构，ClassLoader加载class过程没有总结，这两部分我觉得太重要了，但内容太多，写不完啊。 <br>这部分内容，《Inside Java Virtual Machine》讲解非常清楚，BEA的官方网站这部分也非常不错，要理解深刻，我建议结合JProfiler工具，非常直观。</p><img src ="http://www.cnitblog.com/tilan/aggbug/32110.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/tilan/" target="_blank">Joinclass Inc</a> 2007-08-20 13:48 <a href="http://www.cnitblog.com/tilan/archive/2007/08/20/32110.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java开发者论坛--sqlsoft.com.cn</title><link>http://www.cnitblog.com/tilan/archive/2007/08/12/31654.html</link><dc:creator>Joinclass Inc</dc:creator><author>Joinclass Inc</author><pubDate>Sat, 11 Aug 2007 16:01:00 GMT</pubDate><guid>http://www.cnitblog.com/tilan/archive/2007/08/12/31654.html</guid><wfw:comment>http://www.cnitblog.com/tilan/comments/31654.html</wfw:comment><comments>http://www.cnitblog.com/tilan/archive/2007/08/12/31654.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/tilan/comments/commentRss/31654.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/tilan/services/trackbacks/31654.html</trackback:ping><description><![CDATA[<a  href="http://www.sqlsoft.com.cn/">http://www.SQLSoft.com.cn</a> 成立上线，欢迎IT人士加入<br><br><a  href="http://www.sqlsoft.com.cn/">http://www.SQLSoft.com.cn</a>&nbsp;  <br>开源框架下载站<br><br><a  href="http://bbs.sqlsoft.com.cn/">http://bbs.SQLSoft.com.cn</a><br>java开发者论坛<br><br><a  href="http://www.sqlsoft.com.cn/">SQLSoft.com.cn</a> 寻求资源合作<br>详细请联系：<br>msn:j.joy@msn.com&nbsp; <br>qq:269309672<br><br><br><img src ="http://www.cnitblog.com/tilan/aggbug/31654.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/tilan/" target="_blank">Joinclass Inc</a> 2007-08-12 00:01 <a href="http://www.cnitblog.com/tilan/archive/2007/08/12/31654.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Jquery是继prototype之后又一个优秀的Javascrīpt框架</title><link>http://www.cnitblog.com/tilan/archive/2007/08/03/31186.html</link><dc:creator>Joinclass Inc</dc:creator><author>Joinclass Inc</author><pubDate>Fri, 03 Aug 2007 06:07:00 GMT</pubDate><guid>http://www.cnitblog.com/tilan/archive/2007/08/03/31186.html</guid><wfw:comment>http://www.cnitblog.com/tilan/comments/31186.html</wfw:comment><comments>http://www.cnitblog.com/tilan/archive/2007/08/03/31186.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/tilan/comments/commentRss/31186.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/tilan/services/trackbacks/31186.html</trackback:ping><description><![CDATA[<p>Jquery是继prototype之后又一个优秀的Javascrīpt框架。对prototype我使用不多，简单了解过。但使用上jquery之后，马上被她的优雅吸引住了。有人使用这样的一比喻来比较prototype和jquery：prototype就像Java，而jquery就像ruby.实际上我比较喜欢java（少接触Ruby&nbsp;罢了）但是jquery的简单的实用的确有相当大的吸引力啊！在项目里我把jquery作为自已唯一的框架类包。使用其间也有一点点心得，其实这些心得，在jquery的文档上面也可能有讲，不过还是记下来，以备忘罢。</p>
<p><br>&nbsp;<br><strong>一，找到你了！</strong>&nbsp;<br>还记得$()这个东西吧？prototype还是DWR都使用了这个函数代替document.getElementById()。没错，jquery也跟风了。为达到document.getElementById()的目的，jquery是这样写的：&nbsp;<br><br><br>代码<br></p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 5px; BACKGROUND: #f3f3f3; PADDING-BOTTOM: 5px; MARGIN: 5px 20px; BORDER-LEFT: #cccccc 1px solid; PADDING-TOP: 5px; BORDER-BOTTOM: #cccccc 1px solid">var&nbsp;someElement&nbsp;=&nbsp;$("#myId");&nbsp;&nbsp;</div>
<br>看起来比其他两个框架的要多了一个#，好，看看下面的用法：&nbsp;<br>代码
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 5px; BACKGROUND: #f3f3f3; PADDING-BOTTOM: 5px; MARGIN: 5px 20px; BORDER-LEFT: #cccccc 1px solid; PADDING-TOP: 5px; BORDER-BOTTOM: #cccccc 1px solid">$("div&nbsp;p");(1)&nbsp;&nbsp;&nbsp;<br>$("div.container")(2)&nbsp;&nbsp;&nbsp;<br>$("div&nbsp;#msg");(3)&nbsp;&nbsp;&nbsp;<br>$("table&nbsp;a",context);(4)&nbsp;</div>
&nbsp;<br><br>在prototype里看过这样的写法吗？第一行代码得到所有&lt;div&gt;标签下的&lt;p&gt;元素。第二行代码得到class&nbsp;为container的&lt;div&gt;元素,第三行代码得到&lt;div&gt;标签下面id为msg的元素。第四行代码得到context为上下文的table里面所有的连接元素。&nbsp;<br>如果你熟悉CSS，Xpath，你会觉得这些写法很眼熟！对了。正是。看出奥妙了吧。jquery就是通过这样的方式来找到Dom对象里面的元素。跟CSS的选择器相类似。&nbsp;<br><br><strong>二，Jquery对象？</strong>&nbsp;<br>jquery提供了很多便利的函数，如each(fn)，但是使用这些函数的前提是：你使用的对象是Jquer对象。使一个Dom对象成为一个Jquery对象很简单，通过下面一些方式（只是一部分）：&nbsp;<br><br>代码<br>
<p class=code>&nbsp;</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 5px; BACKGROUND: #f3f3f3; PADDING-BOTTOM: 5px; MARGIN: 5px 20px; BORDER-LEFT: #cccccc 1px solid; PADDING-TOP: 5px; BORDER-BOTTOM: #cccccc 1px solid">var&nbsp;a&nbsp;=&nbsp;$("#cid");(1)&nbsp;&nbsp;&nbsp;<br>var&nbsp;b&nbsp;=&nbsp;$("&lt;p&gt;hello&lt;/p&gt;");(2)&nbsp;&nbsp;&nbsp;<br>var&nbsp;c&nbsp;=&nbsp;document.createElement("table");&nbsp;var&nbsp;tb&nbsp;=&nbsp;$(c);&nbsp;&nbsp;</div>
<br><br><strong>三，代替body标签的onload</strong>&nbsp;<br>这个惯例，也许是除了$()之外，用得最多的地方了。下面一段代码：&nbsp;<br><br>代码<br>
<p class=code>&nbsp;</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 5px; BACKGROUND: #f3f3f3; PADDING-BOTTOM: 5px; MARGIN: 5px 20px; BORDER-LEFT: #cccccc 1px solid; PADDING-TOP: 5px; BORDER-BOTTOM: #cccccc 1px solid">$(document).ready(function(){&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;alert("hello");&nbsp;&nbsp;&nbsp;<br>});(1)&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;<br>&lt;body&nbsp;onload="alert('hello');"&gt;（2）&nbsp;</div>
&nbsp;<br><br>上面两段代码是等价的。但代码1的好处是做到表现和逻辑分离。并且可以在不同的js文件中做相同的操作，即$(document).ready&nbsp;(fn)可以在一个页面中重复出现，而不会冲突。基本上Jqeury的很多plugin都是利用这个特性，正因为这个特性，多个plugin共同使用起来，在初始化时不会发生冲突。&nbsp;<br>不管怎么说，这个惯例可以分离javascrīpt与HTML。推荐使用。&nbsp;<br><br><strong>四，事件机制</strong>&nbsp;<br>我大量使用的事件可能就是button的onclick了。以前习惯在input&nbsp;元素上写onclick&nbsp;=&nbsp;"fn()",使用jquery可以使javascrīpt代码与html代码分离，保持HTML的清洁，还可以很轻松地绑定事件，甚至你可以不知道&#8220;事件&#8221;这个名词。&nbsp;<br><br>代码<br>
<p class=code>&nbsp;</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 5px; BACKGROUND: #f3f3f3; PADDING-BOTTOM: 5px; MARGIN: 5px 20px; BORDER-LEFT: #cccccc 1px solid; PADDING-TOP: 5px; BORDER-BOTTOM: #cccccc 1px solid">$(document).ready(function(){&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;$("#clear").click(function(){&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;alert("i&nbsp;am&nbsp;about&nbsp;to&nbsp;clear&nbsp;the&nbsp;table");&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;});&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;$("form[0]").submit(validate);&nbsp;&nbsp;&nbsp;<br>});&nbsp;&nbsp;&nbsp;<br>function&nbsp;validate(){&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;//do&nbsp;some&nbsp;form&nbsp;validation&nbsp;&nbsp;&nbsp;<br>}</div>
&nbsp;&nbsp;<br><br><strong>五，同一函数实现set&amp;get</strong>&nbsp;<br><br>代码<br>
<p class=code>&nbsp;</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 5px; BACKGROUND: #f3f3f3; PADDING-BOTTOM: 5px; MARGIN: 5px 20px; BORDER-LEFT: #cccccc 1px solid; PADDING-TOP: 5px; BORDER-BOTTOM: #cccccc 1px solid">$("#msg").html();&nbsp;&nbsp;&nbsp;<br>$("#msg").html("hello");&nbsp;&nbsp;</div>
<br><br>上面两行代码，调用了同样的函数。但结果却差别很大。&nbsp;<br>第一行是返回指定元素的HTML值，第二行则是将hello这串字符设置到指定元素中。jquery的函数大部分有这样的特性。<br>&nbsp;<br><strong>六，ajax</strong>&nbsp;<br>这是一个ajax横行的时代。多少人，了不了解ajax的都跟着用上一把。呵。使用jquery实现ajax同样简单异常&nbsp;<br><br>代码<br>
<p class=code>&nbsp;</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 5px; BACKGROUND: #f3f3f3; PADDING-BOTTOM: 5px; MARGIN: 5px 20px; BORDER-LEFT: #cccccc 1px solid; PADDING-TOP: 5px; BORDER-BOTTOM: #cccccc 1px solid">
<p class=code>$.get("search.do",{id:1},rend);&nbsp;&nbsp;&nbsp;<br>function&nbsp;rend(xml){&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;alert(xml);&nbsp;&nbsp;&nbsp;<br>}&nbsp;(1)&nbsp;&nbsp;&nbsp;<br>$.post("search.do",{id:1},rend);&nbsp;&nbsp;&nbsp;<br>function&nbsp;rend(xml){&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;alert(xml);&nbsp;&nbsp;&nbsp;<br>}&nbsp;(2)&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;<br>$("#msg").ajaxStart(function(){&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;this.html("正在加载。。。。");&nbsp;&nbsp;&nbsp;<br>});(3)&nbsp;&nbsp;&nbsp;<br>$("#msg").ajaxSuccess(function(){&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;this.html("加载完成！");&nbsp;&nbsp;&nbsp;<br>});(4)&nbsp;&nbsp;</p>
</div>
<p class=code><br><br>这些都是较常用的方法，get和post用法一样。第一个参数是异步请求的url，第二个为参数，第三个回调方法。&nbsp;<br>3，4的方法会在指定的Dom对象上绑定响应ajax执行的事件。当然，jquery的AJAX相关的函数不仅是这些，有兴趣可以去研究再多。<br>&nbsp;<br><strong>七，渐入淡出</strong>&nbsp;<br><br>代码<br></p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 5px; BACKGROUND: #f3f3f3; PADDING-BOTTOM: 5px; MARGIN: 5px 20px; BORDER-LEFT: #cccccc 1px solid; PADDING-TOP: 5px; BORDER-BOTTOM: #cccccc 1px solid">
<p class=code>$("#msg").fadeIn("fast");&nbsp;&nbsp;&nbsp;<br>$("#msg").fadeOut("slow");&nbsp;&nbsp;</p>
</div>
<p class=code><br><br>没错，上面两行代码已经分别实现了一个id为Msg的jquery对象的渐入和淡出。做一个像Gmail一样的动态加载通知条，用jquery就那么简单。两个函数接受的参数除了快慢等，还可以接收整型，作为渐入或淡出的完成时间，单位为MS。<br>&nbsp;<br><strong>八，plugin</strong>&nbsp;<br>这也是一个插件的时代。&nbsp;<br>jquery插件给我的感觉清一色的清洁，简单。如Jtip，要使用它的功能，只需要在你的元素的class上加上Jtip,并引入jtip.js及其样式即可以了。其他事情插件全包。我喜欢jquery的一个重要原因是发现她已经有了很多很好，很精彩的插件。&nbsp;<br>写得很烂。可能大家看不出jquery的好处。嗯，光听是没用的，试用一下吧。你会发觉很有趣。&nbsp;<br>暂时告一段落吧。待有新的发现再来分享。<br><br><strong>加一些Jquery的资源：</strong>&nbsp;<br>http://www.visualjquery.com/index.xml&nbsp;很好的API查询站点&nbsp;<br>http://jquery.com/demo/thickbox/&nbsp;知道lightBox吧，看看Jquery是怎样实现相同的东西&nbsp;<br>http://www.codylindley.com/blogstuff/js/jtip/&nbsp;Jtip，实用的提示工具&nbsp;<br>http://jquery.com/plugins/&nbsp;很多牛的插件。&nbsp;<br>http://15daysofjquery.com/jquery&nbsp;的15天教程<br></p><img src ="http://www.cnitblog.com/tilan/aggbug/31186.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/tilan/" target="_blank">Joinclass Inc</a> 2007-08-03 14:07 <a href="http://www.cnitblog.com/tilan/archive/2007/08/03/31186.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>八大原因让Linux远离普通用户</title><link>http://www.cnitblog.com/tilan/archive/2007/05/31/27851.html</link><dc:creator>Joinclass Inc</dc:creator><author>Joinclass Inc</author><pubDate>Thu, 31 May 2007 02:38:00 GMT</pubDate><guid>http://www.cnitblog.com/tilan/archive/2007/05/31/27851.html</guid><wfw:comment>http://www.cnitblog.com/tilan/comments/27851.html</wfw:comment><comments>http://www.cnitblog.com/tilan/archive/2007/05/31/27851.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cnitblog.com/tilan/comments/commentRss/27851.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/tilan/services/trackbacks/27851.html</trackback:ping><description><![CDATA[<p><span>【</span><strong><span>CSDN 2007.5.29 </span></strong><strong><span>译文】</span></strong><span>本文来自于<span>Linux Community</span>，</span><span>作者试图解答下面的问题</span><strong><span>：</span></strong>
<p align=left><strong><span>&nbsp;&nbsp; </span></strong><strong><span>&#8220;有如此多的</span></strong><strong><span>Linux</span></strong><strong><span>版本可供下载、安装并完全免费使用的替换方案，为什么普通电脑用户仍然会选择花费几百美金去购买</span></strong><strong><span>Windows</span></strong><strong><span>或</span></strong><strong><span>Mac</span></strong><strong><span>操作系统呢&#8221;？</span></strong></p>
<p align=left><span>总的来说，并不是所有人都讨厌</span><span>Windows</span><span>的：普通用户每天在使用他们的</span><span>Windows</span><span>电脑时并没有遇到很多麻烦。</span></p>
<p align=left><span>版本型号过多：</span> <span>人们在面对</span><span>Vista</span><span>时只需考虑是选择家用基本版还是升级版，但普通的用户该如何在</span><span>36</span><span>种不同口味的</span><span>Linux</span><span>中做出选择呢？人们说&#8220;选择一个合适</span><span>Linux</span><span>版本的感觉，有点象一个没有经验的人来到了星巴克咖啡馆，你期望能够点一杯普通咖啡</span><span>---</span><span>但你会马上意识到生活并不是那么简单，你需要跑出长队并做大量的研究，然后再一次走到柜台前。&#8221;</span></p>
<p align=left><span>人们需要确定的是硬件和软件都能很好的工作：&#8220;所有人在从</span><span>Windows</span><span>转到</span><span>Linux</span><span>时都需要从头开始考虑应用程序的问题</span><span>... ...</span><span>考虑每一个你所用应用程序的替代方案是一件很繁重的工作。&#8221;</span></p>
<p align=left><span>至于大多数人所关心的，（</span><span>Linux</span><span>）命令行又走了恐龙式的复杂路线：它提供的功能更强大了，就象是</span><span>Windows </span><span>的</span><span>PowerShell</span><span>（一种脚本技术），但是你确定普通用户也需要如此强大的功能吗？也许这对于系统管理员在维护服务器运行环境时会很有效，但普通用户甚至不需要知道它（命令行）的存在。</span></p>
<p align=left><span>&nbsp;Linux</span><span>桌面仍然很令人讨厌：但我认为这方面他们正在改进，</span><span>Ubuntu</span><span>桌面就比几年前的</span><span>KDE</span><span>或</span><span>Gnome</span><span>更加友好，再看</span><span>Bery1</span><span>桌面</span><span>... ...</span><span>确实令人惊讶！！但是我自己并非普通用户，我不认为我的律师朋友在写合同或文件的时候会发现它是实用的。</span></p>
<p align=left><span>由于</span><span>Mac</span><span>的影响：想要追求与众不同的人会选用</span><span>Mac</span><span>，它建立在</span><span>Unix</span><span>之上，但是所有的复杂性都隐藏在性感的</span><span>GUI</span><span>和围绕它建立的封闭</span><span>hw Apple</span><span>背后。</span></p>
<p align=left><span>谁来提供免费的技术支持？：大家会知道，周围人中&#8220;谁熟悉</span><span>Windows</span><span>系统&#8221;。在</span><span>Mac</span><span>系统下，这个问题更需要谨慎对待。但对于</span><span>Linux</span><span>，我真的怀疑象一个普通会计</span><span>Jane</span><span>，在她的朋友圈中是否会有人擅长</span><span>Linux</span><span>。</span></p>
<p align=left><span>冷静下来，这仅仅是一个操作系统！：在</span><span>Linux</span><span>社区里充满了新潮的男孩，他们把这个开源操作系统看得太严肃了，这让人觉得充满了攻击性，并且有太多</span><span>RTFM</span><span>（指只要查阅文件就可以解决，拿出来提问只是浪费别人时间的问题）问题。这让人们远离了</span><span>Linux</span><span>。</span></p>
<p align=left><span>　　我热爱</span><span>Linux</span><span>，我认为</span><span>Beryl</span><span>的桌面很好，强大的命令行功能很好，能够自由选择哪一个应用程序运行也很好，但是，就象我之前说的，我并不是一个普通用户，就象</span><span>98%</span><span>阅读我文章的读者（大多为</span><span>Linux</span><span>爱好者）一样。　</span></p>
<p align=left><span>　　　普通用户可不愿意花费整晚的时间对着电脑研究它们（</span><span>Linux</span><span>），仅仅为了让它们能够正常运行。</span><span>【<strong>翻译　付江】</strong></span></p><img src ="http://www.cnitblog.com/tilan/aggbug/27851.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/tilan/" target="_blank">Joinclass Inc</a> 2007-05-31 10:38 <a href="http://www.cnitblog.com/tilan/archive/2007/05/31/27851.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JavaFX Script将终结AJAX？还是另一种选择？</title><link>http://www.cnitblog.com/tilan/archive/2007/05/31/27843.html</link><dc:creator>Joinclass Inc</dc:creator><author>Joinclass Inc</author><pubDate>Thu, 31 May 2007 01:54:00 GMT</pubDate><guid>http://www.cnitblog.com/tilan/archive/2007/05/31/27843.html</guid><wfw:comment>http://www.cnitblog.com/tilan/comments/27843.html</wfw:comment><comments>http://www.cnitblog.com/tilan/archive/2007/05/31/27843.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/tilan/comments/commentRss/27843.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/tilan/services/trackbacks/27843.html</trackback:ping><description><![CDATA[<h5>在JavaOne会议上，Sun负责软件业务的执行副总裁格林公布了JavaFX Script:一种用于编写能够在支持Java的PC和手机上运行的应用软件的更简单的脚本语言。理查德表示，通过JavaFX Script和JavaFX Mobile，Sun和其它Java</h5>
<div class=newscon>
<div><script type=text/javascript>show_ads_zone(13);</script><script language=JavaScript src="http://z.csdn.net/adjs.php?n=502871846&amp;what=zone:13&amp;charset=utf-8&amp;exclude=,&amp;referer=http%3A//www.google.com/search%3Fq%3Djavafx%26hl%3Dzh-CN%26lr%3D%26nxpt%3D20.0117770325710396876090" type=text/javascript></script>
<p>
<p>　　在JavaOne会议上，Sun负责软件业务的执行副总裁格林公布了JavaFX Script:一种用于编写能够在支持Java的PC和手机上运行的应用软件的更简单的脚本语言。</p>
<p><img alt="" src="http://images.csdn.net/20070509/490880355_2d1198a262.jpg"></p>
<p>　　<strong>JavaFX script构架图</strong></p>
<p>　　为了解决手机的兼容性问题，格林详细阐述了JavaFX Mobile:一种面向手机厂商、提高Java应用软件在不同手机间兼容性的软件包。</p>
<p>　　Sun官员还计划发布最后一部分的开放源代码的Java，并阐述与Java相关的开放源代码项目的管理规则。</p>
<p>　　Sun计划通过JavaFX Script复兴Java在小型设备和浏览器上的使用。格林说，Java不仅仅面向企业，还面向消费者。我们即将发布的脚本语言将极大地增加能够为这一平台开发内容的人的数量。</p>
<p>　　JavaFX Script是一种在生产效率和易用性方面好于Java的脚本语言，能够与Java紧密集成。开发人员可以利用JavaFX Script编写能够在支持Java的PC和手机上运行的应用软件。</p>
<p>　　Sun希望扩大编写与Java兼容的应用软件的开发人员数量，并利用对所谓富互联网应用软件日益增长的兴趣赚钱。</p>
<p>　　格林说，Sun还在反对这一想法：即它在富互联网应用软件领域已经落后。RedMonk分析师斯蒂芬说，微软、Adobe、许多小公司都在挺进这一领域。</p>
<p>　　Sun计划发布JavaFX Script的源代码，让其它公司利用它开发Web创作工具。格林表示，Sun还计划开发用于内容创作的脚本工具。</p>
<p>　　随着Web开发人员开发包括从媒体发布站点到桌面风格应用软件在内的更复杂的网络应用，富互联网应用已经成为软件开发方面最热门的领域之一。</p>
<p>　　Burton Group分析师理查德说，Java有着庞大的产品和厂商产业链，但它在前端设计方面的应用受到了兼容性和性能问题的影响。JavaFX Script可能会解决这一问题。</p>
<p>　　据Sun称，利用Java平台开发在桌面系统上运行软件的编程人员已经达到了500万。格林说，全球已经有20亿部手机预装有名为Java ME的Java软件。</p>
<p>　　理查德表示，通过JavaFX Script和JavaFX Mobile，Sun和其它Java许可客户将拥有更有吸引力的富互联网应用软件开发工具。</p>
<p>　　在过去两年中，脚本语言在主流应用开发方面越来越流行了。许多Web网站开发者和企业开发人员已经选择脚本语言作为Java或.Net的轻量级替代者。</p>
<p>　　与Ruby、PHP、Python等相比，与Java有关的脚本语言的优势是，Java编程人员能够很方便地利用既有的编程技能。</p>
<p>　　利用JavaFX Script编写的应用软件能够在Java Runtime Environment上运行。格林说，与Adobe的Apollo一样，开发人员可以利用完全相同的工具编写基于Web浏览器的应用软件或跨平台的桌面软件。</p>
<p>　　尽管安装量非常大，不同Java ME实现之间的差异引起了兼容性问题。JavaFX Mobile面向手机运营商和厂商，能够减少这些差异，提供一系列用于完成常见任务的手机应用软件。</p>
<p>　　斯蒂芬表示，推出与Java有关的脚本语言不一定会让人们放弃Ruby、Python、PHP，JavaFX Script主要对已经在使用Java的开发人员有吸引力。</p>
<p>　　新闻链接：</p>
<p>　　<a href="http://www.sun.com/software/javafx/"><font color=#3f87d7>JavaFX官方站点</font></a></p>
<p>　　<a href="http://了解javafx%20mobile/"><font color=#3f87d7>了解JavaFX mobile</font></a></p>
<p>　　<a href="http://www.sun.com/aboutsun/pr/2007-05/sunflash.20070508.2.xml"><font color=#3f87d7>Sun Radically Simplifies Content Authoring - Previews JavaFX Script</font></a></p>
</div>
</div><img src ="http://www.cnitblog.com/tilan/aggbug/27843.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/tilan/" target="_blank">Joinclass Inc</a> 2007-05-31 09:54 <a href="http://www.cnitblog.com/tilan/archive/2007/05/31/27843.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java中static、this、super、final用法(转载)</title><link>http://www.cnitblog.com/tilan/archive/2007/03/31/24991.html</link><dc:creator>Joinclass Inc</dc:creator><author>Joinclass Inc</author><pubDate>Sat, 31 Mar 2007 15:13:00 GMT</pubDate><guid>http://www.cnitblog.com/tilan/archive/2007/03/31/24991.html</guid><wfw:comment>http://www.cnitblog.com/tilan/comments/24991.html</wfw:comment><comments>http://www.cnitblog.com/tilan/archive/2007/03/31/24991.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/tilan/comments/commentRss/24991.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/tilan/services/trackbacks/24991.html</trackback:ping><description><![CDATA[<p>一、static </p>
		<p>　　请先看下面这段程序：</p>
		<p>
				<br />public class Hello{<br />public static void main(String[] args){ //(1)<br />System.out.println("Hello,world!"); //(2)<br />}<br />}</p>
		<p>
				<br />　　看过这段程序，对于大多数学过Java 的从来说，都不陌生。即使没有学过Java，而学过其它的高级语言，例如C，那你也应该能看懂这段代码的意思。它只是简单的输出“Hello,world”，一点别的用处都没有，然而，它却展示了static关键字的主要用法。 </p>
		<p>
				<br />　　在1处，我们定义了一个静态的方法名为main，这就意味着告诉Java编译器，我这个方法不需要创建一个此类的对象即可使用。你还得你是怎么运行这个程序吗？一般，我们都是在命令行下，打入如下的命令(加下划线为手动输入)：</p>
		<p>javac Hello.java<br />java Hello<br />Hello,world!</p>
		<p>　　这就是你运行的过程，第一行用来编译Hello.java这个文件，执行完后，如果你查看当前，会发现多了一个Hello.class文件，那就是第一行产生的Java二进制字节码。第二行就是执行一个Java程序的最普遍做法。执行结果如你所料。在2中，你可能会想，为什么要这样才能输出。好，我们来分解一下这条语句。（如果没有安装Java文档，请到Sun的官方网站浏览J2SE API）首先，System是位于java.lang包中的一个核心类，如果你查看它的定义，你会发现有这样一行：public static final PrintStream out;接着在进一步，点击PrintStream这个超链接，在METHOD页面，你会看到大量定义的方法，查找println，会有这样一行：</p>
		<p>public void println(String x)。</p>
		<p>　　好了，现在你应该明白为什么我们要那样调用了，out是System的一个静态变量，所以可以直接使用，而out所属的类有一个println方法。</p>
		<p>静态方法</p>
		<p>　　通常，在一个类中定义一个方法为static，那就是说，无需本类的对象即可调用此方法。如下所示：</p>
		<p>
				<br />class Simple{<br />static void go(){<br />System.out.println("Go...");<br />}<br />}<br />public class Cal{<br />public static void main(String[] args){<br />Simple.go();<br />}<br />}</p>
		<p>
				<br />　　调用一个静态方法就是“类名.方法名”,静态方法的使用很简单如上所示。一般来说，静态方法常常为应用程序中的其它类提供一些实用工具所用，在Java的类库中大量的静态方法正是出于此目的而定义的。 </p>
		<p>
				<br />静态变量</p>
		<p>　　静态变量与静态方法类似。所有此类实例共享此静态变量，也就是说在类装载时，只分配一块存储空间，所有此类的对象都可以操控此块存储空间，当然对于final则另当别论了。看下面这段代码：</p>
		<p>
				<br />class Value{<br />static int c=0;<br />static void inc(){<br />c++;<br />}<br />}<br />class Count{<br />public static void prt(String s){<br />System.out.println(s);<br />}<br />public static void main(String[] args){<br />Value v1,v2;<br />v1=new Value();<br />v2=new Value();<br />prt("v1.c="+v1.c+" v2.c="+v2.c);<br />v1.inc();<br />prt("v1.c="+v1.c+" v2.c="+v2.c); <br />}<br />}</p>
		<p>
				<br />　　结果如下： </p>
		<p>
				<br />v1.c=0 v2.c=0<br />v1.c=1 v2.c=1</p>
		<p>　　由此可以证明它们共享一块存储区。static变量有点类似于C中的全局变量的概念。值得探讨的是静态变量的初始化问题。我们修改上面的程序：</p>
		<p>
				<br />class Value{<br />static int c=0;<br />Value(){<br />c=15;<br />}<br />Value(int i){<br />c=i;<br />}<br />static void inc(){<br />c++;<br />}<br />}<br />class Count{<br />public static void prt(String s){<br />System.out.println(s);<br />}<br />Value v=new Value(10);<br />static Value v1,v2;<br />static{<br />prt("v1.c="+v1.c+" v2.c="+v2.c);<br />v1=new Value(27);<br />prt("v1.c="+v1.c+" v2.c="+v2.c);<br />v2=new Value(15);<br />prt("v1.c="+v1.c+" v2.c="+v2.c);<br />}<br />public static void main(String[] args){<br />Count ct=new Count();<br />prt("ct.c="+ct.v.c);<br />prt("v1.c="+v1.c+" v2.c="+v2.c);<br />v1.inc();<br />prt("v1.c="+v1.c+" v2.c="+v2.c);<br />prt("ct.c="+ct.v.c);<br />}<br />}</p>
		<p>
				<br />运行结果如下： </p>
		<p>
				<br />v1.c=0 v2.c=0<br />v1.c=27 v2.c=27<br />v1.c=15 v2.c=15<br />ct.c=10<br />v1.c=10 v2.c=10<br />v1.c=11 v2.c=11<br />ct.c=11</p>
		<p>　　这个程序展示了静态初始化的各种特性。如果你初次接触Java，结果可能令你吃惊。可能会对static后加大括号感到困惑。首先要告诉你的是，static定义的变量会优先于任何其它非static变量，不论其出现的顺序如何。正如在程序中所表现的，虽然v出现在v1和v2的前面，但是结果却是v1和v2的初始化在v的前面。在static{后面跟着一段代码，这是用来进行显式的静态变量初始化，这段代码只会初始化一次，且在类被第一次装载时。如果你能读懂并理解这段代码，会帮助你对static关键字的认识。在涉及到继承的时候，会先初始化父类的static变量，然后是子类的，依次类推。非静态变量不是本文的主题，在此不做详细讨论，请参考Think in Java中的讲解。</p>
		<p>静态类</p>
		<p>　　通常一个普通类不允许声明为静态的，只有一个内部类才可以。这时这个声明为静态的内部类可以直接作为一个普通类来使用，而不需实例一个外部类。如下代码所示：</p>
		<p>
				<br />public class StaticCls{<br />public static void main(String[] args){<br />OuterCls.InnerCls oi=new OuterCls.InnerCls();<br />}<br />}<br />class OuterCls{<br />public static class InnerCls{<br />InnerCls(){<br />System.out.println("InnerCls");<br />}<br />}<br />}</p>
		<p>
				<br />　　输出结果会如你所料： </p>
		<p>
				<br />InnerCls</p>
		<p>　　和普通类一样。内部类的其它用法请参阅Think in Java中的相关章节，此处不作详解。</p>
		<p>二、this &amp; super</p>
		<p>　　在上一篇拙作中，我们讨论了static的种种用法，通过用static来定义方法或成员，为我们编程提供了某种便利，从某种程度上可以说它类似于C语言中的全局函数和全局变量。但是，并不是说有了这种便利，你便可以随处使用，如果那样的话，你便需要认真考虑一下自己是否在用面向对象的思想编程，自己的程序是否是面向对象的。好了，现在开始讨论this&amp;super这两个关键字的意义和用法。</p>
		<p>　　在Java中，this通常指当前对象，super则指父类的。当你想要引用当前对象的某种东西，比如当前对象的某个方法，或当前对象的某个成员，你便可以利用this来实现这个目的，当然，this的另一个用途是调用当前对象的另一个构造函数，这些马上就要讨论。如果你想引用父类的某种东西，则非super莫属。由于this与super有如此相似的一些特性和与生俱来的某种关系，所以我们在这一块儿来讨论，希望能帮助你区分和掌握它们两个。</p>
		<p>在一般方法中</p>
		<p>　　最普遍的情况就是，在你的方法中的某个形参名与当前对象的某个成员有相同的名字，这时为了不至于混淆，你便需要明确使用this关键字来指明你要使用某个成员，使用方法是“this.成员名”，而不带this的那个便是形参。另外，还可以用“this.方法名”来引用当前对象的某个方法，但这时this就不是必须的了，你可以直接用方法名来访问那个方法，编译器会知道你要调用的是那一个。下面的代码演示了上面的用法：</p>
		<p>
				<br />public class DemoThis{<br />private String name;<br />private int age;<br />DemoThis(String name,int age){<br />setName(name); //你可以加上this来调用方法，像这样：this.setName(name);但这并不是必须的<br />setAge(age);<br />this.print();<br />} <br />public void setName(String name){<br />this.name=name;//此处必须指明你要引用成员变量<br />}<br />public void setAge(int age){<br />this.age=age;<br />}<br />public void print(){<br />System.out.println("Name="+name+" Age="+age);//在此行中并不需要用this，因为没有会导致混淆的东西<br />}<br />public static void main(String[] args){<br />DemoThis dt=new DemoThis("Kevin","22");<br />}<br />}</p>
		<p>
				<br />　　这段代码很简单，不用解释你也应该能看明白。在构造函数中你看到用this.print(),你完全可以用print()来代替它，两者效果一样。下面我们修改这个程序，来演示super的用法。</p>
		<p>class Person{<br />public int c;<br />private String name;<br />private int age;<br />protected void setName(String name){<br />this.name=name;<br />}<br />protected void setAge(int age){<br />this.age=age;<br />}<br />protected void print(){<br />System.out.println("Name="+name+" Age="+age);<br />}<br />}<br />public class DemoSuper extends Person{<br />public void print(){<br />System.out.println("DemoSuper:");<br />super.print();<br />}<br />public static void main(String[] args){<br />DemoSuper ds=new DemoSuper();<br />ds.setName("kevin");<br />ds.setAge(22);<br />ds.print();<br />}<br />}</p>
		<p>
				<br />　　在DemoSuper中，重新定义的print方法覆写了父类的print方法，它首先做一些自己的事情，然后调用父类的那个被覆写了的方法。输出结果说明了这一点： </p>
		<p>
				<br />DemoSuper:<br />Name=kevin Age=22</p>
		<p>　　这样的使用方法是比较常用的。另外如果父类的成员可以被子类访问，那你可以像使用this一样使用它，用“super.父类中的成员名”的方式，但常常你并不是这样来访问父类中的成员名的。</p>
		<p>在构造函数中</p>
		<p>　　构造函数是一种特殊的方法，在对象初始化的时候自动调用。在构造函数中，this和super也有上面说的种种使用方式，并且它还有特殊的地方，请看下面的例子：</p>
		<p>
				<br />class Person{<br />public static void prt(String s){<br />System.out.println(s);<br />}<br />Person(){<br />prt("A Person.");<br />}<br />Person(String name){<br />prt("A person name is:"+name);<br />}<br />}<br />public class Chinese extends Person{<br />Chinese(){<br />super(); //调用父类构造函数（1）<br />prt("A chinese.");//(4)<br />}<br />Chinese(String name){<br />super(name);//调用父类具有相同形参的构造函数（2）<br />prt("his name is:"+name);<br />}<br />Chinese(String name,int age){<br />this(name);//调用当前具有相同形参的构造函数（3）<br />prt("his age is:"+age);<br />}<br />public static void main(String[] args){<br />Chinese cn=new Chinese();<br />cn=new Chinese("kevin");<br />cn=new Chinese("kevin",22);<br />}<br />}</p>
		<p>
				<br />　　在这段程序中，this和super不再是像以前那样用“.”连接一个方法或成员，而是直接在其后跟上适当的参数，因此它的意义也就有了变化。super后加参数的是用来调用父类中具有相同形式的构造函数，如1和2处。this后加参数则调用的是当前具有相同参数的构造函数，如3处。当然，在Chinese的各个重载构造函数中，this和super在一般方法中的各种用法也仍可使用，比如4处，你可以将它替换为“this.prt”(因为它继承了父类中的那个方法）或者是“super.prt”（因为它是父类中的方法且可被子类访问），它照样可以正确运行。但这样似乎就有点画蛇添足的味道了。 </p>
		<p>
				<br />　　最后，写了这么多，如果你能对“this通常指代当前对象，super通常指代父类”这句话牢记在心，那么本篇便达到了目的，其它的你自会在以后的编程实践当中慢慢体会、掌握。另外关于本篇中提到的继承，请参阅相关Java教程。</p>
		<p>三、final</p>
		<p>　　final在Java中并不常用，然而它却为我们提供了诸如在C语言中定义常量的功能，不仅如此，final还可以让你控制你的成员、方法或者是一个类是否可被覆写或继承等功能，这些特点使final在Java中拥有了一个不可或缺的地位，也是学习Java时必须要知道和掌握的关键字之一。</p>
		<p>final成员</p>
		<p>　　当你在类中定义变量时，在其前面加上final关键字，那便是说，这个变量一旦被初始化便不可改变，这里不可改变的意思对基本类型来说是其值不可变，而对于对象变量来说其引用不可再变。其初始化可以在两个地方，一是其定义处，也就是说在final变量定义时直接给其赋值，二是在构造函数中。这两个地方只能选其一，要么在定义时给值，要么在构造函数中给值，不能同时既在定义时给了值，又在构造函数中给另外的值。下面这段代码演示了这一点：</p>
		<p>
				<br />import java.util.List;<br />import java.util.ArrayList;<br />import java.util.LinkedList;<br />public class Bat{<br />final PI=3.14; //在定义时便给址值<br />final int i; //因为要在构造函数中进行初始化，所以此处便不可再给值<br />final List list; //此变量也与上面的一样<br />Bat(){<br />i=100;<br />list=new LinkedList();<br />}<br />Bat(int ii,List l){<br />i=ii;<br />list=l;<br />}<br />public static void main(String[] args){<br />Bat b=new Bat();<br />b.list.add(new Bat());<br />//b.i=25;<br />//b.list=new ArrayList();<br />System.out.println("I="+b.i+" List Type:"+b.list.getClass());<br />b=new Bat(23,new ArrayList());<br />b.list.add(new Bat());<br />System.out.println("I="+b.i+" List Type:"+b.list.getClass());<br />}<br />}</p>
		<p>
				<br />　　此程序很简单的演示了final的常规用法。在这里使用在构造函数中进行初始化的方法，这使你有了一点灵活性。如Bat的两个重载构造函数所示，第一个缺省构造函数会为你提供默认的值，重载的那个构造函数会根据你所提供的值或类型为final变量初始化。然而有时你并不需要这种灵活性，你只需要在定义时便给定其值并永不变化，这时就不要再用这种方法。在main方法中有两行语句注释掉了，如果你去掉注释，程序便无法通过编译，这便是说，不论是i的值或是list的类型，一旦初始化，确实无法再更改。然而b可以通过重新初始化来指定i的值或list的类型，输出结果中显示了这一点： </p>
		<p>
				<br />I=100 List Type:class java.util.LinkedList<br />I=23 List Type:class java.util.ArrayList</p>
		<p>　　还有一种用法是定义方法中的参数为final，对于基本类型的变量，这样做并没有什么实际意义，因为基本类型的变量在调用方法时是传值的，也就是说你可以在方法中更改这个参数变量而不会影响到调用语句，然而对于对象变量，却显得很实用，因为对象变量在传递时是传递其引用，这样你在方法中对对象变量的修改也会影响到调用语句中的对象变量，当你在方法中不需要改变作为参数的对象变量时，明确使用final进行声明，会防止你无意的修改而影响到调用方法。<br />另外方法中的内部类在用到方法中的参变量时，此参变也必须声明为final才可使用，如下代码所示：</p>
		<p>
				<br />public class INClass{<br />void innerClass(final String str){<br />class IClass{<br />IClass(){<br />System.out.println(str);<br />}<br />}<br />IClass ic=new IClass();<br />}<br />public static void main(String[] args){<br />INClass inc=new INClass();<br />inc.innerClass("Hello");<br />}<br />}</p>
		<p>
				<br />final方法 </p>
		<p>
				<br />　　将方法声明为final，那就说明你已经知道这个方法提供的功能已经满足你要求，不需要进行扩展，并且也不允许任何从此类继承的类来覆写这个方法，但是继承仍然可以继承这个方法，也就是说可以直接使用。另外有一种被称为inline的机制，它会使你在调用final方法时，直接将方法主体插入到调用处，而不是进行例行的方法调用，例如保存断点，压栈等，这样可能会使你的程序效率有所提高，然而当你的方法主体非常庞大时，或你在多处调用此方法，那么你的调用主体代码便会迅速膨胀，可能反而会影响效率，所以你要慎用final进行方法定义。</p>
		<p>final类</p>
		<p>　　当你将final用于类身上时，你就需要仔细考虑，因为一个final类是无法被任何人继承的，那也就意味着此类在一个继承树中是一个叶子类，并且此类的设计已被认为很完美而不需要进行修改或扩展。对于final类中的成员，你可以定义其为final，也可以不是final。而对于方法，由于所属类为final的关系，自然也就成了final型的。你也可以明确的给final类中的方法加上一个final，但这显然没有意义。</p>
		<p>　　下面的程序演示了final方法和final类的用法：</p>
		<p>
				<br />final class final{<br />final String str="final Data";<br />public String str1="non final data";<br />final public void print(){<br />System.out.println("final method.");<br />}<br />public void what(){<br />System.out.println(str+"<br />"+str1);<br />}<br />}<br />public class FinalDemo { //extends final 无法继承 <br />public static void main(String[] args){<br />final f=new final();<br />f.what();<br />f.print();<br />}<br />}</p>
		<p>
				<br />　　从程序中可以看出，final类与普通类的使用几乎没有差别，只是它失去了被继承的特性。final方法与非final方法的区别也很难从程序行看出，只是记住慎用。 </p>
		<p>
				<br />final在设计模式中的应用</p>
		<p>　　在设计模式中有一种模式叫做不变模式，在Java中通过final关键字可以很容易的实现这个模式，在讲解final成员时用到的程序Bat.java就是一个不变模式的例子。如果你对此感兴趣，可以参考阎宏博士编写的《Java与模式》一书中的讲解。</p>
		<p>　　到此为止，this,static,supert和final的使用已经说完了，如果你对这四个关键字已经能够大致说出它们的区别与用法，那便说明你基本已经掌握。然而，世界上的任何东西都不是完美无缺的，Java提供这四个关键字，给程序员的编程带来了很大的便利，但并不是说要让你到处使用，一旦达到滥用的程序，便适得其反，所以在使用时请一定要认真考虑。</p>
		<p>
				<br />　　请先看下面这段程序：</p>
		<p>
				<br />public class Hello{<br />public static void main(String[] args){ //(1)<br />System.out.println("Hello,world!"); //(2)<br />}<br />}</p>
		<p>
				<br />　　看过这段程序，对于大多数学过Java 的从来说，都不陌生。即使没有学过Java，而学过其它的高级语言，例如C，那你也应该能看懂这段代码的意思。它只是简单的输出“Hello,world”，一点别的用处都没有，然而，它却展示了static关键字的主要用法。 </p>
		<p>
				<br />　　在1处，我们定义了一个静态的方法名为main，这就意味着告诉Java编译器，我这个方法不需要创建一个此类的对象即可使用。你还得你是怎么运行这个程序吗？一般，我们都是在命令行下，打入如下的命令(加下划线为手动输入)：</p>
		<p>javac Hello.java<br />java Hello<br />Hello,world!</p>
		<p>　　这就是你运行的过程，第一行用来编译Hello.java这个文件，执行完后，如果你查看当前，会发现多了一个Hello.class文件，那就是第一行产生的Java二进制字节码。第二行就是执行一个Java程序的最普遍做法。执行结果如你所料。在2中，你可能会想，为什么要这样才能输出。好，我们来分解一下这条语句。（如果没有安装Java文档，请到Sun的官方网站浏览J2SE API）首先，System是位于java.lang包中的一个核心类，如果你查看它的定义，你会发现有这样一行：public static final PrintStream out;接着在进一步，点击PrintStream这个超链接，在METHOD页面，你会看到大量定义的方法，查找println，会有这样一行：</p>
		<p>public void println(String x)。</p>
		<p>　　好了，现在你应该明白为什么我们要那样调用了，out是System的一个静态变量，所以可以直接使用，而out所属的类有一个println方法。</p>
		<p>静态方法</p>
		<p>　　通常，在一个类中定义一个方法为static，那就是说，无需本类的对象即可调用此方法。如下所示：</p>
		<p>
				<br />class Simple{<br />static void go(){<br />System.out.println("Go...");<br />}<br />}<br />public class Cal{<br />public static void main(String[] args){<br />Simple.go();<br />}<br />}</p>
		<p>
				<br />　　调用一个静态方法就是“类名.方法名”,静态方法的使用很简单如上所示。一般来说，静态方法常常为应用程序中的其它类提供一些实用工具所用，在Java的类库中大量的静态方法正是出于此目的而定义的。 </p>
		<p>
				<br />静态变量</p>
		<p>　　静态变量与静态方法类似。所有此类实例共享此静态变量，也就是说在类装载时，只分配一块存储空间，所有此类的对象都可以操控此块存储空间，当然对于final则另当别论了。看下面这段代码：</p>
		<p>
				<br />class Value{<br />static int c=0;<br />static void inc(){<br />c++;<br />}<br />}<br />class Count{<br />public static void prt(String s){<br />System.out.println(s);<br />}<br />public static void main(String[] args){<br />Value v1,v2;<br />v1=new Value();<br />v2=new Value();<br />prt("v1.c="+v1.c+" v2.c="+v2.c);<br />v1.inc();<br />prt("v1.c="+v1.c+" v2.c="+v2.c); <br />}<br />}</p>
		<p>
				<br />　　结果如下： </p>
		<p>
				<br />v1.c=0 v2.c=0<br />v1.c=1 v2.c=1</p>
		<p>　　由此可以证明它们共享一块存储区。static变量有点类似于C中的全局变量的概念。值得探讨的是静态变量的初始化问题。我们修改上面的程序：</p>
		<p>
				<br />class Value{<br />static int c=0;<br />Value(){<br />c=15;<br />}<br />Value(int i){<br />c=i;<br />}<br />static void inc(){<br />c++;<br />}<br />}<br />class Count{<br />public static void prt(String s){<br />System.out.println(s);<br />}<br />Value v=new Value(10);<br />static Value v1,v2;<br />static{<br />prt("v1.c="+v1.c+" v2.c="+v2.c);<br />v1=new Value(27);<br />prt("v1.c="+v1.c+" v2.c="+v2.c);<br />v2=new Value(15);<br />prt("v1.c="+v1.c+" v2.c="+v2.c);<br />}<br />public static void main(String[] args){<br />Count ct=new Count();<br />prt("ct.c="+ct.v.c);<br />prt("v1.c="+v1.c+" v2.c="+v2.c);<br />v1.inc();<br />prt("v1.c="+v1.c+" v2.c="+v2.c);<br />prt("ct.c="+ct.v.c);<br />}<br />}</p>
		<p>
				<br />运行结果如下： </p>
		<p>
				<br />v1.c=0 v2.c=0<br />v1.c=27 v2.c=27<br />v1.c=15 v2.c=15<br />ct.c=10<br />v1.c=10 v2.c=10<br />v1.c=11 v2.c=11<br />ct.c=11</p>
		<p>　　这个程序展示了静态初始化的各种特性。如果你初次接触Java，结果可能令你吃惊。可能会对static后加大括号感到困惑。首先要告诉你的是，static定义的变量会优先于任何其它非static变量，不论其出现的顺序如何。正如在程序中所表现的，虽然v出现在v1和v2的前面，但是结果却是v1和v2的初始化在v的前面。在static{后面跟着一段代码，这是用来进行显式的静态变量初始化，这段代码只会初始化一次，且在类被第一次装载时。如果你能读懂并理解这段代码，会帮助你对static关键字的认识。在涉及到继承的时候，会先初始化父类的static变量，然后是子类的，依次类推。非静态变量不是本文的主题，在此不做详细讨论，请参考Think in Java中的讲解。</p>
		<p>静态类</p>
		<p>　　通常一个普通类不允许声明为静态的，只有一个内部类才可以。这时这个声明为静态的内部类可以直接作为一个普通类来使用，而不需实例一个外部类。如下代码所示：</p>
		<p>
				<br />public class StaticCls{<br />public static void main(String[] args){<br />OuterCls.InnerCls oi=new OuterCls.InnerCls();<br />}<br />}<br />class OuterCls{<br />public static class InnerCls{<br />InnerCls(){<br />System.out.println("InnerCls");<br />}<br />}<br />}</p>
		<p>
				<br />　　输出结果会如你所料： </p>
		<p>
				<br />InnerCls</p>
		<p>　　和普通类一样。内部类的其它用法请参阅Think in Java中的相关章节，此处不作详解。</p>
		<p>二、this &amp; super</p>
		<p>　　在上一篇拙作中，我们讨论了static的种种用法，通过用static来定义方法或成员，为我们编程提供了某种便利，从某种程度上可以说它类似于C语言中的全局函数和全局变量。但是，并不是说有了这种便利，你便可以随处使用，如果那样的话，你便需要认真考虑一下自己是否在用面向对象的思想编程，自己的程序是否是面向对象的。好了，现在开始讨论this&amp;super这两个关键字的意义和用法。</p>
		<p>　　在Java中，this通常指当前对象，super则指父类的。当你想要引用当前对象的某种东西，比如当前对象的某个方法，或当前对象的某个成员，你便可以利用this来实现这个目的，当然，this的另一个用途是调用当前对象的另一个构造函数，这些马上就要讨论。如果你想引用父类的某种东西，则非super莫属。由于this与super有如此相似的一些特性和与生俱来的某种关系，所以我们在这一块儿来讨论，希望能帮助你区分和掌握它们两个。</p>
		<p>在一般方法中</p>
		<p>　　最普遍的情况就是，在你的方法中的某个形参名与当前对象的某个成员有相同的名字，这时为了不至于混淆，你便需要明确使用this关键字来指明你要使用某个成员，使用方法是“this.成员名”，而不带this的那个便是形参。另外，还可以用“this.方法名”来引用当前对象的某个方法，但这时this就不是必须的了，你可以直接用方法名来访问那个方法，编译器会知道你要调用的是那一个。下面的代码演示了上面的用法：</p>
		<p>
				<br />public class DemoThis{<br />private String name;<br />private int age;<br />DemoThis(String name,int age){<br />setName(name); //你可以加上this来调用方法，像这样：this.setName(name);但这并不是必须的<br />setAge(age);<br />this.print();<br />} <br />public void setName(String name){<br />this.name=name;//此处必须指明你要引用成员变量<br />}<br />public void setAge(int age){<br />this.age=age;<br />}<br />public void print(){<br />System.out.println("Name="+name+" Age="+age);//在此行中并不需要用this，因为没有会导致混淆的东西<br />}<br />public static void main(String[] args){<br />DemoThis dt=new DemoThis("Kevin","22");<br />}<br />}</p>
		<p>
				<br />　　这段代码很简单，不用解释你也应该能看明白。在构造函数中你看到用this.print(),你完全可以用print()来代替它，两者效果一样。下面我们修改这个程序，来演示super的用法。</p>
		<p>class Person{<br />public int c;<br />private String name;<br />private int age;<br />protected void setName(String name){<br />this.name=name;<br />}<br />protected void setAge(int age){<br />this.age=age;<br />}<br />protected void print(){<br />System.out.println("Name="+name+" Age="+age);<br />}<br />}<br />public class DemoSuper extends Person{<br />public void print(){<br />System.out.println("DemoSuper:");<br />super.print();<br />}<br />public static void main(String[] args){<br />DemoSuper ds=new DemoSuper();<br />ds.setName("kevin");<br />ds.setAge(22);<br />ds.print();<br />}<br />}</p>
		<p>
				<br />　　在DemoSuper中，重新定义的print方法覆写了父类的print方法，它首先做一些自己的事情，然后调用父类的那个被覆写了的方法。输出结果说明了这一点： </p>
		<p>
				<br />DemoSuper:<br />Name=kevin Age=22</p>
		<p>　　这样的使用方法是比较常用的。另外如果父类的成员可以被子类访问，那你可以像使用this一样使用它，用“super.父类中的成员名”的方式，但常常你并不是这样来访问父类中的成员名的。</p>
		<p>在构造函数中</p>
		<p>　　构造函数是一种特殊的方法，在对象初始化的时候自动调用。在构造函数中，this和super也有上面说的种种使用方式，并且它还有特殊的地方，请看下面的例子：</p>
		<p>
				<br />class Person{<br />public static void prt(String s){<br />System.out.println(s);<br />}<br />Person(){<br />prt("A Person.");<br />}<br />Person(String name){<br />prt("A person name is:"+name);<br />}<br />}<br />public class Chinese extends Person{<br />Chinese(){<br />super(); //调用父类构造函数（1）<br />prt("A chinese.");//(4)<br />}<br />Chinese(String name){<br />super(name);//调用父类具有相同形参的构造函数（2）<br />prt("his name is:"+name);<br />}<br />Chinese(String name,int age){<br />this(name);//调用当前具有相同形参的构造函数（3）<br />prt("his age is:"+age);<br />}<br />public static void main(String[] args){<br />Chinese cn=new Chinese();<br />cn=new Chinese("kevin");<br />cn=new Chinese("kevin",22);<br />}<br />}</p>
		<p>
				<br />　　在这段程序中，this和super不再是像以前那样用“.”连接一个方法或成员，而是直接在其后跟上适当的参数，因此它的意义也就有了变化。super后加参数的是用来调用父类中具有相同形式的构造函数，如1和2处。this后加参数则调用的是当前具有相同参数的构造函数，如3处。当然，在Chinese的各个重载构造函数中，this和super在一般方法中的各种用法也仍可使用，比如4处，你可以将它替换为“this.prt”(因为它继承了父类中的那个方法）或者是“super.prt”（因为它是父类中的方法且可被子类访问），它照样可以正确运行。但这样似乎就有点画蛇添足的味道了。 </p>
		<p>
				<br />　　最后，写了这么多，如果你能对“this通常指代当前对象，super通常指代父类”这句话牢记在心，那么本篇便达到了目的，其它的你自会在以后的编程实践当中慢慢体会、掌握。另外关于本篇中提到的继承，请参阅相关Java教程。</p>
		<p>三、final</p>
		<p>　　final在Java中并不常用，然而它却为我们提供了诸如在C语言中定义常量的功能，不仅如此，final还可以让你控制你的成员、方法或者是一个类是否可被覆写或继承等功能，这些特点使final在Java中拥有了一个不可或缺的地位，也是学习Java时必须要知道和掌握的关键字之一。</p>
		<p>final成员</p>
		<p>　　当你在类中定义变量时，在其前面加上final关键字，那便是说，这个变量一旦被初始化便不可改变，这里不可改变的意思对基本类型来说是其值不可变，而对于对象变量来说其引用不可再变。其初始化可以在两个地方，一是其定义处，也就是说在final变量定义时直接给其赋值，二是在构造函数中。这两个地方只能选其一，要么在定义时给值，要么在构造函数中给值，不能同时既在定义时给了值，又在构造函数中给另外的值。下面这段代码演示了这一点：</p>
		<p>
				<br />import java.util.List;<br />import java.util.ArrayList;<br />import java.util.LinkedList;<br />public class Bat{<br />final PI=3.14; //在定义时便给址值<br />final int i; //因为要在构造函数中进行初始化，所以此处便不可再给值<br />final List list; //此变量也与上面的一样<br />Bat(){<br />i=100;<br />list=new LinkedList();<br />}<br />Bat(int ii,List l){<br />i=ii;<br />list=l;<br />}<br />public static void main(String[] args){<br />Bat b=new Bat();<br />b.list.add(new Bat());<br />//b.i=25;<br />//b.list=new ArrayList();<br />System.out.println("I="+b.i+" List Type:"+b.list.getClass());<br />b=new Bat(23,new ArrayList());<br />b.list.add(new Bat());<br />System.out.println("I="+b.i+" List Type:"+b.list.getClass());<br />}<br />}</p>
		<p>
				<br />　　此程序很简单的演示了final的常规用法。在这里使用在构造函数中进行初始化的方法，这使你有了一点灵活性。如Bat的两个重载构造函数所示，第一个缺省构造函数会为你提供默认的值，重载的那个构造函数会根据你所提供的值或类型为final变量初始化。然而有时你并不需要这种灵活性，你只需要在定义时便给定其值并永不变化，这时就不要再用这种方法。在main方法中有两行语句注释掉了，如果你去掉注释，程序便无法通过编译，这便是说，不论是i的值或是list的类型，一旦初始化，确实无法再更改。然而b可以通过重新初始化来指定i的值或list的类型，输出结果中显示了这一点： </p>
		<p>
				<br />I=100 List Type:class java.util.LinkedList<br />I=23 List Type:class java.util.ArrayList</p>
		<p>　　还有一种用法是定义方法中的参数为final，对于基本类型的变量，这样做并没有什么实际意义，因为基本类型的变量在调用方法时是传值的，也就是说你可以在方法中更改这个参数变量而不会影响到调用语句，然而对于对象变量，却显得很实用，因为对象变量在传递时是传递其引用，这样你在方法中对对象变量的修改也会影响到调用语句中的对象变量，当你在方法中不需要改变作为参数的对象变量时，明确使用final进行声明，会防止你无意的修改而影响到调用方法。<br />另外方法中的内部类在用到方法中的参变量时，此参变也必须声明为final才可使用，如下代码所示：</p>
		<p>
				<br />public class INClass{<br />void innerClass(final String str){<br />class IClass{<br />IClass(){<br />System.out.println(str);<br />}<br />}<br />IClass ic=new IClass();<br />}<br />public static void main(String[] args){<br />INClass inc=new INClass();<br />inc.innerClass("Hello");<br />}<br />}</p>
		<p>
				<br />final方法 </p>
		<p>
				<br />　　将方法声明为final，那就说明你已经知道这个方法提供的功能已经满足你要求，不需要进行扩展，并且也不允许任何从此类继承的类来覆写这个方法，但是继承仍然可以继承这个方法，也就是说可以直接使用。另外有一种被称为inline的机制，它会使你在调用final方法时，直接将方法主体插入到调用处，而不是进行例行的方法调用，例如保存断点，压栈等，这样可能会使你的程序效率有所提高，然而当你的方法主体非常庞大时，或你在多处调用此方法，那么你的调用主体代码便会迅速膨胀，可能反而会影响效率，所以你要慎用final进行方法定义。</p>
		<p>final类</p>
		<p>　　当你将final用于类身上时，你就需要仔细考虑，因为一个final类是无法被任何人继承的，那也就意味着此类在一个继承树中是一个叶子类，并且此类的设计已被认为很完美而不需要进行修改或扩展。对于final类中的成员，你可以定义其为final，也可以不是final。而对于方法，由于所属类为final的关系，自然也就成了final型的。你也可以明确的给final类中的方法加上一个final，但这显然没有意义。</p>
		<p>　　下面的程序演示了final方法和final类的用法：</p>
		<p>
				<br />final class final{<br />final String str="final Data";<br />public String str1="non final data";<br />final public void print(){<br />System.out.println("final method.");<br />}<br />public void what(){<br />System.out.println(str+"<br />"+str1);<br />}<br />}<br />public class FinalDemo { //extends final 无法继承 <br />public static void main(String[] args){<br />final f=new final();<br />f.what();<br />f.print();<br />}<br />}</p>
		<p>
				<br />　　从程序中可以看出，final类与普通类的使用几乎没有差别，只是它失去了被继承的特性。final方法与非final方法的区别也很难从程序行看出，只是记住慎用。 </p>
		<p>
				<br />final在设计模式中的应用</p>
		<p>　　在设计模式中有一种模式叫做不变模式，在Java中通过final关键字可以很容易的实现这个模式，在讲解final成员时用到的程序Bat.java就是一个不变模式的例子。如果你对此感兴趣，可以参考阎宏博士编写的《Java与模式》一书中的讲解。</p>
		<p>　　到此为止，this,static,supert和final的使用已经说完了，如果你对这四个关键字已经能够大致说出它们的区别与用法，那便说明你基本已经掌握。然而，世界上的任何东西都不是完美无缺的，Java提供这四个关键字，给程序员的编程带来了很大的便利，但并不是说要让你到处使用，一旦达到滥用的程序，便适得其反，所以在使用时请一定要认真考虑。</p>
		<p> </p>
		<script type="text/javascript">
				<!--
google_ad_client = "pub-3874079075380071";
google_ad_width = 728;
google_ad_height = 90;
google_ad_format = "728x90_as";
google_ad_type = "image";
google_ad_channel = "";
//-->
		</script>
		<script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
		</script><img src ="http://www.cnitblog.com/tilan/aggbug/24991.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/tilan/" target="_blank">Joinclass Inc</a> 2007-03-31 23:13 <a href="http://www.cnitblog.com/tilan/archive/2007/03/31/24991.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java学习的30个目标</title><link>http://www.cnitblog.com/tilan/archive/2007/03/31/24990.html</link><dc:creator>Joinclass Inc</dc:creator><author>Joinclass Inc</author><pubDate>Sat, 31 Mar 2007 15:08:00 GMT</pubDate><guid>http://www.cnitblog.com/tilan/archive/2007/03/31/24990.html</guid><wfw:comment>http://www.cnitblog.com/tilan/comments/24990.html</wfw:comment><comments>http://www.cnitblog.com/tilan/archive/2007/03/31/24990.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/tilan/comments/commentRss/24990.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/tilan/services/trackbacks/24990.html</trackback:ping><description><![CDATA[本文将告诉你学习Java需要达到的30个目标，希望能够对你的学习有所帮助。对比一下自己，你已经掌握了这30条中的多少条了呢？ <br />　　1.你需要精通面向对象分析与设计(OOA/OOD)、涉及模式(GOF，J2EEDP)以及综合模式。你应该十分了解UML，尤其是class，object，interaction以及statediagrams。<br />　　2.你需要学习JAVA语言的基础知识以及它的核心类库(collections，serialization，streams，networking， multithreading，reflection，event，handling，NIO，localization，以及其他)。<br />　　3.你应该了解JVM，classloaders，classreflect，以及垃圾回收的基本工作机制等。你应该有能力反编译一个类文件并且明白一些基本的汇编指令。<br />　　4.如果你将要写客户端程序，你需要学习WEB的小应用程序(applet)，必需掌握GUI设计的思想和方法，以及桌面程序的SWING，AWT， SWT。你还应该对UI部件的JAVABEAN组件模式有所了解。JAVABEANS也被应用在JSP中以把业务逻辑从表现层中分离出来。<br />　　5.你需要学习java数据库技术，如JDBCAPI并且会使用至少一种persistence/ORM构架，例如Hibernate，JDO， CocoBase，TopLink，InsideLiberator(国产JDO红工厂软件)或者iBatis。<br />　　6.你还应该了解对象关系的阻抗失配的含义，以及它是如何影响业务对象的与关系型数据库的交互，和它的运行结果，还需要掌握不同的数据库产品运用，比如:oracle，mysql，mssqlserver。<br />　　7.你需要学习JAVA的沙盒安全模式(classloaders，bytecodeverification，managers，policyandpermissions，<br />codesigning， digitalsignatures，cryptography，certification，Kerberos，以及其他)还有不同的安全/认证 API，例如JAAS(JavaAuthenticationandAuthorizationService)，JCE (JavaCryptographyExtension)，JSSE(JavaSecureSocketExtension)，以及JGSS (JavaGeneralSecurityService)。<br />　　8.你需要学习Servlets，JSP，以及JSTL(StandardTagLibraries)和可以选择的第三方TagLibraries。<br />　　9.你需要熟悉主流的网页框架，例如JSF，Struts，Tapestry，Cocoon，WebWork，以及他们下面的涉及模式，如MVC/MODEL2。<br />　　10.你需要学习如何使用及管理WEB服务器，例如tomcat，resin，Jrun，并且知道如何在其基础上扩展和维护WEB程序。<br />11.你需要学习分布式对象以及远程API，例如RMI和RMI/IIOP。<br />　　12.你需要掌握各种流行中间件技术标准和与java结合实现，比如Tuxedo、CROBA，当然也包括javaEE本身。<br />　　13.你需要学习最少一种的XMLAPI，例如JAXP(JavaAPIforXMLProcessing)，JDOM(JavaforXMLDocumentObjectModel)，DOM4J，或JAXR(JavaAPIforXMLRegistries)。<br />　　14.你应该学习如何利用JAVAAPI和工具来构建WebService。例如JAX-RPC(JavaAPIforXML/RPC)，SAAJ (SOAPwithAttachmentsAPIforJava)，JAXB(JavaArchitectureforXMLBinding)，JAXM(JavaAPIforXMLMessaging)， JAXR(JavaAPIforXMLRegistries)，或者JWSDP(JavaWebServicesDeveloperPack)。<br />　　15.你需要学习一门轻量级应用程序框架，例如Spring，PicoContainer，Avalon，以及它们的IoC/DI风格(setter，constructor，interfaceinjection)。<br />　　16.你需要熟悉不同的J2EE技术，例如JNDI(JavaNamingandDirectoryInterface)，JMS (JavaMessageService)，JTA/JTS(JavaTransactionAPI/JavaTransactionService)，JMX (JavaManagementeXtensions)，以及JavaMail。<br />　　17.你需要学习企业级JavaBeans(EJB)以及它们的不同组件模式：Stateless/StatefulSessionBeans，EntityBeans(包含Bean- ManagedPersistence[BMP]或者Container-ManagedPersistence[CMP]和它的EJB-QL)，或者 Message-DrivenBeans(MDB)。<br />　　18.你需要学习如何管理与配置一个J2EE应用程序服务器，如WebLogic，JBoss等，并且利用它的附加服务，例如簇类，连接池以及分布式处理支援。你还需要了解如何在它上面封装和配置应用程序并且能够监控、调整它的性能。<br />　　19.你需要熟悉面向方面的程序设计以及面向属性的程序设计(这两个都被很容易混淆的缩写为AOP)，以及他们的主流JAVA规格和执行。例如AspectJ和AspectWerkz。<br />　　20.你需要熟悉对不同有用的API和frame work等来为你服务。例如Log4J(logging/tracing)，Quartz (scheduling)，JGroups(networkgroupcommunication)，JCache(distributedcaching)， Lucene(full-textsearch)，JakartaCommons等等。<br />21.如果你将要对接或者正和旧的系统或者本地平台，你需要学习JNI (JavaNativeInterface) and JCA (JavaConnectorArchitecture)。<br />　　22.你需要熟悉JINI技术以及与它相关的分布式系统，比如掌握CROBA。<br />　　23.你需要JavaCommunityProcess(JCP)以及他的不同JavaSpecificationRequests(JSRs)，例如Portlets(168)，JOLAP(69)，DataMiningAPI(73)，等等。<br />　　24.你应该熟练掌握一种JAVAIDE例如sunOne，netBeans，IntelliJIDEA或者Eclipse。(有些人更喜欢VI或EMACS来编写文件。随便你用什么了：)<br />　　25.JAVA(精确的说是有些配置)是冗长的，它需要很多的人工代码(例如EJB)，所以你需要熟悉代码生成工具，例如XDoclet。<br />　　26.你需要熟悉一种单元测试体系(JNunit)，并且学习不同的生成、部署工具(Ant，Maven)。<br />　　27.你需要熟悉一些在JAVA开发中经常用到的软件工程过程。例如RUP(RationalUnifiedProcess)andAgilemethodologies。<br />　　28.你需要能够深入了解加熟练操作和配置不同的操作系统，比如GNU/linux，sunsolaris，macOS等，做为跨平台软件的开发者。<br />　　29.你还需要紧跟java发展的步伐，比如现在可以深入的学习javaME，以及各种java新规范，技术的运用，如新起的web富客户端技术。<br />　　30.你必需要对opensource有所了解，因为至少java的很多技术直接是靠开源来驱动发展的，如java3D技术。<br /><script type="text/javascript"><!--
google_ad_client = "pub-3874079075380071";
google_ad_width = 728;
google_ad_height = 90;
google_ad_format = "728x90_as";
google_ad_type = "image";
google_ad_channel = "";
//--></script><script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script><img src ="http://www.cnitblog.com/tilan/aggbug/24990.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/tilan/" target="_blank">Joinclass Inc</a> 2007-03-31 23:08 <a href="http://www.cnitblog.com/tilan/archive/2007/03/31/24990.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Eclipse 3.3 M6 发布 基于WPF平台</title><link>http://www.cnitblog.com/tilan/archive/2007/03/27/24721.html</link><dc:creator>Joinclass Inc</dc:creator><author>Joinclass Inc</author><pubDate>Tue, 27 Mar 2007 01:28:00 GMT</pubDate><guid>http://www.cnitblog.com/tilan/archive/2007/03/27/24721.html</guid><wfw:comment>http://www.cnitblog.com/tilan/comments/24721.html</wfw:comment><comments>http://www.cnitblog.com/tilan/archive/2007/03/27/24721.html#Feedback</comments><slash:comments>5</slash:comments><wfw:commentRss>http://www.cnitblog.com/tilan/comments/commentRss/24721.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/tilan/services/trackbacks/24721.html</trackback:ping><description><![CDATA[<h5>昨天, Eclipse官方发布了Eclipse 3.3 M6版本.新版本基于Windows Presentation Foundation平台, 同时增加了Vista的本地化特性, 支持JavaXPCOM, 更好支持OLE等等.+WPF (Windows Presentation Foundation)+Native features on Vista (win32)+JavaXPCOM support.</h5>
		<div id="csdn_tag_adstyle">
		</div>
		<div class="newscon">
				<div>
						<script type="text/javascript"><![CDATA[how_ads_zone(13);]]&gt;</script>
						<script language="JavaScript" src="http://z.csdn.net/adjs.php?n=131711817&amp;what=zone:13&amp;charset=utf-8&amp;exclude=," type="text/javascript">
						</script>
						<p>
						</p>
						<p>昨天, Eclipse官方发布了Eclipse 3.3 M6版本.<br /><br />新版本基于Windows Presentation Foundation平台, 同时增加了Vista的本地化特性, 支持JavaXPCOM, 更好支持OLE等等.<br /><br />新版本的特性包括:<br /><br />+WPF (Windows Presentation Foundation)<br />+Native features on Vista (win32)<br />+JavaXPCOM support<br /><img alt="" src="http://images.csdn.net/20070326/javaxpcom.png" /><br /><br />+OLEExample and OLE improvements<br /><img alt="" src="http://images.csdn.net/20070326/oleexample.png" /><br /><br />+Reparenting support on Mac OSX<br />+Display.post() supports more mouse events<br />+Advanced graphics supports mirroring<br />......<br />等等<br /><br />更多特性参考官方站点<br /><br />Eclipse 3.3 M6官方下载:<br /><a href="http://download.eclipse.org/eclipse/downloads/drops/S-3.3M6-200703231616/index.php" target="_new"><font color="#3f87d7">http://download.eclipse.org/eclipse/downloads/drops/S-3.3M6-200703231616/index.php</font></a></p>
						<p>原文链接：<font face="Arial" color="#3f87d7"><a href="http://www.matrix.org.cn/resource/news/Eclipse3.3+M6_abe8355e-db2b-11db-9bed-29012b8c745e.html">http://www.matrix.org.cn/resource/news/Eclipse3.3+M6_abe8355e-db2b-11db-9bed-29012b8c745e.html</a></font></p>
				</div>
		</div>
		<script type="text/javascript">
				<!--
google_ad_client = "pub-3874079075380071";
google_ad_width = 728;
google_ad_height = 90;
google_ad_format = "728x90_as";
google_ad_type = "text_image";
//2007-03-19: 3G-move, 三星, 摩托罗拉, 索爱, 诺基亚
google_ad_channel = "1730597762+1709572468+0778807001+6838187825+8377398382";
//-->
		</script>
		<script src="http://pagead2.googlesyndication.com/pagead/show_ads.js" type="text/javascript">
		</script><img src ="http://www.cnitblog.com/tilan/aggbug/24721.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/tilan/" target="_blank">Joinclass Inc</a> 2007-03-27 09:28 <a href="http://www.cnitblog.com/tilan/archive/2007/03/27/24721.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>FireFox</title><link>http://www.cnitblog.com/tilan/archive/2007/03/19/24302.html</link><dc:creator>Joinclass Inc</dc:creator><author>Joinclass Inc</author><pubDate>Mon, 19 Mar 2007 13:22:00 GMT</pubDate><guid>http://www.cnitblog.com/tilan/archive/2007/03/19/24302.html</guid><wfw:comment>http://www.cnitblog.com/tilan/comments/24302.html</wfw:comment><comments>http://www.cnitblog.com/tilan/archive/2007/03/19/24302.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/tilan/comments/commentRss/24302.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/tilan/services/trackbacks/24302.html</trackback:ping><description><![CDATA[<script type="text/javascript">
				<!--
google_ad_client = "pub-3874079075380071";
google_ad_width = 468;
google_ad_height = 60;
google_ad_format = "468x60_as_rimg";
google_cpa_choice = "CAAQycb8zwEaCNrmdvgKt1bFKJnA93M";
google_ad_channel = "";
//-->
		</script>
		<script src="http://pagead2.googlesyndication.com/pagead/show_ads.js" type="text/javascript">
		</script><img src ="http://www.cnitblog.com/tilan/aggbug/24302.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/tilan/" target="_blank">Joinclass Inc</a> 2007-03-19 21:22 <a href="http://www.cnitblog.com/tilan/archive/2007/03/19/24302.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Google</title><link>http://www.cnitblog.com/tilan/archive/2007/03/19/24298.html</link><dc:creator>Joinclass Inc</dc:creator><author>Joinclass Inc</author><pubDate>Mon, 19 Mar 2007 12:55:00 GMT</pubDate><guid>http://www.cnitblog.com/tilan/archive/2007/03/19/24298.html</guid><wfw:comment>http://www.cnitblog.com/tilan/comments/24298.html</wfw:comment><comments>http://www.cnitblog.com/tilan/archive/2007/03/19/24298.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/tilan/comments/commentRss/24298.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/tilan/services/trackbacks/24298.html</trackback:ping><description><![CDATA[<script type="text/javascript">
				<!--
google_ad_client = "pub-3874079075380071";
google_ad_width = 728;
google_ad_height = 90;
google_ad_format = "728x90_as";
google_ad_type = "text_image";
//2007-03-19: 3G-move, 三星, 摩托罗拉, 索爱, 诺基亚
google_ad_channel = "1730597762+1709572468+0778807001+6838187825+8377398382";
//-->
		</script>
		<script src="http://pagead2.googlesyndication.com/pagead/show_ads.js" type="text/javascript">
		</script><img src ="http://www.cnitblog.com/tilan/aggbug/24298.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/tilan/" target="_blank">Joinclass Inc</a> 2007-03-19 20:55 <a href="http://www.cnitblog.com/tilan/archive/2007/03/19/24298.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>使用 SVK 构建分布式版本控制环境</title><link>http://www.cnitblog.com/tilan/archive/2007/03/16/24149.html</link><dc:creator>Joinclass Inc</dc:creator><author>Joinclass Inc</author><pubDate>Fri, 16 Mar 2007 15:05:00 GMT</pubDate><guid>http://www.cnitblog.com/tilan/archive/2007/03/16/24149.html</guid><wfw:comment>http://www.cnitblog.com/tilan/comments/24149.html</wfw:comment><comments>http://www.cnitblog.com/tilan/archive/2007/03/16/24149.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/tilan/comments/commentRss/24149.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/tilan/services/trackbacks/24149.html</trackback:ping><description><![CDATA[<p>2007 年 2 月 28 日</p>
		<blockquote>SVK 是一个基于 Subversion 构造的分布式的版本控制系统。通常的集中式管理系统，如 CVS，Subversion 已经得到广泛应用，但是集中式的管理存在相应的缺陷，例如对唯一的版本库过分依赖：一旦不能正常连接到集中式的版本库，整个系统陷入瘫痪。SVK 最大的能力就在于可以维护分布式的版本库，分散的开发人员可以通过 SVK 建立远程的 CVS，Subversion，P4 协议的版本库镜像，选择工作在自己合适的镜像版本库，这个镜像甚至可以是本地的，整个工作可以离线进行，然后在需要的时候同步镜像版本库到主版本库。</blockquote>
		<!--START RESERVED FOR FUTURE USE INCLUDE FILES-->
		<!-- include java script once we verify teams wants to use this and it will work on dbcs and cyrillic characters -->
		<!--END RESERVED FOR FUTURE USE INCLUDE FILES-->
		<p>
				<a name="N10056">
						<span class="atitle">前言</span>
				</a>
		</p>
		<p>SVK 在大部分的操作与设计思想上都与 Subversion 相似，本文假定读者对 Subversion 有一定的了解，将着重介绍 SVK 新增特性与功能，与 Subversion 重叠的部分就不再赘述。读者可以参考作者的另外一篇 <a href="http://www.ibm.com/developerworks/cn/java/j-lo-svk/#resources"><font color="#996699">关于 Subversion 的文章</font></a>。</p>
		<p>
				<a name="N10064">
						<span class="atitle">历史</span>
				</a>
		</p>
		<p>版本管理工具的历史由来已久，CVS 作为标准的版本管理控制工具已经得到了广泛应用。为改善 CVS 天生的缺陷，CollabNet 开发了 Subversion。Subversion 在目录版本化、原子提交、元数据、分支和标签等方面有了极大的改进，但遗憾的是它仍然是集中式的版本管理工具。不过幸运的是，由于 Subversion 灵活的设计，重用 Subversion 已有组件并扩展其功能成为了现实，SVK 就是这样一个基于 Subversion 的扩展实现。高嘉良先生一年时间的全职工作使 SVK 顺利诞生了。目前 SVK 项目已经被 Bestpractical 收录，读者可以访问其官方主页（请参阅 <a href="http://www.ibm.com/developerworks/cn/java/j-lo-svk/#resources"><font color="#996699">参考资源</font></a>）。</p>
		<p>
				<a name="N10072">
						<span class="atitle">License</span>
				</a>
		</p>
		<p>SVK 是基于 Artistic License 发布的。Artistic License 目前基本被用于标准 Perl，CPAN 组件以及 Parrot 软件上。详细信息请参阅 <a href="http://www.ibm.com/developerworks/cn/java/j-lo-svk/#resources"><font color="#996699">参考资源</font></a>。 </p>
		<p>
				<a name="N10080">
						<span class="smalltitle">
								<strong>
										<font face="Arial">安装</font>
								</strong>
						</span>
				</a>
		</p>
		<p>SVK 由一组基于 SVN 的 Perl 绑定的 Perl5 的模块构成。Subversion 本身是构建于 Apache APR 之上，因此 SVK 可以在任何支持 Apache Http Server 的操作系统上运行，包括 Windows、Linux、Mac OS、Free BSD 以及 Netware。</p>
		<p>最简单的安装方式是直接下载对应操作系统的的二进制版本。Windows 版本可以在 <a href="http://svk.bestpractical.com/view/SVKWin32"><font color="#5c81a7">这里</font></a> 找到，Linux 系统上也可以使用 deb 或者 rpm 的安装方式。目前 Cpan 已经提供有 2.0 版本的安装，通过 cpan 的安装方式如下：</p>
		<p>首先需要安装 Subversion 的 Perl 绑定，cpan 没有提供这一模块，如果安装 Subversion 的时候没有选择安装 Perl 绑定则需要重新配置及安装 Subversion。</p>
		<p>安装 Subversion 的 Perl 绑定需要 swig 的支持，swig 是 C/C++ 软件与其他高级语言的连接器，关于 swig 请参考<a href="http://www.swig.org/"><font color="#5c81a7">http://www.swig.org/</font></a>。</p>
		<p>
				<b>安装 swig</b>
		</p>
		<p>下载 swig1.3.24 以上版本（需要 Perl 5.8.0 以上版本支持），解压后在 SWIG-1.3.xx 目录下运行如下命令，其中 /path/to/correct/perl/binary 应当指向 Perl 的可执行文件：</p>
		<table cellspacing="0" cellpadding="0" width="40%" align="right" border="0">
				<tbody>
						<tr>
								<td width="10">
										<img height="1" alt="" src="http://www.ibm.com/i/c.gif" width="10" />
								</td>
								<td>
										<table cellspacing="0" cellpadding="5" width="100%" border="1">
												<tbody>
														<tr>
																<td bgcolor="#eeeeee">
																		<a name="N100A7">
																				<b>验证安装</b>
																		</a>
																		<br />可以用 swig --version 来验证安装是否成功。 </td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
		<table cellspacing="0" cellpadding="0" width="50%" border="0">
				<tbody>
						<tr>
								<td class="code-outline">
										<pre class="displaycode">./configure --with-perl5=/path/to/correct/perl/binary
make
make install
</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>
				<b>配置 Subversion</b>
		</p>
		<p>成功安装了 swig 后便可以安装 subverion 的 perl 绑定了，在 Subversion 源代码目录下运行如下命令：</p>
		<table cellspacing="0" cellpadding="0" width="40%" align="right" border="0">
				<tbody>
						<tr>
								<td width="10">
										<img height="1" alt="" src="http://www.ibm.com/i/c.gif" width="10" />
								</td>
								<td>
										<table cellspacing="0" cellpadding="5" width="100%" border="1">
												<tbody>
														<tr>
																<td bgcolor="#eeeeee">
																		<a name="N100BE">
																				<b>验证安装</b>
																		</a>
																		<br />如果 Subversion 的 configure 找到了合适的 swig，将会生成名为 libsvn_swig_perl.so 的库文件。 </td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
		<table cellspacing="0" cellpadding="0" width="50%" border="0">
				<tbody>
						<tr>
								<td class="code-outline">
										<pre class="displaycode">./configure PERL=/path/to/correct/perl/binary
</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>
				<b>安装 Subversion 的 perl 绑定</b>
		</p>
		<table cellspacing="0" cellpadding="0" width="50%" border="0">
				<tbody>
						<tr>
								<td class="code-outline">
										<pre class="displaycode">make
make swig-pl
make check-swig-pl
make install
make install-swig-pl
</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>
				<b>通过 cpan 安装 SVK</b>
		</p>
		<p>通过如下命令，cpan 会自动寻找并提示安装所有相关模块。</p>
		<table cellspacing="0" cellpadding="0" width="60%" border="0">
				<tbody>
						<tr>
								<td class="code-outline">
										<pre class="displaycode">&gt;cpan
cpan&gt; install SVK
</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>如果全部安装成功。在命令行敲入 svk 便会得到如下的 SVK 帮助信息：</p>
		<table cellspacing="0" cellpadding="0" width="30%" align="right" border="0">
				<tbody>
						<tr>
								<td width="10">
										<img height="1" alt="" src="http://www.ibm.com/i/c.gif" width="10" />
								</td>
								<td>
										<table cellspacing="0" cellpadding="5" width="100%" border="1">
												<tbody>
														<tr>
																<td bgcolor="#eeeeee">
																		<a name="N100E8">
																				<b>获取帮助</b>
																		</a>
																		<br />
																		<p>svk help commands 将会列出所有 SVK 支持的子命令。</p>
																		<p>对于某个特定的命令如 update，svk help update 将会得到关于 update 的说明。</p>
																		<p>svk help environment 将会列出所有与 SVK 相关的环境变量。</p>
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
		<table cellspacing="0" cellpadding="0" width="60%" border="0">
				<tbody>
						<tr>
								<td class="code-outline">
										<pre class="displaycode">SVK Documentation - Main index:

If this is your first time using SVK, you should start by reading a
brief tutorial. When you're ready, type:

    svk help intro

Once you've done that, more in-depth help is available:

    svk help environment    Environment variables that alter svk's behavior
    svk help commands       A list of all available commands
    svk help view           svk view support
    svk help &lt;command-name&gt; Help for a specific command

For commercial support, contact sales@bestpractical.com. For up to date
information about SVK, visit http://svk.bestpractical.com/.
</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>如果想要体验最新的版本，可以直接从 SVK 的版本库取出最新的源代码进行编译安装：</p>
		<p>Perl 绑定安装部分同前述。</p>
		<table cellspacing="0" cellpadding="0" width="60%" border="0">
				<tbody>
						<tr>
								<td class="code-outline">
										<pre class="displaycode">svn co http://code.bestpractical.com/svk/trunk/
cd trunk/
perl Makefile.PL
make
make test
make install
svk
</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td>
										<img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" />
										<br />
										<img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" />
								</td>
						</tr>
				</tbody>
		</table>
		<table class="no-print" cellspacing="0" cellpadding="0" align="right">
				<tbody>
						<tr align="right">
								<td>
										<img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" />
										<br />
										<table cellspacing="0" cellpadding="0" border="0">
												<tbody>
														<tr>
																<td valign="center">
																		<br />
																</td>
																<td valign="top" align="right">
																		<b>
																				<font color="#996699">
																				</font>
																		</b>
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<p>
				<a name="N10107">
						<span class="atitle">新功能</span>
				</a>
		</p>
		<p>相较于 Subversion 而言，SVK 增加了许多强劲的功能。</p>
		<p>
				<a name="N10111">
						<span class="smalltitle">
								<strong>
										<font face="Arial">Depot</font>
								</strong>
						</span>
				</a>
		</p>
		<p>首先介绍一个新概念—— Depot，它是 SVK 进行版本管理的核心。SVK 使用 Subversion 的版本库实现 Depot。对本地 Depot 的引用是使用"//"，由于它完全是 Subversion 兼容的，因此用户也可以很方便的将 Depot 通过 svnserve 或者 http 方式发布到网络上。</p>
		<p>
				<a name="N1011B">
						<span class="smalltitle">
								<strong>
										<font face="Arial">Patch</font>
								</strong>
						</span>
				</a>
		</p>
		<p>在 Subversion 中，用户可以使用重定向 svn diff 的输出来生成 patch 文件：</p>
		<table cellspacing="0" cellpadding="0" width="60%" border="0">
				<tbody>
						<tr>
								<td class="code-outline">
										<pre class="displaycode">svn diff foo &gt; patch.diff
</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>在 SVK 中补丁的功能得到了加强。用户可以通过 commit 以及 smerge 中的 -P(--patch) 选项来创建补丁：</p>
		<table cellspacing="0" cellpadding="0" width="60%" border="0">
				<tbody>
						<tr>
								<td class="code-outline">
										<pre class="displaycode">svk commit -m "this is log" --patch patch_name
svk smerge //foo //bar --patch patch_name
</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>创建的补丁将存储在 Depot 同一目录下的 patch 子目录中，用户可以将这一补丁传递给其他用户使用。</p>
		<p>同时 SVK 的补丁功能支持对二进制文件的补丁操作，例如：</p>
		<table cellspacing="0" cellpadding="0" width="60%" border="0">
				<tbody>
						<tr>
								<td class="code-outline">
										<pre class="displaycode">touch foo
zip foo.zip foo
svk add foo.zip
svk commit -m "this is log" foo.zip --patch patch_name
</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>生成补丁内容如下</p>
		<table cellspacing="0" cellpadding="0" width="60%" border="0">
				<tbody>
						<tr>
								<td class="code-outline">
										<pre class="displaycode">==== Patch &lt;patch_name&gt; level 1
Source: [No source]
Target: 9bbf3572-454d-844a-a388-5e5c8078394f:/tony:1
        (http://localhost/repos)
Log:
this is log
=== foo.zip
==================================================================
Cannot display: file marked as a binary type.

Property changes on: foo.zip
___________________________________________________________________
Name: svn:mime-type
 +application/octet-stream


==== BEGIN SVK PATCH BLOCK ====
Version: svk v2.0.0 (MSWin32)

eJxNks1qE1EUx6c1qWIptMFqcaFFpoKLsXM/5iMphqhJKgY10EQUF5ObmZtkZDIzTm6DLVfIaKjF
J9AHENworly57EJbcO8LuPcFxHunFoRh4HDO/3fOPedfT1obFcDLZZ2rQOdbDxulUpMwd7AmItXk
1PNZlKgGD+iYBiriQdRXMQ/JkIosI0mfsnIZCLF9LK5lghMIlowuYVE4UosZzGEJpSrgsIJ4BXLx
FwEQySimoZNEEVMhN6FIOXIgN4hG1JFCWWzKYqjanHie0/MDqlq8F0XXd/1YUhwh1YBACqnxT+r5
CXXFRDuyQPY0ZNbk7oCEfZpBnDiJ4gwMEB+Nw9LQH1KN7cRUhZiTOA58lzA/Ctcjl1GmjcQTyPAY
ZGT5HYfR58yjASOSI+bQkVjHfUVR0uhqenGvmp/W8puFN9XCxL+TLuw9yqWbhWm1MK1deVVP56f1
869rhWbjVO6scvTitjmj7Cpgq0qVr2eU3Iex43odf5F0Onpnolxe7Xl59LiWHoSfnrxs36vfPfz9
/aez8uwIQKDr4Jz+efJ+beUPOkSTg8rT5cl09q02u9Sf7s+n15b3Vy5t3Pz10Vu8BR4sfZtT2q0F
5fSPGwe1ZmNm9sL80qryJRWdc+1WvtnIz80oFfGGdxX8/zWyxct1IciBbVrIw2bPI8TCwKIGMC2I
u7gIDewhOzsuAJwN/NGq+KR9BCiW7nCki8plyFUIj83TyvxUKrVDf0yTEQnWxMWxrB4I6yV0LILt
bd8TflwXnspuqiKTF7vdHjIsqGHRVLMxJhpBtq0Z1HBt3bJREff+AuTM7ls=
==== END SVK PATCH BLOCK ====
</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>因而通常的patch工具不能支持SVK生成的补丁。SVK 提供了一个 patch 命令来应用补丁，patch 命令包含如下一些常用选项：</p>
		<table cellspacing="0" cellpadding="0" width="60%" border="0">
				<tbody>
						<tr>
								<td class="code-outline">
										<pre class="displaycode">svk patch --list|--ls
查看当前所有的补丁
svk patch --cat|--view PATCHNAME
查看某一补丁的内容
svk patch --regenerate|--regen PATCHNAME
重新生成补丁
svk patch --apply PATCHNAME [TARGET] [-- MERGEOPTIONS]
应用补丁
svk patch --delete|--rm PATCHNAME
删除补丁
</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>
				<a name="N1014D">
						<span class="smalltitle">
								<strong>
										<font face="Arial">Mirror</font>
								</strong>
						</span>
				</a>
		</p>
		<p>SVK 的镜像功能支持如下流行的版本控制工具：</p>
		<table cellspacing="0" cellpadding="0" width="60%" border="0">
				<tbody>
						<tr>
								<td class="code-outline">
										<pre class="displaycode">svk mirror [http|svn]://host/path DEPOTPATH
svk mirror cvs::pserver:user@host:/cvsroot:module/... DEPOTPATH
svk mirror p4:user@host:1666://path/... DEPOTPATH
</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>常用的 mirror 选项包括：</p>
		<table cellspacing="0" cellpadding="0" width="60%" border="0">
				<tbody>
						<tr>
								<td class="code-outline">
										<pre class="displaycode">--list (-l)
察看本机上的所有 mirror
--detach (-d)
取消一个 mirror
--relocate
将 mirror 的源路经重定向
--unlock
非正常操作导致 mirror 被锁住可以用这个选项解锁
</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>
				<a name="N10164">
						<span class="smalltitle">
								<strong>
										<font face="Arial">star-merge(smart-merge)</font>
								</strong>
						</span>
				</a>
		</p>
		<p>smerge 是 SVK 的亮点之一，SVK 的核心功能都是围绕其展开的。主要操作选项列举如下：</p>
		<table cellspacing="0" cellpadding="0" width="60%" border="0">
				<tbody>
						<tr>
								<td class="code-outline">
										<pre class="displaycode"> -I [--incremental]
 渐进式的合并。它可以忠实地记录源版本库的每一次 commit 操作。
 -B [--baseless]
 用最早的版本作为合并的初始点。一般用户新版本库同步的首次合并。
 -b [--base] BASE 
从指定版本开始合并。一般用于合并已有的版本库分支。
 -s [--sync]
 合并前同步 Depot 与源版本库。
 -P [--patch] NAME
 不进行真实的合并，而是将合并内容生成一个补丁。
 -C [--check-only]
 列举合并的内容而不进行真实的操作。
</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>合并过程中难免会遇到冲突的代码，SVK 提供了一些解决冲突的支持。用 perldoc SVK::Resolve 可以列出合并相关的帮助信息：</p>
		<table cellspacing="0" cellpadding="0" width="60%" border="0">
				<tbody>
						<tr>
								<td class="code-outline">
										<pre class="displaycode">NAME

    SVK::Resolve - Interactively resolve conflicts

DESCRIPTION

      Accept:
         a   : Accept the merged/edited file.
         y   : Keep only changes to your file.
         t   : Keep only changes to their file.
      Diff:
         d   : Diff your file against merged file.
         dm  : See merged changes.
         dy  : See your changes alone.
         dt  : See their changes alone.
      Edit:
         e   : Edit merged file with an editor.
         m   : Run an external merge tool to edit merged file.
      Misc:
         s   : Skip this file.
         h   : Print this help message.

      Environment variables:
        EDITOR     : Editor to use for 'e'.
        SVKMERGE   : External merge tool to always use for 'm'.
        SVKRESOLVE : The resolve action to take, instead of asking.

</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>在合并的过程中遇到冲突 SVK 会中断操作并提示用户输入：</p>
		<table cellspacing="0" cellpadding="0" width="60%" border="0">
				<tbody>
						<tr>
								<td class="code-outline">
										<pre class="displaycode">e)dit, d)iff, m)erge, s)kip, t)heirs, y)ours, h)elp? [e]
</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>可以选择的操作有编辑当前文件，打印出差异，合并，跳过，保留源端文件以及保留目标端的文件。</p>
		<p>选择了 merge 以后 SVK 会自动搜寻可以使用的合并工具：</p>
		<table cellspacing="0" cellpadding="0" width="60%" border="0">
				<tbody>
						<tr>
								<td class="code-outline">
										<pre class="displaycode">Multiple merge tools found, choose one:
(to skip this question, set the SVKMERGE environment variable to one of them)
1)GVim, 2)TortoiseMerge, 3)Vim, q)uit?
</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>用户可以使用任何一种合并工具来手动解决冲突。此外 SVK 提供了设定环境变量来定义默认解决冲突的方式，用户可以设定环境变量 SVKRESOLVE 为上述提到的任何一种操作，例如 s(kip)，t(heirs)，y(ours)。</p>
		<br />
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td>
										<img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" />
										<br />
										<img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" />
								</td>
						</tr>
				</tbody>
		</table>
		<table class="no-print" cellspacing="0" cellpadding="0" align="right">
				<tbody>
						<tr align="right">
								<td>
										<img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" />
										<br />
										<table cellspacing="0" cellpadding="0" border="0">
												<tbody>
														<tr>
																<td valign="center">
																		<br />
																</td>
																<td valign="top" align="right">
																		<a class="fbox" href="http://www.ibm.com/developerworks/cn/java/j-lo-svk/#main">
																				<b>
																						<font color="#996699">
																						</font>
																				</b>
																		</a>
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<p>
				<a name="N10191">
						<span class="atitle">性能</span>
				</a>
		</p>
		<p>SVK 在大部分方面具有与 Subversion 相当的性能，而在某些可以离线的操作具有更出色的表现。例如 svk status, svk update 以及 svk switch。</p>
		<p>CVS，SVK 以及 Subversion 详细的比较数据见 <a href="http://svk.bestpractical.com/view/SVKvsSVNvsCVS"><font color="#5c81a7">http://svk.bestpractical.com/view/SVKvsSVNvsCVS</font></a></p>
		<br />
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td>
										<img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" />
										<br />
										<img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" />
								</td>
						</tr>
				</tbody>
		</table>
		<table class="no-print" cellspacing="0" cellpadding="0" align="right">
				<tbody>
						<tr align="right">
								<td>
										<img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" />
										<br />
										<table cellspacing="0" cellpadding="0" border="0">
												<tbody>
														<tr>
																<td valign="center">
																		<br />
																</td>
																<td valign="top" align="right">
																		<b>
																				<font color="#996699">
																				</font>
																		</b>
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<p>
				<a name="N101A2">
						<span class="atitle">完整的例子</span>
				</a>
		</p>
		<p>这一部分介绍 SVK 的实际使用。</p>
		<p>
				<a name="N101AC">
						<span class="smalltitle">
								<strong>
										<font face="Arial">单独使用</font>
								</strong>
						</span>
				</a>
		</p>
		<p>假设有一个远程的版本库 http://remote/repos，用户经常需要离线的工作，则可以使用 SVK 在本地计算机上建立一个远程版本库的镜像 Depot：</p>
		<table cellspacing="0" cellpadding="0" width="60%" border="0">
				<tbody>
						<tr>
								<td class="code-outline">
										<pre class="displaycode">svk mirror http://remote/repos //mirror/local
</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>为此镜像做一个拷贝，所有本地工作都在这一拷贝上完成</p>
		<table cellspacing="0" cellpadding="0" width="60%" border="0">
				<tbody>
						<tr>
								<td class="code-outline">
										<pre class="displaycode">svk cp //mirror/local //local
</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>从本地 Depot 取出 working copy</p>
		<table cellspacing="0" cellpadding="0" width="60%" border="0">
				<tbody>
						<tr>
								<td class="code-outline">
										<pre class="displaycode">svk co //local
</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>在能连接到远程版本库的时候，同步远程的版本库到本地</p>
		<table cellspacing="0" cellpadding="0" width="60%" border="0">
				<tbody>
						<tr>
								<td class="code-outline">
										<pre class="displaycode">svk sy //mirror/local
svk pull //local
</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>当然，将 Depot 作为 Subversion 版本库发布出来以后用户便可以脱离 SVK，使用 Subversion 的客户端即可访问。这样一来，所有对版本库的工作都可以在没有网络环境的情况下进行，在将来能够连上网络的时候使用如下命令便将所有在本地的更动反映到远程版本库中去：</p>
		<table cellspacing="0" cellpadding="0" width="60%" border="0">
				<tbody>
						<tr>
								<td class="code-outline">
										<pre class="displaycode">svk push //local
</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>
				<a name="N101DB">
						<span class="smalltitle">
								<strong>
										<font face="Arial">版本库同步</font>
								</strong>
						</span>
				</a>
		</p>
		<p>现今流行的 Open source 开发模式限制了 committer 的数量，并非所有用户都具有 commit 的权限。假设现有一个远程的版本库 http://remote/repos，数个用户希望能够有权限自由的 commmit，自然的，我们可以利用上述的镜像方法获得一个属于自己的版本库，但是这一版本库必须位于某台服务器上而不是某人的个人电脑上，以使得所有用户都能访问到。如果这个版本库是在一台标准的 Subversion 版本服务器上（假设 URL 是 http://myremote/repos），通常用户对此服务器只有访问 Subversion 版本库的权限，也就是说，用户无法直接在这一台服务器上安装 SVK 而做镜像。SVK 很好的解决了这一问题。我们可以使用任何一台和可以很好的连接上这两台服务器的某一台机器作为中间服务器，定时进行同步，下面是主要操作步骤。</p>
		<p>在安装有SVK的中间服务器上进行如下操作：</p>
		<table cellspacing="0" cellpadding="0" width="60%" border="0">
				<tbody>
						<tr>
								<td class="code-outline">
										<pre class="displaycode">svk mirror http://remote/repos //remote
svk mirror http://myremote/repos //myremote
</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>分别同步两个 depot 的内容</p>
		<table cellspacing="0" cellpadding="0" width="60%" border="0">
				<tbody>
						<tr>
								<td class="code-outline">
										<pre class="displaycode">svk sy //remote
svk sy //myremote
</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>定时从 //remote 同步到 //myremote</p>
		<table cellspacing="0" cellpadding="0" width="60%" border="0">
				<tbody>
						<tr>
								<td class="code-outline">
										<pre class="displaycode">svk smerge //remote //myremote
</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>同时本文也提供了一个 <a href="http://www.ibm.com/developerworks/cn/java/j-lo-svk/#download"><font color="#996699">Perl 脚本</font></a> 作为示例，读者可以配置它自动运行并生成 Html 格式的 Report。</p>
		<br />
		<a name="fig1">
				<b>图 1： 生成的报告</b>
		</a>
		<br />
		<img height="300" alt="生成的报告" src="http://www.ibm.com/developerworks/cn/java/j-lo-svk/report.jpg" width="570" />
		<br />
		<br />
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td>
										<img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" />
										<br />
										<img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" />
								</td>
						</tr>
				</tbody>
		</table>
		<table class="no-print" cellspacing="0" cellpadding="0" align="right">
				<tbody>
						<tr align="right">
								<td>
										<img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" />
										<br />
										<table cellspacing="0" cellpadding="0" border="0">
												<tbody>
														<tr>
																<td valign="center">
																		<br />
																</td>
																<td valign="top" align="right">
																		<b>
																				<font color="#996699">
																				</font>
																		</b>
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<p>
				<a name="N10213">
						<span class="atitle">结束语</span>
				</a>
		</p>
		<p>SVK 是目前唯一的分布式版本库系统，它成功的对分布式版本库领域进行了有效的探索并获得了成功，它的出现使得以往一些实现起来非常复杂的功能变的十分简单，给一些以往无法完成的操作带来了可能。如 P4，CVS 与 Subversion 版本库的同步与移植，版本库的离线访问，以及远程版本库的镜像和同步等等。期待本文能使更多的读者认识 SVK，并从中获得分布式版本管理的种种便利，使得日常工作更加完美与高效。同时也期待更多的读者与本人交流经验。</p>
		<br />
		<br />
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td>
										<img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" />
										<br />
										<img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" />
								</td>
						</tr>
				</tbody>
		</table>
		<table class="no-print" cellspacing="0" cellpadding="0" align="right">
				<tbody>
						<tr align="right">
								<td>
										<img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" />
										<br />
										<table cellspacing="0" cellpadding="0" border="0">
												<tbody>
														<tr>
																<td valign="center">
																		<br />
																</td>
																<td valign="top" align="right">
																		<b>
																				<font color="#996699">
																				</font>
																		</b>
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<p>
				<span class="atitle">
						<a name="download">下载</a>
				</span>
		</p>
		<table class="data-table-1" cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<th scope="col">描述</th>
								<th scope="col">名字</th>
								<th scope="col" align="right">大小</th>
								<th scope="col">下载方法</th>
						</tr>
						<tr>
								<th class="tb-row" scope="row">示例 Perl 脚本</th>
								<td nowrap="">svksync.zip</td>
								<td nowrap="" align="right">3KB</td>
								<td nowrap="">
										<a class="fbox" href="http://www.ibm.com/developerworks/cn/java/j-lo-svk/svksync.zip">
												<b>
														<font color="#5c81a7">HTTP</font>
												</b>
										</a>
								</td>
						</tr>
				</tbody>
		</table>
		<table cellspacing="0" cellpadding="0" border="0">
				<tbody>
						<tr valign="top">
								<td colspan="5">
										<font color="#5c81a7">
												<img height="12" alt="" src="http://www.ibm.com/i/c.gif" width="12" border="0" />
										</font>
								</td>
						</tr>
						<tr>
								<td>
										<font color="#5c81a7">
												<img height="16" alt="" src="http://www.ibm.com/i/v14/icons/fw.gif" width="16" />
										</font>
								</td>
								<td>
										<a class="fbox" href="http://www.ibm.com/developerworks/cn/whichmethod.html">
												<font color="#5c81a7">关于下载方法的信息</font>
										</a>
								</td>
								<td>
										<font color="#5c81a7">
												<img height="1" alt="" src="http://www.ibm.com/i/c.gif" width="50" />
										</font>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<p>
				<a name="resources">
						<span class="atitle">参考资料 </span>
				</a>
		</p>
		<ul>
				<li>
						<a href="http://svk.bestpractical.com/">
								<font color="#5c81a7">http://svk.bestpractical.com/</font>
						</a>：SVK 项目的主页。<br /><br /></li>
				<li>
						<a href="http://svkbook.elixus.org/">
								<font color="#5c81a7">http://svkbook.elixus.org/</font>
						</a>：SVK 文档的在线版本。<br /><br /></li>
				<li>
						<a href="http://www.swig.org/">
								<font color="#5c81a7">http://www.swig.org/</font>
						</a>：SWIG 项目的主页。<br /><br /></li>
				<li>
						<a href="http://code.bestpractical.com/svk/trunk/ARTISTIC">
								<font color="#5c81a7">http://code.bestpractical.com/svk/trunk/ARTISTIC</font>
						</a>：关于 Artistic License 的基础导言。 <br /><br /></li>
				<li>
						<a href="http://www.opensource.org/licenses/">
								<font color="#5c81a7">http://www.opensource.org/licenses/</font>
						</a>：在这里可以找到关于 Open source License 的详细信息。<br /><br /></li>
				<li>
						<a href="http://www.ibm.com/developerworks/cn/java/j-lo-apache-subversion/index.html">
								<font color="#5c81a7">用 Apache 和 Subversion 搭建安全的版本控制环境</font>
						</a>：本文作者的另一篇关于 Subversion 的介绍文章。 </li>
		</ul>
		<br />
		<br />
		<p>
				<a name="author">
						<span class="atitle">关于作者</span>
				</a>
		</p>
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td colspan="3">
										<img height="5" alt="" src="http://www.ibm.com/i/c.gif" width="100%" />
								</td>
						</tr>
						<tr valign="top" align="left">
								<td>
										<p>
												<img alt="吴玥颢的照片" src="http://www.ibm.com/developerworks/cn/java/j-lo-svk/tony.jpg" align="left" valign="top" />
										</p>
								</td>
								<td>
										<img height="5" alt="" src="http://www.ibm.com/i/c.gif" width="4" />
								</td>
								<td width="100%">
										<p>吴玥颢，目前就职于 IBM 中国开发中心 Harmony 开发团队。 除了对 Java 和脚本语言的热爱之外，他的兴趣还包括哲学、神话、历史与篮球。此外他还是个电脑游戏高手。您可以通过<a href="mailto:wuyuehao@cn.ibm.com?cc="><font color="#5c81a7">wuyuehao</font></a></p>
								</td>
						</tr>
				</tbody>
		</table>
		<script type="text/javascript">
				<!--
google_ad_client = "pub-3874079075380071";
google_ad_width = 728;
google_ad_height = 90;
google_ad_format = "728x90_as";
google_ad_type = "text_image";
//2007-03-19: 3G-move, 三星, 摩托罗拉, 索爱, 诺基亚
google_ad_channel = "1730597762+1709572468+0778807001+6838187825+8377398382";
//-->
		</script>
		<script src="http://pagead2.googlesyndication.com/pagead/show_ads.js" type="text/javascript">
		</script><img src ="http://www.cnitblog.com/tilan/aggbug/24149.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/tilan/" target="_blank">Joinclass Inc</a> 2007-03-16 23:05 <a href="http://www.cnitblog.com/tilan/archive/2007/03/16/24149.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>关于trac的介绍</title><link>http://www.cnitblog.com/tilan/archive/2007/03/08/23746.html</link><dc:creator>Joinclass Inc</dc:creator><author>Joinclass Inc</author><pubDate>Thu, 08 Mar 2007 05:39:00 GMT</pubDate><guid>http://www.cnitblog.com/tilan/archive/2007/03/08/23746.html</guid><wfw:comment>http://www.cnitblog.com/tilan/comments/23746.html</wfw:comment><comments>http://www.cnitblog.com/tilan/archive/2007/03/08/23746.html#Feedback</comments><slash:comments>7</slash:comments><wfw:commentRss>http://www.cnitblog.com/tilan/comments/commentRss/23746.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/tilan/services/trackbacks/23746.html</trackback:ping><description><![CDATA[<p>今天介绍一下Trac，一个基于Web的bug管理系统。</p>
		<ul class="list1" style="PADDING-LEFT: 16px; MARGIN-LEFT: 16px">
				<li>
						<a href="http://trac.edgewall.org/" rel="nofollow">Trac官方主页</a>
				</li>
				<li>
						<a href="http://www.hosted-projects.com/trac/TracDemo/Demo/" rel="nofollow">Trac示例</a>
				</li>
		</ul>
		<p>Trac拥有强大的<strong>bug管理</strong>功能，并集成了<strong>Wiki</strong>用于文档管理。它还<strong>支持代码管理工具Subversion</strong>，这样可以在 bug管理和Wiki中方便地参考程序源代码。</p>
		<p>
				<strong>bug管理</strong>
		</p>
		<p>在Trac中，项目中出现的问题称为ticket。像bug、功能改进、 TODO等都可以写成一个ticket。</p>
		<ul class="list1" style="PADDING-LEFT: 16px; MARGIN-LEFT: 16px">
				<li>可设置ticket的优先级别。 
</li>
				<li>可以设置ticket的里程碑，表明这个ticket应在何时完成，并能够通过条形图方式显示里程碑的完成度。 
</li>
				<li>可以自定义条件生成bug报告，并可以通过SQL语句自定义报告的格式。 </li>
		</ul>
		<p>
				<strong>Subversion集成</strong>
		</p>
		<p>通过Subversion集成，开发者可在Trac中以Web方式浏览代码库中各个版本的代码和代码的修改历史，并可方便地比较各个版本间的差别。</p>
		<p>
				<strong>Wiki</strong>
		</p>
		<p>支持常用的Wiki语法。同时增加了许多bug管理的专用标记，可以方便地创建到ticket、代码行甚至修改历史的链接。</p>
		<p>Trac使用Python写成，后台使用SQLite或PostgreSQL数据库，因此构筑一个完整的Trac系统需要安装以下软件：</p>
		<ul class="list1" style="PADDING-LEFT: 16px; MARGIN-LEFT: 16px">
				<li>Apache 
</li>
				<li>Python 
</li>
				<li>Subversion 
</li>
				<li>PostgreSQL(可选) </li>
		</ul>
		<p>下回继续介绍Trac的安装方法。</p>
		<script type="text/javascript">
				<!--
google_ad_client = "pub-3874079075380071";
google_ad_width = 728;
google_ad_height = 90;
google_ad_format = "728x90_as";
google_ad_type = "text_image";
//2007-03-19: 3G-move, 三星, 摩托罗拉, 索爱, 诺基亚
google_ad_channel = "1730597762+1709572468+0778807001+6838187825+8377398382";
//-->
		</script>
		<script src="http://pagead2.googlesyndication.com/pagead/show_ads.js" type="text/javascript">
		</script><img src ="http://www.cnitblog.com/tilan/aggbug/23746.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/tilan/" target="_blank">Joinclass Inc</a> 2007-03-08 13:39 <a href="http://www.cnitblog.com/tilan/archive/2007/03/08/23746.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>GoDaddy域名重定向DIY </title><link>http://www.cnitblog.com/tilan/archive/2007/03/08/23745.html</link><dc:creator>Joinclass Inc</dc:creator><author>Joinclass Inc</author><pubDate>Thu, 08 Mar 2007 05:35:00 GMT</pubDate><guid>http://www.cnitblog.com/tilan/archive/2007/03/08/23745.html</guid><wfw:comment>http://www.cnitblog.com/tilan/comments/23745.html</wfw:comment><comments>http://www.cnitblog.com/tilan/archive/2007/03/08/23745.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cnitblog.com/tilan/comments/commentRss/23745.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/tilan/services/trackbacks/23745.html</trackback:ping><description><![CDATA[<p>最近好多人都在问我GoDaddy的域名转向设置方法。其实我没用过GoDaddy的域名转向，而且据说在中国国内无法访问域名转发服务。幸好GoDaddy对每个域名都提供了免费的虚拟主机，虽然是带广告的，不过我们可以用它来做自己的域名重定向。方法么，自然是用<a href="http://tech.inspiremedia.org/archives/304.html" rel="nofollow">mod_rewrite</a>了。</p>
		<!-- end Pukiwiki generated code-->
		<a id="more-353">
		</a>
		<!-- begin Pukiwiki generated code-->
		<p>以下假设你的域名为example.com，并假设你要将 blog.example.com 重定向至 www.myblog.com/myname/，如用户访问 <a href="http://blog.example.com/archives/sample.html" rel="nofollow">http://blog.example.com/archives/sample.html</a> 则会自动转向至 <a href="http://www.myblog.com/myname/archives/sample.html" rel="nofollow">http://www.myblog.com/myname/archives/sample.html</a>。</p>
		<p>下面这一段翻译自<a href="http://help.godaddy.com/article.php?article_id=994&amp;topic_id=243" rel="nofollow">GoDaddy</a>的帮助。我的免费空间正在使用，因此没法一步步抓图了。</p>
		<ol class="list1" style="PADDING-LEFT: 16px; MARGIN-LEFT: 16px">
				<li>首先登录GoDaddy，然后选择菜单<strong>Hosting &amp; Server</strong>-&gt;<strong>My Hosting Account</strong>。 
</li>
				<li>你会看到页面上有<strong>Free Hosting Credits</strong>的字样，单击旁边的<strong>Use Credit</strong>建立虚拟主机。 
</li>
				<li>选择你要关联的域名 example.com，然后选择主机类型为 Linux，然后<strong>Continue</strong>。 
</li>
				<li>单击 <strong>Set Up Account</strong>。 
</li>
				<li>在 <strong>Hosting Manager</strong> 中单击 <strong>Accept</strong> 接受最终用户协议。 
</li>
				<li>输入用户名和密码。 
</li>
				<li>单击 <strong>Continue</strong>。 
</li>
				<li>确认之后单击 <strong>Submit</strong>。 </li>
		</ol>
		<p>之后进入Hosting Manager就可以管理你的免费虚拟主机了。控制面板功能很简单，我就不多罗嗦了。下面就开始做域名重定向。</p>
		<p>首先打开<strong>Domain Management</strong>，单击example.com下的<strong>Add Sub Domain</strong>，添加子域名blog，路径随意，这里选择<strong>&lt; same as sub domain &gt;</strong>。</p>
		<div class="img_margin" style="TEXT-ALIGN: left">
				<img title="godaddy-domain-redirect-01.png" height="163" alt="godaddy-domain-redirect-01.png" src="http://tech.inspiremedia.org/wp-content/uploads/2007/02/godaddy-domain-redirect-01.png" width="556" />
		</div>
		<p>大约半小时之后状态会变成 Setup。马上通过FTP登录虚拟主机，可以看到主目录下出现了blog子目录。在 /blog 下建立一个 .htaccess 文件，内容如下。</p>
		<pre> &lt;IfModule mod_rewrite.c&gt;
     RewriteEngine On
     RewriteRule ^/(.*) http://www.myblog.com/myname/$1 [R,L]
 &lt;/IfModule&gt;</pre>
		<p>
				<span style="COLOR: blue">GoDaddy服务器会缓存.htaccess文件状态，新建或删除.htaccess文件一般要等待10-30分钟之后才会生效（修改则会立即生效）。因此建议虚拟主机建好之后马上建立空的.htaccess文件以节约时间。</span>
		</p>
		<p>这样所有访问 <a href="http://blog.example.com/" rel="nofollow">http://blog.example.com/</a> 的请求都会被转向至 <a href="http://www.myblog.com/myname/" rel="nofollow">http://www.myblog.com/myname/</a> ，而且你可以通过修改 RewriteRule 来定义更为复杂的转向规则。</p>
		<script type="text/javascript">
				<!--
google_ad_client = "pub-3874079075380071";
google_ad_width = 728;
google_ad_height = 90;
google_ad_format = "728x90_as";
google_ad_type = "text_image";
//2007-03-19: 3G-move, 三星, 摩托罗拉, 索爱, 诺基亚
google_ad_channel = "1730597762+1709572468+0778807001+6838187825+8377398382";
//-->
		</script>
		<script src="http://pagead2.googlesyndication.com/pagead/show_ads.js" type="text/javascript">
		</script><img src ="http://www.cnitblog.com/tilan/aggbug/23745.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/tilan/" target="_blank">Joinclass Inc</a> 2007-03-08 13:35 <a href="http://www.cnitblog.com/tilan/archive/2007/03/08/23745.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Spring2.0中文参考手册final发布</title><link>http://www.cnitblog.com/tilan/archive/2007/02/05/22677.html</link><dc:creator>Joinclass Inc</dc:creator><author>Joinclass Inc</author><pubDate>Mon, 05 Feb 2007 03:49:00 GMT</pubDate><guid>http://www.cnitblog.com/tilan/archive/2007/02/05/22677.html</guid><wfw:comment>http://www.cnitblog.com/tilan/comments/22677.html</wfw:comment><comments>http://www.cnitblog.com/tilan/archive/2007/02/05/22677.html#Feedback</comments><slash:comments>8</slash:comments><wfw:commentRss>http://www.cnitblog.com/tilan/comments/commentRss/22677.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/tilan/services/trackbacks/22677.html</trackback:ping><description><![CDATA[<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td width="100%">
										<span class="postdetails">
												<font size="2">
												</font>
										</span>
								</td>
								<td valign="top" nowrap="">
										<a href="http://spring.jactiongroup.net/posting.php?mode=quote&amp;p=6996">
												<font size="2">
														<img title="引用并回复" alt="引用并回复" src="http://spring.jactiongroup.net/templates/subSilver/images/lang_english/icon_quote.gif" border="0" />
												</font>
										</a>
								</td>
						</tr>
						<tr>
								<td colspan="2">
										<hr />
								</td>
						</tr>
						<tr>
								<td colspan="2">
										<span class="postbody">
												<a class="postlink" href="http://spring.jactiongroup.net/viewtopic.php?t=2279" target="_blank">
														<img src="http://www.jactiongroup.net/image/spring2-logo.png" border="0" />
												</a>
												<font size="2">
														<br />
														<br />
												</font>
												<span style="FONT-SIZE: 16px; LINE-HEIGHT: normal">
														<br />自国庆节10.1发布了<a class="postlink" href="http://spring.jactiongroup.net/viewtopic.php?t=2279" target="_blank"><font color="#006699">Spring 2.0中文参考手册RC2</font></a>后，下载超过20000份，并被各个媒体转载和发布。经过翻译小组的不懈努力，Spring2.0 中文参考手册final版本完成了，其中，修正了RC2中的遗漏和同步了Spring英文文档中的所有内容。同时，我们也根据大家的需求生成了CHM版本，方便大家查阅使用。 <br /><br />感谢翻译团队的每个人员，感谢大家的认可和支持。 <br /><br /></span>
												<br />
												<span style="FONT-SIZE: 18px; LINE-HEIGHT: normal">
														<br />
														<img src="http://www.jactiongroup.net/reference2/images/admons/note.png" border="0" />
														<span style="FONT-WEIGHT: bold">在线查阅版本:</span>
														<br />
														<br />
														<a href="http://www.redsaga.com/spring_ref/2.0/html/" target="_blank">
																<font color="#006699">http://www.redsaga.com/spring_ref/2.0/html/</font>
														</a>
														<br />
														<br />
														<a href="http://www.jactiongroup.net/reference2/html/" target="_blank">
																<font color="#006699">http://www.jactiongroup.net/reference2/html/</font>
														</a>
														<br />
														<br />
														<br />
														<br />
														<img src="http://www.jactiongroup.net/reference2/images/admons/note.png" border="0" />
														<span style="FONT-WEIGHT: bold">下载版本:</span>
														<br />
														<a href="https://gro.clinux.org/projects/jaction/" target="_blank">
																<font color="#006699">https://gro.clinux.org/projects/jaction/</font>
														</a>
														<br />
												</span>
										</span>
								</td>
						</tr>
				</tbody>
		</table>
		<script type="text/javascript">
				<!--
google_ad_client = "pub-3874079075380071";
google_ad_width = 728;
google_ad_height = 90;
google_ad_format = "728x90_as";
google_ad_type = "text_image";
//2007-03-19: 3G-move, 三星, 摩托罗拉, 索爱, 诺基亚
google_ad_channel = "1730597762+1709572468+0778807001+6838187825+8377398382";
//-->
		</script>
		<script src="http://pagead2.googlesyndication.com/pagead/show_ads.js" type="text/javascript">
		</script><img src ="http://www.cnitblog.com/tilan/aggbug/22677.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/tilan/" target="_blank">Joinclass Inc</a> 2007-02-05 11:49 <a href="http://www.cnitblog.com/tilan/archive/2007/02/05/22677.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>探讨Spring框架使用真相</title><link>http://www.cnitblog.com/tilan/archive/2007/02/05/22672.html</link><dc:creator>Joinclass Inc</dc:creator><author>Joinclass Inc</author><pubDate>Mon, 05 Feb 2007 03:41:00 GMT</pubDate><guid>http://www.cnitblog.com/tilan/archive/2007/02/05/22672.html</guid><wfw:comment>http://www.cnitblog.com/tilan/comments/22672.html</wfw:comment><comments>http://www.cnitblog.com/tilan/archive/2007/02/05/22672.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cnitblog.com/tilan/comments/commentRss/22672.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/tilan/services/trackbacks/22672.html</trackback:ping><description><![CDATA[<p align="center">
				<a href="http://www.jdon.com/aboutme.htm">板桥里人</a> http://www.jdon.com 2004/08/25 </p>
		<p>　　最近，Spring很热闹，因为实现IoC模式和AOP（见<a href="http://www.jdon.com/design.htm" target="_blank">本站专栏</a>），然后又成立公司，吸取上次JBoss的教训，文档不敢收费，结果迎来了一片祝贺声。</p>
		<p>　　Spring真正的精华是它的<a href="http://www.jdon.com/AOPdesign/Ioc.htm" target="_blank">Ioc模式</a>实现的BeanFactory和<a href="http://www.jdon.com/AOPdesign/jdon-aop.htm" target="_blank">AOP</a>，它自己在这个基础上延伸的功能有些画蛇添足。</p>
		<p>　　其实说白了，大家"惊奇"的是它的IoC模式(使用AOP功能需要了解AOP，比较难)，那么，Spring之类的Ioc模式是什么？ 就是：你在编制程序时，只要写被调用者的接口代码，具体子类实例可通过配置实现。</p>
		<p>
				<a href="http://www.jdon.com/AOPdesign/Ioc.htm" target="_blank">　　Ioc模式是什么</a>知道的人不多，但是，当他知道生成对象不用再使用new了，只要在配置文件里配置一下，他感到新鲜，其实这就是Ioc模式的实现，PicoContainer是另外一种真正轻量的Ioc模式实现，PicoContainer还是采取代码将对象注射一个小容器中，而Spring采取配置文件。</p>
		<p>　　配置式编码其实有利有弊，编码本来可通过开发工具或编译器检查错误，但是过分依赖配置时，就会经常出现因为粗心导致的小错误，如果调试程序出错经常是因为配置文件中小写字母写成大写字母，不知道你是怎么心情？</p>
		<p>　　Spring最近还发表了Spring without EJB的书，这倒是说了实话，Spring和EJB其实是相竞争，如同黑与白，如果硬是将两者搭配使用，显得不协调，更不是一些人所谓优化EJB调用的谣言，原因下面将会分析。既然Spring+EJB有缺陷，那么就直接使用Spring+Hibernate架构，但是又带来了新问题：无集群分布式计算性能，只能在一台机器上运行啊，具体分析见：<a href="http://www.jdon.com/artichect/scalable.htm" target="_blank">可伸缩性和重/轻量，谁是实用系统的架构主选？</a></p>
		<p>　　下面来分析所谓Spring+EJB的不协调性，正如水和油搅拌在一起使用一样。<br />　　目前，Spring+EJB有两种应用方式：</p>
		<p>　　1. Spring不介入EJB容器，只做Web与EJB之间的接口，这个位置比较尴尬，Web层直接调用EJB的方法比较直接快捷，为什么要中间加个Spring？可实现Web缓存？使用性能更好的AOP框架<font face="arial,sans-serif" color="#000000" size="-1">aspectwerkz</font>啊；实现Web和EJB解耦？这样的工具更多，自己都可以做个小框架实现，就不必打扰背着AOP和IOC双重重担的Spring了吧。</p>
		<p>　　2. Spring介入EJB容器，这时，需要在你的ejb-jar.xml中配置beanFactoryPath值指向你为EJB配置的applicationContext.xml，那么你的EJB还需要继承Spring的SimpleRemoteStatelessSessionProxyFactoryBean。</p>
		<p>　　好了，现在你的SLSB（无状态Session Bean）成为下面这个样子：</p>
		<p>　　void updateUser(){<br />　　　　<br />　　　　　　myService.updateUser(); //委托给一个POJO的方法，真正业务逻辑封装在这个POJO中</p>
		<p>　　} </p>
		<p>　　这样做有很多“优点”，当然最大“优点”是：</p>
		<p>　　由于真正业务核心在POJO中实现，因此，只要改一下applicationContext.xml配置，这样，调试时，前台就可以直接调用POJO，不必通过EJB，调试起来方便了，这有一个前提：他们认为调试EJB复杂，其实不然，在JBuilder中，结合Junit，测试EJB如同测试POJO一样方便，这是其他分支，不在此讨论。当部署使用时，再改一下applicationContext.xml配置，指引前台调用到EJB。</p>
		<p>　　似乎很巧妙，这里有两个疑问，首先，指引到EJB的改变是什么时候做？持续集成前还是后，在前在后都有问题，这里不仔细分析。</p>
		<p>　　<strong>这种表面巧妙的优点带来最大的问题是：粗粒度事务机制</strong>。所谓粗粒度事务机制，最早见于Petstore的WEB调用EJB Command模式，在<a href="http://www.jdon.com/jive/article.jsp?forum=61&amp;thread=15476" target="_blank">这个帖子</a>中有讨论。 </p>
		<p>　　下面以代码描述什么是粗粒度事务机制：</p>
		<p>　　ejb方法：<br />　　public void updateUser(){<br />　　　　service.updateUser();<br />　　}</p>
		<p>　　service是一个POJO，具体方法可能是更新两个表：<br />　　public void updateUser(){<br />　　　　updateTabel1();//更新table1<br />　　　　updateTable2(); //更新table2<br />　　}</p>
		<p>　　当updateTable2()抛出异常，updateTable1()是不回滚的。这样，table1中就有一条错误的多余的记录，而table2则没有这条记录。</p>
		<p>　　那么，怎么做才能使两个表记录一致，采取事务机制，只有下面这样书写才能实现真正事务：<br />在EJB方法中写两个方法，因为EJB方法体缺省是一个事务。<br />　　public void updateUser(){<br />　　　　updateTabel1();//更新table1<br />　　　　updateTable2(); //更新table2<br />　　}</p>
		<p>　　关于EJB自动的事务机制，最近也有一个道友做了测试，<a href="http://www.jdon.com/jive/thread.jsp?forum=16&amp;thread=16072" target="_blank">对于JBoss中容器管理的事务的疑惑。</a></p>
		<p>
				<a href="http://www.jdon.com/jive/thread.jsp?forum=16&amp;thread=16072" target="_blank">
				</a>　　如果你从事关键事务，就是带money相关操作的事务，这种粗粒度机制可能害苦你，那么，似乎有一种办法可弥补事务，不使用EJB容器事务(CMT)，在service中使用Spring的事务机制。</p>
		<p>
				<a href="http://www.jdon.com/jive/thread.jsp?forum=16&amp;thread=16072" target="_blank">
				</a>　　如果使用Spring事务机制，业务核心又在POJO中实现，那么我有一个疑问：还要套上EJB干什么？至此，你终于明白，Spring本质是和EJB竞争的，如果硬套上EJB使用，只是相借助其集群分布式功能，而这个正是Spring目前所缺少的。</p>
		<p>　　我太惊异Spring精巧的诡异了，他和EJB关系，正如异型和人的关系一样。</p>
		<p>　　为了避免你每次使用Spring时想到粘糊糊的异型，不如Spring without EJB，这也正是Spring的初衷，也是它的一个畅销书名。</p>
		<p>　　为让初学者更容易掌握Spring，在本站教学区新增一篇“<a href="http://www.jdon.com/my/train/controllAction.html" target="_blank">Spring入门速成</a>”，简单易懂，专门针对VIP会员的。</p>
		<p align="left">参考文章：</p>
		<p>
				<a href="http://www.jdon.com/AOPdesign/Ioc.htm" target="_blank">Ioc模式(又称DI：Dependency Injection)</a>
		</p>
		<p>
				<a href="http://www.jdon.com/jive/thread.jsp?forum=91&amp;thread=23671" target="_blank">IOC模式的思考和疑问</a>
		</p>
		<p>
				<a href="http://www.jdon.com/AOPdesign/iocimpls.htm">Ioc容器的革命性优点</a>
		</p>
		<p>
				<a href="http://www.jdon.com/artichect/java_ee_architecture.htm" target="_blank">Java企业系统架构选择考量</a>
		</p>
		<p>
				<a href="http://www.jdon.com/artichect/embeddable.htm" target="_blank">JBoss 5迎来Java的彻底的可配置时代</a>
		</p><img src ="http://www.cnitblog.com/tilan/aggbug/22672.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/tilan/" target="_blank">Joinclass Inc</a> 2007-02-05 11:41 <a href="http://www.cnitblog.com/tilan/archive/2007/02/05/22672.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Spring 系列: Spring 框架简介</title><link>http://www.cnitblog.com/tilan/archive/2007/02/05/22671.html</link><dc:creator>Joinclass Inc</dc:creator><author>Joinclass Inc</author><pubDate>Mon, 05 Feb 2007 03:37:00 GMT</pubDate><guid>http://www.cnitblog.com/tilan/archive/2007/02/05/22671.html</guid><wfw:comment>http://www.cnitblog.com/tilan/comments/22671.html</wfw:comment><comments>http://www.cnitblog.com/tilan/archive/2007/02/05/22671.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cnitblog.com/tilan/comments/commentRss/22671.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/tilan/services/trackbacks/22671.html</trackback:ping><description><![CDATA[<p id="subtitle">Spring AOP 和 IOC 容器入门<br /><br /></p>
		<blockquote>在这由三部分组成的介绍 Spring 框架的系列文章的第一期中，将开始学习如何用 Spring 技术构建轻量级的、强壮的 J2EE 应用程序。developerWorks 的定期投稿人 Naveen Balani 通过介绍 Spring 框架开始了他由三部分组成的 <i>Spring 系列</i>，其中还将介绍 Spring 面向方面的编程（AOP）和控制反转（IOC）容器。</blockquote>
		<!--START RESERVED FOR FUTURE USE INCLUDE FILES-->
		<!-- include java script once we verify teams wants to use this and it will work on dbcs and cyrillic characters -->
		<!--END RESERVED FOR FUTURE USE INCLUDE FILES-->
		<p>Spring 是一个开源框架，是为了解决企业应用程序开发复杂性而创建的。框架的主要优势之一就是其分层架构，分层架构允许您选择使用哪一个组件，同时为 J2EE 应用程序开发提供集成的框架。</p>
		<p>在这篇由三部分组成的 <i>Spring 系列</i> 的第 1 部分中，我将介绍 Spring 框架。我先从框架底层模型的角度描述该框架的功能，然后将讨论两个最有趣的模块：Spring 面向方面编程（AOP）和控制反转 （IOC） 容器。接着将使用几个示例演示 IOC 容器在典型应用程序用例场景中的应用情况。这些示例还将成为本系列后面部分进行的展开式讨论的基础，在本文的后面部分，将介绍 Spring 框架通过 Spring AOP 实现 AOP 构造的方式。</p>
		<p>请参阅 <a href="http://www.ibm.com/developerworks/cn/java/wa-spring1/?S_TACT=105AGX52&amp;S_CMP=techccid#download"><font color="#5c81a7">下载</font></a>，下载 Spring 框架和 Apache Ant，运行本系列的示例应用程序需要它们。</p>
		<p>
				<a name="1">
						<span class="atitle">Spring 框架</span>
				</a>
		</p>
		<p>Spring 框架是一个分层架构，由 7 个定义良好的模块组成。Spring 模块构建在核心容器之上，核心容器定义了创建、配置和管理 bean 的方式，如图 1 所示。</p>
		<p id="subtitle">
				<br />
				<br />
				<a name="fig1">
						<b>图 1. Spring 框架的 7 个模块</b>
				</a>
				<br />
				<img height="288" alt="Spring 框架图示" src="http://www.ibm.com/developerworks/cn/java/wa-spring1/spring_framework.gif" width="555" />
				<br />
		</p>
		<p>组成 Spring 框架的每个模块（或组件）都可以单独存在，或者与其他一个或多个模块联合实现。每个模块的功能如下： 
</p>
		<ul>
				<li>
						<b>核心容器</b>：核心容器提供 Spring 框架的基本功能。核心容器的主要组件是 <code>BeanFactory</code>，它是工厂模式的实现。<code>BeanFactory</code> 使用<i>控制反转</i> （IOC） 模式将应用程序的配置和依赖性规范与实际的应用程序代码分开。 
</li>
				<li>
						<b>Spring 上下文</b>：Spring 上下文是一个配置文件，向 Spring 框架提供上下文信息。Spring 上下文包括企业服务，例如 JNDI、EJB、电子邮件、国际化、校验和调度功能。 
</li>
				<li>
						<b>Spring AOP</b>：通过配置管理特性，Spring AOP 模块直接将面向方面的编程功能集成到了 Spring 框架中。所以，可以很容易地使 Spring 框架管理的任何对象支持 AOP。Spring AOP 模块为基于 Spring 的应用程序中的对象提供了事务管理服务。通过使用 Spring AOP，不用依赖 EJB 组件，就可以将声明性事务管理集成到应用程序中。 
</li>
				<li>
						<b>Spring DAO</b>：JDBC DAO 抽象层提供了有意义的异常层次结构，可用该结构来管理异常处理和不同数据库供应商抛出的错误消息。异常层次结构简化了错误处理，并且极大地降低了需要编写的异常代码数量（例如打开和关闭连接）。Spring DAO 的面向 JDBC 的异常遵从通用的 DAO 异常层次结构。 
</li>
				<li>
						<b>Spring ORM</b>：Spring 框架插入了若干个 ORM 框架，从而提供了 ORM 的对象关系工具，其中包括 JDO、Hibernate 和 iBatis SQL Map。所有这些都遵从 Spring 的通用事务和 DAO 异常层次结构。 
</li>
				<li>
						<b>Spring Web 模块</b>：Web 上下文模块建立在应用程序上下文模块之上，为基于 Web 的应用程序提供了上下文。所以，Spring 框架支持与 Jakarta Struts 的集成。Web 模块还简化了处理多部分请求以及将请求参数绑定到域对象的工作。 
</li>
				<li>
						<b>Spring MVC 框架</b>：MVC 框架是一个全功能的构建 Web 应用程序的 MVC 实现。通过策略接口，MVC 框架变成为高度可配置的，MVC 容纳了大量视图技术，其中包括 JSP、Velocity、Tiles、iText 和 POI。 </li>
		</ul>
		<p>
		</p>
		<p>Spring 框架的功能可以用在任何 J2EE 服务器中，大多数功能也适用于不受管理的环境。Spring 的核心要点是：支持不绑定到特定 J2EE 服务的可重用业务和数据访问对象。毫无疑问，这样的对象可以在不同 J2EE 环境 （Web 或 EJB）、独立应用程序、测试环境之间重用。 </p>
		<p id="subtitle">
				<br />
		</p>
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td>
										<img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" />
										<br />
										<img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" />
								</td>
						</tr>
				</tbody>
		</table>
		<table class="no-print" cellspacing="0" cellpadding="0" align="right">
				<tbody>
						<tr align="right">
								<td>
										<img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" />
										<br />
										<table cellspacing="0" cellpadding="0" border="0">
												<tbody>
														<tr>
																<td valign="center">
																		<img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" />
																		<br />
																</td>
																<td valign="top" align="right">
																		<a class="fbox" href="http://www.ibm.com/developerworks/cn/java/wa-spring1/?S_TACT=105AGX52&amp;S_CMP=techccid#main">
																				<b>
																						<font color="#5c81a7">回页首</font>
																				</b>
																		</a>
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<p>
				<a name="2">
						<span class="atitle">IOC 和 AOP</span>
				</a>
		</p>
		<p>控制反转模式（也称作依赖性介入）的基本概念是：不创建对象，但是描述创建它们的方式。在代码中不直接与对象和服务连接，但在配置文件中描述哪一个组件需要哪一项服务。容器 （在 Spring 框架中是 IOC 容器） 负责将这些联系在一起。</p>
		<p>在典型的 IOC 场景中，容器创建了所有对象，并设置必要的属性将它们连接在一起，决定什么时间调用方法。下表列出了 IOC 的一个实现模式。</p>
		<p id="subtitle">
		</p>
		<table cellspacing="4" cellpadding="2" width="80%" border="1">
				<tbody>
						<tr valign="top">
								<td>类型 1</td>
								<td>服务需要实现专门的接口，通过接口，由对象提供这些服务，可以从对象查询依赖性（例如，需要的附加服务）</td>
						</tr>
						<tr valign="top">
								<td>类型 2</td>
								<td>通过 JavaBean 的属性（例如 setter 方法）分配依赖性</td>
						</tr>
						<tr valign="top">
								<td>类型 3</td>
								<td>依赖性以构造函数的形式提供，不以 JavaBean 属性的形式公开</td>
						</tr>
				</tbody>
		</table>
		<p>Spring 框架的 IOC 容器采用类型 2 和类型3 实现。</p>
		<p>
				<a name="N10101">
						<span class="smalltitle">
								<strong>
										<font face="Arial">面向方面的编程</font>
								</strong>
						</span>
				</a>
		</p>
		<p>
				<i>面向方面的编程</i>，即 AOP，是一种编程技术，它允许程序员对横切关注点或横切典型的职责分界线的行为（例如日志和事务管理）进行模块化。AOP 的核心构造是<i>方面</i>，它将那些影响多个类的行为封装到可重用的模块中。</p>
		<p>AOP 和 IOC 是补充性的技术，它们都运用模块化方式解决企业应用程序开发中的复杂问题。在典型的面向对象开发方式中，可能要将日志记录语句放在所有方法和 Java 类中才能实现日志功能。在 AOP 方式中，可以反过来将日志服务<i>模块化</i>，并以声明的方式将它们应用到需要日志的组件上。当然，优势就是 Java 类不需要知道日志服务的存在，也不需要考虑相关的代码。所以，用 Spring AOP 编写的应用程序代码是松散耦合的。</p>
		<p>AOP 的功能完全集成到了 Spring 事务管理、日志和其他各种特性的上下文中。</p>
		<p id="subtitle">
				<br />
		</p>
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td>
										<img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" />
										<br />
										<img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" />
								</td>
						</tr>
				</tbody>
		</table>
		<table class="no-print" cellspacing="0" cellpadding="0" align="right">
				<tbody>
						<tr align="right">
								<td>
										<img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" />
										<br />
										<table cellspacing="0" cellpadding="0" border="0">
												<tbody>
														<tr>
																<td valign="center">
																		<img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" />
																		<br />
																</td>
																<td valign="top" align="right">
																		<a class="fbox" href="http://www.ibm.com/developerworks/cn/java/wa-spring1/?S_TACT=105AGX52&amp;S_CMP=techccid#main">
																				<b>
																						<font color="#5c81a7">回页首</font>
																				</b>
																		</a>
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<p>
				<a name="3">
						<span class="atitle">IOC 容器</span>
				</a>
		</p>
		<p>Spring 设计的核心是 <code>org.springframework.beans</code> 包，它的设计目标是与 JavaBean 组件一起使用。这个包通常不是由用户直接使用，而是由服务器将其用作其他多数功能的底层中介。下一个最高级抽象是 <code>BeanFactory</code> 接口，它是工厂设计模式的实现，允许通过名称创建和检索对象。<code>BeanFactory</code> 也可以管理对象之间的关系。</p>
		<p>
				<code>BeanFactory</code> 支持两个对象模型。</p>
		<ul>
				<li>
						<b>单态</b> 模型提供了具有特定名称的对象的共享实例，可以在查询时对其进行检索。Singleton 是默认的也是最常用的对象模型。对于无状态服务对象很理想。 
</li>
				<li>
						<b>原型</b> 模型确保每次检索都会创建单独的对象。在每个用户都需要自己的对象时，原型模型最适合。 </li>
		</ul>
		<p>bean 工厂的概念是 Spring 作为 IOC 容器的基础。IOC 将处理事情的责任从应用程序代码转移到框架。正如我将在下一个示例中演示的那样，Spring 框架使用 JavaBean 属性和配置数据来指出必须设置的依赖关系。</p>
		<p>
				<a name="N10149">
						<span class="smalltitle">
								<strong>
										<font face="Arial">BeanFactory 接口</font>
								</strong>
						</span>
				</a>
		</p>
		<p>因为 <code>org.springframework.beans.factory.BeanFactory</code> 是一个简单接口，所以可以针对各种底层存储方法实现。最常用的 <code>BeanFactory</code> 定义是 <code>XmlBeanFactory</code>，它根据 XML 文件中的定义装入 bean，如清单 1 所示。</p>
		<p id="subtitle">
				<br />
				<br />
				<a name="N1015F">
						<b>清单 1. XmlBeanFactory</b>
				</a>
				<br />
		</p>
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td class="code-outline">
										<pre class="displaycode">BeanFactory factory = new XMLBeanFactory(new FileInputSteam("mybean.xml"));
</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>在 XML 文件中定义的 Bean 是被消极加载的，这意味在需要 bean 之前，bean 本身不会被初始化。要从 <code>BeanFactory</code> 检索 bean，只需调用 <code>getBean()</code> 方法，传入将要检索的 bean 的名称即可，如清单 2 所示。</p>
		<p id="subtitle">
				<br />
				<br />
				<a name="N10175">
						<b>清单 2. getBean()</b>
				</a>
				<br />
		</p>
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td class="code-outline">
										<pre class="displaycode">MyBean mybean = (MyBean) factory.getBean("mybean");
</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>每个 bean 的定义都可以是 POJO （用类名和 JavaBean 初始化属性定义） 或 <code>FactoryBean</code>。<code>FactoryBean</code> 接口为使用 Spring 框架构建的应用程序添加了一个间接的级别。</p>
		<p id="subtitle">
				<br />
		</p>
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td>
										<img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" />
										<br />
										<img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" />
								</td>
						</tr>
				</tbody>
		</table>
		<table class="no-print" cellspacing="0" cellpadding="0" align="right">
				<tbody>
						<tr align="right">
								<td>
										<img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" />
										<br />
										<table cellspacing="0" cellpadding="0" border="0">
												<tbody>
														<tr>
																<td valign="center">
																		<img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" />
																		<br />
																</td>
																<td valign="top" align="right">
																		<a class="fbox" href="http://www.ibm.com/developerworks/cn/java/wa-spring1/?S_TACT=105AGX52&amp;S_CMP=techccid#main">
																				<b>
																						<font color="#5c81a7">回页首</font>
																				</b>
																		</a>
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<p>
				<a name="4">
						<span class="atitle">IOC 示例</span>
				</a>
		</p>
		<p>理解控制反转最简单的方式就是看它的实际应用。在对由三部分组成的 <i>Spring 系列</i> 的第 1 部分进行总结时，我使用了一个示例，演示了如何通过 Spring IOC 容器注入应用程序的依赖关系（而不是将它们构建进来）。</p>
		<p>我用开启在线信用帐户的用例作为起点。对于该实现，开启信用帐户要求用户与以下服务进行交互： 
</p>
		<ul>
				<li>信用级别评定服务，查询用户的信用历史信息。 
</li>
				<li>远程信息链接服务，插入客户信息，将客户信息与信用卡和银行信息连接起来，以进行自动借记（如果需要的话）。 
</li>
				<li>电子邮件服务，向用户发送有关信用卡状态的电子邮件。 </li>
		</ul>
		<p>
		</p>
		<p id="subtitle">
				<br />
		</p>
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td>
										<img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" />
										<br />
										<img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" />
								</td>
						</tr>
				</tbody>
		</table>
		<table class="no-print" cellspacing="0" cellpadding="0" align="right">
				<tbody>
						<tr align="right">
								<td>
										<img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" />
										<br />
										<table cellspacing="0" cellpadding="0" border="0">
												<tbody>
														<tr>
																<td valign="center">
																		<img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" />
																		<br />
																</td>
																<td valign="top" align="right">
																		<a class="fbox" href="http://www.ibm.com/developerworks/cn/java/wa-spring1/?S_TACT=105AGX52&amp;S_CMP=techccid#main">
																				<b>
																						<font color="#5c81a7">回页首</font>
																				</b>
																		</a>
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<p>
				<a name="5">
						<span class="atitle">三个接口</span>
				</a>
		</p>
		<p>对于这个示例，我假设服务已经存在，理想的情况是用松散耦合的方式把它们集成在一起。以下清单显示了三个服务的应用程序接口。</p>
		<p id="subtitle">
				<br />
				<br />
				<a name="N101B1">
						<b>清单 3. CreditRatingInterface</b>
				</a>
				<br />
		</p>
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td class="code-outline">
										<pre class="displaycode">public interface CreditRatingInterface {
   public boolean getUserCreditHistoryInformation(ICustomer iCustomer);
}
</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>清单 3 所示的信用级别评定接口提供了信用历史信息。它需要一个包含客户信息的 <code>Customer</code> 对象。该接口的实现是由 <code>CreditRating</code> 类提供的。</p>
		<p id="subtitle">
				<br />
				<br />
				<a name="N101C7">
						<b>清单 4. CreditLinkingInterface</b>
				</a>
				<br />
		</p>
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td class="code-outline">
										<pre class="displaycode">public interface CreditLinkingInterface {
public String getUrl();
		public void setUrl(String url);
		public void linkCreditBankAccount() throws Exception ;
}
</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>信用链接接口将信用历史信息与银行信息（如果需要的话）连接在一起，并插入用户的信用卡信息。信用链接接口是一个远程服务，它的查询是通过 <code>getUrl()</code> 方法进行的。URL 由 Spring 框架的 bean 配置机制设置，我稍后会讨论它。该接口的实现是由 <code>CreditLinking</code> 类提供的。</p>
		<p id="subtitle">
				<br />
				<br />
				<a name="N101DD">
						<b>清单 5. EmailInterface</b>
				</a>
				<br />
		</p>
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td class="code-outline">
										<pre class="displaycode">public interface EmailInterface {
      public void sendEmail(ICustomer iCustomer);
      public String getFromEmail();
      public void setFromEmail(String fromEmail) ;
      public String getPassword();
      public void setPassword(String password) ;
      public String getSmtpHost() ;
      public void setSmtpHost(String smtpHost);
      public String getUserId() ;
      public void setUserId(String userId);
   }
</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>
				<code>EmailInterface</code> 负责向客户发送关于客户信用卡状态的电子邮件。邮件配置参数（例如 SMPT 主机、用户名、口令）由前面提到的 bean 配置机制设置。<code>Email</code> 类提供了该接口的实现。</p>
		<p id="subtitle">
				<br />
		</p>
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td>
										<img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" />
										<br />
										<img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" />
								</td>
						</tr>
				</tbody>
		</table>
		<table class="no-print" cellspacing="0" cellpadding="0" align="right">
				<tbody>
						<tr align="right">
								<td>
										<img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" />
										<br />
										<table cellspacing="0" cellpadding="0" border="0">
												<tbody>
														<tr>
																<td valign="center">
																		<img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" />
																		<br />
																</td>
																<td valign="top" align="right">
																		<a class="fbox" href="http://www.ibm.com/developerworks/cn/java/wa-spring1/?S_TACT=105AGX52&amp;S_CMP=techccid#main">
																				<b>
																						<font color="#5c81a7">回页首</font>
																				</b>
																		</a>
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<p>
				<a name="6">
						<span class="atitle">Spring 使其保持松散</span>
				</a>
		</p>
		<p>这些接口就位之后，接下来要考虑的就是如何用松散耦合方式将它们集成在一起。在 <a href="http://www.ibm.com/developerworks/cn/java/wa-spring1/listing1.html"><font color="#5c81a7">清单 6</font></a> 中可以看到信用卡帐户用例的实现。</p>
		<p>注意，所有的 setter 方法都是由 Spring 的配置 bean 实现的。所有的依赖关系 （也就是三个接口）都可以由 Spring 框架用这些 bean 注入。<code>createCreditCardAccount()</code> 方法会用服务去执行其余实现。在 <a href="http://www.ibm.com/developerworks/cn/java/wa-spring1/listing2.html"><font color="#5c81a7">清单 7 </font></a>中可以看到 Spring 的配置文件。我用箭头突出了这些定义。 </p>
		<p id="subtitle">
				<br />
		</p>
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td>
										<img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" />
										<br />
										<img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" />
								</td>
						</tr>
				</tbody>
		</table>
		<table class="no-print" cellspacing="0" cellpadding="0" align="right">
				<tbody>
						<tr align="right">
								<td>
										<img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" />
										<br />
										<table cellspacing="0" cellpadding="0" border="0">
												<tbody>
														<tr>
																<td valign="center">
																		<img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" />
																		<br />
																</td>
																<td valign="top" align="right">
																		<a class="fbox" href="http://www.ibm.com/developerworks/cn/java/wa-spring1/?S_TACT=105AGX52&amp;S_CMP=techccid#main">
																				<b>
																						<font color="#5c81a7">回页首</font>
																				</b>
																		</a>
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<p>
				<a name="7">
						<span class="atitle">运行应用程序</span>
				</a>
		</p>
		<p>要运行示例应用程序，首先必须 <a href="http://prdownloads.sourceforge.net/" target="_new"><font color="#5c81a7">下载 Spring 框架</font></a> 及其所有依赖文件。接下来，将框架释放到（比如说）磁盘 <i>c:\</i>，这会创建 <i>C:\spring-framework-1.2-rc2</i> （适用于当前发行版本） 这样的文件夹。在继续后面的操作之前，还必须下载和释放 <a href="http://ant.apache.org/" target="_new"><font color="#5c81a7">Apache Ant</font></a>。</p>
		<p>接下来，将源代码释放到文件夹，例如 <i>c:\</i> 盘，然后创建 <i>SpringProject</i>。将 Spring 库（即 <i>C:\spring-framework-1.2-rc2\dist</i> 下的 <i>spring.jar</i> 和 <i>C:\spring-framework-1.2-rc2\lib\jakarta-commons</i> 下的 <i>commons-logging.jar</i>）复制到 <i>SpringProject\lib</i> 文件夹中。完成这些工作之后，就有了必需的构建依赖关系集。</p>
		<p>打开命令提示符，将当前目录切换到 <i>SpringProject</i>，在命令提示符中输入以下命令：<code>build</code>。 </p>
		<p>这会构建并运行 <code>CreateCreditAccountClient</code> 类，类的运行将创建 <code>Customer</code> 类对象并填充它，还会调用 <code>CreateCreditCardAccount</code> 类创建并链接信用卡帐户。<code>CreateCreditAccountClient</code> 还会通过 <code>ClassPathXmlApplicationContext</code> 装入 Spring 配置文件。装入 bean 之后，就可以通过 <code>getBean()</code> 方法访问它们了，如清单 8 所示。</p>
		<p id="subtitle">
				<br />
				<br />
				<a name="code8">
						<b>清单 8. 装入 Spring 配置文件</b>
				</a>
				<br />
		</p>
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td class="code-outline">
										<pre class="displaycode">ClassPathXmlApplicationContext appContext = 
                    new ClassPathXmlApplicationContext(new String[] {
     "springexample-creditaccount.xml"
    });
CreateCreditCardAccountInterface creditCardAccount = 
                    (CreateCreditCardAccountInterface)
	appContext.getBean("createCreditCard");
</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td>
										<img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" />
										<br />
										<img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" />
								</td>
						</tr>
				</tbody>
		</table>
		<table class="no-print" cellspacing="0" cellpadding="0" align="right">
				<tbody>
						<tr align="right">
								<td>
										<img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" />
										<br />
										<table cellspacing="0" cellpadding="0" border="0">
												<tbody>
														<tr>
																<td valign="center">
																		<img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" />
																		<br />
																</td>
																<td valign="top" align="right">
																		<a class="fbox" href="http://www.ibm.com/developerworks/cn/java/wa-spring1/?S_TACT=105AGX52&amp;S_CMP=techccid#main">
																				<b>
																						<font color="#5c81a7">回页首</font>
																				</b>
																		</a>
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<p>
				<a name="8">
						<span class="atitle">结束语</span>
				</a>
		</p>
		<p>在这篇由三部分组成的 <i>Spring 系列</i> 的第一篇文章中，我介绍了 Spring 框架的基础。我从讨论组成 Spring 分层架构的 7 个模块开始，然后深入介绍了其中两个模块：Spring AOP 和 IOC 容器。</p>
		<p>由于学习的最佳方法是实践，所以我用一个工作示例介绍了 IOC 模式 （像 Spring 的 IOC 容器实现的那样）如何用松散耦合的方式将分散的系统集成在一起。在这个示例中可以看到，将依赖关系或服务注入工作中的信用卡帐户应用程序，要比从头开始构建它们容易得多。</p>
		<p>请继续关注这一系列的下一篇文章，我将在这里学习的知识基础上，介绍 Spring AOP 模块如何在企业应用程序中提供持久支持，并让您开始了解 Spring MVC 模块和相关插件。 </p>
		<p id="subtitle">
				<br />
				<br />
		</p>
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td>
										<img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" />
										<br />
										<img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" />
								</td>
						</tr>
				</tbody>
		</table>
		<table class="no-print" cellspacing="0" cellpadding="0" align="right">
				<tbody>
						<tr align="right">
								<td>
										<img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" />
										<br />
										<table cellspacing="0" cellpadding="0" border="0">
												<tbody>
														<tr>
																<td valign="center">
																		<img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" />
																		<br />
																</td>
																<td valign="top" align="right">
																		<a class="fbox" href="http://www.ibm.com/developerworks/cn/java/wa-spring1/?S_TACT=105AGX52&amp;S_CMP=techccid#main">
																				<b>
																						<font color="#5c81a7">回页首</font>
																				</b>
																		</a>
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<p>
				<span class="atitle">
						<a name="download">下载</a>
				</span>
		</p>
		<p id="subtitle">
		</p>
		<table class="data-table-1" cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<th scope="col">描述</th>
								<th scope="col">名字</th>
								<th scope="col" align="right">大小</th>
								<th scope="col">下载方法</th>
						</tr>
						<tr>
								<th class="tb-row" scope="row">Examples: source code, spring files, build scripts</th>
								<td nowrap="">wa-spring1-SpringProject.zip</td>
								<td nowrap="" align="right">9 KB</td>
								<td nowrap=""> <a class="fbox" href="ftp://www6.software.ibm.com/software/developer/library/wa-spring1-SpringProject.zip"><b><font color="#5c81a7">FTP</font></b></a></td>
						</tr>
				</tbody>
		</table>
		<table cellspacing="0" cellpadding="0" border="0">
				<tbody>
						<tr valign="top">
								<td colspan="5">
										<font color="#5c81a7">
												<img height="12" alt="" src="http://www.ibm.com/i/c.gif" width="12" border="0" />
										</font>
								</td>
						</tr>
						<tr>
								<td>
										<font color="#5c81a7">
												<img height="16" alt="" src="http://www.ibm.com/i/v14/icons/fw.gif" width="16" />
										</font>
								</td>
								<td>
										<a class="fbox" href="http://www.ibm.com/developerworks/cn/whichmethod.html">
												<font color="#5c81a7">关于下载方法的信息</font>
										</a>
								</td>
								<td>
										<font color="#5c81a7">
												<img height="1" alt="" src="http://www.ibm.com/i/c.gif" width="50" />
										</font>
								</td>
								<td>
										<font color="#5c81a7">
												<img height="16" alt="" src="http://www.ibm.com/i/v14/icons/sout.gif" width="16" />
										</font>
								</td>
								<td>
										<a class="fbox" href="http://www.adobe.com/products/acrobat/readstep2.html">
												<font color="#5c81a7">Get Adobe® Reader®</font>
										</a>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<p>
				<a name="resources">
						<span class="atitle">参考资料 </span>
				</a>
		</p>
		<ul>
				<li>您可以参阅本文在 developerWorks 全球站点上的 <a href="http://www.ibm.com/developerworks/web/library/wa-spring1/?S_TACT=105AGX52&amp;S_CMP=cn-a-j" target="_blank"><font color="#5c81a7">英文原文</font></a> 。<br /><br /></li>
				<li>虽然 Spring AOP 提供了独特的优势，但它并不是惟一的 AOP 实现。请参阅“<a href="http://www.ibm.com/developerworks/cn/java/j-aopwork1/"><font color="#5c81a7">AOP@Work: AOP 工具比较，第 1 部分</font></a>”（<i>developerWorks</i>，2005 年 2 月），了解 Spring AOP 的构成。<br /><br /></li>
				<li>通过“<a href="http://www.ibm.com/developerworks/cn/java/j-hibern/"><font color="#5c81a7">无需容器的对象关系映射</font></a>”（<i>developerWorks</i>，2004 年 4 月）学习如何用 Hibernate 和 Spring AOP 开发事务性的持久层（persistence layer）。<br /><br /></li>
				<li>请从 <a href="http://prdownloads.sourceforge.net/springframework/"><font color="#5c81a7">Spring homepage</font></a> 下载 Spring 框架。<br /><br /></li>
				<li>请从 <a href="http://ant.apache.org/"><font color="#5c81a7">Ant homepage</font></a> 下载 Apache Ant。<br /><br /></li>
				<li>通过参与 <a href="http://www.ibm.com/developerworks/blogs/?S_TACT=105AGX52&amp;S_CMP=cn-a-j"><font color="#5c81a7">developerWorks blogs</font></a> 加入 developerWorks 社区。<br /><br /></li>
				<li>还请参阅 <i>developerWorks</i> 上的一些丰富的参考资料： 
<ul><li><a href="http://www.ibm.com/developerworks/web/?S_TACT=105AGX52&amp;S_CMP=cn-a-j"><font color="#5c81a7">Web 架构专区</font></a> 中的文章专门介绍了各种基于 Web 的解决方案。 
</li><li><a href="http://devworks.krcinfo.com/"><font color="#5c81a7">Developer Bookstore</font></a> 提供了技术书籍的完整清单，其中包括数百本 Web 相关主题的书籍。 </li></ul><br /></li>
		</ul>
		<p id="subtitle">
				<br />
				<br />
		</p>
		<p>
				<a name="author">
						<span class="atitle">关于作者</span>
				</a>
		</p>
		<p id="subtitle">
		</p>
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td colspan="3">
										<img height="5" alt="" src="http://www.ibm.com/i/c.gif" width="100%" />
								</td>
						</tr>
						<tr valign="top" align="left">
								<td>
										<p>
										</p>
								</td>
								<td>
										<img height="5" alt="" src="http://www.ibm.com/i/c.gif" width="4" />
								</td>
								<td width="100%">
										<p>Naveen Balani 把他的大多数时间都花在了设计和开发基于 J2EE 的框架和产品上。他为 IBM <i>developerWorks</i> 撰写了各种不同的文章，涉及的主题包括：ESB、SOA、JMS、WebServices Architectures、CICS、AXIS、DB2 XML Extender、WebSphere Studio、MQSeries 和 Java Wireless Devices，以及 DB2 Everyplace for Palm、J2ME、MIDP、Java-Nokia、Visual Studio .Net 和无线数据同步。您可以通过 <a href="mailto:naveenbalani@rediffmail.com?cc=htc@us.ibm.com"><font color="#5c81a7">naveenbalani@rediffmail.com</font></a> 与他联系。 </p>
								</td>
						</tr>
				</tbody>
		</table><img src ="http://www.cnitblog.com/tilan/aggbug/22671.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/tilan/" target="_blank">Joinclass Inc</a> 2007-02-05 11:37 <a href="http://www.cnitblog.com/tilan/archive/2007/02/05/22671.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>用 hibernate 和 xdoclet 开发 数据库应用程序</title><link>http://www.cnitblog.com/tilan/archive/2007/01/24/22277.html</link><dc:creator>Joinclass Inc</dc:creator><author>Joinclass Inc</author><pubDate>Wed, 24 Jan 2007 10:03:00 GMT</pubDate><guid>http://www.cnitblog.com/tilan/archive/2007/01/24/22277.html</guid><wfw:comment>http://www.cnitblog.com/tilan/comments/22277.html</wfw:comment><comments>http://www.cnitblog.com/tilan/archive/2007/01/24/22277.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cnitblog.com/tilan/comments/commentRss/22277.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/tilan/services/trackbacks/22277.html</trackback:ping><description><![CDATA[前两天 xdoclet 发布了版本 1.2b3，里面包含了 hibernate 的自动生成 mapping file 的 module  <br />今天试了试，居然成功了，很有意思。  <br /><br /><br /><br />用 hibernate 和 xdoclet 开发的流程如下：  <br /><br />  1.写 Persistent class，并在 源程序里写上一些 hibernate 的 tag  <br /><br />  2.用 xdoclet 根据 Persistent class 里的 tag 自动生成 mapping file  <br /><br />  3.用 Hibernate 提供的 SchemaExport 类生成 数据库建表的 ddl  <br /><br />然后就不用考虑数据库的细节啦，哈哈。 <br /><br />中文的一篇文档： <br /><br />值得关注的持久化技术： hibernate  <br />http://www.huihoo.com/java/hibernate/ <br /><br /><br />这里有老外写的详细的文档，介绍 hibernate 和 xdoclet ，里面也包含了代码下载：  <br />  http://www.meagle.com:8080/hibernate.jsp   <br /><br /><br />我自己学习过程中也写了一个 demo，用 ant 运行，来我的 ftp 下载：  <br /><br />  ftp://cinc.3322.org/pub/doc/code/hibernate/  <br /><br />    hibernatedemo_20030622.zip          是没用 xdoclet 的例子  <br />    hibernate_xdoclet_demo_20030614.zip 是使用 xdoclet 的例子  <br />    HibernateExamplesMeagle.zip         Meagle 那个网站的例子  <br /><br /><br />hibernate: <br />http://sourceforge.net/projects/hibernate/ <br /><br />xdoclet: <br />http://sourceforge.net/projects/xdoclet/<br /><br /><img src ="http://www.cnitblog.com/tilan/aggbug/22277.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/tilan/" target="_blank">Joinclass Inc</a> 2007-01-24 18:03 <a href="http://www.cnitblog.com/tilan/archive/2007/01/24/22277.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>每日构建+单元测试</title><link>http://www.cnitblog.com/tilan/archive/2007/01/16/21911.html</link><dc:creator>Joinclass Inc</dc:creator><author>Joinclass Inc</author><pubDate>Tue, 16 Jan 2007 03:18:00 GMT</pubDate><guid>http://www.cnitblog.com/tilan/archive/2007/01/16/21911.html</guid><wfw:comment>http://www.cnitblog.com/tilan/comments/21911.html</wfw:comment><comments>http://www.cnitblog.com/tilan/archive/2007/01/16/21911.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cnitblog.com/tilan/comments/commentRss/21911.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/tilan/services/trackbacks/21911.html</trackback:ping><description><![CDATA[<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
				<b>
						<span lang="EN-US" style="FONT-SIZE: 12pt">1.</span>
				</b>
				<b>
						<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">每日构建（</span>
				</b>
				<b>
						<span lang="EN-US" style="FONT-SIZE: 12pt">Daily Build</span>
				</b>
				<b>
						<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">）</span>
				</b>
				<b>
						<span lang="EN-US" style="FONT-SIZE: 12pt">
								<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /?>
								<o:p>
								</o:p>
						</span>
				</b>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 24pt; mso-char-indent-count: 2.0; mso-char-indent-size: 12.0pt">
				<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">在项目中使用每日构建（</span>
				<span lang="EN-US" style="FONT-SIZE: 12pt">Daily Build</span>
				<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">）是为了实现“持续集成”。传统构建只发生在项目发布前夕很短的一段时间，压力和风险不小。每日构建一定程度上缓解了这种压力，削平了曲线。好东西！但每日构建也需项目组的投入，学习和使用</span>
				<span lang="EN-US" style="FONT-SIZE: 12pt">Ant</span>
				<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">（或</span>
				<span lang="EN-US" style="FONT-SIZE: 12pt">Nant</span>
				<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">）就是一个不错的办法。</span>
				<span lang="EN-US" style="FONT-SIZE: 12pt">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 24pt; mso-char-indent-count: 2.0; mso-char-indent-size: 12.0pt">
				<span lang="EN-US" style="FONT-SIZE: 12pt"> <o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
				<b>
						<span lang="EN-US" style="FONT-SIZE: 12pt">2.</span>
				</b>
				<b>
						<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">单元测试（</span>
				</b>
				<b>
						<span lang="EN-US" style="FONT-SIZE: 12pt">Unit Test</span>
				</b>
				<b>
						<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">）</span>
				</b>
				<b>
						<span lang="EN-US" style="FONT-SIZE: 12pt">
								<o:p>
								</o:p>
						</span>
				</b>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 24pt; mso-char-indent-count: 2.0; mso-char-indent-size: 12.0pt">
				<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">在项目中使用单元测试（</span>
				<span lang="EN-US" style="FONT-SIZE: 12pt">Unit Test</span>
				<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">）和每日构建在思想上有相似之处，在实践中又交相呼应。单元测试可以确保每个软件项目最小逻辑部件的正确性。在耦合始终存在的情况下，单元测试的作用其实也被放大了，对某个逻辑部件的测试自然也包括了对所引用其他部件的测试（虽然这并不是单元测试的初衷）。单元测试不是最重要的，但的确是非常重要的和必须的。单元测试也需要项目组的投入，编写单元测试用例是起码的，学习和使用</span>
				<span lang="EN-US" style="FONT-SIZE: 12pt">JUnit</span>
				<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">（或</span>
				<span lang="EN-US" style="FONT-SIZE: 12pt">Nunit</span>
				<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">）能帮上不小的忙。</span>
				<span lang="EN-US" style="FONT-SIZE: 12pt">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 24pt; mso-char-indent-count: 2.0; mso-char-indent-size: 12.0pt">
				<span lang="EN-US" style="FONT-SIZE: 12pt"> <o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
				<b>
						<span lang="EN-US" style="FONT-SIZE: 12pt">3.</span>
				</b>
				<b>
						<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">结合起来（</span>
				</b>
				<b>
						<span lang="EN-US" style="FONT-SIZE: 12pt">Do Them All</span>
				</b>
				<b>
						<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">）</span>
				</b>
				<b>
						<span lang="EN-US" style="FONT-SIZE: 12pt">
								<o:p>
								</o:p>
						</span>
				</b>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 24pt; mso-char-indent-count: 2.0; mso-char-indent-size: 12.0pt">
				<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">单元测试的最佳实施者是每个开发人员自己，也可以采用同行测试（</span>
				<span lang="EN-US" style="FONT-SIZE: 12pt">Buddy Test</span>
				<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">）。他们阅读设计文档，编写单元测试用例、编写逻辑部件，然后把逻辑部件放到测试用例中测试，测试通过就继续往前走。单元测试的发起者是项目组中单个的开发者时，会使得单元测试此起彼伏，但问题是有些单元测试有很多都是无效的。原因很简单，因为不同开发者编写的逻辑部件之间的耦合只要存在，这样的单元测试就是无效的。参考《<a href="http://www.dearbook.com.cn/book/viewbook.aspx?pno=TS0022573">软件配置管理模式</a>》一书中关于“活动开发线”模式的讲述：当在项目的一条码线（</span>
				<span lang="EN-US" style="FONT-SIZE: 12pt">Code Line</span>
				<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">）上，测试与开发在时间上同存时，测试都是无效的，单元测试也不例外。</span>
				<span lang="EN-US" style="FONT-SIZE: 12pt">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 24pt; mso-char-indent-count: 2.0; mso-char-indent-size: 12.0pt">
				<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">也许在开发者自行单元测试的同时，我们还应该定时的让所有的开发者都停下来，提交他们的代码，然后一起来进行单元测试。其实这不难，每天下班的时候他们都会自动的停下来，如果项目的配置管理还算可以的话，他们也都会在下班前提交代码，然后让我们来运行单元测试吧。</span>
				<span lang="EN-US" style="FONT-SIZE: 12pt">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 24pt; mso-char-indent-count: 2.0; mso-char-indent-size: 12.0pt">
				<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">我们用</span>
				<span lang="EN-US" style="FONT-SIZE: 12pt">Ant</span>
				<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">来进行每日构建。同样，我们也可以让</span>
				<span lang="EN-US" style="FONT-SIZE: 12pt">Ant+JUnit</span>
				<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">帮助我们进行每日单元测试（</span>
				<span lang="EN-US" style="FONT-SIZE: 12pt">Daily Test</span>
				<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">？）。每次听微软的讲师讲</span>
				<span lang="EN-US" style="FONT-SIZE: 12pt">MSF</span>
				<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，都要讲他们的开发是深夜</span>
				<span lang="EN-US" style="FONT-SIZE: 12pt">12:00</span>
				<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">开始的，也就是“自动构建</span>
				<span lang="EN-US" style="FONT-SIZE: 12pt">+</span>
				<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">自动测试”，第二天早上，开发组的人拿到自动生成的报告，该</span>
				<span lang="EN-US" style="FONT-SIZE: 12pt">code</span>
				<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的就</span>
				<span lang="EN-US" style="FONT-SIZE: 12pt">code</span>
				<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，该</span>
				<span lang="EN-US" style="FONT-SIZE: 12pt">debug</span>
				<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的就</span>
				<span lang="EN-US" style="FONT-SIZE: 12pt">debug</span>
				<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">。（其实，这也就是一种测试驱动开发：</span>
				<span lang="EN-US" style="FONT-SIZE: 12pt">Test-Driven Development</span>
				<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，又一个很多人争议的软件方法。）这不难，是看公司要不要这么做。</span>
				<span lang="EN-US" style="FONT-SIZE: 12pt">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 24pt; mso-char-indent-count: 2.0; mso-char-indent-size: 12.0pt">
				<span lang="EN-US" style="FONT-SIZE: 12pt"> <o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
				<b>
						<span lang="EN-US" style="FONT-SIZE: 12pt">4.</span>
				</b>
				<b>
						<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">实践（</span>
				</b>
				<b>
						<span lang="EN-US" style="FONT-SIZE: 12pt">Practice</span>
				</b>
				<b>
						<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">）</span>
				</b>
				<b>
						<span lang="EN-US" style="FONT-SIZE: 12pt">
								<o:p>
								</o:p>
						</span>
				</b>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 24pt; mso-char-indent-count: 2.0; mso-char-indent-size: 12.0pt">
				<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">关于使用</span>
				<span lang="EN-US" style="FONT-SIZE: 12pt">Ant</span>
				<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">实现每日构建的请看陋文：“<a href="http://blog.csdn.net/beegee/archive/2004/07/01/31761.aspx">一个轻巧的每日构建解决方案</a>”。</span>
				<span lang="EN-US" style="FONT-SIZE: 12pt">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 24pt; mso-char-indent-count: 2.0; mso-char-indent-size: 12.0pt">
				<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">在此基础上，在</span>
				<span lang="EN-US" style="FONT-SIZE: 12pt">Ant</span>
				<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的“</span>
				<span lang="EN-US" style="FONT-SIZE: 12pt">build.xml</span>
				<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">”中加入单元测试任务即可，同时也可以生成单元测试报告。甚至可以将单元测试结果报告通过</span>
				<span lang="EN-US" style="FONT-SIZE: 12pt">email</span>
				<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">发送给开发组成员。</span>
				<span lang="EN-US" style="FONT-SIZE: 12pt">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 24pt; mso-char-indent-count: 2.0; mso-char-indent-size: 12.0pt">
				<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">先请出国内外的几篇好文：</span>
				<span lang="EN-US" style="FONT-SIZE: 12pt">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 24pt; TEXT-ALIGN: left; mso-char-indent-count: 2.0; mso-char-indent-size: 12.0pt" align="left">
				<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">“<a href="http://www-900.ibm.com/developerWorks/cn/java/j-junitmail/">让编译和测试过程自动化</a>”</span>
				<span lang="EN-US" style="FONT-SIZE: 12pt">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 24pt; TEXT-ALIGN: left; mso-char-indent-count: 2.0; mso-char-indent-size: 12.0pt" align="left">
				<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">“<a href="http://www-900.ibm.com/developerWorks/cn/java/j-ant/index.shtml">利用</a></span>
				<a href="http://www-900.ibm.com/developerWorks/cn/java/j-ant/index.shtml">
						<span lang="EN-US" style="FONT-SIZE: 12pt">Ant</span>
						<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">和</span>
						<span lang="EN-US" style="FONT-SIZE: 12pt">JUnit</span>
				</a>
				<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">
						<a href="http://www-900.ibm.com/developerWorks/cn/java/j-ant/index.shtml">进行增量开发</a>”</span>
				<span lang="EN-US" style="FONT-SIZE: 12pt">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 24pt; mso-char-indent-count: 2.0; mso-char-indent-size: 12.0pt">
				<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">“<a href="http://www.infomall.cn/cgi-bin/mallgate/20040514/http://hedong.3322.org/archives/000427.html">每日创建之自动测试</a>”</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 24pt; mso-char-indent-count: 2.0; mso-char-indent-size: 12.0pt">
				<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">到今天（</span>
				<span lang="EN-US" style="FONT-SIZE: 12pt">2004-08-20</span>
				<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">）为止，在</span>
				<span lang="EN-US" style="FONT-SIZE: 12pt">Google</span>
				<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">上面以“</span>
				<span lang="EN-US" style="FONT-SIZE: 12pt">ant+junit</span>
				<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">”可以搜出</span>
				<span lang="EN-US" style="FONT-SIZE: 12pt">127000</span>
				<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">条记录，大家都做得很好。但上面</span>
				<span lang="EN-US" style="FONT-SIZE: 12pt">3</span>
				<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">篇的确已经足够帮助还未实作的人快速的实现“每日构建</span>
				<span lang="EN-US" style="FONT-SIZE: 12pt">+</span>
				<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">单元测试”了。</span>
				<span lang="EN-US" style="FONT-SIZE: 12pt">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 24pt; mso-char-indent-count: 2.0; mso-char-indent-size: 12.0pt">
				<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">关于实践他们都说得很清楚，我也是在看了这些文档后完成实践的。我在自己的</span>
				<span lang="EN-US" style="FONT-SIZE: 12pt">Blog</span>
				<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">上加点自己的东西吧，也就是在实现“每日构建</span>
				<span lang="EN-US" style="FONT-SIZE: 12pt">+</span>
				<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">单元测试”时的小贴士。</span>
				<span lang="EN-US" style="FONT-SIZE: 12pt">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 24.1pt; mso-char-indent-count: 2.0; mso-char-indent-size: 12.05pt">
				<b>
						<span lang="EN-US" style="FONT-SIZE: 12pt">1)</span>
				</b>
				<b>
						<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">环境配置之&lt;mail&gt;<mail /></span>
				</b>
				<b>
						<span lang="EN-US" style="FONT-SIZE: 12pt">
								<mail>
								</mail>
						</span>
				</b>
				<b>
						<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">：</span>
				</b>
				<b>
						<span lang="EN-US" style="FONT-SIZE: 12pt">
								<o:p>
								</o:p>
						</span>
				</b>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 24pt; mso-char-indent-count: 2.0; mso-char-indent-size: 12.0pt">
				<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">“让编译和测试过程自动化”一文的作者</span>
				<span lang="EN-US" style="FONT-SIZE: 12pt">Erik Hatcher</span>
				<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">也是</span>
				<span lang="EN-US" style="FONT-SIZE: 12pt">Ant</span>
				<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的开发者之一。但此文有些早了，文中所提到的</span>
				<span lang="EN-US" style="FONT-SIZE: 12pt">Ant</span>
				<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的&lt;mimemail&gt;</span>
				<span lang="EN-US" style="FONT-SIZE: 12pt">
						<mimemail>
						</mimemail>
				</span>
				<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">已经合并到&lt;mail&gt;</span>
				<span lang="EN-US" style="FONT-SIZE: 12pt">
						<mail>
						</mail>
				</span>
				<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">中，&lt;mimemail&gt;</span>
				<span lang="EN-US" style="FONT-SIZE: 12pt">
						<mimemail>
						</mimemail>
				</span>
				<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">已经废置不用了。&lt;mail&gt;</span>
				<mail>
						<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">任务依赖于</span>
						<span lang="EN-US" style="FONT-SIZE: 12pt">
								<a href="http://java.sun.com/products/javamail/index.html">JavaMail</a>
						</span>
						<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">和</span>
						<span lang="EN-US" style="FONT-SIZE: 12pt">
								<a href="http://java.sun.com/products/javabeans/glasgow/jaf.html">JAF</a>
						</span>
						<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，如果没有用过的话，请到</span>
						<span lang="EN-US" style="FONT-SIZE: 12pt">SUN</span>
						<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">公司的网站上下载，并在下载后完成以下配置（以我的目录结构为例）：</span>
						<span lang="EN-US" style="FONT-SIZE: 12pt">
								<o:p>
								</o:p>
						</span>
				</mail>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 24pt; mso-char-indent-count: 2.0; mso-char-indent-size: 12.0pt">
				<font color="#000080">
						<span lang="EN-US" style="FONT-SIZE: 12pt">CLASSPATH</span>
						<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">：</span>
						<span lang="EN-US" style="FONT-SIZE: 12pt">
								<o:p>
								</o:p>
						</span>
				</font>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 24pt; mso-char-indent-count: 2.0; mso-char-indent-size: 12.0pt">
				<span lang="EN-US" style="FONT-SIZE: 12pt">
						<font color="#000080">C:\javamail-1.3.2ea\mail.jar;<o:p></o:p></font>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 24pt; mso-char-indent-count: 2.0; mso-char-indent-size: 12.0pt">
				<span lang="EN-US" style="FONT-SIZE: 12pt">
						<font color="#000080">C:\javamail-1.3.2ea\lib\mailapi.jar;<o:p></o:p></font>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 24pt; mso-char-indent-count: 2.0; mso-char-indent-size: 12.0pt">
				<span lang="EN-US" style="FONT-SIZE: 12pt">
						<font color="#000080">C:\javamail-1.3.2ea\lib\pop3.jar;<o:p></o:p></font>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 24pt; mso-char-indent-count: 2.0; mso-char-indent-size: 12.0pt">
				<span lang="EN-US" style="FONT-SIZE: 12pt">
						<font color="#000080">C:\javamail-1.3.2ea\lib\smtp.jar;<o:p></o:p></font>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 24pt; mso-char-indent-count: 2.0; mso-char-indent-size: 12.0pt">
				<span lang="EN-US" style="FONT-SIZE: 12pt">
						<font color="#000080">C:\jaf-1.0.2\activation.jar;<o:p></o:p></font>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 24pt; mso-char-indent-count: 2.0; mso-char-indent-size: 12.0pt">
				<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">这样才能保证</span>
				<span lang="EN-US" style="FONT-SIZE: 12pt">Ant</span>
				<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">以</span>
				<span lang="EN-US" style="FONT-SIZE: 12pt">email</span>
				<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">发送构建和测试报告时的正确。</span>
				<span lang="EN-US" style="FONT-SIZE: 12pt">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 24.1pt; mso-char-indent-count: 2.0; mso-char-indent-size: 12.05pt">
				<b>
						<span lang="EN-US" style="FONT-SIZE: 12pt">2)</span>
				</b>
				<b>
						<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">环境配置之&lt;junit&gt;&lt;junitreport&gt;</span>
				</b>
				<b>
						<span lang="EN-US" style="FONT-SIZE: 12pt">
								<junit>
										<junitreport>
										</junitreport>
								</junit>
						</span>
				</b>
				<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">：</span>
				<span lang="EN-US" style="FONT-SIZE: 12pt">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 24pt; mso-char-indent-count: 2.0; mso-char-indent-size: 12.0pt">
				<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">如果项目组在白天用的是</span>
				<span lang="EN-US" style="FONT-SIZE: 12pt">JBuilder</span>
				<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，其中集成了</span>
				<span lang="EN-US" style="FONT-SIZE: 12pt">JUnit</span>
				<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">和</span>
				<span lang="EN-US" style="FONT-SIZE: 12pt">Ant</span>
				<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">。（建议下载单独的</span>
				<span lang="EN-US" style="FONT-SIZE: 12pt">Ant</span>
				<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">和</span>
				<span lang="EN-US" style="FONT-SIZE: 12pt">JUnit</span>
				<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">）但当晚上</span>
				<span lang="EN-US" style="FONT-SIZE: 12pt">Ant</span>
				<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">调用</span>
				<span lang="EN-US" style="FONT-SIZE: 12pt">JUnit</span>
				<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">执行测试任务时，必须保证</span>
				<span lang="EN-US" style="FONT-SIZE: 12pt">
						<junit>
						</junit>
				</span>
				<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，&lt;junit&gt;&lt;junitreport&gt;</span>
				<junitreport>
						<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">能被</span>
						<span lang="EN-US" style="FONT-SIZE: 12pt">Ant</span>
						<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">所识别。所以，你要将</span>
						<span lang="EN-US" style="FONT-SIZE: 12pt">JUnit</span>
						<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">所属的</span>
						<span lang="EN-US" style="FONT-SIZE: 12pt">3</span>
						<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">个</span>
						<span lang="EN-US" style="FONT-SIZE: 12pt">*.jar</span>
						<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">文件：</span>
						<span lang="EN-US" style="FONT-SIZE: 12pt">src.jar ，junit.jar，junitmail.jar</span>
						<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">拷贝到</span>
						<span lang="EN-US" style="FONT-SIZE: 12pt">Ant</span>
						<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的库所在目录（以我的目录结构为例）：</span>
						<span lang="EN-US" style="FONT-SIZE: 12pt">
								<o:p>
								</o:p>
						</span>
				</junitreport>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 24pt; mso-char-indent-count: 2.0; mso-char-indent-size: 12.0pt">
				<span lang="EN-US" style="FONT-SIZE: 12pt">
						<font color="#000080">C:\ant\lib<o:p></o:p></font>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 24pt; mso-char-indent-count: 2.0; mso-char-indent-size: 12.0pt">
				<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">这样才能保证，</span>
				<span lang="EN-US" style="FONT-SIZE: 12pt">Ant+JUnit</span>
				<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">会为你生成漂亮的</span>
				<span lang="EN-US" style="FONT-SIZE: 12pt">html</span>
				<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">格式的测试报告，并发送到你指定的</span>
				<span lang="EN-US" style="FONT-SIZE: 12pt">email</span>
				<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">中。</span>
				<span lang="EN-US" style="FONT-SIZE: 12pt">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 24pt; mso-char-indent-count: 2.0; mso-char-indent-size: 12.0pt">
				<span lang="EN-US" style="FONT-SIZE: 12pt"> <o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
				<b>
						<span lang="EN-US" style="FONT-SIZE: 12pt">5.</span>
				</b>
				<b>
						<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">总结（Summary）</span>
				</b>
				<b>
						<span lang="EN-US" style="FONT-SIZE: 12pt">
								<o:p>
								</o:p>
						</span>
				</b>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 24pt; mso-char-indent-count: 2.0; mso-char-indent-size: 12.0pt">
				<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">讨论了每日构建和单元测试的作用和结合起来使用的理由。配合软件开发配置管理模式提出了供参考的结合方法，并通过实践验证该方案的可行性和简单性。最后和</span>
				<span lang="EN-US" style="FONT-SIZE: 12pt">java</span>
				<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">不太熟练的朋友分享了少量经验。</span>
				<span lang="EN-US" style="FONT-SIZE: 12pt">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 24pt; mso-char-indent-count: 2.0; mso-char-indent-size: 12.0pt">
				<span lang="EN-US" style="FONT-SIZE: 12pt"> <o:p></o:p></span>
		</p><img src ="http://www.cnitblog.com/tilan/aggbug/21911.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/tilan/" target="_blank">Joinclass Inc</a> 2007-01-16 11:18 <a href="http://www.cnitblog.com/tilan/archive/2007/01/16/21911.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title> The Joel Test: 软件开发成功 12 法则 </title><link>http://www.cnitblog.com/tilan/archive/2007/01/16/21909.html</link><dc:creator>Joinclass Inc</dc:creator><author>Joinclass Inc</author><pubDate>Tue, 16 Jan 2007 03:09:00 GMT</pubDate><guid>http://www.cnitblog.com/tilan/archive/2007/01/16/21909.html</guid><wfw:comment>http://www.cnitblog.com/tilan/comments/21909.html</wfw:comment><comments>http://www.cnitblog.com/tilan/archive/2007/01/16/21909.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cnitblog.com/tilan/comments/commentRss/21909.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/tilan/services/trackbacks/21909.html</trackback:ping><description><![CDATA[<p>
				<span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">有没有听说过</span>
				<a href="http://www.sei.cmu.edu/sema/welcome.html">
						<span style="mso-fareast-language: ZH-CN">SEMA</span>
				</a>
				<span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">？这可是衡量一个软件开发组好坏的很深奥的系统。别介，<i>等一下！别按那个联接！</i></span>
				<i>
						<span lang="ZH-CN" style="mso-fareast-language: ZH-CN">
						</span>
				</i>
				<span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">给你六年你也搞不清这玩意。所以我自己随便攒了一套衡量系统，信不信由你，这系统，三分钟就可掌握。你可以把省下的时间去读医学院了（译注：美国的医学院可是要读死人的！）。</span>
				<span style="mso-fareast-language: ZH-CN">
						<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /?>
						<o:p>
						</o:p>
				</span>
		</p>
		<table border="1">
				<tbody>
						<tr>
								<td>
										<p align="center">
												<font face="Arial Black,Arial,Helvetica" color="#333333" size="4">
														<span style="FONT-SIZE: 13.5pt; COLOR: #333333; FONT-FAMILY: 'Arial Black'; mso-fareast-language: ZH-CN">Joel </span>
														<span lang="ZH-CN" style="FONT-SIZE: 13.5pt; COLOR: #333333; FONT-FAMILY: SimSun; mso-ascii-font-family: 'Arial Black'; mso-hansi-font-family: 'Arial Black'; mso-fareast-language: ZH-CN">衡量法则</span>
												</font>
										</p>
										<ol>
												<li class="MsoNormal" style="mso-list: l1 level1 lfo3; tab-stops: list .5in; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto">
														<span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">你们用不用源文件管理系统？</span>
														<span lang="ZH-CN" style="mso-fareast-language: ZH-CN">
														</span>
														<span style="mso-fareast-language: ZH-CN">
																<o:p>
																</o:p>
														</span>
												</li>
												<li class="MsoNormal" style="mso-list: l1 level1 lfo3; tab-stops: list .5in; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto">
														<span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">你们可以把整个系统从源码到ＣＤ映像文件一步建成吗？</span>
														<span style="mso-fareast-language: ZH-CN">
																<o:p>
																</o:p>
														</span>
												</li>
												<li class="MsoNormal" style="mso-list: l1 level1 lfo3; tab-stops: list .5in; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto">
														<span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">你们每天白天都把从系统源码到ＣＤ映像做一遍吗？</span>
														<span lang="ZH-CN" style="mso-fareast-language: ZH-CN">
														</span>
														<span style="mso-fareast-language: ZH-CN">
																<o:p>
																</o:p>
														</span>
												</li>
												<li class="MsoNormal" style="mso-list: l1 level1 lfo3; tab-stops: list .5in; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto">
														<span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">你们有软件虫管理系统吗？</span>
														<span lang="ZH-CN" style="mso-fareast-language: ZH-CN">
														</span>
														<span style="mso-fareast-language: ZH-CN">
																<o:p>
																</o:p>
														</span>
												</li>
												<li class="MsoNormal" style="mso-list: l1 level1 lfo3; tab-stops: list .5in; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto">
														<span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">你们在写新程序之前总是把现有程序里已知的虫解决吗？</span>
														<span lang="ZH-CN" style="mso-fareast-language: ZH-CN">
														</span>
														<span style="mso-fareast-language: ZH-CN">
																<o:p>
																</o:p>
														</span>
												</li>
												<li class="MsoNormal" style="mso-list: l1 level1 lfo3; tab-stops: list .5in; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto">
														<span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">你们的产品开发日程安排是否反映最新的开发进展情况？</span>
														<span style="mso-fareast-language: ZH-CN">
																<o:p>
																</o:p>
														</span>
												</li>
												<li class="MsoNormal" style="mso-list: l1 level1 lfo3; tab-stops: list .5in; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto">
														<span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">你们有没有软件开发的详细说明书？</span>
														<span lang="ZH-CN" style="mso-fareast-language: ZH-CN">
														</span>
														<span style="mso-fareast-language: ZH-CN">
																<o:p>
																</o:p>
														</span>
												</li>
												<li class="MsoNormal" style="mso-list: l1 level1 lfo3; tab-stops: list .5in; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto">
														<span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">你们的程序员是否工作在安静的环境里？</span>
														<span lang="ZH-CN" style="mso-fareast-language: ZH-CN">
														</span>
														<span style="mso-fareast-language: ZH-CN">
																<o:p>
																</o:p>
														</span>
												</li>
												<li class="MsoNormal" style="mso-list: l1 level1 lfo3; tab-stops: list .5in; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto">
														<span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">你们是否使用现有市场上能买到的最好的工具？</span>
														<span lang="ZH-CN" style="mso-fareast-language: ZH-CN">
														</span>
														<span style="mso-fareast-language: ZH-CN">
																<o:p>
																</o:p>
														</span>
												</li>
												<li class="MsoNormal" style="mso-list: l1 level1 lfo3; tab-stops: list .5in; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto">
														<span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">你们有没有专职的软件测试人员？</span>
														<span lang="ZH-CN" style="mso-fareast-language: ZH-CN">
														</span>
														<span style="mso-fareast-language: ZH-CN">
																<o:p>
																</o:p>
														</span>
												</li>
												<li class="MsoNormal" style="mso-list: l1 level1 lfo3; tab-stops: list .5in; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto">
														<span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">你们招人面试时是否让写一段程序？</span>
														<span lang="ZH-CN" style="mso-fareast-language: ZH-CN">
														</span>
														<span style="mso-fareast-language: ZH-CN">
																<o:p>
																</o:p>
														</span>
												</li>
												<li class="MsoNormal" style="mso-list: l1 level1 lfo3; tab-stops: list .5in; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto">
														<span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">你们是否随便抓一些人来试用你们的软件？</span>
														<span lang="ZH-CN" style="mso-fareast-language: ZH-CN">
														</span>
												</li>
										</ol>
								</td>
						</tr>
				</tbody>
		</table>
		<div align="center"> </div>
		<div align="left">
				<p>
						<span lang="ZH-CN" style="COLOR: #333333; FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN; mso-bidi-font-size: 13.5pt">“</span>
						<span style="COLOR: #333333; mso-fareast-language: ZH-CN; mso-bidi-font-size: 13.5pt">Joel </span>
						<span lang="ZH-CN" style="COLOR: #333333; FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN; mso-bidi-font-size: 13.5pt">衡量法则”好就好在你只需照着逐条回答以上问题，然后</span>
						<span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">把所答为“是”的问题算成一分，再加起来</span>
						<span lang="ZH-CN" style="COLOR: #333333; FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN; mso-bidi-font-size: 13.5pt">就可以了，而不需要去算什么每天写的程序行数或程序虫的平均数等等</span>
						<span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">。但咱丑话说在前面，可别用</span>
						<span lang="ZH-CN" style="COLOR: #333333; FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN; mso-bidi-font-size: 13.5pt">“</span>
						<span style="COLOR: #333333; mso-fareast-language: ZH-CN; mso-bidi-font-size: 13.5pt">Joel </span>
						<span lang="ZH-CN" style="COLOR: #333333; FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN; mso-bidi-font-size: 13.5pt">衡量法则”去推算你的核电站管理程序是否可靠。</span>
						<span style="mso-fareast-language: ZH-CN">
								<o:p>
								</o:p>
						</span>
				</p>
				<p>
						<span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">如果你们得了１２分，那是最好，得了１１分还过得去，但如果只得了１０分或低于１０分，你们可能就有很严重的问题了。严酷的现实是：大多数的软件开发公司只能得到２到３分。这些公司如果得不到急救可就玄了，因为像微软这样的公司从来就没有低过１２分。</span>
						<span style="mso-fareast-language: ZH-CN"> <o:p></o:p></span>
				</p>
				<p>
						<span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">当然，一个公司成功与否不仅仅只取决于以上标准。比如，让一个管理绝佳的软件公司去开发一个没有人要的软件，那开发出来的软件也只能是没有人要。或反过来，一帮软件痞子以上标准一条也达不到，没准照样也能搞出一个改变世界的伟大软件。但我告诉你，如果不考虑别的因素，你只要能达到以上１２条准则，你的团队就是一个可以准时交活的纪律严明的好团队。</span>
						<span style="mso-fareast-language: ZH-CN">
								<o:p>
								</o:p>
						</span>
				</p>
				<p>
						<b>
								<span style="FONT-FAMILY: 'Arial Black'; mso-fareast-language: ZH-CN">1. </span>
						</b>
						<span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">你们用不用源文件管理系统？</span>
						<span style="mso-fareast-language: ZH-CN">
								<br />
						</span>
						<span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">我用过商业化的源文件管理系统，我也用过免费的系统，比如</span>
						<a href="http://www.cvshome.org/">
								<span style="mso-fareast-language: ZH-CN">CVS</span>
						</a>
						<span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">，告诉你吧，</span>
						<span style="mso-fareast-language: ZH-CN">CVS</span>
						<span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">挺好用。但如果你根本就没有用源文件管理系统，那你就是累死了也没法让你的程序员出活：他们没法知道别人在改动什么源文件，写错了的源文件也没法恢复。</span>
						<span style="mso-fareast-font-family: SimSun; mso-fareast-language: ZH-CN">
								<o:p>
								</o:p>
						</span>
				</p>
				<p>
						<span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">使用源文件管理系统还有一大好处是，由于每一位程序员都把源文件从源文件管理系统里提出来放到自己的硬盘里，几乎不会发生丢失源文件的事，最起码我还没听说过。</span>
						<span style="mso-fareast-language: ZH-CN">
								<o:p>
								</o:p>
						</span>
				</p>
				<p>
						<b>
								<span style="FONT-FAMILY: 'Arial Black'; mso-fareast-language: ZH-CN">2. </span>
						</b>
						<span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">你们可以把整个系统从源码到ＣＤ映像文件一步建成吗？</span>
						<span style="mso-fareast-language: ZH-CN">
								<br />
						</span>
						<span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">这句话问的问题是：从你们最新的源码开始到建立起能够交出去的最后文件，你们有多少步骤要做？</span>
						<span lang="ZH-CN" style="mso-fareast-language: ZH-CN">
						</span>
						<span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">一个好的团队应该有一个批处理程序一步便可将所有的工作做完，像把源文件提取出来，跟据不同的语言版本要求（英文版，中文版），和各种编译开关（</span>
						<span style="mso-fareast-language: ZH-CN">#ifdef</span>
						<span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">）进行编译，联接成可执行文件，标上版本号，打包成ＣＤ映像文件或直接送到网站上去，等等等等。</span>
						<span style="mso-fareast-language: ZH-CN">
								<o:p>
								</o:p>
						</span>
				</p>
				<p>
						<span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">如果这些步骤不是一步做完，就有可能出人为差错。而且当你很接近产品开发尾声的时侯，你可能很急于把最后几个虫解决，然后尽快地交活。如果这时候你需要做２０步才能把最终文件制出来，你肯定会急得要命，然后犯一些很不该犯的错误。</span>
						<span style="mso-fareast-language: ZH-CN">
								<o:p>
								</o:p>
						</span>
				</p>
				<p>
						<span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">正因为这个原因，我工作的前一个公司从用</span>WISE<span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">改用</span>InstallShield<span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">：我们必需要让我们的批处理程序完全自动化地，在夜里，被</span>NT scheduler<span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">起动把最终文件制成，</span>WISE<span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">不能被</span>NT scheduler<span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">启动而</span>InstallShield<span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">可以，我们只能把</span>WISE<span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">扔掉。（</span><span style="mso-fareast-language: ZH-CN">WISE</span><span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">的那帮家伙向我保证他们的下一代产品一定支持在夜里自动运行</span><span style="mso-fareast-language: ZH-CN">.)<o:p></o:p></span></p>
				<p>
						<b>
								<span style="FONT-FAMILY: 'Arial Black'; mso-fareast-language: ZH-CN">3. </span>
						</b>
						<span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">你们每天白天都把从系统源码到ＣＤ映像做一遍吗？</span>
						<span style="mso-fareast-language: ZH-CN">
								<br />
						</span>
						<span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">你们有没有遇到过这样的事情：一个程序员不小心把有毛病的源码放进源文件管理系统，结果造成最终文件没法制成。比如，他建立了一个新源文件但忘了把它放进源文件管理系统，然后他高高兴兴锁机回家了，因为在他的机器上整个编译得很好。可是别人却因为这没法工作下去了，也只好闷闷地回家了。</span>
						<span style="mso-fareast-language: ZH-CN">
								<o:p>
								</o:p>
						</span>
				</p>
				<p>
						<span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">这种造成最终文件没法制成的情况很糟糕，但却很常见。如果每天在白天就把最终文件制一遍的话，就可以让这种事不造成太大危害。在一个大的团队里，要想保证有毛病的源码及时得到纠正，最好每天下午（比如午餐时）制一下最终文件。午餐前，每个人都尽可能地把改动的源文件放到源文件管理系统里，午餐后，大家回来，如果最终文件已经制成了，好！这时大家再从源文件管理系统里取出最新的源文件接着干活。如果最终文件制作出错，出错者马上修正，而别人还可接着用原有的没问题的源程序干活。</span>
						<span style="mso-fareast-language: ZH-CN">
								<o:p>
								</o:p>
						</span>
				</p>
				<p>
						<span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">在我以前曾干过的微软</span>
						<span style="mso-fareast-language: ZH-CN">Excel</span>
						<span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">开发组里，我们有一条规定：谁造成最终文件制作出错，谁就得被罚去负责监视以后的最终文件制作过程，直到下一位造成最终文件制作出错的人来接任他。这样做不仅可以督促大家少造成最终文件制作出错，而且可以让每个人都有机会去了解最终文件制作过程。</span>
						<span style="mso-fareast-language: ZH-CN">
								<o:p>
								</o:p>
						</span>
				</p>
				<p>
						<span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">如果想更多了解这个话题，可以读我的另一篇文章</span>
						<span lang="ZH-CN" style="mso-fareast-language: ZH-CN">
						</span>
						<a href="http://www.joelonsoftware.com/printerFriendly/articles/fog0000000023.html">Daily Builds are Your Friend</a>.</p>
				<p>
						<b>
								<span style="FONT-FAMILY: 'Arial Black'; mso-fareast-language: ZH-CN">4. </span>
						</b>
						<span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">你们有软件虫管理系统吗？</span>
						<span style="mso-fareast-language: ZH-CN">
								<br />
						</span>
						<span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">不论你有任何借口，只要你写程序，哪怕只是一个人的小组，如果你没有一个系统化的管理软件虫的工具，你写的程序的质量一定高不了。许多程序员觉得自己可以记得自己的软件虫。没门！我从来记不住超过２到３个软件虫。而且第二天早上起床后忙着去买这买那，好不容易记住的软件虫早忘掉了。你绝对需要一个系统来管住你的那些虫。</span>
						<span style="mso-fareast-language: ZH-CN">
								<o:p>
								</o:p>
						</span>
				</p>
				<p>
						<span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">软件虫管理系统功能有多有少。但最少要管理以下几种信息：</span>
						<span style="mso-fareast-language: ZH-CN">
								<o:p>
								</o:p>
						</span>
				</p>
				<ul type="disc">
						<li class="MsoNormal" style="mso-list: l0 level1 lfo6; tab-stops: list .5in; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto">
								<span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">如何重复软件虫的详细步骤</span>
								<span lang="ZH-CN" style="mso-fareast-language: ZH-CN">
								</span>
								<span style="mso-fareast-language: ZH-CN">
										<o:p>
										</o:p>
								</span>
						</li>
						<li class="MsoNormal" style="mso-list: l0 level1 lfo6; tab-stops: list .5in; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto">
								<span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">正常情况（无虫）应是怎样</span>
								<span lang="ZH-CN" style="mso-fareast-language: ZH-CN">
								</span>
								<span style="mso-fareast-language: ZH-CN">
										<o:p>
										</o:p>
								</span>
						</li>
						<li class="MsoNormal" style="mso-list: l0 level1 lfo6; tab-stops: list .5in; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto">
								<span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">现在情况（有虫）又是怎样</span>
								<span lang="ZH-CN" style="mso-fareast-language: ZH-CN">
								</span>
								<span style="mso-fareast-language: ZH-CN">
										<o:p>
										</o:p>
								</span>
						</li>
						<li class="MsoNormal" style="mso-list: l0 level1 lfo6; tab-stops: list .5in; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto">
								<span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">谁来负责杀虫</span>
								<span lang="ZH-CN" style="mso-fareast-language: ZH-CN">
								</span>
								<span style="mso-fareast-language: ZH-CN">
										<o:p>
										</o:p>
								</span>
						</li>
						<li class="MsoNormal" style="mso-list: l0 level1 lfo6; tab-stops: list .5in; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto">
								<span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">问题有没有解决</span>
								<span lang="ZH-CN" style="mso-fareast-language: ZH-CN">
								</span>
								<span style="mso-fareast-language: ZH-CN">
										<o:p>
										</o:p>
								</span>
						</li>
				</ul>
				<p>
						<span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">如果你觉得用软件虫管理系统太麻烦，可以简化一下，建立一个有以上５列的表来用就行了。</span>
						<span style="mso-fareast-language: ZH-CN">
								<o:p>
								</o:p>
						</span>
				</p>
				<p>
						<span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">如果想更多了解这个话题，可以读我的另一篇文章</span>
						<a href="http://www.joelonsoftware.com/printerFriendly/articles/fog0000000029.html">Painless Bug Tracking</a>.</p>
				<p>
						<b>
								<span style="FONT-FAMILY: 'Arial Black'; mso-fareast-language: ZH-CN">5. </span>
						</b>
						<span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">你们在写新程序之前总是把现有程序里已知的虫解决吗？</span>
						<span style="mso-fareast-language: ZH-CN">
								<br />
						</span>
						<span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">微软</span>
						<span style="mso-fareast-language: ZH-CN">Windows Word</span>
						<span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">的第一版的开发项目曾被认为是“死亡之旅”项目。好象永远也做不完，永远超时。所有人疯狂地工作，可怎么也完成不了任务。整个项目一拖再拖，大家都觉得压力大得受不了。最后终于做完了这个鬼项目，微软把全组送到墨西哥的</span>
						<span style="mso-fareast-language: ZH-CN">Cancun</span>
						<span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">去度假，让大家坐下来好好想想。</span>
						<span style="mso-fareast-language: ZH-CN">
								<o:p>
								</o:p>
						</span>
				</p>
				<p>
						<span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">大家意识到由于项目经理过于强求程序员们按时交活，结果大家只能匆匆地赶活，写出的程序毛病百出。由于项目经理的开发计划并没有考虑杀虫的时间，大家只能把杀虫的任务往后推，结果虫越积越多。有一个程序员负责写计算字体高度的程序，为了图快，居然写一行“</span>return 12;<span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">”了事。他指望以后的质检人员发现这段程序有毛病后报告他再改正。项目经理的开发计划事实上已变成一个列写程序功能的清单，而上面列的所谓程序功能迟早都会成为软件虫。在项目总结会上，我们称这种工作方法为“绝对劣质之路”。</span></p>
				<p>
						<span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">为了避免再犯这个错误，微软制定了“零缺陷策略”。许多程序员嘲笑这个策略，觉得经理们似乎在指望靠行政命令来提高产品质量。而事实上“零缺陷策略”的真正含义是：在任何时候，都要把解决现有程序里的问题作为首要问题来抓，然后再去写新程序。</span>
						<span style="mso-fareast-font-family: SimSun; mso-fareast-language: ZH-CN">
								<o:p>
								</o:p>
						</span>
				</p>
				<p>
						<span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">为什么要这样做呢？</span>
						<span style="mso-fareast-font-family: SimSun; mso-fareast-language: ZH-CN">
								<o:p>
								</o:p>
						</span>
				</p>
				<p>
						<span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">一般说来，你越不及时地杀虫，杀虫的代价（时间和金钱）就会越高。比如，你写程序时打错了一个字，编译器马上告诉你，你很容易就把它改正。你刚写好的程序在第一次运行时发现了一个问题，你也很快就能解决它，因为你对你刚写的程序还记忆犹新。如果你运行你的程序时发现了一个问题，可这个程序是几天以前写的，你可能就需要折腾一会儿，还好，你还大致记得，所以不会花太长时间。但如果你在你几个月以前写的程序里发现了问题，就比较难解决了，因为你已经忘了许多细节。这时候，你还没准儿正忙着杀别人程序里的虫呐，因为这家伙到加勒比海阿鲁巴岛度假去了。这时候，解决这一堆问题的难度不亚于从事尖端科学研究。你一定得小心翼翼地，非常系统化地从事，而且你很难知道多长时间你才能把问题解决。还有更糟糕的，你的程序已交到用户手里了，才发现问题，那你就等着套腰包吧。</span>
						<span style="mso-fareast-font-family: SimSun; mso-fareast-language: ZH-CN">
								<o:p>
								</o:p>
						</span>
				</p>
				<p>
						<span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">总结起来，就一条：越早解决问题，越容易解决。</span>
						<span style="mso-fareast-font-family: SimSun; mso-fareast-language: ZH-CN">
								<o:p>
								</o:p>
						</span>
				</p>
				<p>
						<span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">另外还有一个原因，刚写的程序里发现问题，你能够比较容易地估算解决它的时间。举个例子，如果我问你写一段程序去把一个列表排序需要花多长时间，你可以给我一个比较确切的估计。如果你的程序，在</span>Internet Explorer 5.5<span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">安装以后，工作不正常。我问你要多长时间把这个问题解决，你恐怕都估计不出来，因为你根本就不知道是什么原因造成了这个问题。你可能要花三天时间才能解决，也有可能只花两分钟。</span><span style="mso-fareast-font-family: SimSun; mso-fareast-language: ZH-CN"><o:p></o:p></span></p>
				<p>
						<span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">这个例子告诉我们，如果你的开发过程中有许多虫没有及时解决，那你的开发计划肯定不可靠。反过来，如果你们已经把已知的虫全部解决了，要做的事只是写新的程序，那你的开发计划就会比较准确。</span>
						<span style="mso-fareast-font-family: SimSun; mso-fareast-language: ZH-CN">
								<o:p>
								</o:p>
						</span>
				</p>
				<p>
						<span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">把已知的虫全部解决，这样做还有一个好处：你可以对竞争对手快速反击。有些人把这叫着“让开发中的产品随时处在可以交给用户的状态”。如果你的竞争对手推出一个新的功能想把你的客户抢走，你可以马上在你的产品里加上这个功能，立刻将新产品交付用户，因为你没有一大堆积累下来的问题要解决。</span>
						<span style="mso-fareast-font-family: SimSun; mso-fareast-language: ZH-CN">
								<o:p>
								</o:p>
						</span>
				</p>
				<p>
						<b>
								<span style="FONT-FAMILY: 'Arial Black'; mso-fareast-language: ZH-CN">6. </span>
						</b>
						<span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">你们的产品开发日程安排是否反映最新的开发进展情况？</span>
						<span style="mso-fareast-language: ZH-CN">
								<br />
						</span>
						<span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">为什么我们需要开发日程安排？如果你的程序对公司的业务很重要，那公司就必须知道你的程序何时能写完。满世界的程序员都有一个通病，那就是他们都搞不清自己何时才能写完要写的程序。他们都只会对管理人员嚷嚷：“等我做好了就做好了！”</span>
						<span style="mso-fareast-font-family: SimSun; mso-fareast-language: ZH-CN">
								<o:p>
								</o:p>
						</span>
				</p>
				<p>
						<span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">不幸的是，程序写完了，事远远没完。作为一个公司，在发行产品之前，还有许许多多的事情要做：何时做产品演示？何时参加展览会？何时发广告？等等。所有的这一且都依赖于产品的开发日程安排。</span>
						<span lang="ZH-CN" style="mso-fareast-language: ZH-CN">
						</span>
				</p>
				<p>
						<span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">定下产品开发日程安排，还有一个很关键的好处：它逼着你只做叫你做的功能，甩掉那些可要可不要的功能，否则这些可要可不要的东西有可能把你缠住。请看</span>
						<a href="http://www.netmeg.net/jargon/terms/c/creeping_featuritis.html">featuritis</a>
						<span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">。</span>
						<span style="mso-fareast-font-family: SimSun; mso-fareast-language: ZH-CN">
								<o:p>
								</o:p>
						</span>
				</p>
				<p>
						<span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">定下产品开发日程安排，按照它开发，这并不难做，请看我的另一篇文章</span>
						<span lang="ZH-CN" style="mso-fareast-language: ZH-CN">
						</span>
						<a href="http://www.joelonsoftware.com/printerFriendly/articles/fog0000000245.html">Painless Software Schedules</a>
						<span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">，这篇文章告诉你一种制订产品开发日程的好方法。</span>
				</p>
				<p>
						<b>
								<span style="FONT-FAMILY: 'Arial Black'; mso-fareast-language: ZH-CN">7. </span>
						</b>
						<span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">你们有没有软件开发的详细说明书？</span>
						<span style="mso-fareast-language: ZH-CN">
								<br />
						</span>
						<span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">写软件开发的详细说明书就像是绣花：人人皆知是好东西，可没谁愿意去做。</span> </p>
				<p>
						<span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">我不知道这是为什么，也许是因为多数程序员天生就不喜欢写文章。其结果是，一个开发组里的程序员们，宁可用程序来沟通，也不愿写文章来表达自己。他们喜欢上来就写程序，而不是写什么详细说明书。</span>
						<span style="mso-fareast-font-family: SimSun; mso-fareast-language: ZH-CN">
								<o:p>
								</o:p>
						</span>
				</p>
				<p>
						<span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">在产品的前期设计过程中，如果你发现了一些问题，你可以轻易地在说明书里该几行字就行了。一旦进入了写程序的阶段，解决问题的代价就要高得多了，不仅仅是时间上的代价，而且也有感情上的代价，因为没人愿意将自己做成的东西扔掉。所以这时候解决问题总有一些阻力。</span>
						<span style="mso-fareast-font-family: SimSun; mso-fareast-language: ZH-CN">
								<o:p>
								</o:p>
						</span>
				</p>
				<p>
						<span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">没有产品开发详细说明书就开始写程序，往往会导致程序写的乱七八糟，而且左拖右拖不能交付使用。我觉得这就是</span>Netscape<span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">遇到的问题。前四个版本的程序越写越乱，以至管理人员作出一个</span><a href="http://www.joelonsoftware.com/printerFriendly/articles/fog0000000069.html"><span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">愚蠢的决定</span></a><span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">：把以前的程序统统扔掉，重新写。后来他们在开发</span>Mozilla<span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">时又犯了同样的错误。产品越做越乱，完全失控，花了几年的时间才进入内部测试阶段。</span></p>
				<p>
						<span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">我最得意的理论是：如果让程序员们接受一些写文章的训练如</span>
						<a href="http://www.yale.edu/engl450b/">
								<font color="#0000ff">an intensive course in writing</font>
						</a>
						<span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">，他们就可能会改变一下不写说明书的坏习惯，而以上所说的糟糕的例子就有可能少发生。</span>
						<span style="mso-fareast-font-family: SimSun; mso-fareast-language: ZH-CN">
								<o:p>
								</o:p>
						</span>
				</p>
				<p>
						<span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">另一个解决问题的办法是：雇一些能干的项目主任，专职写产品开发详细说明书。</span>
						<span style="mso-fareast-font-family: SimSun; mso-fareast-language: ZH-CN">
								<o:p>
								</o:p>
						</span>
				</p>
				<p>
						<span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">不论采用以上哪种方法，道理只有一个：在没有产品开发详细说明书之前，决不可写程序。</span>
						<span style="mso-fareast-font-family: SimSun; mso-fareast-language: ZH-CN">
								<o:p>
								</o:p>
						</span>
				</p>
				<p>
						<span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">如果想更多了解这个话题，可以读我的</span>
						<a href="http://www.joelonsoftware.com/printerFriendly/articles/fog0000000036.html">
								<span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">四篇文章</span>
						</a>
						<span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">。</span>
						<span style="mso-fareast-font-family: SimSun; mso-fareast-language: ZH-CN">
								<o:p>
								</o:p>
						</span>
				</p>
				<p>
						<b>
								<span style="FONT-FAMILY: 'Arial Black'; mso-fareast-language: ZH-CN">8. </span>
						</b>
						<span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">你们的程序员是否工作在安静的环境里？</span>
						<span style="mso-fareast-language: ZH-CN">
								<br />
						</span>
						<span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">当你让你的智囊们工作在安静，宽敞，不受人打扰的环境里，他们往往能更快地出活，这已是不争的事实。有一本经典的讲软件开发管理的书</span>
						<a href="http://www.amazon.com/exec/obidos/ASIN/0932633439/ref=nosim/joelonsoftware/">Peopleware</a>
						<span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">把这个问题阐述得很清楚。</span>
				</p>
				<p>
						<span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">问题在于，我们都知道最好不要打断这些智囊们的思路，让他们一直处于他们的最佳状态中，这样他们就能全神贯注，废寝忘食地工作，充分发挥他们的作用。作家，程序员，科学家，甚至篮球运动员都有他们的最佳状态。</span>
						<span lang="ZH-CN" style="mso-fareast-language: ZH-CN">
						</span>
				</p>
				<p>
						<span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">问题还在于，进入这个最佳状态不容易。我觉得平均起来，需要１５分钟才能进入最佳状态，达到最高工作效率。有时侯，当你疲劳了或已经高效率地干了许多工作了，你就很难再进入这个状态，只好干点杂事打发时间，或上网，玩游戏等。</span>
						<span lang="ZH-CN" style="mso-fareast-language: ZH-CN">
						</span>
				</p>
				<p>
						<span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">问题更在于，你很容易就被各种各样的事打扰，被拽出你的最佳状态：噪音啦，电话啦，吃午饭啦，喝杯咖啡啦，被同事打扰啦，等等。如果一个同事问你一个问题，只花你一分钟，可你却被拽出你的最佳工作状态，重新回到这个状态需要花半小时。你的工作效率因此而受到很大影响。如果让你在一个嘈杂的大房间里工作（那帮搞网站的家伙还就喜欢这样），边上的推销员在电话里大叫大嚷，你就很难出活，因为你进入不了你的最佳工作状态。</span>
						<span lang="ZH-CN" style="mso-fareast-language: ZH-CN">
						</span>
				</p>
				<p>
						<span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">作为程序员，进入最佳工作状态更难。你先要把方方面面的细节装在脑子里，</span>
						<span lang="ZH-CN" style="mso-fareast-language: ZH-CN">
						</span>
						<span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">任何一种干扰都可能让你忘掉其中某些东西。你重新回来工作时，发现好些东西记不起来了（如你刚用的局部变量名，或你刚才的搜索程序写到哪里了等）你只好看看刚写的程序，回忆一下，慢慢地回到你刚才的最佳工作状态。</span>
						<span style="mso-fareast-font-family: SimSun; mso-fareast-language: ZH-CN">
								<o:p>
								</o:p>
						</span>
				</p>
				<p>
						<span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">我们来做一个简单的算数。假设一个程序员被打扰一下，哪怕只有一分钟，他却需要花１５分钟才能回到最佳工作状态（统计资料显示如此）。我们有两个程序员：杰夫和愚夫，</span>
						<span lang="ZH-CN" style="mso-fareast-language: ZH-CN">
						</span>
						<span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">坐在一个大办公区里工作。愚夫想不起来用什么函数去进行</span>Unicode <span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">字符串复制。他可以花３０秒查一下，或者花１５秒问杰夫。由于他坐在杰夫的旁边，他就选择去问杰夫。杰夫被打扰了一下，耽误了他１５分钟，节省了愚夫１５秒钟。</span><span style="mso-fareast-font-family: SimSun; mso-fareast-language: ZH-CN"><o:p></o:p></span></p>
				<p>
						<span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">现在，我们把他们俩用墙和门隔开，让他们俩分坐在不同的办公室里，愚夫又想不起来什么涵数名，自己查一下要花３０秒；问杰夫，要花４５秒，因为他要站起来走过去问（对这帮程序员来说，这可不是件简单的事，看看他们的体质就知道为什么了）。所以他选择自己去查。愚夫损失了３０秒钟，可是杰夫少损失了１５分钟。哈哈！</span>
						<span style="mso-fareast-font-family: SimSun; mso-fareast-language: ZH-CN">
								<o:p>
								</o:p>
						</span>
				</p>
				<p>
						<b>
								<span style="FONT-FAMILY: 'Arial Black'; mso-fareast-language: ZH-CN">
										<span style="mso-spacerun: yes"> </span>9. </span>
						</b>
						<span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">你们是否使用现有市场上能买到的最好的工具？</span>
						<span style="mso-fareast-language: ZH-CN">
								<br />
						</span>
						<span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">用可编译语言写程序恐怕是这世界上为数不多的还不能随便抓一个破计算机就可以做的事。如果你用于编译的时间超过几秒钟，你就应该换一台最新最快的计算机了。因为如果编译时间超过１５秒，程序员们就会不耐烦，转而去上网看一些无关的东西比如</span>
						<a href="http://www.theonion.com/">
								<font color="#0000ff">The Onion</font>
						</a>
						<span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">，弄不好一看就是好几个小时。</span>
				</p>
				<p>
						<span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">调试图形界面软件时，用只有一个显示器的计算机不仅不方便，有时甚至是不可能。用有两个显示器的计算机，要方便许多。</span>
				</p>
				<p>
						<span lang="ZH-CN" style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">程序员们经常不可避免地要去画一些图标或工具栏图。多数程序员没有一个好的图形编辑器可用。用微软的“画笔”软件去画图标简直是笑话，可事实上大家还就在这样做。</span>
						<span style="mso-fareast-font-family: SimSun; mso-fareast-language: ZH-CN">
								<o:p>
								</o:p>
						</span>
				</p>
		</div><img src ="http://www.cnitblog.com/tilan/aggbug/21909.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/tilan/" target="_blank">Joinclass Inc</a> 2007-01-16 11:09 <a href="http://www.cnitblog.com/tilan/archive/2007/01/16/21909.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>每日构建（daily build）是你的朋友----周思博趣谈软件</title><link>http://www.cnitblog.com/tilan/archive/2007/01/16/21908.html</link><dc:creator>Joinclass Inc</dc:creator><author>Joinclass Inc</author><pubDate>Tue, 16 Jan 2007 03:05:00 GMT</pubDate><guid>http://www.cnitblog.com/tilan/archive/2007/01/16/21908.html</guid><wfw:comment>http://www.cnitblog.com/tilan/comments/21908.html</wfw:comment><comments>http://www.cnitblog.com/tilan/archive/2007/01/16/21908.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cnitblog.com/tilan/comments/commentRss/21908.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/tilan/services/trackbacks/21908.html</trackback:ping><description><![CDATA[<p>1982年，我家定购了IBM的PC机(IBM生产的最早的个人计算机，是现代流行的标准化的个人计算机的祖宗）。我们家可能是以色列最早拥有这种PC机的几个家庭之一。当时我们跑到了仓库等着电脑从港口运过来。事实上，我说服我爸购买的是带有全套附属设备的个人计算机（译者按：有些现在很便宜的附属设备，那时候都是非常昂贵的），这些附属设备包括<i>两个</i>软盘驱动器，128K内存，一个针式点阵打印机（用来快速打印草稿）和一个运转起来发出机关枪扫射声音的兄弟牌的雏菊轮式打印机（译者按：原文为Daisy Wheel printer，是一种已经淘汰的打印机，原理类似于老式的机械打字机，可以产生清晰的英文字符）。<img height="91" alt="" hspace="4" src="http://chinese.joelonsoftware.com/Images/IBM_PC.jpg" width="160" align="right" vspace="4" border="0" cd:pos="3" />附属的软件也很齐全，PC-DOS 1.0（最早的PC操作系统），75美元的参考书册，包括BIOS的完整源代码。 一个汇编语言编译器（Macro Assembler），非常棒的IBM单色显示器，可以显示80列宽的字符，而且支持小写字母显示。整套配置大概花了10000美元。这些钱包括以色列的荒谬的进口税。呵呵，那时候我家可真舍得花钱啊！</p>
		<p>因为当时“每个人”都知道BASIC是给小孩玩的语言，用这种语言只能使你写出非结构化的垃圾代码，然后你的的脑子也会被这种语言变成Camembert产的奶酪（Camembert cheese，法国的一种奶酪，实心，圆饼状，灰色，有一个拳头大小）。所以我们又花了600美元买了一个IBM公司PASCAL语言开发包，需要3张软盘才装的下。PASCAL编译器运行分别需要第一号软盘，和第二号软盘，PASCAL链接器需要第三号软盘。我写了一个简单的输出文字“你好，世界”程序然后编译链接这个程序，总共花了8分钟。</p>
		<p>嗯，8分钟好像太长了。我写了一个脚本程序来自动化整个过程，把时间缩减为7.5分钟。这样好一点了。但是我想设计一个可以玩奥赛罗的程序。（译者按：奥赛罗原文为Othello，一种棋类游戏，规则见http://www.ugateways.com/bof4.html）这个游戏<i>总是</i>能打动我。我不得不花很多时间等待编译器编译我的程序。“就是这样的，”一个专业程序员告诉我，“我们通常在办公室里房放上sit-up board（译者按：一种健身器材，可以在上面做仰卧起坐或者有氧操什么的） ，当PASCAL编译器开始运行时，我们就开始锻炼。我这样编程了几个月后，我的身材不要太棒喔！”</p>
		<p>后来有一天，丹麦程序员写了一个很灵的叫做Compas Pascal的程序。Philippe Kahn（Borland公司的创始人）买下了它，更名为<a href="http://community.borland.com/article/0,1410,20161,00.html">Borland Turbo Pascal</a>。Turbo Pascal好得简直难以想象，因为它能做IBM Pascal能做的所有事情，但是只要33K内存。<i>而且还额外提供一个编辑器</i>。 这还不是最棒的。最棒的是编译一个小程序只需要不到一秒。这就好比一个你从来没有听说过的公司生产了通用公司别克轿车的克隆版，这种克隆车可以每小时行驶一百万英里，但是只消耗了一滴汽油。一只小小的蚂蚁喝下这点汽油也不会撑死。</p>
		<p>突然，我的编程效率变得高的<i>多</i>了</p>
		<p>那时我开始明白了<i>“REP循环”（Rep loop）</i>这个概念. REP是“读入，求值，打印（Read, Eval, Print）”的缩写。这个概念解释了Lisp（一种编程语言，用于人工智能）解释器的基本原理：它“读入”你的输入，计算你的输入得到结果，打印结果。下面给一个例子：我输入一些东西，Lisp解释器计算，然后输出结果。</p>
		<p>
				<img height="296" alt="REP Loop" hspace="4" src="http://chinese.joelonsoftware.com/Images/REP_Loop.jpg" width="496" border="0" cd:pos="0" />
		</p>
		<p>在一个稍微大点的规模上，当你写代码时，你也处于一个REP循环的宏版本中，这个循环就是“编码－编译－测试”。你编写代码，把代码编译成可执行的文件，然后测试它，看一下运行起来怎么样。</p>
		<p>关键一点是当你写一个程序时，你的工作过程是循环的。一个循环所花时间越短，你的生产力就越高，当然最短时间不会小于编译器运行的时间。 这就是一个程序员为什么总是要一个<i>真正够快的硬件</i>而编译器开发者们总是不断使他们的编译器运行更快的正式的纯计算机科学角度的原因。Visual Basic的办法是当你输入代码时，它就开始进行代码的语法解析，这样程序解释运行时速度很快。Visual C++的办法是增量编译（incremental compiles），预编译头文件（precompiled headers）和增量链接（incremental linking）。</p>
		<p>但是一个大型的团队有多个开发人员和测试人员，你碰到了同样的循环，可能不同点就是有更多的文档要写(可是这还只是草稿，天哪！)。一个测试人员发现了bug并报告，然后开发人员修复了这个bug。那么测试人员得到修正后的代码需要多少时间？在一些软件开发机构，这样的报告－修正－再测试循环（Report-Fix-Retest loop）可能需要几个礼拜。如果一个循环需要这么长的时间，通常意味着该机构生产力很低。想让整个开发过程运转得更平滑一点，你必须想方设法使得报告－修正－再测试循环（Report-Fix-Retest loop）花的时间更少。</p>
		<p>一个好的办法是<i>每日构建（daily builds）</i>。 每日构建意味着<i>自动地，每天，完整地</i>构建整个代码树、（译者按：“代码树”，原文为source tree，意思是将整个项目源代码的目录，子目录，文件的位置尽可能事先固定下来，这样在开发过程中各个模块间，各个文件间的相对位置都不会混乱。源代码树指的就是一个项目所有的已经组织好的代码文件。通常代码树应该用版本控制软件管理起来。虽然这个概念很基本，但是据我的观察，国内还是有软件公司在这方面做的不够好的，所以有必要解释一下。）</p>
		<p>
				<b>自动地 <i>－</i></b> 因为你设定代码每天在固定的时间构建。在Unix环境下使用cron，在windows下使用“任务计划”。</p>
		<p>
				<b>每天 －</b> 或者更频繁. 当然每天构建的次数越多越好啦。但是有时候构建次数还是有上限的，原因和版本控制有关系，等会儿我会谈到的。</p>
		<p>
				<b>完整地 －</b>很可能你的代码有多个版本。多语言版本，多操作系统版本，或者高端低端版本。每日构建（daily build）需要构建<i>所有</i>这些版本。并且每个文件都需要从头编译，而不是使用编译器的不完美的增量编译功能。</p>
		<p>以下是每日构建（daily build）能带来的好处：</p>
		<ol>
				<li>当一个bug被修正了，测试者可以很快得到最新的修正后的版本开始重新测试，以验证bug是否真正地被修复了。 
</li>
				<li>开发人员可以更加确定他们对代码做的修改不会破坏1024个操作系统上的任何一个版本。验证这一点不需要在他们的机器上<i>安装</i>OS/2（IBM公司生产的PC机操作系统）。 
</li>
				<li>那些每天将修改过的代码导入（check in）版本控制服务器的开发人员知道，他们对一个模块导入的修改不会拖别的开发人员的后腿。拖后腿的意思是，那些开发别的模块的程序员使用这个修改过的模块，出了问题，于是他们自己的模块也没有办法开发下去了。每日构建则<i>不会</i>有人拖后腿。如果把一个开发团队比作一台PC机，那么团队中的一个程序员对某个模块的修改导致其他人无法开发别的模块，相当于PC机发生了蓝屏。当一个程序员忘记把他（她）新建立的文件导入到repository（指版本控制服务器上的代码树）时，这种开发过程中的“蓝屏”会经常发生。因为在这个程序员<i>自己的</i>计算机上有这个文件，所以他（她）构建 这个程序没有问题。但是其他程序员是从版本控制服务器上导出（check out）代码的，由于服务器上没有这个文件，他们遇到了链接错误（link error），无法继续工作了。 
</li>
				<li>外部团队（例如市场销售部门，进行beta测试的一些客户）可以获得一个比较稳定的版本，这样对他们开展自己的工作比较有利。 
</li>
				<li>假如你将每日构建出的二进制文件（例如一个可执行程序，一个dll等等）存档管理，那么当你发现一个非常奇怪的，无法解决的bug时，你可以通过对这些文件进行二进制搜索（binary search）来确定什么时候这个bug第一次出现。如果有对代码进行了完善的版本控制，你也可以找出是谁在何时对代码进行的导入（check in）导致了这个bug。 
</li>
				<li>当开发者修正了测试者报告的一个错误时，如果测试者同时报告了发现错误时的构建的版本，开发人员可以直接在那个版本中测试是否bug<i>真正</i>被修复了。（译者按：测试者报告出现了一个bug，只是报告了一个错误症状，而错误的原因可能有多个，每个原因可能在不同的模块中。前文中的方法是为了避免只修正了一个模块中一个原因，别的模块由于在变动，于是掩盖了而不是修复了bug） </li>
		</ol>
		<p>以下是如何进行每日构建（daily build）的具体步骤。你需要用最快的电脑建立一个每日构建服务器。写一个脚本，可以自动从版本控制服务器中导出（check out）完整的代码，（你<i>当然使用</i>版本控制，不是吗？），然后对代码从头开始进行构建（build），要构建所有的版本。如果你有一个安装打包程序，也要在脚本中自动运行。所有会卖给最终用户的东西都要包括在构建过程中。把构建出来的版本放在各自的的目录里，不同时间构建的相同版本也应该按日期整理好，不要相互覆盖。每天固定的时间运行这样的脚本。</p>
		<ul>
				<li>最关键的是<i>所有这些步骤</i>都应该由脚本自动化完成，从导出（check out）代码到将最终产品放在网上供用户下载（当然在开发阶段，产品是放在一台测试服务器上的）。要保证开发过程中的<i>任何东西</i>的任何记录是由文档记录的而不是由某个人的脑子来记录的，这是唯一的办法。否则你会碰到这样的情况，产品需要发布了，可是只有Shaniqua知道如何将产品打包的，可是他刚刚被巴士撞了。在Juno公司（本文作者工作过的公司之一），要进行每日构建，你唯一需要学会的东西就是双击每日构建服务器桌面上的一个快捷方式。 
</li>
				<li>如果你在发行程序的当天发现了<i>一个小bug</i>，没有问题。修正它，然后重新运行每日构建脚本，现在你可以安安心心的发行程序了。当然，黄金定律是每日构建脚本应该是把所有的事情从头做一遍，遵循这个定律就不会有什么问题。 
</li>
				<li>将你的编译器的警告参数设到最大（在微软的VC中是-W4 ; 在GCC中是-Wall），当遇到任何一个最微小的警告时就应该停下来。 
</li>
				<li>如果每日构建失败了，可能整个开发团队的工作会因此进行不下去。当务之急是立刻找出原因，使得每日构建能成功进行下去。某天也许你会一天运行好几次每日构建脚本的。 
</li>
				<li>每日构建一旦失败，应该自动地将失败用email通知整个团队。提取错误日志中的恰当部分并包括在email正文中也不是很难。每日构建脚本也可以将当前的状态报告整理成一个html文件，自动发布到一个所有人都可以访问的web服务器上，这样测试者可以很快知道那个版本的构建是成功的。 
</li>
				<li>当我在微软的excel团队中工作时，我们的一个有效办法是，谁导致每日构建（daily build）失败，他（她）就得负责照看当日的每日构建（译者按：微软通常每日构建都在半夜），直到有另一个人导致构建失败而接替他（她）。这样做当然可以使每个开发者都小心不要因为自己代码的错误破坏了构建，更重要的是团队中的每个人都可以学会每日构建（daily build）的原理。 
</li>
				<li>如果你的团队在同一个时区工作，在午饭时间进行每日构建（daily build）是个不错的主意。午饭前每个程序员导入（check in）代码，这样当程序员在吃饭时，构建系统在工作。当程序员吃完饭回来时，如果每日构建失败了，所有的人也都在，可以尽快找出失败的原因。当构建系统运作起来时，没有人再会担心别人导入（check in）代码会妨碍自己的工作了。. 
</li>
				<li>如果你的团队同时在两个时区工作，计划好每日构建（daily build）的时间使得一个时区的工作不会影响另一个时区的工作。在Juno公司，纽约程序员在晚上7：00导入（check in）到版本控制服务器。如果他们的导入导致构建失败，印度Hyderabad市（译者按：印度科技重镇）的程序员在纽约时间晚上8：00以后的工作几乎无法进行下去。我们每天进行两次每日构建（daily build），每次构建的时间都在两地的程序员回家之前，这下就没有问题了。 </li>
		</ul>
		<p>更进一步的阅读：</p>
		<ul>
				<li>一些关于每日构建工具的<a href="http://discuss.fogcreek.com/joelonsoftware/default.asp?cmd=show&amp;ixPost=862">讨论</a></li>
				<li>做每日构建是很重要的，它是 <a href="http://chinese.joelonsoftware.com/Articles/TheJoelTest.html">获得高质量代码的12个步骤</a>之一。 
</li>
				<li>Windows NT team G. Pascal Zachary关于微软Windows NT团队每周构建的书中有一些很有趣的东西。<a href="http://www.amazon.com/exec/obidos/ASIN/0029356717/ref=nosim/joelonsoftware">超级明星（译者按：原文为showstopper，指特别受人喜爱，杰出之人或之物）</a>. 
</li>
				<li>Steve McConnell（译者按：著名的软件工程作家，Win2000开发组总负责人，其名著《Writing Solid Code》，《Debugging the Development Process》都有中文译本。） 写的关于每日构建（daily build）的文章在<a href="http://www.construx.com/stevemcc/bp04.htm">这里</a>. </li>
		</ul>
		<br /><img src ="http://www.cnitblog.com/tilan/aggbug/21908.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/tilan/" target="_blank">Joinclass Inc</a> 2007-01-16 11:05 <a href="http://www.cnitblog.com/tilan/archive/2007/01/16/21908.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>使用luntbuild进行每日构建 </title><link>http://www.cnitblog.com/tilan/archive/2007/01/16/21906.html</link><dc:creator>Joinclass Inc</dc:creator><author>Joinclass Inc</author><pubDate>Tue, 16 Jan 2007 02:56:00 GMT</pubDate><guid>http://www.cnitblog.com/tilan/archive/2007/01/16/21906.html</guid><wfw:comment>http://www.cnitblog.com/tilan/comments/21906.html</wfw:comment><comments>http://www.cnitblog.com/tilan/archive/2007/01/16/21906.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cnitblog.com/tilan/comments/commentRss/21906.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/tilan/services/trackbacks/21906.html</trackback:ping><description><![CDATA[<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
				<b style="mso-bidi-font-weight: normal">
						<font face="仿宋_GB2312">
								<font size="4">
										<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">概要</span>
										<span lang="EN-US">
												<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /?>
												<o:p>
												</o:p>
										</span>
								</font>
						</font>
				</b>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
				<font face="仿宋_GB2312">
						<font size="4">
								<b style="mso-bidi-font-weight: normal">
										<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">通过每日构建或者持续集成，项目组可以及早发现集成问题。现在它的意义已经为众多的开发团队所认识。一些重要问题的处理，如构建版本的分类和提升、与自动测试系统和项目或缺陷管理系统的集成，能够使项目组从中得到更多的收益。本文将对这些方面进行描述，并介绍作为开放源代码构建自动化和管理工具的</span>
										<span lang="EN-US">luntbuild</span>
								</b>
								<b style="mso-bidi-font-weight: normal">
										<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">在以上方面的努力。</span>
										<span lang="EN-US">
												<o:p>
												</o:p>
										</span>
								</b>
						</font>
				</font>
		</p>
		<h3 style="MARGIN: 13pt 0cm">
				<font face="仿宋_GB2312">
						<font size="5">
								<span lang="EN-US">1</span>
								<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">．每日构建和存在的问题</span>
								<span lang="EN-US">
										<o:p>
										</o:p>
								</span>
						</font>
				</font>
		</h3>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 8.9pt; mso-para-margin-left: .85gd">
				<font face="仿宋_GB2312">
						<font size="4">
								<b style="mso-bidi-font-weight: normal">
										<span lang="EN-US">1</span>
								</b>
								<b style="mso-bidi-font-weight: normal">
										<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">．</span>
										<span lang="EN-US">1 </span>
								</b>
								<b style="mso-bidi-font-weight: normal">
										<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">每日构建的一般机理</span>
										<span lang="EN-US">
												<o:p>
												</o:p>
										</span>
								</b>
						</font>
				</font>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 8.9pt; mso-para-margin-left: .85gd">
				<b>
						<span lang="EN-US">
								<o:p>
										<font face="仿宋_GB2312" size="4"> </font>
								</o:p>
						</span>
				</b>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 8.9pt; mso-para-margin-left: .85gd">
				<font face="仿宋_GB2312">
						<font size="4">
								<span style="FONT-FAMILY: 宋体; mso-bidi-font-weight: bold; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">如今，每日构建已经在许多项目中得到广泛的应用，以便及早发现集成问题。本文描述了建立每日构建系统中的一些想法，并</span>
								<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">介绍开放源代码的每日构建工具</span>
								<span lang="EN-US">luntbuild</span>
								<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">（</span>
								<span lang="EN-US">http://luntbuild.sf.net</span>
								<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">）。</span>
								<span lang="EN-US" style="mso-bidi-font-weight: bold">
										<o:p>
										</o:p>
								</span>
						</font>
				</font>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 10.35pt; TEXT-INDENT: -1.45pt; mso-para-margin-left: .85gd; mso-char-indent-count: -.14">
				<span lang="EN-US">
						<o:p>
								<font face="仿宋_GB2312" size="4"> </font>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 10.35pt; TEXT-INDENT: -1.45pt; mso-para-margin-left: .85gd; mso-char-indent-count: -.14">
				<font face="仿宋_GB2312">
						<font size="4">
								<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">每日构建的机理很简单：</span>
								<span lang="EN-US">
										<o:p>
										</o:p>
								</span>
						</font>
				</font>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 26.9pt; TEXT-INDENT: -18pt; mso-list: l0 level1 lfo1; tab-stops: list 26.9pt">
				<font face="仿宋_GB2312">
						<font size="4">
								<span lang="EN-US" style="mso-fareast-font-family: 'Times New Roman'">
										<span style="mso-list: Ignore">1．<span style="FONT: 7pt 'Times New Roman'">  </span></span>
								</span>
								<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">定期（如每夜）检查源代码库</span>
						</font>
				</font>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 26.9pt; TEXT-INDENT: -18pt; mso-list: l0 level1 lfo1; tab-stops: list 26.9pt">
				<font face="仿宋_GB2312">
						<font size="4">
								<span lang="EN-US" style="mso-fareast-font-family: 'Times New Roman'">
										<span style="mso-list: Ignore">2．<span style="FONT: 7pt 'Times New Roman'">  </span></span>
								</span>
								<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">如果源代码库中发生改变将触发构建和后续的冒烟测试</span>
						</font>
				</font>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 26.9pt; TEXT-INDENT: -18pt; mso-list: l0 level1 lfo1; tab-stops: list 26.9pt">
				<font face="仿宋_GB2312">
						<font size="4">
								<span lang="EN-US" style="mso-fareast-font-family: 'Times New Roman'">
										<span style="mso-list: Ignore">3．<span style="FONT: 7pt 'Times New Roman'">  </span></span>
								</span>
								<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">给源代码库的当前构建作一个标签，以便将来可以提取当前构建进行重新构建</span>
						</font>
				</font>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 26.9pt; TEXT-INDENT: -18pt; mso-list: l0 level1 lfo1; tab-stops: list 26.9pt">
				<font face="仿宋_GB2312">
						<font size="4">
								<span lang="EN-US" style="mso-fareast-font-family: 'Times New Roman'">
										<span style="mso-list: Ignore">4．<span style="FONT: 7pt 'Times New Roman'">  </span></span>
								</span>
								<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">给相应开发人员发送报告构建情况的</span>
								<span lang="EN-US">email</span>
								<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">。</span>
						</font>
				</font>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 8.9pt; mso-para-margin-left: .85gd">
				<span lang="EN-US">
						<o:p>
								<font face="仿宋_GB2312" size="4"> </font>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 8.9pt; mso-para-margin-left: .85gd">
				<font face="仿宋_GB2312">
						<font size="4">
								<span lang="EN-US">XP</span>
								<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">方法的持续集成风格也具有与每日构建相同的机理</span>
						</font>
				</font>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 10.35pt; TEXT-INDENT: -1.45pt; mso-para-margin-left: .85gd; mso-char-indent-count: -.14">
				<span lang="EN-US">
						<o:p>
								<font face="仿宋_GB2312" size="4"> </font>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 10.4pt; TEXT-INDENT: -1.5pt; mso-para-margin-left: .85gd; mso-char-indent-count: -.14">
				<font face="仿宋_GB2312">
						<font size="4">
								<b style="mso-bidi-font-weight: normal">
										<span lang="EN-US">1</span>
								</b>
								<b style="mso-bidi-font-weight: normal">
										<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">．</span>
										<span lang="EN-US">2 </span>
								</b>
								<b style="mso-bidi-font-weight: normal">
										<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">每日构建存在的问题</span>
										<span lang="EN-US">
												<o:p>
												</o:p>
										</span>
								</b>
						</font>
				</font>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 8.9pt; mso-para-margin-left: .85gd">
				<span lang="EN-US">
						<br />
				</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">
						<font face="仿宋_GB2312" color="#000000" size="4">如果下列方面能够得到妥善处理，项目组可以从每日构建系统中获得除尽早发现集成问题之外的好处。</font>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 8.9pt; mso-para-margin-left: .85gd">
				<span lang="EN-US">
						<o:p>
								<font face="仿宋_GB2312" size="4"> </font>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 8.9pt; mso-para-margin-left: .85gd">
				<font face="仿宋_GB2312">
						<font size="4">
								<span lang="EN-US">1</span>
								<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">．为了给并行开发提供最大程度的构建支持，构建系统应该可以将源代码库中来自不同分支或有不同标签的模块组合起来进行构建。这一点对于大项目的开发尤其重要。</span>
						</font>
				</font>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 8.9pt">
				<span lang="EN-US">
						<o:p>
								<font face="仿宋_GB2312" size="4"> </font>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 8.9pt">
				<font face="仿宋_GB2312">
						<font size="4">
								<span lang="EN-US">2</span>
								<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">．历史构建应该能够进行很好的管理。在项目开发尤其是持续集成过程中会产生大量的构建版本，因此，应该能够将他们加以分类以确定一些重要的构建。实现的方法有两个：第一个方法是将一个已经存在的低级构建版本（如通过每日构建产生的一个版本）提升进高级构建类（如测试构建类）。由于分类是在构建完成之后进行的，这种方法被称为后构建标识。第二个方法是直接在指定的类中构建。由于构建类是在构建之前就确定了，这种方法被称为前构建标识。除了分类，系统还应该能查找或删除历史构建。系统可以很方便地找到指定版本、日期、状态等的构建，这就能够在大量的历史构建中搜寻而快速地找到指定的构建。通过删除不重要的历史构建，可以节省存储空间。</span>
								<span lang="EN-US">
										<o:p>
										</o:p>
								</span>
						</font>
				</font>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 8.9pt">
				<span lang="EN-US">
						<o:p>
								<font face="仿宋_GB2312" size="4"> </font>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 8.9pt">
				<font face="仿宋_GB2312">
						<font size="4">
								<span lang="EN-US">3</span>
								<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">．当开发大项目时，需要构建记录不仅应该包含最终的分发包，还应该包含一些中间文件或是调试版本文件。因此，构建系统除了替项目组对源代码库进行集成校验外，还提供近期的开发基准或是调试环境。这样，将来可以很方便地通过发出一个命令实现下载特定构建的相关文件并更新开发环境。</span>
								<span lang="EN-US">
										<o:p>
										</o:p>
								</span>
						</font>
				</font>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 8.9pt">
				<span lang="EN-US">
						<o:p>
								<font face="仿宋_GB2312" size="4"> </font>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 8.9pt">
				<font face="仿宋_GB2312">
						<font size="4">
								<span lang="EN-US">4</span>
								<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">．当控制访问不同的项目或者是系统的构建或功能时，特别是系统由多个项目构成或是可以被客户下载的等情况，需要使用访问控制机制进行访问控制。</span>
						</font>
				</font>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 8.9pt">
				<span lang="EN-US">
						<o:p>
								<font face="仿宋_GB2312" size="4"> </font>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 8.9pt">
				<font face="仿宋_GB2312">
						<font size="4">
								<span lang="EN-US">5</span>
								<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">．每日构建系统必须能够与项目管理、缺陷跟踪系统建立连接，这样才能方便地建立并保持构建和</span>
								<span lang="EN-US">bug/feature</span>
								<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">之间的关系。例如，某开发人员提交一个</span>
								<span lang="EN-US">bug</span>
								<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">给缺陷管理系统申明该</span>
								<span lang="EN-US">bug</span>
								<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">将在下一个构建中改正，当下次构建完成之后构建管理系统将通知缺陷管理系统刚刚完成构建的版本号，从而缺陷跟踪系统能够知道该开发人员刚刚提交的</span>
								<span lang="EN-US">bug</span>
								<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">在哪个版本中被提交。并且，当发布一个特定的版本时，构建系统可以与缺陷管理系统连接以获得本版本处于不同状态的的</span>
								<span lang="EN-US">bug/feature</span>
								<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">列表和描述，并写入</span>
								<span lang="EN-US">release notes</span>
								<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">中。</span>
						</font>
				</font>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 8.9pt">
				<span lang="EN-US">
						<o:p>
								<font face="仿宋_GB2312" size="4"> </font>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 8.9pt">
				<font face="仿宋_GB2312">
						<font size="4">
								<span lang="EN-US">6</span>
								<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">．每日构建系统必须可以与自动测试系统连接以便在构建完成后除单元测试外的进一步测试。例如，构建系统在生成一个新的构建版本之后将通知自动测试系统，接到通知后，测试系统将下载新的构建版本，将其安装并进行项目跟踪系统所要求的冒烟测试等。</span>
						</font>
				</font>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 8.9pt">
				<span lang="EN-US">
						<o:p>
								<font face="仿宋_GB2312" size="4"> </font>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 8.9pt">
				<font face="仿宋_GB2312">
						<font size="4">
								<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">实现以上提到的每日构建系统的各个功能并不象安装一个每日构建系统那么容易。在研究了已有的工具之后，我打算开发一个全新的自动构建工具——</span>
								<span lang="EN-US">luntbuild</span>
								<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，它可以逐步实现上述功能。当前发布的</span>
								<span lang="EN-US">1.0.2</span>
								<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">版本除了具有每日构建系统或持续集成工具的基本功能之外，还可以实现上述的</span>
								<span lang="EN-US">1</span>
								<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">、</span>
								<span lang="EN-US">2</span>
								<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">、</span>
								<span lang="EN-US">3</span>
								<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">功能。下文将介绍</span>
								<span lang="EN-US">luntbuild</span>
								<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，解释它在这些方面的功能。</span>
						</font>
				</font>
		</p>
		<h3 style="MARGIN: 13pt 0cm">
				<font face="仿宋_GB2312">
						<font size="5">
								<span lang="EN-US">2</span>
								<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">．</span>
								<span lang="EN-US">Luntbuild</span>
								<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">如何解决上述问题</span>
								<span lang="EN-US">
										<o:p>
										</o:p>
								</span>
						</font>
				</font>
		</h3>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
				<font face="仿宋_GB2312">
						<font size="4">
								<span lang="EN-US">Luntbuild</span>
								<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">不仅仅是一个每日构建和持续集成工具，而是一个自动构建和管理的系统。它基于</span>
								<span lang="EN-US">apache ant</span>
								<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，需要存在一个</span>
								<span lang="EN-US">ant build</span>
								<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">脚本。而通过提供一个</span>
								<span lang="EN-US">ant</span>
								<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">脚本封装，</span>
								<span lang="EN-US">ant</span>
								<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">脚本的编写会变得十分容易。在用户手册中详细说明了具体步骤。</span>
						</font>
				</font>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
				<span lang="EN-US">
						<o:p>
								<font face="仿宋_GB2312" size="4"> </font>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 41.9pt; TEXT-INDENT: -33pt; mso-list: l1 level2 lfo2; tab-stops: list 41.9pt">
				<font face="仿宋_GB2312">
						<font size="4">
								<b style="mso-bidi-font-weight: normal">
										<span lang="EN-US" style="mso-fareast-font-family: 'Times New Roman'">
												<span style="mso-list: Ignore">2.1 </span>
										</span>
								</b>
								<b style="mso-bidi-font-weight: normal">
										<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">对并行开发提供构建支持</span>
										<span lang="EN-US">
												<o:p>
												</o:p>
										</span>
								</b>
						</font>
				</font>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
				<b style="mso-bidi-font-weight: normal">
						<span lang="EN-US">
								<o:p>
										<font face="仿宋_GB2312" size="4"> </font>
								</o:p>
						</span>
				</b>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 10.35pt; TEXT-INDENT: -1.45pt; mso-para-margin-left: .85gd; mso-char-indent-count: -.14">
				<font face="仿宋_GB2312">
						<font size="4">
								<span lang="EN-US">Luntbuild</span>
								<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">利用项目、视图、模块和计划的概念来自动化和管理构建。项目表示实际的项目以及对应的源代码库。模块表示一组具有版本号的目录以及文件，通常是一个特定分支上或者由特定标签标识的一个源代码目录路径。视图包含若干模块，而项目又包含若干视图。下面举例对此进行说明：</span>
						</font>
				</font>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 10.3pt; TEXT-INDENT: 10.7pt; mso-para-margin-left: .98gd">
				<font face="仿宋_GB2312">
						<font size="4">
								<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">在</span>
								<span lang="EN-US">luntbuild</span>
								<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">中配置一个</span>
								<span lang="EN-US">cvs</span>
								<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">项目“</span>
								<span lang="EN-US">footbar</span>
								<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">”，假定</span>
								<span lang="EN-US">footbar</span>
								<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">包含“</span>
								<span lang="EN-US">src</span>
								<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">”和“</span>
								<span lang="EN-US">web</span>
								<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">”两个目录，“</span>
								<span lang="EN-US">src</span>
								<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">”包含功能源代码而“</span>
								<span lang="EN-US">web</span>
								<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">”包含</span>
								<span lang="EN-US">web</span>
								<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">界面的</span>
								<span lang="EN-US">html</span>
								<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">文件。我们首先创建一个由主分支上的“</span>
								<span lang="EN-US">src</span>
								<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">”和“</span>
								<span lang="EN-US">web</span>
								<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">”模块组成的“</span>
								<span lang="EN-US">development</span>
								<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">”视图，该视图计划每晚构建。开发顺利进行，某日发布了“</span>
								<span lang="EN-US">foobar-1.0 build123</span>
								<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">”并出售给客户。后来，客户反馈的</span>
								<span lang="EN-US">bug</span>
								<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">与“</span>
								<span lang="EN-US">src</span>
								<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">”目录中代码有关。为了解决这些</span>
								<span lang="EN-US">bug</span>
								<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，我们在源代码管理系统中为“</span>
								<span lang="EN-US">src</span>
								<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">”目录创建“</span>
								<span lang="EN-US">1_0_bugfix</span>
								<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">”分支，同时，在</span>
								<span lang="EN-US">luntbuild</span>
								<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的“</span>
								<span lang="EN-US">footbar</span>
								<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">”项目下创建“</span>
								<span lang="EN-US">foobar1.0-bugfix</span>
								<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">”视图，配置两个模块：“</span>
								<span lang="EN-US">1_0_bugfix</span>
								<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">”分支上的“</span>
								<span lang="EN-US">src</span>
								<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">”模块，和“</span>
								<span lang="EN-US">foobar-1_0-build123</span>
								<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">”标签上的“</span>
								<span lang="EN-US">web</span>
								<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">”模块。该视图的构建计划仍然是每天晚上。这样，新功能和改正</span>
								<span lang="EN-US">bug</span>
								<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的开发工作有单独的视图，并且可以分别按计划进行每日构建。</span>
								<span lang="EN-US">
										<o:p>
										</o:p>
								</span>
						</font>
				</font>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 8.9pt; mso-para-margin-left: .85gd">
				<b style="mso-bidi-font-weight: normal">
						<span lang="EN-US">
								<o:p>
										<font face="仿宋_GB2312" size="4"> </font>
								</o:p>
						</span>
				</b>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 8.9pt; mso-para-margin-left: .85gd">
				<font face="仿宋_GB2312">
						<font size="4">
								<b style="mso-bidi-font-weight: normal">
										<span lang="EN-US">2.2 </span>
								</b>
								<b style="mso-bidi-font-weight: normal">
										<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">对历史构建管理的支持</span>
										<span lang="EN-US">
												<o:p>
												</o:p>
										</span>
								</b>
						</font>
				</font>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 8.9pt; mso-para-margin-left: .85gd">
				<span lang="EN-US">
						<o:p>
								<font face="仿宋_GB2312" size="4"> </font>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 8.9pt; mso-para-margin-left: .85gd">
				<font face="仿宋_GB2312">
						<font size="4">
								<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">在</span>
								<span lang="EN-US">luntbuild</span>
								<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">中，计划不仅用于实现自动构建，还用于实现构建分类。计划被创建之后，可以与特定的视图相关联。这种视图</span>
								<span lang="EN-US">-</span>
								<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">计划对被称为“构建计划”或“构建分类”。为了支持多个构建分类，一个视图可以与多个计划相关联。例如，你可以给开发视图关联三个计划：“每小时”、“每晚”和“发布构建”。“每小时”和“每晚”计划将自动被触发，而“发布构建”计划只能手动触发。为了提高构建速度，我们将“每小时”计划配置为增量构建；为了避免源代码库中的标签过多，我们将“每小时”计划的策略选为“不设标签”。“每小时”计划主要为“持续集成”而设置，这样，可以保证源代码库的一致性。为了提高可靠性，我们将“每晚”计划配置为干净构建；为了使所有的夜晚构建可再现，我们将“每晚”计划的策略选为“在构建成功时进行标签”。“每晚”计划为“更新开发环境”而设置，这将用于更新开发人员的开发环境。“发布构建”计划为维护所有已经发布出去的构建而设置，该构建类中的版本可以是手工触发该类中的构建而生成（即构建前标识），或者是采用构建后标识方法将其他构建类（如每晚构建类中的经过测试过的版本）提升到本类中。</span>
						</font>
				</font>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 8.9pt; mso-para-margin-left: .85gd">
				<span lang="EN-US">
						<o:p>
								<font face="仿宋_GB2312" size="4"> </font>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 8.9pt; mso-para-margin-left: .85gd">
				<font face="仿宋_GB2312">
						<font size="4">
								<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">除了构建分类和提升，</span>
								<span lang="EN-US">luntbuild</span>
								<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">还可以严格或不严格匹配地查找某个版本号的构建，查找指定时间范围、状态或特定构建类中的构建。可以删除查找结果或是特定的构建版本。这样，就可以很方便地执行某些操作比如查找失败的历史构建并删除之。<br /></span>
						</font>
				</font>
				<span lang="EN-US">
						<br />
				</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">
						<font style="BACKGROUND-COLOR: #ffffff" face="仿宋_GB2312" color="#000000" size="4">而且对于某个特定的构建版本，可以删除它下面的文件，或者上传新的文件。从而达到为某个特定的构建版本打补丁的目的。</font>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 8.9pt; mso-para-margin-left: .85gd">
				<span lang="EN-US">
						<o:p>
								<font face="仿宋_GB2312" size="4"> </font>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 8.9pt; mso-para-margin-left: .85gd">
				<font face="仿宋_GB2312">
						<font size="4">
								<b style="mso-bidi-font-weight: normal">
										<span lang="EN-US">2.3 </span>
								</b>
								<b style="mso-bidi-font-weight: normal">
										<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">对设置最新开发环境的支持</span>
										<span lang="EN-US">
												<o:p>
												</o:p>
										</span>
								</b>
						</font>
				</font>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 8.9pt; mso-para-margin-left: .85gd">
				<span lang="EN-US">
						<o:p>
								<font face="仿宋_GB2312" size="4"> </font>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 8.9pt; mso-para-margin-left: .85gd">
				<font face="仿宋_GB2312">
						<font size="4">
								<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">在</span>
								<span lang="EN-US">luntbuild</span>
								<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">中，特定构建版本所发布的文件是由用户提供的构建脚本决定的，</span>
								<span lang="EN-US">luntbuild</span>
								<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">仅仅提供一个发布文件的根目录。所以您可以自由选择要在</span>
								<span lang="EN-US">luntbuild</span>
								<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">中发布的文件。对于大项目来说，如果最新的开发环境包（如调试版本文件等）可以与最终分发包一起发布，开发人员就不需要花很长的时间来编译其他开发人员的代码以更新环境，这将带来极大的便利。</span>
						</font>
				</font>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 8.9pt; mso-para-margin-left: .85gd">
				<span lang="EN-US">
						<o:p>
								<font face="仿宋_GB2312" size="4"> </font>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 8.9pt; mso-para-margin-left: .85gd">
				<font face="仿宋_GB2312">
						<font size="4">
								<b style="mso-bidi-font-weight: normal">
										<span lang="EN-US">2.4 </span>
								</b>
								<b style="mso-bidi-font-weight: normal">
										<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">正在开发中的功能</span>
										<span lang="EN-US">
												<o:p>
												</o:p>
										</span>
								</b>
						</font>
				</font>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 8.9pt; mso-para-margin-left: .85gd">
				<span lang="EN-US">
						<o:p>
								<font face="仿宋_GB2312" size="4"> </font>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 8.9pt; mso-para-margin-left: .85gd">
				<font face="仿宋_GB2312">
						<font size="4">
								<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">所有的单体测试或冒烟测试应在构建脚本中进行，</span>
								<span lang="EN-US">luntbuild</span>
								<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">捕获脚本运行的输出结果，并最终发送给为失败视图负责的开发人员（邮件策略是可以配置的，你可以选择每次构建都发送邮件或是不发送邮件）。将来，</span>
								<span lang="EN-US">luntbuild</span>
								<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">会以图形的方式显示测试结果，这会比用原始的日志文件表示得更加清楚。</span>
						</font>
				</font>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 8.9pt; mso-para-margin-left: .85gd">
				<span lang="EN-US">
						<o:p>
								<font face="仿宋_GB2312" size="4"> </font>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 8.9pt; mso-para-margin-left: .85gd">
				<font face="仿宋_GB2312">
						<font size="4">
								<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">目前，</span>
								<span lang="EN-US">luntbuild</span>
								<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">尚未实现访问控制。当在开放环境中使用</span>
								<span lang="EN-US">luntbuild</span>
								<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">时，访问控制功能具有重要的意义，因此，现在正在设计这个功能，在日后发布的版本中将会实现。</span>
						</font>
				</font>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 8.9pt; mso-para-margin-left: .85gd">
				<span lang="EN-US">
						<o:p>
								<font face="仿宋_GB2312" size="4"> </font>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 8.9pt; mso-para-margin-left: .85gd">
				<font face="仿宋_GB2312">
						<font size="4">
								<span lang="EN-US">Luntbuild</span>
								<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">尚不能与第三方项目管理</span>
								<span lang="EN-US">/</span>
								<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">缺陷跟踪系统或是自动测试系统连接。这项功能将在日后发布的版本中实现。第一步是提供</span>
								<span lang="EN-US">web-service</span>
								<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">类</span>
								<span lang="EN-US">API</span>
								<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，使其他系统可以方便地访问</span>
								<span lang="EN-US">luntbuild</span>
								<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">构建信息。</span>
						</font>
				</font>
		</p><img src ="http://www.cnitblog.com/tilan/aggbug/21906.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/tilan/" target="_blank">Joinclass Inc</a> 2007-01-16 10:56 <a href="http://www.cnitblog.com/tilan/archive/2007/01/16/21906.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>StarTeam软件协作解决方案</title><link>http://www.cnitblog.com/tilan/archive/2007/01/15/21897.html</link><dc:creator>Joinclass Inc</dc:creator><author>Joinclass Inc</author><pubDate>Mon, 15 Jan 2007 15:25:00 GMT</pubDate><guid>http://www.cnitblog.com/tilan/archive/2007/01/15/21897.html</guid><wfw:comment>http://www.cnitblog.com/tilan/comments/21897.html</wfw:comment><comments>http://www.cnitblog.com/tilan/archive/2007/01/15/21897.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cnitblog.com/tilan/comments/commentRss/21897.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/tilan/services/trackbacks/21897.html</trackback:ping><description><![CDATA[<p>
				<font color="#ff0000">根据The Standish Group International, Inc.的研究报告，40%的软件开发项目在完成前被取消，33%的项目延期或超支。如果像这样搞建筑项目，您能够想象一下纽约城会变成什么样子？</font>
		</p>
		<p>
				<b>协同是关键</b>
		</p>
		<p>从开发环境到版本控制，你常常会走过又一个循环：采购工具，使用培训，围绕着工具使用建立内部开发过程，日常应用等等。希望在合同到期时能够顺利完成并且没有超支...</p>
		<p>让我们来问这样一个问题：<font color="#ff0000">下一步是什么？</font></p>
		<p align="left">在你让开发小组提高了一点点效率之后，在你配置了开发工具之后，你仍然需要保持竞争力，<font color="#ff0000">下一步改善那里能够获得最大的生产力？</font></p>
		<p align="left">我们要求你看一下目前你周围的信息组织，你一定能看到不同的开发小组，同时你也能够发现其它许多技术上的协作者，如文档、外部资源、客户、设计人员等等。你将发现不同的开发小组的数量在增加，麻烦也在增加。你还能发现合作者分散在不同的部门或不同的地方。</p>
		<p align="left">当你看到这一切时，相信你会认识到项目组织中存在的噪音和混乱带来了沉重的经济负担。你将意识到这是下一步提高生产力的突破点，不是其它的技术工具，也不是下一个更快的编译器。</p>
		<p align="left">下一个效益增长点将来自管理，简化技术协作，使不同的小组以一种更快速而简单的方式共享工作中的相关信息，从而降低“项目组织中的噪音”，而且使优秀的小组不会被拖住后腿。换句话说，<font color="#ff0000">你的下一个效益增长点将来自实现你的信息组织中所有成员之间的协同工作。</font></p>
		<hr size="1" />
		<table cellspacing="0" cellpadding="0" width="400" border="0">
				<tbody>
						<tr>
								<td>
										<img height="274" alt="techcoll_why1.gif (13069 bytes)" src="http://www.huihoo.com/development/i/techcoll_why1.gif" width="250" />
								</td>
								<td valign="top">
										<font color="#008080">
												<span style="FONT-SIZE: 10.5pt; LINE-HEIGHT: 20px">“我只需要版本控制，或许是软件配置管理...</span>
										</font>
										<p>
												<font color="#008080">
														<span style="FONT-SIZE: 10.5pt; LINE-HEIGHT: 20px">何必要协同呢？”</span>
												</font>
										</p>
								</td>
						</tr>
				</tbody>
		</table>
		<center>
		</center>
		<div>
		</div>
		<p>获得协同的动机依赖于企业内信息组织的个体：应用开发组（如上图中的Tom），应用开发管理（如Ann）和技术协作者（如文档、帮助平台和客户等等），他们参与不同的软件活动，所以会有各自的看法。</p>
		<p>例如，让我们考虑一下Tom，作为软件开发组长，他可能在应用开发和维护领域有特长，因此自然会倾向于采用专门技术，如版本控制等。那么Tom是否需要技术协作？</p>
		<p>　</p>
		<hr size="1" />
		<p>
				<font face="黑体" color="#000000">
						<big>从哪儿提高生产力</big>
				</font>
		</p>
		<p>　</p>
		<div align="center">
				<center>
						<table cellspacing="0" cellpadding="0" width="400" border="0">
								<tbody>
										<tr>
												<td>
														<img height="274" alt="techcoll_why2.gif (11416 bytes)" src="http://www.huihoo.com/development/i/techcoll_why2.gif" width="250" />
												</td>
												<td valign="top">
														<font color="#008080">
																<span style="FONT-SIZE: 10.5pt; LINE-HEIGHT: 20px">版本控制和软件配置管理通过加强日常开发环境的控制，很快得到了大家的认可。但是它们能进一步提高生产力吗？</span>
														</font>
												</td>
										</tr>
								</tbody>
						</table>
				</center>
		</div>
		<p>许多已经使用了版本控制和软件配置管理工具和软件组织，很快发现生产力的提高比预期的要低，下面列出了其中一些原因：<i><ul></ul></i></p>
		<li>不同的项目组使用不同的工具，降低了效率。但搞统一是不合理的，违背自然规律。 
</li>
		<li>不同工具之间有“隔阂”，难于重用数据，也减少了项目组之间的交流。 
</li>
		<li>已有的版本控制工具不能支持远程用户，或者性能明显退化（如一个基于文件服务器的工具，当在WAN或Internet上使用时，会变得非常迟缓）。 </li>
		<p>考虑到上述因素，很明显Tom肯定会对技术协作发生兴趣： 
</p>
		<ul type="DISC">
				<li>建立在版本控制和软件配置管理之上，提供对信息技术资源的准确访问。 
</li>
				<li>通过无缝访问不同的版本控制工具促进代码共享。 
</li>
				<li>从任何地方访问（LAN/WAN/Internet/WEB），改善已有的版本控制工具 
</li>
				<li>从其它平台（通过统一的JAVA客户端），扩展垮平台的代码共享和重用。 
</li>
				<li>提供一个具有高度伸缩性的现代化体系结构，使得将工具扩展到其它领域和功能范畴成为可能。 </li>
		</ul>
		<p>StarTeam满足所有上述需求，它具有： 
</p>
		<ul type="DISC">
				<li>与PVCS和SourceSafe的互操作性， 
</li>
				<li>完全的地理位置独立性， 
</li>
				<li>客户/服务器体系结构，为Internet和WAN开发环境特别优化， 
</li>
				<li>能够运行在任何JAVA平台上的统一的客户端应用。 </li>
		</ul>
		<p>更重要的是，StarTeam支持开发队伍建立一个协同工作的稳固基础的需要。</p>
		<p>　</p>
		<hr size="1" />
		<p>
				<big>
						<font face="黑体">队伍中的其它部分怎么办？</font>
				</big>
		</p>
		<p>　</p>
		<div align="center">
				<center>
						<table cellspacing="0" cellpadding="0" width="400" border="0">
								<tbody>
										<tr>
												<td>
														<img height="274" alt="techcoll_why3.gif (11407 bytes)" src="http://www.huihoo.com/development/i/techcoll_why3.gif" width="250" />
												</td>
												<td valign="top">
														<font color="#008080">
																<span style="FONT-SIZE: 10.5pt; LINE-HEIGHT: 20px">我的需求还未满足：我要求所有的项目组能够协调工作！我要求他们能够共享和重用，不管他们用什么样的版本控制工具，并且我需要能够完全有关联性地访问技术上的协作者，即使他们可能并不是技术方面的。</span>
														</font>
												</td>
										</tr>
								</tbody>
						</table>
				</center>
		</div>
		<p>迄今为止，Tom已有了他所需要的版本控制和软件配置管理工具，如StarTeam Versions、 PVCS或Visual SourceSafe等。</p>
		<p>但这仍然无法解决团队中其它人员的需要，如Ann。这些需要是： 
</p>
		<ul>
				<b>
						<li>项目组之间的协同：</li>
				</b>Tom、John和Mary使用不同的工具，他们之间在代码共享和重用上有一定的困难。 
<li><strong>系统资源的公共访问，</strong>而不管使用哪个版本数据库。像PVCS和SourceSafe这样的配置管理工具都是很专门的，使用不同的术语和操作。因此，你可能需要访问John和Mary使用的两种完全不同的系统。 
</li><li>需要支持位于<strong>不同地点</strong>的项目组成员，而且可能是动态变化的，比如你需要在用户现场干一段。 
</li><li><strong>快速、直观地访问开发相关的内容</strong>，包括文档、计划、外部资源、管理、帮助平台和客户等不具有“软件开发头脑”的对象。除非选择一个非常容易使用、高度集成和直观的解决方案，否则要将技术协作集成到开发功能中几乎是不可能的。 </li></ul>
		<p>因此，单纯的技术工具与期望尚有一段距离。版本控制和软件配置管理是不可缺少的工具（否则如何安全地管理信息技术财富？），但它们不是设计成用于解决协同工作需要的。</p>
		<p>　</p>
		<hr size="1" />
		<p>
				<big>
						<font face="黑体">协同将他们结合在一起</font>
				</big>
		</p>
		<p>　</p>
		<div align="center">
				<center>
						<table cellspacing="0" cellpadding="0" width="400" border="0">
								<tbody>
										<tr>
												<td>
														<img height="274" alt="techcoll_why4.gif (16484 bytes)" src="http://www.huihoo.com/development/i/techcoll_why4.gif" width="250" />
												</td>
												<td valign="top">
														<font color="#008080">
																<span style="FONT-SIZE: 10.5pt; LINE-HEIGHT: 20px">一个真正的协同解决方案支持所有的功能范畴和团队，无论他们是处在传统软件开发环境之内还是之外。</span>
														</font>
												</td>
										</tr>
								</tbody>
						</table>
				</center>
		</div>
		<p>StarTeam提供了真正的协同工作，使得开发环境内外的所有的功能范畴和团队能够积极参与共同的活动。协同自底向上建立：底层是安全地控制和管理信息技术财富，上层是协同： 
</p>
		<ul>
				<li>
						<strong>版本控制</strong>和<strong>配置管理</strong>功能没有这一关键的功能。 
</li>
				<li>
						<strong>透明的</strong>跨引擎（不同的工具）<strong>互操作性</strong>。 
</li>
				<li>一个提供访问你的所有软件资源的<strong>协同框架</strong>。 
</li>
				<li>允许已有的用户继续使用其版本控制工具的能力，<strong>保护已有的投资</strong>。 
</li>
				<li>完全的<strong>位置独立性</strong>。 
</li>
				<li>
						<strong>平台独立性</strong>（LAN/WAN/Internet/WEB）。 
</li>
				<li>一个获奖的、<strong>非常容易使用的图形用户界面</strong>，非技术性用户也能应付自如。 
</li>
				<li>文件、交流和变化请求等所有应用资源之间的<strong>关联</strong>。 
</li>
				<li>
						<strong>虚拟的信息资源视图</strong>，允许每个项目成员将信息资源看作只与自己有关，并支持直观的进度、生命周期状态、产品版本、基线版本和私有配置。 
</li>
				<li>完全<strong>集成的变化请求管理</strong>，集成在一个更高、更有意义的层次上。 </li>
		</ul>
		<p>你可以发现，这些额外的功能特性并不仅仅提供了对软件配置管理的支持。更重要的是，在软件配置管理的基础上建立技术协同。</p>
		<p>StarTeam所提供的协同能力，能够真正提高生产力并取得竞争优势：所有成员主动合作和共享相关资源，实现更快、更好的目标。</p>
		<p>总之，StarTeam是一个真正的技术协同解决方案。</p>
		<hr size="1" />
		<p>　</p>
		<table cellspacing="0" cellpadding="5" width="763" border="0">
				<tbody>
						<tr>
								<td width="252">
										<img height="248" alt="techcoll_what1.gif (27453 bytes)" src="http://www.huihoo.com/development/i/techcoll_what1.gif" width="250" />
								</td>
								<td valign="top" width="491">　 
<p><font color="#008080"><span style="FONT-SIZE: 10.5pt; LINE-HEIGHT: 20px">从里到外建立协同。</span></font></p></td>
						</tr>
				</tbody>
		</table>
		<p>所有的协同工具都有一个共同的目标：允许一起工作的人们快速有效地共享关联信息。这样就容易确定专业范围，并使在公共领域中的交流更方便。</p>
		<p>因此，技术和事务协同解决方案适合于建立一个公共的、易于实现的工作人员协同工作的环境。</p>
		<p>但是，技术和事务协同在一下三方面有重要差别：</p>
		<table cellspacing="0" cellpadding="5" width="100%" border="0">
				<ul type="DISC">
						<b>
								<i>
										<li>
										</li>
								</i>使用的技术财富：</b>事务协同的对象是办公文档和文件，而技术协同的对象是软件财富。 
<li><strong>核心人员：</strong>事务协同将办公人员集合在一起；技术协同的首要也是最重要的目的是解决软件开发人员（包括管理和技术合作者）的需求。 
</li><li><strong>使用的关联信息的复杂性：</strong>技术协同必须共享高度复杂的关联信息，其中这些关系不是立即显现的，也不会包含所有的交流内容（即交谈内容必须能被以后的合作者多次访问）。而事务合作更有时效性，简单的关联和短期的交流。 
<ul></ul><p><big><font face="黑体">版本控制和配置管理基础</font></big></p><p>由于技术协同要求安全可靠、可审核以及有效地访问企业的关键应用，它必须建立在强大的版本控制和配置管理上...一个事务文件通常随着版本发展，而应用部件必须是可以在时间上游动的，即能够支持频繁的回溯和修订。</p><p>进一步，技术协同必须与开发人员日常使用的工具和环境紧密集成在一起。</p><p><big><font face="黑体">特别支持软件开发</font></big></p><p>除非软件开发小组利用技术协同系统，否则所有的协同将会停止在与信息组织的其余部分分隔开来的地方。这就是StarTeam为什么提供扩展的开发支持功能的原因，如差异比较、可视化合并、版本标签（version labeling）、审核印迹（audit trails）、表示阶段的虚拟视图、时间游动事例（time-travel instances）和私有对象等等。</p><p><big><font face="黑体">信息关联的表达和共享</font></big></p><p>为了支持复杂关联信息的共享和重用，技术协同工具必须能够做到： 
</p><ul type="DISC"><li>适当地表示关系，通过一个通用化的链接引擎支持所有在协同信息库中跟踪的对象之间的扩展链接。StarTeam将这种链接扩充到文件、版本、变化请求和会话。 
</li><li>支持同一个数据库的多虚拟视图，因此每一个功能范围都能够“看到”与之有关的关联内容。StarTeam通过最先进的虚拟视图支持这种需求，从协同环境的所有对象中虚拟选择，从而实现生命周期阶段化、时间游动、调试、私有视图和其它许多功能。 
</li><li>不断积累应用开发中产生的知识，使得诸如文档、帮助平台、质量保证人员等等能够快速有效地共享这些知识，而不会额外增加沟通成本。 </li></ul></li><tbody><tr><td><img height="248" alt="techcoll_what2.gif (30594 bytes)" src="http://www.huihoo.com/development/i/techcoll_what2.gif" width="250" /></td><td valign="top"><span style="FONT-SIZE: 10.5pt">因此，技术协同加强了“同心环”之间的合作，从开发环境向外扩展到：</span><ul><li><span style="FONT-SIZE: 10.5pt">技术协同</span></li><li><span style="FONT-SIZE: 10.5pt">程序管理办公室（PMO）</span></li><li><span style="FONT-SIZE: 10.5pt">项目管理功能（PM）</span></li></ul><p><span style="FONT-SIZE: 10.5pt">下面我们将看到，这些不同的功能组的需求是有差别的，但是它们都有一个共同的目标－技术协同。</span></p></td></tr><ul></ul></tbody></ul>
		</table>
		<p>　</p>
		<hr size="1" />
		<p>
				<big>
						<big>
								<font face="黑体">开发需求</font>
						</big>
				</big>
		</p>
		<font color="#0066ff">
				<b>
						<i>
								<p>
								</p>
						</i>
				</b>
		</font>当前的分布式开发环境强调软件配置管理解决方案的能力： 
<ul type="DISC"><b><i><li></li></i>产品化的信息库：</b>StarTeam提供一个可伸缩、成熟的信息库，完全面向对象，版本化<strong>所有的</strong>对象（包括文件、目录、视图和变化请求），完全支持多重实体关系。StarTeam信息库使用了扩展的行业标准，如ODBC、COM、JAVA beans和Active-X等等。<br />  
<li><strong>真正的客户/服务器体系结构：</strong>基于文件系统的工具（如PVCS和SourceSafe）很难有效地运行在WAN、Internet或WEB环境中，因为其性能是难以接受的。<br />  
</li><li><b>WAN/WEB优化：</b>StarTeam特别针对WAN、Internet和WEB进行了优化，增强了诸多特性，如加密、压缩、增量式提交（即只提交差异部分而不是这个文件）、数据库的远程同步（无需传输所有相关的文件）等等。<br />  
</li><li><strong>可视化配置管理：</strong>特别方便使用，且功能强大，允许开发人员以一种可视化和直观的方式定义任何数量的数据库切片，支持分阶段、“时间游动”和调试。<br />  
</li><li><strong>所有信息库对象之间的通用化链接：</strong>用户自然地用关系表示上下文相关的内容，而与其他开发人员共享这些关联内容对他们的工作来说是至关重要的。StarTeam支持对这种关系的要求，跨所有对象类型（文件、版本、会话和变化请求等）的通用化链接简便易用。<br />  
</li><li><strong>功能集成：</strong>为什么开发人员不得不使用两个单独的应用：一个制作变化，另一个跟踪这些变化和外部变化请求之间的关系？StarTeam在一个高效率的用户界面下集成了所有这些功能。<br />  
</li><li><strong>易于使用：</strong>屡获殊荣的StarTeam图形用户界面是一个高效率、直观、使用方便的开发环境。<br />  
</li><li><strong>与开发工具集成：</strong>StarTeam与所有主流的开发工具集成。同时，StarTeam提供应用接口开发的能力（通过COM和JAVA beans）。<br />  
</li><li><strong>与其它配置管理软件的透明互操作：</strong>如果你的开发队伍已经使用了其它版本控制工具，如PVCS和 SourceSafe，StarTeam保护和继承你当前的工作和投资，你可以在一个用户界面下透明地使用三个产品的版本档案（单独或通过StarTeam）。这不是导入/导出功能，这是<strong>完全的透明互操作！</strong></li></ul><p>　</p><hr size="1" /><p><font face="黑体"><big><big>技术协同</big></big></font></p><font color="#0066ff"><b><i><p></p></i></b></font>传统上将开发环境划分为开发、测试、集成和产品，越来越独立于与其它技术功能，如文档、设计、计划、外部资源、管理、帮助平台、经营主管、客户等等。<p>作为一个例子，让我们考虑WEB应用开发：JAVA开发人员如何能够没有说明文档、设计人员、手册编写人员等的密切协同？</p><p>如果不能满足下列关键需求，则这些技术协同将不能发挥作用： 
</p><ul type="DISC"><b><i><li></li></i>非常容易使用：</b>传统的开发工具需要大量的使用培训。而让管理人员去上课是乎有些困难。 
<li><strong>熟悉文件管理界面：</strong>用于存取文件夹、文件和任何其它对象的界面应该与Windows资源管理器相似，绝大多数合作者都会使用它。 
</li><li><strong>地理位置独立：</strong>管理人员和开发人员都可能分布在不同的地方，或临时变动工作地点，但他们都需要随时访问有关系统。 
</li><li><strong>直接的关联导航：</strong>StarTeam的多向链接能给技术协同者带来巨大的好处，因为链接提供了一个容易跟随、直观的导航机制，轻松访问与特定对象关联的文件、变化请求和会话等。 
</li><li><strong>线索化的会话：</strong>在开发和维护过程中，StarTeam用线索化的会话的形式保持日常的活动和决定，用户将从中积累大量有价值的知识，这些知识库可以直接被其它技术协同者访问。 </li></ul><p>　</p><hr size="1" /><p><big><big><font face="黑体">程序管理办公室（PMO）</font></big></big></p><p>在大型项目中，经常需要一个程序办公室，是管理这个应用的中心。</p><p>根据行业专家的研究报告，如果不使用集中的记录数据库，程序办公室将无法开展工作，集中数据库中所有受影响的对象会被跟踪。</p><p>StarTeam 2000是StarTeam Professional的一个特别版本，增加了以上功能，提供对依从跟踪系统（Compliance Tracking System）的综合支持。</p><p>CTS变成了建立记录数据库的理想工具，通过与StarTeam的集成，将数字化财富、依从工作及其在软件部件上的表示形成了一个闭环。</p><p>　</p><hr size="1" /><p><big><big><font face="黑体">项目管理功能</font></big></big></p><p>开发环境处理文件、变化和资源，项目管理针对任务、工作分配、依赖关系和时间。</p><p>尽管有许多项目管理产品，如Microsoft Project，但通常都不能很好地支持开发项目，因为跟踪制作变化的时间、执行它们所用的资源和更新贯穿整个生命周期的项目信息需要很高的开销。</p><p>这是很不幸的，因为开发人员确实希望从项目管理功能中获得好处，并且因为诸如应用软件这样关键的财富游离于项目管理框架之外。</p><p>要提高团队生产力，必须将项目管理功能与开发环境集成在一起。集成必须能够： 
</p><ul type="DISC"><li>支持<strong>任务</strong>，任务是一个完全激活的对象，用于关联资源、变化请求 、工作分配和变化。 
</li><li><strong>完全集成</strong>任务对象与开发信息库中维护的其它对象。 
</li><li>支持<strong>项目模板</strong>，因此任务和工作分配能够自动应用到相似的项目中。 
</li><li>开发信息库和MS Project引擎之间<strong>透明、双向的数据更新</strong>。 </li></ul><p>StarBase支持上述功能，为你提供了一个完整的应用开发项目管理解决方案。</p><p>　</p><hr size="1" /><p>协同的所有原理是－自底向上。即从低层的服务到高层次的协同功能。</p><p>首先，协同提供的最基本的服务是产品化的、成熟的版本控制和软件配置管理。因为协同是建立在应用财富之上的，它们必须被安全地管理、审查、保护和版本化。</p><p>StarTeam提供的版本控制引擎支持典型的软件开发事务，如文件差异分析和合并、版本标签、建立支持和文件管理等等。</p><p>StarTeam的版本控制引擎与Oracle、Symantec、Allaire、Haht Software等其它许多软件公司提供的版本控制工具是一样的。</p><div align="center"><center><table cellspacing="0" cellpadding="0" width="300" border="0"><tbody><tr><td><img height="58" alt="techcoll_how1.gif (5488 bytes)" src="http://www.huihoo.com/development/i/techcoll_how1.gif" width="300" /></td></tr></tbody></table></center></div><p>　</p><hr size="1" /><p><font face="黑体"><big><big>共同访问信息技术财富</big></big></font></p><p>多少年来，开发队伍已经使用版本控制保护其信息技术财富。因此，当在开发小组之间实现协同时，你将发现开发小组会逐渐抛弃传统的版本控制工具。</p><p>StarTeam是唯一能保护你的版本控制工具投资的这种产品，提供与其它版本控制工具（如PVCS和SourceSafe）的透明互操作。不仅是导入/导出功能：完全的真实的互操作。即用户A可以使用SourceSafe建立一个文件的版本，用户B使用StarTeam，那么任一用户都可以通过SourceSafe和StarTeam访问自己或他人的版本。</p><div align="center"><center><table cellspacing="0" cellpadding="0" width="300" border="0"><tbody><tr><td><img height="129" alt="techcoll_how2.gif (9621 bytes)" src="http://www.huihoo.com/development/i/techcoll_how2.gif" width="300" /></td></tr></tbody></table></center></div><p>　</p><hr size="1" /><p><font face="黑体"><big><big>协同框架</big></big></font></p><p>在版本控制引擎互操作之上，StarTeam建立了它最重要的功能层：<strong>协同框架</strong>。StarTeam这一独特的体系结构，是建立世界级产品的基础。</p><p>该功能层的技术描述是：强壮的，可伸缩的，基于标准的，面向对象的信息数据库，完全版本化的，支持多向通用化链接。用通俗的话来说就是，协同框架是StarTeam允许所有团队成员快速有效地进行协同工作的功能性（表示和共享关联信息）。</p><div align="center"><center><table cellspacing="0" cellpadding="0" width="300" border="0"><tbody><tr><td><img height="163" alt="techcoll_how3.gif (12489 bytes)" src="http://www.huihoo.com/development/i/techcoll_how3.gif" width="300" /></td></tr></tbody></table></center></div><p>协同框架提供： 
</p><ul type="DISC"><b><i><li></li></i>从任何地方进行安全有效的访问：</b>StarTeam是一个客户/服务器产品，针对宽带和窄带连接进行了优化设计。用户能够使用下列方式访问PVCS、SourceSafe和StarTeam版本库： 
<ul type="circle"><li>运行在LAN、WAN或TCP/IP连接（如Internet）上的StarTeam客户端应用。 
</li><li>运行在任何JAVA平台并连接在LAN、WAN或Internet上的StarTeam JAVA客户端。 
</li><li>一个标准的浏览器，不需要装入插件程序和JAVA小程序。<br />  </li></ul><li><b>获奖的易于使用的图形用户界面：</b>StarTeam已经多次被专家和用户一致评定为软件配置管理类中最容易使用的产品。无论你是开发人员或是不懂版本控制的技术协同者，都可以立即学会使用StarTeam，并且其功能性将会给你留下深刻的影响。<br />  
</li><li><b>直观的文件管理界面：</b>StarTeam让你通过熟悉的Windows风格访问项目中的文件目录结构。你可以在许多文件夹中使用相同的文件名：StarTeam使用的文件和版本名字没有限制，这与Windows环境不同（许多基于文件相同的工具是有限制的）。<br />  
</li><li><b>通用化链接引擎：</b>StarTeam数据库中所有的对象，无论文件、版本、变化请求或会话，都可以被任意链接，以表示它们之间逻辑和/或物理关系中包含的关联信息。你要想了解一个对象的上下文关系，只需跟着链接走。<br />  
</li><li><b>可视化配置管理：</b>定义信息库的虚拟视图的能力对用户来说总是有吸引力的，但通常在高端的SCM工具中才会有。StarTeam实现了这一特性并且更进一步，包括用户界面的所有可视化元素。StarTeam用户能够可视化定义和维护虚拟视图实现隔离应用场合、阶段化（例如开发、测试、集成和产品等）、对应用过去的任何精确的日期和时间的<strong>时间游动</strong>、执行增量式调试等等。 </li></ul><p>协同框架中的所有功能可应用于信息库中的所有对象、建立在其上的任何生产力模块以及任何与StarTeam通讯的应用。</p><p>　</p><hr size="1" /><p><font face="黑体"><big><big>标准接口</big></big></font></p><p>StarTeam基于标准的集成接口层能够扩展信息数据库的功能性。它提供了从任何使用COM或JAVA Beans的应用完全存取所有信息库对象的能力。因此用Visual Basic、JAVA以及COM或JAVA兼容的语言编写的应用都能存取StarTeam中保存的版本、变化请求、会话、任务或其它任何对象。想象一下这样的可能性，将自己内部开发的应用和第三方的软件包集成在一个保存有你的信息技术财富的透明的信息库中，不管它们是在StarTeam还是在SourceSafe数据库中，这不是很美妙吗？</p><div align="center"><center><table cellspacing="0" cellpadding="0" width="300" border="0"><tbody><tr><td><img height="184" alt="techcoll_how4.gif (14043 bytes)" src="http://www.huihoo.com/development/i/techcoll_how4.gif" width="300" /></td></tr></tbody></table></center></div><p>　</p><hr size="1" /><p><big><big><font face="黑体">生产力模块</font></big></big></p><p>生产力模块是集成的部件，它增加了对象定义和功能性，如变化请求管理、会话、任务管理等等。</p><div align="center"><center><table cellspacing="0" cellpadding="0" width="300" border="0"><tbody><tr><td><img height="241" alt="techcoll_how5.gif (16406 bytes)" src="http://www.huihoo.com/development/i/techcoll_how5.gif" width="300" /></td></tr></tbody></table></center></div><p>生产力模块自动集成到StarTeam的用户界面。要在StarTeam客户端应用中实现一个新对象只要有一个动态连接库.DLL即可。将一个.DLL拿走，与该特殊对象（如变化请求）有关的所有功能性将立即从用户界面上消失。</p><p>这一独特、最先进的对象集成技术是StarTeam强大的协同框架体系和信息数据库实现的副产品。</p><p>　</p><hr size="1" /><p><big><big><font face="黑体">集成自己的应用</font></big></big></p><p>前面描述的基于标准的集成，同样适用于你自己内部开发的应用，可以用VB或任何COM或JAVA Beans兼容的语言实现。</p><div align="center"><center><table cellspacing="0" cellpadding="0" width="300" border="0"><tbody><tr><td><img height="241" alt="techcoll_how6.gif (17079 bytes)" src="http://www.huihoo.com/development/i/techcoll_how6.gif" width="300" /></td></tr></tbody></table></center></div><p>　</p><hr size="1" /><p><big><big><font face="黑体">集成多厂家的应用</font></big></big></p><p>互操作层让版本控制引擎协同工作，协同框架使用户合作。同样，标准接口层实现技术的协同。</p><div align="center"><center><table cellspacing="0" cellpadding="0" width="300" border="0"><tbody><tr><td><img height="238" alt="techcoll_how7.gif (17583 bytes)" src="http://www.huihoo.com/development/i/techcoll_how7.gif" width="300" /></td></tr></tbody></table></center></div><p>StarTeam正在推出StarPartner软件合作伙伴策略，通过StarTeam SDK，保证其它技术能够利用StarTeam生产力模块同样的机制使用产品信息数据库的服务。</p><p>　</p><hr size="1" /><p>StarTeam是目前唯一的企业级协同解决方案。</p><p>StarTeam是一个集成的解决方案，为企业信息组织中从开发人员到项目管理人员的所有成员带来了好处。</p><p>这一革命性的解决方案事实上正在成为标准。许多全球性的大型企业正在采用StarTeam，通过建立跨团队、跨部门、跨专业的协同工作，提高应用队伍的效率。</p><img src ="http://www.cnitblog.com/tilan/aggbug/21897.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/tilan/" target="_blank">Joinclass Inc</a> 2007-01-15 23:25 <a href="http://www.cnitblog.com/tilan/archive/2007/01/15/21897.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>软件开发:需求分析的20条法则</title><link>http://www.cnitblog.com/tilan/archive/2007/01/15/21896.html</link><dc:creator>Joinclass Inc</dc:creator><author>Joinclass Inc</author><pubDate>Mon, 15 Jan 2007 15:23:00 GMT</pubDate><guid>http://www.cnitblog.com/tilan/archive/2007/01/15/21896.html</guid><wfw:comment>http://www.cnitblog.com/tilan/comments/21896.html</wfw:comment><comments>http://www.cnitblog.com/tilan/archive/2007/01/15/21896.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cnitblog.com/tilan/comments/commentRss/21896.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/tilan/services/trackbacks/21896.html</trackback:ping><description><![CDATA[<em>对商业用户来说，他们后面是成百上千个供应商，前面是成千上万个消费顾客。怎样利用软件管理错综复杂的供应商和消费顾客，如何做好精细到一个小小调料包的进、销、调、存的商品流通工作，这些都是商业企业需要信息管理系统的理由。软件开发的意义也就在于此。而弄清商业用户如此复杂需求的真面目，正是软件开发成功的关键所在。</em>
		<p>
				<font class="v15">
						<font color="#ffffff">---　　</font>经理：“我们要建立一套完整的商业管理软件系统，包括商品的进、销、调、存管理，是总部-门店的连锁经营模式。通过通信手段门店自动订货，供应商自动结算，卖场通过扫条码实现销售，管理人员能够随时查询门店商品销售和库存情况。另外，我们也得为政府部门提供关于商品营运的报告。” 
<p><font class="v15"><font color="#ffffff">--　　-</font>分析员：“我已经明白这个项目的大体结构框架，这非常重要，但在制定计划之前，我们必须收集一些需求。” 
<p><font class="v15"><font color="#ffffff">--　　-</font>经理觉得奇怪：“我不是刚告诉你我的需求了吗？” 
<p><font class="v15"><font color="#ffffff">--　　-</font>分析员：“实际上，您只说明了整个项目的概念和目标。这些高层次的业务需求不足以提供开发的内容和时间。我需要与实际将要使用系统的业务人员进行讨论，然后才能真正明白达到业务目标所需功能和用户要求，了解清楚后，才可以发现哪些是现有组件即可实现的，哪些是需要开发的，这样可节省很多时间。” 
<p><font class="v15"><font color="#ffffff">--　　-</font>经理：“业务人员都在招商。他们非常忙，没有时间与你们详细讨论各种细节。你能不能说明一下你们现有的系统？” 
<p><font class="v15"><font color="#ffffff">---　　</font>分析员尽量解释从用户处收集需求的合理性：“如果我们只是凭空猜想用户的要求，结果不会令人满意。我们只是软件开发人员，而不是采购专家、营运专家或是财务专家，我们并不真正明白您这个企业内部运营需要做些什么。我曾经尝试过，未真正明白这些问题就开始编码，结果没有人对产品满意。” 
<p><font class="v15"><font color="#ffffff">---　　</font>经理坚持道：“行了，行了，我们没有那么多的时间。让我来告诉您我们的需求。实际上我也很忙。请马上开始开发，并随时将你们的进展情况告诉我。” 
<p><font class="v15"><font color="#ffffff">---　　</font><font color="#b00e">风险躲在需求的迷雾之后</font><p><font class="v15"><font color="#ffffff">-　　--</font>以上我们看到的是某客户项目经理与系统开发小组的分析人员讨论业务需求。在项目开发中，所有的项目风险承担者都对需求分析阶段备感兴趣。这里所指的风险承担者包括客户方面的项目负责人和用户，开发方面的需求分析人员和项目管理者。这部分工作做得到位，能开发出很优秀的软件产品，同时也会令客户满意。若处理不好，则会导致误解、挫折、障碍以及潜在的质量和业务价值上的威胁。因此可见——需求分析奠定了软件工程和项目管理的基础。 
<p><font class="v15"><font color="#ffffff">--　　-</font><font color="#b00e">拨开需求分析的迷雾</font><p><font class="v15"><font color="#ffffff">---　　</font>像这样的对话经常出现在软件开发的过程中。客户项目经理的需求对分析人员来讲，像“雾里看花”般模糊并令开发者感到困惑。那么，我们就拨开雾影，分析一下需求的具体内容： 
<p><font class="v15"><font color="#ffffff">--　-</font>·业务需求——反映了组织机构或客户对系统、产品高层次的目标要求，通常在项目定义与范围文档中予以说明。 
<p><font class="v15"><font color="#ffffff">---　</font>·用户需求——描述了用户使用产品必须要完成的任务，这在使用实例或方案脚本中予以说明。 
<p><font class="v15"><font color="#ffffff">---　</font>·功能需求——定义了开发人员必须实现的软件功能，使用户利用系统能够完成他们的任务，从而满足了业务需求。 
<p><font class="v15"><font color="#ffffff">--　-</font>·非功能性的需求——描述了系统展现给用户的行为和执行的操作等，它包括产品必须遵从的标准、规范和约束，操作界面的具体细节和构造上的限制。 
<p><font class="v15"><font color="#ffffff">---　</font>·需求分析报告——报告所说明的功能需求充分描述了软件系统所应具有的外部行为。“需求分析报告”在开发、测试、质量保证、项目管理以及相关项目功能中起着重要作用。 
<p><font class="v15"><font color="#ffffff">---　</font>前面提到的客户项目经理通常阐明产品的高层次概念和主要业务内容，为后继工作建立了一个指导性的框架。其他任何说明都应遵循“业务需求”的规定，然而“业务需求”并不能为开发人员提供开发所需的许多细节说明。 
<p><font class="v15"><font color="#ffffff">---　</font>下一层次需求——用户需求，必须从使用产品的用户处收集。因此，这些用户构成了另一种软件客户，他们清楚要使用该产品完成什么任务和一些非功能性的特性需求。例如：程序的易用性、健壮性和可靠性，而这些特性将会使用户很好地接受具有该特点的软件产品。 
<p><font class="v15"><font color="#ffffff">---　</font>经理层有时试图代替实际用户说话，但通常他们无法准确说明“用户需求”。用户需求来自产品的真正使用者，必须让实际用户参与到收集需求的过程中。如果不这样做，产品很可能会因缺乏足够的信息而遗留不少隐患。 
<p><font class="v15"><font color="#ffffff">---　</font>在实际需求分析过程中，以上两种客户可能都觉得没有时间与需求分析人员讨论，有时客户还希望分析人员无须讨论和编写需求说明就能说出用户的需求。除非遇到的需求极为简单；否则不能这样做。如果您的组织希望软件成功，那么必须要花上数天时间来消除需求中模糊不清的地方和一些使开发者感到困惑的方面。 
<p><font class="v15"><font color="#ffffff">---　</font>优秀的软件产品建立在优秀的需求基础之上，而优秀的需求源于客户与开发人员之间有效的交流和合作。只有双方参与者都明白自己需要什么、成功的合作需要什么时，才能建立起一种良好的合作关系。 
<p><font class="v15"><font color="#ffffff">---　</font>由于项目的压力与日俱增，所有项目风险承担者有着一个共同目标，那就是大家都想开发出一个既能实现商业价值又能满足用户要求，还能使开发者感到满足的优秀软件产品。 
<p><font class="v15"><font color="#ffffff">--　-</font><font color="#b00e">客户的需求观</font><p><font class="v15"><font color="#ffffff">--　-</font>客户与开发人员交流需要好的方法。下面建议20条法则，客户和开发人员可以通过评审以下内容并达成共识。如果遇到分歧，将通过协商达成对各自义务的相互理解，以便减少以后的磨擦（如一方要求而另一方不愿意或不能够满足要求）。 
<p><font class="v15"><font color="#ffffff">---　</font><b>1、 分析人员要使用符合客户语言习惯的表达</b><p><font class="v15"><font color="#ffffff">---　</font>需求讨论集中于业务需求和任务，因此要使用术语。客户应将有关术语（例如：采价、印花商品等采购术语）教给分析人员，而客户不一定要懂得计算机行业的术语。 
<p><font class="v15"><font color="#ffffff">---　</font><b>2、分析人员要了解客户的业务及目标</b><p><font class="v15"><font color="#ffffff">---　</font>只有分析人员更好地了解客户的业务，才能使产品更好地满足需要。这将有助于开发人员设计出真正满足客户需要并达到期望的优秀软件。为帮助开发和分析人员，客户可以考虑邀请他们观察自己的工作流程。如果是切换新系统，那么开发和分析人员应使用一下目前的旧系统，有利于他们明白目前系统是怎样工作的，其流程情况以及可供改进之处。s 
<p><font class="v15"><font color="#ffffff">---　</font><b>3、 分析人员必须编写软件需求报告</b><p><font class="v15"><font color="#ffffff">---　</font>分析人员应将从客户那里获得的所有信息进行整理，以区分业务需求及规范、功能需求、质量目标、解决方法和其他信息。通过这些分析，客户就能得到一份“需求分析报告”，此份报告使开发人员和客户之间针对要开发的产品内容达成协议。报告应以一种客户认为易于翻阅和理解的方式组织编写。客户要评审此报告，以确保报告内容准确完整地表达其需求。一份高质量的“需求分析报告”有助于开发人员开发出真正需要的产品。 
<p><font class="v15"><font color="#ffffff">---　</font><b>4、 要求得到需求工作结果的解释说明</b><p><font class="v15"><font color="#ffffff">---　</font>分析人员可能采用了多种图表作为文字性“需求分析报告”的补充说明，因为工作图表能很清晰地描述出系统行为的某些方面，所以报告中各种图表有着极高的价值；虽然它们不太难于理解，但是客户可能对此并不熟悉，因此客户可以要求分析人员解释说明每个图表的作用、符号的意义和需求开发工作的结果，以及怎样检查图表有无错误及不一致等。 
<p><font class="v15"><font color="#ffffff">---　</font><b>5、 开发人员要尊重客户的意见</b><p><font class="v15"><font color="#ffffff">---　</font>如果用户与开发人员之间不能相互理解，那关于需求的讨论将会有障碍。共同合作能使大家“兼听则明”。参与需求开发过程的客户有权要求开发人员尊重他们并珍惜他们为项目成功所付出的时间，同样，客户也应对开发人员为项目成功这一共同目标所做出的努力表示尊重。 
<p><font class="v15"><font color="#ffffff">---　</font><b>6、 开发人员要对需求及产品实施提出建议和解决方案</b><p><font class="v15"><font color="#ffffff">---　</font>通常客户所说的“需求”已经是一种实际可行的实施方案，分析人员应尽力从这些解决方法中了解真正的业务需求，同时还应找出已有系统与当前业务不符之处，以确保产品不会无效或低效；在彻底弄清业务领域内的事情后，分析人员就能提出相当好的改进方法，有经验且有创造力的分析人员还能提出增加一些用户没有发现的很有价值的系统特性。 
<p><font class="v15"><font color="#ffffff">---　</font><b>7、 描述产品使用特性</b><p><font class="v15"><font color="#ffffff">---　</font>客户可以要求分析人员在实现功能需求的同时还注意软件的易用性，因为这些易用特性或质量属性能使客户更准确、高效地完成任务。例如：客户有时要求产品要“界面友好”或“健壮”或“高效率”，但对于开发人员来讲，太主观了并无实用价值。正确的做法是，分析人员通过询问和调查了解客户所要的“友好、健壮、高效所包含的具体特性，具体分析哪些特性对哪些特性有负面影响，在性能代价和所提出解决方案的预期利益之间做出权衡，以确保做出合理的取舍。 
<p><font class="v15"><font color="#ffffff">---　</font><b>8、 允许重用已有的软件组件</b><p><font class="v15"><font color="#ffffff">---　</font>需求通常有一定灵活性，分析人员可能发现已有的某个软件组件与客户描述的需求很相符，在这种情况下，分析人员应提供一些修改需求的选择以便开发人员能够降低新系统的开发成本和节省时间，而不必严格按原有的需求说明开发。所以说，如果想在产品中使用一些已有的商业常用组件，而它们并不完全适合您所需的特性，这时一定程度上的需求灵活性就显得极为重要了。 
<p><font class="v15"><font color="#ffffff">---　</font><b>9、 要求对变更的代价提供真实可靠的评估</b><p><font class="v15"><font color="#ffffff">---　</font>有时，人们面临更好、也更昂贵的方案时，会做出不同的选择。而这时，对需求变更的影响进行评估从而对业务决策提供帮助，是十分必要的。所以，客户有权利要求开发人员通过分析给出一个真实可信的评估，包括影响、成本和得失等。开发人员不能由于不想实施变更而随意夸大评估成本。 
<p><font class="v15"><font color="#ffffff">---　</font><b>10、 获得满足客户功能和质量要求的系统</b><p><font class="v15"><font color="#ffffff">---　</font>每个人都希望项目成功，但这不仅要求客户要清晰地告知开发人员关于系统“做什么”所需的所有信息，而且还要求开发人员能通过交流了解清楚取舍与限制，一定要明确说明您的假设和潜在的期望，否则，开发人员开发出的产品很可能无法让您满意。 
<p><font class="v15"><font color="#ffffff">---　</font><b>11、 给分析人员讲解您的业务</b><p><font class="v15"><font color="#ffffff">---　</font>分析人员要依靠客户讲解业务概念及术语，但客户不能指望分析人员会成为该领域的专家，而只能让他们明白您的问题和目标；不要期望分析人员能把握客户业务的细微潜在之处，他们可能不知道那些对于客户来说理所当然的“常识”。 
<p><font class="v15"><font color="#ffffff">---　</font><b>12、 抽出时间清楚地说明并完善需求</b><p><font class="v15"><font color="#ffffff">---　</font>客户很忙，但无论如何客户有必要抽出时间参与“头脑高峰会议”的讨论，接受采访或其他获取需求的活动。有些分析人员可能先明白了您的观点，而过后发现还需要您的讲解，这时请耐心对待一些需求和需求的精化工作过程中的反复，因为它是人们交流中很自然的现象，何况这对软件产品的成功极为重要。 
<p><font class="v15"><font color="#ffffff">---　</font><b>13、 准确而详细地说明需求</b><p><font class="v15"><font color="#ffffff">---　</font>编写一份清晰、准确的需求文档是很困难的。由于处理细节问题不但烦人而且耗时，因此很容易留下模糊不清的需求。但是在开发过程中，必须解决这种模糊性和不准确性，而客户恰恰是为解决这些问题作出决定的最佳人选，否则，就只好靠开发人员去正确猜测了。 
<p><font class="v15"><font color="#ffffff">---　</font>在需求分析中暂时加上“待定”标志是个方法。用该标志可指明哪些是需要进一步讨论、分析或增加信息的地方，有时也可能因为某个特殊需求难以解决或没有人愿意处理它而标注上“待定”。客户要尽量将每项需求的内容都阐述清楚，以便分析人员能准确地将它们写进“软件需求报告”中去。如果客户一时不能准确表达，通常就要求用原型技术，通过原型开发，客户可以同开发人员一起反复修改，不断完善需求定义。 
<p><font class="v15"><font color="#ffffff">---　</font><b>14、 及时作出决定</b><p><font class="v15"><font color="#ffffff">---　</font>分析人员会要求客户作出一些选择和决定，这些决定包括来自多个用户提出的处理方法或在质量特性冲突和信息准确度中选择折衷方案等。有权作出决定的客户必须积极地对待这一切，尽快做处理，做决定，因为开发人员通常只有等客户做出决定才能行动，而这种等待会延误项目的进展。 
<p><font class="v15"><font color="#ffffff">---　</font><b>15、 尊重开发人员的需求可行性及成本评估</b><p><font class="v15"><font color="#ffffff">---　</font>所有的软件功能都有其成本。客户所希望的某些产品特性可能在技术上行不通，或者实现它要付出极高的代价，而某些需求试图达到在操作环境中不可能达到的性能，或试图得到一些根本得不到的数据。开发人员会对此作出负面的评价，客户应该尊重他们的意见。 
<p><font class="v15"><font color="#ffffff">---　</font><b>16、 划分需求的优先级</b><p><font class="v15"><font color="#ffffff">---　</font>绝大多数项目没有足够的时间或资源实现功能性的每个细节。决定哪些特性是必要的，哪些是重要的，是需求开发的主要部分，这只能由客户负责设定需求优先级，因为开发者不可能按照客户的观点决定需求优先级；开发人员将为您确定优先级提供有关每个需求的花费和风险的信息。 
<p><font class="v15"><font color="#ffffff">---　</font>在时间和资源限制下，关于所需特性能否完成或完成多少应尊重开发人员的意见。尽管没有人愿意看到自己所希望的需求在项目中未被实现，但毕竟是要面对现实，业务决策有时不得不依据优先级来缩小项目范围或延长工期，或增加资源，或在质量上寻找折衷。 
<p><font class="v15"><font color="#ffffff">---　</font><b>17、 评审需求文档和原型</b><p><font class="v15"><font color="#ffffff">---　</font>客户评审需求文档，是给分析人员带来反馈信息的一个机会。如果客户认为编写的“需求分析报告”不够准确，就有必要尽早告知分析人员并为改进提供建议。 
<p><font class="v15"><font color="#ffffff">---　</font>更好的办法是先为产品开发一个原型。这样客户就能提供更有价值的反馈信息给开发人员，使他们更好地理解您的需求；原型并非是一个实际应用产品，但开发人员能将其转化、扩充成功能齐全的系统。 
<p><font class="v15"><font color="#ffffff">---　</font><b>18、 需求变更要立即联系</b><p><font class="v15"><font color="#ffffff">---　</font>不断的需求变更，会给在预定计划内完成的质量产品带来严重的不利影响。变更是不可避免的，但在开发周期中，变更越在晚期出现，其影响越大；变更不仅会导致代价极高的返工，而且工期将被延误，特别是在大体结构已完成后又需要增加新特性时。所以，一旦客户发现需要变更需求时，请立即通知分析人员。 
<p><font class="v15"><font color="#ffffff">---　</font><b>19、 遵照开发小组处理需求变更的过程</b><p><font class="v15"><font color="#ffffff">---　</font>为将变更带来的负面影响减少到最低限度，所有参与者必须遵照项目变更控制过程。这要求不放弃所有提出的变更，对每项要求的变更进行分析、综合考虑，最后做出合适的决策，以确定应将哪些变更引入项目中。 
<p><font class="v15"><font color="#ffffff">---　</font><b>20、 尊重开发人员采用的需求分析过程</b><p><font class="v15"><font color="#ffffff">---　</font>软件开发中最具挑战性的莫过于收集需求并确定其正确性，分析人员采用的方法有其合理性。也许客户认为收集需求的过程不太划算，但请相信花在需求开发上的时间是非常有价值的；如果您理解并支持分析人员为收集、编写需求文档和确保其质量所采用的技术，那么整个过程将会更为顺利。 
<p><font class="v15"><font color="#ffffff">---　</font><font color="#b00e">“需求确认”意味着什么</font><p><font class="v15"><font color="#ffffff">---　</font>在“需求分析报告”上签字确认，通常被认为是客户同意需求分析的标志行为，然而实际操作中，客户往往把“签字”看作是毫无意义的事情。“他们要我在需求文档的最后一行下面签名，于是我就签了，否则这些开发人员不开始编码。” 
<p><font class="v15"><font color="#ffffff">---　</font>这种态度将带来麻烦，譬如客户想更改需求或对产品不满时就会说：“不错，我是在需求分析报告上签了字，但我并没有时间去读完所有的内容，我是相信你们的，是你们非让我签字的。” 
<p><font class="v15"><font color="#ffffff">---　</font>同样问题也会发生在仅把“签字确认”看作是完成任务的分析人员身上，一旦有需求变更出现，他便指着“需求分析报告”说：“您已经在需求上签字了，所以这些就是我们所开发的，如果您想要别的什么，您应早些告诉我们。” 
<p><font class="v15"><font color="#ffffff">---　</font>这两种态度都是不对的。因为不可能在项目的早期就了解所有的需求，而且毫无疑问地需求将会出现变更，在“需求分析报告”上签字确认是终止需求分析过程的正确方法，所以我们必须明白签字意味着什么。 
<p><font class="v15"><font color="#ffffff">---　</font>对“需求分析报告”的签名是建立在一个需求协议的基线上，因此我们对签名应该这样理解：“我同意这份需求文档表述了我们对项目软件需求的了解，进一步的变更可在此基线上通过项目定义的变更过程来进行。我知道变更可能会使我们重新协商成本、资源和项目阶段任务等事宜。”对需求分析达成一定的共识会使双方易于忍受将来的摩擦，这些摩擦来源于项目的改进和需求的误差或市场和业务的新要求等。 
<p><font class="v15"><font color="#ffffff">---　</font>需求确认将迷雾拨散，显现需求的真面目，给初步的需求开发工作画上了双方都明确的句号，并有助于形成一个持续良好的客户与开发人员的关系，为项目的成功奠定了坚实的基础。 </font></p></font></p></font></p></font></p></font></p></font></p></font></p></font></p></font></p></font></p></font></p></font></p></font></p></font></p></font></p></font></p></font></p></font></p></font></p></font></p></font></p></font></p></font></p></font></p></font></p></font></p></font></p></font></p></font></p></font></p></font></p></font></p></font></p></font></p></font></p></font></p></font></p></font></p></font></p></font></p></font></p></font></p></font></p></font></p></font></p></font></p></font></p></font></p></font></p></font></p></font></p></font></p></font></p></font></p></font></p></font></p></font></p></font></p></font></p></font></p></font></p></font></p></font></p></font></p></font></p></font></p></font></p></font></p></font></p></font></p></font></p></font></p></font></p></font>
		</p><img src ="http://www.cnitblog.com/tilan/aggbug/21896.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/tilan/" target="_blank">Joinclass Inc</a> 2007-01-15 23:23 <a href="http://www.cnitblog.com/tilan/archive/2007/01/15/21896.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>EIP企业信息平台系统介绍</title><link>http://www.cnitblog.com/tilan/archive/2007/01/15/21895.html</link><dc:creator>Joinclass Inc</dc:creator><author>Joinclass Inc</author><pubDate>Mon, 15 Jan 2007 15:11:00 GMT</pubDate><guid>http://www.cnitblog.com/tilan/archive/2007/01/15/21895.html</guid><wfw:comment>http://www.cnitblog.com/tilan/comments/21895.html</wfw:comment><comments>http://www.cnitblog.com/tilan/archive/2007/01/15/21895.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/tilan/comments/commentRss/21895.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/tilan/services/trackbacks/21895.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 1.1     门户建设服务器（Portal Builder Server）EIP门户建设服务器主要的功能是实现系统的基本架构管理，包括：门户管理、多站点建设、工作流、系统安全与权限、节点与频道管理、模块管理与接口、模版管理、资源管理等模块组成，通过EIP门户架构服务器可以实现对于门户框架的全部管理功能，主要的特点如下： 1.         适应普通用户。提供类似Web浏览器这样直观的工具来满足...&nbsp;&nbsp;<a href='http://www.cnitblog.com/tilan/archive/2007/01/15/21895.html'>阅读全文</a><img src ="http://www.cnitblog.com/tilan/aggbug/21895.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/tilan/" target="_blank">Joinclass Inc</a> 2007-01-15 23:11 <a href="http://www.cnitblog.com/tilan/archive/2007/01/15/21895.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JSTL 入门: 表达式语言</title><link>http://www.cnitblog.com/tilan/archive/2007/01/11/21767.html</link><dc:creator>Joinclass Inc</dc:creator><author>Joinclass Inc</author><pubDate>Thu, 11 Jan 2007 08:40:00 GMT</pubDate><guid>http://www.cnitblog.com/tilan/archive/2007/01/11/21767.html</guid><wfw:comment>http://www.cnitblog.com/tilan/comments/21767.html</wfw:comment><comments>http://www.cnitblog.com/tilan/archive/2007/01/11/21767.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/tilan/comments/commentRss/21767.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/tilan/services/trackbacks/21767.html</trackback:ping><description><![CDATA[<blockquote>JSP 标准标记库（JSP Standard Tag Library，JSTL）是一个实现 Web 应用程序中常见的通用功能的定制标记库集，这些功能包括迭代和条件判断、数据管理格式化、XML 操作以及数据库访问。在 developerWorks 上其新系列的第一篇文章中，软件工程师 Mark Kolb 向您展示了如何使用 JSTL 标记来避免在 JSP 页面中使用脚本编制元素。您还将了解如何通过从表示层删除源代码来简化软件维护。最后，您将了解 JSTL 经过简化的表达式语言，它允许在不必使用功能齐全的编程语言的情况下对 JSTL 操作指定动态属性值。</blockquote>
		<!--START RESERVED FOR FUTURE USE INCLUDE FILES-->
		<!-- include java script once we verify teams wants to use this and it will work on dbcs and cyrillic characters -->
		<!--END RESERVED FOR FUTURE USE INCLUDE FILES-->
		<p>JavaServer Pages（JSP）是用于 J2EE 平台的标准表示层技术。JSP 技术提供了用于执行计算（这些计算用来动态地生成页面内容）的脚本编制元素和操作。脚本编制元素允许在 JSP 页面中包括程序源代码，在为响应用户请求而呈现页面时可以执行这些源代码。操作将计算操作封装到很象 HTML 或 XML 标记的标记中，JSP 页面的模板文本通常包含这些标记。JSP 规范只将几种操作定义成了标准，但从 JSP 1.1 开始，开发人员已经能够以定制标记库的方式创建其自己的操作了。</p>
		<p>JSP 标准标记库（JSTL）是 JSP 1.2 定制标记库集，这些标记库实现大量服务器端 Java 应用程序常用的基本功能。通过为典型表示层任务（如数据格式化和迭代或条件内容）提供标准实现，JSTL 使 JSP 作者可以专注于特定于应用程序的开发需求，而不是为这些通用操作“另起炉灶”。</p>
		<p>当然，您可以使用 JSP 脚本编制元素（scriptlet、表达式和声明）来实现此类任务。例如，可以使用三个 scriptlet 实现条件内容，清单 1 中着重显示了这三个 scriptlet。但是，因为脚本编制元素依赖于在页面中嵌入程序源代码（通常是 Java 代码），所以对于使用这些脚本编制元素的 JSP 页面，其软件维护任务的复杂度大大增加了。例如，清单 1 中的 scriptlet 示例严格地依赖于花括号的正确匹配。如果不经意间引入了一个语法错误，则条件内容中的嵌套其它 scriptlet 可能会造成严重破坏，并且在 JSP 容器编译该页面时，要使所产生的错误信息有意义可能会很困难。</p>
		<br />
		<a name="listing1">
				<b>清单 1. 通过 scriptlet 实现条件内容</b>
		</a>
		<br />
		<table cellspacing="0" cellpadding="5" width="500" bgcolor="#eeeeee" border="1">
				<tbody>
						<tr>
								<td>
										<pre>
												<code class="section">
														<font face="Lucida Console">&lt;% if (user.getRole() == "member")) { %&gt;
    &lt;p&gt;Welcome, member!&lt;/p&gt;
&lt;% } else { %&gt;
    &lt;p&gt;Welcome, guest!&lt;/p&gt;
&lt;% } %&gt;</font>
												</code>
										</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>修正此类问题通常需要相当丰富的编程经验。尽管通常会由十分精通页面布局和图形设计的设计人员来开发和维护 JSP，但是同一页面中的脚本编制元素出现问题时，需要程序员的介入。这种状况将单个文件中代码的责任分担给多人，因而使得开发、调试和增强此类 JSP 页面成为很麻烦的任务。通过将常用功能包装到定制标记库的标准集合中，JSTL 使 JSP 作者可以减少对编制脚本元素的需求，甚至可以不需要它们，并避免了相关的维护成本。</p>
		<br />
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td>
										<img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" />
										<br />
										<img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" />
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<p>
				<a name="1">
						<span class="atitle">
								<font face="Arial" size="4">JSTL 1.0</font>
						</span>
				</a>
		</p>
		<p>JSTL 1.0 发布于 2002 年 6 月，由四个定制标记库（ <code>core</code> 、 <code>format</code> 、 <code>xml</code> 和 <code>sql</code> ）和一对通用标记库验证器（ <code>ScriptFreeTLV</code> 和 <code>PermittedTaglibsTLV</code> ）组成。 <code>core</code> 标记库提供了定制操作，通过限制了作用域的变量管理数据，以及执行页面内容的迭代和条件操作。它还提供了用来生成和操作 URL 的标记。顾名思义， <code>format</code> 标记库定义了用来格式化数据（尤其是数字和日期）的操作。它还支持使用本地化资源束进行 JSP 页面的国际化。 <code>xml</code> 库包含一些标记，这些标记用来操作通过 XML 表示的数据，而 <code>sql</code> 库定义了用来查询关系数据库的操作。 </p>
		<p>两个 JSTL 标记库验证器允许开发人员在其 JSP 应用程序中强制使用编码标准。可以配置 <code>ScriptFreeTLV</code> 验证器以在 JSP 页面中禁用各种类型的 JSP 脚本元素 ― scriptlet、表达式和声明。类似地， <code>PermittedTaglibsTLV</code> 验证器可以用来限制可能由应用程序的 JSP 页面访问的定制标记库集（包括 JSTL 标记库）。 </p>
		<p>尽管 JSTL 最终将会成为 J2EE 平台的必需组件，但目前只有少数应用程序服务器包括它。JSTL 1.0 的参考实现可作为 Apache 软件基金会（Apache Software Foundation）的 Jakarta Taglibs 项目（请参阅 <a href="http://www.ibm.com/developerworks/cn/java/j-jstl0211/#resources"><font color="#996699">参考资料</font></a>）的一部分而获得。可以将该参考实现中的定制标记库合并到任何支持 JSP 1.2 和 Servlet 2.3 规范的服务器，以添加对 JSTL 的支持。 </p>
		<br />
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td>
										<img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" />
										<br />
										<img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" />
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<p>
				<a name="2">
						<span class="atitle">
								<font face="Arial" size="4">表达式语言</font>
						</span>
				</a>
		</p>
		<p>在 JSP 1.2 中，可以使用静态字符串或表达式（如果允许的话）指定 JSP 操作的属性。例如，在清单 2 中，对 <code>&lt;jsp:setProperty&gt;</code> 操作的 <code>name</code> 和 <code>property</code> 属性指定了静态值，而用表达式指定了其 <code>value</code> 属性。这个操作的效果是将请求参数的当前值赋予命名的 bean 特性。以这种形式使用的表达式被称为 <i>请求时属性值（request-time attribute value）</i>，这是构建到 JSP 规范中的用于动态指定属性值的唯一机制。 </p>
		<br />
		<a name="IDAHFSVB">
				<b>清单 2. 合并请求时属性值的 JSP 操作</b>
		</a>
		<br />
		<table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1">
				<tbody>
						<tr>
								<td>
										<pre>
												<code class="section">
														<font face="Lucida Console">&lt;jsp:setProperty name="user" property="timezonePref"
                 value='&lt;%= request.getParameter("timezone") %&gt;'/&gt;
</font>
												</code>
										</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>因为请求时属性值是用表达式指定的，所以它们往往有和其它脚本元素一样的软件维护问题。因此，JSTL 定制标记支持另一种用于指定动态属性值的机制。可以用简化的 <i>表达式语言</i>（EL）而不使用完整的 JSP 表达式来指定 JSTL 操作的属性值。EL 提供了一些标识符、存取器和运算符，用来检索和操作驻留在 JSP 容器中的数据。EL 在某种程度上以 EcmaScript（请参阅 <a href="http://www.ibm.com/developerworks/cn/java/j-jstl0211/#resources"><font color="#996699">参考资料</font></a>）和 XML 路径语言（XML Path Language，XPath）为基础，因此页面设计人员和程序员都应该熟悉它的语法。EL 擅长寻找对象及其特性，然后对它们执行简单操作；它不是编程语言，甚至不是脚本编制语言。但是，与 JSTL 标记一起使用时，它就能使用简单而又方便的符号来表示复杂的行为。EL 表达式的格式是这样的：用美元符号（$）定界，内容包括在花括号（{}）中，如清单 3 所示。 </p>
		<br />
		<a name="IDAYFSVB">
				<b>清单 3. 说明 EL 表达式定界符的 JSTL 操作</b>
		</a>
		<br />
		<table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1">
				<tbody>
						<tr>
								<td>
										<pre>
												<code class="section">
														<font face="Lucida Console">&lt;c:out value="${user.firstName}"/&gt;
</font>
												</code>
										</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>此外，您可以将多个表达式与静态文本组合在一起以通过字符串并置来构造动态属性值，如清单 4 所示。单独的表达式由标识符、存取器、文字和运算符组成。标识符用来引用存储在数据中心中的数据对象。EL 有 11 个保留标识符，对应于 11 个 EL 隐式对象。假定所有其它标识符都引用 <i>限制了作用域的变量</i>。存取器用来检索对象的特性或集合的元素。文字表示固定的值 ― 数字、字符、字符串、布尔型或空值。运算符允许对数据和文字进行组合以及比较。 </p>
		<br />
		<a name="IDAHGSVB">
				<b>清单 4. 组合静态文本和多个 EL 表达式以指定动态属性值</b>
		</a>
		<br />
		<table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1">
				<tbody>
						<tr>
								<td>
										<pre>
												<code class="section">
														<font face="Lucida Console">&lt;c:out value="Hello ${user.firstName} ${user.lastName}"/&gt;
</font>
												</code>
										</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td>
										<font face="Lucida Console">
												<img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" />
												<br />
												<img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" />
										</font>
								</td>
						</tr>
				</tbody>
		</table>
		<table class="no-print" cellspacing="0" cellpadding="0" align="right">
				<tbody>
						<tr align="right">
								<td>
										<font face="Lucida Console">
												<img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" />
												<br />
										</font>
										<table cellspacing="0" cellpadding="0" border="0">
												<tbody>
														<tr>
																<td valign="center">
																		<font face="Lucida Console">
																				<img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" />
																				<br />
																		</font>
																</td>
																<td valign="top" align="right">
																		<b>
																				<font color="#996699">
																				</font>
																		</b>
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<p>
				<a name="3">
						<span class="atitle">
								<font face="Arial" size="4">限制了作用域的变量</font>
						</span>
				</a>
		</p>
		<p>JSP API 通过 <code>&lt;jsp:useBean&gt;</code> 操作允许从 JSP 容器内的四个不同作用域中存储和检索数据。JSTL 通过提供用于指定和除去这些作用域中的对象的附加操作来扩展这一能力。此外，EL 提供将这些对象作为限制了作用域的变量进行检索的内置支持。特别地，任何出现在 EL 表达式中但不对应于任何 EL 隐式对象的标识符，都被自动假定为引用存储在四个 JSP 作用域的其中某个中的对象，这四个作用域是： </p>
		<ul>
				<li>页面作用域 
</li>
				<li>请求作用域 
</li>
				<li>会话作用域 
</li>
				<li>应用程序作用域 </li>
		</ul>
		<p>您可能还记得，只有在为特定请求处理页面期间才能检索存储在该页面作用域中的对象。如果对象是存储在请求作用域中的，可以在处理所有参与处理某请求的页面期间检索这些对象（譬如在对某个请求的处理中遇到了一个或多个 <code>&lt;jsp:include&gt;</code> 或 <code>&lt;jsp:forward&gt;</code> 操作）。如果对象是存储在会话作用域中的，则在与 Web 应用程序的交互式会话期间，可以由用户访问的任何页面检索它（即，直到与该用户交互相关联的 <code>HttpSession</code> 对象无效为止）。可以由任何用户从任何页面访问存储在应用程序作用域中的对象，直到卸载 Web 应用程序本身为止（通常是由于关闭 JSP 容器所致）。 </p>
		<p>通过将字符串映射为期望作用域中的对象来将对象存储到该作用域。然后，就可以通过提供相同字符串来从该作用域检索该对象。在作用域的映射中查找字符串，并返回被映射的对象。在 Servlet API 中，将此类对象称为相应作用域的 <i>属性</i>。但是，在 EL 的上下文中，也将与属性相关联的字符串看作变量的名称，该变量通过属性映射的方式获得特定的值。 </p>
		<p>在 EL 中，与隐式对象无关联的标识符被认为是存储在四个 JSP 作用域中的名称对象。首先对页面作用域检查是否存在这样的标识符，其次对请求作用域、然后对会话作用域、最后对应用程序作用域依次进行这样的检查，然后测试该标识符的名称是否与存储在该作用域中的某个对象的名称匹配。第一个这样的匹配作为 EL 标识符的值被返回。通过这种方法，可以将 EL 标识符看作引用限制了作用域的变量。</p>
		<p>从更技术的方面来说，没有映射到隐式对象的标识符是用 <code>PageContext</code> 实例的 <code>findAttribute()</code> 方法求值的，该实例表示对页面的处理，在该页面上，当前正在处理用于请求的表达式。标识符的名称作为参数传递给这个方法，然后该方法依次在四个作用域中搜索具有相同名称的属性。并将所找到的第一个匹配项作为 <code>findAttribute()</code> 方法的值返回。如果未在这四个作用域中找到这样的属性，则返回 <code>null</code> 。 </p>
		<p>最终，限制了作用域的变量是四个 JSP 作用域的属性，这些属性具有可以用作 EL 标识符的名称。只要对限制了作用域的变量赋予由字母数字组成的名称，就可以通过 JSP 中提供的用于设置属性的任何机制来创建它们。这包括内置的 <code>&lt;jsp:useBean&gt;</code> 操作，以及由 Servlet API 中的几个类定义的 <code>setAttribute()</code> 方法。此外，四个 JSTL 库中定义的许多定制标记本身就能够设置作为限制了作用域的变量使用的属性值。 </p>
		<br />
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td>
										<img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" />
										<br />
										<img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" />
								</td>
						</tr>
				</tbody>
		</table>
		<table class="no-print" cellspacing="0" cellpadding="0" align="right">
				<tbody>
						<tr align="right">
								<td>
										<img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" />
										<br />
										<table cellspacing="0" cellpadding="0" border="0">
												<tbody>
														<tr>
																<td valign="center">
																		<img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" />
																		<br />
																</td>
																<td valign="top" align="right">
																		<b>
																				<font color="#996699">
																				</font>
																		</b>
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<p>
				<a name="4">
						<span class="atitle">
								<font face="Arial" size="4">隐式对象</font>
						</span>
				</a>
		</p>
		<p>表 1 中列出了 11 个 EL 隐式对象的标识符。不要将这些对象与 JSP 隐式对象（一共只有九个）混淆，其中只有一个对象是它们所共有的。</p>
		<p>
				<a name="N10147">
						<span class="smalltitle">
								<strong>
										<font face="Arial">表 1. EL 隐式对象</font>
								</strong>
						</span>
				</a>
		</p>
		<p>
		</p>
		<table cellspacing="0" cellpadding="3" width="100%" border="1">
				<tbody>
						<tr valign="top">
								<td>
										<strong>类别</strong>
								</td>
								<td>
										<b>标识符</b>
								</td>
								<td>
										<b>描述</b>
								</td>
						</tr>
						<tr valign="top">
								<td>JSP</td>
								<td>
										<code>pageContext</code>
								</td>
								<td>
										<code>PageContext</code> 实例对应于当前页面的处理 </td>
						</tr>
						<tr valign="top">
								<td rowspan="4">作用域</td>
								<td>
										<code>pageScope</code>
								</td>
								<td>与页面作用域属性的名称和值相关联的 <code>Map</code> 类 </td>
						</tr>
						<tr valign="top">
								<td>
										<code>requestScope</code>
								</td>
								<td>与请求作用域属性的名称和值相关联的 <code>Map</code> 类 </td>
						</tr>
						<tr valign="top">
								<td>
										<code>sessionScope</code>
								</td>
								<td>与会话作用域属性的名称和值相关联的 <code>Map</code> 类 </td>
						</tr>
						<tr valign="top">
								<td>
										<code>applicationScope</code>
								</td>
								<td>与应用程序作用域属性的名称和值相关联的 <code>Map</code> 类 </td>
						</tr>
						<tr valign="top">
								<td rowspan="2">请求参数</td>
								<td>
										<code>param</code>
								</td>
								<td>按名称存储请求参数的主要值的 <code>Map</code> 类 </td>
						</tr>
						<tr valign="top">
								<td>
										<code>paramValues</code>
								</td>
								<td>将请求参数的所有值作为 <code>String</code> 数组存储的 <code>Map</code> 类 </td>
						</tr>
						<tr valign="top">
								<td rowspan="2">请求头</td>
								<td>
										<code>header</code>
								</td>
								<td>按名称存储请求头主要值的 <code>Map</code> 类 </td>
						</tr>
						<tr valign="top">
								<td>
										<code>headerValues</code>
								</td>
								<td>将请求头的所有值作为 <code>String</code> 数组存储的 <code>Map</code> 类 </td>
						</tr>
						<tr valign="top">
								<td>Cookie</td>
								<td>
										<code>cookie</code>
								</td>
								<td>按名称存储请求附带的 cookie 的 <code>Map</code> 类 </td>
						</tr>
						<tr valign="top">
								<td>初始化参数</td>
								<td>
										<code>initParam</code>
								</td>
								<td>按名称存储 Web 应用程序上下文初始化参数的 <code>Map</code> 类 </td>
						</tr>
				</tbody>
		</table>
		<p>尽管 JSP 和 EL 隐式对象中只有一个公共对象（ <code>pageContext</code> ），但通过 EL 也可以访问其它 JSP 隐式对象。原因是 <code>pageContext</code> 拥有访问所有其它八个 JSP 隐式对象的特性。实际上，这是将它包括在 EL 隐式对象中的主要理由。 </p>
		<p>其余所有 EL 隐式对象都是映射，可以用来查找对应于名称的对象。前四个映射表示先前讨论的各种属性作用域。可以用它们来查找特定作用域中的标识符，而不用依赖于 EL 在缺省情况下使用的顺序查找过程。</p>
		<p>接下来的四个映射用来获取请求参数和请求头的值。因为 HTTP 协议允许请求参数和请求头具有多个值，所以它们各有一对映射。每对中的第一个映射返回请求参数或头的主要值，通常是恰巧在实际请求中首先指定的那个值。每对中第二个映射允许检索参数或头的所有值。这些映射中的键是参数或头的名称，但这些值是 <code>String</code> 对象的数组，其中的每个元素都是单一参数值或头值。 </p>
		<p>cookie 隐式对象提供了对由请求设置的 cookie 名称的访问。这个对象将所有与请求相关联的 cookie 名称映射到表示那些 cookie 特性的 <code>Cookie</code> 对象。 </p>
		<p>最后一个 EL 隐式对象 <code>initParam</code> 是一个映射，它储存与 Web 应用程序相关联的所有上下文的初始化参数的名称和值。初始化参数是通过 <code>web.xml</code> 部署描述符文件指定的，该文件位于应用程序的 <code>WEB-INF</code> 目录中。 </p>
		<br />
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td>
										<img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" />
										<br />
										<img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" />
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<p>
				<a name="5">
						<span class="atitle">
								<font face="Arial" size="4">存取器</font>
						</span>
				</a>
		</p>
		<p>因为 EL 标识符是作为隐式对象或限制了作用域的变量（通过属性来实现）解析的，因此有必要将它们转换成 Java 对象。EL 可以自动包装和解包其相应的 Java 类中的基本类型（例如，可以在后台将 <code>int</code> 强制转换成 <code>Integer</code> 类，反之亦可），但大多数的标识符将成为指向完整的 Java 对象的指针。 </p>
		<p>结果是，对这些对象的特性或（在对象是数组和集合的情况下）对其元素的访问通常是令人满意的。就为了实现这种用途，EL 提供了两种不同的存取器（点运算符（ <code>.</code> ）和方括号运算符（ <code>[]</code> ）），也支持通过 EL 操作特性和元素。 </p>
		<p>点运算符通常用于访问对象的特性。例如，在表达式 <code>${user.firstName}</code> 中，使用点运算符来访问 <code>user</code> 标识符所引用对象的名为 <code>firstName</code> 的特性。EL 使用 Java bean 约定访问对象特性，因此必须定义这个特性的 getter 方法（通常是名为 <code>getFirstName()</code> 的方法），以便表达式正确求值。当被访问的特性本身是对象时，可以递归地应用点运算符。例如，如果我们虚构的 <code>user</code> 对象有一个实现为 Java 对象的 <code>address</code> 特性，那么也可以用点运算符来访问这个对象的特性。例如，表达式 <code>${user.address.city}</code> 将会返回这个地址对象嵌套的 <code>city</code> 特性。 </p>
		<p>方括号运算符用来检索数组和集合的元素。在数组和有序集合（也即，实现了 <code>java.util.List</code> 接口的集合）的情况下，把要检索的元素的下标放在方括号中。例如，表达式 <code>${urls[3]}</code> 返回 <code>urls</code> 标识符所引用的数组或集合的第四个元素（和 Java 语言以及 JavaScript 中一样，EL 中的下标是从零开始的）。 </p>
		<p>对于实现 <code>java.util.Map</code> 接口的集合，方括号运算符使用关联的键查找存储在映射中的值。在方括号中指定键，并将相应的值作为表达式的值返回。例如，表达式 <code>${commands["dir"]}</code> 返回与 <code>commands</code> 标识符所引用的 <code>Map</code> 中的 <code>"dir"</code> 键相关联的值。 </p>
		<p>对于上述两种情况，都可允许表达式出现在方括号中。对嵌套表达式求值的结果将被作为下标或键，用来检索集合或数组的适当元素。和点运算符一样，方括号运算符也可以递归应用。这使得 EL 能够从多维数组、嵌套集合或两者的任意组合中检索元素。此外，点运算符和方括号运算符还可以互操作。例如，如果数组的元素本身是对象，则可以使用方括号运算符来检索该数组的元素，并结合点运算符来检索该元素的一个特性（例如 <code>${urls[3].protocol}</code> ）。 </p>
		<p>假定 EL 充当指定动态属性值的简化语言，EL 存取器有一个有趣的功能（与 Java 语言的存取器不同），那就是它们在应用于 <code>null</code> 时不抛出异常。如果应用 EL 存取器的对象（例如， <code>${foo.bar}</code> 和 <code>${foo["bar"]}</code> 中的 <code>foo</code> 标识符）是 <code>null</code> ，那么应用存取器的结果也是 <code>null</code> 。事实证明，在大多数情况下，这是一个相当有用的行为，不久您就会了解这一点。 </p>
		<p>最后，点运算符和方括号运算符可能实现某种程度的互换。例如，也可以使用 <code>${user["firstName"]}</code> 来检索 <code>user</code> 对象的 <code>firstName</code> 特性，正如可以用 <code>${commands.dir}</code> 获取与 <code>commands</code> 映射中的 <code>"dir"</code> 键相关联的值一样。 </p>
		<br />
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td>
										<img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" />
										<br />
										<img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" />
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<p>
				<a name="6">
						<span class="atitle">
								<font face="Arial" size="4">运算符</font>
						</span>
				</a>
		</p>
		<p>EL 还可以通过使用标识符和存取器，遍历包含应用程序数据（通过限制了作用域的变量公开）或关于环境的信息（通过 EL 隐式对象）的对象层次结构。但是，只是访问这些数据，通常不足以实现许多 JSP 应用程序所需的表示逻辑。</p>
		<p>最终，EL 还包括了几个用来操作和比较 EL 表达式所访问数据的运算符。表 2 中汇总了这些运算符。</p>
		<p>
				<a name="N10329">
						<span class="smalltitle">
								<strong>
										<font face="Arial">表 2. EL 运算符</font>
								</strong>
						</span>
				</a>
		</p>
		<p>
		</p>
		<table cellspacing="0" cellpadding="3" width="100%" border="1">
				<tbody>
						<tr valign="top">
								<td>
										<strong>类别</strong>
								</td>
								<td>
										<b>运算符</b>
								</td>
						</tr>
						<tr valign="top">
								<td>算术运算符</td>
								<td>
										<code>+</code> 、 <code>-</code> 、 <code>*</code> 、 <code>/</code> （或 <code>div</code> ）和 <code>%</code> （或 <code>mod</code> ） </td>
						</tr>
						<tr valign="top">
								<td>关系运算符</td>
								<td>
										<code>==</code> （或 <code>eq</code> ）、 <code>!=</code> （或 <code>ne</code> ）、 <code>&lt;</code> （或 <code>lt</code> ）、 <code>&gt;</code> （或 <code>gt</code> ）、 <code>&lt;=</code> （或 <code>le</code> ）和 <code>&gt;=</code> （或 <code>ge</code> ） </td>
						</tr>
						<tr valign="top">
								<td>逻辑运算符</td>
								<td>
										<code>&amp;&amp;</code> （或 <code>and</code> ）、 <code>||</code> （或 <code>or</code> ）和 <code>!</code> （或 <code>not</code> ） </td>
						</tr>
						<tr valign="top">
								<td>验证运算符</td>
								<td>
										<code>empty</code>
								</td>
						</tr>
				</tbody>
		</table>
		<p>算术运算符支持数值的加法、减法、乘法和除法。还提供了一个求余运算符。注：除法和求余运算符都有替代的、非符号的名称（为的是与 XPath 保持一致）。清单 5 中显示了一个演示算术运算符用法的示例表达式。对几个 EL 表达式应用算术运算符的结果是将该算术运算符应用于这些表达式返回的数值所得的结果。</p>
		<br />
		<a name="IDAD5SVB">
				<b>清单 5. 利用算术运算符的 EL 表达式</b>
		</a>
		<br />
		<table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1">
				<tbody>
						<tr>
								<td>
										<pre>
												<code class="section">
														<font face="Lucida Console">${item.price * (1 + taxRate[user.address.zipcode])}
</font>
												</code>
										</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>关系运算符允许比较数字或文本数据。比较的结果作为布尔值返回。逻辑运算符允许合并布尔值，返回新的布尔值。因此，可以将 EL 逻辑运算符应用于嵌套的关系或逻辑运算符的结果，如清单 6 所示。</p>
		<br />
		<a name="IDAO5SVB">
				<b>清单 6. 利用关系和逻辑运算符的 EL 表达式</b>
		</a>
		<br />
		<table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1">
				<tbody>
						<tr>
								<td>
										<pre>
												<code class="section">
														<font face="Lucida Console">${(x &gt;= min) &amp;&amp; (x &lt;= max)}
</font>
												</code>
										</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>最后一种 EL 运算符是 <code>empty</code> ，它对于验证数据特别有用。 <code>empty</code> 运算符采用单个表达式作为其变量（也即， <code>${empty input}</code> ），并返回一个布尔值，该布尔值表示对表达式求值的结果是不是“空”值。求值结果为 <code>null</code> 的表达式被认为是空，即无元素的集合或数组。如果参数是对长度为零的 <code>String</code> 求值所得的结果，则 <code>empty</code> 运算符也将返回 <code>true</code> 。 </p>
		<p>表 3 显示了 EL 运算符的优先级。正如清单 5 和 6 所示，可以用圆括号对表达式分组，高于普通的优先级规则。</p>
		<p>
				<a name="N10415">
						<span class="smalltitle">
								<strong>
										<font face="Arial">表 3. EL 运算符优先级（自顶到底，从左到右）</font>
								</strong>
						</span>
				</a>
		</p>
		<p>
		</p>
		<table cellspacing="0" cellpadding="3" width="100%" border="1">
				<tbody>
						<tr valign="top">
								<td>
										<code>[]</code> , <code>.</code></td>
						</tr>
						<tr valign="top">
								<td>
										<code>()</code>
								</td>
						</tr>
						<tr valign="top">
								<td>unary <code>-</code> 、 <code>not</code> 、 <code>!</code> 、 <code>empty</code></td>
						</tr>
						<tr valign="top">
								<td>
										<code>*</code> 、 <code>/</code> 、 <code>div</code> 、 <code>%</code> 、 <code>mod</code></td>
						</tr>
						<tr valign="top">
								<td>
										<code>+</code> 、binary <code>-</code></td>
						</tr>
						<tr valign="top">
								<td>() <code>&lt;&lt;/code&gt;</code> 、 <code>&gt;</code> 、 <code>&lt;=</code> 、 <code>&gt;=</code> 、 <code>lt</code> 、 <code>gt</code> 、 <code>le</code> 、 <code>ge</code></td>
						</tr>
						<tr valign="top">
								<td>
										<code>==</code> 、 <code>!=</code> 、 <code>eq</code> 、 <code>ne</code></td>
						</tr>
						<tr valign="top">
								<td>
										<code>&amp;&amp;</code> 、 <code>and</code></td>
						</tr>
						<tr valign="top">
								<td>
										<code>||</code> 、 <code>or</code></td>
						</tr>
				</tbody>
		</table>
		<br />
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td>
										<img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" />
										<br />
										<img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" />
								</td>
						</tr>
				</tbody>
		</table>
		<table class="no-print" cellspacing="0" cellpadding="0" align="right">
				<tbody>
						<tr align="right">
								<td>
										<img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" />
										<br />
										<table cellspacing="0" cellpadding="0" border="0">
												<tbody>
														<tr>
																<td valign="center">
																		<img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" />
																		<br />
																</td>
																<td valign="top" align="right">
																		<b>
																				<font color="#996699">
																				</font>
																		</b>
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<p>
				<a name="7">
						<span class="atitle">
								<font face="Arial" size="4">文字</font>
						</span>
				</a>
		</p>
		<p>在 EL 表达式中，数字、字符串、布尔值和 <code>null</code> 都可以被指定为文字值。字符串可以用单引号或双引号定界。布尔值被指定为 <code>true</code> 和 <code>false</code> 。 </p>
		<br />
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td>
										<img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" />
										<br />
										<img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" />
								</td>
						</tr>
				</tbody>
		</table>
		<table class="no-print" cellspacing="0" cellpadding="0" align="right">
				<tbody>
						<tr align="right">
								<td>
										<img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" />
										<br />
										<table cellspacing="0" cellpadding="0" border="0">
												<tbody>
														<tr>
																<td valign="center">
																		<img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" />
																		<br />
																</td>
																<td valign="top" align="right">
																		<b>
																				<font color="#996699">
																				</font>
																		</b>
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<p>
				<a name="8">
						<span class="atitle">
								<font face="Arial" size="4">Taglib 伪指令</font>
						</span>
				</a>
		</p>
		<p>正如我们先前讨论的，JSTL 1.0 包括四个定制标记库。为了演示 JSTL 标记和表达式语言的交互，我们将研究几个来自 JSTL <code>core</code> 库的标记。和使用任何 JSP 定制标记库一样，必须在您想要使用这个库标记的任何页面中包括 <code>taglib</code> 伪指令。清单 7 显示了用于这个特定库的伪指令。 </p>
		<br />
		<a name="IDAFCTVB">
				<b>清单 7. 用于 JSTL core 库 EL 版本的 taglib 伪指令</b>
		</a>
		<br />
		<table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1">
				<tbody>
						<tr>
								<td>
										<pre>
												<code class="section">
														<font face="Lucida Console">&lt;%@ taglib uri="http://java.sun.com/jstl/core" prefix="c" %&gt;
</font>
												</code>
										</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>实际上，对应于 JSTL <code>core</code> 库的 <code>taglib</code> 伪指令有两种，因为在 JSTL 1.0 中，EL 是可选的。所有四个 JSTL 1.0 定制标记库都有使用 JSP 表达式（而不是 EL）指定动态属性值的备用版本。因为这些备用库依赖于 JSP 的更传统的请求时属性值，所以它们被称为 <i>RT</i>库，而那些使用表达式语言的则被称为 <i>EL</i> 库。开发人员用不同的 <code>taglib</code> 伪指令来区分每个库的这两个版本。清单 8 显示了使用 core 库的 RT 版本的伪指令。但是，由于现在我们讨论的重点是 EL，所以首先需要这些伪指令。 </p>
		<br />
		<a name="IDAADTVB">
				<b>清单 8. 用于 JSTL core 库 RT 版本的 taglib 伪指令</b>
		</a>
		<br />
		<table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1">
				<tbody>
						<tr>
								<td>
										<pre>
												<code class="section">
														<font face="Lucida Console">&lt;%@ taglib uri="http://java.sun.com/jstl/core_rt" prefix="c_rt" %&gt;
</font>
												</code>
										</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td>
										<font face="Lucida Console">
												<img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" />
												<br />
												<img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" />
										</font>
								</td>
						</tr>
				</tbody>
		</table>
		<table class="no-print" cellspacing="0" cellpadding="0" align="right">
				<tbody>
						<tr align="right">
								<td>
										<font face="Lucida Console">
												<img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" />
												<br />
										</font>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<p>
				<a name="9">
						<span class="atitle">
								<font face="Arial" size="4">变量标记</font>
						</span>
				</a>
		</p>
		<p>我们首先要考虑的 JSTL 定制标记是 <code>&lt;c:set&gt;</code> 操作。正如已经说明的，限制了作用域的变量在 JSTL 中起关键作用， <code>&lt;c:set&gt;</code> 操作提供基于标记的机制来创建和设置限制了作用域的变量。清单 9 中显示了该操作的语法，其中 <code>var</code> 属性指定了限制了作用域的变量的名称， <code>scope</code> 属性表明了该变量驻留在哪个作用域中， <code>value</code> 属性指定了分配给该变量的值。如果指定变量已经存在，则简单地将所指明的值赋给它。如果不存在，则创建新的限制了作用域的变量，并用该值初始化这个变量。 </p>
		<br />
		<a name="IDAHETVB">
				<b>清单 9. &lt;c:set&gt; 操作的语法</b>
		</a>
		<br />
		<table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1">
				<tbody>
						<tr>
								<td>
										<pre>
												<code class="section">
														<font face="Lucida Console">&lt;c:set var="
        <i>name</i>" scope="
        <i>scope</i>" value="
        <i>expression</i>"/&gt;

      </font>
												</code>
										</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>
				<code>scope</code> 属性是可选的，其缺省值是 <code>page</code> 。 </p>
		<p>清单 10 中显示了 <code>&lt;c:set&gt;</code> 的两个示例。在第一个示例中，将会话作用域变量设置成 <code>String</code> 值。在第二个示例中，用表达式来设置数值：将页面作用域内名为 <code>square</code> 的变量赋值为名为 <code>x</code> 的请求参数的值的平方。 </p>
		<br />
		<a name="IDARFTVB">
				<b>清单 10. &lt;c:set&gt; 操作示例</b>
		</a>
		<br />
		<table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1">
				<tbody>
						<tr>
								<td>
										<pre>
												<code class="section">
														<font face="Lucida Console">&lt;c:set var="timezone" scope="session" value="CST"/&gt;
&lt;c:set var="square" value="${param['x'] * param['x']}"/&gt;
</font>
												</code>
										</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>您还可以将限制了作用域的变量的值指定为 <code>&lt;c:set&gt;</code> 操作的主体内容，而不是使用属性。使用这种方法，您可以重新编写清单 10 中的第一个示例，如清单 11 所示。此外，正如我们马上可以看到的， <code>&lt;c:set&gt;</code> 标记的主体内容本身也可以使用定制标记。 <code>&lt;c:set&gt;</code> 主体内生成的所有内容都将作为一个 <code>String</code> 值赋给指定变量。 </p>
		<br />
		<a name="listing11">
				<b>清单 11. 通过主体内容指定 &lt;c:set&gt; 操作的值</b>
		</a>
		<br />
		<table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1">
				<tbody>
						<tr>
								<td>
										<pre>
												<code class="section">
														<font face="Lucida Console">&lt;c:set var="timezone" scope="session"&gt;CST&lt;/c:set&gt;
</font>
												</code>
										</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>JSTL core 库包含第二个用于管理限制了作用域的变量的标记 ― <code>&lt;c:remove&gt;</code> 。顾名思义， <code>&lt;c:remove&gt;</code> 操作是用来删除限制了作用域的变量的，它获取两个属性。 <code>var</code> 属性指定待删除变量的名称， <code>scope</code> 属性是可选的，它表示待删除变量来自哪个作用域，缺省为 <code>page</code> ，如清单 12 所示。 </p>
		<a name="IDALHTVB">
				<b>清单 12. &lt;c:remove&gt; 操作示例</b>
		</a>
		<table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1">
				<tbody>
						<tr>
								<td>
										<pre>
												<code class="section">
														<font face="Lucida Console">&lt;c:remove var="timezone" scope="session"/&gt;
</font>
												</code>
										</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td>
										<font face="Lucida Console">
												<img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" />
												<br />
												<img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" />
										</font>
								</td>
						</tr>
				</tbody>
		</table>
		<table class="no-print" cellspacing="0" cellpadding="0" align="right">
				<tbody>
						<tr align="right">
								<td>
										<font face="Lucida Console">
												<img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" />
												<br />
										</font>
										<table cellspacing="0" cellpadding="0" border="0">
												<tbody>
														<tr>
																<td valign="center">
																		<font face="Lucida Console">
																				<img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" />
																				<br />
																		</font>
																</td>
																<td valign="top" align="right">
																		<b>
																				<font color="#996699">
																				</font>
																		</b>
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<p>
				<a name="10">
						<span class="atitle">
								<font face="Arial" size="4">输出</font>
						</span>
				</a>
		</p>
		<p>尽管 <code>&lt;c:set&gt;</code> 操作允许将表达式结果赋给限制了作用域的变量，但开发人员通常会希望只显示表达式的值，而不存储它。JSTL <code>&lt;c:out&gt;</code> 定制标记承担这一任务，其语法如清单 13 所示。该标记对由其 <code>value</code> 属性指定的表达式进行求值，然后打印结果。如果指定了可选属性 <code>default</code> ，那么，在对 <code>value</code> 属性的表达式求值所得结果为 <code>null</code> 或空 <code>String</code> 的情况下， <code>&lt;c:out&gt;</code> 将打印其值。 </p>
		<br />
		<a name="IDABJTVB">
				<b>清单 13. &lt;c:out&gt; 操作的语法</b>
		</a>
		<br />
		<table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1">
				<tbody>
						<tr>
								<td>
										<pre>
												<code class="section">
														<font face="Lucida Console">&lt;c:out value="
        <i>expression</i>" default="
        <i>expression</i>" escapeXml="
        <i>boolean</i>"/&gt;

      </font>
												</code>
										</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>
				<code>escapeXml</code> 属性也是可选的。它控制当用 <code>&lt;c:out&gt;</code> 标记输出诸如“&lt;”、“&gt;”和“&amp;”之类的字符（在 HTML 和 XML 中具有特殊意义）时是否应该进行转义。如果将 <code>escapeXml</code> 设置为 true，则会自动将这些字符转换成相应的 XML 实体（此处提到的字符分别转换成 <code>&lt;</code> 、 <code>&gt;</code> 和 <code>&amp;</code> ）。 </p>
		<p>例如，假定有一个名为 <code>user</code> 的会话作用域变量，它是一个类的实例，该类为用户定义了两个特性： <code>username</code> 和 <code>company</code> 。每当用户访问站点时，这个对象被自动分配给会话，但直到用户实际登录后，才会设置这两个特性。假定是这种方案，请考虑清单 14 中的 JSP 片段。在用户登录之后，这个片段将显示单词“Hello”，其后是他／她的用户名和一个惊叹号。但是，在用户登录之前，由这个片段生成的内容则是短语“Hello Guest!”。在这种情况下，因为 <code>username</code> 特性还有待初始化，所以 <code>&lt;c:out&gt;</code> 标记将转而打印出 <code>default</code> 属性的值（即字符串“Guest”）。 </p>
		<br />
		<a name="IDADLTVB">
				<b>清单 14. 带缺省内容的 &lt;c:out&gt; 操作示例</b>
		</a>
		<br />
		<table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1">
				<tbody>
						<tr>
								<td>
										<pre>
												<code class="section">
														<font face="Lucida Console">Hello &lt;c:out value="${user.username}" default=="Guest"/&gt;!
</font>
												</code>
										</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>接下来，考虑清单 15，它使用了 <code>&lt;c:out&gt;</code> 标记的 <code>escapeXml</code> 属性。如果在这种情况下已经将 <code>company</code> 特性设置成 Java <code>String</code> 值 <code>"Flynn &amp; Sons"</code> ，那么，实际上该操作生成的内容将是 <code>Flynn &amp; Sons</code> 。如果这个操作是生成 HTML 或 XML 内容的 JSP 页面的一部分，那么，这个字符串中间的“&amp;”符号最终可能被解释为 HTML 或 XML 控制字符，从而妨碍了对该内容的显示或解析。但是，如果将 <code>escapeXml</code> 属性值设置成 <code>true</code> ，则所生成的内容将是 <code>Flynn &amp; Sons</code> 。浏览器或解析器不会因在解释时遇到这种内容而出问题。假定 HTML 和 XML 是 JSP 应用程序中最常见的内容类型，所以 <code>escapeXml</code> 属性的缺省值是 <code>true</code> 就不足为奇了。 </p>
		<br />
		<a name="IDA0MTVB">
				<b>清单 15. 禁用转义的 &lt;c:out&gt; 操作示例</b>
		</a>
		<br />
		<table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1">
				<tbody>
						<tr>
								<td>
										<pre>
												<code class="section">
														<font face="Lucida Console">&lt;c:out value="${user.company}" escapeXml=="false"/&gt;
</font>
												</code>
										</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td>
										<font face="Lucida Console">
												<img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" />
												<br />
												<img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" />
										</font>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<p>
				<a name="11">
						<span class="atitle">
								<font face="Arial" size="4">用缺省值设置变量</font>
						</span>
				</a>
		</p>
		<p>除了简化动态数据的显示之外，当通过 <code>&lt;c:set&gt;</code> 设置变量值时， <code>&lt;c:out&gt;</code> 指定缺省值的能力也很有用。正如 <a href="http://www.ibm.com/developerworks/cn/java/j-jstl0211/#listing11"><font color="#996699">清单 11</font></a> 所示，用来赋给限制了作用域的变量的值可以指定为 <code>&lt;c:set&gt;</code> 标记的主体内容，也可以通过其值属性来指定。通过将 <code>&lt;c:out&gt;</code> 操作嵌套在 <code>&lt;c:set&gt;</code> 标记的主体内容中，变量赋值就可以利用其缺省值能力。 </p>
		<p>清单 16 中说明了这种方法。外部 <code>&lt;c:set&gt;</code> 标记的行为非常简单：它根据其主体内容设置会话作用域 <code>timezone</code> 变量的值。但是，在这种情况下，主体内容是通过 <code>&lt;c:out&gt;</code> 操作生成的。这个嵌套操作的值属性是表达式 <code>${cookie['tzPref'].value}</code> ，它尝试通过 <code>cookie</code> 隐式对象返回名为 <code>tzPref</code> 的 cookie 值。（ <code>cookie</code> 隐式对象将 cookie 名称映射到相应的 <code>Cookie</code> 实例，这意味着必须通过对象的 <code>value</code> 特性使用点运算符来检索储存在 cookie 中的实际数据。） </p>
		<br />
		<a name="IDAKPTVB">
				<b>清单 16. 合并 &lt;c:set&gt; 和 &lt;c:out&gt; 以提供缺省变量值</b>
		</a>
		<br />
		<table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1">
				<tbody>
						<tr>
								<td>
										<pre>
												<code class="section">
														<font face="Lucida Console">&lt;c:set var="timezone" scope=="session"&gt;
   &lt;c:out value="${cookie['tzPref'].value}" default=="CST"/&gt;
&lt;/c:set&gt;
</font>
												</code>
										</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>但是，请考虑以下情况，用户是第一次尝试使用这段代码的 Web 应用程序。结果是，请求中没有提供名为 <code>tzPref</code> 的 cookie。这意味着使用隐式对象的查找将返回 <code>null</code> ，在这种情况下整个表达式将返回 <code>null</code> 。因为对 <code>&lt;c:out&gt;</code> 标记的 <code>value</code> 属性求值的结果是 <code>null</code> ，所以 <code>&lt;c:out&gt;</code> 标记会转而输出对其 <code>default</code> 属性求值的结果。在这里是字符串 <code>CST</code> 。因此，实际的结果是将 <code>timezone</code> 限制了作用域的变量设置成用户的 <code>tzPref</code> cookie 中存储的时区，或者，如果没有，则使用缺省时区 <code>CST</code> 。 </p>
		<table cellspacing="0" cellpadding="0" width="40%" align="right" border="0">
				<tbody>
						<tr>
								<td width="10">
										<img height="1" alt="" src="http://www.ibm.com/i/c.gif" width="10" />
								</td>
								<td>
										<table cellspacing="0" cellpadding="5" width="100%" border="1">
												<tbody>
														<tr>
																<td bgcolor="#eeeeee">
																		<a name="IDAFRTVB">
																				<b>EL 和 JSP 2.0</b>
																		</a>
																		<br />
																		<p>目前，表达式语言仅可用于指定 JSTL 定制标记中的动态属性值。但 JSTL 1.0 表达式语言的一个扩展已经被提出，会把它包括到 JSP 2.0 中去，眼下正在进行最后评审。这个扩展将允许开发人员通过自己的定制标记来使用 EL。页面作者将可以在目前允许使用 JSP 表达式的任何地方使用 EL 表达式，譬如将动态值插入模板文本中： <code>&lt;p&gt;Your preferred time zone is ${timezone}&lt;/p&gt;</code> 。 </p>
																		<p>这个 JSP 2.0 功能（就象 JSTL 本身一样）将支持页面作者进一步减少对 JSP 编制脚本元素的依赖，从而改进 JSP 应用程序的可维护性。 </p>
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td>
										<img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" />
										<br />
										<img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" />
								</td>
						</tr>
				</tbody>
		</table>
		<table class="no-print" cellspacing="0" cellpadding="0" align="right">
				<tbody>
						<tr align="right">
								<td>
										<img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" />
										<br />
										<table cellspacing="0" cellpadding="0" border="0">
												<tbody>
														<tr>
																<td valign="center">
																		<img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" />
																		<br />
																</td>
																<td valign="top" align="right">
																		<a class="fbox" href="http://www.ibm.com/developerworks/cn/java/j-jstl0211/#main">
																				<b>
																						<font color="#996699">回页首</font>
																				</b>
																		</a>
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<p>
				<a name="12">
						<span class="atitle">
								<font face="Arial" size="4">结束语</font>
						</span>
				</a>
		</p>
		<p>EL（与四个 JSTL 定制标记库提供的操作结合起来）允许页面作者不使用脚本元素即可实现表示层逻辑。例如，对比本文开头 <a href="http://www.ibm.com/developerworks/cn/java/j-jstl0211/#listing1"><font color="#996699">清单 1</font></a> 中的 JSP 代码和清单 17 中显示的通过 JSTL 实现的同样功能。（JSTL <code>core</code> 库中其余的标记，包括 <code>&lt;c:choose&gt;</code> 及其子标记，将在本系列的下一篇文章中讨论。）尽管显然执行了条件逻辑，但是 JSTL 版本中没有 Java 语言源代码，并且标记之间的关系（尤其是关于嵌套需求）对于任何精通 HTML 语法的人都应该是熟悉的。 </p>
		<br />
		<a name="IDAISTVB">
				<b>清单 17. 合并 &lt;c:set&gt; 和 &lt;c:out&gt; 以提供缺省变量值</b>
		</a>
		<br />
		<table cellspacing="0" cellpadding="5" width="400" bgcolor="#eeeeee" border="1">
				<tbody>
						<tr>
								<td>
										<pre>
												<code class="section">
														<font face="Lucida Console">&lt;c:choose&gt;&lt;c:when test="${user.role == 'member'}"&gt;
    &lt;p&gt;Welcome, member!&lt;/p&gt;
  &lt;/c:when&gt;&lt;c:otherwise&gt;
    &lt;p&gt;Welcome, guest!&lt;/p&gt;
  &lt;/c:otherwise&gt;&lt;/c:choose&gt;</font>
												</code>
										</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>通过提供大多数 Web 应用程序常用功能的标准实现，JSTL 有助于加速开发周期。与 EL 结合起来，JSTL 可以不需要对表示层程序编写代码，这极大地简化了 JSP 应用程序的维护。</p>
		<br />
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td>
										<img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" />
										<br />
										<img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" />
								</td>
						</tr>
				</tbody>
		</table>
		<table class="no-print" cellspacing="0" cellpadding="0" align="right">
				<tbody>
						<tr align="right">
								<td>
										<img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" />
										<br />
										<table cellspacing="0" cellpadding="0" border="0">
												<tbody>
														<tr>
																<td valign="center">
																		<img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" />
																		<br />
																</td>
																<td valign="top" align="right">
																		<b>
																				<font color="#996699">
																				</font>
																		</b>
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<p>
				<a name="resources">
						<span class="atitle">
								<font face="Arial" size="4">参考资料 </font>
						</span>
				</a>
		</p>
		<ul>
				<li>您可以参阅本文在 developerWorks 全球站点上的 <a href="http://www.ibm.com/developerworks/library/j-jstl0211.html"><font color="#5c81a7">英文原文</font></a>. <br /><br /></li>
				<li>Sun 的 <a href="http://java.sun.com/products/jsp/jstl/index.html"><font color="#5c81a7">JSP 标准标记库主页</font></a>是了解关于 JSTL 的更多信息的良好起点。 <br /><br /><br /></li>
				<li>
						<a href="http://jcp.org/aboutJava/communityprocess/final/jsr052/">
								<font color="#5c81a7">JSTL 1.0 规范</font>
						</a>是关于 EL 和四个 JSTL 标记库的最终权威文本。 <br /><br /><br /></li>
				<li>
						<a href="http://jakarta.apache.org/taglibs/index.html">
								<font color="#5c81a7">Jakarta Taglibs</font>
						</a>项目是 JSTL 1.0 参考实现的起源。 <br /><br /><br /></li>
				<li>Shawn Bayern 所著的 <a href="http://www.manning.com/bayern/index.html"><font color="#5c81a7"><i>JSTL in Action</i></font></a>（Manning Publications Co.，2002 年）提供了对所有 JSTL 功能的精彩论述，作者是该参考实现的领导。 <br /><br /><br /></li>
				<li>David Geary 是 Java 技术方面很受欢迎的作者，他也写了一本关于 JSTL 的书，书名是 <a href="http://www.amazon.com/exec/obidos/tg/detail/-/0131001531/103-4207394-1320606?vi=glance"><font color="#5c81a7"><i>Core JSTL</i></font></a>。 <br /><br /><br /></li>
				<li>
						<a href="http://jsptags.com/index.jsp">
								<font color="#5c81a7">JSPTags.com</font>
						</a>是 JSP 技术参考资料的目录，它尤其专注于定制标记库。 <br /><br /><br /></li>
				<li>Sun 的 <a href="http://java.sun.com/webservices/docs/ea2/tutorial/doc/JSTL3.html"><font color="#5c81a7">Java Web Services Tutorial</font></a>中包含了对 JSTL 的讨论。 <br /><br /><br /></li>
				<li>“ <a href="http://www7b.software.ibm.com/wsdd/library/tutorials/vajwebsph353/Part-I/JSP11Part-I.html"><font color="#5c81a7">Using JSPs and custom tags within VisualAge for Java and WebSphere Studio</font></a>”（ <a href="http://www7b.software.ibm.com/wsdd/"><font color="#5c81a7">WebSphere 开发者园地</font></a>）是一篇 WBOnline 实用论文，它演示了 servlet、JSP 和定制标记库的使用。 <br /><br /><br /></li>
				<li>通过 Jeff Wilson 精彩的文章“ <a href="http://www.ibm.com/developerworks/cn/java/j-taglib/index.html"><font color="#5c81a7">使用定制标记控制 JSP 页面</font></a>”（ <i>developerWorks</i>，2002 年 1 月）了解关于定制标记库的一切。 <br /><br /><br /></li>
				<li>Noel Bergman 的文章“ <a href="http://www.ibm.com/developerworks/cn/java/j-jsptags/index.html"><font color="#5c81a7">JSP 标记库：着意设计的更好的可用性</font></a>”（ <i>developerWorks</i>，2001 年 12 月）向您展示了声明性标记是如何帮助提高 JSP 页面的可用性的。 <br /><br /><br /></li>
				<li>有关 EcmaScript 的更多详细信息，请参阅 Sing Li 的“ <a href="http://www.ibm.com/developerworks/cn/java/j-qdjava/index.html"><font color="#5c81a7">快速上手 Java 编程</font></a>”（ <i>developerWorks</i>，2001 年 7 月）。 <br /><br /><br /></li>
				<li>在 <a href="http://www.ibm.com/developerworks/cn/java/index.html"><font color="#5c81a7"><i>developerWorks</i>Java 技术专区 </font></a>可以找到多达数百篇的 Java 技术参考资料。 <br /></li>
		</ul><img src ="http://www.cnitblog.com/tilan/aggbug/21767.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/tilan/" target="_blank">Joinclass Inc</a> 2007-01-11 16:40 <a href="http://www.cnitblog.com/tilan/archive/2007/01/11/21767.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Thinking in AJAX(三) —— AJAX框架汇总</title><link>http://www.cnitblog.com/tilan/archive/2007/01/10/21751.html</link><dc:creator>Joinclass Inc</dc:creator><author>Joinclass Inc</author><pubDate>Wed, 10 Jan 2007 15:42:00 GMT</pubDate><guid>http://www.cnitblog.com/tilan/archive/2007/01/10/21751.html</guid><wfw:comment>http://www.cnitblog.com/tilan/comments/21751.html</wfw:comment><comments>http://www.cnitblog.com/tilan/archive/2007/01/10/21751.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/tilan/comments/commentRss/21751.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/tilan/services/trackbacks/21751.html</trackback:ping><description><![CDATA[<p>此文原出于<a href="http://www.ajaxpatterns.org/AJAXFrameworks">AJAX Patterns网站的一篇《Ajax Frameworks》的wiki文章</a>，很早前我就注意到，后来在国内也有人翻译了，不过最近发现此wiki还是在不断添加维护中，截止此文发布前，作者又添加了好几个新诞生的AJAX开发工具，所以我决定重新翻译一遍，并且时常注意原文发布状态，一有新的内容立马也翻译过来，做到同步:)</p>
		<p>此翻译稿很大一部分内容出自<a href="http://www.baidu.com/baidu?word=AJAX%B5%C4%D3%A6%D3%C3%B3%CC%D0%F2%BC%DC%B9%B9%BB%E3%D7%DC&amp;tn=myie2dg">国内出现的那个先前版本</a>，我只是对新加入的几项进行了翻译，并且对我熟悉的产品项着重介绍了一下，以后我会抽时间收集文中提到AJAX工具相关的文章，尽量将内容介绍和功能点评做到全面详细点。所以请关注和准备用AJAX做开发的朋友关注这篇文章，我会时常更新的。原文因为是由一个wiki系统维护，所以在所难免出现参差不齐，风格上也有不统一的情况，翻译时我也是参照原文原封不动的挪了过来，以后我会抽时间改良下。</p>
		<hr style="MARGIN: 10px" />
		<h1>翻译正文</h1>
		<p>基于浏览器的应用框架一般分为两种： 
</p>
		<ul>
				<li>Aplication frameworks:提供了浏览器功能，但其最著名的还是在于通过窗口生成组件建立桌面GUI。 
</li>
				<li>Infrastructural frameworks:提供基本的框架功能和轻便式浏览器端操作，让开发者去创建具体应用，主要功能包括： 
<ul><li>基于XMLHttpRequest组件的浏览器交互功能 
</li><li>XML解析和操作功能 
</li><li>根据XMLHttpRequest的返回信息进行相应的DOM操作 
</li><li>一些特殊情况下，和其他的浏览器端技术如Flash（或Java Applets）等集合到一起应用 </li></ul></li>
		</ul>基于服务器端的应用框架通常以下面两种方式工作(尽管它们根据不同的语言进行了分类) 
<ul><li>HTML/JS Generation(HTML/JS生成)：通过服务器端生成HTML和JS代码在传递给浏览器端进行直接运行 
</li><li>远程交互：JavaScript调用服务器端函数(例如调用Java函数)并返回给JavaScript的回调句柄，或者请求服务器端数据信息，例如Session信息，数据库查询等。 </li></ul><p></p><hr style="MARGIN: 10px" /><h1>目录</h1><dt></dt><div style="MARGIN: 5px"><a href="http://www.duduwolf.com/post/AJAX_Frameworks.asp#1">1 Pure Javascript: Application Frameworks</a></div><dd><a href="http://www.duduwolf.com/post/AJAX_Frameworks.asp#1.1">1.1 Bindows</a></dd><dd><a href="http://www.duduwolf.com/post/AJAX_Frameworks.asp#1.2">1.2 BackBase</a></dd><dd><a href="http://www.duduwolf.com/post/AJAX_Frameworks.asp#1.3">1.3 DOJO</a></dd><dd><a href="http://www.duduwolf.com/post/AJAX_Frameworks.asp#1.4">1.4 Open Rico</a></dd><dd><a href="http://www.duduwolf.com/post/AJAX_Frameworks.asp#1.5">1.5 qooxdoo</a></dd><dd><a href="http://www.duduwolf.com/post/AJAX_Frameworks.asp#1.6">1.6 Tibet</a></dd><dd><a href="http://www.duduwolf.com/post/AJAX_Frameworks.asp#1.7">1.7 AJFORM</a></dd><dt></dt><div style="MARGIN: 5px"><a href="http://www.duduwolf.com/post/AJAX_Frameworks.asp#2">2 Pure Javascript: Infrastructural Frameworks</a></div><dd><a href="http://www.duduwolf.com/post/AJAX_Frameworks.asp#2.1">2.1 AjaxCaller</a></dd><dd><a href="http://www.duduwolf.com/post/AJAX_Frameworks.asp#2.2">2.2 Flash JavaScript Integration Kit </a></dd><dd><a href="http://www.duduwolf.com/post/AJAX_Frameworks.asp#2.3">2.3 Google AJAXSLT</a></dd><dd><a href="http://www.duduwolf.com/post/AJAX_Frameworks.asp#2.4">2.4 HTMLHttpRequest</a></dd><dd><a href="http://www.duduwolf.com/post/AJAX_Frameworks.asp#2.5">2.5 Interactive Website Framework </a></dd><dd><a href="http://www.duduwolf.com/post/AJAX_Frameworks.asp#2.6">2.6 LibXMLHttpRequest</a></dd><dd><a href="http://www.duduwolf.com/post/AJAX_Frameworks.asp#2.7">2.7 MAJAX</a></dd><dd><a href="http://www.duduwolf.com/post/AJAX_Frameworks.asp#2.8">2.8 RSLite</a></dd><dd><a href="http://www.duduwolf.com/post/AJAX_Frameworks.asp#2.9">2.9 Sack</a></dd><dd><a href="http://www.duduwolf.com/post/AJAX_Frameworks.asp#2.10">2.10 Sarissa</a></dd><dd><a href="http://www.duduwolf.com/post/AJAX_Frameworks.asp#2.11">2.11 XHConn</a></dd><dt></dt><div style="MARGIN: 5px"><a href="http://www.duduwolf.com/post/AJAX_Frameworks.asp#3">3 Server-Side: Multi-Language</a></div><dd><a href="http://www.duduwolf.com/post/AJAX_Frameworks.asp#3.1">3.1 Cross-Platform Asynchronous INterface Toolkit</a></dd><dd><a href="http://www.duduwolf.com/post/AJAX_Frameworks.asp#3.2">3.2 SAJAX</a></dd><dd><a href="http://www.duduwolf.com/post/AJAX_Frameworks.asp#3.3">3.3 Javascipt Object Notation (JSON) and JSON-RPC</a></dd><dd><a href="http://www.duduwolf.com/post/AJAX_Frameworks.asp#3.4">3.4 Javascript Remote Scripting (JSRS)</a></dd><dd><a href="http://www.duduwolf.com/post/AJAX_Frameworks.asp#3.5">3.5 Bitkraft for ASP.NET</a></dd><dt></dt><div style="MARGIN: 5px"><a href="http://www.duduwolf.com/post/AJAX_Frameworks.asp#4">4 Server-Side: Java</a></div><dd><a href="http://www.duduwolf.com/post/AJAX_Frameworks.asp#4.1">4.1 WebORB for Java</a></dd><dd><a href="http://www.duduwolf.com/post/AJAX_Frameworks.asp#4.2">4.2 Echo 2</a></dd><dd><a href="http://www.duduwolf.com/post/AJAX_Frameworks.asp#4.3">4.3 Direct Web Remoting (DWR)</a></dd><dd><a href="http://www.duduwolf.com/post/AJAX_Frameworks.asp#4.4">4.4 SWATO</a></dd><dd><a href="http://www.duduwolf.com/post/AJAX_Frameworks.asp#4.5">4.5 AJAX JSP Tag Library</a></dd><dd><a href="http://www.duduwolf.com/post/AJAX_Frameworks.asp#4.6">4.6 AJAX Java Server Faces Framework</a></dd><dt></dt><div style="MARGIN: 5px"><a href="http://www.duduwolf.com/post/AJAX_Frameworks.asp#5">5 Server-Side: Lisp</a></div><dd><a href="http://www.duduwolf.com/post/AJAX_Frameworks.asp#5.1">5.1 CL-Ajax</a></dd><dt></dt><div style="MARGIN: 5px"><a href="http://www.duduwolf.com/post/AJAX_Frameworks.asp#6">6 Server-Side: .NET</a></div><dd><a href="http://www.duduwolf.com/post/AJAX_Frameworks.asp#6.1">6.1 WebORB for .NET</a></dd><dd><a href="http://www.duduwolf.com/post/AJAX_Frameworks.asp#6.2">6.2 Ajax.NET</a></dd><dd><a href="http://www.duduwolf.com/post/AJAX_Frameworks.asp#6.3">6.3 ComfortASP.NET</a></dd><dd><a href="http://www.duduwolf.com/post/AJAX_Frameworks.asp#6.4">6.4 AjaxAspects</a></dd><dt></dt><div style="MARGIN: 5px"><a href="http://www.duduwolf.com/post/AJAX_Frameworks.asp#7">7 Server-Side: PHP</a></div><dd><a href="http://www.duduwolf.com/post/AJAX_Frameworks.asp#7.1">7.1 AjaxAC</a></dd><dd><a href="http://www.duduwolf.com/post/AJAX_Frameworks.asp#7.2">7.2 JPSpan</a></dd><dd><a href="http://www.duduwolf.com/post/AJAX_Frameworks.asp#7.3">7.3 XAJAX</a></dd><dt></dt><div style="MARGIN: 5px"><a href="http://www.duduwolf.com/post/AJAX_Frameworks.asp#8">8 Server-Side: Ruby</a></div><dd><a href="http://www.duduwolf.com/post/AJAX_Frameworks.asp#8.1">8.1 Ruby On Rails</a><hr style="MARGIN: 10px" /><h1>1. <a name="1"></a>Pure Javascript: Application Frameworks</h1><h3>1.1 <a name="1.1"></a>Bindows (成立于2003年)</h3><p><a href="http://www.backbase.com/">Backbase</a>是一个通过DHTML、JavaScript、CSS和HTML等技术强劲联合起来的一套完整的Windows桌面式的WEB应用程序解决方案。Bindows无需下载安装客户端支撑组件（如Java、ActiveX或Flash），仅需一个浏览器。纯OO的理念体现在Bindows任何地方，Bindows或许是笔者见过的最完整最强大的AJAX应用程序平台。 <br />Bindows是商业程序的，使用了来自于MB的技术(总部位于GA USA，主要开发中心在瑞典，成立于2002年)。</p>Bindows框架提供的功能和特性有： 
<ul><li>基于面相对象技术的类和API 
</li><li>一套完整的Windows桌面系统，支持各种特性窗口模式，包括菜单、表单、表格、滑动条、测量仪器窗口和其他一些Windows窗口特性支持。 
</li><li>是开发zero-footprint(零空间占用)SOA客户端应用程序首选工具包 
</li><li>本机的XML，SOAP和XML-RPC支持 
</li><li>单用户到企业级开发的支持 
</li><li>内建的完美的AJAX支持 </li></ul>Bindows开发环境： 
<ul><li>支持企业级规模的项目开发 
</li><li>跨浏览器、跨OS平台的支持 
</li><li>不受服务器结构限制 
</li><li>良好的与新的、现有的资源互操作性 
</li><li>统一的开发接口 </li></ul><p></p><h3>1.2 <a name="1.2"></a>BackBase (成立于2003年)</h3><a href="http://www.backbase.com/">BackBase</a>是一个完整的浏览器端框架，提供了丰富的浏览器操作功能，以及对.NET和JAVA平台的集成。 <br />商业化产品，来自于Backbase B.V(总部在Amsterdam，成立于2003年)。 
<p></p><h3>1.3 <a name="1.3"></a>DOJO (开发中,成立于2004年9月) </h3><p>DOJO提供完整的轻量级窗口组件和浏览器-服务器消息映射支持</p><ul><li>提供创建自定义Javascript窗口组件的框架支持 
</li><li>预制的丰富的窗口类型库 
</li><li>B/S消息映射支持——XMLHttpRequest和其他机制 
</li><li>支持浏览器中的URL操纵功能 
</li><li>开源许可(<a href="http://opensource.org/licenses/afl-2.1.php">Academic Free License 2.1</a>)，由<a href="http://www.jot.com/">JotSpot</a>的<a href="http://alex.dojotoolkit.org/">Alex Russell</a>所领导。 </li></ul><h3>1.4 <a name="1.4"></a>Open Rico (开发中;成立于2005年5月;基于早期的一个proprietary 框架) </h3><p><a href="http://openrico.org/demos.page">Open Rico</a>是一个支持Ajax架构和用户交互的多用途框架。 
</p><ul><li>一个XMLHttpRequest response能被一个或多个的DOM对象，或者Javascript对象调用。 
</li><li>支持拖拽操作 
</li><li>支持基于AJAX的动画模式，如缩放和变换等 
</li><li>基于Behaviors的操作库 
</li><li><a href="http://www.mirimar.net/mailbrowser/">使用指南</a>，由RussMirimar的Yonah提供 
</li><li>开源。源于Sabre航空公司解决方案，由<a href="http://looksgoodworkswell.blogspot.com/">Bill Scott</a>，Darren James及另外一些人维护。 </li></ul><p></p><h3>1.5 <a name="1.5"></a>qooxdoo (开发中; 成立于2005年5月) </h3><a href="http://qooxdoo.sourceforge.net/">qooxdoo</a>，是另一个发展迅猛的应用框架，提供广泛的UI支持，正在开发基础架构等特性。 
<ul><li>基础结构特性： 
<ul><li>能轻易的捕获和操纵DOM事件 
</li><li>支持调试 
</li><li>支持一个时间操作的Timer类 
</li><li>Getter/Setter支持 </li></ul></li><li>UI: 
<ul><li>窗口组件库和框架 
</li><li>界面布局管理 
</li><li>图像缓存和透明PNG图片处理 </li></ul></li><li>开源(LGPL). </li></ul><h3><a name="1.6"></a>1.6 Tibet (开发中; 创建于2005年6月)</h3><p><a href="http://www.technicalpursuit.com/">Tibet</a>提供了大量的易移植和完整的JavaScript API，通过这些可以快速生成大量的客户端代码，Tibet自称是企业级AJAX。</p><ul><li>远程脚本调用封装在XMLHttpRequest中 
</li><li>URI支持 
</li><li>支持所有的HTTP事件，不再仅仅是GET和POST 
</li><li>低级的协议-File://和WebDav也可以当作HTTP正常使用 
</li><li>Web Services调用支持，包括SOAP、XML-RPC等等 
</li><li>大型的Javascript对象库 
</li><li>多种多样的XML操作支持 
</li><li>IDE和开发工具 
</li><li>开源协议(OSI) </li></ul><h3><a name="1.7"></a>1.7 AJFORM (创建于2005年6月)</h3><p><a href="http://redredmusic.com/brendon/ajform/">AJFORM</a>是一个极易上手的AJAX框架，被用来编写入门级的AJAX代码，提供有以下功能：</p><ul><li>三步安装 
</li><li>自动支持任意HTML表单元素 
</li><li>几乎无需编码即可实现AJAX </li></ul><h1><a name="2"></a>2 Pure Javascript: Infrastructural Frameworks</h1><h3><a name="2.1"></a>2.1 AjaxCaller(创建于2005年5月，目前是Alpha版)</h3><a href="http://ajaxify.com/run/testAjaxCaller/">AjaxCaller</a>是一个具有多线程安全访问的XMLHttpRequest组件，主要针对Ajax开发新手，目前仍处于alpha开发阶段，仅在<a href="http://www.ajaxpatterns.org/">AjaxPatterns</a>的在线搜索范例中使用了这个程序。 
<ul><li>用明文或者XML结构的数据实现和服务器的交互(GET/POST/PUT/DELETE) 
</li><li>支持XMLHttRequest对象的构析(销毁对象，C++支持内存对象的构析操作) 
</li><li>支持Response的高速缓存(尚在计划中) 
</li><li>简单的库文件代码易于新手学习使用，并且支持脚本调试 
</li><li>开源协议 </li></ul><h3><a name="2.2"></a>2.2 Flash JavaScript Integration Kit</h3><p><a href="http://www.osflash.org/doku.php?id=flashjs">The Flash JavaScript Integration Kit</a>可以使Flash和Javascript脚本实现相互集成。</p><ul><li>可以实现在JavaScript中调用Flash ActionScript脚本，反之亦然。 
</li><li>几乎支持双方主要数据类型的在不同环境中的传递调用。 
</li><li>开源协议，有几个Flash开源爱好者维护。 </li></ul><h3><a name="2.3"></a>2.3 Google AJAXSLT (2005年6月发行) </h3><p><a href="http://goog-ajaxslt.sourceforge.net/">Google AJAXSLT</a>，是一个Javascript框架，用来执行XSLT转换以及XPath查询。</p><ul><li>目前在Google Map上就使用了这个。 
</li><li>开源协议(BSD) </li></ul><h3><a name="2.4"></a>2.4 HTMLHttpRequest(Beta版；创建于2005年)</h3><p><a href="http://www.twinhelix.com/javascript/htmlhttprequest/">HtmlHttpRequest</a>最大的特点就是运用XMLHttpRequest对象和标准HTML标签IFrame来实现最大限度的跨浏览跨平台的AJAX支持，其原理是在支持XMLHttpRequest的浏览器上调用XMLHttp，如果不支持，就用IFrame来模拟实现异步交互。</p><ul><li>目前支持的浏览器：IE6/Win, IE5.5/Win, IE5/Win, IE4/Win, Mozilla/Win, Opera7/Win, Safari/Mac, IE5/Mac 
</li><li>尚未测试的浏览器：IE4/Mac, Mozilla/Mac, Opera/Other, Konqueror/Linux。 
</li><li>开源协议(LGPL) </li></ul><h3><a name="2.5"></a>2.5 Interactive Website Framework (创建于2005年)</h3><p><a href="http://sourceforge.net/projects/iwf/">Interactive Website Framework</a>定位在浏览器中支持各种各样的AJAX基础应用的开源项目。自称是通过JavaScript、CSS、XML和HTML实现高性能的交互式WEB框架，包括一个可定制易读的XML解析器。实际上，IWF是一个AJAX的基础框架，并且还包括一些通用脚本代码。</p><ul><li>实现了线程安全的XMLHttpRequest 
</li><li>对XML Document进行封装，以便创建更具有可读性的代码：<br /><blockquote>var node = doc.groceries.frozen[0].pizza[0].size;</blockquote>封装后的数据读取 
<blockquote>var node = doc.documentElement.firstChild.firstChild.getAttribute("size");</blockquote>原始的DOM操作读取 
</li><li>开源协议 </li></ul><h3><a name="2.6"></a>2.6 LibXMLHttpRequest (2003年6月发布) </h3><p><a href="http://www.whitefrost.com/servlet/connector?file=reference/2003/06/17/libXmlRequest.html">libXmlRequest</a>是一个小型XMLHttpRequest封装包</p><ul><li>用getXML()和postXML()两个事件简化XMLHttpReuqest调用 
</li><li>支持XMLHttpRequest对象池 
</li><li>Response缓存处理 
</li><li>源码可以使用，但是有版权保护。 </li></ul><h3><a name="2.7"></a>2.7 MAJAX </h3><p><a href="http://unips.sourceforge.net/devblog/?page_id=2">MAJAX</a>是另一个非常小巧的HttpRequest封装包，为收发字符型信息提供简单接口，并为每步动作设置回调界面。</p><h3><a name="2.8"></a>2.8 RSLite (x) </h3><p><a href="http://www.ashleyit.com/rs/main.htm">RSLite</a>是一个XMLHttpRequest封装组件，作为Brent Ashley的JSRS(JavaScript Remote Scripting)其中的一部分功能单独发布。详情可以看JSRS的介绍</p><h3><a name="2.9"></a>2.9 Sack(开发中，成立于2005年5月) </h3><p><a href="http://twilightuniverse.com/2005/05/sack-of-ajax/">Sack</a>也是一个很有名字的微型XMLHttpRequest封装包。调用者可以自定义回调函数或者是DOM对象。借助于回调DOM对象，可以把Response回来的数据直接以文本的方式嵌入DOM中。</p><h3><a name="2.10"></a>2.10 Sarissa (发布于2003年2月)</h3><p><a href="http://sarissa.sf.net/">Sarissa</a>是一个JavaScript API，封装了在浏览器端独立调用XML的功能。</p><ul><li>可移植的XMLHttpRequest对象创造 
</li><li>可移植的XPath查询 
</li><li>可移植的DOM操控 
</li><li>可移植的XSLT 
</li><li>可移植的XML序列化 
</li><li>开源协议(GPL2.0和LGPL2.1) </li></ul><h3><a name="2.11"></a>2.11 XHConn (2005年4月发布)</h3><p><a href="http://xkr.us/code/javascript/XHConn/">XHConn</a>也是一个小型的XMLHttpRequest封装库。笔者也使用改良过的XHConn，其特点就是调用简单，代码也清晰易读。</p><ul><li>例子： 
<blockquote>new XHConn().connect("mypage.php"，"POST"，"foo=bar&amp;baz=qux"，fnWhenDone);</blockquote></li><li>开源协议许可 </li></ul><h1><a name="3"></a>3 Server-Side: Multi-Language</h1><h3><a name="3.1"></a>3.1 Cross-Platform Asynchronous INterface Toolkit (2005年5月) </h3><p><a href="http://cpaint.sourceforge.net/">CPAINT</a>是一个真正的同时支持PHP和ASP/VBScript脚本的AJAX和JSRS工具包。CPAINT在后台提供你需求的AJAX和JSRS代码，并自动返回到浏览器端相应的Javascript脚本代码，这种方式易于实时反馈需求的WEB应用程序。</p><ul><li>支持PHP和ASP 
</li><li>所有功能函数都在统一的JavaScript文件中 
</li><li>支持远程脚本和XML 
</li><li>支持本地和远程函数调用 
</li><li>可以创建单个或多个XMLHttp对象 
</li><li>返回给后台的数据即可以是文本也可以是XML/DOM文档对象 
</li><li>支持POST和GET 
</li><li>用服务端代理的方式实现远程函数和数据的访问操作 
</li><li>大部分浏览器中测试正常使用 
</li><li>在GNU、GPL、LGPL开源协议保护下发行 </li></ul><h3><a name="3.2"></a>3.2 SAJAX (2005年3月) </h3><p><a href="http://www.modernmethod.com/sajax/">SAJAX</a>的实现方式很独特，例如：调用一个javascript方法x_calculateBudget()，将先把响应传到服务器并调用一个Java calculateBudget()方法，然后以javascript方式把值返回到x_calculateBudget_cb()中。SAJAX的名气不错，估计很多人都听过甚至用过，不过缺点就是它的这套映射理论感觉较繁锁，远不如一些轻量级的封装库好用，不过SAJAX最大的特点就是支持的平台丰富，几乎囊括了WEB下常用的编程语言和平台</p><ul><li>很方便从JavaScript函数映射到服务端代理操作 
</li><li>支持多种平台(ASP/ColdFusion/Io/Lua/Perl/PHP/Python/Ruby) 
</li><li>开源协议 </li></ul><h3><a name="3.3"></a>3.3 Javascipt Object Notation (JSON) and JSON-RPC </h3><p><a href="http://www.crockford.com/JSON/index.html">JSON</a>是一个"face-free" XML，而<a href="http://www.json-rpc.org/">JSON-RPC</a>是一种远程交互协议，类似于XML-RPC，对JavaScript支持较强</p><ul><li><a href="http://www.json-rpc.org/impl.xhtml">支持多服务端平台</a>: Java, Python, Ruby, Perl. 
</li><li>针对不同的平台有不同的包和许可协议, 如<a href="http://oss.metaparadigm.com/jsonrpc/">JSON-RPC-Java</a>. </li></ul><h3><a name="3.4"></a>3.4 JavaScript Remote Scripting(JSRS)(2000年) </h3><p><a href="http://www.ashleyit.com/rs/jsrs/test.htm">JSRS</a>，较经典的远程脚本访问组件，支持将客户端数据通过服务器做代理进行远程的数据/操作交互。</p><ul><li>支持的浏览器：IE4+，NS4.x，NS6.x，Mozilla，Opera7和Galeon。 
</li><li>服务器端脚本语言支持：ASP，ColdFusion，PerlCGI，PHP,Python和JSP(servlet)。 
</li><li>开源协议。由<a href="http://www.ashleyit.com/">Brent Ashley</a>提供支持。 </li></ul><h3><a name="3.5"></a>3.5 Bitkraft for ASP.NET </h3><p><a href="http://www.tiggrbitz.com/">Bitkraft</a>是个基于(.NET)Web框架的CLR(公共语言运行库)，允许用独特的方式创建和操作分布式Web内容。用C#编写，运行在微软的.NET 1.1和Mono框架下，无缝式的客户端-服务器响应方式是它的最大特点。Bitkraft没有使用XML组织数据，而是用JSON代替。</p><ul><li>支持的浏览器： IE5+, Firefox1+, NS6 
</li><li>服务器端要求：ASP.NET, Mono XSP, Cassini, Apache (modMono) .NET Framework 1.1+ 
</li><li>事件驱动 
</li><li>支持同步和异步的远程代理 
</li><li>客户端支持所有的.NET类型或自定义类对象映射到JSON中 
</li><li>用JSON取代XML 
</li><li>免费，开源许可协议 </li></ul><h1><a name="4"></a>4 Server-Side: Java </h1><h3><a name="4.1"></a>4.1 WebORB for Java (2005年8月) </h3><p><a href="http://www.themidnightcoders.com/weborb/aboutWeborb.htm">WebORB for Java</a>是一个开发AJAX和基于Flash的富客户端应用程序的开发平台。<a href="http://www.themidnightcoders.com/examples">在线例子</a></p><ul><li>WebORB包括一个富客户端开发类库。提供简单的在线式API用来绑定或者调用任何Java对象、XML Web Services和EJB 
</li><li>支持异步或同步的事件驱动 
</li><li>不需要在服务端修改任何代码，不需要自定义方法或属性、变量等。不要求设计时指定代理等。 
</li><li>同步调用不需要回调，异步调用需要一个回调方法。 
</li><li>客户端可以向服务端请求指定的活动方式，不需要任何编程就可以把处理结果轻易的转变为状态。 
</li><li>提供一个特定API来处理数据库查询结果-服务器代码能返回DataSet或者DataTable，而客户端以一个类似于RecordSet的JavaScript对象来显示这个结果。该对象提供检索列名和行数据的方法。 
</li><li>支持数据分页技术。客户应用程序能检索页面中的数据。 
</li><li>支持以参数的方式返回所有服务期端数据类型，如primitives, strings, complex types, arrays, native .net collections, remote references 
</li><li>目前有两个版本：标准版(免费)，专业版(商业许可) </li></ul><h3><a name="4.2"></a>4.2 Echo 2 (2005年3月) </h3><p><a href="http://www.nextapp.com/products/echo2/">Echo 2</a>允许你用纯Java语言编写AJAX程序。 <a href="http://demo.nextapp.com/InteractiveTest/ia">Demo</a>. </p><ul><li>自动生成HTML和Javascript代码 
</li><li>用XML在客户端-服务端传递消息 
</li><li>如果愿意支持自定义Javascript组件 
</li><li>开源协议(Mozilla Public License or GNU LGPL) </li></ul><h3><a name="4.3"></a>4.3 Direct Web Remoting (DWR) (2005) </h3><p><a href="http://www.getahead.ltd.uk/dwr/">Direct Web Remoting</a>可以在Javascript代码中直接调用Java方法的应用框架</p><ul><li>类似于SAJAX，可以把Javascript中的请求调用转递到Java方法中并将执行结果返回给Javascript 
</li><li>可以和任何Web框架一起使用，如Struts、Tapestry等等 
</li><li>开源(Apache)，目前该产品被加入到<a href="http://www.duduwolf.com/post/%20//www.opensymphony.com/webwork/">WebWork</a>中 </li></ul><h3><a name="4.4"></a>4.4 SWATO (2005) </h3><p><a href="http://swato.dev.java.net/">SWATO</a>是一套可重用的和良好集成的Java/JavaScript库，它实现了一种更容易的方式来改变你的web应用程序的交互，通过AJAX方式实现。</p><ul><li>服务端Java库可以非常容易的部署到所有Servlet2.3+兼容的容器中 
</li><li>客户端Javascript库可以在所有支持XMLHttpRequest的浏览器中使用 
</li><li>使用JSON技术在服务端组织POJO数据，这样你可以在任何Javascript环境中(HTML、XUL、SVG)访问这些远程数据，这种方式很容易通过硬编码或者某种成熟的Javascript库集成到当前应用中 
</li><li>提供一个简单接口使你能在Javascript中调用远程的POJO数据 
</li><li>使用&lt;servlet&gt;和&lt;filter&gt;灵活的在web.xml中进行配置，并且可以集成(不是必须)到你的Spring框架中 
</li><li>提供了几个可帮助你快速开发web应用程序的组件(如自动完成的文本框，在线表单，在线列表等等) </li></ul><h3><a name="4.5"></a>4.5 AJAX JSP Tag Library </h3><p><a href="http://ajaxtags.sourceforge.net/">The AJAX JSP Tag Library</a>是一组JSP标签库，用来AJAX程序开发。可以在J2EE下无需Javascript就能轻松开发AJAX模式的Web Form。标签库为比较通用的AJAX功能提供了5个标签：</p><ul><li>autocomplete: 用户在文本框中输入字符，自动从指定的数据中匹配用户输入的字符，类似于Google Suggest 
</li><li>callout:可以为A标签加入气泡式的消息提示框，不过是实时的服务端取出数据 
</li><li>Select/dropdown:类似于联动菜单，比如地州市的联动下拉框 
</li><li>toggle:开关闸按钮，比如在一个hidden表单域中存储true和falsh，同时显示相应的img图像 
</li><li>update field:更新数据，也就是无刷新提交了。 </li></ul><h3><a name="4.6"></a>4.6 AJAX Java Server Faces Framework </h3><p><a href="http://smirnov.org.ru/en/ajax-jsf.html">The AJAX-JSF</a>用来把任意的JSF应用程序转变为AJAX应用程序</p><ul><li><a href="http://smirnov.org.ru/myfaces-ajax/ajax.jsf">例子</a>：AJAX组件的 MyFaces JSF Tree(树型目录), table scroller(可滚动的表格), tabbed pane(分页栏) 
</li><li>开源协议(<a href="http://www.apache.org/licenses/LICENSE-2.0.html">Apache Software License</a>) </li></ul><h1><a name="5"></a>Server-Side: Lisp </h1><h3><a name="5.1"></a>5.1 CL-Ajax </h3><p><a href="http://cliki.net/cl-ajax">CL-Ajax</a>实现Javascript直接调用服务端Lisp</p><ul><li>生成可带参数的函数 
</li><li>可以回调Javascript函数或者DOM对象 
</li><li>可以集成到SAJAX中 
</li><li>开源许可 </li></ul><h1><a name="6"></a>6 Server-Side: .NET </h1><h3><a name="6.1"></a>6.1 WebORB for .NET (2005年8月) </h3><p><a href="http://www.themidnightcoders.com/weborb/aboutWeborb.htm">WebORB for .NET</a>是一个用.NET和XML Web Services方式开发AJAX和基于Flash的富客户端应用程序(<a href="http://www.themidnightcoders.com/examples">在线例子</a>) </p><ul><li>WebORB包括一个富客户端开发类库。提供简单的在线式API用来绑定或者调用任何.NET对象、XML Web Services 
</li><li>支持异步或同步的事件驱动 
</li><li>不需要在服务端修改任何代码，不需要自定义方法或属性、变量等。不要求设计时指定代理等。 
</li><li>同步调用不需要回调，异步调用需要一个回调方法。 
</li><li>客户端可以向服务端请求指定的活动方式，不需要任何编程就可以把处理结果轻易的转变为状态。 
</li><li>提供一个特定API来处理数据库查询结果-服务器代码能返回DataSet或者DataTable，而客户端以一个类似于RecordSet的JavaScript对象来显示这个结果。该对象提供检索列名和行数据的方法。 
</li><li>支持数据分页技术。客户应用程序能检索页面中的数据。 
</li><li>支持以参数的方式返回所有服务期端数据类型，如primitives, strings, complex types, arrays, native .net collections, remote references 
</li><li>目前有两个版本：标准版(免费)，专业版(商业许可) </li></ul><h3><a name="6.2"></a>6.2 Ajax.NET (2005年3月) </h3><p><a href="http://ajax.schwarz-interactive.de/">Ajax.NET</a>是首家支持各种方式通过Javascript访问服务端.net的免费库</p><ul><li>类似于SAJAX，能把Javascript请求发送到.NET方法，服务端回传给Javascript，甚至包括串行化自定义类。 
</li><li>可以在Javascript中访问Session和Application数据 
</li><li>缓存查询结果 
</li><li>免费使用源代码 
</li><li>无需更改源代码，允许给Ajax.NET添加和修改方法和属性 
</li><li>所有类支持Javascript客户端返回数据，可以在JavaScript中使用DataSet：res.Tables[0].Rows 
</li><li>使用HtmlControls组件访问和返回数据 
</li><li>页面无需重载，用事件代理(数据访问层) 
</li><li>因为只提供一个调用接口方法，所以服务端CPU占用非常少 </li></ul><h3><a name="6.3"></a>6.3 ComfortASP.NET (2005年8月) </h3><p><a href="http://www.daniel-zeiss.de/ComfortASP/">ComfortASP.NET</a>可以让开发者在纯.NET下开发类似AJAX(DHTML,JavaScript,XMLHttp)特性的应用程序。</p><ul><li>快速应答 
</li><li>减少HTML传输 
</li><li>减少页面重载 
</li><li>无闪烁的浏览器内容更改 
</li><li>AJAX用户体验， </li></ul><h3><a name="6.4"></a>6.4 AjaxAspects (2005年8月) </h3><p><a href="http://ajaxaspects.blogspot.com/">AjaxAspects</a>是个可以用Javascript调用服务端WebService事件的引擎</p><ul><li>用标准的SOAP和WSDL进行服务端-客户端通信 
</li><li>用简单的类型和XML对象支持带参数的返回值 
</li><li>缓存支持 
</li><li>动作队列 
</li><li>免费使用，开源协议 </li></ul><h1><a name="7"></a>7 Server-Side: PHP </h1><h3><a name="7.1"></a>7.1 AjaxAC (2005年4月) </h3><p><a href="http://ajax.zervaas.com.au/">AjaxAC</a>用一个单独类封装了完整的应用程序功能</p><ul><li>所有的功能集成在自包含的类中(另外附带一些Javascript库) 
</li><li>调用PHP文件或者HTML页面非常简易，只需创建App类后把类引用传递给需要调用的Javascript对象或者HTML元素即可。 
</li><li>捕获Javascript事件 
</li><li>可以自定义配置数据，并且支持运行时参数更改 
</li><li>无需再Javascript代码中夹杂凌乱的Html代码，所有事件都是被动态附加上的 
</li><li>由于以上两个优点，所以支持良好的模版引擎 
</li><li>容易Hook到PHP类和MySql数据已返回给自己的request 
</li><li>能够容易的用Javascript建立窗口模式应用程序。 </li></ul><h3><a name="7.2"></a>7.2 JPSpan </h3><p><a href="http://jpspan.sourceforge.net/wiki/doku.php">JPSPAN</a>通过Javascript直接调用PHP中的函数。</p><ul><li>进行了严谨的单元测试 
</li><li>开源许可(PHP) </li></ul><h3><a name="7.3"></a>7.3 XAJAX </h3><p><a href="http://xajax.sf.net/">XAjax</a>通过Javascript直接调用PHP中的函数</p><ul><li>支持用Javascript调用PHP脚本 
</li><li>开源许可协议 </li></ul><h1><a name="8"></a>8 Server-Side: Ruby </h1><h3><a name="8.1"></a>8.1 Ruby On Rails </h3><p><a href="http://www.rubyonrails.org/">Ruby On Rails</a>是一个支持AJAX的完整Web框架，使用Ruby语言编写，严格按照MVC结构开发。</p><ul><li>当Ajax出现的时候Rails还处于其发展的早期，因此Ajax可能逐渐成为Rails框架的核心。 
</li><li>生成浏览器中大多数/全部的Window应用组件和动画的Javascript脚本。 
</li><li>支持服务器端调用。 
</li><li>队列支持 
</li><li>开源许可 </li></ul><div style="PADDING-RIGHT: 5px; PADDING-LEFT: 5px; PADDING-BOTTOM: 5px; BORDER-LEFT: #666633 5px solid; PADDING-TOP: 5px; BACKGROUND-COLOR: #d9d7ca">相关文章 
<ul><li><a href="http://www.duduwolf.com/post/ajax_x.asp">Thinking in AJAX(一) —— AJAX - X</a></li><li><a href="http://www.duduwolf.com/post/webdev_by_ajax.asp">Thinking in AJAX(二) —— 基于AJAX的WEB设计</a></li><li><a href="http://www.duduwolf.com/post/AJAX_Frameworks.asp">Thinking in AJAX(三) —— AJAX框架汇总</a></li></ul></div></dd><img src ="http://www.cnitblog.com/tilan/aggbug/21751.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/tilan/" target="_blank">Joinclass Inc</a> 2007-01-10 23:42 <a href="http://www.cnitblog.com/tilan/archive/2007/01/10/21751.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>