<?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>Juven Xu</title>
	<atom:link href="http://www.juvenxu.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.juvenxu.com</link>
	<description>Maven, 开源, Java, 敏捷</description>
	<lastBuildDate>Wed, 02 May 2012 13:31:30 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>敏捷咨询，起步</title>
		<link>http://www.juvenxu.com/2012/05/02/agile-consultant-start/</link>
		<comments>http://www.juvenxu.com/2012/05/02/agile-consultant-start/#comments</comments>
		<pubDate>Wed, 02 May 2012 13:26:12 +0000</pubDate>
		<dc:creator>juvenxu</dc:creator>
				<category><![CDATA[总结]]></category>
		<category><![CDATA[咨询]]></category>
		<category><![CDATA[敏捷]]></category>

		<guid isPermaLink="false">http://www.juvenxu.com/?p=723</guid>
		<description><![CDATA[从三月中起开始从事敏捷实践咨询工作，至此一月有余，这期间经历很大的角色转变，从程序员转向敏捷实践教练，需要不停的挑战自己原有的思维习惯，挺难的，不过我一直对自己说，“放空自己，用心去体验”，这么一想后似乎也没那么难了。 4月16号我发了条微博： 第一次正式做敏捷咨询工作，每天各种挑战，很多东西要学，不确定自己能做到多好，但我决定坚持用积极的态度去体验并思考每天发生的一切。 对此@powerfish给了一条中肯的建议： 加油！我也觉得咨询是很有挑战的工作。我觉得每天维持6小时的工作，2小时的反思，每周维持4天工作，1天反思，是非常必要的！ 虽然我暂时还不能做到每天2小时的反思，但我非常同意反思的重要性并努力在做，这也是写本文的初衷之一。反思好比是敏捷开发流程中的回顾会议，只有不断的观察自己，找出优秀的地方加以提倡保持，找出存在的问题加以更正改善，自己才能变得更好。下面简述几条我感受最深的体验。 视角转换 我一直是个地地道道的程序员，计算机科班毕业，然后一直做软件开发，也做过一些运维、技术写作、培训、开源社区服务等等的工作，但主要还是开发软件：拿一个task过来，讨论，编码，写自动化测试保证基本质量，当然还包括review别人的代码，测试别人完成的task，做版本发布，修bug，写脚本处理后台数据等等，不一而足。总之我是团队的一份子，每天尽可能高质量的去完成一些或被分配，或主动挑选的任务。 做了敏捷教练之后，我有机会从旁观者的角度观察一些团队，我发现团队中的大部分人都非常优秀，尤其是在技术方面，但从整个团队看却存在一些问题，产品不符合用户的预期，产品质量问题严重，团队氛围不够愉快……如果我是个程序员，如果我是他们中间的一员，十有八九我会抱怨，抱怨恶心的遗留代码，抱怨SB的管理层，抱怨SB的用户，抱怨不清晰的产品定义。这种抱怨是可以理解的，作为程序员，我已经在技术上尽力了，甚至我都加班了，我还能做什么呢？ 我现在渐渐明白程序员能做的其实还有很多，从整个产品的角度来考虑，看似SB的管理层其实有他们非常实际的考量，看似恶心的遗留代码其实有很大改进的余地，看似SB的用户其实要求很简单，看似不清晰的产品定义其实很大程度上是由于程序员自身沟通不主动引起的。其实这些问题在很多书里都有讲述，之前我也看过不少，不过看了也就看了，没太大的感觉，只有在切身观察后，才真正意识到问题的严重性。 就我所了解的，有很多程序员崇尚Geek风格，其实我自己也是，追求和推崇技术本没什么错，但过于纠结技术细节而忽视产品方向，忽略团队沟通，就比较危险了。 过高的自我预期 作为咨询师，或者敏捷教练，普通人的第一反应就是你在技术上必须比你所coach的对象优秀，直觉上这很好理解，要帮别人做得更好，你自己当然要做得比他们好。我一开始也是这么认为的，但随着和客户进一步地接触，我发现实际上他们在某些方面非常优秀，比如C++语言，短期内我的水平是不可能超过他们的，更不用提具体的领域知识了，这么一想我就给自己带来的很大的压力，生怕哪天一不小心就暴露了自己的弱点。 但渐渐的，通过和同事的聊天，通过阅读这方面专家的著作（Agile Coaching），我明白了技术优秀不是一个敏捷教练的第一要务。这就好比作为一名足球教练，他的第一要务不是球踢得比球队的明星球员好，更重要的是帮助球队融合，帮助球员成长。想明白这点非常重要，移除了对自己的一个不必要的过高预期后，我每天工作能更有信心，更自在，同时也明白了专注点应该放在对团队的观察和帮助，而不是自己的技术。 不过话说回来，自身的技术能力也不是不重要的，所以必须保持不停学习的习惯。 面对挫败 这段做敏捷教练的时间里，让我体验最大的挫败感，并且到现在都无法释怀的一件事是：我曾尝试给一位程序员提供一些自认为非常中肯的建议，尝试说服他并且也编写了很多代码表达我的想法，但结果是他完全不认同我的说法，与我讨论言辞激烈，甚至最终对我产生了非常抵触的情绪。 我反思过，并且在写下了一句话提醒自己： So it&#8217;s my fault I was too eager to give opinion to XXX, rather than first listening carefully and then try helping. 认真倾听他人的想法是件非常重要但很容易被忽视的事情，我们常常会看到两人面红耳赤的争论一些问题可他们其实是在说两件事情。在上述的例子中，由于我太急于表现自己，而没有认真倾听，直接导致失去了对方的信任。当然也不是所有情况都会得到上述那样强烈的反应，人和人的性格都有差别。 不过即使我想明白了自己的问题所在，也知道怎样去改正，我还是无法对这样的挫败完全释怀，可能潜意识里希望新职位的开端要完满，可能性格上一时无法接受强烈的人与人冲突，我必须不停告诉自己，用平常心对待这件事情，至于什么时候我能真正泰然应对此类事情，暂时还不清楚。 DON&#8217;T PANIC 《银河系漫游指南》是我最喜爱的科幻书籍之一，DON’T PANIC是该书中最著名的话之一，我想这句话放在像我这样一个新的敏捷教练面前再合适不过了。不管发生什么情况都不必惊慌，咨询是个充满挑战的职业，挑战当然伴随着风险，当各种各样的预期范围之外的事情接踵而至的时候，要保持信心，冷静地观察分析，而不是手足无措。 客户的肯定，同事的经验分享及指导，阅读前辈的书籍论述，都是帮助自己理清思路，建立信心的有效途径。我真心感激所有给我提供帮助的朋友，不论是一句‘早安’，或者是耐心的分析，或者是您的一篇博客或者一本书，这都能让我感到脚下的路踏实温暖。 &#160;]]></description>
			<content:encoded><![CDATA[<p><img title="DontPanic.jpg" src="http://www.juvenxu.com/wp-content/uploads/2012/05/DontPanic.jpg" alt="DontPanic" width="300" height="252" border="0" /></p>
<p>从三月中起开始从事敏捷实践咨询工作，至此一月有余，这期间经历很大的角色转变，从程序员转向敏捷实践教练，需要不停的挑战自己原有的思维习惯，挺难的，不过我一直对自己说，“放空自己，用心去体验”，这么一想后似乎也没那么难了。</p>
<p>4月16号我发了条<a href="http://weibo.com/1671981772/yeSSSrWxA">微博</a>：</p>
<blockquote><p>第一次正式做敏捷咨询工作，每天各种挑战，很多东西要学，不确定自己能做到多好，但我决定坚持用积极的态度去体验并思考每天发生的一切。</p></blockquote>
<p>对此<a href="http://weibo.com/powerfish321">@powerfish</a>给了一条中肯的建议：</p>
<blockquote><p>加油！我也觉得咨询是很有挑战的工作。我觉得每天维持6小时的工作，2小时的反思，每周维持4天工作，1天反思，是非常必要的！</p></blockquote>
<p>虽然我暂时还不能做到每天2小时的反思，但我非常同意反思的重要性并努力在做，这也是写本文的初衷之一。反思好比是敏捷开发流程中的回顾会议，只有不断的观察自己，找出优秀的地方加以提倡保持，找出存在的问题加以更正改善，自己才能变得更好。下面简述几条我感受最深的体验。</p>
<h2>视角转换</h2>
<p>我一直是个地地道道的程序员，计算机科班毕业，然后一直做软件开发，也做过一些运维、技术写作、培训、开源社区服务等等的工作，但主要还是开发软件：拿一个task过来，讨论，编码，写自动化测试保证基本质量，当然还包括review别人的代码，测试别人完成的task，做版本发布，修bug，写脚本处理后台数据等等，不一而足。总之我是团队的一份子，每天尽可能高质量的去完成一些或被分配，或主动挑选的任务。</p>
<p>做了敏捷教练之后，我有机会从旁观者的角度观察一些团队，我发现团队中的大部分人都非常优秀，尤其是在技术方面，但从整个团队看却存在一些问题，产品不符合用户的预期，产品质量问题严重，团队氛围不够愉快……如果我是个程序员，如果我是他们中间的一员，十有八九我会抱怨，抱怨恶心的遗留代码，抱怨SB的管理层，抱怨SB的用户，抱怨不清晰的产品定义。这种抱怨是可以理解的，作为程序员，我已经在技术上尽力了，甚至我都加班了，我还能做什么呢？</p>
<p>我现在渐渐明白程序员能做的其实还有很多，从整个产品的角度来考虑，看似SB的管理层其实有他们非常实际的考量，看似恶心的遗留代码其实有很大改进的余地，看似SB的用户其实要求很简单，看似不清晰的产品定义其实很大程度上是由于程序员自身沟通不主动引起的。其实这些问题在很多书里都有讲述，之前我也看过不少，不过看了也就看了，没太大的感觉，只有在切身观察后，才真正意识到问题的严重性。</p>
<p>就我所了解的，有很多程序员崇尚Geek风格，其实我自己也是，追求和推崇技术本没什么错，但过于纠结技术细节而忽视产品方向，忽略团队沟通，就比较危险了。</p>
<h2>过高的自我预期</h2>
<p>作为咨询师，或者敏捷教练，普通人的第一反应就是你在技术上必须比你所coach的对象优秀，直觉上这很好理解，要帮别人做得更好，你自己当然要做得比他们好。我一开始也是这么认为的，但随着和客户进一步地接触，我发现实际上他们在某些方面非常优秀，比如C++语言，短期内我的水平是不可能超过他们的，更不用提具体的领域知识了，这么一想我就给自己带来的很大的压力，生怕哪天一不小心就暴露了自己的弱点。</p>
<p>但渐渐的，通过和同事的聊天，通过阅读这方面专家的著作（<a href="http://book.douban.com/subject/3793063/">Agile Coaching</a>），我明白了技术优秀不是一个敏捷教练的第一要务。这就好比作为一名足球教练，他的第一要务不是球踢得比球队的明星球员好，更重要的是帮助球队融合，帮助球员成长。想明白这点非常重要，移除了对自己的一个不必要的过高预期后，我每天工作能更有信心，更自在，同时也明白了专注点应该放在对团队的观察和帮助，而不是自己的技术。</p>
<p>不过话说回来，自身的技术能力也不是不重要的，所以必须保持不停学习的习惯。</p>
<h2>面对挫败</h2>
<p>这段做敏捷教练的时间里，让我体验最大的挫败感，并且到现在都无法释怀的一件事是：我曾尝试给一位程序员提供一些自认为非常中肯的建议，尝试说服他并且也编写了很多代码表达我的想法，但结果是他完全不认同我的说法，与我讨论言辞激烈，甚至最终对我产生了非常抵触的情绪。</p>
<p>我反思过，并且在写下了一句话提醒自己：</p>
<blockquote><p>So it&#8217;s my fault I was too eager to give opinion to XXX, rather than first listening carefully and then try helping.</p></blockquote>
<p>认真倾听他人的想法是件非常重要但很容易被忽视的事情，我们常常会看到两人面红耳赤的争论一些问题可他们其实是在说两件事情。在上述的例子中，由于我太急于表现自己，而没有认真倾听，直接导致失去了对方的信任。当然也不是所有情况都会得到上述那样强烈的反应，人和人的性格都有差别。</p>
<p>不过即使我想明白了自己的问题所在，也知道怎样去改正，我还是无法对这样的挫败完全释怀，可能潜意识里希望新职位的开端要完满，可能性格上一时无法接受强烈的人与人冲突，我必须不停告诉自己，用平常心对待这件事情，至于什么时候我能真正泰然应对此类事情，暂时还不清楚。</p>
<h2>DON&#8217;T PANIC</h2>
<p><a href="http://book.douban.com/subject/6265745/">《银河系漫游指南》</a>是我最喜爱的科幻书籍之一，<a href="http://en.wikipedia.org/wiki/Phrases_from_The_Hitchhiker%27s_Guide_to_the_Galaxy#Don.27t_Panic">DON’T PANIC</a>是该书中最著名的话之一，我想这句话放在像我这样一个新的敏捷教练面前再合适不过了。不管发生什么情况都不必惊慌，咨询是个充满挑战的职业，挑战当然伴随着风险，当各种各样的预期范围之外的事情接踵而至的时候，要保持信心，冷静地观察分析，而不是手足无措。</p>
<p>客户的肯定，同事的经验分享及指导，阅读前辈的书籍论述，都是帮助自己理清思路，建立信心的有效途径。我真心感激所有给我提供帮助的朋友，不论是一句‘早安’，或者是耐心的分析，或者是您的一篇博客或者一本书，这都能让我感到脚下的路踏实温暖。</p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.juvenxu.com/2012/05/02/agile-consultant-start/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Travis CI，翩翩而至的CI云</title>
		<link>http://www.juvenxu.com/2012/03/06/travis-ci/</link>
		<comments>http://www.juvenxu.com/2012/03/06/travis-ci/#comments</comments>
		<pubDate>Tue, 06 Mar 2012 07:35:05 +0000</pubDate>
		<dc:creator>juvenxu</dc:creator>
				<category><![CDATA[持续集成]]></category>
		<category><![CDATA[travis-ci]]></category>
		<category><![CDATA[开源]]></category>

		<guid isPermaLink="false">http://www.juvenxu.com/?p=709</guid>
		<description><![CDATA[在开源社区的持续集成领域，当Jenkins/Hudson一统天下的时候，天边突然有个家伙踩着云朵飞了过来，风格非常小清新，而且表现得和最近大红大紫的Github非常亲昵。Ruby on Rails、Ruby和Node.js等项目已经被他吸引，或者说大部分有身份的Ruby开源项目都成了他的粉丝，事实上投靠他的项目已经超过7,500个，他每天执行超过4,000次的构建，他支持Ruby、Java、Python、Perl……好吧，其实是除了C/C++/C#之外的所有主流语言。 他是Travis CI，为开源社区提供的云端持续集成服务。 &#160; &#160; DSL方式的配置 我还记得07年接触CruiseControl的时候，所有配置都得通过后台的XML文件完成，修改完了再重启服务，如此反复，久而久之，烦不胜烦。然后08年接触到Hudson，修改配置有比较友好的Web界面了，自然一见倾心。现在来看，travis-ci似乎回到了CruiseControl的原始时期？其实不是这样，下面是一个典型的travis-ci的构建配置： language: java script: mvn -q clean install # whitelist branches:   only:     - master notifications:   email:     - cukes-devs@googlegroups.com   irc:     - &#8220;irc.freenode.org#cucumber&#8221; 首先，和XML相比，非常小清新，现在好像大家都喜欢这么搞，比如Gradle较之于Maven，这么简洁性感的配置，无疑是非常有吸引力的。其次，这里的配置和CI服务其实是没有关系的，因此对于项目开发人员来说，我只关心怎么构建我的项目，而不用关心CI服务器如何配置。 这个DSL模型是非常简单的，它主要只包含了四个部分： 语言，比如java还是ruby，进一步的，还能指定具体版本（可以是多个），比如rvm 1.9.3。 生命周期，关于安装依赖的 before_install、install、after_install，关于具体构建的 before_script、script、after_script。 构建脚本，针对具体生命周期的一步，调用用户定义的脚本执行构建，例如上例中的 script: mvn -q clean install 。 通知，告诉用户CI成功或者失败，支持email和irc等等。 值得一提的是，Travis CI提供了工具travis-lint帮助你验证DSL的语法。 另外，由于构建配置是存储在版本控制仓库中的文本，因此天生就继承了版本控制带来的各种好处，例如可以回溯历史、不怕丢失、一有更改大家都能看到。 与Github集成 Travis CI只支持Github，但是集成得非常平滑，你可以直接用Github账号登陆，看到自己的Git仓库，然后点个按钮开启集成并授权Travis CI访问你的仓库即可，之后默认每次的push都会触发集成。 换句话说，默认Travis CI不支持你自己的Git仓库，更不用说Subversion什么的了。但是，Travis CI是开源的，因此技术上来说支持其他形式的SCM不是什么困难的事情。 企业级CI 从InfoQ的这篇报道我们可以看到，Travis [...]]]></description>
			<content:encoded><![CDATA[<p>在开源社区的持续集成领域，当Jenkins/Hudson一统天下的时候，天边突然有个家伙踩着云朵飞了过来，风格非常小清新，而且表现得和最近大红大紫的Github非常亲昵。Ruby on Rails、Ruby和Node.js等项目已经被他吸引，或者说大部分有身份的Ruby开源项目都成了他的粉丝，事实上<a href="http://travis-ci.org/stats">投靠他的项目已经超过7,500个</a>，他每天执行超过4,000次的构建，他支持Ruby、Java、Python、Perl……好吧，其实是除了C/C++/C#之外的所有主流语言。</p>
<p>他是Travis CI，为开源社区提供的云端持续集成服务。</p>
<p><a href="http://www.juvenxu.com/wp-content/uploads/2012/03/travis-ci-logo.jpg"><img class="alignnone size-full wp-image-706" style="border-image: initial; border-width: 1px; border-color: black; border-style: solid;" title="travis-ci-logo.jpg" src="http://www.juvenxu.com/wp-content/uploads/2012/03/travis-ci-logo.jpg" alt="" width="600" height="151" /></a></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<h2>DSL方式的配置</h2>
<p>我还记得07年接触CruiseControl的时候，所有配置都得通过后台的XML文件完成，修改完了再重启服务，如此反复，久而久之，烦不胜烦。然后08年接触到Hudson，修改配置有比较友好的Web界面了，自然一见倾心。现在来看，travis-ci似乎回到了CruiseControl的原始时期？其实不是这样，下面是一个典型的travis-ci的构建配置：</p>
<blockquote>
<div id="LC1" class="line" style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 1em; border-image: initial; font-size: 12px; font: inherit; background-color: transparent; margin: 0px; border: 0px initial initial;"><span class="l-Scalar-Plain" style="border-image: initial; font-size: 12px; font: inherit; padding: 0px; margin: 0px; border: 0px initial initial;">language</span><span class="p-Indicator" style="border-image: initial; font-size: 12px; font: inherit; padding: 0px; margin: 0px; border: 0px initial initial;">:</span> <span class="l-Scalar-Plain" style="border-image: initial; font-size: 12px; font: inherit; padding: 0px; margin: 0px; border: 0px initial initial;">java</span></div>
<div id="LC2" class="line" style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 1em; border-image: initial; font-size: 12px; font: inherit; background-color: transparent; margin: 0px; border: 0px initial initial;"><span class="l-Scalar-Plain" style="border-image: initial; font-size: 12px; font: inherit; padding: 0px; margin: 0px; border: 0px initial initial;">script</span><span class="p-Indicator" style="border-image: initial; font-size: 12px; font: inherit; padding: 0px; margin: 0px; border: 0px initial initial;">:</span> <span class="l-Scalar-Plain" style="border-image: initial; font-size: 12px; font: inherit; padding: 0px; margin: 0px; border: 0px initial initial;">mvn -q clean install</span></div>
<div id="LC3" class="line" style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 1em; border-image: initial; font-size: 12px; font: inherit; background-color: transparent; margin: 0px; border: 0px initial initial;"><span class="c1" style="border-image: initial; font-size: 12px; font: inherit; color: #999988; font-style: italic; padding: 0px; margin: 0px; border: 0px initial initial;"># whitelist</span></div>
<div id="LC4" class="line" style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 1em; border-image: initial; font-size: 12px; font: inherit; background-color: transparent; margin: 0px; border: 0px initial initial;"><span class="l-Scalar-Plain" style="border-image: initial; font-size: 12px; font: inherit; padding: 0px; margin: 0px; border: 0px initial initial;">branches</span><span class="p-Indicator" style="border-image: initial; font-size: 12px; font: inherit; padding: 0px; margin: 0px; border: 0px initial initial;">:</span></div>
<div id="LC5" class="line" style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 1em; border-image: initial; font-size: 12px; font: inherit; background-color: transparent; margin: 0px; border: 0px initial initial;">  <span class="l-Scalar-Plain" style="border-image: initial; font-size: 12px; font: inherit; padding: 0px; margin: 0px; border: 0px initial initial;">only</span><span class="p-Indicator" style="border-image: initial; font-size: 12px; font: inherit; padding: 0px; margin: 0px; border: 0px initial initial;">:</span></div>
<div id="LC6" class="line" style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 1em; border-image: initial; font-size: 12px; font: inherit; background-color: transparent; margin: 0px; border: 0px initial initial;">    <span class="p-Indicator" style="border-image: initial; font-size: 12px; font: inherit; padding: 0px; margin: 0px; border: 0px initial initial;">-</span> <span class="l-Scalar-Plain" style="border-image: initial; font-size: 12px; font: inherit; padding: 0px; margin: 0px; border: 0px initial initial;">master</span></div>
<div id="LC8" class="line" style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 1em; border-image: initial; font-size: 12px; font: inherit; background-color: transparent; margin: 0px; border: 0px initial initial;"><span class="l-Scalar-Plain" style="border-image: initial; font-size: 12px; font: inherit; padding: 0px; margin: 0px; border: 0px initial initial;">notifications</span><span class="p-Indicator" style="border-image: initial; font-size: 12px; font: inherit; padding: 0px; margin: 0px; border: 0px initial initial;">:</span></div>
<div id="LC9" class="line" style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 1em; border-image: initial; font-size: 12px; font: inherit; background-color: transparent; margin: 0px; border: 0px initial initial;">  <span class="l-Scalar-Plain" style="border-image: initial; font-size: 12px; font: inherit; padding: 0px; margin: 0px; border: 0px initial initial;">email</span><span class="p-Indicator" style="border-image: initial; font-size: 12px; font: inherit; padding: 0px; margin: 0px; border: 0px initial initial;">:</span></div>
<div id="LC10" class="line" style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 1em; border-image: initial; font-size: 12px; font: inherit; background-color: transparent; margin: 0px; border: 0px initial initial;">    <span class="p-Indicator" style="border-image: initial; font-size: 12px; font: inherit; padding: 0px; margin: 0px; border: 0px initial initial;">-</span> <span class="l-Scalar-Plain" style="border-image: initial; font-size: 12px; font: inherit; padding: 0px; margin: 0px; border: 0px initial initial;">cukes-devs@googlegroups.com</span></div>
<div id="LC11" class="line" style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 1em; border-image: initial; font-size: 12px; font: inherit; background-color: transparent; margin: 0px; border: 0px initial initial;">  <span class="l-Scalar-Plain" style="border-image: initial; font-size: 12px; font: inherit; padding: 0px; margin: 0px; border: 0px initial initial;">irc</span><span class="p-Indicator" style="border-image: initial; font-size: 12px; font: inherit; padding: 0px; margin: 0px; border: 0px initial initial;">:</span></div>
<div id="LC12" class="line" style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 1em; border-image: initial; font-size: 12px; font: inherit; background-color: transparent; margin: 0px; border: 0px initial initial;">    <span class="p-Indicator" style="border-image: initial; font-size: 12px; font: inherit; padding: 0px; margin: 0px; border: 0px initial initial;">-</span> <span class="s" style="border-image: initial; font-size: 12px; font: inherit; color: #dd1144; padding: 0px; margin: 0px; border: 0px initial initial;">&#8220;irc.freenode.org#cucumber&#8221;</span></div>
</blockquote>
<p>首先，和XML相比，非常小清新，现在好像大家都喜欢这么搞，比如<a href="http://www.juvenxu.com/2011/04/07/infoq-maven-gradle/">Gradle较之于Maven</a>，这么简洁性感的配置，无疑是非常有吸引力的。其次，这里的配置和CI服务其实是没有关系的，因此对于项目开发人员来说，我只关心怎么构建我的项目，而不用关心CI服务器如何配置。</p>
<p>这个<a href="http://about.travis-ci.org/docs/user/build-configuration/">DSL模型</a>是非常简单的，它主要只包含了四个部分：</p>
<ol>
<li>语言，比如java还是ruby，进一步的，还能指定具体版本（可以是多个），比如rvm 1.9.3。</li>
<li>生命周期，关于安装依赖的 before_install、install、after_install，关于具体构建的 before_script、script、after_script。</li>
<li>构建脚本，针对具体生命周期的一步，调用用户定义的脚本执行构建，例如上例中的 <span class="l-Scalar-Plain" style="font-size: 12px; font: inherit; padding: 0px; margin: 0px;">script</span><span class="p-Indicator" style="font-size: 12px; font: inherit; padding: 0px; margin: 0px;">:</span> <span class="l-Scalar-Plain" style="font-size: 12px; font: inherit; padding: 0px; margin: 0px;">mvn -q clean install </span>。</li>
<li>通知，告诉用户CI成功或者失败，支持email和irc等等。</li>
</ol>
<p>值得一提的是，Travis CI提供了工具<a href="http://about.travis-ci.org/docs/user/travis-lint/">travis-lint</a>帮助你验证DSL的语法。</p>
<p>另外，由于构建配置是存储在版本控制仓库中的文本，因此天生就继承了版本控制带来的各种好处，例如可以回溯历史、不怕丢失、一有更改大家都能看到。</p>
<h2>与Github集成</h2>
<p>Travis CI只支持Github，但是集成得非常平滑，你可以直接用Github账号登陆，看到自己的Git仓库，然后点个按钮开启集成并授权Travis CI访问你的仓库即可，之后默认每次的push都会触发集成。</p>
<p><img style="border-style: solid; border-color: black; border-image: initial; border-width: 1px;" title="travis-ci-github.jpg" src="http://www.juvenxu.com/wp-content/uploads/2012/03/travis-ci-github.jpg" alt="Travis ci github" width="600" height="393" border="0" /></p>
<p>换句话说，默认Travis CI不支持你自己的Git仓库，更不用说Subversion什么的了。但是，<a href="https://github.com/travis-ci">Travis CI是开源的</a>，因此技术上来说支持其他形式的SCM不是什么困难的事情。</p>
<h2>企业级CI</h2>
<p>从<a href="http://www.infoq.com/cn/news/2012/02/travis-cloud-ci">InfoQ的这篇报道</a>我们可以看到，Travis CI已经试图将这一成功的开源项目在企业层面复制，名字也想好了：Travis Pro。</p>
<p>在我看来，这是Travis CI大有可为的一个领域，首先，云CI可以解放开发人员的生产力，正如我们在前面看到的，开发人员一方面不需要考虑CI背后的基础设置，另一方面又能够很轻松地对自己的构建任务实现可控。传统的做法，一种是开发人员自己维护CI服务器，包括服务器本身和集成任务的配置；一种是交给配置管理员，那开发人员想要修改集成任务配置的时候，就需要和配置管理员协调。</p>
<p>其次，这种将CI作为服务按需提供给开发人员的方式，可以节省企业的成本，从这篇<a href="http://about.travis-ci.org/docs/user/ci-environment/">关于Travis CI环境的文档</a>我们可以看到，Travis CI在执行每次构建之前才开启虚拟机，执行完之后立刻关闭，这可以让硬件资源得到充分的利用。</p>
<p>当然，真正把Travis CI部署到企业环境中还是有许多工作要做的，这需要有人熟悉它的工作原理；可能要进一步开发以集成企业内部的各种环境，例如常见的LDAP；Travis CI目前对Ruby支持非常好，但对于Java就一般，还不支持C#。</p>
<h2>其他亮点</h2>
<p>Travis CI还有很多非常Cool的特性，包括：</p>
<ul>
<li><a href="http://about.travis-ci.org/docs/user/database-setup/">数据库支持</a>，MySQL、PostgreSQL、MongoDB等等，该支持的都支持。</li>
<li><a href="http://about.travis-ci.org/docs/user/gui-and-headless-browsers/">GUI浏览器测试支持</a>，所以放心用Selenium吧。</li>
<li><a href="http://about.travis-ci.org/docs/dev/api/">RESTful API</a>，方便用户将CI信息展示到任何自己想展示的地方，比如下面的<a href="http://madebynathan.com/2012/01/30/travis-ci-status-in-shell-prompt/">命令行</a>。<img style="border-style: initial; border-color: initial; border-image: initial; margin-top: 2px; margin-bottom: 2px; border-width: 0px;" title="travis_ci_prompt.png" src="http://www.juvenxu.com/wp-content/uploads/2012/03/travis_ci_prompt.png" alt="Travis ci prompt" width="412" height="76" border="0" /></li>
<li><a href="https://github.com/travis-ci">Travis CI是开源的</a>，并且有一个逐渐壮大的社区。</li>
<li><a href="http://about.travis-ci.org/docs/user/build-configuration/">构建矩阵（Build Matrix）</a>，你可以指定多个环境然后并行的执行构建。</li>
</ul>
<h2>小结</h2>
<p>Travis CI有没有革命性的新技术？看起来是没有，不过它用到了很多当前最流行的技术和工具，比如DSL、Github、RESTful、Chef等等，而且达到了非常好的效果，这自然吸引了大量Geek，这也受益于开源社区所独有的特别开放的氛围。</p>
<p>关于Travis Ci和Jenkins/Hudson的关系，在我看来，短时间Jenkins/Hudson的主流地位并不会受到挑战，这主要是因为Jenkins的生态圈目前更为成熟，对Java的支持更好，另外对大多数中小企业来说，部署Jenkisn/Hudson容易得多。但长期来看，Travis CI这种云的方式必然会在大型的企业中占据主流的地位。</p>
<p>本文只是从用户角度简单分析了Travis CI，关于Travis CI的架构和实现，希望有机会再学习分享，目前，感兴趣的读者可以参考这篇<a href="http://about.travis-ci.org/docs/dev/overview/">架构概览</a>。</p>
<h2>延伸阅读</h2>
<ul>
<li>Travis CI官方文档：<a href="http://about.travis-ci.org/docs/">http://about.travis-ci.org/docs/</a></li>
<li>InfoQ报道，Travis CI宣布支持Java，并计划推出Travis Pro：<a href="http://www.infoq.com/cn/news/2012/02/travis-cloud-ci">http://www.infoq.com/cn/news/2012/02/travis-cloud-ci</a></li>
<li>Larry Cai，Ci on demand &#8211; learn from travis-cl：<a href="http://codeslife.com/2012/02/23/ci-on-demand-learn-from-travis-ci/">http://codeslife.com/2012/02/23/ci-on-demand-learn-from-travis-ci/</a></li>
<li>Travis CI Status in Shell Prompt：<a href="http://madebynathan.com/2012/01/30/travis-ci-status-in-shell-prompt/">http://madebynathan.com/2012/01/30/travis-ci-status-in-shell-prompt/</a></li>
</ul>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.juvenxu.com/2012/03/06/travis-ci/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>随想，冬末</title>
		<link>http://www.juvenxu.com/2012/02/23/thoughts-winter-end/</link>
		<comments>http://www.juvenxu.com/2012/02/23/thoughts-winter-end/#comments</comments>
		<pubDate>Thu, 23 Feb 2012 09:17:49 +0000</pubDate>
		<dc:creator>juvenxu</dc:creator>
				<category><![CDATA[总结]]></category>
		<category><![CDATA[思考]]></category>

		<guid isPermaLink="false">http://www.juvenxu.com/?p=698</guid>
		<description><![CDATA[1. 不知道温水是不是真能煮青蛙，我没试验过，但我相信没人想做被煮熟的青蛙，找不到激情了，发现自己思考不够了，就要看看改变的机会，然后，勇敢点。 2. 内心的理想，热情，是值得我们为之一搏的，这个过程中必须有代价，如果怕付出代价，那就别谈热情，诳论理想，更不要把什么“Follow Your Heart”放嘴边。 3. 理想是可以被说服的，我走一条我相信正确的路，如果你能分析并证明这路弯了，我真诚感激你，我走回正确的路上，继续追寻理想。 4. 但是，你永远不可能通过肤浅的说教或者热情的感染来改变我的理想。 5. 不要对他人期望过高，期望低一点，如果他超出你的期望了，那要感激对方。 6. 不要对自己期望过低，期望高一点，如果自己做不到，那至少是个审视自己的机会。 7. 宽容很重要，当然是对别人的宽容，不是说要对别人多好，这主要是为了让自己过得舒服点。 8. 倾听很重要，了解他人的想法比推销自己的想法难多了，无法做好倾听？参考上一条。 9. 坐高铁比做飞机舒服，即使多花3-4个小时。 &#160;]]></description>
			<content:encoded><![CDATA[<p>1. 不知道温水是不是真能煮青蛙，我没试验过，但我相信没人想做被煮熟的青蛙，找不到激情了，发现自己思考不够了，就要看看改变的机会，然后，勇敢点。</p>
<p>2. 内心的理想，热情，是值得我们为之一搏的，这个过程中必须有代价，如果怕付出代价，那就别谈热情，诳论理想，更不要把什么“Follow Your Heart”放嘴边。</p>
<p>3. 理想是可以被说服的，我走一条我相信正确的路，如果你能分析并证明这路弯了，我真诚感激你，我走回正确的路上，继续追寻理想。</p>
<p>4. 但是，你永远不可能通过肤浅的说教或者热情的感染来改变我的理想。</p>
<p>5. 不要对他人期望过高，期望低一点，如果他超出你的期望了，那要感激对方。</p>
<p>6. 不要对自己期望过低，期望高一点，如果自己做不到，那至少是个审视自己的机会。</p>
<p>7. 宽容很重要，当然是对别人的宽容，不是说要对别人多好，这主要是为了让自己过得舒服点。</p>
<p>8. 倾听很重要，了解他人的想法比推销自己的想法难多了，无法做好倾听？参考上一条。</p>
<p>9. 坐高铁比做飞机舒服，即使多花3-4个小时。</p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.juvenxu.com/2012/02/23/thoughts-winter-end/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Addison-Wesley的大师签名系列图书</title>
		<link>http://www.juvenxu.com/2012/02/05/addison-wesley-signature-series/</link>
		<comments>http://www.juvenxu.com/2012/02/05/addison-wesley-signature-series/#comments</comments>
		<pubDate>Sun, 05 Feb 2012 04:57:01 +0000</pubDate>
		<dc:creator>juvenxu</dc:creator>
				<category><![CDATA[书]]></category>
		<category><![CDATA[Addison-Wesley]]></category>
		<category><![CDATA[敏捷]]></category>

		<guid isPermaLink="false">http://www.juvenxu.com/?p=661</guid>
		<description><![CDATA[在‘阅读计算机图书的一些心得’中我提过 首先是挑书，我在读书的同时慢慢锻炼了挑书的能力，因为读书最大的消费不是书价，而是时间，因此挑对书是至关重要的。我读书主要是看出版社，比如国外著名的有O’Reilly、Manning、Addison Wesley、Pragmatic Bookshelf等等，这些出版社的书大部分质量非常优秀，也包含了不少的经典，就算你不小心遇到本很水的，那几率也是非常地低。 本文就介绍一个我认为质量非常非常之高的系列图书（注意，是两个非常哦），它就是Addison-Wesley的大师签名系列，具体的它是三个子系列，签名者分别为： Martin Fowler：http://www.informit.com/imprint/series_detail.aspx?ser=2629220 Mike Cohn：http://www.informit.com/imprint/series_detail.aspx?ser=2393388 Kent Beck：http://www.informit.com/imprint/series_detail.aspx?ser=2175138 这其中Martin Fowler相信大家已经耳熟能详了，包括他的《重构》和他所在的ThoughtWorks，为软件行业做了很大的贡献。Kent Beck的知名更多的是因为他在极限编程和TDD方面的贡献。而Mike Cohn则是敏捷流程方面的专家，Scrum联盟的创立者之一。 那么这三个系列中到底有什么好书呢？名气大的一大把，最近很热的《持续交付》，Kent Beck的著作《测试驱动开发》，前几年得过Jolt Award的《持续集成》，Martin自己的《企业应用架构模式》等等。 挑书的时候，名气当然是一个重要考虑的因素的，以我自己为例，当《持续交付》英文版刚出来的时候，我只是觉得是本好书，并没有立即去读的欲望，但随着越来越多的人推崇这本书，我就觉得需要快点拿来一读了，这就是名气的影响。 但名气只是一个因素而已，这个大师签名系列中，就我读过的而言，好几本其实在国内没什么名气，但确实是难得的好书，我特别推崇的有： Growing Object-Oriented Software, Guided by Tests：初看起来是本讲TDD的书，但本书充满了OO设计的智慧，而且案例非常实在。 Agile Testing: A Practical Guide for Testers and Agile Teams：敏捷开发的流程中，测试到底是个怎样的角色？我们应该怎么样去做测试，这不仅仅是每个测试人员要考虑，作为程序员，也应该认真关心。 该系列的图书，封面设计也作得很漂亮，风格一致，色彩也很不沉闷，如果你细心观察，会注意到Martin签名系列的封面上都是一座桥。然后可惜的是，这些图书一经引进，风格再难保持一致，有些是翻译有些是影印，出版社也各不相同，这些都是客观因素。 这个签名系列图书中大部分已经由国内出版社翻译引进了，有几本是影印，有兴趣的可以上豆瓣搜索对应版本，所以阅读渠道还是挺畅通的，英文好的也可以直接购买电子版，英文好再加上舍得花钱的，可直接上amazon.com购买纸质版。]]></description>
			<content:encoded><![CDATA[<p>在‘<a href="http://www.juvenxu.com/2011/10/25/what-i-learned-on-reading-it-books/">阅读计算机图书的一些心得</a>’中我提过</p>
<blockquote><p>首先是挑书，我在读书的同时慢慢锻炼了挑书的能力，因为读书最大的消费不是书价，而是时间，因此挑对书是至关重要的。我读书主要是看出版社，比如国外著名的有O’Reilly、Manning、Addison Wesley、Pragmatic Bookshelf等等，这些出版社的书大部分质量非常优秀，也包含了不少的经典，就算你不小心遇到本很水的，那几率也是非常地低。</p></blockquote>
<p>本文就介绍一个我认为质量非常非常之高的系列图书（注意，是两个非常哦），它就是Addison-Wesley的大师签名系列，具体的它是三个子系列，签名者分别为：</p>
<ul>
<li>Martin Fowler：<a href="http://www.informit.com/imprint/series_detail.aspx?ser=2629220">http://www.informit.com/imprint/series_detail.aspx?ser=2629220</a></li>
<li>Mike Cohn：<a href="http://www.informit.com/imprint/series_detail.aspx?ser=2393388">http://www.informit.com/imprint/series_detail.aspx?ser=2393388</a></li>
<li>Kent Beck：<a href="http://www.informit.com/imprint/series_detail.aspx?ser=2175138">http://www.informit.com/imprint/series_detail.aspx?ser=2175138</a></li>
</ul>
<p><img class="size-medium wp-image-666 alignright" title="kent_beck" src="http://www.juvenxu.com/wp-content/uploads/2012/02/kent_beck-198x300.jpg" alt="" width="130" height="200" /><img class="size-full wp-image-664 alignright" title="Martin Fowler" src="http://www.juvenxu.com/wp-content/uploads/2012/02/martin_fowler.jpg" alt="" width="150" height="200" /></p>
<p>这其中Martin Fowler相信大家已经耳熟能详了，包括他的《重构》和他所在的ThoughtWorks，为软件行业做了很大的贡献。Kent Beck的知名更多的是因为他在极限编程和TDD方面的贡献。而Mike Cohn则是敏捷流程方面的专家，Scrum联盟的创立者之一。</p>
<p>那么这三个系列中到底有什么好书呢？名气大的一大把，最近很热的《持续交付》，Kent Beck的著作《测试驱动开发》，前几年得过Jolt Award的《持续集成》，Martin自己的《企业应用架构模式》等等。</p>
<p>挑书的时候，名气当然是一个重要考虑的因素的，以我自己为例，当《持续交付》英文版刚出来的时候，我只是觉得是本好书，并没有立即去读的欲望，但随着越来越多的人推崇这本书，我就觉得需要快点拿来一读了，这就是名气的影响。</p>
<p>但名气只是一个因素而已，这个大师签名系列中，就我读过的而言，好几本其实在国内没什么名气，但确实是难得的好书，我特别推崇的有：</p>
<ul>
<li>Growing Object-Oriented Software, Guided by Tests：初看起来是本讲TDD的书，但本书充满了OO设计的智慧，而且案例非常实在。</li>
<li>Agile Testing: A Practical Guide for Testers and Agile Teams：敏捷开发的流程中，测试到底是个怎样的角色？我们应该怎么样去做测试，这不仅仅是每个测试人员要考虑，作为程序员，也应该认真关心。</li>
</ul>
<p><a href="http://www.juvenxu.com/wp-content/uploads/2012/02/cd.jpeg"><img class="size-full wp-image-674 alignnone" style="margin-left: 10px; margin-right: 2px;" title="cd" src="http://www.juvenxu.com/wp-content/uploads/2012/02/cd.jpeg" alt="" width="120" height="160" /></a><a href="http://www.juvenxu.com/wp-content/uploads/2012/02/at.jpeg"><img class="size-full wp-image-675 alignnone" style="margin-left: 2px; margin-right: 2px;" title="at" src="http://www.juvenxu.com/wp-content/uploads/2012/02/at.jpeg" alt="" width="120" height="160" /></a><a href="http://www.juvenxu.com/wp-content/uploads/2012/02/go.jpeg"><img class="size-full wp-image-676 alignnone" style="margin-left: 2px; margin-right: 2px;" title="go" src="http://www.juvenxu.com/wp-content/uploads/2012/02/go.jpeg" alt="" width="120" height="160" /></a><a href="http://www.juvenxu.com/wp-content/uploads/2012/02/tdd.jpeg"><img class="size-full wp-image-677 alignnone" style="margin-left: 2px; margin-right: 2px;" title="tdd" src="http://www.juvenxu.com/wp-content/uploads/2012/02/tdd.jpeg" alt="" width="120" height="160" /></a></p>
<p>该系列的图书，封面设计也作得很漂亮，风格一致，色彩也很不沉闷，如果你细心观察，会注意到Martin签名系列的封面上都是一座桥。然后可惜的是，这些图书一经引进，风格再难保持一致，有些是翻译有些是影印，出版社也各不相同，这些都是客观因素。</p>
<p>这个签名系列图书中大部分已经由国内出版社翻译引进了，有几本是影印，有兴趣的可以上豆瓣搜索对应版本，所以阅读渠道还是挺畅通的，英文好的也可以直接购买电子版，英文好再加上舍得花钱的，可直接上amazon.com购买纸质版。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.juvenxu.com/2012/02/05/addison-wesley-signature-series/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>培育软件的可测试性</title>
		<link>http://www.juvenxu.com/2011/12/27/cultivate-software-testability/</link>
		<comments>http://www.juvenxu.com/2011/12/27/cultivate-software-testability/#comments</comments>
		<pubDate>Tue, 27 Dec 2011 07:15:22 +0000</pubDate>
		<dc:creator>juvenxu</dc:creator>
				<category><![CDATA[敏捷]]></category>
		<category><![CDATA[可测试性]]></category>
		<category><![CDATA[演讲]]></category>

		<guid isPermaLink="false">http://www.juvenxu.com/?p=654</guid>
		<description><![CDATA[本月我在AgileTour上发表了一个演讲，主题为‘培育软件的可测试性’，该主题讲述了三个问题： 为什么要关注软件的可测试性？ 什么是软件的可测试性？ 如何提高软件的可测试性？ 培育软件的可测试性 View more presentations from agiletourchina]]></description>
			<content:encoded><![CDATA[<p>本月我在<a href="http://agiletour.cn/">AgileTour</a>上发表了一个演讲，主题为‘培育软件的可测试性’，该主题讲述了三个问题：</p>
<ul>
<li>为什么要关注软件的可测试性？</li>
<li>什么是软件的可测试性？</li>
<li>如何提高软件的可测试性？</li>
</ul>
<div style="width:510px" id="__ss_10671115"> <strong style="display:block;margin:12px 0 4px"><a href="http://www.slideshare.net/agiletourchina/ss-10671115" title="培育软件的可测试性" target="_blank">培育软件的可测试性</a></strong> <iframe src="http://www.slideshare.net/slideshow/embed_code/10671115" width="510" height="426" frameborder="0" marginwidth="0" marginheight="0" scrolling="no"></iframe>
<div style="padding:5px 0 12px"> View more <a href="http://www.slideshare.net/" target="_blank">presentations</a> from <a href="http://www.slideshare.net/agiletourchina" target="_blank">agiletourchina</a> </div>
</p></div>
]]></content:encoded>
			<wfw:commentRss>http://www.juvenxu.com/2011/12/27/cultivate-software-testability/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>没有银弹，但你也需要子弹——读《测试驱动开发的艺术》</title>
		<link>http://www.juvenxu.com/2011/11/07/review-on-lasse-koskela-s-tdd-book/</link>
		<comments>http://www.juvenxu.com/2011/11/07/review-on-lasse-koskela-s-tdd-book/#comments</comments>
		<pubDate>Mon, 07 Nov 2011 09:02:41 +0000</pubDate>
		<dc:creator>juvenxu</dc:creator>
				<category><![CDATA[书]]></category>
		<category><![CDATA[敏捷]]></category>
		<category><![CDATA[ATDD]]></category>
		<category><![CDATA[TDD]]></category>
		<category><![CDATA[书评]]></category>

		<guid isPermaLink="false">http://www.juvenxu.com/?p=642</guid>
		<description><![CDATA[昨晚我发了条微博，内容如下： 编程本质上是用脑的，当程序复杂的时候人脑会不够用，于是bug百出，程序员心力憔悴。好在出现了各种工具和方法论来帮助降低人脑的负荷，让人能够专注于有限的地方。但是，很多人迷信工具和方法论以致几乎忽略了人脑的能力，就好像只要用对了方法和工具，放只猴子也能把软件写出来，这也应该反思。 这是我最近看到一些关于敏捷方法的争论有感而发，就以测试驱动开发（TDD）为例，有那么两派人，一派是死忠，认为不用TDD写不出好的代码，不写测试就不能写主代码；另一派则相反，觉得TDD是很扯淡的东西，是咨询公司忽悠人的工具。我则认为两派都走了极端，在我看来，包括TDD在内的敏捷方法论都旨在帮助降低程序员的脑负荷，因此恰当的使用能帮助我们专注于重要的事情，但认为TDD是万能的，而忽视了人，那也大错特错了，不管多么神奇的方法，多么完善的过程，我们都不能否认人脑思考是编程活动中最重要的一环。 所以TDD不是能让你秒杀狼人的银弹，但它的确是能帮助打猎的子弹。 回到《测试驱动开发的艺术》一书上来，首先我想批评的是这个看似很雅实则恶俗的题目，原书名为 Test Driven &#8211; Practical TDD and Acceptance TDD for Java Developers ，一经翻译，意思完全走样。这书比较重在介绍TDD（包括ATDD）以及相关的实践，离”艺术”二字真差十万八千里。不过除了题目，其他一切都不错，包括那个照搬的Manning系列封面。下面介绍下内容： 第1-3章 是对TDD入门的介绍，TDD是什么，为什么要用TDD，相关工具，然后是实际操作等等。由于TDD无法脱离重构而存在，因此这里也有不少涉及。这一部分很棒，不是说内容多精彩，重要的是浅显易懂。 第4章 是对TDD概念和模式的一些挖掘，也是期望比较大的一章，我也看到了一些精彩的论述，包括如何提高代码可测试性的手段，将测试分为基于状态和基于交互两类，等等。可惜不够过瘾，作者引申的书倒不少，自己的料不够足啊。 第5-8章 就是一些实际的实践了，可能也算本书的重头，包括测试web组件，数据访问组件，Swing组件，时间相关功能，以及多线程代码等等。根据自己背景需要，跳着看看就可以了。 第9-11章 是对验收测试驱动开发（ATDD）的介绍，是我个人，除第4章之外最喜欢的部分，因为我之前对TDD了解得不算少了，但对验收测试的了解寥寥，这部分帮助我扫盲了，也学习了一下相关工具Fit（由Wiki之父Ward Cunningham开发）。 第12章 也是最后一章，是教你如何推行TDD，基本上是一些咨询培训的技巧，也挺有趣，不过故事少了点（作者自己还在文中强调故事的重要性，有点搞笑啊）。 总得来说这是本介绍TDD和ATDD的不错的书，优点在于浅显易懂，而且有不少实践，缺点就是深度不够。 和TDD相关的书还有不少，顺带介绍几本不错的： Test Driven Development by Kent Beck 极限编程之父的经典，必读 Growing Object-Oriented Software, Guided by Tests by Steve Freeman and Nat Pryce 我个人非常非常喜欢的一本书，他告诉了TDD就是面向对象设计，启发非常之大 Agile Testing by Lisa Crispin and Janet [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.juvenxu.com/wp-content/uploads/2011/11/tdd-book.jpg"><img class="alignright size-medium wp-image-645" title="tdd-book" src="http://www.juvenxu.com/wp-content/uploads/2011/11/tdd-book-300x300.jpg" alt="" width="300" height="300" /></a>昨晚我发了条<a href="http://weibo.com/1671981772/xtO9dfE4w" target="_blank">微博</a>，内容如下：</p>
<blockquote><p>编程本质上是用脑的，当程序复杂的时候人脑会不够用，于是bug百出，程序员心力憔悴。好在出现了各种工具和方法论来帮助降低人脑的负荷，让人能够专注于有限的地方。但是，很多人迷信工具和方法论以致几乎忽略了人脑的能力，就好像只要用对了方法和工具，放只猴子也能把软件写出来，这也应该反思。</p></blockquote>
<p>这是我最近看到一些关于敏捷方法的争论有感而发，就以测试驱动开发（TDD）为例，有那么两派人，一派是死忠，认为不用TDD写不出好的代码，不写测试就不能写主代码；另一派则相反，觉得TDD是很扯淡的东西，是咨询公司忽悠人的工具。我则认为两派都走了极端，在我看来，包括TDD在内的敏捷方法论都旨在帮助降低程序员的脑负荷，因此恰当的使用能帮助我们专注于重要的事情，但认为TDD是万能的，而忽视了<strong>人</strong>，那也大错特错了，不管多么神奇的方法，多么完善的过程，我们都不能否认人脑思考是编程活动中最重要的一环。</p>
<p>所以TDD不是能让你秒杀狼人的<a href="http://en.wikipedia.org/wiki/Silver_bullet" target="_blank">银弹</a>，但它的确是能帮助打猎的子弹。</p>
<p>回到《测试驱动开发的艺术》一书上来，首先我想批评的是这个看似很雅实则恶俗的题目，原书名为 Test Driven &#8211; Practical TDD and Acceptance TDD for Java Developers ，一经翻译，意思完全走样。这书比较重在介绍TDD（包括ATDD）以及相关的实践，离”艺术”二字真差十万八千里。不过除了题目，其他一切都不错，包括那个照搬的Manning系列封面。下面介绍下内容：</p>
<ul>
<li>第1-3章 是对TDD入门的介绍，TDD是什么，为什么要用TDD，相关工具，然后是实际操作等等。由于TDD无法脱离重构而存在，因此这里也有不少涉及。这一部分很棒，不是说内容多精彩，重要的是浅显易懂。</li>
<li>第4章 是对TDD概念和模式的一些挖掘，也是期望比较大的一章，我也看到了一些精彩的论述，包括如何提高代码可测试性的手段，将测试分为基于状态和基于交互两类，等等。可惜不够过瘾，作者引申的书倒不少，自己的料不够足啊。</li>
<li>第5-8章 就是一些实际的实践了，可能也算本书的重头，包括测试web组件，数据访问组件，Swing组件，时间相关功能，以及多线程代码等等。根据自己背景需要，跳着看看就可以了。</li>
<li>第9-11章 是对验收测试驱动开发（ATDD）的介绍，是我个人，除第4章之外最喜欢的部分，因为我之前对TDD了解得不算少了，但对验收测试的了解寥寥，这部分帮助我扫盲了，也学习了一下相关工具Fit（由Wiki之父<a href="http://en.wikipedia.org/wiki/Ward_Cunningham" target="_blank">Ward Cunningham</a>开发）。</li>
<li>第12章 也是最后一章，是教你如何推行TDD，基本上是一些咨询培训的技巧，也挺有趣，不过故事少了点（作者自己还在文中强调故事的重要性，有点搞笑啊）。</li>
</ul>
<p>总得来说这是本介绍TDD和ATDD的不错的书，优点在于浅显易懂，而且有不少实践，缺点就是深度不够。</p>
<p>和TDD相关的书还有不少，顺带介绍几本不错的：</p>
<ul>
<li><a href="http://book.douban.com/subject/1771049/" target="_blank">Test Driven Development by Kent Beck</a> 极限编程之父的经典，必读</li>
<li><a href="http://book.douban.com/subject/4156589/" target="_blank">Growing Object-Oriented Software, Guided by Tests by Steve Freeman and Nat Pryce</a> 我个人非常非常喜欢的一本书，他告诉了TDD就是面向对象设计，启发非常之大</li>
<li><a href="http://book.douban.com/subject/3307177/" target="_blank">Agile Testing by Lisa Crispin and Janet Gregory</a> 还没来得及读，不过看目录就心向往之。</li>
</ul>
<p>关于TDD，我最喜欢的是它的两点。第一是它能帮助我建立对自己代码的信心，让我能够保持前进而不用在潜意识里担心破坏什么东西；第二是它教会我在代码用户的角度设计API，而不是在代码中越钻越深最后竟忘了最初的需要。</p>
<p>TDD是枚不错的子弹，当然前提是你眼睛得好使。</p>
<p>最后再引申下这个关于子弹的比喻：</p>
<blockquote><p>有些大师，打猎不用枪，随手来块石头，就能搞定猎物，当然他也不排斥用子弹，不过工具对他来说不重要，因为修为在。</p>
<p>有些猎人（布道者），有一定经验了，发现对于新手来说，拿枪是最靠得住的打猎方式，因此不仅自己用，也告诉别人也去用。新人当然会虚心听取前人的意见。</p>
<p>但也有些人，见识过大师，自己也有一定经验了，就说，“大师都无视枪和子弹的，你们新人别听某些人吹牛，我自己用弓箭不也一样搞定猎物了？更何况我见过xxx就用一个石子，重要的是你们的内力⋯⋯” 新人就问“什么是内力呢？” 答，“你多写几年code就知道了。”</p>
<p>当然，一些伪布道者会完全忽视猎物的存在，嘴巴里不停地对新人喊“注意枪！注意枪！注意枪！”<em>。</em></p></blockquote>
<p><span style="color: #0000ff;"><em>本文已经首发于<a href="http://www.ituring.com.cn/"><span style="color: #0000ff;">图灵社区</span></a>，<em>原文为<a href="http://www.ituring.com.cn/article/378"><span style="color: #0000ff;">“没有银弹，但你也需要子弹——读《测试驱动开发的艺术》”</span></a>，</em></em><em>如需转载，请务必附带本声明，谢谢。</em></span></p>
]]></content:encoded>
			<wfw:commentRss>http://www.juvenxu.com/2011/11/07/review-on-lasse-koskela-s-tdd-book/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>阅读计算机图书的一些心得</title>
		<link>http://www.juvenxu.com/2011/10/25/what-i-learned-on-reading-it-books/</link>
		<comments>http://www.juvenxu.com/2011/10/25/what-i-learned-on-reading-it-books/#comments</comments>
		<pubDate>Mon, 24 Oct 2011 18:24:06 +0000</pubDate>
		<dc:creator>juvenxu</dc:creator>
				<category><![CDATA[总结]]></category>
		<category><![CDATA[读书]]></category>

		<guid isPermaLink="false">http://www.juvenxu.com/?p=637</guid>
		<description><![CDATA[我是个喜欢读书的人，大学里买不起书就收集了好多电子书（盗版行为，不鼓励），工作后手头没那么拮据了，就买很多书，影印的、翻译的、国人原创的、二手的，还有一些直接从amazon.com购买的原版书，当然那个价格就相对贵很多了。到目前为止，书房一个大大的书架也已经塞了十之八九。这还不包括我在iPad上的不少阅读量。 虽然是计算机书，但大多都是随性而读，换句话说就是全凭兴趣，因而不够严肃专业，自然太深的积累是没有的，不过浅一些的心得还是可以说一说的。 首先是挑书，我在读书的同时慢慢锻炼了挑书的能力，因为读书最大的消费不是书价，而是时间，因此挑对书是至关重要的。我读书主要是看出版社，比如国外著名的有O’Reilly、Manning、Addison Wesley、Pragmatic Bookshelf等等，这些出版社的书大部分质量非常优秀，也包含了不少的经典，就算你不小心遇到本很水的，那几率也是非常地低。国内出版社和国外差距很大，但应该说一直在进步，我个人最喜欢的是东南大学出版社的O’Reilly影印系列，质量真是好得没话说，价格也公道。关于翻译，人民邮电图灵的质量应该是做得最好的了，特别是有阮一峰这样的译者，真是读者的福气。原创方面的话，应该说机械工业的华章和电子工业的博文视点强一点，经常会出现一些让人眼前一亮的书，其作者水平真不比老外差。 挑书还得看作者，不熟悉作者的话，那就去网店搜一下作者的名字，如果看到他有10本或者更多的著作或译作，三五年内完成，专业领域跨度又极大，那基本上这是个不负责任的家伙。计算机行业写作不是写玄幻小说，本身需要很厚的技术积累，很多专家都是积累三五年，然后再花一两年才能磨出一本好书的，因此高产的基本就无法保证质量。还有一个看作者的方法是看他有没有自己给书开辟一个网页，负责的作者会把自己的书看得很重，因此写完了也会持续收集反馈。 挑书当然也可以看网店的书评，什么China-Pub啊、当当啊、京东啊、卓越啊、豆瓣啊等等，但不是所有书评都是可以相信的，书拖书黑在这个年代就像火车站卖发票的贩子一样常见。我个人会关注那些购买了书后，写得较长的有理有据的书评。什么“好书，顶”，或者“垃圾、骗子”这样的评论其实等于什么都没说。看看amazon.com上的书评，好在哪里、不好在哪里，说得清清楚楚，那才是有意义的。 挑到了好书就开始享受咯！我会大概把书分为简单两类，其一是硬技术，例如一门语言ruby，一个技术lucene，不学就不会，学了就会。对这类书，会有两种阅读的驱动力，一是完全凭兴趣，例如前一阵子因为《黑客与画家》的缘故，想学学lisp了，那就找本lisp的书看看，又或者因为最近买了mac，就找本mac编程的书看看，等等。二是功利性阅读了，例如最近一个项目要用到lucene，那就找本lucene的书来啃，以应付工作。功利和兴趣还是结合起来的好，完全功利了就没有自己的想法，完全凭兴趣那也不太现实，毕竟还是要工作的。当然，如果工作的技术点就是你的兴趣，那再好不过。 除了硬技术类书籍，还有大量软技术的书籍。最好的例子就是《程序员修炼之道》，它没说某个特定的技术，但总结了大量闪光的思想，可能读到其中一条你会有豁然开朗的感觉，又或者你读的时候没在意，一段时间后在实际工作中遇到的问题让你想起书中的一些建议。出版社可能会将其归入“技术人文类”，但我觉得，所有那些看过一遍都要思考理解后才能慢慢感悟的书都属于“软技术”，例如《重构》也算，还有一些软件工程类的如敏捷开发等等。 我会夹杂着读硬技术书籍和软技术书籍，相对来说软技术书籍读起来会轻松一点，因为表面意思理解很容易，而硬技术，懂就是懂，不懂就是不懂，前后还有衔接，要求你硬记住，或者实际操作才能理解。但其实真正理解软技术更难，这些书往往需要你读过一遍之后，过一年再读，再过几年再读，才能理解作者的思想。当然读太多这类的书而忽于实践也不好，到最后只剩下空洞的理论。功利性的阅读往往只再硬技术上，但如果缺乏软技术的补充，往往会迷失，好比已经积累了很多内力但缺乏调理。 书读得多了，我渐渐有了点怪癖，例如追求原版书的印刷质量，有时候会不惜好几倍的价格买原版书。又或者一直盯着市场看有什么好书出来，有了就买，到最后都来不及读。还有就是能读英文就不读翻译，完全是盲目的。其实只要翻译够好，读起来也爽，还能节省时间。不过话说回来，作为一个程序员，读个至少十本八本的英文版还是有必要的，这点能力是必须的。 读书的时候做点笔记也大有帮助，给自己买本漂亮的笔记本，多少写写划划，电子版的话，很多软件如iPad平台上的，都支持做些笔记。这都帮助思考，而不是简单的字面意思都过掉了，以为读完了，其实理解甚少。 大概想到的就这么多了，最后给大家的建议是，只要是你认定的好书，读一遍肯定是不够的，一定要读个两到三遍！ 本文已经首发于图灵社区，原文为《阅读计算机图书的一些心得》，如需转载，请务必附带本声明，谢谢。]]></description>
			<content:encoded><![CDATA[<p>我是个喜欢读书的人，大学里买不起书就收集了好多电子书（盗版行为，不鼓励），工作后手头没那么拮据了，就买很多书，影印的、翻译的、国人原创的、二手的，还有一些直接从amazon.com购买的原版书，当然那个价格就相对贵很多了。到目前为止，书房一个大大的书架也已经塞了十之八九。这还不包括我在iPad上的不少阅读量。</p>
<p>虽然是计算机书，但大多都是随性而读，换句话说就是全凭兴趣，因而不够严肃专业，自然太深的积累是没有的，不过浅一些的心得还是可以说一说的。</p>
<p>首先是挑书，我在读书的同时慢慢锻炼了挑书的能力，因为读书最大的消费不是书价，而是时间，因此挑对书是至关重要的。我读书主要是看出版社，比如国外著名的有O’Reilly、Manning、Addison Wesley、Pragmatic Bookshelf等等，这些出版社的书大部分质量非常优秀，也包含了不少的经典，就算你不小心遇到本很水的，那几率也是非常地低。国内出版社和国外差距很大，但应该说一直在进步，我个人最喜欢的是东南大学出版社的O’Reilly影印系列，质量真是好得没话说，价格也公道。关于翻译，人民邮电图灵的质量应该是做得最好的了，特别是有阮一峰这样的译者，真是读者的福气。原创方面的话，应该说机械工业的华章和电子工业的博文视点强一点，经常会出现一些让人眼前一亮的书，其作者水平真不比老外差。</p>
<p>挑书还得看作者，不熟悉作者的话，那就去网店搜一下作者的名字，如果看到他有10本或者更多的著作或译作，三五年内完成，专业领域跨度又极大，那基本上这是个不负责任的家伙。计算机行业写作不是写玄幻小说，本身需要很厚的技术积累，很多专家都是积累三五年，然后再花一两年才能磨出一本好书的，因此高产的基本就无法保证质量。还有一个看作者的方法是看他有没有自己给书开辟一个网页，负责的作者会把自己的书看得很重，因此写完了也会持续收集反馈。</p>
<p>挑书当然也可以看网店的书评，什么China-Pub啊、当当啊、京东啊、卓越啊、豆瓣啊等等，但不是所有书评都是可以相信的，书拖书黑在这个年代就像火车站卖发票的贩子一样常见。我个人会关注那些购买了书后，写得较长的有理有据的书评。什么“好书，顶”，或者“垃圾、骗子”这样的评论其实等于什么都没说。看看amazon.com上的书评，好在哪里、不好在哪里，说得清清楚楚，那才是有意义的。</p>
<p>挑到了好书就开始享受咯！我会大概把书分为简单两类，其一是硬技术，例如一门语言ruby，一个技术lucene，不学就不会，学了就会。对这类书，会有两种阅读的驱动力，一是完全凭兴趣，例如前一阵子因为《<a href="http://www.turingbook.com/book/39" target="_blank">黑客与画家</a>》的缘故，想学学lisp了，那就找本lisp的书看看，又或者因为最近买了mac，就找本mac编程的书看看，等等。二是功利性阅读了，例如最近一个项目要用到lucene，那就找本lucene的书来啃，以应付工作。功利和兴趣还是结合起来的好，完全功利了就没有自己的想法，完全凭兴趣那也不太现实，毕竟还是要工作的。当然，如果工作的技术点就是你的兴趣，那再好不过。</p>
<p>除了硬技术类书籍，还有大量软技术的书籍。最好的例子就是《程序员修炼之道》，它没说某个特定的技术，但总结了大量闪光的思想，可能读到其中一条你会有豁然开朗的感觉，又或者你读的时候没在意，一段时间后在实际工作中遇到的问题让你想起书中的一些建议。出版社可能会将其归入“技术人文类”，但我觉得，所有那些看过一遍都要思考理解后才能慢慢感悟的书都属于“软技术”，例如《<a href="http://www.turingbook.com/book/211" target="_blank">重构</a>》也算，还有一些软件工程类的如敏捷开发等等。</p>
<p>我会夹杂着读硬技术书籍和软技术书籍，相对来说软技术书籍读起来会轻松一点，因为表面意思理解很容易，而硬技术，懂就是懂，不懂就是不懂，前后还有衔接，要求你硬记住，或者实际操作才能理解。但其实真正理解软技术更难，这些书往往需要你读过一遍之后，过一年再读，再过几年再读，才能理解作者的思想。当然读太多这类的书而忽于实践也不好，到最后只剩下空洞的理论。功利性的阅读往往只再硬技术上，但如果缺乏软技术的补充，往往会迷失，好比已经积累了很多内力但缺乏调理。</p>
<p>书读得多了，我渐渐有了点怪癖，例如追求原版书的印刷质量，有时候会不惜好几倍的价格买原版书。又或者一直盯着市场看有什么好书出来，有了就买，到最后都来不及读。还有就是能读英文就不读翻译，完全是盲目的。其实只要翻译够好，读起来也爽，还能节省时间。不过话说回来，作为一个程序员，读个至少十本八本的英文版还是有必要的，这点能力是必须的。</p>
<p>读书的时候做点笔记也大有帮助，给自己买本漂亮的笔记本，多少写写划划，电子版的话，很多软件如iPad平台上的，都支持做些笔记。这都帮助思考，而不是简单的字面意思都过掉了，以为读完了，其实理解甚少。</p>
<p>大概想到的就这么多了，最后给大家的建议是，只要是你认定的好书，读一遍肯定是不够的，一定要读个两到三遍！</p>
<p><span style="color: #0000ff;"><em>本文已经首发于<a href="http://www.ituring.com.cn/"><span style="color: #0000ff;">图灵社区</span></a>，<em>原文为<a href="http://www.ituring.com.cn/article/22"><span style="color: #0000ff;">《阅读计算机图书的一些心得》</span></a>，</em></em><em>如需转载，请务必附带本声明，谢谢。</em></span></p>
]]></content:encoded>
			<wfw:commentRss>http://www.juvenxu.com/2011/10/25/what-i-learned-on-reading-it-books/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>May your builds always succeeds!</title>
		<link>http://www.juvenxu.com/2011/10/06/may-your-builds-always-succeeds/</link>
		<comments>http://www.juvenxu.com/2011/10/06/may-your-builds-always-succeeds/#comments</comments>
		<pubDate>Thu, 06 Oct 2011 15:36:37 +0000</pubDate>
		<dc:creator>juvenxu</dc:creator>
				<category><![CDATA[书]]></category>
		<category><![CDATA[Ant]]></category>
		<category><![CDATA[Book Review]]></category>
		<category><![CDATA[Gradle]]></category>
		<category><![CDATA[Maven]]></category>
		<category><![CDATA[书评]]></category>

		<guid isPermaLink="false">http://www.juvenxu.com/?p=624</guid>
		<description><![CDATA[Just finished the book &#8220;Building and Testing with Gradle&#8221; in this vacation, and here is my review. First of all this book has a great Foreword by Ken Sipe, the CTO of Gradleware. I totally agree with him on What I have discovered over the years as a software engineer is that in order to [...]]]></description>
			<content:encoded><![CDATA[<p><img class="size-medium wp-image-625 alignright" style="margin: 2px; border: 1px solid black;" title="gradle-book" src="http://www.juvenxu.com/wp-content/uploads/2011/10/gradle-book-227x300.jpg" alt="" width="227" height="300" /></p>
<p>Just finished the book &#8220;Building and Testing with Gradle&#8221; in this vacation, and here is my review.</p>
<p>First of all this book has a great Foreword by Ken Sipe, the CTO of Gradleware. I totally agree with him on</p>
<blockquote><p>What I have discovered over the years as a software engineer is that in order to solve a problem best, I have to understand the model. The reason make wasn&#8217;t a great build tool for Java is that it didn&#8217;t have a way to express the model well. Ant gave us platform independence and a better vocabulary, but a weak model. Maven provided a stronger model, which is why so many people prefer it over Ant. The challenge for Maven is that it provided a &#8220;the one model to rule them all&#8221;. You&#8217;re able to express your build needs within that model and only that model.</p>
<p>Gradle fills the gap. Gradle provides a way of modeling a build system using a DSL with convention over configuration, yet allowing an enterprise to define its own model. It goes deeper than this, as explained in this introductory book by Matthew and Tim, but modeling by convention is truly a game changer for enterprise software development.</p></blockquote>
<p>To simplify, <em>Make has no build model, Ant has weak model, Maven has one (and only one) strong model, and Gradle allows you do define model. </em>I&#8217;m not saying Gradle is better than Maven, actually I think in most cases, one strong model is better than allowing people define models. But the &#8216;model&#8217; concept is the key to undertand the differences among those tools.</p>
<p>BTW, the title of this post if borrowed from Ken&#8217;s foreword <img src='http://www.juvenxu.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> .</p>
<p>This is one of the shortest technique book I&#8217;ve ever read, only 110 pages composed by 6 chapters:</p>
<ol>
<li>Hello, Gradle!</li>
<li>Gradle Tasks</li>
<li>Ant and Gradle</li>
<li>Maven and Gradle</li>
<li>Testing with Gradle</li>
<li>Multiproject Builds</li>
</ol>
<p>Just like any tool introduction book, the first chapter is for the very beginners. The &#8216;Gradle Tasks&#8217; chapter is the most valuable part of this book, it does a good job explaining this key concept, and in a practical way. The third chapter is for Ant users the fourth is for Maven users, I belong to the latter. From the &#8216;Maven and Gradle&#8217; chapter I can see the Gradle implementations of Maven concepts like coordinate, dependency, repository, and convention, but a bit disappointed on the missing of lifecycle. The &#8216;Testing with Gradle&#8217; has little value, it&#8217;s just too basic. The last chapter is on multi-project builds, or sometimes we call this multi-module builds. Any real project is multi-moduled so I could not skip it. This chapters introduces 3 ways to organize your modules, one build file for each module, one master build file for all modules, and in a hybrid way which some modules have build file while somes don&#8217;t. This is interesting to me because Maven only gives me one choice. But, when I looked forward to see some advice on when to use which style, the authors told me to decide by myself <img src='http://www.juvenxu.com/wp-includes/images/smilies/icon_sad.gif' alt=':(' class='wp-smiley' /> .</p>
<p>Too short the book is so sometimes I have to refer to the <a href="http://www.gradle.org/current/docs/userguide/userguide.html">official gradle user guide</a> to understand something. The authors mentioned that there will be future volumes for Gradle plugin ecosystem and Java plugin, besides, I also hope there will be something on Gradle&#8217;s lifecycle, and more importantly, real world examples and best practices. This is the only published Gradle book and Gradle itself is only on version 1.0-milestone-3, so there is a lot of space to improve.</p>
<p>Thanks to Tim Berglund &amp; Matthew McCullough for making this book out.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.juvenxu.com/2011/10/06/may-your-builds-always-succeeds/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>InfoQ Maven专栏（十）——Maven 3，是时候升级了</title>
		<link>http://www.juvenxu.com/2011/08/05/infoq-maven-time-to-upgrade-to-maven3/</link>
		<comments>http://www.juvenxu.com/2011/08/05/infoq-maven-time-to-upgrade-to-maven3/#comments</comments>
		<pubDate>Thu, 04 Aug 2011 18:56:54 +0000</pubDate>
		<dc:creator>juvenxu</dc:creator>
				<category><![CDATA[Maven]]></category>
		<category><![CDATA[InfoQ]]></category>
		<category><![CDATA[InfoQ Maven专栏]]></category>
		<category><![CDATA[Maven 3]]></category>

		<guid isPermaLink="false">http://www.juvenxu.com/?p=619</guid>
		<description><![CDATA[去年10月份Apache Maven发布了3.0正式版，而在上个月的22号，Eclipse基金会宣布了Eclipse 3.7（Indigo）的发布，该版本Eclipse最大的新特性之一就是集成了Maven。下载Eclipse IDE for Java Developers版 本的用户会发现，Eclipse已经能够自动识别Maven项目了。Indigo中内置的Maven版本是3.0.2，这在一定程度上说明Maven 3已经非常稳定了。不过我相信一定还有很多Maven 2用户在犹豫是否升级，本文会介绍一些Maven 3最重要的特性，旨在帮助读者扫除疑虑，尽早享受Maven 3所能带来的各种便利。 确保兼容性 在升级软件的时候，兼容性显然是首先要考虑的问题，如果原本在Maven 2下能成功构建的项目，在Maven 3下立刻就失败了，而且难以简单修复，那显然是不可接受的。 好在Maven用户大可打消这一顾虑，Maven 3自设计之初就一直考虑与Maven 2的兼容性，这不仅是指兼容Maven 2的核心，还包括大量的org.apache.maven.plugins与org.codehaus.mojo插件。虽然由于某些插件代码的特殊性，无 法做到100%完全的兼容，但已经基本不会遇到问题了。 如果你还有担心，那可以先仔细阅读官方发布的Maven 3.x兼容性笔记和Maven 3.x插件兼容性列表。这两份文档记录的兼容性问题主要涉及的是一些应当被弃用的特性，并且都给出了Maven 3下的解决方案。 改进性能 Maven 3的性能较之于Maven 2是有了很大的进步的，这体现在内存占用的减少和构建时间的减少两个方面。特别是Maven 3引入的并行构建特性，能够分析项目模块之间的依赖关系，然后并行地构建那些相互间没有依赖关系的模块，从而充分利用如今普遍的多核CPU资源。 以下两条命令分别表示用4个线程构建，以及根据CPU核数每个核分配1个线程进行构建： $ mvn -T 4 clean install $ mvn -T 1C clean install Maven的提交者之一Anders Hammar在其文章迁移到Maven 3的十大理由中介绍了一个简单的实验，分别用Maven 2.2.1，Maven 3.0.2（单线程），和Maven 3.0.2（4线程）构建同样的包含32个模块的Maven源代码，得到了如下的结果： Table 1. 用&#8221;mvn package&#8221;构建Maven SCM trunk（32个模块） 时间/内存 Maven [...]]]></description>
			<content:encoded><![CDATA[<p>去年10月份Apache Maven发布了3.0正式版，而在上个月的22号，<a href="http://www.eclipse.org/org/press-release/20110622indigo.php">Eclipse基金会宣布了Eclipse 3.7（Indigo）</a>的发布，该版本Eclipse最大的新特性之一就是集成了Maven。下载<a href="http://www.eclipse.org/downloads/packages/eclipse-ide-java-developers/indigor">Eclipse IDE for Java Developers</a>版 本的用户会发现，Eclipse已经能够自动识别Maven项目了。Indigo中内置的Maven版本是3.0.2，这在一定程度上说明Maven  3已经非常稳定了。不过我相信一定还有很多Maven 2用户在犹豫是否升级，本文会介绍一些Maven  3最重要的特性，旨在帮助读者扫除疑虑，尽早享受Maven 3所能带来的各种便利。</p>
<h2>确保兼容性</h2>
<p>在升级软件的时候，兼容性显然是首先要考虑的问题，如果原本在Maven 2下能成功构建的项目，在Maven  3下立刻就失败了，而且难以简单修复，那显然是不可接受的。 好在Maven用户大可打消这一顾虑，Maven 3自设计之初就一直考虑与Maven  2的兼容性，这不仅是指兼容Maven  2的核心，还包括大量的org.apache.maven.plugins与org.codehaus.mojo插件。虽然由于某些插件代码的特殊性，无 法做到100%完全的兼容，但已经基本不会遇到问题了。</p>
<p>如果你还有担心，那可以先仔细阅读官方发布的<a href="https://cwiki.apache.org/MAVEN/maven-3x-compatibility-notes.html">Maven 3.x兼容性笔记</a>和<a href="https://cwiki.apache.org/MAVEN/maven-3x-plugin-compatibility-matrix.html">Maven 3.x插件兼容性列表</a>。这两份文档记录的兼容性问题主要涉及的是一些应当被弃用的特性，并且都给出了Maven 3下的解决方案。</p>
<h2>改进性能</h2>
<p>Maven 3的性能较之于Maven 2是有了很大的进步的，这体现在内存占用的减少和构建时间的减少两个方面。特别是Maven 3引入的<a href="https://cwiki.apache.org/MAVEN/parallel-builds-in-maven-3.html">并行构建特性</a>，能够分析项目模块之间的依赖关系，然后并行地构建那些相互间没有依赖关系的模块，从而充分利用如今普遍的多核CPU资源。</p>
<p>以下两条命令分别表示用4个线程构建，以及根据CPU核数每个核分配1个线程进行构建：</p>
<pre>$ mvn -T 4 clean install
$ mvn -T 1C clean install</pre>
<p>Maven的提交者之一Anders Hammar在其文章<a href="http://www.sonatype.com/people/2011/02/top-ten-reasons-to-move-to-maven-3/">迁移到Maven 3的十大理由</a>中介绍了一个简单的实验，分别用Maven 2.2.1，Maven 3.0.2（单线程），和Maven 3.0.2（4线程）构建同样的包含32个模块的Maven源代码，得到了如下的结果：</p>
<table id="d0e1180" border="1">
<caption>Table 1. 用&#8221;mvn package&#8221;构建Maven SCM trunk（32个模块）</caption>
<tbody>
<tr>
<td></td>
<td>时间/内存</td>
</tr>
<tr>
<td>Maven 2.2.1</td>
<td>3:20/53M</td>
</tr>
<tr>
<td>Maven 3.0.2（单线程）</td>
<td>3:15/27M</td>
</tr>
<tr>
<td>Maven 3.0.2（4线程）</td>
<td>2:26/28M</td>
</tr>
</tbody>
</table>
<p>可以看到Maven 3下内存的占用减少了近一半！而开启并行构建后，时间的节省也是非常可观的。而项目越大，这种性能的改进就越为明显。如果你的开发环境没有充裕的内存，而你的项目又非常大，那光内存节省这一条就足以让你立刻转向Maven 3了。</p>
<h2>改进模块间依赖解析</h2>
<p>Maven  2中一个比较令人头疼的问题是，当你在构建一个多模块项目的时候，为了使前面的模块能在后面模块classpath中生效，你必须将其install到本 地仓库中之后，Maven才能解析使用。几乎所有Maven 2用户或早或晚都遇到了这个困惑，“为什么我已经 mvn clean package  了模块A，可构建模块B的时候还是无法看到A的更新呢？”这个问题在Maven 3中得以解决了，在构建多模块项目的时候，Maven  3会从反应堆（reactor）中解析模块间依赖，也就是说只要模块A执行了package，那模块B就能根据相对路径找到并解析使用A生成的jar文 件。</p>
<h2>提倡最佳实践</h2>
<p>刚从Maven 2转到Maven 3的用户很可能会发现执行构建的时候命令行会打印很多如下的警告：</p>
<pre>[WARNING] 'build.plugins.plugin.version' for org.apache.maven.plugins:maven-javadoc-plugin is missing.
[WARNING] It is highly recommended to fix these problems because they threaten the stability of your build.</pre>
<p>大部分如下的警告是因为用户在配置插件或者依赖的时候没有指定版本，无法保证<a href="../2010/05/07/reproducibility-of-maven-build/">构建的可重现性</a>，从而为构建引入了潜在的风险。这样的警告是一种既保持兼容性，又提倡最佳实践而做出的权衡。类似的改进还包括弃用profile.xml特性、明确分离项目依赖和插件依赖等等。</p>
<h2>改进日志输出</h2>
<p>这是一个很微小的改进，却突显了Maven开发者对Maven用户的关怀，我个人非常喜欢这点改进。简单得来说，Maven  3的构建日志更容易阅读了。插件的输出之间都有空行隔开，每个被运行插件的版本、目标、以及所处模块的artifactId都得以清晰显示。当构建出现错 误的时候，这样的输出能帮助用户更快地找到问题所在。</p>
<h2>站点（注意！）</h2>
<p>站点这一特性是Maven 2的核心，但是在Maven 3中，该特性被完全移到了maven-site-plugin中，这就导致了相关的配置也需要转移。Maven 2中与站点相关的配置是在POM的reporting元素下的，如：</p>
<pre>&lt;project&gt;
  ...
  &lt;reporting&gt;
    &lt;plugins&gt;
      &lt;plugin&gt;
        &lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;
        &lt;artifactId&gt;maven-javadoc-plugin&lt;/artifactId&gt;
        &lt;version&gt;2.7&lt;/version&gt;
      &lt;/plugin&gt;
    &lt;/plugins&gt;
  &lt;/reporting&gt;
&lt;/project&gt;</pre>
<p>在Maven 3中，所有站点相关的配置都应该出现在maven-site-plugin下面：</p>
<pre>&lt;project&gt;
 ...
 &lt;build&gt;
   ...
   &lt;plugins&gt;
     ...
     &lt;plugin&gt;
       &lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;
       &lt;artifactId&gt;maven-site-plugin&lt;/artifactId&gt;
       &lt;version&gt;3.0-beta-3&lt;/version&gt;
       &lt;configuration&gt;
         &lt;reportPlugins&gt;
           &lt;plugin&gt;
             &lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;
             &lt;artifactId&gt;maven-javadoc-plugin&lt;/artifactId&gt;
             &lt;version&gt;2.7&lt;/version&gt;
           &lt;/plugin&gt;
         &lt;/reportPlugins&gt;
       &lt;/configuration&gt;
     &lt;/plugin&gt;
   &lt;/plugins&gt;
 &lt;/build&gt;
&lt;/project&gt;</pre>
<h2>小结与致谢</h2>
<p>本文从兼容性、新特性、性能改进、以及重要细节等方面全面介绍了Maven 3。Maven 3是Maven从成熟走向巅峰的标志，如果你还未升级，我强烈建议你至少尝试一下，Maven的安装是非常简单的，只需要下载一个zip包、解压、然后设置简单的环境变量即可，<a href="http://maven.apache.org/download.html">马上去下载吧</a>！</p>
<p>由于能力及精力所限，我已经很难再写更多既不重复又符合很多读者口味的Maven文章，因此暂且计划将该专栏告一段落。我衷心感谢张凯峰的策划和编 辑，感谢读者的支持，另外也感谢我的家人，特别是我三岁的女儿，那些给写稿的时间本该属于她们。最后，我还是会持续关心  Maven的发展，有机会也一定会分享更多的经验和心得。</p>
<p><span style="color: #0000ff;"><em>本文已经首发于<a href="http://www.infoq.com/cn" target="_blank">InfoQ中文站</a>，版权所有，<em>原文为</em><a href="http://www.infoq.com/cn/news/2011/07/xxb-maven-10-time-to-update">《Maven实战（ 十）——Maven 3，是时候升级了》</a></em><em><em>，</em>如需转载，请务必附带本声明，谢谢。<br />
<a href="http://www.infoq.com/cn" target="_blank">InfoQ中文站</a>是一个面向中高端技术人员的在线独立社区，为Java、.NET、Ruby、SOA、敏捷、架构等领域提供及时而有深度的资讯、高端技术大会如<a href="http://www.qconbeijing.com/" target="_blank">QCon</a> 、线下技术交流活动<a title="QClub" href="http://www.infoq.com/cn/qclub" target="_blank">QClub</a>、免费迷你书下载如<a title="《架构师 》" href="http://www.infoq.com/cn/architect" target="_blank">《</a><a href="http://www.infoq.com/cn/architect" target="_blank">架构师</a>》等。</em></span></p>
]]></content:encoded>
			<wfw:commentRss>http://www.juvenxu.com/2011/08/05/infoq-maven-time-to-upgrade-to-maven3/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>InfoQ Maven专栏（九）——打包的技巧</title>
		<link>http://www.juvenxu.com/2011/08/05/infoq-maven-packag/</link>
		<comments>http://www.juvenxu.com/2011/08/05/infoq-maven-packag/#comments</comments>
		<pubDate>Thu, 04 Aug 2011 18:49:41 +0000</pubDate>
		<dc:creator>juvenxu</dc:creator>
				<category><![CDATA[Maven]]></category>
		<category><![CDATA[InfoQ]]></category>
		<category><![CDATA[InfoQ Maven专栏]]></category>
		<category><![CDATA[maven插件]]></category>
		<category><![CDATA[打包]]></category>

		<guid isPermaLink="false">http://www.juvenxu.com/?p=615</guid>
		<description><![CDATA[“打包“这个词听起来比较土，比较正式的说法应该是”构建项目软件包“，具体说就是将项目中的各种文件，比如源代码、编译生成的字节码、配置文件、文档，按照规范的格式生成归档，最常见的当然就是JAR包和WAR包了，复杂点的例子是Maven官方下载页面的分发包， 它有自定义的格式，方便用户直接解压后就在命令行使用。作为一款”打包工具“，Maven自然有义务帮助用户创建各种各样的包，规范的JAR包和WAR包 自然不再话下，略微复杂的自定义打包格式也必须支持，本文就介绍一些常用的打包案例以及相关的实现方式，除了前面提到的一些包以外，你还能看到如何生成源 码包、Javadoc包、以及从命令行可直接运行的CLI包。 Packaging的含义 任何一个Maven项目都需要定义POM元素packaging（如果不写则默认值为jar）。顾名思义，该元素决定了项目的打包方式。实际的情形 中，如果你不声明该元素，Maven会帮你生成一个JAR包；如果你定义该元素的值为war，那你会得到一个WAR包；如果定义其值为POM（比如是一个 父模块），那什么包都不会生成。除此之外，Maven默认还支持一些其他的流行打包格式，例如ejb3和ear。你不需要了解具体的打包细节，你所需要做 的就是告诉Maven，”我是个什么类型的项目“，这就是约定优于配置的力量。 为了更好的理解Maven的默认打包方式，我们不妨来看看简单的声明背后发生了什么，对一个jar项目执行mvn package操作，会看到如下的输出： [INFO] --- maven-jar-plugin:2.3.1:jar (default-jar) @ git-demo --- [INFO] Building jar: /home/juven/git_juven/git-demo/target/git-demo-1.2-SNAPSHOT.jar 相比之下，对一个war项目执行mvn package操作，输出是这样的： [INFO] --- maven-war-plugin:2.1:war (default-war) @ webapp-demo --- [INFO] Packaging webapp [INFO] Assembling webapp [webapp-demo] in [/home/juven/git_juven/webapp-demo/target/webapp-demo-1.0-SNAPSHOT] [INFO] Processing war project [INFO] Copying webapp resources [/home/juven/git_juven/webapp-demo/src/main/webapp] [INFO] Webapp assembled in [90 msecs] [...]]]></description>
			<content:encoded><![CDATA[<p>“打包“这个词听起来比较土，比较正式的说法应该是”构建项目软件包“，具体说就是将项目中的各种文件，比如源代码、编译生成的字节码、配置文件、文档，按照规范的格式生成归档，最常见的当然就是JAR包和WAR包了，复杂点的例子是<a href="http://maven.apache.org/download.html">Maven官方下载页面的分发包</a>， 它有自定义的格式，方便用户直接解压后就在命令行使用。作为一款”打包工具“，Maven自然有义务帮助用户创建各种各样的包，规范的JAR包和WAR包 自然不再话下，略微复杂的自定义打包格式也必须支持，本文就介绍一些常用的打包案例以及相关的实现方式，除了前面提到的一些包以外，你还能看到如何生成源 码包、Javadoc包、以及从命令行可直接运行的CLI包。</p>
<h2>Packaging的含义</h2>
<p>任何一个Maven项目都需要定义POM元素packaging（如果不写则默认值为jar）。顾名思义，该元素决定了项目的打包方式。实际的情形 中，如果你不声明该元素，Maven会帮你生成一个JAR包；如果你定义该元素的值为war，那你会得到一个WAR包；如果定义其值为POM（比如是一个 父模块），那什么包都不会生成。除此之外，Maven默认还支持一些其他的流行打包格式，例如ejb3和ear。你不需要了解具体的打包细节，你所需要做 的就是告诉Maven，”我是个什么类型的项目“，这就是<strong>约定优于配置</strong>的力量。</p>
<p>为了更好的理解Maven的默认打包方式，我们不妨来看看简单的声明背后发生了什么，对一个jar项目执行mvn package操作，会看到如下的输出：</p>
<pre>[INFO] --- maven-jar-plugin:2.3.1:jar (default-jar) @ git-demo ---
[INFO] Building jar: /home/juven/git_juven/git-demo/target/git-demo-1.2-SNAPSHOT.jar</pre>
<p>相比之下，对一个war项目执行mvn package操作，输出是这样的：</p>
<pre>[INFO] --- maven-war-plugin:2.1:war (default-war) @ webapp-demo ---
[INFO] Packaging webapp
[INFO] Assembling webapp [webapp-demo] in [/home/juven/git_juven/webapp-demo/target/webapp-demo-1.0-SNAPSHOT]
[INFO] Processing war project
[INFO] Copying webapp resources [/home/juven/git_juven/webapp-demo/src/main/webapp]
[INFO] Webapp assembled in [90 msecs]
[INFO] Building war: /home/juven/git_juven/webapp-demo/target/webapp-demo-1.0-SNAPSHOT.war</pre>
<p>对应于同样的package生命周期阶段，Maven为jar项目调用了maven-jar-plugin，为war项目调用了maven-war-plugin，换言之，<strong>packaging直接影响Maven的构建生命周期</strong>。了解这一点非常重要，特别是当你需要自定义打包行为的时候，你就必须知道去配置哪个插件。一个常见的例子就是在打包war项目的时候排除某些web资源文件，这时就应该配置maven-war-plugin如下：</p>
<pre>&lt;plugin&gt;
    &lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;
    &lt;artifactId&gt;maven-war-plugin&lt;/artifactId&gt;
    &lt;version&gt;2.1.1&lt;/version&gt;
    &lt;configuration&gt;
      &lt;webResources&gt;
        &lt;resource&gt;
          &lt;directory&gt;src/main/webapp&lt;/directory&gt;
          &lt;excludes&gt;
            &lt;exclude&gt;**/*.jpg&lt;/exclude&gt;
          &lt;/excludes&gt;
        &lt;/resource&gt;
      &lt;/webResources&gt;
    &lt;/configuration&gt;
  &lt;/plugin&gt;</pre>
<h2>源码包和Javadoc包</h2>
<p>本专栏的<a href="http://www.infoq.com/cn/news/2010/12/xxb-maven-1">《坐标规划》</a>一 文中曾解释过，一个Maven项目只生成一个主构件，当需要生成其他附属构件的时候，就需要用上classifier。源码包和Javadoc包就是附属 构件的极佳例子。它们有着广泛的用途，尤其是源码包，当你使用一个第三方依赖的时候，有时候会希望在IDE中直接进入该依赖的源码查看其实现的细节，如果 该依赖将源码包发布到了Maven仓库，那么像Eclipse就能通过m2eclipse插件解析下载源码包并关联到你的项目中，十分方便。由于生成源码 包是极其常见的需求，因此Maven官方提供了一个插件来帮助用户完成这个任务：</p>
<pre>  &lt;plugin&gt;
    &lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;
    &lt;artifactId&gt;maven-source-plugin&lt;/artifactId&gt;
    &lt;version&gt;2.1.2&lt;/version&gt;
    &lt;executions&gt;
      &lt;execution&gt;
        &lt;id&gt;attach-sources&lt;/id&gt;
        &lt;phase&gt;verify&lt;/phase&gt;
        &lt;goals&gt;
          &lt;goal&gt;jar-no-fork&lt;/goal&gt;
        &lt;/goals&gt;
      &lt;/execution&gt;
    &lt;/executions&gt;
  &lt;/plugin&gt;</pre>
<p>类似的，生成Javadoc包只需要配置插件如下：</p>
<pre>  &lt;plugin&gt;
    &lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;
    &lt;artifactId&gt;maven-javadoc-plugin&lt;/artifactId&gt;
    &lt;version&gt;2.7&lt;/version&gt;
    &lt;executions&gt;
      &lt;execution&gt;
        &lt;id&gt;attach-javadocs&lt;/id&gt;
          &lt;goals&gt;
            &lt;goal&gt;jar&lt;/goal&gt;
          &lt;/goals&gt;
      &lt;/execution&gt;
    &lt;/executions&gt;
  &lt;/plugin&gt;</pre>
<p>为了帮助所有Maven用户更方便的使用Maven中央库中海量的资源，中央仓库的维护者强制要求开源项目提交构件的时候同时提供源码包和Javadoc包。这是个很好的实践，读者也可以尝试在自己所处的公司内部实行，以促进不同项目之间的交流。</p>
<h2>可执行CLI包</h2>
<p>除了前面提到了常规JAR包、WAR包，源码包和Javadoc包，另一种常被用到的包是在命令行可直接运行的CLI（Command  Line）包。默认Maven生成的JAR包只包含了编译生成的.class文件和项目资源文件，而要得到一个可以直接在命令行通过java命令运行的 JAR文件，还要满足两个条件：</p>
<ul>
<li>JAR包中的/META-INF/MANIFEST.MF元数据文件必须包含Main-Class信息。</li>
<li>项目所有的依赖都必须在Classpath中。</li>
</ul>
<p>Maven有好几个插件能帮助用户完成上述任务，不过用起来最方便的还是<a href="http://maven.apache.org/plugins/maven-shade-plugin/">maven-shade-plugin</a>， 它可以让用户配置Main-Class的值，然后在打包的时候将值填入/META-INF/MANIFEST.MF文件。关于项目的依赖，它很聪明地将依 赖JAR文件全部解压后，再将得到的.class文件连同当前项目的.class文件一起合并到最终的CLI包中，这样，在执行CLI  JAR文件的时候，所有需要的类就都在Classpath中了。下面是一个配置样例：</p>
<pre>  &lt;plugin&gt;
    &lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;
    &lt;artifactId&gt;maven-shade-plugin&lt;/artifactId&gt;
    &lt;version&gt;1.4&lt;/version&gt;
    &lt;executions&gt;
      &lt;execution&gt;
        &lt;phase&gt;package&lt;/phase&gt;
        &lt;goals&gt;
          &lt;goal&gt;shade&lt;/goal&gt;
        &lt;/goals&gt;
        &lt;configuration&gt;
          &lt;transformers&gt;
            &lt;transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"&gt;
              &lt;mainClass&gt;com.juvenxu.mavenbook.HelloWorldCli&lt;/mainClass&gt;
            &lt;/transformer&gt;
          &lt;/transformers&gt;
        &lt;/configuration&gt;
      &lt;/execution&gt;
    &lt;/executions&gt;
  &lt;/plugin&gt;</pre>
<p>上述例子中的，我的Main-Class是com.juvenxu.mavenbook.HelloWorldCli，构建完成后，对应于一个常规 的hello-world-1.0.jar文件，我还得到了一个hello-world-1.0-cli.jar文件。细心的读者可能已经注意到了，这里 用的是cli这个classifier。最后，我可以通过<strong>java -jar hello-world-1.0-cli.jar</strong>命令运行程序。</p>
<h2>自定义格式包</h2>
<p>实际的软件项目常常会有更复杂的打包需求，例如我们可能需要为客户提供一份产品的分发包，这个包不仅仅包含项目的字节码文件，还得包含依赖以及相关脚本文件以方便客户解压后就能运行，此外分发包还得包含一些必要的文档。这时项目的源码目录结构大致是这样的：</p>
<pre>pom.xml
src/main/java/
src/main/resources/
src/test/java/
src/test/resources/
src/main/scripts/
src/main/assembly/
README.txt</pre>
<p>除了基本的pom.xml和一般Maven目录之外，这里还有一个src/main/scripts/目录，该目录会包含一些脚本文件如 run.sh和run.bat，src/main/assembly/会包含一个assembly.xml，这是打包的描述文件，稍后介绍，最后的 README.txt是份简单的文档。</p>
<p>我们希望最终生成一个zip格式的分发包，它包含如下的一个结构：</p>
<pre>bin/
lib/
README.txt</pre>
<p>其中bin/目录包含了可执行脚本run.sh和run.bat，lib/目录包含了项目JAR包和所有依赖JAR，README.txt就是前面提到的文档。</p>
<p>描述清楚需求后，我们就要搬出Maven最强大的打包插件：<a href="http://maven.apache.org/plugins/maven-assembly-plugin/">maven-assembly-plugin</a>。 它支持各种打包文件格式，包括zip、tar.gz、tar.bz2等等，通过一个打包描述文件（该例中是src/main /assembly.xml），它能够帮助用户选择具体打包哪些文件集合、依赖、模块、和甚至本地仓库文件，每个项的具体打包路径用户也能自由控制。如下 就是对应上述需求的打包描述文件src/main/assembly.xml：</p>
<pre>&lt;assembly&gt;
  &lt;id&gt;bin&lt;/id&gt;
  &lt;formats&gt;
    &lt;format&gt;zip&lt;/format&gt;
  &lt;/formats&gt;
  &lt;dependencySets&gt;
    &lt;dependencySet&gt;
      &lt;useProjectArtifact&gt;true&lt;/useProjectArtifact&gt;
      &lt;outputDirectory&gt;lib&lt;/outputDirectory&gt;
    &lt;/dependencySet&gt;
  &lt;/dependencySets&gt;
  &lt;fileSets&gt;
    &lt;fileSet&gt;
      &lt;outputDirectory&gt;/&lt;/outputDirectory&gt;
      &lt;includes&gt;
        &lt;include&gt;README.txt&lt;/include&gt;
      &lt;/includes&gt;
    &lt;/fileSet&gt;
    &lt;fileSet&gt;
      &lt;directory&gt;src/main/scripts&lt;/directory&gt;
      &lt;outputDirectory&gt;/bin&lt;/outputDirectory&gt;
      &lt;includes&gt;
        &lt;include&gt;run.sh&lt;/include&gt;
        &lt;include&gt;run.bat&lt;/include&gt;
      &lt;/includes&gt;
    &lt;/fileSet&gt;
  &lt;/fileSets&gt;
&lt;/assembly&gt;</pre>
<ul>
<li>首先这个assembly.xml文件的id对应了其最终生成文件的classifier。</li>
<li>其次formats定义打包生成的文件格式，这里是zip。因此结合id我们会得到一个名为hello-world-1.0-bin.zip的文件。（假设artifactId为hello-world，version为1.0）</li>
<li>dependencySets用来定义选择依赖并定义最终打包到什么目录，这里我们声明的一个depenencySet默认包含所有所有 依赖，而useProjectArtifact表示将项目本身生成的构件也包含在内，最终打包至输出包内的lib路径下（由 outputDirectory指定）。</li>
<li>fileSets允许用户通过文件或目录的粒度来控制打包。这里的第一个fileSet打包README.txt文件至包的根目录下，第二个fileSet则将src/main/scripts下的run.sh和run.bat文件打包至输出包的bin目录下。</li>
</ul>
<p>打包描述文件所支持的配置远超出本文所能覆盖的范围，为了避免读者被过多细节扰乱思维，这里不再展开，读者若有需要可以去参考<a href="http://maven.apache.org/plugins/maven-assembly-plugin/assembly.html">这份文档</a>。</p>
<p>最后，我们需要配置maven-assembly-plugin使用打包描述文件，并绑定生命周期阶段使其自动执行打包操作：</p>
<pre>  &lt;plugin&gt;
    &lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;
    &lt;artifactId&gt;maven-assembly-plugin&lt;/artifactId&gt;
    &lt;version&gt;2.2.1&lt;/version&gt;
    &lt;configuration&gt;
      &lt;descriptors&gt;
        &lt;descriptor&gt;src/main/assembly/assembly.xml&lt;/descriptor&gt;
      &lt;/descriptors&gt;
    &lt;/configuration&gt;
    &lt;executions&gt;
      &lt;execution&gt;
        &lt;id&gt;make-assembly&lt;/id&gt;
        &lt;phase&gt;package&lt;/phase&gt;
        &lt;goals&gt;
          &lt;goal&gt;single&lt;/goal&gt;
        &lt;/goals&gt;
      &lt;/execution&gt;
    &lt;/executions&gt;
  &lt;/plugin&gt;</pre>
<p>运行<strong>mvn clean package</strong>之后，我们就能在target/目录下得到名为hello-world-1.0-bin.zip的分发包了。</p>
<h2>小结</h2>
<p>打包是项目构建最重要的组成部分之一，本文介绍了主流Maven打包技巧，包括默认打包方式的原理、如何制作源码包和Javadoc包、如何制作命 令行可运行的CLI包、以及进一步的，如何基于个性化需求自定义打包格式。这其中涉及了很多的Maven插件，当然最重要，也是最为复杂和强大的打包插件 就是maven-assembly-plugin。事实上Maven本身的分发包就是通过maven-assembly-plugin制作的，感兴趣的读 者可以直接<a href="http://svn.apache.org/viewvc/maven/maven-3/trunk/apache-maven/src/main/assembly/">查看源码</a>一窥究竟。</p>
<p><span style="color: #0000ff;"><em>本文已经首发于<a href="http://www.infoq.com/cn" target="_blank">InfoQ中文站</a>，版权所有，<em>原文为</em><a href="http://www.infoq.com/cn/news/2011/06/xxb-maven-9-package">《Maven实战（九）——打包的技巧》</a></em><em><em>，</em>如需转载，请务必附带本声明，谢谢。<br />
<a href="http://www.infoq.com/cn" target="_blank">InfoQ中文站</a>是一个面向中高端技术人员的在线独立社区，为Java、.NET、Ruby、SOA、敏捷、架构等领域提供及时而有深度的资讯、高端技术大会如<a href="http://www.qconbeijing.com/" target="_blank">QCon</a> 、线下技术交流活动<a title="QClub" href="http://www.infoq.com/cn/qclub" target="_blank">QClub</a>、免费迷你书下载如<a title="《架构师 》" href="http://www.infoq.com/cn/architect" target="_blank">《</a><a href="http://www.infoq.com/cn/architect" target="_blank">架构师</a>》等。</em></span></p>
]]></content:encoded>
			<wfw:commentRss>http://www.juvenxu.com/2011/08/05/infoq-maven-packag/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

