<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>持续交付</title>
	<atom:link href="http://www.continuousdelivery.info/index.php/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.continuousdelivery.info</link>
	<description>软件是一门艺术，交付是一门学问，持续交付则是一种对卓越的追求。</description>
	<lastBuildDate>Tue, 08 May 2012 06:21:35 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1.3</generator>
		<item>
		<title>剖析“持续交付”：五个核心实践</title>
		<link>http://www.continuousdelivery.info/index.php/2012/02/06/5-practices-for-cd/</link>
		<comments>http://www.continuousdelivery.info/index.php/2012/02/06/5-practices-for-cd/#comments</comments>
		<pubDate>Mon, 06 Feb 2012 09:01:29 +0000</pubDate>
		<dc:creator>乔梁</dc:creator>
				<category><![CDATA[持续交付]]></category>
		<category><![CDATA[MVP]]></category>
		<category><![CDATA[validated learning]]></category>
		<category><![CDATA[最佳实践]]></category>
		<category><![CDATA[精益创业]]></category>
		<category><![CDATA[翻译]]></category>

		<guid isPermaLink="false">http://www.continuousdelivery.info/?p=258</guid>
		<description><![CDATA[​ 原文发表于 InformIT 持续交付 是一种软件开发策略，用于优化软件交付流程，以尽快得到高质量、有价值的软件。这种方法让你能更快地验证业务想法，通过直接在用户那里进行试验，做到快速迭代。 尽管《持续交付》一书主要讲的是工程实践，但持续交付的概念对整个产品交付过程都有重大意义，包括对特性的&#8221;fuzzy front end&#8221;、设计和分析的意义。 持续交付的一般性原则如下： 与其设计一大堆特性，再策划一个持续数月的版本发布，不如持续不断地尝试新想法，并独立发布给用户。通过充分思考，即便很大的特性或者大范围的变更，也能够通过一系列小步骤得到更快反馈，而且一旦你认为有必要停下来的话，可以随时停下来。利用 跨功能团队 在几小时或几天内交付这些小且增量式的功能，就能比竞争者有更多的创新，将投资回报最大化。 持续交付五个关键实践，为你建立一个从猜测到持续反馈的最有效途径，它们就是： 从最小可行产品（MVP）开始——Start with a minimum viable product 衡量新特性的价值——Measure the value of your features. 做恰好充分的预先分析——Perform just enough analysis up front. 少做——Do less. 用户故事中要包括特性开关——Include feature toggles in your stories. Start with a Minimum Viable Product (MVP) &#8230; <a href="http://www.continuousdelivery.info/index.php/2012/02/06/5-practices-for-cd/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>​</p>
<p><em>原文发表于 <a title="持续交付五个实践" href="http://www.informit.com/articles/article.aspx?p=1829417" target="_blank">InformIT</a></em></p>
<p>持续交付 是一种软件开发策略，用于优化软件交付流程，以尽快得到高质量、有价值的软件。这种方法让你能更快地验证业务想法，通过直接在用户那里进行试验，做到快速迭代。 尽管<a href="http://www.informit.com/store/product.aspx?isbn=0321601912">《持续交付》一书</a>主要讲的是工程实践，但持续交付的概念对整个产品交付过程都有重大意义，包括对特性的&#8221;fuzzy front end&#8221;、设计和分析的意义。</p>
<p>持续交付的<strong>一般性原则</strong>如下：</p>
<p>与其设计一大堆特性，再策划一个持续数月的版本发布，不如持续不断地尝试新想法，并独立发布给用户。通过充分思考，即便很大的特性或者<a href="http://continuousdelivery.com/2011/05/make-large-scale-changes-incrementally-with-branch-by-abstraction/">大范围的变更</a>，也能够通过一系列小步骤得到更快反馈，而且一旦你认为有必要停下来的话，可以随时停下来。利用 <a href="http://continuousdelivery.com/2011/12/organize-software-delivery-around-outcomes-not-roles/">跨功能团队</a> 在几小时或几天内交付这些小且增量式的功能，就能比竞争者有更多的创新，将投资回报最大化。</p>
<p>持续交付<strong>五个关键实践</strong>，为你建立一个从猜测到持续反馈的最有效途径，它们就是：</p>
<ul>
<li>从最小可行产品（MVP）开始——Start with a minimum viable product</li>
<li>衡量新特性的价值——Measure the value of your features.</li>
<li>做恰好充分的预先分析——Perform just enough analysis up front.</li>
<li>少做——Do less.</li>
<li>用户故事中要包括特性开关——Include feature toggles in your stories.</li>
</ul>
<h2><span id="more-258"></span>Start with a Minimum Viable Product (MVP)</h2>
<blockquote><p>“假如你没有因产品首发版本的寒酸而感到尴尬，就说明该产品的发布实在是太晚了。 ” Reid Hoffman, cofounder and chairman of LinkedIn (参见“<a href="http://greylockvc.com/2011/03/22/ten-entrepreneurship-rules-for-building-massive-companies/">建立大公司的十大创业原则</a>”）</p></blockquote>
<p>如果你的项目一启动，就有一大堆<a href="http://crankypm.com/2009/02/video-chose-product-marketing-deal/">需求文档</a> 放在项目经理的桌上，那你已经失败了。<a href="http://theleanstartup.com/">精益创业运动</a>的核心思想中，关键的一个就是<a href="http://www.informit.com/articles/article.aspx?p=1750200">最小可行性产品(minimum viable product</a>,缩写为MVP)， 即为验证你的业务猜想而需做出的最小工作量。</p>
<p>当然，在制造业，MVP的概念已经有数十年的历史——它们被称作原型（prototypes）。在使用原型时，你不必把你的MVP展示给全世界的所有人，只要选择其中一组测试（beta）用户就行了。甚至用一个尚无法工作的软件都行——你可以创建一个<a href="http://www.pretotyping.org/">pretotype</a>，来收集信息，一行代码也不必写。</p>
<p>假如对受众来说，第一个版本至关重要，你也完全可以向全范围的用户展示经过精心打造的更完美的产品。例如，某个公司用别的商标品牌发布了它的iPhone应用的一个MVP版本。只是为了得到具有统计意义的重要反馈，即它的业务规划是否能成功。而次要目标是验证一下该软件的交付流程。</p>
<p>找到MVP如何运作至关重要的一点是，需要一个由业务人员和技术人员组成的跨功能团队（cross-functional team）。这个团队中的角色包括用户体验设计（User Experience Designer，UX），分析、测试、开发、运营和基础设施建设。当然，一个人可以承担多个角色，所以也不是非要很多人，才能完成一件事。</p>
<p>由于一个小团队在数周内（而不是一两个月的时间里）就可以完成MVP，所以此时也不需要很多仪式，因为你不必象赌博一样，押上整个公司，或一大笔钱。</p>
<h2>Measure the Value of Your Features</h2>
<blockquote><p>&#8220;度量是产品的一部分&#8221; John Allspaw, VP of Technical Operations, <a href="http://www.etsy.com/">Etsy</a> (参见&#8221;<a href="http://www.usievents.com/en/conferences/8-paris-usi-2011/sessions/968-john-allspaw">Building Resiliencein Web Development and Operations</a>&#8220;).</p></blockquote>
<p>​ <a href="http://www.peachpit.com/store/product.aspx?isbn=0321804813">精益创业</a>中<a href="http://www.peachpit.com/store/product.aspx?isbn=0321804813">另一个核心概念</a>是 <a href="http://blogs.hbr.org/cs/2010/02/entrepreneurs_beware_of_vanity_metrics.html">验证性学习（validated learning</a>），即通过收集产品被真正使用后的衡量指标，而不是通过对用户的提问来验证效果。正是电视剧《<a href="http://en.wikipedia.org/wiki/House_%28TV_series%29">Dr. Gregory House</a>》中，他喜欢说的那样，人们会说慌的——尽管更文雅一些，我们可以说他们不知道他们想要什么。把你的用户当做是试验对象，而不是那些聪明的代言人（intelligent agents）。</p>
<p>你要能回答下面这样的问题：</p>
<ul>
<li>我们在产品上所做的这些修改是否让更多的人注册了，逗留时间增加了，还是增加了收入? Or is it time to <a href="http://www.slideshare.net/startuplessonslearned/david-binetti-lean-startup-votizen-pivot-at-sllconf-2011">pivot</a>?</li>
<li>在做A/B测试时，该特性在哪个版本的效果更好？</li>
<li>所有的系统指标看上去都不错，一个用户说我们的网站不能用。难道是我们的网站坏了吗？</li>
<li>我们产品中的哪些特性是收入的最大来源？</li>
</ul>
<p>你不必在Apache的日志中搜罗信息，也不必试图从那些辅助功能上回溯，或利用定制化查询，就应该能够回答这些问题。这些问题应该看一眼仪表盘（Dashboard）就能知道，而且，这些信息应该是完全可审计的。</p>
<p>在Eric Rie的《精益创业》<em>The Lean Startup: How Today&#8217;s Entrepreneurs Use Continuous Innovation to Create Radically Successful Businesses(Crown Business, 2011)</em>一书中，他提到了 <a href="https://grockit.com/">Grockit</a>的故事:</p>
<blockquote><p>遵循精益制造中的 <a href="http://en.wikipedia.org/wiki/Kanban">kanban</a>原则， […]Grockit改变了产品优先级评估流程。在这个新流程中， 直到验证性学习（ validated learning）时，用户故事才算完成。.所以，一个用户故事要经历四个阶段：在product backlog中，正在实现中，完成（从技术角度看特性是完成了），以及验证中。验证被定义为：“第一时间知道某个用户故事是不是一个好主意&#8221; 。这种验证通常是以某种隔离测试来展示客户行为的变化，当然也包括客户访谈或问卷调查。</p></blockquote>
<p>只有当度量项被放在用户故事中一起完成时，这种学习方式才有可能。</p>
<p>看上去，这一原则可能是针对web应用的，事实上，对于嵌入式系统和用户自行安装的产品也是同样道理。为了远程调试和失败报警的目的，以及理解用户的使用模式，所有类型的系统需要收集这些度量项。</p>
<h2>Perform Just Enough Analysis Up Front</h2>
<blockquote><p>&#8220;你要知道，当团队在编码之前试图完成规格说明的收集时，你就不是在做迭代开发。” Bas Vodde, &#8220;<a href="http://blog.odd-e.com/basvodde/2011/02/history-of-nokia-test.html">History of Nokia Test</a>.&#8221;</p></blockquote>
<p>一旦你想到了一个点子，是一个最小可行产品（minimum viable product），你就要开始交付软件了。第一步是分析。但是backlog中所有的用户故事不必被全面分析。因为那么做，这也是一种浪费。为了全面分析用户故事，你要从客户、开发人员、测试人员、用户体验设计和用户那里得到信息。如果团队在花大量时间去收集这些信息，那么他们的这些工作实际上还没有交付有价值的功能，也无法从那些使用该系统的用户中得到真正的反馈。</p>
<p>那么，需要做多少前置分析呢？在开始开发一个用户故事之前，我们只关心三件事：</p>
<ul>
<li>交付用户故事的marginal value是什么?</li>
<li>交付用户故事的marginal 成本是什么？</li>
<li>我们是否有足够的信息开始开发用户故事？</li>
</ul>
<p>前两个问题是很重要的，这样当有交付能力时，我们就可以决定我们应该做哪个用户故事。为了做到这一点，需要找到哪个用户故事会让经济产出最大化。而后两个问题是紧密相关的，因为评估某个用户故事的成本所需信息的数量通常要比你开始实现它所需的信息量多。但是，象我的同​事Peter Gillard-Moss曾经和我说的：至少需要一个<a href="http://dannorth.net/whats-in-a-story/">验收条件。</a></p>
<p>&#8220;刚好够用的分析”这个纪律需要在整个项目生命周期持续进行，并要强调创建小的、增量式的用户故事。这会把我们带到下一个实践： doing less。</p>
<h2>Do Less</h2>
<blockquote><p>&#8220;[如果]你发现自己没有空间放卡片，就使用更小的卡片.&#8221; <a href="http://www.c2.com/cgi/wiki?PhlIp">PhlIp</a> (see &#8220;<a href="http://tech.groups.yahoo.com/group/extremeprogramming/message/67908">Re: [XP] Re: Token definition in User Stories</a>&#8220;).</p></blockquote>
<p>在敏捷分析中，也许最流行的短语就是<a href="http://xp123.com/articles/invest-in-good-stories-and-smart-tasks/">Bill Wake的INVEST原则。</a>Wake认为，好的用户故事是独立的（independent），可协商的（negotiable）, 有价值的（valuable）,可估计的（estimable）,小的（ small）,和可测试的（testable）。我想说的是：“小的（small）”。</p>
<p>大家常常认为，特性 features和 stories是可以互换的。有时候人们认为一个特性就是需要花两星期完成的工作。我记得在某个项目里，一个用户故事就是一个几页长的word文档。</p>
<p>XP让人们把用户故事写在一个3 [ts] 5的索引卡片上，这是有原因的。用户故事不应该几天内还做不完。超过一个星期的工作就是太长了，应该被分成更小的工作。为什么呢？</p>
<ul>
<li>为了确保我们可以从用户那里得到对我们工作产出的瞬时反馈，以便我们可以发现我们做的事情是否有价值。</li>
<li>为了验证我们是否做完了——不只是“开发完成”，而是可发布——以便我们可以展示我们真实的工作进度。</li>
<li>为了避免完成大块工作后再集成、测试和发布带来的痛苦。</li>
<li>为了确保我们不断地测试并改进我们的交付过程</li>
</ul>
<p>常见听到的反对意见是，我们不能在几天内就完成有价值的事儿。我认为，这说明了两件事儿。一是缺乏想象力，二是没有理解“哪些东西组成了价值”。正如我之前提到的，只有通过向用户展示，一个用户故事的价值才能被衡量。的确，你无法在一两天之内就完成整个特性。是，你可以完成该特性的一个很小的部分，并得到反馈。比如说，你正在做一个网上订酒店的网站，打算增加一个特性，让人们能选择他们是否需要早餐。你不必为所有的酒店或所有的合作方创建这个功能。相反，最开始的一个用户故事只是为某个酒店增加这样的特性，而且也不需要什么配置选项，然后在进行下一步时，为这种特性的可行性收集一些反馈。</p>
<p>无论你做什么，都不要把特性按照解决方案中的那些分层概念来划分用户故事，比如一个故事是实现持久层，另一个故事是实现业务逻辑，还有一个是实现UI。用户故事应该总是很小的纵向切分。如果你不得不做一些集成工作，也要聚焦于让这种切片尽可能薄。比如，假如作为功能的一部分，你要传递一系列信息的消息给另外一个系统，那么你第一个用户故事应该是传递那个最简单的消息，以便第一次实现就做到“端到端”的集成。</p>
<p>通过不断对功能的分解，直到找到你可以向用户展示的功能最小集，来强迫自己找到某个特性的真正价值（并从中学习）是一个很困难，但也极其有价值的学问。你可以使用得到的反馈来决定下一步（两三天的工作）的工作是什么，或者是否不要再按当前的样式开发这个特性，因为它并没有象你想的那么有价值。</p>
<p>时刻牢记一点，即软件开发中，最大的浪费就是无用的功能——超过50%的功能从来没有或很少被使用（详见<a href="http://martinfowler.com/articles/xp2002.html#BuildOnlyTheFeaturesYouNeed">这里</a>）。</p>
<p>不要问下面这类问题：“我们还要加点什么放在这个特性里，才能确保大家喜欢它？”或者“我们还要在当前这个版本中增加哪些功能，才能算一个真正伟大的产品？”。相反，需要问这样的问题：“我们现在就能交付我们手里的东西吗？如果不能，那是为什么呢？”少做点儿，你就不再太关注你付出的努力，而是关注于从你的用户那里学到了什么。</p>
<p>​你可能想做一堆用户故事之后才把某个特性展示给所有人。但总是要在发布和确保发布内容满足质量要求（由用户决定）之间做出平衡。所以你需要feature toggles。</p>
<h2>Include Feature Toggles in Your Stories</h2>
<blockquote><p>&#8220;现在，在<a href="http://www.facebook.com/">Facebook.com</a>网站上的代码中，已经包含了后六个月后将要发布的特性了。&#8221; Chuck Rossi (see <a href="http://techcrunch.com/2011/05/30/facebook-source-code/">TechCrunch discussion</a> about Rossi&#8217;s May 26, 2011 &#8220;<a href="http://www.facebook.com/video/video.php?v=10100259101684977&amp;oid=9445547199&amp;comments">Facebook Tech Talk</a>&#8220;).</p></blockquote>
<p>&nbsp;</p>
<p>如果你想提高发布的频率，将应用的部署和特性的发布解耦是关键。<a href="http://martinfowler.com/bliki/FeatureToggle.html">特性开关</a> 是一种模式，用于控制谁可以使用哪个特性。这样，即使软件中包含包含一两个故事，还不想公开的未完成特性，你也可以发布新版本。</p>
<p>Facebook的工具Gatekeeper让它可以动态控制谁能看到哪个特性。比如，将某个特性仅开放给10%的Facebook用户， 或者那些在Facebook工作的人，或者25岁以下的女性用户，或者是英国居民，等等。(Gatekeeper甚至有这样一个开关，可以让除了<a href="http://techcrunch.com/">TechCrunch</a>员工以外的所有人使用某个特性)。这使得Facebook的开发人员可以仅在某类人群中试验某个特性，并逐步向更多的人群扩展。</p>
<p>在将特性分解成多个用户故事时，特性开关是一种非常重要的约束条件。对于使用开关来说，常见的反对意见是： &#8221;有些用户故事会涉及所有的用户界面。如果对其使用特性开关的话，需要增加很多工作。&#8221; 答案是：以一种非常容易增加特性开关的方式将特性分解成用户故事。</p>
<p>特性开关应该是用户故事中的一等公民。<a href="http://www.orbitz.com/">Orbitz</a>的一个团队在其用户故事中有特性开关，那么他们在实现这个用户故事时的第一个任务就是加一个开关。特性开关是用户故事价值的一部分，当然，由于增加开关所带来的开发成本也在估算时考虑了。如果增加开关的成本太高了，这就是一个信号，你的用户故事分解的不好。</p>
<p>除了能够做增量式地功能交付以外，特性开关还有另一个重要的用途。万一遇到未预期的负载过高，它们可以优雅地对在线服务进行降级（degrade），比如通过关闭资源密集型的特性，如推荐引擎。另外，当发布出了问题时，它们也可以让你马上关闭存在问题的特性，相当于做了一次回滚操作。</p>
<h2>Conclusions</h2>
<p>一种常见的软件项目失败模式是Don Reinertsen在他的书《The Principles of Product Development Flow: Second Generation Lean Product Development (Celeritas, 2009)》所说的“<em>large batch death-spiral</em>”，而product owners为了试图确保产品的成功，在项目进行中，增加越来越多的范围，从而导致成本显著增加，工期明显拖长。</p>
<p>持续交付让团队大幅度减少发布高质量软件的 transaction成本，所以你可以更频繁地发布，产品团队从而能够多用户那里得到更加丰富和迅速的反馈。但是，反过来，对于在整个软件交付流程中如何管理工作流，你也需要改变一下思考方式。尤其强调的一点是，假如你正确地实施了持续交付，在用户那里验证新的主意时，技术人员就不再是一种约束了。使用传统的交付流程，则你不得不等上数个星期或都是数月，才能看到你的想法变成软件。通过增量式交付小的功能，并收集反馈，我们可以持续思考：“下一步我们应用做什么？”没有哪个团队达到这种转变后，还想再回到原有的工作方式上。</p>
<p>使用传统的交付方法，我们必须细心地挑选我们想实现哪些想法，因为软件交付的过程成本太高了。当然，那种审查流程也并不是基于真实数据的。然而，通过持续交付，我们就有了我的同事<a href="http://www.kumana.co.uk/">Darius Kumana</a>所说的一种 &#8221;创新失败的安全气囊&#8221;。在系统we can try crazily innovative ideas cheaply and safely at any stage in the evolution 演进的过程中，可以用廉价且安全的方式尝试那些异想天开的创新想法，通过仅将其开放给少量用户组，缓解可能失败的风险。 持续交付通过大幅度减少软件发布的风险来解放我们，把分析师带回他们本来的位置——全力创新。​</p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.continuousdelivery.info/index.php/2012/02/06/5-practices-for-cd/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>为什么要做持续部署？</title>
		<link>http://www.continuousdelivery.info/index.php/2012/01/20/imvu-why-contiuous-deployment/</link>
		<comments>http://www.continuousdelivery.info/index.php/2012/01/20/imvu-why-contiuous-deployment/#comments</comments>
		<pubDate>Fri, 20 Jan 2012 14:09:12 +0000</pubDate>
		<dc:creator>乔梁</dc:creator>
				<category><![CDATA[持续交付]]></category>
		<category><![CDATA[validated learning]]></category>
		<category><![CDATA[持续部署]]></category>
		<category><![CDATA[精益创业]]></category>

		<guid isPermaLink="false">http://www.continuousdelivery.info/?p=246</guid>
		<description><![CDATA[本文是《Lean Startup》一书的作者Eric 在2009年发表的一篇博文，他是IMVU的创始人之一。文中没有讨论如何做持续部署，而是讨论了一个更关键的问题：“IMVU为什么要做持续部署？”这也充分地表达了他关于“Learning from production and customer”的观点。 －－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－ 在我所倡导的Lean Startup所有实践中，没有哪个实践比持续部署更有争议（持续部署是指：让公司在几分钟内发布软件的过程，而不是几天或几个月才发布一次）。我之前所在的一个创业公司IMVU使用这个流程，平均每天部署50次。这也引发了一些争论，有些人说：这种快速发布流程会导致低质量的软件，或者阻碍公司的创新。假如我们能够接受由客户来评判，而不是专家的判定，那么，我想这些说法就很容易消散了。一个更为常见，且更为困难的问题是：如何回答那些只想知道这种持续部署是否可以用于他们自己的业务、行业或团队的人们。 IMVU的历史尤其引人关注。作为一个有数百万用户消费者的互联网公司，看上去可能与那些只有一小撮潜在客户的企业软件公司，或者那些客户要在软件发布前需要严格审核的计算机安全公司没有太多关系。我想，持有这种反对观点的人实际上没有真正明白持续部署的关键点，因为他们关注点都放在了具体的实现上，而不是通用原则。目前关于持续部署的文章都关注于“如何做”， 但我在这里想说的是“为什么做？”（如果你想了解如何开始做持续部署，请参见&#8221;五步实现持续部署&#8220;） 持续部署的目标是通过减少批量工作的大小，并加快团队工作的节奏，帮助开发团队在其开发流程中消除浪费。这使团队能够一直处于一种可持续的平稳流状态， 让团队更容易去创新、试验，并达到可持续的生产率。而且，这也很好地支撑了其它的持续改进系统，如５个Whys。在开发中，浪费的一个最大来源是“double-checking”。想像一下，在传统瀑布开发环境中的一个团队，没有持续部署、测试驱动开发或者持续集成。当开发人员想要提交代码时，就到了一个令人担心的时刻。他或她有两种选择：一是马上提交，二是再检查一下，确保不会出问题。两种选择都很有吸引力。假如马上提交的话，就可以说“提前完成任务了&#8221;。可是，如果提交后引起了问题，那么之前的工作速度必然要打折扣。他们为什么不再多花五分钟时间，确保自己的提交不会导致问题呢？事实上，开发人员如何应对这种问题是由他们的激励机制决定的，而激励机制是由团队文化决定的。导致问题后会受到多么严重的惩罚？谁最终会承担这些错误带来的成本？时间表有多么重要？团队是否以尽早完成工作来做评价？然而，在这种情况下，我们应该意识到，其实并没有所谓正确的答案。被这种选择性所折磨的人最终很可能哪种都做不好。结果，开发人员会走向两个极端：一些人认为应该尽快地完成事情，另一些认为应该细心地做工作检查。从长远来看，二者之间的任何一个中间状态都无法长久。一旦出了问题，无论你怎么去细心解释当时是如何做决定的，都不会令人满意。毕竟，你要么可以做得更快一些，要么可以做得更细心一些。要是你能提前知道问题多好呀啊？！事后再回头看看当时的那些评判，它们好象都存在问题。然而，从另一个角度上看，每种极端的做法都很容易起到自我保护作用。两种方式都有借口：“的确是有几个bug，但我一直在以一个安排得非常紧的时间表来完成任务，有几个bug也是再所难免的。”或者，“我知道你想快点完成这个事儿，但你要知道，我要确保绝对没问题的情况下才能交付给你，所以等一等是值得的。”这两个做法在开发团队中会发&#8221;派系&#8221;冲突，可能产生很多不愉快。经理开始注意到，哪类人在哪个小团队中，然后再依此来分派任务。当在最后一分钟拿到了某个新功能的请求，先找个牛仔完成它—— 然后，在下一个发布中再找个人（Quality Defenders）来&#8221;擦屁股&#8221;。两边都开始从他们各自的视角来思考：“那些家伙没有看到快速行动带来的经济价值，只在意他们那完美的架构图”，又或者， “那些家伙太懒了，根本没有专业精神。” 在我的职业生涯中，经常被找来调节双方的矛盾。在我看来，这些都真是太浪费啦。 其实，上述这种结果是完全符合逻辑的，因为对于那种大批量生产的开发流程来说，它迫使开发人员利用传统的“时间-质量-金钱，选其中两个的谬论”，在时间和质量之间进行权衡。因为得到的反馈很慢，所以由于​某个错误引发的损坏和做出决定之间有很长的时间，这也使人们很难从中学习。因为每个人都在最后的某个时间点同时做整个发布的集成工作（并没有尽早集成的激励机制）， 要在很大的时间压力下解决该集成过程中中发现的冲突。某些特性像泡沫一样，看上去做好了，很美，但不得不等到下一次发布才行。然而，一旦这些特性被推迟了，就会增加下次发布的工作范围。（“毕竟，我们有完整的发布周期，而这个特性几乎就要完成啦…”），这就会导致下一个时间压力等等。然而，在生产环境中代码运行的方式与其在测试或试运行环境中并不完全一样，这也导致每次发布之后马上就会有一系列的hot-fixes。这也会增加下一次发布的工作量，也就意味着每个发布周期从一开始就已经落后了。有很多次，当我访谈一个遇到这种情况的开发团队时，他们想让我帮助“fixing people&#8221;。这种现象心理学上叫做“基本归因错误 ”，人们倾向于认为其他人的行为来源于其基本属性，如他们的个性，道德准则，或士气 –甚至当受到所在环境的影响时，我们也会为自己的行为找借口。所以，在这种环境下的开发人员，他们的心灵深处也会认为其团队的其他开发人员也是行动缓慢的老学究或邋遢的码农。事实并不是这样的，他们只是让他们的动机搞砸了。你无法通过把所有工作都做得非常完美，来改变这种状况下的根本动因。做更靠谱的发布计划、估算、架构或者集成只能缓解症状。解决这种问题的一种传统做法是：在时间排期表中预留更多的空槽，增加额外的时间做集成，代码冻结，或类似的事情。事实上，大多数组织并不知道，在做时间估算时，开发人员到底已经为这种事情加入了多少Buffer。但是，这种缓冲没什么好处，因为，它只会让整个过程变得更慢。正象所有开发人员都会对你说：“时间太短啦”。实际上，额外的时间压力正是他们认为他们会遇到这些问题的原因。所以，我们要站在整个系统层面上找到解决方案，让团队冲出这种束缚。敏捷软件开发已经做出了巨大的贡献：持续集成帮助加快速了对缺陷的反馈速度；用户故事和看板减少了批量生产的大小；每日站会增加了节奏感。持续部署是另外一种类似的技术，它具有强大的动力让开发团队变得更好。 持续部署为什么会起作用？ 首先，持续部署将两种不同的“发布”概念区分开来。一种是工程师所说的：将代码部署到生产环境的过程。另一种是从市场人员的角度来看的：让用户看到。在传统的“批量及排队”这种开发模式中，两种概念是相联的。一旦新版软件被部署了，所有客户也就能看到它了。这就要求在部署之前，我们要在特定的试运行或测试环境中完成本次发布相关的所有测试。这就使得从写完代码开始，到生产环境部署这之间的这段时间里，由于某些未曾预料到的问题而令本次发布变得不可控。在这些开销中，由于市场发布与技术发布的合并，也让交付活动的协作开销急剧增加。而在持续部署环境下，一旦代码写完，就开始向生产环境进发。也就是说，我们经常只部署某个特性百分之一的功能，尽管客户可能要在很久之后才能看到它。事实上，一个新特性的绝大部分工作都是用户无法看到的。相反，这个特性与之前已完成的特性之间却有很多集成点。想像一下，当我们想要在系统中传递一个新增的参数时，就需要修改多个API。这些修改通常应该没有“副作用”，也就是说，它们不会影响当前系统的行为——这里要强调一下“应该”两个字。实际上，很多缺陷是由于那些修改中不常见或没有意识到的​副作用引起的。 对于那些只是影响生产环境中的配置参数的很小的修改来说，也是一样。尽快得到这种反馈是最好的，而持续部署恰好提供了这样的途径。持续部署也扮演了速度调解器的角色。每当部署流程遇到了一个问题时，就需要有人去诊断。在诊断期间，其他人就不能进行部署了。当团队已为部署做好准备，但部署流程被阻塞时，他们就可以马上去帮助诊断并修复部署问题。（相反的做法是团队其他人继续去写更多的代码，但是并不部署，那么这些新代码就会不断堆积，使批量变大，这对每个人都是一种损害）。对于那些通过度量个人效率来衡量其流程的团队来说，通常这个速度调解器是一种比较棘手tracky的调解。在这种环境中，每个工程师的主要目标是保持忙碌状态，写代码的时间尽可能地接近。不幸的是，这种视角忽视了团队的整个产出。即使你不采纳我所提倡的激进定义，比如“validated learning about customers”，让每个人都保持忙碌状态仍旧是局部优化。当你正在追踪和修复集成问题时，其它人写的代码很可能会由于冲突而不得不回滚。配置不匹配或多团队之间的冲突都可能会怒导致同样的结果。在这种情况下，对于整体生产率来说，最好是大家停止编码，开始讨论。一旦找到如何进行协作，以便不会导致工作重来，再开始编码，这样生产率才高。再回到我们之前讨论过的两种类型开发团队成员（牛仔和保质派），看看持续部署如何改变他们所处状况的症结。首先，持续部署对于双方来说，都能促进学习和专业地开发。双方不必争论哪种是写代码的正确方式，而是每个人都可以直接从生产环境上得到学习的机会。这就是“让错误成为你的老师”。如果一个工程师倾向于快速交付，他们可能很快发现自己被集群免疫系统（cluster immune system，由持续集成服务器和5个 whys等组成）逮到。与传统团队的那种高风险问题相比，此时遇到的问题风险都很小，大多数仅影响自己或者比较小的范围。由于反馈迅速，牛仔们开始意识到，哪些测试、准备和检查工作的确会让他们工作得更快。他们就会知到原来还有这样的东西要可以这么快反馈。但是，对于工程师来说，总是有一种在交付前希望等待很长时间的趋势。对于这样的人，批量工作越大，集成就越难。在IMVU，我们偶尔也会招聘到一些从非常传统的组织里出来的工程蚰，他们在那样的公司里已经养成了那里的“最佳实践”和习惯。有时候，他们希望自己使用自己的分支进行工作，并在最后再做集成。尽管我总是会尽最大的努力去说服他们不要那么做，但如果他们坚持要那样的话，我也会鼓励他们试一下的。最终在一两个星期之后，我很高兴地看到他们还是回到了我所谓的“code bouncing”的主流。这就好比向墙上扔一个橡皮球。在一个code bouncing的环境下，如果有人试图一次性提交一个大版本，他们首先就会遇到集成冲突，这就要与团队中的很多成员进行沟通，了解如何恰当地解决这些冲突。当然，当他们正在解决冲突的时间，又会有新的提交，所以新的冲突又会出现了。这个循环一直重复，直到解决所有的冲突，或者要求团队的其他人员先不要提交代码。 然后，更有趣的事情开始了。把这一大堆修改扔到了持续集成服务器上，第一次一定会令增量部署系统和实时监控系统趴窝。所以，这一大包修改就被回滚了。然而，当这些问题被解决时，已经有更多新的修改被提交了。除非我们冻结整个团队的工作，但这有可能会持续几天的时间。假如我们全面要求做这种提交冻结的话，那会令其他人的工作也形成堆积，这就会进一步导致连续的code bouncing。根据我的经验，只要一两次这样的事情就足以让那些想做批量提交的同学回心转意啦。由于持续部署鼓励学习，随着时间的推移，使用这个实践的团队会越来越快。那是因为每个人的动机都与​团队的目标一致。每个人都在工作中消除浪费，这种效率提升得到的收益将会大于那些因为要做持续部署而需要构建和维护的基础设施而增加的开销。事实上，假如你也经常使用5个Whys的话，你也可以用一种完全增量的方式建立这种基础设施。这个过程真的非常有意思。最后，还有一个收益，那就是“士气”。曾经有一个人问我：持续部署是否会对士气产生不良影响。他是一个经理。他担心做这种更快速的发布会令工程师感到更大的压力，让他们觉得自己一直在救火和发布，根本没有时间做“真正的工作”。有一个IMVU的工程师回答了这个问题，我认为，他给出的回答比我的更好。他解释说，通过减少做每次发布的开销，每个工程师都可以有他个人的发布时间表。也就是说，只要他们已经准备好部署了，就可以部署。所以，即便是在半夜，如果你的特性做好了，你也可以提交、部署并马上告诉客户这个新特性。没有额外的申请审批、会议，或者协作要求。只需要有你、你的代码和你的客户就行了，听上去相当不错。​]]></description>
			<content:encoded><![CDATA[<p>本文是《Lean Startup》一书的作者Eric 在2009年发表的一篇<a title="为什么做持续部署" href="http://www.startuplessonslearned.com/2009/06/why-continuous-deployment.html" target="_blank">博文</a>，他是IMVU的创始人之一。文中没有讨论如何做持续部署，而是讨论了一个更关键的问题：“IMVU为什么要做持续部署？”这也充分地表达了他关于“Learning from production and customer”的观点。</p>
<p>－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－</p>
<p>在我所倡导的<a id="zw-134e9a04969l_ctTz45343" href="http://startuplessonslearned.blogspot.com/2008/09/lean-startup.html">Lean Startup</a>所有实践中，没有哪个实践比<a id="zw-134e6c41958Yk_d645343" href="http://startuplessonslearned.blogspot.com/search/label/continuous%20deployment">持续部署</a>更有争议（持续部署是指：让公司在几分钟内发布软件的过程，而不是几天或几个月才发布一次）。我之前所在的一个创业公司<a id="zw-134e6c41959oIzPB45343" title="IMVU" rel="homepage" href="http://www.imvu.com/">IMVU</a>使用这个流程，<a id="zw-134e6c4195acqTrdY45343" href="http://timothyfitz.wordpress.com/2009/02/10/continuous-deployment-at-imvu-doing-the-impossible-fifty-times-a-day/">平均每天部署50次</a>。这也引发了一些争论，有些人说：这种快速发布流程会导致低质量的软件，或者阻碍公司的创新。假如我们能够接受由客户来评判，而不是专家的判定，那么，我想这些说法就很容易消散了。一个更为常见，且更为困难的问题是：如何回答那些只想知道这种持续部署是否可以用于他们自己的业务、行业或团队的人们。<span id="more-246"></span></p>
<p>IMVU的历史尤其引人关注。作为一个有数百万用户消费者的互联网公司，看上去可能与那些只有一小撮潜在客户的企业软件公司，或者那些客户要在软件发布前需要严格审核的计算机安全公司没有太多关系。我想，持有这种反对观点的人实际上没有真正明白持续部署的关键点，因为他们关注点都放在了具体的实现上，而不是通用原则。目前关于持续部署的文章都<a id="zw-134e6c4195dXwLSSy45343" href="http://radar.oreilly.com/2009/03/continuous-deployment-5-eas.html">关注于“如何做”</a>， 但我在这里想说的是“<strong>为什么做？</strong>”（如果你想了解如何开始做持续部署，请参见&#8221;<a id="zw-134e6c4195ee6AVFc45343" href="http://radar.oreilly.com/2009/03/continuous-deployment-5-eas.html">五步实现持续部署</a>&#8220;）</p>
<p><br id="zw-134e6c4195flpofw745343" />持续部署的目标是通过<a id="zw-134e9c13472CIGjpi45343" href="http://startuplessonslearned.blogspot.com/2009/02/work-in-small-batches.html">减少批量工作的大小，</a>并加快团队工作的节奏，帮助开发团队在其开发流程中消除浪费。这使团队能够一直处于一种可持续的平稳流状态， 让团队更容易去创新、试验，并达到可持续的生产率。而且，这也很好地支撑了其它的持续改进系统，如<a id="zw-134e6c41961G4gtVL45343" href="http://startuplessonslearned.blogspot.com/2008/11/five-whys.html">５个Whys</a>。<br id="zw-134e6c41962Y_tK6a45343" /><br id="zw-134e6c41962exfqve45343" /><strong>在开发中，浪费的一个最大来源是“double-checking”。</strong>想像一下，在传统瀑布开发环境中的一个团队，没有持续部署、测试驱动开发或者持续集成。当开发人员想要提交代码时，就到了一个令人担心的时刻。他或她有两种选择：一是马上提交，二是再检查一下，确保不会出问题。两种选择都很有吸引力。假如马上提交的话，就可以说“提前完成任务了&#8221;。可是，如果提交后引起了问题，那么之前的工作速度必然要打折扣。他们为什么不再多花五分钟时间，确保自己的提交不会导致问题呢？事实上，开发人员如何应对这种问题是由他们的激励机制决定的，而激励机制是由团队文化决定的。导致问题后会受到多么严重的惩罚？谁最终会承担这些错误带来的成本？时间表有多么重要？团队是否以尽早完成工作来做评价？<br id="zw-134e6c41963uRtDeN45343" /><br id="zw-134e6c41963cGP7SC45343" />然而，在这种情况下，我们应该意识到，其实并没有所谓正确的答案。被这种选择性所折磨的人最终很可能哪种都做不好。结果，开发人员会走向两个极端：一些人认为应该尽快地完成事情，另一些认为应该细心地做工作检查。从长远来看，二者之间的任何一个中间状态都无法长久。一旦出了问题，无论你怎么去细心解释当时是如何做决定的，都不会令人满意。毕竟，你要么可以做得更快一些，要么可以做得更细心一些。要是你能提前知道问题多好呀啊？！事后再回头看看当时的那些评判，它们好象都存在问题。然而，从另一个角度上看，每种极端的做法都很容易起到自我保护作用。两种方式都有借口：“的确是有几个bug，但我一直在以一个安排得非常紧的时间表来完成任务，有几个bug也是再所难免的。”或者，“我知道你想快点完成这个事儿，但你要知道，我要确保绝对没问题的情况下才能交付给你，所以等一等是值得的。”<br id="zw-134e6c41964kljxfT45343" /><br id="zw-134e6c41965bTu8gv45343" />这两个做法在开发团队中会发&#8221;派系&#8221;冲突，可能产生很多不愉快。经理开始注意到，哪类人在哪个小团队中，然后再依此来分派任务。当在最后一分钟拿到了某个新功能的请求，先找个牛仔完成它—— 然后，在下一个发布中再找个人（Quality Defenders）来&#8221;擦屁股&#8221;。两边都开始从他们各自的视角来思考：“那些家伙没有看到快速行动带来的经济价值，只在意他们那完美的架构图”，又或者， “那些家伙太懒了，根本没有专业精神。” 在我的职业生涯中，经常被找来调节双方的矛盾。在我看来，这些都真是太浪费啦。<br id="zw-134e6c41965EGO09B45343" /></p>
<p>其实，上述这种结果是完全符合逻辑的，因为对于那种大批量生产的开发流程来说，它迫使开发人员利用传统的“<a id="zw-134ea62cd38LkjmQ45343" href="http://startuplessonslearned.blogspot.com/2008/10/engineering-managers-lament.html">时间-质量-金钱，选其中两个的谬论</a>”，在时间和质量之间进行权衡。因为得到的反馈很慢，所以由于<img id="zw-134fb628ab2Ir2NOO45343" src="http://xiexie.baihui.com/images/spacer.gif" alt="" align="top" />​某个错误引发的损坏和做出决定之间有很长的时间，这也使人们很难从中学习。因为每个人都在最后的某个时间点同时做整个发布的集成工作（并没有尽早集成的激励机制）， 要在很大的时间压力下解决该集成过程中中发现的冲突。某些特性像泡沫一样，看上去做好了，很美，但不得不等到下一次发布才行。然而，一旦这些特性被推迟了，就会增加下次发布的工作范围。（“毕竟，我们有完整的发布周期，而这个特性几乎就要完成啦…”），这就会导致下一个时间压力等等。然而，在生产环境中代码运行的方式与其在测试或试运行环境中并不完全一样，这也导致每次发布之后马上就会有一系列的hot-fixes。这也会增加下一次发布的工作量，也就意味着每个发布周期从一开始就已经落后了。<br id="zw-134e6c41968KNzyBn45343" /><br id="zw-134e6c41968JFIt45343" />有很多次，当我访谈一个遇到这种情况的开发团队时，他们想让我帮助“fixing people&#8221;。这种现象心理学上叫做“<a id="zw-134e6c41968un6nO545343" title="Fundamental attribution error" rel="wikipedia" href="http://en.wikipedia.org/wiki/Fundamental_attribution_error">基本归因错误</a> ”，人们倾向于认为其他人的行为来源于其基本属性，如他们的个性，道德准则，或士气 –甚至当受到所在环境的影响时，我们也会为自己的行为找借口。所以，在这种环境下的开发人员，他们的心灵深处也会认为其团队的其他开发人员也是行动缓慢的老学究或邋遢的码农。事实并不是这样的，他们只是让他们的动机搞砸了。<br id="zw-134e6c4196akAlztB45343" /><br id="zw-134e6c4196a1fZNY045343" />你无法通过把所有工作都做得非常完美，来改变这种状况下的根本动因。做更靠谱的发布计划、估算、架构或者集成只能缓解症状。解决这种问题的一种传统做法是：在时间排期表中预留更多的空槽，增加额外的时间做集成，代码冻结，或类似的事情。事实上，大多数组织并不知道，在做时间估算时，开发人员到底已经为这种事情加入了多少Buffer。但是，这种缓冲没什么好处，因为，它只会让整个过程变得更慢。正象所有开发人员都会对你说：“时间太短啦”。实际上，额外的时间压力正是他们认为他们会遇到这些问题的原因。<br id="zw-134e6c4196bw06fR845343" /><br id="zw-134e6c4196bLZofzl45343" />所以，我们要站在整个系统层面上找到解决方案，让团队冲出这种束缚。敏捷软件开发已经做出了巨大的贡献：持续集成帮助加快速了对缺陷的反馈速度；用户故事和看板减少了批量生产的大小；每日站会增加了节奏感。持续部署是另外一种类似的技术，它具有强大的动力让开发团队变得更好。</p>
<h1>持续部署为什么会起作用？</h1>
<p>首先，<strong>持续部署将两种不同的“发布”概念区分开来</strong>。一种是工程师所说的：将代码部署到生产环境的过程。另一种是从市场人员的角度来看的：让用户看到。在传统的“批量及排队”这种开发模式中，两种概念是相联的。一旦新版软件被部署了，所有客户也就能看到它了。这就要求在部署之前，我们要在特定的试运行或测试环境中完成本次发布相关的所有测试。这就使得从写完代码开始，到生产环境部署这之间的这段时间里，由于某些未曾预料到的问题而令本次发布变得不可控。在这些开销中，由于市场发布与技术发布的合并，也让交付活动的协作开销急剧增加。<br id="zw-134e6c4196efRjyaa45343" /><br id="zw-134e6c4196ft4RzWi45343" />而在持续部署环境下，一旦代码写完，就开始向生产环境进发。也就是说，我们经常只部署某个特性百分之一的功能，尽管客户可能要在很久之后才能看到它。事实上，一个新特性的绝大部分工作都是用户无法看到的。相反，这个特性与之前已完成的特性之间却有很多集成点。想像一下，当我们想要在系统中传递一个新增的参数时，就需要修改多个API。这些修改通常应该没有“副作用”，也就是说，它们不会影响当前系统的行为——这里要强调一下“应该”两个字。实际上，很多缺陷是由于那些修改中不常见或没有意识到的<img id="zw-134fb628ac0jvV6JD45343" src="http://xiexie.baihui.com/images/spacer.gif" alt="" align="top" />​副作用引起的。 对于那些只是影响生产环境中的配置参数的很小的修改来说，也是一样。尽快得到这种反馈是最好的，而持续部署恰好提供了这样的途径。<br id="zw-134e6c41970d0yFYG45343" /><br id="zw-134e6c41970HbId9245343" /><strong>持续部署也扮演了速度调解器的角色。</strong>每当部署流程遇到了一个问题时，就需要有人去诊断。在诊断期间，其他人就不能进行部署了。当团队已为部署做好准备，但部署流程被阻塞时，他们就可以马上去帮助诊断并修复部署问题。（相反的做法是团队其他人继续去写更多的代码，但是并不部署，那么这些新代码就会不断堆积，使批量变大，这对每个人都是一种损害）。对于那些通过度量个人效率来衡量其流程的团队来说，通常这个速度调解器是一种比较棘手tracky的调解。在这种环境中，每个工程师的主要目标是保持忙碌状态，写代码的时间尽可能地接近。不幸的是，这种视角忽视了团队的整个产出。即使你不采纳我所提倡的激进定义，比如“<a id="zw-134e6c41971D37Soz45343" href="http://startuplessonslearned.blogspot.com/2009/04/validated-learning-about-customers.html">validated learning about customers</a>”，让每个人都保持忙碌状态仍旧是局部优化。当你正在追踪和修复集成问题时，其它人写的代码很可能会由于冲突而不得不回滚。配置不匹配或多团队之间的冲突都可能会怒导致同样的结果。在这种情况下，对于整体生产率来说，最好是大家停止编码，开始讨论。一旦找到如何进行协作，以便不会导致工作重来，再开始编码，这样生产率才高。<br id="zw-134e6c41972P3ERRk45343" /><br id="zw-134e6c41972qn5TXZ45343" />再回到我们之前讨论过的两种类型开发团队成员（牛仔和保质派），看看持续部署如何改变他们所处状况的症结。首先，持续部署对于双方来说，都能促进学习和专业地开发。双方不必争论哪种是写代码的正确方式，而是<strong>每个人都可以直接从生产环境上得到学习的机会。这就是“让错误成为你的老师”。</strong><br id="zw-134e6c41973BVbuo45343" /><br id="zw-134e6c41973vkIZ4v45343" />如果一个工程师倾向于快速交付，他们可能很快发现自己被<a id="zw-134e6c41974_AuOja45343" href="http://startuplessonslearned.blogspot.com/2008/09/just-in-time-scalability.html">集群免疫系统（cluster immune system</a>，由持续集成服务器和<a id="zw-134eed89395rVRICc45343" href="http://startuplessonslearned.blogspot.com/2008/11/five-whys.html">5个 whys</a>等组成）逮到。与传统团队的那种高风险问题相比，此时遇到的问题风险都很小，大多数仅影响自己或者比较小的范围。由于反馈迅速，牛仔们开始意识到，哪些测试、准备和检查工作的确会让他们工作得更快。他们就会知到原来还有这样的东西要可以这么快反馈。<br id="zw-134e6c41976MZrIqF45343" /><br id="zw-134e6c41976SpPh45343" />但是，对于工程师来说，总是有一种在交付前希望等待很长时间的趋势。对于这样的人，批量工作越大，集成就越难。在IMVU，我们偶尔也会招聘到一些从非常传统的组织里出来的工程蚰，他们在那样的公司里已经养成了那里的“最佳实践”和习惯。有时候，他们希望自己使用自己的分支进行工作，并在最后再做集成。尽管我总是会尽最大的努力去说服他们不要那么做，但如果他们坚持要那样的话，我也会鼓励他们试一下的。最终在一两个星期之后，我很高兴地看到他们还是回到了我所谓的“code bouncing”的主流。这就好比向墙上扔一个橡皮球。在一个code bouncing的环境下，如果有人试图一次性提交一个大版本，他们首先就会遇到集成冲突，这就要与团队中的很多成员进行沟通，了解如何恰当地解决这些冲突。当然，当他们正在解决冲突的时间，又会有新的提交，所以新的冲突又会出现了。这个循环一直重复，直到解决所有的冲突，或者要求团队的其他人员先不要提交代码。 然后，更有趣的事情开始了。把这一大堆修改扔到了持续集成服务器上，第一次一定会令增量部署系统和实时监控系统趴窝。所以，这一大包修改就被回滚了。然而，当这些问题被解决时，已经有更多新的修改被提交了。除非我们冻结整个团队的工作，但这有可能会持续几天的时间。假如我们全面要求做这种提交冻结的话，那会令其他人的工作也形成堆积，这就会进一步导致连续的code bouncing。根据我的经验，只要一两次这样的事情就足以让那些想做批量提交的同学回心转意啦。<br id="zw-134e6c41977B2lD045343" /><br id="zw-134e6c41977Mox7wL45343" /><strong>由于持续部署鼓励学习，随着时间的推移，使用这个实践的团队会越来越快</strong>。那是因为每个人的动机都与<img id="zw-134fb628acaOW3ZX945343" src="http://xiexie.baihui.com/images/spacer.gif" alt="" align="top" />​团队的目标一致。每个人都在工作中消除浪费，这种效率提升得到的收益将会大于那些因为要做持续部署而需要构建和维护的基础设施而增加的开销。事实上，假如你也经常使用<a id="zw-134e6c41978uBcf5r45343" href="http://startuplessonslearned.blogspot.com/2008/11/five-whys.html">5个Whys</a>的话，你也可以用一种完全增量的方式建立这种基础设施。这个过程真的非常有意思。<br id="zw-134e6c41979OwXYNs45343" /><br id="zw-134e6c419798g7zLX45343" />最后，还有一个收益，那就是“<strong>士气</strong>”。曾经有一个人问我：持续部署是否会对士气产生不良影响。他是一个经理。他担心做这种更快速的发布会令工程师感到更大的压力，让他们觉得自己一直在救火和发布，根本没有时间做“真正的工作”。有一个IMVU的工程师回答了这个问题，我认为，他给出的回答比我的更好。他解释说，通过减少做每次发布的开销，每个工程师都可以有他个人的发布时间表。也就是说，只要他们已经准备好部署了，就可以部署。所以，即便是在半夜，如果你的特性做好了，你也可以提交、部署并马上告诉客户这个新特性。没有额外的申请审批、会议，或者协作要求。只需要有你、你的代码和你的客户就行了，听上去相当不错。​</p>
]]></content:encoded>
			<wfw:commentRss>http://www.continuousdelivery.info/index.php/2012/01/20/imvu-why-contiuous-deployment/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>LinkedIn:移动APP开发中的自动化测试与持续部署流水线</title>
		<link>http://www.continuousdelivery.info/index.php/2012/01/16/cd-pipeline-in-mobile-development/</link>
		<comments>http://www.continuousdelivery.info/index.php/2012/01/16/cd-pipeline-in-mobile-development/#comments</comments>
		<pubDate>Mon, 16 Jan 2012 08:42:03 +0000</pubDate>
		<dc:creator>乔梁</dc:creator>
				<category><![CDATA[持续交付]]></category>
		<category><![CDATA[casestudy]]></category>
		<category><![CDATA[linkedin]]></category>
		<category><![CDATA[持续集成]]></category>
		<category><![CDATA[最佳实践]]></category>
		<category><![CDATA[测试]]></category>
		<category><![CDATA[部署流水线]]></category>

		<guid isPermaLink="false">http://www.continuousdelivery.info/?p=239</guid>
		<description><![CDATA[最近，有很多人问我关于“移动应用开发中的自动化测试如何做？持续集成和部署流水线从哪里开始？”的问题，觉得有必要写一写。恰好这个周末在家无意间看到Linkedin的做法，觉得非常有意思，尤其是截屏做对比测试的做法，在移动应用中比较少见， 在这里与大家分享。原文地址在这里。 几个月前，LinkedIn发布了新的移动 APP，支持多种平台，包括  Native App和 Html5。 brand new mobile experience on a wide variety of platforms, including native apps and HTML5 webapps. 在这背面，我们在客户端大量使用了JavaScript和HTML 5，在服务器端也严重依赖于Node.js。为了能够快速地开发、测试和发布，我们构建了一个持续集成自动化流水线。本文中，我讲述如何做移动应用的持续集成工作。 概述 下面是LinkedIn移动应用的总体架构。 图1 LinkedIn 移动应用架构 我们所支持的各种平台 (iPhone, Android, mobile web)主要使用JavaScript和HTML向我们的Node.js 移动服务器发送RESTful请求。而这个服务器通过RESTful调用从LinkedIn平台上获取数据。关于我们的移动架构，你可以在这里 和这里了解到更多的内容。 持续集成流水线 我们的移动持续集成流水线一共包括五个阶段： Unit tests: 通常少于10秒，用于测试独立的模块和单元 Fixtures &#8230; <a href="http://www.continuousdelivery.info/index.php/2012/01/16/cd-pipeline-in-mobile-development/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>最近，有很多人问我关于“移动应用开发中的自动化测试如何做？持续集成和部署流水线从哪里开始？”的问题，觉得有必要写一写。恰好这个周末在家无意间看到Linkedin的做法，觉得非常有意思，尤其是截屏做对比测试的做法，在移动应用中比较少见， 在这里与大家分享。原文地址在<a title="持续交付, 持续集成, linkedin, CI, Continuous delivery" href="http://engineering.linkedin.com/testing/continuous-integration-mobile" target="_blank">这里</a>。</p>
<p><span id="more-239"></span></p>
<p id="zw-134e4219b186dqL5i45343">几个月前，LinkedIn发布了<a id="zw-134e43a9cc8ZQUbEm45343" title="新的移动 APP，支持多种平台" href="http://blog.linkedin.com/2011/08/16/new-linkedin-mobile/" target="_blank">新的移动 APP，支持多种平台</a>，包括  Native App和 Html5。</p>
<p id="zw-134e4219b6fCyI97645343"><a id="zw-134e4219b1cKpnrKF45343" title="new" href="http://blog.linkedin.com/2011/08/16/new-linkedin-mobile/" target="_blank">brand new mobile experience</a> on a wide variety of platforms, including <a id="zw-134e4219b1eyaVtm45343" href="http://www.linkedin.com/static?key=mobile" target="_blank">native apps</a> and <a id="zw-134e4219b1fY8_gTe45343" href="http://touch.linkedin.com/" target="_blank">HTML5 webapps</a>. 在这背面，我们在客户端大量使用了JavaScript和HTML 5，在服务器端也严重依赖于Node.js。为了能够快速地开发、测试和发布，我们构建了一个持续集成自动化流水线。本文中，我讲述如何做移动应用的持续集成工作。</p>
<h1 id="zw-134e4219b21Xp4DYA45343"><strong>概述</strong></h1>
<p id="zw-134e4219b23H9-Dt145343">下面是LinkedIn移动应用的总体架构。</p>
<p id="zw-134e4219b26FL3RcJ45343"><img id="zw-134e4219b29kfRcKr45343" class="aligncenter" src="http://engineering.linkedin.com/sites/default/files/Architecture-clean-2.png" alt="" /></p>
<p id="zw-134e4219b70mMdr545343" style="text-align: center;">图1 LinkedIn 移动应用架构</p>
<p id="zw-134e4219b2b6QvddF45343">我们所支持的各种平台 (iPhone, Android, mobile web)主要使用JavaScript和HTML向我们的Node.js 移动服务器发送RESTful请求。而这个服务器通过RESTful调用从<a id="zw-134e4219b2fPqK_1C45343" href="http://developer.linkedin.com/" target="_blank">LinkedIn平台</a>上获取数据。关于我们的移动架构，你可以在<a id="zw-134e4219b30nLUJ1A45343" href="http://www.slideshare.net/phegaro/linkedin-mobile-how-do-we-do-it" target="_blank">这里</a> 和<a id="zw-134e4219b31JMc1I645343" href="http://venturebeat.com/2011/08/16/linkedin-node/" target="_blank">这里</a>了解到更多的内容。</p>
<h1 id="zw-134e4219b31RledmV45343"><strong>持续集成流水线</strong></h1>
<p id="zw-134e4219b33kdHEVY45343">我们的移动持续集成流水线一共包括五个阶段：</p>
<p id="zw-134e4219b34vEnQGn45343"><img id="zw-134e4219b39CCmjIn45343" src="http://engineering.linkedin.com/sites/default/files/pipeline-short.png" alt="" /></p>
<ol id="zw-134e4219b3977e5Tu45343">
<li id="zw-134e4219b3b_1RgR245343">Unit tests: 通常少于10秒，用于测试独立的模块和单元</li>
<li id="zw-134e4219b3cus3HKl45343">Fixtures tests: 通过使用静态或模拟数据对客户端应用进行测试。</li>
<li id="zw-134e4219b3eRLu70g45343">Layout tests: 通过截屏并与基线图像进行对比，测试客户端应用的Layout。</li>
<li id="zw-134e4219b3fnP80E445343">Deployment: 自动部署到一个试运行环境中。</li>
<li id="zw-134e4219b40ccnJJ245343">End-to-end tests: 在试运行环境中进行端到端的测试。</li>
</ol>
<p id="zw-134e4219b70IansPv45343">&nbsp;</p>
<p id="zw-134e4219b42VCvvsz45343">前面的阶段通常比后面的阶段要快，而且在后一个阶段开始之前，必须保证前面的100%通过。</p>
<h1 id="zw-134e4219b4440C5-X45343"><strong>单元测试及覆盖率</strong></h1>
<p id="zw-134e4219b45PoJX2z45343">我们使用Hudson做我们的持续集成服务器，让它在每次提交之后就执行单元测试<img id="zw-134e45345d5jTctzj45343" src="http://xiexie.baihui.com/images/spacer.gif" alt="" align="top" />。我们用</p>
<p id="zw-134e4219b71ys_KPq45343"><a id="zw-134e4219b48m30w9s45343" href="http://code.google.com/p/js-test-driver/" target="_blank">JsTestDriver</a> 做测试框架，因为它是能够支持持续集成的仅有的几个JavaScript单元测试框架之一。另外，它还可以计算测试覆盖率：</p>
<p id="zw-134e4219b48UhieVH45343"><img id="zw-134e4219b4bRRmaK645343" class="aligncenter" src="http://engineering.linkedin.com/sites/default/files/jstestdriver-coverage_0.png" alt="" /></p>
<p id="zw-134e4219b716bfjFq45343" style="text-align: center;">图2. JsTestDriver中的代码覆盖率</p>
<p id="zw-134e4219b4dyLxU-g45343">&nbsp;</p>
<h1 id="zw-134e4219b4e9cQPO045343"><strong>Fixtures tests</strong></h1>
<p id="zw-134e4219b4fyu0fH-45343">我们可以通过配置让客户端向一个nginx服务器发送请求，它会以JSON文件格式返回<a id="zw-134e4219b50gBLzp45343" href="http://en.wikipedia.org/wiki/Test_fixture" target="_blank">test fixtures</a>。由于这些测试完成与模拟数据打交道，所以只要出错，就可以认为是客户端的bugs。而且，这些模拟数据的使用令测试执行得更快。</p>
<p id="zw-134e4219b51NEQ7ym45343">我们还可以在测试过程中配置nginx，用来查看客户端是如何处理不同的HTTP状态码的。你可以看一下<a id="zw-134e4219b52VXsBOk45343" href="https://gist.github.com/1225958">我们用的nginx规则，</a>用于确保我们的客户端代码能优雅地处理HTTP500错误，或204等等。</p>
<h1 id="zw-134e4219b53rqWpmN45343"><strong>Layout tests</strong></h1>
<p id="zw-134e4219b55V3CArs45343">这种fixtures环境也让我们可能运行layout tests，它可以自动地验证界面渲染是否正确，而不需要人用肉眼来看。我们使用<a id="zw-134e4219b56MBNeRu45343" href="http://www.webkit.org/projects/layout/index.html" target="_blank">WebKit Layout 和Rendering</a> 来做无标题栏（抬头）的浏览器截屏。当界面开发完成后，这个截屏就被标记为基线。更进一步，我们只要根据这个基础PNG文件进行对比，就可以发现回归问题。</p>
<p id="zw-134e4219b573ZwhNn45343">这些工具fixtures会让那些引起UI变化的随机数据最少化。有一少部分情况下，渲染总是动态的，比如时间戳，在截屏之前，我们执行特定的JavaScript用静态数据来取代动态的数据。PNG的比较，我们也增加了一些容忍度，因为在某些情况下，WebKit会生成稍有不同的PNG文件。</p>
<h1 id="zw-134e4219b58ziefH445343"><strong>部署与端到端测试</strong></h1>
<p id="zw-134e4219b59GAD7N-45343">​当layout tests全部通过以后，一个产品构建就会自动化的部署到试运行环境中，并运行端到端的测试。这些测试会在整个架构上执行全路径，并试图捕获在之间的测试中可能遗漏的任何集成问题。我们在生产环境上也运行端到端的测试，使我们可以快速地识别任何live site的问题，比如某个服务器宕机了，或者负载平衡器出了问题。我们使用<a id="zw-134e4219b5auh3vZT45343" href="http://seleniumhq.org/docs/03_webdriver.html" target="_blank">Selenium WebDriver</a> 和 <a id="zw-134e4219b5bIs2bt745343" href="http://testng.org/" target="_blank">TestNg</a>.来创建端到端的测试。我们成功地使用 <a id="zw-134e4219b5cy_AmAM45343" href="http://code.google.com/p/selenium/wiki/IPhoneDriver" target="_blank">iPhoneDriver</a> 让这些测试可以运行在一个iPhone模拟器之上。我们想用<a id="zw-134e4219b5dw6M9uF45343" href="http://code.google.com/p/selenium/wiki/AndroidDriver" target="_blank">AndroidDriver</a>，但是最近，被<a id="zw-134e4219b5eMTm-Ht45343" href="http://code.google.com/p/selenium/issues/detail?id=1420" target="_blank">CSS selectors</a>的一个问题阻塞了。WebDriver团队刚刚修复完。而Selenium-WebDriver的测试可以使用很多种语言来写，而我们用Java，因为对它的支持比较广泛。<a id="zw-134e4219b5eICLfvc45343" href="https://gist.github.com/1225976">这里</a>有一些Selenium-WebDriver测试的例子。</p>
<p id="zw-134e4219b5f6xvunz45343">我们使用<a id="zw-134e4219b605VEomV45343" href="http://siliconforks.com/jscoverage/" target="_blank">JSCoverage</a>来分析端到端测试的覆盖率：<img id="zw-134e4b3ee00aI_YOo45343" src="http://xiexie.baihui.com/images/spacer.gif" alt="" align="top" /></p>
<p id="zw-134e4219b61SpXyNH45343"><img id="zw-134e4219b62c25u45343" class="aligncenter" src="http://engineering.linkedin.com/sites/default/files/JSCoverage.png" alt="" /></p>
<p id="zw-134e4219b757N6fw45343" style="text-align: center;">图3. JSCoverage: 红色是没有被端到端测试执行到的代码</p>
<p id="zw-134e4219b63OOiULJ45343">&nbsp;</p>
<h1 id="zw-134e4219b64fLeKXZ45343"><strong>小结</strong></h1>
<p id="zw-134e4219b64Wcz0w45343">通过所有这些移动持续集成的阶段，我们的测试覆盖率为75%，这使我们能捕获到很多bugs，尤其是单元测试和fixtures tests。这些测试的一个要点是快速：当新代码提交后，通常不到5分钟就可以找到。在发现漏到开发中后面阶段（比如试运行和生产环境）的问题来说，端到端测试也是有帮助的。</p>
<p id="zw-134e4219b65iEcpVv45343">在不久的将来，随着团队更趋于测试驱动开发（TDD），我们会在流水线的最后增加一个阶段：向生产环境部署。这样，就达成了持续部署的目标。</p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.continuousdelivery.info/index.php/2012/01/16/cd-pipeline-in-mobile-development/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>围绕最终交付物，而不是角色来组织软件交付活动</title>
		<link>http://www.continuousdelivery.info/index.php/2011/12/26/organize_software_delivery_around_outcomes_not_roles/</link>
		<comments>http://www.continuousdelivery.info/index.php/2011/12/26/organize_software_delivery_around_outcomes_not_roles/#comments</comments>
		<pubDate>Mon, 26 Dec 2011 05:53:48 +0000</pubDate>
		<dc:creator>乔梁</dc:creator>
				<category><![CDATA[持续交付]]></category>
		<category><![CDATA[DevOps]]></category>
		<category><![CDATA[MVP]]></category>
		<category><![CDATA[交付原则]]></category>

		<guid isPermaLink="false">http://www.continuousdelivery.info/?p=217</guid>
		<description><![CDATA[——持续交付与跨功能团队 在实施持续交付的过程中，我们很容易聚焦于自动化和工具，因为作为起点，它们通常是最容易做的。然而，持续交付的成功实现，还依赖于根据最终交付物而对组织结构所做的优化。对于持续交付来说，最大的障碍是依据角色和分层结构来组织团队，而非业务上的最终交付物（即产品或服务）。 为了解决开发团队、测试团队和运维团队之间的“筒仓”，Devops运动应运产生。那么，这些“筒仓”为什么会存在呢？Gartner的Coleen Young说过下面这段话，直接切入这个问题的核心： 事实上，每个IT组织一定会面临一个必然引起组织结构彻底改变的流程改造。传统IT服务的交付和组织模式以有效性为代价，达到了高效性。在过去，计算能力非常昂贵，资源稀缺的时候，将人员利用率和资产的生命周期成本最大化是合理的。这种面向资源的业务流程最终会导致功能壁垒。优化后的基于流程的组织在横向上侧重于各自环节的产出，而不是在全局上最终交付物的产量。 “筒仓”产生的根本原因在于计算资源的历史费用和发布过程的高成本。而批量单位的大小与交接成本之间有直接关系。这在Economic Lot Size 方程式上已经体现了，这个方程式是来处理交易成本（transaction cost）将一个工作块交付给下一环节（如从开发到测试）和持有成本（不交给下游的成本）之间的平衡。这在Donald Reinertsen的书《产品开发流程的原则》中有讨论，如下图所示： 持续交付：减少交易成本 在大型机时代，发布一个版本的交易成本较小。之后，当我们进入客户端/服务器架构的时代，以及后来基于网页的软件系统，每次发布的交易成本就变得越来越高了，甚至在总成本中占首位。而这就驱使我们进行批量开发，从而导致了我们今天看到的“筒仓”。 然而，持续交付传递了一种信息，即现在有很多工具、模式和实践，可以大幅度地降低发布的交易成本，使得持有成本占到交付总成本的大头。 这样的话，形成组织壁垒的根因就不复存在了。而且，由于壁垒会导致低质量的软件，生产环境的稳定性差，以及发布的次数越来越少。因此，对于那些关键业务的项目团队来说，更有必要消除这些问题。 跨功能团队：为了最终交付物而做优化 筒仓的替代物是跨功能团队。正如Young建议的那样，在跨功能团队中，我们对最终交付物或者交货时间做优化。通过实现持续交付的那些实践，可以将交易成本降到可忽略不计的水平。然后，通过限制在制品数量这种方式来实现小批量生产，并设法让这些小批量功能在尽可能短的时间里发布给用户，或者至少能够做到“可以发布给用户”的水平。 跨功能团队并不是一个新概念，但人们常常低估了它的重要性。对于减少交货时间（lead-time）来说，跨功能团队是一个至关重要的因素。因为，功能交付的延期在很多时候是由于沟通开销引起的。如果参与某产品（或服务）的所有人都能够在一起工作，那么在写代码之前，开发人员就可以直接把测试人员叫来，给他展示已做好的功能，以便能够得到快速反馈。而测试人员和开发人员可以一起合作创建功能验收测试，开发人员也可以与DBA一起讨论数据库结构的变更，还可以与基础设施专家一起讨论基础架构上的一些平衡点。 这不但会让软件交付更快，而且会有更多的乐趣。当然，我们最终会得到高质量的软件、低风险的发布，以及从客户那儿得到更快速的响应。在Amazon做出“组成面向服务架构的跨功能团队”这一决定时，这些因素都是其认为的关键收益。 对于“跨功能团队”，常常会听到这样几种的反对声音。一是当所在的组织要遵从某些法案，如萨班斯－奥克斯利法案，或支付卡行业数据安全标准（PCI-DSS，全称为Payment Card Industry Data Security Standard）时，需要做到责任隔离。实际上，在跨功能团队里，能够更高效地实现责任分离，正如我在最近为 Cutter IT Journal的一篇文章提到的。 另一个反对的声音是当创建跨功能团队，并实现持续交付时，会有附加成本。的确如此，这意味着你只会在那些处于战略地位的核心服务组合上投入这种附加成本。此时，通过产品的快速上市、从用户那里学习并快速迭代，以及避免开发没有用的功能（这是软件开发中产生浪费的最大来源）得到通常数倍于这种附加成本的回报。——当然，在“筒仓”引起的问题当中，有一部分问题是可以通过更好的管理手段来缓解的。比如，确保在这些“筒仓”中，资源负荷不过重，人员在各筒仓间轮换，以鼓励协作和理解。 如何走向跨功能模式的组织？ 如果你的IT组织不大，比如还不到30人，那么你可以一下就转变成跨功能模式。然而，在大型组织中，正如《持续交付》中的所有事情一样，这应该是个迭代且增量的过程。 从一个试点项目开始。首先，确保你能收集整个项目周期中的总成本和总收入，以及其它相关度量项，比如周期时间(cycle time)以及每个发布版本所交付的增量价值。整个团队要对该服务的SLA（服务等级协议，Service-Level Agreement）负责。而且，更为重要的是，对自己依赖的基础设施，能够做到自服务，包括测试环境和生产环境在内，从而不必为了硬件准备这样的工作而等上几天或几星期。应该给该团队一些时间来实现持续交付，并且聚焦于交付一个最低可行的产品（minimum viable product），然后根据从用户那儿反馈的真实数据进行快速迭代。 有分布式团队的大型组织更应该转向“跨功能团队”这个目标。而关键在于：确保不是依据角色不同而组织团队。对于“持续交付高质量软件”来说，没有什么能比让开发团队在一个国家、测试团队在另一个国家，而运维团队在其它国家的伤害更大啦。 最后，团队应该首先关注于，通过分解成最低可行的产品集并测试，以验证其所做出的业务假设。而一旦失败，就很容易进行调整。 原文来自《持续交付》英文站，Organize software &#8230; <a href="http://www.continuousdelivery.info/index.php/2011/12/26/organize_software_delivery_around_outcomes_not_roles/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<h2 style="text-align: center;">——持续交付与跨功能团队</h2>
<p style="text-align: left;">在实施持续交付的过程中，我们很容易聚焦于自动化和工具，因为作为起点，它们通常是最容易做的。然而，持续交付的成功实现，还依赖于根据最终交付物而对组织结构所做的优化。对于持续交付来说，最大的障碍是依据角色和分层结构来组织团队，而非业务上的最终交付物（即产品或服务）。</p>
<p style="text-align: left;"><span id="more-217"></span></p>
<p style="text-align: left;">为了解决开发团队、测试团队和运维团队之间的“筒仓”，Devops运动应运产生。那么，这些“筒仓”为什么会存在呢？<a title="Six steps to process-based IT organizational design" href="http://www.gartner.com/DisplayDocument?ref=seo&amp;id=497149">Gartner的Coleen Young说过</a>下面这段话，直接切入这个问题的核心：</p>
<blockquote>
<p style="text-align: left;">事实上，每个IT组织一定会面临一个必然引起组织结构彻底改变的流程改造。传统IT服务的交付和组织模式以有效性为代价，达到了高效性。在过去，计算能力非常昂贵，资源稀缺的时候，将人员利用率和资产的生命周期成本最大化是合理的。这种面向资源的业务流程最终会导致功能壁垒。优化后的基于流程的组织在横向上侧重于各自环节的产出，而不是在全局上最终交付物的产量。</p>
</blockquote>
<p style="text-align: left;">“筒仓”产生的根本原因在于计算资源的历史费用和发布过程的高成本。而批量单位的大小与交接成本之间有直接关系。这在Economic Lot Size 方程式上已经体现了，这个方程式是来处理交易成本（transaction cost）将一个工作块交付给下一环节（如从开发到测试）和持有成本（不交给下游的成本）之间的平衡。这在Donald Reinertsen的书《<a title="产品开发流程的原则" href="http://www.amazon.com/gp/product/1935401009?tag=contindelive-20" target="_blank">产品开发流程的原则</a>》中有讨论，如下图所示：</p>
<p style="text-align: left;"><a href="http://www.continuousdelivery.info/wp-content/uploads/2011/12/Fig2-2rev1-Humble.jpg"><img class="aligncenter size-full wp-image-218" title="Fig2-2rev1-Humble" src="http://www.continuousdelivery.info/wp-content/uploads/2011/12/Fig2-2rev1-Humble.jpg" alt="持有成本与交易成本" width="2700" height="2249" /></a></p>
<h1 style="text-align: left;">持续交付：减少交易成本</h1>
<p style="text-align: left;">在大型机时代，发布一个版本的交易成本较小。之后，当我们进入客户端/服务器架构的时代，以及后来基于网页的软件系统，每次发布的交易成本就变得越来越高了，甚至在总成本中占首位。而这就驱使我们进行批量开发，从而导致了我们今天看到的“筒仓”。</p>
<p style="text-align: left;">然而，持续交付传递了一种信息，即现在有很多工具、模式和实践，可以大幅度地降低发布的交易成本，使得持有成本占到交付总成本的大头。</p>
<p style="text-align: left;">这样的话，形成组织壁垒的根因就不复存在了。而且，由于壁垒会导致低质量的软件，生产环境的稳定性差，以及发布的次数越来越少。因此，对于那些关键业务的项目团队来说，更有必要消除这些问题。</p>
<h1 style="text-align: left;">跨功能团队：为了最终交付物而做优化</h1>
<p style="text-align: left;">筒仓的替代物是跨功能团队。正如Young建议的那样，在跨功能团队中，我们对最终交付物或者交货时间做优化。通过实现持续交付的那些实践，可以将交易成本降到可忽略不计的水平。然后，通过<a title="Limited work-in-progress" href="http://www.amazon.com/gp/product/0984521402?tag=contindelive-20" target="_blank">限制在制品数量</a>这种方式来实现小批量生产，并设法让这些小批量功能在<a href="http://www.leanessays.com/2011/07/how-cadence-determines-process.html" target="_blank">尽可能短的时间里</a>发布给用户，或者至少能够做到“可以发布给用户”的水平。</p>
<p style="text-align: left;">跨功能团队并不是一个新概念，但人们常常低估了它的重要性。对于减少交货时间（lead-time）来说，跨功能团队是一个至关重要的因素。因为，功能交付的延期在很多时候是由于沟通开销引起的。如果参与某产品（或服务）的所有人都能够在一起工作，那么在写代码之前，开发人员就可以直接把测试人员叫来，给他展示已做好的功能，以便能够得到快速反馈。而测试人员和开发人员可以一起合作创建功能验收测试，开发人员也可以与DBA一起讨论数据库结构的变更，还可以与基础设施专家一起讨论基础架构上的一些平衡点。</p>
<p style="text-align: left;">这不但会让软件交付更快，而且会有更多的乐趣。当然，我们最终会得到高质量的软件、低风险的发布，以及从客户那儿得到更快速的响应。在<a title="amazon " href="http://www.fastcompany.com/magazine/85/bezos_2.html" target="_blank">Amazon做出“组成面向服务架构的跨功能团队”这一决定</a>时，这些因素都是其认为的关键收益。</p>
<p style="text-align: left;">对于“跨功能团队”，常常会听到这样几种的反对声音。一是当所在的组织要遵从某些法案，如萨班斯－奥克斯利法案，或支付卡行业数据安全标准（PCI-DSS，全称为Payment Card Industry Data Security Standard）时，需要做到责任隔离。实际上，在跨功能团队里，能够更高效地实现责任分离，<a href="http://cutter.com/offers/devopsrevolution.html" target="_blank">正如我在最近为 Cutter IT Journal的一篇文章提到的</a>。</p>
<p style="text-align: left;">另一个反对的声音是当创建跨功能团队，并实现持续交付时，会有附加成本。的确如此，这意味着你只会在那些<a href="http://continuousdelivery.com/2011/01/strategic-vs-utility-services/" target="_blank">处于战略地位的核心服务组合</a>上投入这种附加成本。此时，通过产品的快速上市、从用户那里学习并快速迭代，以及避免开发没有用的功能（<a href="http://martinfowler.com/articles/xp2002.html#BuildOnlyTheFeaturesYouNeed" target="_blank">这是软件开发中产生浪费的最大来源</a>）得到通常数倍于这种附加成本的回报。——当然，在“筒仓”引起的问题当中，有一部分问题是可以通过更好的管理手段来缓解的。比如，确保在这些“筒仓”中，资源负荷不过重，人员在各筒仓间轮换，以鼓励协作和理解。</p>
<h1 style="text-align: left;">如何走向跨功能模式的组织？</h1>
<p style="text-align: left;">如果你的IT组织不大，比如还不到30人，那么你可以一下就转变成跨功能模式。然而，在大型组织中，正如《持续交付》中的所有事情一样，这应该是个迭代且增量的过程。</p>
<p style="text-align: left;">从一个试点项目开始。首先，确保你能收集整个项目周期中的总成本和总收入，以及其它相关度量项，比如周期时间(cycle time)以及每个发布版本所交付的增量价值。整个团队要对该服务的SLA（服务等级协议，Service-Level Agreement）负责。而且，更为重要的是，对自己依赖的基础设施，能够做到自服务，包括测试环境和生产环境在内，从而不必为了硬件准备这样的工作而等上几天或几星期。应该给该团队一些时间来实现持续交付，并且聚焦于交付一个最低可行的产品（<a title="MVP" href="http://www.informit.com/articles/article.aspx?p=1750200">minimum viable product</a>），然后根据从用户那儿反馈的真实数据进行快速迭代。</p>
<p style="text-align: left;">有分布式团队的大型组织更应该转向“跨功能团队”这个目标。而关键在于：确保不是依据角色不同而组织团队。对于“持续交付高质量软件”来说，没有什么能比让开发团队在一个国家、测试团队在另一个国家，而运维团队在其它国家的伤害更大啦。</p>
<p style="text-align: left;">最后，团队应该首先关注于，通过分解成最低可行的产品集并测试，以验证其所做出的业务假设。而一旦失败，就很容易进行调整。</p>
<p style="text-align: left;">原文来自《持续交付》<a title="continuous delivery" href="http://continuousdelivery.com" target="_blank">英文站</a>，<a title="organize-software-delivery-around-outcomes-not-roles" href="http://continuousdelivery.com/2011/12/organize-software-delivery-around-outcomes-not-roles/#more-485" target="_blank">Organize software delivery around outcomes, not roles: continuous delivery and cross-functional teams</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.continuousdelivery.info/index.php/2011/12/26/organize_software_delivery_around_outcomes_not_roles/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>持续集成案例分析系列(1)——大规模项目团队持续集成历程</title>
		<link>http://www.continuousdelivery.info/index.php/2011/11/14/casestudy-largesize/</link>
		<comments>http://www.continuousdelivery.info/index.php/2011/11/14/casestudy-largesize/#comments</comments>
		<pubDate>Mon, 14 Nov 2011 13:30:47 +0000</pubDate>
		<dc:creator>乔梁</dc:creator>
				<category><![CDATA[持续交付]]></category>
		<category><![CDATA[casestudy]]></category>
		<category><![CDATA[dvcs]]></category>
		<category><![CDATA[交付原则]]></category>
		<category><![CDATA[部署]]></category>
		<category><![CDATA[部署流水线]]></category>

		<guid isPermaLink="false">http://www.continuousdelivery.info/?p=205</guid>
		<description><![CDATA[这篇文章是我在两年前写的，记录了一个150+人的软件团队（最多时近200人）如何在一个庞大的遗留系统上，通过逐步建立一个持续交付部署流水线，从而达到频繁发布的状态。最终在该团队的持续交付基础设施中，共有260台服务器用于构建、测试和部署（几乎全部是虚拟机）。而这个产品也可以每六周发布一次。 一、在大规模项目团队中可能遇到的问题 对于小规模、短周期的项目来说，团队与持续集成会相处地非常融洽。而对于大规模、长周期项目的初期来说，也不会有太多的问题。此时常见的也是基本的持续集成模式就是：Build-&#62;test-&#62;package。然而，只要时间稍长一点儿，持续集成就会发出坏味道了。此时的症状包括： 1. 作为开发人员 要等很长时间才能知道是否可以提交代码了。如果你遵守“频繁提交”的原则，那么百人团队不间断的提交，会使集成服务器一直处于繁忙状态，而你不得不等待他人的build过了以后，才能看到自己提交的结果。 要等很长时间才能知道我的提交是否通过了； 如果build失败了，要花很长时间才能知道是否和自己的修改相关； 既使提交了fix，也不知道自己的提交是否真的修复了这次构建； 构建经常处于失败状态。 2. 作为测试人员 测试人员不知道到哪里拿哪一次的构建产物来进行测试； 发布经理不知道当前各种各样的测试部署环境中，到底部署了哪个版本，包括哪些新功能或修改的bug； 不确定在同一个构建里，所有组件的版本是否都是正确的； &#160; 3. 作为项目经理 不确定各个测试部署环境中的配置是否都与其上运行的构建相一致； 不确定测试人员测试的是否在正确的运行环境上运行了正确的版本； 4. 其他方面的问题 所有的安装部署都需要手工操作。 以上这些问题会给你的发布管理带来无限的问题和风险。那么，是否因为这种“持续闹心”就放弃持续集成呢？回答当然是否定的。Do it more if it hurts you. 不要因问题的暴露而放弃，相反，应该欢呼。因为这反映了发布过程中的问题与风险，是时候解决它们了。 二、如何解决大规模项目中的持续交付问题 由于大项目本身的复杂性，其解决方案也不能一概而论。下面以某大型项目为例，介绍其中的几个解决方法。 1、项目基本信息描述 该项目最初就试图建立一个好的持续集成环境和基础。由于是一个遗留系统，费了很大劲儿，才能够得到可工作的软件。然而，由于队伍不断壮大，而且环境也在不断变化，持续集成很快就无法达不到其预期目标了。怎么办呢？ 项目背景: 项目是一个具有可配置性的Web 门户产品，面向不同行业的市场，可自己定制门户。该项目有一个遗留的代码库，而且可以肯定的说，在今后的一年半之内是无法摆脱这个遗留代码库的。而且，很多紧耦合的、不必要的臃肿代码，同时根本不存在有价值的测试代码。现在我们在逐步地重写代码，但还是不能删除它们，因为某些网站还要依赖于旧代码。事实上，这是一个.NET平台上基于SOA的网站。 开发团队情况： 团队是一个敏捷分布开发团队（三地协作，均有开发人员，且有时差）。整个团队有150多人，分成十几个团队，每个团队都有一个完成的结构（BA/DEV/QA），其中有一个是项目持续集成团队（项目之初，大约有五六个人，工作负荷很大，项目运行一段时间后只要两个人就足够了）。使用SVN做版本管理工具，在Windows2003上使用NAT, &#8230; <a href="http://www.continuousdelivery.info/index.php/2011/11/14/casestudy-largesize/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>这篇文章是我在两年前写的，记录了一个150+人的软件团队（最多时近200人）如何在一个庞大的遗留系统上，通过逐步建立一个持续交付部署流水线，从而达到频繁发布的状态。最终在该团队的持续交付基础设施中，共有<strong>260台服务器用于构建、测试和部署（几乎全部是虚拟机）。而这个产品也可以每六周发布一次</strong>。</p>
<p><span id="more-205"></span></p>
<p><strong>一、在大规模项目团队中可能遇到的问题</strong></p>
<p>对于小规模、短周期的项目来说，团队与持续集成会相处地非常融洽。而对于大规模、长周期项目的初期来说，也不会有太多的问题。此时常见的也是基本的持续集成模式就是：Build-&gt;test-&gt;package。然而，只要时间稍长一点儿，持续集成就会发出坏味道了。此时的症状包括：</p>
<p><span style="font-size: 16px; font-family: Georgia, 'Bitstream Charter', serif; line-height: 24px;"> </span></p>
<ul>
<li>1. 作为开发人员
<ul>
<li>要等很长时间才能知道是否可以提交代码了。如果你遵守“频繁提交”的原则，那么百人团队不间断的提交，会使集成服务器一直处于繁忙状态，而你不得不等待他人的build过了以后，才能看到自己提交的结果。</li>
<li>要等很长时间才能知道我的提交是否通过了；</li>
<li>如果build失败了，要花很长时间才能知道是否和自己的修改相关；</li>
<li>既使提交了fix，也不知道自己的提交是否真的修复了这次构建；</li>
<li>构建经常处于失败状态。</li>
</ul>
</li>
<li>2. 作为测试人员
<ul>
<li>测试人员不知道到哪里拿哪一次的构建产物来进行测试；</li>
<li>发布经理不知道当前各种各样的测试部署环境中，到底部署了哪个版本，包括哪些新功能或修改的bug；</li>
<li>不确定在同一个构建里，所有组件的版本是否都是正确的；</li>
</ul>
</li>
</ul>
<p>&nbsp;</p>
<ul>
<li>3. 作为项目经理
<ul>
<li>不确定各个测试部署环境中的配置是否都与其上运行的构建相一致；</li>
<li>不确定测试人员测试的是否在正确的运行环境上运行了正确的版本；</li>
</ul>
</li>
</ul>
<ul>
<li>4. 其他方面的问题
<ul>
<li>所有的安装部署都需要手工操作。</li>
</ul>
</li>
</ul>
<p>以上这些问题会给你的发布管理带来无限的问题和风险。那么，是否因为这种“持续闹心”就放弃持续集成呢？回答当然是否定的。<strong>Do it more if it hurts you.</strong> 不要因问题的暴露而放弃，相反，应该欢呼。因为这反映了发布过程中的问题与风险，是时候解决它们了。</p>
<p><strong>二、如何解决大规模项目中的持续交付问题</strong></p>
<p>由于大项目本身的复杂性，其解决方案也不能一概而论。下面以某大型项目为例，介绍其中的几个解决方法。</p>
<p><strong>1、项目基本信息描述</strong></p>
<p>该项目最初就试图建立一个好的持续集成环境和基础。由于是一个遗留系统，费了很大劲儿，才能够得到可工作的软件。然而，由于队伍不断壮大，而且环境也在不断变化，持续集成很快就无法达不到其预期目标了。怎么办呢？</p>
<p><strong>项目背景:</strong></p>
<p>项目是一个具有可配置性的Web 门户产品，面向不同行业的市场，可自己定制门户。该项目有一个遗留的代码库，而且可以肯定的说，在今后的一年半之内是无法摆脱这个遗留代码库的。而且，很多紧耦合的、不必要的臃肿代码，同时根本不存在有价值的测试代码。现在我们在逐步地重写代码，但还是不能删除它们，因为某些网站还要依赖于旧代码。事实上，这是一个.NET平台上基于SOA的网站。</p>
<p><strong>开发团队情况：</strong></p>
<p>团队是一个敏捷分布开发团队（三地协作，均有开发人员，且有时差）。整个团队有150多人，分成十几个团队，每个团队都有一个完成的结构（BA/DEV/QA），其中有一个是项目持续集成团队（项目之初，大约有五六个人，工作负荷很大，项目运行一段时间后只要两个人就足够了）。使用SVN做版本管理工具，在Windows2003上使用NAT, MSbuild和batch脚本进行构建管理，最初使用CC.NET做为持续集成服务器，后来使用Cruise(Go)。</p>
<p><strong>初始的持续集成环境：</strong></p>
<p>上面所述的持续集成问题在项目一开始就出现了，因为该项目有一个庞大的遗留代码库，而且使用的基本持续集成方式（build-&gt;test-&gt;package）而且测试人员手工部署进行各类测试。</p>
<p><strong>其初始的持续集成环境如下所示：</strong><br />
<img src="http://p.blog.csdn.net/images/p_blog_csdn_net/tony1130/EntryImages/20090907/init.jpg" alt="init-CI" width="934" height="150" /></p>
<h2><strong>第一步目标：尽量减少团队之间影响</strong></h2>
<p><strong>方法：先化整为零，再化零为整</strong> ————根据团队划分代码（或者根据代码划分团队）。<br />
<strong>手段：DVCS＋私有持续集成服务器＋全局持续集成服务器</strong><br />
每个团队都使用GIT做为中间源代码管理工具。这样，团队人员可以先提交到GIT。每个团队有自己的持续集成环境。一但构建成功，触发将代码提交到中心的源代码库，并触发中心源代码的持续集成。有一个专职团队负责全局持续集成的结果跟踪。</p>
<p><strong>益处：</strong>1. 每个团队都可以天天提交代码 （如果这些代码没有让自己的构建失败，就说明至少能够通过初步检验）。<br />
2. 任何一个团队的构建坏了，并不影响整个项目，而只是一个团队。<br />
3. 有一个专职团队负责全局，不用每个团队都停下来。<br />
4. 如果全局持续集成失败了，不用所有的团队停下。</p>
<p><img src="http://p.blog.csdn.net/images/p_blog_csdn_net/tony1130/EntryImages/20090907/noname.jpg" alt="multiple pipeline" width="986" height="393" /></p>
<h2><strong>第二步目标：提高反馈速度</strong></h2>
<p><strong>方法：化整为零，再化零为整</strong>————测试分组运行。<br />
<strong>手段：</strong>并行化与中心仓库（Cruise的并行化与中心仓库）<br />
由于功能多且复杂，测试较多，运行很长。利用Cruise的并行化特点，每个团队将测试分成28组。一旦提交后，Cruise会将其放在28台机器上并行运行。运行后，将所有测试输出和结果上传到同一处（Cruise Server的中心仓库）。<br />
<strong>益处：</strong>1. 反馈时间大幅度缩短（原来30分钟以上，现在20分钟之内）。<br />
2. 易扩展：如果因测试增多而导致反馈周期长，可通过增加更多的机器解决。<br />
3. 易维护：对于测试分组和构建机器的增减来说，在Cruise中都非常容易，只要在同一处修改配置即可。<br />
4. 易追踪和Debug：所有的信息（包括artifacts）都放在同一处，能过Web访问。<br />
5. Single view (在同一个Web管理页面上，可以监控所有团队的构建状态)。</p>
<h2><strong>第三步目标：减少手工操作</strong></h2>
<p><strong> </strong><strong>方法：一键发布————自动化部署</strong><br />
<strong>手段：使用持续发布管理工具</strong>Cruise  (Cruise的dependency + Story Tracker plugin + audit)<br />
由于有很多个团队，每个团队都有多个测试环境。如果全部使用手工部署分花费很多时间。所以，每个团队建立三个构建管道，其目标分别为：(1)得到测试过的 installer；(2)部署到测试环境中；(3)将通过测试的installer部署到演示环境中。前一个构建成功后，就可以触发下一个（自动或手动）。<br />
<strong>益处：</strong>1. QA可以清晰识别需要测试哪个安装包，该安装包中含有哪些功能<br />
2. QA自己可能很容易地部署测试环境。<br />
3. 易于追踪功能的历史版本(在同一个pipeline中，所有的stage同一版本.而且在使用Pipeline dependency时，版本信息会向下游传递)。<br />
4. 易于掌握对各种部署环境的管理。<br />
<img src="http://p.blog.csdn.net/images/p_blog_csdn_net/tony1130/EntryImages/20090907/deploy.jpg" alt="pipeline dependency" width="934" height="540" /></p>
<p><strong>使用上述手段后，该项目的持续交付已入佳境。目前可以做到</strong>：</p>
<ol>
<li>所有的构建和部署都是自动化的；</li>
<li>开发人员最多在20分钟内就会得到反馈。</li>
<li>对于每种环境来说，可以做到每天部署四次。</li>
<li>部署无差错：因为是自动化过程，每次的执行步骤都一样。</li>
<li>机器资源复用：Cruise自动向165台机器上分发工作进行构建和部署。</li>
<li>所有信息都显示在一个屏幕上（Single dashboard view of everything!）</li>
<li>开发人员非常高兴：他们可以多次提交而不影响他人。</li>
<li>测试人员非常高兴：他们可以很快地得到好的installer，通过自己点一下按钮就完成部署工作。</li>
<li>管理人员非常高兴：他们可以马上了解当前的项目状态（哪些版本在测试中，那些版本已经演示了）。</li>
<li> 很容易了解每个版本里包括哪些功能和修复了哪些缺陷。</li>
</ol>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.continuousdelivery.info/index.php/2011/11/14/casestudy-largesize/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>用veewee创建vagrant的虚拟机</title>
		<link>http://www.continuousdelivery.info/index.php/2011/11/04/veewee-vargrant/</link>
		<comments>http://www.continuousdelivery.info/index.php/2011/11/04/veewee-vargrant/#comments</comments>
		<pubDate>Fri, 04 Nov 2011 02:56:37 +0000</pubDate>
		<dc:creator>乔梁</dc:creator>
				<category><![CDATA[Tools]]></category>
		<category><![CDATA[DevOps]]></category>
		<category><![CDATA[veewee]]></category>
		<category><![CDATA[工具]]></category>
		<category><![CDATA[虚拟机]]></category>

		<guid isPermaLink="false">http://www.continuousdelivery.info/?p=192</guid>
		<description><![CDATA[感谢larrycai的投稿。 原文链接：https://github.com/larrycai/blog/blob/master/cn/veewee_create_vm.mkd 简介 虚拟机有很多好处，不仅仅节省硬件资源，而且还可以快速切换系统环境，会在软件开发中起到极大作用。 在上一篇vagrant和jenkins的文章中我们说到了vagrant这个工具，你必须要先有一个盒子：vagrant box，它是vagrant对virtualbox虚拟机的进一步封装。将virtualbox虚拟机转变成vagrant的盒子有点麻烦，可以参见vagrant的说明，所以，大家都是找一个现成的盒子来用。 但是，没有更好的办法了吗？现在网络的开放精神真是强大，你能想到的一般都存在了，它就是我要介绍的veewee，它的功能就是从你的ISO光盘开始，准备好你需要的vagrant虚拟机（盒子）。 veewee使用入门 这一块有篇英文文章Building Vagrant boxes with veewee讲的不错，github上的官方网站veewee也是蛮详尽的，我在这儿快速的重复一下，再加上一些自己的小技巧。 安装 首先安装好vagrant，virtualbox。veewee实际上是vagrant的一个插件，也是ruby写的，安装很方便。 rdccaiy@ubuntu:~ $ sudo gem install veewee 使用 安装好以后，你可以使用下面的命令试试到底有何奥妙了。 rdccaiy@ubuntu:~ $ vagrant basebox templates The following templates are available: vagrant basebox define '&#60;boxname&#62;' 'Fedora-14-amd64-netboot' vagrant basebox &#8230; <a href="http://www.continuousdelivery.info/index.php/2011/11/04/veewee-vargrant/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>感谢<a title="larrycai" href="https://github.com/larrycai" target="_blank">larrycai</a>的投稿。<br />
原文链接：<a title="jenkins vagrant" href="https://github.com/larrycai/blog/blob/master/cn/veewee_create_vm.mkd" target="_blank">https://github.com/larrycai/blog/blob/master/cn/veewee_create_vm.mkd</a></p>
<h1>简介</h1>
<p>虚拟机有很多好处，不仅仅节省硬件资源，而且还可以快速切换系统环境，会在软件开发中起到极大作用。</p>
<p>在<a href="http://www.continuousdelivery.info/index.php/2011/10/27/vagrant_jenkins_vm/">上一篇vagrant和jenkins的文章</a>中我们说到了vagrant这个工具，你必须要先有一个盒子：<em>vagrant box</em>，它是vagrant对virtualbox虚拟机的进一步封装。将virtualbox虚拟机转变成vagrant的盒子有点麻烦，可以参见<a href="http://vagrantup.com/">vagrant的说明</a>，所以，大家都是找一个现成的盒子来用。</p>
<p>但是，没有更好的办法了吗？现在网络的开放精神真是强大，你能想到的一般都存在了，它就是我要介绍的<a href="http://github.com/jedi4ever/veewee">veewee</a>，它的功能就是从你的ISO光盘开始，准备好你需要的vagrant虚拟机（盒子）。</p>
<h1><span id="more-192"></span>veewee使用入门</h1>
<p>这一块有篇英文文章<a href="http://www.ducea.com/2011/08/15/building-vagrant-boxes-with-veewee/">Building Vagrant boxes with veewee</a>讲的不错，github上的官方网站<a href="http://github.com/jedi4ever/veewee">veewee</a>也是蛮详尽的，我在这儿快速的重复一下，再加上一些自己的小技巧。</p>
<h2>安装</h2>
<p>首先安装好vagrant，virtualbox。veewee实际上是vagrant的一个插件，也是ruby写的，安装很方便。</p>
<pre><code>rdccaiy@ubuntu:~ $ sudo gem install veewee
</code></pre>
<h2>使用</h2>
<p>安装好以后，你可以使用下面的命令试试到底有何奥妙了。</p>
<pre><code>rdccaiy@ubuntu:~ $ vagrant basebox templates
The following templates are available:
vagrant basebox define '&lt;boxname&gt;' 'Fedora-14-amd64-netboot'
vagrant basebox define '&lt;boxname&gt;' 'ubuntu-10.04.2-server-i386-netboot'
vagrant basebox define '&lt;boxname&gt;' 'CentOS-6.0-x86_64-netboot'
vagrant basebox define '&lt;boxname&gt;' 'CentOS-4.8-i386'
vagrant basebox define '&lt;boxname&gt;' 'Debian-5.0.8-amd64-netboot'
vagrant basebox define '&lt;boxname&gt;' 'CentOS-5.6-i386'
vagrant basebox define '&lt;boxname&gt;' 'CentOS-5.6-i386-netboot'
vagrant basebox define '&lt;boxname&gt;' 'freebsd-8.2-experimental'
vagrant basebox define '&lt;boxname&gt;' 'Fedora-15-i386-netboot'
vagrant basebox define '&lt;boxname&gt;' 'ubuntu-11.04-server-i386'
vagrant basebox define '&lt;boxname&gt;' 'ubuntu-8.04.4-server-amd64'
vagrant basebox define '&lt;boxname&gt;' 'archlinux-x86_64'
..
</code></pre>
<p>basebox就是veewee插件装好以后变成的vagrant中的一个任务，从结果中可以看到已经有好多模板了，怎么用呢，先建一个目录（如veewee），然后再创建机器。</p>
<pre><code>rdccaiy@ubuntu:~$ mkdir veewee ; cd veewee
rdccaiy@ubuntu:~/veewee$ vagrant basebox define 'ubuntu1104' 'ubuntu-11.04-server-i386'
</code></pre>
<p>创建之后，查看一下结果。</p>
<pre><code>rdccaiy@ubuntu:~/veewee$ find .
./definitions/ubuntu1104
./definitions/ubuntu1104/postinstall.sh
./definitions/ubuntu1104/preseed.cfg
./definitions/ubuntu1104/definition.rb
</code></pre>
<p><code>definition.rb</code>中指定了iso文件</p>
<pre><code>Veewee::Session.declare({
  :cpu_count =&gt; '1', :memory_size=&gt; '384',
  :disk_size =&gt; '10140', :disk_format =&gt; 'VDI', :hostiocache =&gt; 'off',
  :os_type_id =&gt; 'Ubuntu',
  :iso_file =&gt; "ubuntu-11.04-server-i386.iso",
  :iso_src =&gt; "http://releases.ubuntu.com/11.04/ubuntu-11.04-server-i386.iso",
</code></pre>
<p>iso文件就是操作系统的安装光盘，建议先从网上下载，veewee要求本地就必须放在和<code>definitions</code>平级（也就是上面veewee的下面一级）的<code>iso</code>目录下。</p>
<pre><code>rdccaiy@ubuntu:~/veewee$ ls iso
ubuntu-11.04-server-i386.iso
</code></pre>
<p>闲话少说，让veewee工作起来吧！</p>
<pre><code>rdccaiy@ubuntu:~/veewee$ vagrant basebox build ubuntu1104
</code></pre>
<p>理论上它应该能无图形化执行，不过我的环境里还是需要打开X-Windows，你应该看到virtualbox虚拟机起来，然后自动按键运行，中间还会重启，我蛮顺利的做出了虚拟机，真是很棒，如下图。（不知怎么的，每次看到电脑帮我自动打字，我很开心）</p>
<p><a href="http://www.continuousdelivery.info/wp-content/uploads/2011/11/veewee.png"><img class="aligncenter size-full wp-image-193" title="veewee" src="http://www.continuousdelivery.info/wp-content/uploads/2011/11/veewee.png" alt="veewee, 持续交付, 工具" width="923" height="668" /></a></p>
<p>&nbsp;</p>
<p>可以看到在终端上的漂亮log</p>
<pre><code>rdccaiy@ubuntu:~/veewee$ vagrant basebox build ubuntu1104

Verifying the isofile ubuntu-11.04-server-i386.iso is ok.
We found no good state so we are destroying the previous machine+disks
VBoxManage unregistervm  'ubuntu1104' --delete
Deleting vm ubuntu1104
Deleting disk /home/rdccaiy/VirtualBox VMs/ubuntu1104/ubuntu1104.vdi
VBoxManage closemedium disk '/home/rdccaiy/VirtualBox VMs/ubuntu1104/ubuntu1104.vdi' --delete
Creating vm ubuntu1104 : 384M - 1 CPU - Ubuntu
Creating new harddrive of size 10140
VBoxManage createhd --filename '/home/rdccaiy/VirtualBox VMs/ubuntu1104/ubuntu1104.vdi' --size '10140' --format vdi &gt; /dev/null
Attaching disk: /home/rdccaiy/VirtualBox VMs/ubuntu1104/ubuntu1104.vdi
Mounting cdrom: /home/rdccaiy/veewee/iso/ubuntu-11.04-server-i386.iso
Waiting for the machine to boot
....
</code></pre>
<p>时间应该蛮长的，一切的OK的话，你就能得到vagrant的虚拟机了。</p>
<pre><code>rdccaiy@ubuntu:~/veewee$ vagrant basebox export 'ubuntu1104'
</code></pre>
<p>然后就用vagrant的方法去尝试了，如<code>vagrant box add ‘ubuntu1104’ ubuntu1104.box</code>。</p>
<p>如果你要的操作系统模板没找到，可以到<a href="https://github.com/jedi4ever/veewee/tree/master/templates">veewee的最新代码中的模板库看看</a></p>
<h1>veewee的原理</h1>
<p>如果你对操作系统安装（如linux）熟悉的话，应该能很快琢磨出道道来，veewee调用了<a href="https://www.virtualbox.org/manual/ch08.html">virtualbox的API-VBoxManage</a>来控制虚拟机，如构建裸盘（<code>VBoxManage createhd</code>），以及光盘的加载。</p>
<p>现在再来看看相关的三个文件是干嘛的。</p>
<ul>
<li><code>definition.rb</code> 中是你的一些基本硬件配置，每个模板都差不多，中间一段定义了机器启动时如何加载，注意不同的操作系统会用不同的方法，redhat是kickstart，ubuntu是preseed</li>
<li><code>preseed.cfg</code>中就是ubuntu自动安装的配置参数，如果是SuSE，那就是<code>autoinst.xml</code>了，它来完成你的初始光盘安装。</li>
<li><code>postinstall.sh</code> 顾名思义就是装完操作系统后的后续工作，这和你想要的配置有关，为了vagrant，要加上相应的包，当然别做复杂了，记住你只是做一个操作系统的初始虚拟机，具体里面的东西可以让vagrant用puppet或chef来完成。</li>
</ul>
<h1>总结</h1>
<p>这篇文章主要简单讲了一下用<a href="http://github.com/jedi4ever/veewee">veewee</a>这个软件来如何快速创建vagrant虚拟机，有没有体会到持续交付中反复提到的配置管理了，所有的东西都写成配置文件，然后有软件自动生成你要的东西，慢慢试试再体会吧。</p>
<p>下次我该来谈谈<a href="http://puppetlabs.com/">puppet</a>了，而且是无主机模式的，给些建议鼓励鼓励吧 <a href="http://weibo.com/larrycai">@larrycai</a>，让我持续交付。</p>
<h1>参考</h1>
<ol>
<li>larry的英文博客：http://codeslife.com/2011/10/25/create-virtualbox-on-fly-using-veewee/</li>
<li>veewee的官网：http://github.com/jedi4ever/veewee</li>
<li>老外介绍的如何用veewee建立vagrant盒子：<a href="http://www.ducea.com/2011/08/15/building-vagrant-boxes-with-veewee/">Building Vagrant boxes with veewee</a></li>
<li>VirtualBox API &#8211; VBoxManage: https://www.virtualbox.org/manual/ch08.html</li>
<li>持续交付：http://www.continuousdelivery.info/</li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://www.continuousdelivery.info/index.php/2011/11/04/veewee-vargrant/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>《持续交付》封面上的故事——福斯铁路桥</title>
		<link>http://www.continuousdelivery.info/index.php/2011/11/03/bridge/</link>
		<comments>http://www.continuousdelivery.info/index.php/2011/11/03/bridge/#comments</comments>
		<pubDate>Wed, 02 Nov 2011 23:59:43 +0000</pubDate>
		<dc:creator>乔梁</dc:creator>
				<category><![CDATA[持续交付]]></category>
		<category><![CDATA[推荐书目]]></category>

		<guid isPermaLink="false">http://www.continuousdelivery.info/?p=187</guid>
		<description><![CDATA[不知道有多少人把《持续交付》一书的前言看全了。最后一部分讲的是福斯铁路桥（本站Logo上的这座美丽的桥），并把它和软件做类比。现摘录如下： 福斯铁路桥是英国第一座使用钢铁建造的大桥。其钢铁使用最新的西门子马丁平炉工艺制造，并由在苏格兰的两个钢铁厂和威尔士的一个钢铁厂交付。钢铁是以管状桁架的形式运送的，这是英国首次使用大规模生产的零部件组装桥梁。与早期的桥梁不同，设计师John Fowler爵士，Benjamin Baker爵士和Allan Stewart计算了建筑压发生率，以便减少后续的维护成本，并计算了风压和温度对结构的影响，而这很像软件开发中的功能需求和非功能需求。他们还监督了桥梁建设，以确保这些要求都能得到满足。 当时有4600名工人参与建造该桥，其中不幸死亡约一百人，致残数百人。然而它仍是工业革命的一个奇迹，因为1890年建成时，它是世界上最长的桥，而到了21世纪初，它仍是世界第二长的悬臂大桥。就像长生命周期的软件项目一样，这座桥需要持续维护。这已在设计时考虑到了，大桥配套工程中不但有一个维护车间和场地，而且在Dalmeny车站还有一个50个房间的铁路“聚居点”。据估计，该桥的使用寿命还有一百多年。]]></description>
			<content:encoded><![CDATA[<p>不知道有多少人把《持续交付》一书的前言看全了。最后一部分讲的是福斯铁路桥（本站Logo上的这座美丽的桥），并把它和软件做类比。现摘录如下：</p>
<p><strong>福斯铁路桥</strong>是英国第一座使用钢铁建造的大桥。其钢铁使用最新的西门子马丁平炉工艺制造，并由在苏格兰的两个钢铁厂和威尔士的一个钢铁厂交付。钢铁是以管状桁架的形式运送的，这是英国首次使用大规模生产的零部件组装桥梁。与早期的桥梁不同，设计师John Fowler爵士，Benjamin Baker爵士和Allan Stewart计算了建筑压发生率，以便减少后续的维护成本，并计算了风压和温度对结构的影响，<strong>而这很像软件开发中的功能需求和非功能需求。</strong>他们还监督了桥梁建设，以确保这些要求都能得到满足。</p>
<p>当时有4600名工人参与建造该桥，其中不幸死亡约一百人，致残数百人。然而它仍是工业革命的一个奇迹，因为1890年建成时，它是世界上最长的桥，而到了21世纪初，它仍是世界第二长的悬臂大桥。就像长生命周期的软件项目一样，这座桥需要持续维护。这已在设计时考虑到了，大桥配套工程中不但有一个维护车间和场地，而且在Dalmeny车站还有一个50个房间的铁路“聚居点”。据估计，该桥的使用寿命还有一百多年。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.continuousdelivery.info/index.php/2011/11/03/bridge/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>使用vagrant+jenkins来管理虚拟机的技巧</title>
		<link>http://www.continuousdelivery.info/index.php/2011/10/27/vagrant_jenkins_vm/</link>
		<comments>http://www.continuousdelivery.info/index.php/2011/10/27/vagrant_jenkins_vm/#comments</comments>
		<pubDate>Thu, 27 Oct 2011 13:36:42 +0000</pubDate>
		<dc:creator>乔梁</dc:creator>
				<category><![CDATA[持续交付]]></category>
		<category><![CDATA[DevOps]]></category>
		<category><![CDATA[工具]]></category>
		<category><![CDATA[最佳实践]]></category>
		<category><![CDATA[虚拟机]]></category>

		<guid isPermaLink="false">http://www.continuousdelivery.info/?p=157</guid>
		<description><![CDATA[感谢larrycai的投稿。 简介 虚拟机有很多好处，不仅仅节省硬件资源，而且还可以快速切换系统环境，显然会在软件开发中起到极大作用。 在《持续交付》第十一章（11.7.1）中就提到了虚拟机环境的管理。如下图 它描述的是在你的持续集成的Jenkins CI服务器（以下简称jenkins）中，需要各种服务器来测试一个应用。我们可以快速的从虚拟机的VMM模板库中，启动需要的各种类型虚拟机，而不是每个都重新安装（省时），完成测试，产生报告后，也快速消失（省钱）。 让我们一起来看看一种漂亮的实现方案vagrant+jenkins实现技巧。 基本知识 vagrant 不同的虚拟机技术（virtualbox，vmware，xen/kvm等等)可能用不同的方法管理，vagrant是virtualbox的前端，它简化了virtualbox虚拟机的操作，而且增加了对自动化（provisioning)的puppet/chef的支持，这里就不详细介绍。vagrant的入门介绍已经很详细了，有一篇博客也可以借鉴一下。 你要知道的就是下面的几个命令 $ cd ubuntu1104-vm # 进入已有的 ubuntu 11.04 虚拟机目录 $ vagrant up # 启动 ubuntu 虚拟机 $ vagrant ssh -c "pwd" /home/vagrant $ vagrant halt # 停止虚拟机 jenkins CI jenkins &#8230; <a href="http://www.continuousdelivery.info/index.php/2011/10/27/vagrant_jenkins_vm/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>感谢<a title="larrycai" href="https://github.com/larrycai" target="_blank">larrycai</a>的<a title="jenkins vagrant" href="https://github.com/larrycai/blog/blob/master/cn/vagrant_jenkins_ci.mkd" target="_blank">投稿</a>。</p>
<h1>简介</h1>
<p>虚拟机有很多好处，不仅仅节省硬件资源，而且还可以快速切换系统环境，显然会在软件开发中起到极大作用。</p>
<p>在《持续交付》第十一章（11.7.1）中就提到了虚拟机环境的管理。如下图<br />
<a href="http://www.continuousdelivery.info/wp-content/uploads/2011/10/1.png"><img class="aligncenter size-full wp-image-159" title="通过虚拟机创建环境" src="http://www.continuousdelivery.info/wp-content/uploads/2011/10/1.png" alt="持续交付 虚拟机创建环境" width="707" height="318" /></a>它描述的是在你的持续集成的Jenkins CI服务器（以下简称jenkins）中，需要各种服务器来测试一个应用。我们可以快速的从虚拟机的VMM模板库中，启动需要的各种类型虚拟机，而不是每个都重新安装（省时），完成测试，产生报告后，也快速消失（省钱）。</p>
<p>让我们一起来看看一种漂亮的实现方案vagrant+jenkins实现技巧。</p>
<h1><span id="more-157"></span>基本知识</h1>
<h2>vagrant</h2>
<p>不同的虚拟机技术（virtualbox，vmware，xen/kvm等等)可能用不同的方法管理，<a href="http://vagrantup.com/">vagrant</a>是virtualbox的前端，它简化了virtualbox虚拟机的操作，而且增加了对自动化（provisioning)的puppet/chef的支持，这里就不详细介绍。<a href="http://vagrantup.com/">vagrant</a>的入门介绍已经很详细了，有一篇<a href="http://blog.crowdint.com/2011/06/21/vagrant.html">博客</a>也可以借鉴一下。</p>
<p>你要知道的就是下面的几个命令</p>
<pre><code>$ cd ubuntu1104-vm # 进入已有的 ubuntu 11.04 虚拟机目录
$ vagrant up # 启动 ubuntu 虚拟机
$ vagrant ssh -c "pwd"
/home/vagrant
$ vagrant halt # 停止虚拟机
</code></pre>
<h2>jenkins CI</h2>
<p>jenkins 是一个最常用的持续集成服务器，可单独运行或者放在Web服务器中运行。</p>
<p>直接启动一个任务（jenkins job)去调用vagrant操作虚拟机不是一个很好的方式，因为启动jenkins的用户（如tomcat）的权限都比较小，以防止任务误操作。</p>
<p>幸好jenkins有个超级棒的主从模式（master/slave)来解决。</p>
<h1>方案搭建</h1>
<h2>建立vagrant用户</h2>
<p>最好先在一个机器上（可以和jenkins主机不在一起）创建一个vagrant用户，建立一套vagrant的用户环境。</p>
<p>因为无密码访问，所以要配好ssh环境，我们可以重用vagrant虚拟机的公私密钥，如下面的 IdentityFile就是私钥。</p>
<pre><code>vagrant@host:~/vm/ubuntu1104$ vagrant ssh_config
Host default
  HostName 127.0.0.1
  User vagrant
  Port 2222
  UserKnownHostsFile /dev/null
  StrictHostKeyChecking no
  PasswordAuthentication no
  IdentityFile /var/lib/gems/1.8/gems/vagrant-0.8.7/keys/vagrant
  IdentitiesOnly yes
</code></pre>
<p>把公私密钥拷到vagrant用户的.ssh目录下。</p>
<pre><code>vagrant@host:~$ mkdir .ssh
vagrant@host:~$ cp /var/lib/gems/1.8/gems/vagrant-0.8.7/keys/vagrant .ssh/id_rsa
vagrant@host:~$ chmod 600 .ssh/id_rsa
vagrant@host:~$ cat /var/lib/gems/1.8/gems/vagrant-0.8.7/keys/vagrant.pub &gt;&gt; .ssh/authorized_keys
</code></pre>
<h2>jenkins slave设置</h2>
<p>然后到jenkins主机的 系统管理-&gt;管理节点-&gt;新建节点 来增加vagrant虚拟机节点，如下图。</p>
<p><a href="http://www.continuousdelivery.info/wp-content/uploads/2011/10/2.png"><img class="aligncenter size-full wp-image-160" title="持续交付 hudson" src="http://www.continuousdelivery.info/wp-content/uploads/2011/10/2.png" alt="持续交付 hudson" width="807" height="601" /></a>例子中，vagrant节点和jenkins主机在一台机器上，所以是localhost，配好了私有密钥，并且设置标签为vagrant-vm</p>
<h2>jenkins 任务设置</h2>
<p>现在可以设置新的任务了，选定自由风格（freestyle)，如下图<a href="http://www.continuousdelivery.info/wp-content/uploads/2011/10/2.png"></a></p>
<p><a href="http://www.continuousdelivery.info/wp-content/uploads/2011/10/2.png"></a><a href="http://www.continuousdelivery.info/wp-content/uploads/2011/10/3.png"><img class="aligncenter size-full wp-image-161" title="配置jenkins任务" src="http://www.continuousdelivery.info/wp-content/uploads/2011/10/3.png" alt="持续交付 配置jenkins任务" width="567" height="396" /></a>限定它去vagrant-vm去执行，到时它就会触发jenkins从机(slave)的启动。</p>
<p><a href="http://www.continuousdelivery.info/wp-content/uploads/2011/10/4.png"><img class="aligncenter size-full wp-image-162" title="持续交付 hudson配置" src="http://www.continuousdelivery.info/wp-content/uploads/2011/10/4.png" alt="持续交付 hudson配置" width="476" height="230" /></a>然后设置一个构建内容，就是启动虚拟机，执行命令（真实情况会用puppet安装，并进行测试）。</p>
<p>最后就可以让它跑起来。</p>
<h1>总结</h1>
<p>这篇文章主要简单讲了一下在jenkins中管理虚拟机的一种方案，自动化的安装<a href="http://puppetlabs.com/">puppet</a>并没提到，可自己尝试。另外vagrant创立虚拟机也没有谈到，一般可以用<a href="http://github.com/jedi4ever/veewee">veewee</a>这个软件来完成，有空下次讲。</p>
<h1>参考</h1>
<ol>
<li>larry的英文博客：http://codeslife.com/2011/10/21/make-ci-easier-with-jenkins-ci-and-vagrant/</li>
<li>stackoverflow的问题讨论：<a href="http://stackoverflow.com/questions/6941547">How to combine Vagrant with Jenkins for the perfect Continuous Integration Environment?</a></li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://www.continuousdelivery.info/index.php/2011/10/27/vagrant_jenkins_vm/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>《持续交付》中文版已上架销售，欢迎对译文进行意见反馈。</title>
		<link>http://www.continuousdelivery.info/index.php/2011/10/20/cd-zh-published/</link>
		<comments>http://www.continuousdelivery.info/index.php/2011/10/20/cd-zh-published/#comments</comments>
		<pubDate>Thu, 20 Oct 2011 02:27:10 +0000</pubDate>
		<dc:creator>乔梁</dc:creator>
				<category><![CDATA[持续交付]]></category>
		<category><![CDATA[推荐书目]]></category>
		<category><![CDATA[最佳实践]]></category>

		<guid isPermaLink="false">http://www.continuousdelivery.info/?p=151</guid>
		<description><![CDATA[《持续交付》中文版已于2011年10月17日上架销售。 该书由Jez Humble 和 Dave Farley历时三年完成， Martin Fowler为该书作序，并称其为“2010年最重要的持续书籍”， 同时，在2011年8月获得 “Jolt 杰出奖”。 从下面网站均可购得： 中国互动出版网 当当网 卓越亚马逊 如果您在书中发现有些地方翻译欠妥，您有多种渠道反馈建议。 请在下面直接回复即可。内容包括：问题所在页号、原文句子，以及您的建议。 点击这里，进入图灵社区的《持续交付》专栏勘误。 直接邮件给译者，邮箱是：qiaoliang.email@gmail.com 谢谢！ &#160;]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.continuousdelivery.info/wp-content/uploads/2011/10/cd-book.jpg"><img class="alignleft size-full wp-image-153" title="持续交付中文版" src="http://www.continuousdelivery.info/wp-content/uploads/2011/10/持续交付中文版.jpg" alt="持续交付, continuous delivery" width="112" height="140" /></a>《持续交付》中文版已于2011年10月17日上架销售。</p>
<p>该书由Jez Humble 和 Dave Farley历时三年完成，</p>
<p>Martin Fowler为该书作序，并称其为“2010年最重要的持续书籍”，</p>
<p>同时，在2011年8月获得 “Jolt 杰出奖”。</p>
<p>从下面网站均可购得：</p>
<ul>
<li><a title="持续交付中文版 在 中国互动出版网" href="http://search.china-pub.com/s/?key1=%u6301%u7eed%u4ea4%u4ed8&amp;type=&amp;pz=1&amp;t=2" target="_blank">中国互动出版网</a></li>
<li><a title="持续交付 中文版 在 当当网" href="http://product.dangdang.com/product.aspx?product_id=22513036&amp;ref=search-1-pub" target="_blank">当当网</a></li>
<li><a title="持续交付 在 卓越" href="http://www.amazon.cn/%E6%8C%81%E7%BB%AD%E4%BA%A4%E4%BB%98-%E5%8F%91%E5%B8%83%E5%8F%AF%E9%9D%A0%E8%BD%AF%E4%BB%B6%E7%9A%84%E7%B3%BB%E7%BB%9F%E6%96%B9%E6%B3%95-%E8%8B%B1-Jez-Humble%E3%80%80David-Farley/dp/B005V9BB1M/ref=sr_1_1?ie=UTF8&amp;qid=1319077207&amp;sr=8-1" target="_blank">卓越亚马逊</a></li>
</ul>
<p>如果您在书中发现有些地方翻译欠妥，您有多种渠道反馈建议。</p>
<ol>
<li>请在下面直接回复即可。内容包括：问题所在页号、原文句子，以及您的建议。</li>
<li>点击<a title="持续交付" href="http://www.ituring.com.cn/book/758" target="_blank">这里</a>，进入图灵社区的《持续交付》专栏勘误。</li>
<li>直接邮件给译者，邮箱是：qiaoliang.email@gmail.com</li>
</ol>
<p>谢谢！</p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.continuousdelivery.info/index.php/2011/10/20/cd-zh-published/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>持续交付成熟度模型更新，新版本v1.2发布</title>
		<link>http://www.continuousdelivery.info/index.php/2011/10/17/cd-v12/</link>
		<comments>http://www.continuousdelivery.info/index.php/2011/10/17/cd-v12/#comments</comments>
		<pubDate>Mon, 17 Oct 2011 07:26:09 +0000</pubDate>
		<dc:creator>乔梁</dc:creator>
				<category><![CDATA[持续交付]]></category>
		<category><![CDATA[DevOps]]></category>
		<category><![CDATA[成熟度模型]]></category>
		<category><![CDATA[推荐书目]]></category>
		<category><![CDATA[最佳实践]]></category>
		<category><![CDATA[部署流水线]]></category>

		<guid isPermaLink="false">http://www.continuousdelivery.info/?p=139</guid>
		<description><![CDATA[《持续交付》一书中提供的“持续交付成熟度模型”是1.0版本。 这是经过再次调整的改进版，更具有指导性和可操作性。 使用说明： 建议使用该模型进行现状分析，发现改进点，不建议将其作为绩效衡量的标准。 一、七个维度 它们分别是： 1. 持续集成（Continuous Integration) 2. 环境与部署（Environments and Deployments） 3. 可视化与可追踪性（Visibility and Traceability） 4. 测试（Testing） 5. 数据管理（Data Management） 6. 配置管理（Configuration Management） 7. 组织协调性（Organisational Alignment） 二、每个维度又分成五个级别，它们分别是： 一级：阻碍级（Regressive） 二级：可重复级(Repeatable) 三级：可定义级 四级：可定量级（Quantitatively managed） 五级：优化级（Optimizing） 其中，持续集成维度的五个级别分别是： 一级：阻碍级（Regressive） 1. 软件的构建过程是手工的。 2. &#8230; <a href="http://www.continuousdelivery.info/index.php/2011/10/17/cd-v12/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>《持续交付》一书中提供的“持续交付成熟度模型”是1.0版本。</p>
<p>这是经过再次调整的改进版，更具有指导性和可操作性。</p>
<p><strong>使用说明：</strong></p>
<p>建议使用该模型进行现状分析，发现改进点，不建议将其作为绩效衡量的标准。</p>
<h2>一、七个维度</h2>
<p>它们分别是：</p>
<p>1. <strong>持续集成</strong>（Continuous Integration)</p>
<p>2. <strong>环境与部署</strong>（Environments and Deployments）</p>
<p>3. <strong>可视化与可追踪性</strong>（Visibility and Traceability）</p>
<p>4. <strong>测试</strong>（Testing）</p>
<p>5. <strong>数据管理</strong>（Data Management）</p>
<p>6. <strong>配置管理</strong>（Configuration Management）</p>
<p>7. <strong>组织协调性</strong>（Organisational Alignment）</p>
<h2>二、每个维度又分成五个级别，它们分别是：</h2>
<p>一级：<strong>阻碍级</strong>（Regressive）</p>
<p>二级：<strong>可重复级</strong>(Repeatable)</p>
<p>三级：<strong>可定义级</strong></p>
<p>四级：<strong>可定量级</strong>（Quantitatively managed）</p>
<p>五级：<strong>优化级</strong>（Optimizing）</p>
<h2>其中，<strong>持续集成维度</strong>的五个级别分别是：</h2>
<p>一级：<strong>阻碍级</strong>（Regressive）</p>
<p>1.	软件的构建过程是手工的。<br />
2.	构建过程冗长，而且其中的主要步骤常常出错。</p>
<p>二级：<strong>可重复级</strong>(Repeatable)</p>
<p>1.	在开发人员的代码上进行定期的自动化构建和单元测试。<br />
2.	利用自动化过程，能够从源控制中重新生成任意一个构建版本。<br />
3.	开发人员的提交频率是不定的。</p>
<p>三级：<strong>已定义级</strong></p>
<p>1.	每次提交都会触发构建和各类测试。<br />
2.	公共工具集中的脚本或工件得到重用。</p>
<p>四级：<strong>可定量级</strong>（Quantitatively managed）</p>
<p>1.	构建数据度量项被收集，高度可视化，并执行相应的改进活动。<br />
2.	构建失败不会没人管。所有团队成员至少每天提交一次。<br />
3.	尽可能在最后时刻（即将发布时）才拉发布分支。</p>
<p>五级：<strong>优化级</strong>（Optimizing）</p>
<p>1.	随时可以从主干上拿到已全面集成且生产环境可部署的构建版本。<br />
2.	关注点是：随着对代码质量信心不断提交，能够进行更加频繁的提交。</p>
<h2><strong>环境与部署</strong>的五个级别分别是：</h2>
<p>一级：<strong>阻碍级</strong>（Regressive）</p>
<p>1.	手工准备环境，无适当方法管理环境冲突。<br />
2.	手工部署软件。</p>
<p>二级：<strong>可重复级</strong>(Repeatable)</p>
<p>1.	环境已被定义，并可自动化地准备和控制。<br />
2.	部署操作是手工和自动化相结合才能完成。</p>
<p>三级：<strong>可定义级</strong></p>
<p>1.	开发和测试环境是全面自动化且自服务的。<br />
2.	已具备 “点击按钮即可向任意环境进行部署”的能力。<br />
3.	为了完成自己的工作，每个人都有相应权限访问并操作相应的环境。</p>
<p>四级：<strong>可定量级</strong>（Quantitatively managed）</p>
<p>1.	协调的部署管理。<br />
2.	发布计划自动产生。<br />
3.	对所有的失败进行根因分析。<br />
4.	回滚流程被脚本化，并被管理起来。<br />
5.	建立了环境和系统健康状态指示板（Dashboard），其上显示的数据被监控和报告。</p>
<p>五级：<strong>优化级</strong>（Optimizing）</p>
<p>1.	环境的准备是全自动化的。<br />
2.	已具备根据需求快速重建完整环境和基础设施的能力。<br />
3.	端到端的业务度量项被监控。</p>
<p>这里可以下载<a href="http://download.csdn.net/detail/tony1130/3690829">全部</a>。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.continuousdelivery.info/index.php/2011/10/17/cd-v12/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

