<?xml version="1.0" encoding="utf-8" ?>
<!-- generator="FEEDCREATOR_VERSION" -->
<rss version="2.0" xmlns:sns="http://blog.sina.com.cn/sns">
    <channel>
        <title>人月神话的BLOG</title>
        <description></description>
        <link>http://blog.sina.com.cn/cmmi</link>
        <lastBuildDate>Thu, 24 May 2012 22:05:36 +0800</lastBuildDate>
        <generator>FEEDCREATOR_VERSION</generator>
        <language>zh-cn</language>
        <copyright>Copyright 1996 - 2009 SINA Inc. All Rights Reserved.</copyright>
        <pubDate>Wed, 30 May 2012 10:13:59 +0800</pubDate>
        <item>
            <title>领域模型-服务</title>
            <link>http://blog.sina.com.cn/s/blog_493a8455010158zc.html</link>
            <description><![CDATA[服务Service是领域模型中的一种重要模式。在某些情况下最清楚，最实用的设计会包含一些特殊的操作，这些操作从概念上讲不属于任何对象。如果勉强的把这些操作归属到Entity或Value
Object中，那么不是扭曲了基于模型的对象定义，就是人为的增加了一些无意义的对象。<br />
<br />
服务是在整个模型中作为独立接口的操作，定义Service的时候需要使用模型语言，同时Service本身无状态。如果说Entity强调的是行为，那么Service则强调的是操作，而且这个操作强调的是和一个或多个对象的关系，因此Service往往会以动宾方式进行命名。<br />

<br />
资金转账功能即属于一种领域层的Service，其原因是这个功能不是账户对象某一个对象实例的行为，而是多个对象实例的行为。获取用户信用等级也可能是领域层的Service，因为不仅仅是涉及到一个对象，而且是涉及到多个对象协同才能给完成，而不是属于单一对象的职责。<br />

<br />
结合系统内的SOA化，基于上面的原则对于服务的理解做一些扩展。对于领域层提供出来的服务本身应该整个领域层核心能力的接口暴露，只是暴露方式是通过服务的方式暴露出来。这些服务我们建议是业务服务而不是简单的数据传递，服务本身有明确的业务规则和业务含义，这样更加能够体现领域的核心作用，封装各种业务逻辑而不是简单的DTO或数据CRUD操作而已。<br />

<br />
基于上面思考，我们期望不仅仅是将不属于单个对象职责的内容放到Service中，也希望将单个对象需要暴露的核心业务能力或接口放到Service中。对于应用层和领域层的关系而言，应用层调用服务接口，而逻辑层则是具体的服务实现。逻辑层和领域层只能通过Service进行交互。对于Factory封装复杂对象的创建和管理，Repository负责数据的持久化，Factory本身并不体现业务能力，所有的业务能力全部体现在Service中来实现。<br />

<br />
再转移到应用层，结合SOA参考服务架构，对于应用层可能还有Service，这里的Service应该理解为一种组合服务，跨多个Service的一种能力组合。这种组合服务本身还可以聚合为Service，实现一种复用。或者就是应用层直接通过代码来实现多个服务的装配，服务流转。注意在这种模式先应用层重点是服务的流转，服务的协同，服务的组合，而不是具体业务规则的实现。业务规则和能力完全在领域层内聚。<br /><br /><img width="34" height="17" src="http://simg.sinajs.cn/blog7style/images/special/1265.gif">&nbsp;&nbsp;<a href="http://t.cn/zO1XLB6" target="_blank">秀萌宝照片，酷赢“拉比盒子”</a>&nbsp;&nbsp;<a href="http://union.9173.com/pub?p=1&u=1008" target="_blank">“警告：您的主城已被占领！！”</a>&nbsp;&nbsp;<a href="http://qing.weibo.com/fancy.html" target="_blank">发现兴趣所在，玩转新浪Qing！</a>]]></description>
            <author>人月神话</author>
            <category>随笔文章</category>
            <comments>http://blog.sina.com.cn/s/blog_493a8455010158zc.html#comment</comments>
            <pubDate>Thu, 24 May 2012 22:05:36 +0800</pubDate>
            <guid>http://blog.sina.com.cn/s/blog_493a8455010158zc.html</guid>
        </item>
        <item>
            <title>领域模型-工厂和仓储</title>
            <link>http://blog.sina.com.cn/s/blog_493a84550101572k.html</link>
            <description><![CDATA[首先为什么需要工厂Factory，因为有了聚合的概念，很多时候我们需要创建Aggregate整个聚合，创建过程很复杂，如果我们把这个创建职责分配给聚合里面的任何一个Entity来说都是不合适的，一个是暴露了聚合内部的结构破坏了边界，一个是聚合内的实体承担了本身不应该自己承担的职责。<br />

<br />
因此应该将创建复杂对象的实例和聚合的职责转移给一个单独的对象，这个对象本身在领域模型中可能没有职责，但是它仍然是领域模型的一部分。提供一个封装所有复杂装配操作的接口，而且这个接口应该不需要客户引用要被实例化的对象的具体类。在创建Aggregate的时候要把它作为一个整体，并确保它满足固定规则。<br />

<br />
而设计模式里面的工厂模式，则强调的是工厂提供一个公共的接口，可以根据我们的需求灵活的返回不同的实现该接口的对象实例。对象的创建和实例化由工厂来完成，而不是简单的由对象的构造函数完成。而实际领域模型里面的Factory往往并没有这么复杂，仅仅是接管复杂聚合对象的创建和实例化而已。因此对于简单的Entity，或者本身不存在聚合的时候是不需要再加上Factory类的。<br />

<br />
对于仓储Repository需要说明两个方面的内容。一个是解决持久化的问题，一个是对数据层做屏蔽，避免应用或展现层直接跳过领域层对数据库进行操作而使领域模型最终无用。在有了Repository后，我们不再关心对象的存储和访问操作，而将重心真正转移到领域模型本身。或者叫使应用程序和领域设计与持久化技术解耦。<br />

<br />
对于工厂和仓储的关系，工厂负责对象生命周期的开始，而仓储负责对象生命周期的中间或结束。当对象驻留在内存或对象数据库的时候很好理解。但是至少有一部分数据会持久化存在到类似关系型数据库或文件中，这样检索出来的数据就必须重建为对象形式。<br />

<br />
对于工厂和仓储的协同，有些理解和书上有些不一致。个人理解工厂不仅仅应该关注复杂对象的创建，同时也应该关注复杂对象的保存。工厂不负责对象的持久化，工厂将持久化职责委托到仓储来完成。仓储不应该直接和应用层打交道，对于整个领域层来说。和应用层打交道的是Service接口，而和持久化层打交道的是Repository接口而已。和书里面理解最大的差异就是Repository没有保留给Client，也不是Repository委托Factory来重建对象。<br />

<br />
举一个场景来说，根据订单号获取一个聚合复杂对象采购订单，对采购订单进行修改后再进行保存。这个时候和持久化层存在两次交互，第一次是数据的读取，第二次是修改后数据的存入。<br />

<br />
对于数据读取，到领域层则是Factory需要实例化一个聚合对象并返回应用层。而Factory将该工作分解到聚合里美的每一个子实体，子实体通过Repository接口获取到ResultSet并进行OR转换后返回，Factory将拿到的所有实例化对象进行聚合返回一个完整的聚合对象实例。对于数据存储，仍然应该是Factory接管该操作，然后对数据进行分解后分别调用聚合中的每一个实体的仓储接口本身的保存方法，对数据进行持久化，在Factory层进行完整的事务控制并返回结果。<br /><br /><img width="34" height="17" src="http://simg.sinajs.cn/blog7style/images/special/1265.gif">&nbsp;&nbsp;<a href="http://t.cn/zO1XLB6" target="_blank">秀萌宝照片，酷赢“拉比盒子”</a>&nbsp;&nbsp;<a href="http://union.9173.com/pub?p=1&u=1008" target="_blank">“警告：您的主城已被占领！！”</a>&nbsp;&nbsp;<a href="http://qing.weibo.com/fancy.html" target="_blank">发现兴趣所在，玩转新浪Qing！</a>]]></description>
            <author>人月神话</author>
            <category>读书笔记</category>
            <comments>http://blog.sina.com.cn/s/blog_493a84550101572k.html#comment</comments>
            <pubDate>Wed, 23 May 2012 22:02:20 +0800</pubDate>
            <guid>http://blog.sina.com.cn/s/blog_493a84550101572k.html</guid>
        </item>
        <item>
            <title>领域模型-聚合和聚合根</title>
            <link>http://blog.sina.com.cn/s/blog_493a84550101554f.html</link>
            <description><![CDATA[聚合和聚合根是领域模型里面很重要的一个概念，其实我们在从真实世界对业务对象进行识别和概念建模的时候，关注的就是聚合根，这才是我们真正要管理的业务对象。一个对象可能有多个层次，也可能有多个子实体，但是这些子实体都不可能孤立存在，它们必须依附于一个聚合根存在，它们和根节点具有同样的生命周期。<br />

<br />
如果一个客户消亡，客户联系方式，客户的多张银行账户信息将不再有任何意义。如果一张采购订单头消失，那么采购订单明细没有任何存在的意义。客户，采购订单，发票这些从真实业务中转化过来的业务对象才是真正的领域核心对象。这些对象可能在领域建模的时候会分解到多个Entity或Value
Object，但是一定要意识到实际的聚合在哪里？我们真正关注的业务对象实体究竟有哪些？<br />
<br />
为什么如此强调领域模型，强调聚合根的概念，因此我们在关注领域模型的时候将有助于我们打破原有的关系型数据库的思维模式，转化为对象和领域的思维模式。可以看到领域建模和聚合根的思路正是既适合于关系型数据库，也适合NoSql数据库的建模思路。因为在NoSQL持久化的时候，我们看到采购订单就是一个对象，其它明细和关联信息都是这个对象下的子实体信息，采购订单应该作为一个对象整体进行查询和存储，我们并不关系NoSQL会如何去存储这个对象。让我们正在关注领域对象，而不是去关心如何持久化。<br />

<br />
聚合Aggregate就是一组相关对象的集合，我们把它作为数据修改和访问的单元。每个聚合都会有一个聚合根和聚合的边界Boundary，边界定义了在一个聚合里面内部应该有哪些实体，哪些子实体对象。定义边界的原因是我们期望对一个聚合的访问是通过聚合根点进行的，聚合里面的子实体对外界是完全封闭的。对于外部对象不应该去访问到一个聚合边界里面的子实体。<br />

<br />
在一些场景下，对于一个聚合的访问，我们往往只需要查询到头信息，而不关心具体的子实体信息，这个有点类似于传统O/R
Mapping里面的惰性加载。在这里也必须要考虑到。在实现和设计聚合的时候，需要考虑到这种场景，即根据需要来加载一个完整聚合中的实体和子实体，以满足性能的需要。如何对应关系型数据库，对一个聚合实际的新增变更处理则可能涉及到多个数据表的多次操作，而这已经是仓储接口和仓储实现需要考虑的问题。现在对一个聚合的一次操作一定应该在一个完整的事务里面，以保障实际的事务完整性要求。<br />

<br />
按实际对象分析思路，在领域模型中的领域对象分析应该按照从顶向下的思路进行展开，如果这样的话首先识别到的就是聚合根对象，然后再考虑对聚合根对象进行展开，在聚合根对象的展开过程中进一步细化子实体之间的关联和依赖关系。<br /><br /><img width="34" height="17" src="http://simg.sinajs.cn/blog7style/images/special/1265.gif">&nbsp;&nbsp;<a href="http://t.cn/zO1XLB6" target="_blank">秀萌宝照片，酷赢“拉比盒子”</a>&nbsp;&nbsp;<a href="http://union.9173.com/pub?p=1&u=1008" target="_blank">“警告：您的主城已被占领！！”</a>&nbsp;&nbsp;<a href="http://qing.weibo.com/fancy.html" target="_blank">发现兴趣所在，玩转新浪Qing！</a>]]></description>
            <author>人月神话</author>
            <category>随笔文章</category>
            <comments>http://blog.sina.com.cn/s/blog_493a84550101554f.html#comment</comments>
            <pubDate>Tue, 22 May 2012 22:27:38 +0800</pubDate>
            <guid>http://blog.sina.com.cn/s/blog_493a84550101554f.html</guid>
        </item>
        <item>
            <title>领域模型-谈实体对象和值对象</title>
            <link>http://blog.sina.com.cn/s/blog_493a84550101534t.html</link>
            <description><![CDATA[对于实体Entity和值对象Value
Object是领域驱动设计里面两个重要的模型对象。所以有必要对两者的关系和区别进行理解。以下部分内容直接引用自《领域驱动设计》一书相关内容。<br />

<br />
首先对于实体Entity，实体核心是用唯一的标识符来定义，而不是通过属性来定义。即即使属性完全相同也可能是两个不同的对象。同时实体本身有状态的，实体又演进的生命周期，实体本身会体现出相关的业务行为，业务行为会实体属性或状态造成影响和改变。<br />

<br />
真正的现实世界，每个事物都一定会有唯一的标识，关键点是我们实际的业务场景和需求是否需要管理到唯一标识。书里面举了一个例子，当我们发放的门票上有座位号的时候，座位需要作为独立的实体，座位号是唯一的标识。而当先到先座模式下，我们只关心剩余座位数，那么座位号并不是唯一标识。这跟我们的业务需求有关。<br />

<br />
一个对象不由属性来定义，那么看人这个对象，身份证号是属性，其实也是对于人的唯一标识。不考虑本身身份证号的位数升级，一个身份证号会跟随你一辈子。但是对于人我们一般仍然会作为实体Entity来看待，因为人有状态，有对象演进的生命周期，会主动产生各种行为。<br />

<br />
对于企业内信息系统，很多时候我们把员工工卡号作为唯一标识来使用，但是要意识到工卡号只是人员的一个属性。虽然工卡号本身不会出现两个重复的，但是该属性仍然可能演变，如果将工卡号作为唯一标识和ID，那么在该属性变化时候所有其余关联对象都将受到影响。从这个层面来看，一个唯一的内码ID才是可信的唯一标识。<br />

<br />
而对于值对象Value
Object，它用于描述领域的某个方面本身没有概念标识的对象，值对象被实例化后只是提供值或叫设计元素，我们只关心这些设计元素是什么？而不关心这些设计元素是谁。书里面谈到颜色，数字是常见的值对象。这种对象无状态，本身不产生行为，不存在生命周期演进。<br />

<br />
是否为值对象跟实际的业务场景仍然关系密切。书里面又举了地址的例子，当地址是值对象的时候，地址本身无状态，可以被多个实际有状态的实体使用，地址不存在太多的生命周期演进场景下地址为值对象。而对于本身行政区域管理软件中，地址本身存在状态，存在根据行政区域规划变化而演进的过程，因此地址为实体。<br />

<br />
如果从值对象本身无状态，不可变，并且不分配具体的标识层面来看。那么值对象可以仅仅理解为实际的Entity对象的一个属性结合而已。该值对象附属在一个实际的实体对象上面。值对象本身不存在一个独立的生命周期，也一般不会产生独立的行为。<br />

<br />
值对象往往可能是多个属性的聚合，本身无唯一标识，多个属性最终形成的一个结果值，而这个结果值往往又依附在一个实际的实体Entity上面。那么如果从这个概念来说，值对象往往不会单独进行持久化，或形成数据库设计的一张数据表。另外一种情况，对于简单的数据字典类对象，是否考虑作为值对象，这种对象需要持久化，如纳税属性，物料类型，它们设计到数据字典中取值，这个数据字典无状态，无自己的生命周期，是可以作为值对象来处理的。<br /><br /><img width="34" height="17" src="http://simg.sinajs.cn/blog7style/images/special/1265.gif">&nbsp;&nbsp;<a href="http://t.cn/zO1XLB6" target="_blank">秀萌宝照片，酷赢“拉比盒子”</a>&nbsp;&nbsp;<a href="http://union.9173.com/pub?p=1&u=1008" target="_blank">“警告：您的主城已被占领！！”</a>&nbsp;&nbsp;<a href="http://qing.weibo.com/fancy.html" target="_blank">发现兴趣所在，玩转新浪Qing！</a>]]></description>
            <author>人月神话</author>
            <category>读书笔记</category>
            <comments>http://blog.sina.com.cn/s/blog_493a84550101534t.html#comment</comments>
            <pubDate>Mon, 21 May 2012 20:01:10 +0800</pubDate>
            <guid>http://blog.sina.com.cn/s/blog_493a84550101534t.html</guid>
        </item>
        <item>
            <title>谈知识体系的演进</title>
            <link>http://blog.sina.com.cn/s/blog_493a8455010151jj.html</link>
            <description><![CDATA[如果我们谈IT咨询规划顾问，或者谈大型IT项目的项目经理，很多时候往往需要的都是综合能力。对于综合能力在这里不再谈沟通，ppt和演示，团队协同，写作能软技能能力。而重点来谈谈业务和技术方面综合能力的演进过程和路线。<br />

<br />
拿IT项目经理来说，如果没有真正做过比较专职化的项目经理，很难真正的理解到项目经理的工作内容和实践，项目管理中的实际问题。而你真正做了项目经理，你又会发现很多工作内容原来就在做，只是没有系统化和体系化。正如管理不在于知，而在于行一样道理，<span STYLE="color: rgb(255, 0, 0);">很多事情如果没有实践很难真正系统化和体系化形成经验和能力</SPAN>。<br />

<br />
前面工作3-4年基本以软件开发为主，没有做过专职的需求，也没有做过专职的测试，但是在软件开发过程中自然涉及到这些内容，通过软件开发实践，以问题驱动的方式自然会对整个软件生命周期中的需求和测试环节提出更深入的理解。<span STYLE="color: rgb(255, 0, 0);">旁观者清，旁观者往往更多的是问题和场景驱动，通过问题和场景来反思上下游过程存在的问题和不足，以理解各个过程的核心要素</SPAN>。<br />

<br />
在8年后我基本在逐步开始做外部大型项目的项目管理，IT业务咨询方面的工作。个人核心观点就是这个层面往往已经不是靠单个岗位上工作经验的积累，更多的是靠整个IT领域相关知识的积累。如果原来多年的积累就只关注点上的知识，要在学习能力下降后的现在考虑快速的面上的拓展是相当困难的事情。前面8年的工作基本涉及到软件开发，业务领域知识，需求，架构，测试，开发平台，IT项目管理，cmmi，产品开发等多个方面的知识，这些知识基本也是以核心业务域+软件工程的拓展。有大环境，有项目实战，再加上自己兴趣驱动就容易去拓展和深入。可以讲现在在实际工作中使用到的知识涉及到的方面太多，而这些又刚好基本都在原来学习和实践过，有些是亲自参加，有些是参与专题讨论和评审，制定方案。<span STYLE="color: rgb(255, 0, 0);">所以讲现在之学习和实践必将为后续工作所用，即使是跨行业，那么你仍然可以学习原来的学习方法和解决问题思维</SPAN>。<br />

<br />
<span STYLE="color: rgb(255, 0, 0);">原来我讲过学习的前导性和学习的外延性的问题。其核心就是学习知识不仅仅是一个类似知识树的静态结构，而是一个通过前导-》当前-》外延拓展有效串联的动态学习链</SPAN>。当前工作开展不下去是前导知识缺失，当面工作完结而主动思考和总结减少了拓展和外延的机会。工作中学习的过程其好处就是实际问题驱动，<span STYLE="color: rgb(255, 0, 0);">只有问题驱动的学习是最有价值，也产生价值的学习，学习的过程就是不断前导外延双向拓展的过程，各个知识点不断抽象进行系统化和体系化的过程。</SPAN><br />

<br />
回到正题，知识有一个完整的演进路线，并不是说学习过程一定遵循这些演进路线，只是提供一种参考。个人经验来看仅仅谈从软件开发走到最好的咨询管理岗位的学习和渐进路线。<br />

<br />
在技术层面：前面三年重点是编码能力提升，好的编码本身就是设计，在编码过程中加强重构。后面三年过渡到系统分析设计能力提升，一个是本身架构设计能力的提升，在架构设计能力提升中自然会更加关注需求和测试，关注整个软件生命周期，架构中开始关注技术架构和框架方面的内容，也关注RUP，MDA，DDD，FDD，敏捷等各种方法的核心思想，并选择性的使用。后面接着可以关注大型产品研发方面内容，关注技术平台和产品平台的概念，关注SOA和组件化架构这些内容。<span STYLE="color: rgb(255, 0, 0);">在技术层面，如果不是完全纯粹的技术线发展，要知道cmmi和软件工程体系知识重要性远远高于数据结构和算法。</SPAN><br />

<br />
在业务领域层面：对于技术路线刚开始很少会关注到真正的业务域，所以我们说虽然从事技术或软件产品，仍然最好是能够适当的做不同业务域的软件，只有真正做该业务域的时候你才会真正关心业务需求和流程。在前阶段的自我学习往往都是理论和宏观的概念，很难真正的去细化。做企业信息化不管互联网如何发展，企业价值链分析思路，ERP说涉及到业务域仍然是核心内容。大的业务线条如供应链(计划，库存，采购)，财务，合同，市场营销和CRM，产品研发，HR等都需要有所了解。在中后期阶段，重点感觉是企业架构和各个业务域的核心业界标准和模型的学习。比如谈供应链的时候会谈到scor模型，谈产品研发会谈到cmmi和ipd等。而且你原来涉及到的是一个行业，跨行业的时候还会出现很多差异化的内容，比如09年我做电力行业项目的时候，发现电网企业很多业务和系统和传统制造型企业有很多的不同。做运营商项目的时候又不得不去研究eTOM和SID等模型和规划体系。但是不管怎么变，核心业务仍然是通的。<span STYLE="color: rgb(255, 0, 0);">知识很多时候并不一定必须是从下向上抽象，很多时候也可以从顶向下构建，先构建完整的总体框架，然后根据需要逐步研究和深入。</SPAN><br /><br /><img width="34" height="17" src="http://simg.sinajs.cn/blog7style/images/special/1265.gif">&nbsp;&nbsp;<a href="http://t.cn/zO1XLB6" target="_blank">秀萌宝照片，酷赢“拉比盒子”</a>&nbsp;&nbsp;<a href="http://union.9173.com/pub?p=1&u=1008" target="_blank">“警告：您的主城已被占领！！”</a>&nbsp;&nbsp;<a href="http://qing.weibo.com/fancy.html" target="_blank">发现兴趣所在，玩转新浪Qing！</a>]]></description>
            <author>人月神话</author>
            <category>随笔文章</category>
            <comments>http://blog.sina.com.cn/s/blog_493a8455010151jj.html#comment</comments>
            <pubDate>Sun, 20 May 2012 23:53:26 +0800</pubDate>
            <guid>http://blog.sina.com.cn/s/blog_493a8455010151jj.html</guid>
        </item>
        <item>
            <title>谈产品集成</title>
            <link>http://blog.sina.com.cn/s/blog_493a84550101517n.html</link>
            <description><![CDATA[为何要进行产品集成<br />
<br />
对于大型产品开发，一次可能开发多个新的业务系统，同时一个业务系统本身又包含多个业务模块和组件。只要我们在前期产品规划中存在子系统和模块的分解，那么后续就一定存在产品集成的动作。在架构设计中我们通过进行组件分解，识别和定义组件间接口，一方面是通过分而治之降低大系统复杂度，另外一方面则是通过分解和接口定义后各模块可以并行开发。只要架构阶段存在分解动作，那么最终在各模块开发完成后一定存在集成动作。架构做出一个假设，只要在分解的时候各组件模块按预定的接口契约进行实现，那么后续各个组件一定可以进行集成和组装形成一个完整的产品。所以架构不能仅仅只关心解耦，还必须关心集成和装配，解耦后的东西无法集成，那么分解过程仍然是失败的。<br />

<br />
产品集成和持续集成的关系<br />
<br />
产品集成强调是的是把左右的组件最终能够组装和集成起来，形成一个完整的系统。而大师Martin
Fowler对持续集成是这样定义的:持续集成是一种软件开发实践，即团队开发成员经常集成它们的工作，通常每个成员每天至少集成一次，也就意味着每天可能会发生多次集成。每次集成都通过自动化的构建（包括编译，发布，自动化测试)来验证，从而尽快地发现集成错误。许多团队发现这个过程可以大大减少集成的问题，让团队能够更快的开发内聚的软件。可见持续集成只能算做产品集成的一个子实践。<br />

<br />
要明白持续集成只是产品集成的一种方式，不论是开发过程是瀑布模式，增量模式还是迭代模式，都可以采用持续集成的思路。要明白持续集成的一个核心是将整个开发过程透明化，同时将集成工作提前化。尽可能早的暴露问题和风险，同时纠正在前期系统分析和架构设计中的不足。<br />

<br />
对于持续集成我们往往会强调每日构建，冒烟测试，自动化测试等内容。强调开发，测试和生产环境的部署流水线作业。但是要明白对于大型产品集成仍然回包括模块内测试和集成，模块间测试和集成，跨系统间的测试和集成工作。对于单个模块内可以采用每日构建和持续集成策略，但是对于模块间和跨系统我们可以采取分迭代式的集成方式进行集成。<br />

<br />
关于持续集成的核心逻辑<br />
<br />
在这里要分两个层面来谈，首先是单环境，涉及到自动化构建，部署，测试一系列动作。具体过程可以简化描述如下。首先是编写好自动化编译脚本代码，如使用ant工具完成；然后设置定时作业和任务，开发人员按时check
in相关代码。使用CI持续集成工具根据定时任务点在构建环境自动获取最新代码，自动运行ant自动化编译脚本对代码进行编译，编译完成后自动化部署到某个环境。部署完成后运行单元测试自动化脚本对代码进行自动化测试，输出自动化测试结果和报告；如果通过的话测试人员通过QTP进行进一步自动化测试或手工执行一遍冒烟测试脚本，完成本次持续集成。在持续集成模式下，一方面是可以尽可能早的发现问题，一方面对测试人员随时都可以有一个可进行详细功能性测试的可用环境。<br />

<br />
其次如果对于多环境，涉及到开发环境测试通过后自动部署集成测试环境，集成测试环境测试通过后自动部署到验收环境等一系列动作。对此我们叫部署流水线模式，实现跨环境的持续集成管理。<br />

<br />
对于持续集成，由于组件间可能存在编译依赖，我们需要分析组件间的依赖关系，以顺利的完成整改编译过程。而在产品集成过程中我们考虑的不是编译依赖而是本身组件间的功能依赖，因此我们需要进一步详细的考虑组件间的集成顺序和集成策略问题。<br />

<br />
产品集成顺序的分析<br />
<br />
产品集成顺序分为两种模式，一种是自顶向下的模式进行集成，一种是自底向上的方式进行集成。对于自顶向下方式的集成，首先集成最外层或流程最末端的业务模块，业务模块前置依赖用模拟器(桩)实现。然后继续在每一层按宽度或深度优先，用完全实现模块代替模拟器，并建立下层。以这种方式继续直到所有被测系统中的桩已经实现和测试。在这种模式下可以看到整个集成过程完全是顶层需求驱动进行，集成工作可以较早的开始进行，如果产品集成图是正金字塔结构较容易，模拟器开发较少；反之同理。<br />

<br />
对于自底向上集成，首先集成最底层的业务模块，只在底层模块未实现前使用模拟器(桩)。然后继续在实现并测试对上一级模块，这些构件使用已经测试的下级模块。整个系统使用根一级模块测试。对于这种模式模拟器开发较少，同时上次各模块基本可以开始并行测试。这种集成方式最大的风险是如果上次需求变化可能直接影响到最底层。<br />

<br />
产品集成的集成场景分析<br />
<br />
集成场景分析目的是为后续的集成测试用例设计提供依据，集成测试用例要覆盖所有场景。对于场景分析输入主要包括跨模块协同业务流程图，系统需求规格说明书，概要设计说明书等。对于集成场景分析可以从静态和动态两个层面进行分析，对于静态分析主要分析模块依赖关系，分析某一个服务接口影响到的业务模块具体功能点，可以模块-》模块的矩阵分析方法进行。对于动态分析主要是根据跨系统或模块流程入手，分析跨模块的流程协同，流程协同中所涉及到的所有接口服务。<br />

<br />
集成场景的分析将为集成测试用例的设计提供核心输入，要明白，集成测试不是简单的接口测试，接口反映的是跨系统或模块的交互流程，需要通过交互流程的贯通来检验接口本身的正确性。<br /><br /><img width="34" height="17" src="http://simg.sinajs.cn/blog7style/images/special/1265.gif">&nbsp;&nbsp;<a href="http://t.cn/zO1XLB6" target="_blank">秀萌宝照片，酷赢“拉比盒子”</a>&nbsp;&nbsp;<a href="http://union.9173.com/pub?p=1&u=1008" target="_blank">“警告：您的主城已被占领！！”</a>&nbsp;&nbsp;<a href="http://qing.weibo.com/fancy.html" target="_blank">发现兴趣所在，玩转新浪Qing！</a>]]></description>
            <author>人月神话</author>
            <category>IT咨询</category>
            <comments>http://blog.sina.com.cn/s/blog_493a84550101517n.html#comment</comments>
            <pubDate>Sun, 20 May 2012 17:28:04 +0800</pubDate>
            <guid>http://blog.sina.com.cn/s/blog_493a84550101517n.html</guid>
        </item>
        <item>
            <title>持续集成工具的选择-装载</title>
            <link>http://blog.sina.com.cn/s/blog_493a84550101516h.html</link>
            <description><![CDATA[原文：<a HREF="http://www.iteye.com/topic/482658" TARGET="_blank">http://www.iteye.com/topic/482658</A><br />
<br />
持续集成(continuous
integration)作为敏捷编程的基石现在已经被绝大多数的开发团队所广泛采用。而持续集成的工具现如今也是百花齐放，各有千秋，本文主要对比了在Java领域中比较常见的几种CI
server（因为公司要求统一整个公司的CI server）。<br />
<br />
如果想了解更多的工具，可以看这里：<a HREF="http://confluence.public.thoughtworks.org/display/CC/CI+Feature+Matrix" TARGET="_blank">http://confluence.public.thoughtworks.org/display/CC/CI+Feature+Matrix</A>，这个网页集中了决大多数比较流行的CI
server，但是我发现很多的内容已经落后于实际产品的功能了，所以如果要对比的话，可能要实际到产品的站点去看一下，最好还是下载下来运行起来看。<br />

<br />
在本文中，我主要针对以下几种CI Server作对比，这也是公司里各个项目组目前自行选用的（版本有点多，国内的多选用了一些open
source的，而老外那边用得比较多的是商用版本，CruiseControl和TeamCity是我加的，因为名气非常大。）：<br />

<br />
<ul>
<li>CruiseControl (<a HREF="http://cruisecontrol.sourceforge.net/" TARGET="_blank">http://cruisecontrol.sourceforge.net/</A>)</LI>
<li>Hudson (<a HREF="https://hudson.dev.java.net/" TARGET="_blank">https://hudson.dev.java.net/</A>)</LI>
<li>LuntBuild (<a HREF="http://luntbuild.javaforge.com/" TARGET="_blank">http://luntbuild.javaforge.com/</A>)</LI>
<li>TeamCity (<a HREF="http://www.jetbrains.com/teamcity/" TARGET="_blank">http://www.jetbrains.com/teamcity/</A>)</LI>
<li>AntHill Pro (<a HREF="http://www.anthillpro.com/" TARGET="_blank">http://www.anthillpro.com/</A>)</LI>
<li>Bamboo (<a HREF="http://www.atlassian.com/software/bamboo/" TARGET="_blank">http://www.atlassian.com/software/bamboo/</A>)</LI>
<li>QuickBuild (<a HREF="http://www.pmease.com/" TARGET="_blank">http://www.pmease.com/</A>)</LI>
</UL>
<br />
在持续集成领域，OpenSource的CruiseControl和LuntBuild可谓老牌了，尤其是CruiseControl，出自thoughtworks，这可是Martin
Fowler的老巢啊。Hudson作为OpenSource里持续集成的后起之秀，现在已经赶超了这两个前辈，目前恐怕是使用最多的一个CI
Server了。而后面4个是商用的CI
Server，其中TeamCity是来自jetbrains的，jetbrains是开发著名的IDE
IntelliJ的公司。Bamboo则是开发著名的Bug Tracking工具Jira和Wiki
Confluence的公司atlassian公司出品的。AntHill也属于Continuous
Integration界的元老，QuickBuild则是LuntBuild的商业版本。<br />
<br />
我在下面重点考量的是QuickBuild，因为LuntBuild好像现在更新较慢了，而且QuickBuild现在好像也有了免费的所谓的Community
Edition，功能齐全，只是配置数有所限制。在这些商业版本中，TeamCity应该是目前市场占有率最高的。由于公司里比较倾向使用商业版本的服务器，所以我重点比较的是后4种，捎带比较了一下CruiseControl和Hudson。TeamCity和QuickBuild都有各自的免费版本，有兴趣的也可以去看看。<br />

<br />
<span STYLE="font-weight: bold;">功能对比</SPAN><br />
<br />
CI
Server在本质上就是一个定时调度器。我们配置一系列的项目，然后设定一个定时器，让它干一些活，然后通知大家。所以很多公司都使用所谓Home-made的工具，用cron+Ant/Maven来做持续集成，这个就已经可以达到CI的最简单的功能了。而使用工具，就是我们除了基本的编译和通知功能以外，我们还有很多其它的需求，在我们公司里，选择CI
Server主要考虑以下几点：<br />
<br />
<ul>
<li>便于公司的统一管理（大约有200+ Projects需要统一管理）</LI>
<li>对于项目本身进行流程管理: Daily Build -&gt; QA Build
-&gt; Release Build</LI>
<li>和公司AD（Active Directory）的连接以对用户进行权限管理</LI>
<li>Continuous
Testing的支持，即对于项目的Test要能产生出详尽的报告以及收集Test的统计数据以作为项目的分析和考量</LI>
<li>Continuous Code Quality
Analysis的支持，即能处理项目产生的Coverage报告，Code的static
analysis报告，并且能收集这些报告的统计数据以作项目的分析和考量</LI>
<li>与SCM工具的集成，我们公司主要有三种VCS，ClearCase, Subversion和StarTeam</LI>
<li>与其它工具的集成，如bug tracking工具，IDE集成等等。</LI>
</UL>
<br />
<span STYLE="font-weight: bold;">安装CI</SPAN><br />
<br />
安装是我们开始的第一步，同时也对各个CI
server都有了初步的印象。按照各自的手册，很快就装好了，我基本上选择的是Standalone的版本，就是不配置数据库，使用自带的，也不deploy到Tomcat或者其它容器，这点，基本上每个CI
Server都非常简单。所以也没看出什么好坏来。这里不得不提一下AntHill，有点小家子气，要download还得提交一个request，然后才能下载，安装，有点烦。<br />

<br />
<span STYLE="font-weight: bold;">配置项目</SPAN><br />
<br />
在大多数的CI Server中，绝大部分都是以Project或者Project
Group来进行管理，只有LuntBuild和QuickBuild比较另类，它们使用了Configuration这个术语，意即一个配置。在配置一个典型的项目的时候，即只处理基本的一个流程：CheckOut,
Build, Publish
Artifacts，这些工具都完成的非常好，也非常简单，我使用下来，觉得TeamCity的导航最方便，一目了然。而LuntBuild和QuickBuild在这方面稍显人性化不足，这两个工具都没有使用wizard的模式。<br />

<br />
下面，我接着实验配置50个测试项目，这也就开始考验一个CI
Server的管理能力了（因为我们项目较多）。使用下来，我发现QuickBuild对于我而言，最实用。因为它使用Configuration而不是Project，并且QuickBuild是这些CI
Server中唯一支持树状结构配置的。我可以把Configuration配置成Team A, Team B
...，然后根据实际情况，对每个Team配置任意多个子节点，孙节点（注意，Configuration的数目在QuickBuild的Community
Edition里是要限制的，好像是最多16个），<span STYLE="color: rgb(255, 0, 0);">另外，QuickBuild的继承关系使用起来也非常方便，如果要管理一个大型的CI
Server，没有这种继承对我而言简直是一种折磨。比如说用hudson来配置50个项目，我折腾了大半天，而用QuickBuild来，我大约只用了一个小时</SPAN>，我实际配置的Configuration（含有实际step定义的）只有3个，其它的都是继承下来，然后修改了一下参数而已，而如果我们需要批量修改一系列的configurations的时候，则由于有继承关系，通常我们只要去修改一下父节点的设置就可以了。TeamCity支持Project
Group的概念，类似于一种树形，但是还不完备，它只能分成两级关系，即Project
Group和Project。另外QuickBuild所拥有的继承的功能，在别的CI里没有看到过，有的只是象TeamCity类似的copy
project的功能。而QuickBuild在复制的能力上远远胜过其它的CI
Server，它可以整个子树拷贝，这也就意味着，我可以配置一个公司用的template
configuration树，然后复制出A部门，B部门，C部门，等等等等。对于不同项目之间的区别则通过变量来控制，赞一个！TeamCity在配置的方便上真得是没话说，非常直观，最酷的是象JUnit，NUnit这样的Tests，连Ant脚本都不需要写了，它直接就可以找出项目里的unit
tests，这个在其它的工具里也没有看到过。至于CruiseControl，Hudson，Bamboo等则是中规中矩，无甚亮点。这个环节，QuickBuild和TeamCity胜出。<br />

<br />
另外配置一个项目要配的就是项目持续集成的流程管理，在我们这里，基本上是这样一个流程: <span STYLE="color: rgb(255, 0, 0);">Daily Build -&gt; QA Build
-&gt; Integration Build -&gt; Release
Build</SPAN>。所谓Daily Build，顾名思义，就是每天一次的，由development
team管理以保证项目的顺畅执行，然后经过一段时间后，development
team要提交到QA那边进行测试，通常是2个星期到一个月左右，随项目大小不等，QA测试结束之后，如果没有重大的问题，则提交作Integration
Test，以保证在模拟的实际环境中能正常工作，最后，如果没有什么问题的话则作Release
Build以形成发布版本。对于公司里有一些Team使用敏捷编程的，则需要增加所谓的Commit Test
Build，也就是developer在作每一个checkin的时候自动触发一个build，以保证build不会被这个checkin破坏（包括不会破坏unit
tests和code quality)。这也是所谓的要作continuous testing和continuous code
quality analysis，这些都是通过利用JUnit, NUnit，CheckStyle,
PMD，Cobertura，FxCop等工具来实现的。我们在后面也会讲到，这里略过。这个环节里，个人比较喜欢AntHill
Pro和QuickBuild，这两个工具都是比较强调流程的，尤其是AntHill Pro更是将其作为卖点。<span STYLE="color: rgb(255, 0, 0);">AntHill
Pro以工作流的模式来定义这个流程，一个项目可以定义多个的workflow</SPAN>，对应于我们的case，就是定义Daily
Build的workflow，定义QA
Build的workflow，等等，然后在作promote的时候，通过选择不同的workflow来达到目的。而QuickBuild则是利用已有的configuration的概念，定义不同的Configuration，然后在Configuration的setting里定义一个或多个要promote的configurations。要作promote的时候，则通过点击某个build的promote按钮将其promote到指定的configuration上去，也很方便。使用AntHill的模式，概念上很清晰，因为我们要作的是流程管理嘛，所以workflow会听起来比较容易接受。而QuickBuild则是把它绑定在Configuration上，使用起来比较简单，但是找起来要费点事，至少对于我而言是这样。Hudson也有类似的流程管理，但是它是自动的，而promote在我们这里是需要人来作review的，也就是说要人去参与，判断究竟使用哪个版本来promote，所以在我们这里，不是很合适。<br />

<br />
在配置项目这个环节里，个人感觉QuickBuild比较灵活，既可以做到很简单的配置，也可以做到非常复杂的配置，而且配置起来方便性非常好。只是术语与其它的CI
Server有些不同，需要熟悉一下。<br />
<br />
<span STYLE="font-weight: bold;">Build功能</SPAN><br />
<br />
CI
Server最重要的就是Build本身的功能，包括SCM的连接，用户的权限管理，Build工具的支持。首先我们来看看SCM的支持。<br />

<br />
<span STYLE="font-weight: bold;">SCM支持</SPAN><br />
<br />
在这些CI Server中，AntHill
Pro和Hudson支持的种类最多，尤其是Hudson，基本上市面上的SCM都有所支持。对于象比较常见的Subversion，CVS，ClearCase，StarTeam，SourceSafe等，各家都已经支持了。而在上一项目中表现较好的QuickBuild，则属于在SCM里支持最少的一家，它还不支持git，Team
Foundation
Server，这个目前已经很流行的两种SCM，实在有些遗憾。不过瑕不掩瑜，QuickBuild在支持SCM的时候，由于使用变量的支持，却是多家CI
Server中最灵活的一家，它可以使用变量来配置SCM的URL，而其它的，则是通过定义一个基本的URL，然后针对不同项目来定义各自的SCM
repository。而QuickBuild还有一个它自有的QuickBuild
Repository，用于在不同的Configuration中传递artifacts，实际用起来也很方便，比如说我们在一个项目里要用到别的项目的artifacts，那么就可以定义一下这个repository。当然，这个功能也可以通过Maven的repository来完成来达到相同的目的。TeamCity也提供了类似的机制，只不过TeamCity的Repository其实就是一个Ivy的扩展。<br />

<br />
SCM的数据在这些CI Server中都有体现，从每一个Build的change
sets到历史统计。说明现在大家都很重视对于这些数据的收集和分析。其中TeamCity能直接从Web页面上直接调用IDE来打开这些改动的文件是一大亮点，毕竟是做IntelliJ的公司啊！<br />

<br />
<span STYLE="font-weight: bold;">用户管理</SPAN><br />
<br />
这个基本上是每个CI
Server的必备功能了，基本上都是既可以用内置的数据库管理（Hudson好像没用数据库），又可以连接LDAP服务器。我只是简单测试了一下，没有深入，也就没有什么发言权了。<br />

Build的Dependencies管理 (Dependent Builds)<br />
<br />
在实际的项目中，我们常常会出现项目之间的依赖关系，比如说A项目依赖于B项目，B项目依赖于C项目。所以当我们要编译A项目的时候，我们需要先编译C项目，然后编译B项目，最后再来编译A项目，这样做的好处显而易见，就是保证我们总是使用最新开发的code来编译一个版本，如果发生了什么问题，我们也可以很容易的知道究竟是哪个项目break了整个build的流程。这个功能基本上所有的这些CI
Server都有提供，而能力各有千秋。TeamCity在这里属于最弱的一个，它只能通过定义Ivy来达到Artifacts在不同项目中的依赖管理，而AntHill
Pro，Bamboo和QuickBuild则都有提供两种类型的dependency管理，即artifacts和项目本身的依赖管理。不过TeamCity却有另外的杀手锏，就是导入项目的功能，它支持从IntelliJ的项目，Maven的项目中直接导入创建这种依赖关系。<br />

<br />
<span STYLE="font-weight: bold;">分布式Build Pool</SPAN><br />
<br />
由于公司的项目繁多，平台繁多，对于一个项目需要分布到不同的平台去编译，测试，这时候就需要建立一个Build
Pool了，基本上上述各家的CI Server都已经支持了这种分布式的build pool，其实质是利用了grid
computing技术来进行管理。也就是一个build server带上一群的build
agent，然后把build的任务分布到不同的agent上去执行。在这里不得不再赞一个QuickBuild了（呵呵，这个QuickBuild好像给人惊喜不断啊），其实QuickBuild的agent与其它家的倒没什么不同，只不过就是一个computing
unit，关键在于QuickBuild里配置一个configuration，它使用了step的概念（这个QuickBuild的术语倒是不少嘛），这个step在AntHill
Pro里也存在，关键在于这个step是可以分布的，也就是说，我配置一个项目的时候，可以定义一系列并行的分布式的step，这样对于管理和收集artifacts非常方便，我们可以定义Test
On Windows, Test On Mac, Test On
Linux，然后设置一下运行这些step的时候需要什么类型的agent，QuickBuild就可以把这些任务分布到这些平台的agents上去运行了。而其它家的可能是因为收费的方式，象TeamCity，一个build只能在一个agent上运行，我如果要做到同样的效果，就需要定义出三个项目，然后让这三个项目在不同的agents上运行，最后，还要再定义一个项目，让这个项目去收集它们的artifacts，非常麻烦。Bamboo和AntHill也类似于TeamCity。而Hudson在这块的能力很弱，个人感觉不如其它的产品强大，而且使用起来也更复杂一些。<br />

<br />
<span STYLE="font-weight: bold;">Report功能和统计</SPAN><br />
<br />
上述各家CI
SERVER都提供了Report的功能和统计的功能，在这个领域里，Hudson毫无悬念的是支持报告类型最多，最全的（谁叫咱OpenSource呢，有的是人开发）。Bamboo属于支持报告类型最少的，不过也有很多第三方的plugin供选择。我们所关心的几个reports都有被各家支持，其中QuickBuild的report给我的感觉最华丽，不过好像是参考google
analytics来的，从界面上看和analytics简直就是一个翻版。在使用上，QuickBuild和TeamCity的最方便，直接点报告中的链接就可以作一些过滤。在统计信息方面，各家对tests的统计都非常完备，这也从一个侧面反应出test
driven现在那是深入人心啊。在支持Test
Driven方面，TeamCity是力拔头筹，得益于开发IntelliJ的经验，TeamCity不仅可以自动寻找出项目中的unit
tests（你不用在Ant脚本里调用junit task，或者在Maven里调用surefire），而且对于上次运行失败的test
cases，它可以在下次build中自动先运行，这样就可以避免一个build运行了很久才发现上次失败的test还没有被更正过来呢，强！<br />

<br />
另外，要提一下的是QuickBuild中那个Build的Dashboard我非常喜欢，对于一个项目当前的状况可以一目了然，有多少个tests成功了，多少失败了，多少被fix了，多少还没有fix，总之，信息很丰富，不过就是配置起来有点复杂，需要我去一个报告一个报告去加step，如果能做到TeamCity的程度，简直就是完美了。对于其它的CI
Server则是亮点不多（其实也很强，只不过是对比而言，我觉得TeamCity和QuickBuild更强，更好）。<br />
<br />
<span STYLE="font-weight: bold;">与第三方工具的集成</SPAN><br />
<br />
在与第三方工具的集成中，Hudson遥遥领先，是所有CI Server里Plugin最多的。可以和FaceBook，Google
Calendar，Twitter，反正基本上你能想到的，它都有。不过对于我们而言，好多Plugin没有太大的价值。Bamboo在与它自己的几个产品中集成度也非常好，比如说Jira，Wiki，Clover等。这几个我们公司都有用到，在这点上非常理想。<br />

<br />
<span STYLE="font-weight: bold;">价格</SPAN><br />
<br />
不得不考虑一下价格的因素，好像记得有人说过，Price is nothing, but price is
everything，尤其在这个金融危机的年代里。这点，勿庸置疑，OpenSource永远是最好的。而在商用的这几个里QuickBuild最便宜，它使用的是Site
License，一个Site收$2999，AntHill最贵，我询问了一下，按我的配置，随便搞搞就要$10000了，TeamCity的入门也很便宜，$1999带3个agents，可是针对我们的情况，算了一下也要上$8000了（它是按agent收费的），Bamboo也很贵，按照它的功能而言，我觉得性价比不是很好。<br />

<br />
<span STYLE="font-weight: bold;">总结</SPAN><br />
<br />
综合各方面因素的考虑，我们最终选择了QuickBuild，虽然这个产品名声不是很大，不过想想它的客户中，不乏象Cisco，HP这样级别的公司，应该还是可以值得信赖的吧。另外就是我们使用下来觉得它还是拥有诸多亮点，对于我们的统一管理来说，可谓是方便至极。另外价格方面考虑也很不错。当然如果你的团队不是很大，那么选择QuickBuild的Community
Edition和TeamCity的Professional
Edition都是非常值得的，这两者都是免费的，而且QuickBuild的Community
Edition功能没有任何裁剪，只是限制了一下configuration的数目，非常适合要求比较高而项目不是很多的团队。<br />
<br />
好了，有太多太多需要讨论的东西了，CI这个领域现在还处于高速发展阶段，本文纯属探讨，欢迎大家拍砖。由于时间有限，对每个产品了解的不是很深入，错误在所难免，如果我有什么地方不是很准确，也欢迎告诉我。<br /><br /><img width="34" height="17" src="http://simg.sinajs.cn/blog7style/images/special/1265.gif">&nbsp;&nbsp;<a href="http://t.cn/zO1XLB6" target="_blank">秀萌宝照片，酷赢“拉比盒子”</a>&nbsp;&nbsp;<a href="http://union.9173.com/pub?p=1&u=1008" target="_blank">“警告：您的主城已被占领！！”</a>&nbsp;&nbsp;<a href="http://qing.weibo.com/fancy.html" target="_blank">发现兴趣所在，玩转新浪Qing！</a>]]></description>
            <author>人月神话</author>
            <category>转载文章</category>
            <comments>http://blog.sina.com.cn/s/blog_493a84550101516h.html#comment</comments>
            <pubDate>Sun, 20 May 2012 17:06:32 +0800</pubDate>
            <guid>http://blog.sina.com.cn/s/blog_493a84550101516h.html</guid>
        </item>
        <item>
            <title>持续集成工具-转载(王海鹏)</title>
            <link>http://blog.sina.com.cn/s/blog_493a845501014r9r.html</link>
            <description><![CDATA[原文1: http://blog.sina.com.cn/s/blog_61469a410100g539.html<br />
原文2: http://blog.sina.com.cn/s/blog_61469a410100g53a.html<br />
<br />
Thomas
Carlyle说：“人类是使用工具的动物。没有工具，人什么都不是；有了工具，人无所不能。”金融家们创造了复杂的金融工具，并利用这些工具制造了财富神话，制造了著名的跨国公司，也制造了世界范围的危机。软件精英们为了让自己的工作效率更高，有更多时间去做想做的事，也创造了各式各样的工具。持续集成已经不是一个新概念，在这个概念发展的十多年间，出现了支持这一概念的众多工具。这些工具的组合使用，为软件开发提供了强大的支持。<br />

<br />
<span STYLE="font-weight: bold;">持续集成工具的分类和功能</SPAN><br />
<br />
一般来说，持续集成工具可以分成两大类：自动化构建工具和构建计划安排工具。<br />
<br />
自动化构建工具有这样一些基本功能：代码编译、组件打包、程序执行和文件操作。编译源代码是构建的主要工作之一，为了提高效率，编译应该根据相应的源代码是否发生改变而有条件地执行。组件打包是将编译的结果和其他需要包含的文件组织在一起，形成可以部署的组件。构建工具应该知道何时需要重新打包。程序执行是指构建工具能够在它支持的平台上，调用所有提供命令行接口的程序。构建工具应该支持创建、拷贝、删除文件和目录等操作。<br />

<br />
某些自动化构建工具还有一些扩展功能：执行开发者测试、版本控制工具集成、文档集成、部署功能、代码品质分析、支持扩展、多平台构建、加速构建。虽然构建工具可以通过命令行执行的方式来集成构建工具和测试工具，但如果它提供更直接的集成方式，开发者就更省力。同样，如果构建工具能够直接与版本控制工具集成，开发者也会觉得更方便。文档集成是指构建工具能够自动从源代码中抽取并生成API文档。构建工具还可以将打包好的组件自动部署到目标测试环境中去。构建工具一般通过一些第三方插件，支持对代码品质进行分析。而提供插件接口，是构建工具实现可扩展性的通用方式。如果您开发的软件需要在多个平台上构建并测试，那么构建工具对多平台的支持就会带来极大的方便。对于较大的代码集，一次构建可能需要好几个小时，这为持续集成带来了一些挑战。有的构建工具支持加速构建，即在多个构建服务器的多个处理器上进行分布式构建。<br />

<br />
常见的自动化构建工具包括Ant、NAnt、MSBuild、make、Maven、Rake等。<br />
<br />
构建计划安排工具有这样一些基本功能：构建执行、版本控制集成、构建工具集成、提供反馈、为构建打上标签。构建计划安排工具的核心功能就是在特定时间执行自动化的构建，这可以通过轮询版本控制库、计划驱动或事件通知等方式来实现。大部分构建计划安排工具都支持大多数流行的版本控制系统，也支持大多数流行的构建工具。构建计划安排工具至少支持通过电子邮件提供反馈信息，有一些工具可以通过即时消息、手机短信或其他设备来提供反馈。大多数构建计划安排工具会提供某种类型的升序计数，作为构建版本的标签。<br />

<br />
某些构建计划安排工具还有一些扩展功能：支持项目间依赖关系、提供用户界面、制品发布、安全。如果项目间存在依赖关系，您可能希望在被依赖的项目重新构建时，重新构建依赖于它的项目。设计良好的用户界面会在工作时为您节约时间。制品发布是指除了得到可部署的组件之外，一些成熟的某些构建计划安排工具可以将文档、测试结果、品质分析结构和其他测量指标数据格式化，便于查看。有一些工具提供了身份认证和授权等安全方面的功能，允许您指定谁能查看结果和修改配置。<br />

<br />
常见的构建计划安排工具包括AnthillPro、Continuum、CruiseControl、CruiseControl.NET、Draco.NET、Luntbuild、Hudson等。<br />

<br />
<span STYLE="font-weight: bold;">下面介绍两个颇具代表性的工具：Ant和Hudson。</SPAN><br />
<br />
<span STYLE="font-weight: bold;">Ant</SPAN>是Java构建工具的事实标准，一般建议，不论项目团队成员使用哪种集成开发环境，项目都要有一个可以脱离IDE执行的Ant脚本。Ant采用插件式的设计结构，通过不同的插件来实现各种任务，其任务分类如表1所示。<br />

<br />
<ul>
<li>Archive Tasks :
打包解包任务，支持的格式包括：BZip2、Cab、Ear、GZip、Jar、Rpm、Tar、War、Zip。</LI>
<li>Audit/Coverage Tasks :
JDepend任务，调用JDepend实现代码静态分析，针对每个Java包生成设计品质指标数据。</LI>
<li>Compile Tasks : 编译任务，实现对Java、JSP、NetRexx等源文件的编译。</LI>
<li>Deployment Tasks : 部署任务，实现在JavaEE服务器上热部署。</LI>
<li>Documentation Tasks : 文档生成任务，生成javadoc文档、Apache
Stylebook文档。</LI>
<li>EJB Tasks : EJB任务，提供对1.x和2.x的EJB的支持，并支持不同供应商的应用服务器。</LI>
<li>Execution Tasks :
执行任务，包括对子项目调用Ant、调用同一脚本中的另一个target、执行系统提供的命令行程序、执行Java程序、暂停和并行同步执行等功能。</LI>
<li>File Tasks : 文件任务，实现对文件和目录的操作。</LI>
<li>Java2 Extensions Tasks : Java2
扩展信息任务，对jar包中的版本、供应商等扩展信息进行检查和操作。</LI>
<li>Logging Tasks : 日志任务，将构建过程事件记录到文件中。</LI>
<li>Mail Tasks : 邮件任务，发送SMTP邮件。</LI>
<li>Miscellaneous Tasks : 其他任务，各种或许会用到的小任务，例如播放wav文件。</LI>
<li>.NET Tasks :
.NET任务，支持执行.NET程序、执行NUnit测试、调用NAnt、调用MSBuild、调用WiX工具。</LI>
<li>Pre-process Tasks :
预处理任务，实现编译之前的一些预处理。例如调用ANTLR、JavaCC、Native2Ascii等程序。</LI>
<li>Property Tasks : 属性任务，对脚本中的属性变量进行判断和操作。</LI>
<li>Remote Tasks : 远程任务，支持FTP、Rexec、Scp、SSH和Telnet。</LI>
<li>SCM Tasks :
SCM任务，支持各种配置管理（版本控制）软件，包括CVS、ClearCase、Continuus、Visual
SourceSafe、Perforce、PVCS、SourceOffSite和StarTeam。</LI>
<li>Testing Tasks : 测试任务，支持执行JUnit测试。</LI>
</UL>
<br />
以上介绍的只是Ant发行版所带的一些任务。由于Ant采用的是插件结构，所以开发者可以开发自己需要的Ant任务，支持各种工具，如FindBugs、TestNG等其他代码检查工具和测试工具。早期的Ant没有很好的依赖关系支持，后来则通过Ivy弥补了这一缺点。<br />

<br />
关键是Ant为我们提供了一个跨平台的Java构建工具，为持续集成提供了根本的支持。对于Java开发者来说，如果不想采用Ant，也可以考虑采用Maven。<br />

<br />
<span STYLE="font-weight: bold;">Hudson</SPAN>是一个开放源代码的CI服务器，受到世界各地各种规模和类型的开发团队的欢迎。关键是因为它非常易于安装和使用，提供了灵活的配置方式和复杂的功能，同时支持Java项目和非Java项目，由强大的Hudson社区提供技术支持。<br />

<br />
简而言之，Hudson不仅仅是一个CI服务器，它的可扩展架构使它不仅是一个构建管理系统，也成为一个通用的开发生命周期管理系统，让开发者能够完成提升基线、打标签、执行工作流、根据依赖关系追踪变更、监视并图示测试结果、查看代码覆盖率和违反编码标准的情况等任务。<br />

<br />
Hudson是最活跃，成长最快的开源社区之一，目前每周下载达4000次，有超过2万个在工作的安装实例。它的开发者超过160人，贡献的工作量超过137人年，目前已发布了超过300个发行版本。Hudson实际上是现在世界上最受欢迎的开源CI服务器。<br />

<br />
Huddon的主要优点包括：<br />
<br />
<ul>
<li>易于安装。只要执行“java &ndash;jar
hudson.war”，或者将hudson.war部署到应用服务器上就可以了，不需要其他的安装工作，也不需要建立数据库。</LI>
<li>易于配置。所有东西都通过Web GUI界面来配置，不需要手工修改XML文件。</LI>
<li>
支持分布式构建。Hudson支持将构建和测试负载分布到多台机器上，图2是Apache采用Hudson的分布式构建功能。</LI>
<li>
支持环境配置矩阵。Hudson支持在不同的环境配置下执行相同的任务，例如不同的JDK版本、不同的操作系统、不同的数据库。执行的结果可以汇总在一起。</LI>
<li>支持JUnit/TestNG测试报告。测试的结果可以分标签列出、汇总，并与历史信息一同显示。历史趋势可以显示在图中。</LI>
<li>
追踪依赖关系。Hudson追踪记录哪次构建生成了哪些jar，某次构建使用了哪些版本的jar，即使这些jar包来自于外部也可以。</LI>
</UL>
<br />
Hudson通过大量的插件来实现其丰富的功能，这些插件大致可以分为以下几类：<br />
<br />
<ul>
<li>
SCM。Hudson缺省支持CVS和Subversion，通过安装插件支持Accurev、Bitkeeper、ClearCase、Git、Mercurial、Perforce、StarTeam、Synergy等</LI>
<li>构建触发器。可以通过IRC、Ivy、Jabber、Join、Locks and
Latches、Navigator来触发执行构建。</LI>
<li>构建工具。缺省支持Ant、Maven、shell scripts和Windows 批处理命令，通过安装插件支持batch
tasks、Gant、Gradle、Grails、Groovy、Jython、Kundo、MSBuild、Phing、Powershell、Python、Rake、Ruby、SCons、SCTMExecutor,Selenium等。</LI>
<li>构建包装。对构建的方式进行一些控制，如并发同步、启停虚拟机等。包括Hudson Centralized Job
Action、Hudson Distributed Workspace Clean、Locks and Latches、M2
Extra Steps、M2 Release、Release、VMware、Xvnc、Zen Timestamp等。</LI>
<li>构建通知。缺省支持电子邮件通知，通过插件支持Campfire、Google Calendar、HudsonTracker
(RSS feeds)、IRC、Jabber、Nabaztag、SameTime、Status Monitor、The new
Emailer、TuxDroid、Twitter等。</LI>
<li>Slave启动和控制。缺省支持JNLP和命令行，通过插件支持SSH。</LI>
<li>
构建报告。缺省支持JUnit、javadoc和FindBugs，通过插件支持CCCC、Checkstyle、Clover、DRY、Emma、Gallio、Gnat、Grinder、Japaex、JavaNCS、JavaTest
Report、MSTest、N Cover、NUint、Plot、PMD、PureCoverage、Ruby
metrics、Selenium AES、Selenium hq、Serenitec、SLOCCount、Task
Scanner、Testability Explorer、Violations、Warnings、WebTest
Presenter等。图3是Sonar生成的项目报告的样例。</LI>
<li>集群管理/分布式构建。支持DistFork、Hadoop、PXE、Selenium、Swarm等。</LI>
<li>制品上传。支持FTP-Publisher、java.net uploader、SCP,SFEE、SVN等。</LI>
<li>身份认证和用户管理。支持操作审计追踪、LDAP、MySQL认证等。</LI>
</UL>
<br />
工欲善其事，必先利其器。人是工具的主宰。A fool with a tool is still a
fool（傻子拿着工具还是傻子）。人们总是在学习工具、使用工具、创造更好的工具，以期提高工作的效率和品质。人要有智慧，工具要先进。<br /><br /><img width="34" height="17" src="http://simg.sinajs.cn/blog7style/images/special/1265.gif">&nbsp;&nbsp;<a href="http://t.cn/zO1XLB6" target="_blank">秀萌宝照片，酷赢“拉比盒子”</a>&nbsp;&nbsp;<a href="http://union.9173.com/pub?p=1&u=1008" target="_blank">“警告：您的主城已被占领！！”</a>&nbsp;&nbsp;<a href="http://qing.weibo.com/fancy.html" target="_blank">发现兴趣所在，玩转新浪Qing！</a>]]></description>
            <author>人月神话</author>
            <category>转载文章</category>
            <comments>http://blog.sina.com.cn/s/blog_493a845501014r9r.html#comment</comments>
            <pubDate>Mon, 14 May 2012 22:22:33 +0800</pubDate>
            <guid>http://blog.sina.com.cn/s/blog_493a845501014r9r.html</guid>
        </item>
        <item>
            <title>对eTom过程框架的再认识</title>
            <link>http://blog.sina.com.cn/s/blog_493a845501014fim.html</link>
            <description><![CDATA[<a href="http://blog.photo.sina.com.cn/showpic.html#url=http://s6.sinaimg.cn/orignal/493a8455tbf5bad04ea05" TARGET="_blank"><img SRC="http://s6.sinaimg.cn/middle/493a8455tbf5bad04ea05&amp;690" WIDTH="597" HEIGHT="330" NAME="image_operate_34671336301749604" /></A><br />
<br />
首先来看纵向，为电信运营商的完整生命周期。如果是传统的制造型企业其对应的是核心价值链模型，前面来看都类似即战略，规划，产品，产品后对应到具体的交付和后续售后服务环境。对于运营型企业，产品即服务，用户要的不是产品而是产品提供的能力，因此对运营层面进行细化，包括了运营支撑，实施，保障和计费。以构成电信运营商完整的生命周期。<br />

<br />
在eTom模型中，我们又把纵向分为两个大的阶段，即第一阶段为战略，基础设施和产品；第二阶段为运营。第一阶段的目的是战略和业务目标驱动，推进基础设施建设，通过产品生命周期管理形成产品；而第二阶段即对产品进行运营形成服务能力并产生收益。对传统制造型企业强化第一阶段，而运营型企业更加关注第二阶段。所有第一阶段的工作都是为运营并产生价值而服务。<br />

<br />
在前面谈企业架构，过程框架体系的时候可以看到，很多在最终形成框架体系的时候都是两维度的矩阵模型。对于CBM业务架构，可以看到纵向仍然为生命周期，横向为执行管理决策三层。在谈到项目管理知识体系时候，纵向为生命周期，横向为9大知识体系。在谈cmmi的时候纵向为PA过程域，横向为软件工程，项目管理，过程支撑三大域。再谈到IT应用架构时候，纵向为业务系统，横向为技术平台和产品三层。<br />

<br />
再转过来看eTom的过程框架，横向为供应链，资源，服务，产品四层。可以讲整个过程框架的精髓不在于纵向生命周期，纵向生命周期仅仅是价值链分析方法的而一个延伸。而在于横向的分层，解耦和逐层递进关系上。底层的供应链为最底层的基础设施支撑层，最终形成的是价值维度的资产。资产最终转化为资源，资源分为物理资源和逻辑资源，资源本身已经是能力层面的概念，资源即能力。最上层为产品或客户，为最终面对用户的层面，对于运营商而言我们采购的产品本身即是一种服务能力，只是我们对各种服务能力进行规划，设计和组装，形成了可以独立计价和运维支撑的产品。<br />

<br />
客户购买的是产品，而资源提供产品需要的能力，两者通过中间层服务有效的衔接起来。产品需要多种服务，而服务本身有来自于多个资源能力。通过服务层真正实现了产品和资源的解耦。而通过资源层又实现了逻辑能力和物理基础设施的解耦。真正实现了资源有效的规划，分配和调度，发挥资源的最大价值。可以反过来看下云计算三层之间的逻辑关系，你会发现完全是同样的道理。这个可以看我前面的一篇文章。从eTom模型思考云计算运营支撑系统建设
。<a HREF="http://blog.sina.com.cn/s/blog_493a84550100s305.html" TARGET="_blank">http://blog.sina.com.cn/s/blog_493a84550100s305.html</A><br /><br /><img width="34" height="17" src="http://simg.sinajs.cn/blog7style/images/special/1265.gif">&nbsp;&nbsp;<a href="http://t.cn/zO1XLB6" target="_blank">秀萌宝照片，酷赢“拉比盒子”</a>&nbsp;&nbsp;<a href="http://union.9173.com/pub?p=1&u=1008" target="_blank">“警告：您的主城已被占领！！”</a>&nbsp;&nbsp;<a href="http://qing.weibo.com/fancy.html" target="_blank">发现兴趣所在，玩转新浪Qing！</a>]]></description>
            <author>人月神话</author>
            <category>随笔文章</category>
            <comments>http://blog.sina.com.cn/s/blog_493a845501014fim.html#comment</comments>
            <pubDate>Sun, 06 May 2012 18:32:03 +0800</pubDate>
            <guid>http://blog.sina.com.cn/s/blog_493a845501014fim.html</guid>
        </item>
        <item>
            <title>诸法无我</title>
            <link>http://blog.sina.com.cn/s/blog_493a845501014f4s.html</link>
            <description><![CDATA[一切有为法，如梦幻泡影，都是无常变化的，我们执着的原因有两个，一个是认为有一个真实存在的自我，一个是认为有一个真实存在的外物，内在心乱而外在着想，自然执着。而无我则是要我们去除执着，一个去我执，一个去法执，既不执着于自我，也不执着于外在才是真正的无我。<br />

<br />
无我执首先则是降低欲望，训练专注。为学日益，为道日损，少私寡欲和抱朴守拙都是降低欲望，这个可以让你不再受到太多外界复杂的事物的干扰，能够真正找寻一份平静，能够专注到一件事情上面来。专注和去我并不矛盾，只有专注到一件事情上面后，后面需要舍弃的仅仅是一个点而已而不是一个面。你越专注，你贪嗔痴的东西越少，或者说内心杂思越少，你越容易心静下来。<br />

<br />
吾有三宝，持而保之。一日慈，二日俭，三日不敢为天下先。而这正是降低欲望所需要的。慈是利他，俭是慎独，不敢为天下先去我。梦里有时终须有,梦里无时别强求，你强求的越多欲望越强烈，自我情绪越难以控制。事物发展有自身的因果，不要执着于自我，也不要执着于他人，更不要执着于外物，一切随缘而已。<br />

<br />
无我是一种利他精神，凡事多站在他人的角度思考一下，多想着方便他人而不是自己，能够付出的地方多付出一点而不是一味的想着索取。多学会倾听自然会减少主观臆断。慈悲心，慈为能够分享自己的快乐，悲为能够为他人分担忧伤。勿以善小而不为，每个人内心都有一份善，只要持之以恒，自然会以小积多。<br />

<br />
无我是一种正确的内观，我们有太多的仇恨，嫉妒，虚荣，傲慢，自私。这些都是我们天生就有的吗？我想很多还是后天所形成和发展的，我们太多受到他人的影响，你太在乎别人怎么看你，太想在一个群体社会里面表现自己，而忽视了自己如何看待自己？很多时候你发现你自己都找不到一个真实的自我，看到的只是一个戴着面具的假我，这是一件很悲哀的事情。一个人真正的内心强大是可以去影响外界，而不是太多的受外在负面因素的影响，而我理解的内观就是取发现我们自己善的一面，慈悲的一面，而不是简单的一句一味的适应社会。<br />

<br />
放下屠刀，立地成佛，你欲望越强烈，你越难真正的放下。而欲望本身是一个无休无止的东西，或许对你根本就没有一天所有的欲望都能够达成。生活真正的就是一个过程，而不是一个目标。<br /><br /><img width="34" height="17" src="http://simg.sinajs.cn/blog7style/images/special/1265.gif">&nbsp;&nbsp;<a href="http://t.cn/zO1XLB6" target="_blank">秀萌宝照片，酷赢“拉比盒子”</a>&nbsp;&nbsp;<a href="http://union.9173.com/pub?p=1&u=1008" target="_blank">“警告：您的主城已被占领！！”</a>&nbsp;&nbsp;<a href="http://qing.weibo.com/fancy.html" target="_blank">发现兴趣所在，玩转新浪Qing！</a>]]></description>
            <author>人月神话</author>
            <category>随笔文章</category>
            <comments>http://blog.sina.com.cn/s/blog_493a845501014f4s.html#comment</comments>
            <pubDate>Sun, 06 May 2012 11:30:46 +0800</pubDate>
            <guid>http://blog.sina.com.cn/s/blog_493a845501014f4s.html</guid>
        </item>
    </channel>
</rss>

