<?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>IDEAL Garden</title>
	<atom:link href="http://kfzhang.thoughtworkers.org/feed/" rel="self" type="application/rss+xml" />
	<link>http://kfzhang.thoughtworkers.org</link>
	<description></description>
	<lastBuildDate>Tue, 08 May 2012 14:16:49 +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://kfzhang.thoughtworkers.org/2012/05/impedance-mismatch-at-front-end/</link>
		<comments>http://kfzhang.thoughtworkers.org/2012/05/impedance-mismatch-at-front-end/#comments</comments>
		<pubDate>Tue, 08 May 2012 14:11:54 +0000</pubDate>
		<dc:creator>zhangkf</dc:creator>
				<category><![CDATA[Tech]]></category>
		<category><![CDATA[Work]]></category>
		<category><![CDATA[extjs]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[mvc]]></category>

		<guid isPermaLink="false">http://kfzhang.thoughtworkers.org/?p=1102</guid>
		<description><![CDATA[Impedance Mismatch（阻抗失配）经常被用来比喻服务器端面向对象代码和关系型数据库存储模型之间的关系，先有ORM技术，后有NoSQL（Document based，Key-value store），都是解决这个阻抗失配的方案。 最近在做的一个项目，具有丰富的前端UI，简单的后台逻辑。应客户的要求，采用ExtJS4作为前端技术，利用它极具交互性的UI和号称优雅的MVC框架，来构造应用的所有页面。 不落俗套，在应用最初搭建阶段，是和ExtJS相处的蜜月期，“优雅”的MVC框架和清晰的封装让人眼前一亮。但是随着项目的进展，在功能需求没有显著增加的同时，客户对于前端交互友好性的需求却与日俱增，不可避免地让前端构造UI及交互的代码日益复杂。 出于面向对象和封装的考虑，对于页面上大大小小的控件，我们基本上都做了封装，而且封装还是嵌套的，在大控件内部还封装着小空间。每一个控件基本上都是满足ExtJS的MVC模式，即对应至少View、Controller两个“类”。 同样出于对架构腐化的担心和对它的不断思考和优化，我们在不断地调整不同类的封装，对事件和行为做一一调整，力争做到合适的封装、减少重复代码、易于理解，从而达到更好的可维护性。 这样最直接的后果就是，在每次我们需要深入代码去解决一些问题时，要费上好一番功夫，从大控件找到内部的小控件，从一个事件发送者搜索到事件的响应者，才能确定出问题的代码可能藏在某个犄角旮旯。 对于封装如此良好、层次如此清晰的前端“面向对象”代码，我的反应开始是：这是否就是解决前端实现或者说架构最优的选择呢？可惜的是，我在Stackoverflow和Delicious上没有找到相似的讨论，倒是发现了很多对于JavaScript MVC的讨论。 以下是我自己的一点想法： 前端代码用ExtJS或者Dojo这样的rich library构建，用程序员惯常的面向对象思维和成熟的MVC架构来实现，无可厚非。但实现的过程与前端页面的渲染并无简单直接的对应关系。程序员在用熟悉的建模和框架时，不会简单地推演出到正在实现的控件及其行为在页面渲染后将以怎样的结果出现。这里需要框架自身的技术支撑和程序员对框架的理解，框架加载脚本的顺序、对MVC实现的风格，不一而足。 浏览器是从页面的开头到结束完成页面的渲染，中间包括脚本的同步或异步的加载，包括框架对于富UI控件的渲染。在页面初始渲染成功后，由框架接手完成未来发生的所有的UI交互，直至页面重新刷新。 如果把浏览器页面的渲染结果，或浏览器内存中的DOM看作是结构、样式和数据的存储，类似于关系型数据中逐行的数据，这与前端实现所采用的面向对象和MVC相对应，同样存在模式的不匹配，即阻抗失配。 不同的是，程序员不用太关心数据库如何存储数据，但不得不清楚不同浏览器如何渲染页面，及框架如何完成帮助后续的交互。]]></description>
			<content:encoded><![CDATA[<p>Impedance Mismatch（阻抗失配）经常被用来比喻服务器端面向对象代码和关系型数据库存储模型之间的关系，先有ORM技术，后有NoSQL（Document based，Key-value store），都是解决这个阻抗失配的方案。</p>
<p>最近在做的一个项目，具有丰富的前端UI，简单的后台逻辑。应客户的要求，采用ExtJS4作为前端技术，利用它极具交互性的UI和号称优雅的MVC框架，来构造应用的所有页面。</p>
<p>不落俗套，在应用最初搭建阶段，是和ExtJS相处的蜜月期，“优雅”的MVC框架和清晰的封装让人眼前一亮。但是随着项目的进展，在功能需求没有显著增加的同时，客户对于前端交互友好性的需求却与日俱增，不可避免地让前端构造UI及交互的代码日益复杂。</p>
<p>出于面向对象和封装的考虑，对于页面上大大小小的控件，我们基本上都做了封装，而且封装还是嵌套的，在大控件内部还封装着小空间。每一个控件基本上都是满足ExtJS的MVC模式，即对应至少View、Controller两个“类”。</p>
<p>同样出于对架构腐化的担心和对它的不断思考和优化，我们在不断地调整不同类的封装，对事件和行为做一一调整，力争做到合适的封装、减少重复代码、易于理解，从而达到更好的可维护性。</p>
<p>这样最直接的后果就是，在每次我们需要深入代码去解决一些问题时，要费上好一番功夫，从大控件找到内部的小控件，从一个事件发送者搜索到事件的响应者，才能确定出问题的代码可能藏在某个犄角旮旯。</p>
<p>对于封装如此良好、层次如此清晰的前端“面向对象”代码，我的反应开始是：这是否就是解决前端实现或者说架构最优的选择呢？可惜的是，我在Stackoverflow和Delicious上没有找到相似的讨论，倒是发现了很多对于JavaScript MVC的讨论。</p>
<p>以下是我自己的一点想法：</p>
<p>前端代码用ExtJS或者Dojo这样的rich library构建，用程序员惯常的面向对象思维和成熟的MVC架构来实现，无可厚非。但实现的过程与前端页面的渲染并无简单直接的对应关系。程序员在用熟悉的建模和框架时，不会简单地推演出到正在实现的控件及其行为在页面渲染后将以怎样的结果出现。这里需要框架自身的技术支撑和程序员对框架的理解，框架加载脚本的顺序、对MVC实现的风格，不一而足。</p>
<p>浏览器是从页面的开头到结束完成页面的渲染，中间包括脚本的同步或异步的加载，包括框架对于富UI控件的渲染。在页面初始渲染成功后，由框架接手完成未来发生的所有的UI交互，直至页面重新刷新。</p>
<p>如果把浏览器页面的渲染结果，或浏览器内存中的DOM看作是结构、样式和数据的存储，类似于关系型数据中逐行的数据，这与前端实现所采用的面向对象和MVC相对应，同样存在模式的不匹配，即阻抗失配。</p>
<p>不同的是，程序员不用太关心数据库如何存储数据，但不得不清楚不同浏览器如何渲染页面，及框架如何完成帮助后续的交互。</p>
]]></content:encoded>
			<wfw:commentRss>http://kfzhang.thoughtworkers.org/2012/05/impedance-mismatch-at-front-end/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Team的一次Code Kata</title>
		<link>http://kfzhang.thoughtworkers.org/2012/01/code-kata/</link>
		<comments>http://kfzhang.thoughtworkers.org/2012/01/code-kata/#comments</comments>
		<pubDate>Mon, 16 Jan 2012 14:06:03 +0000</pubDate>
		<dc:creator>zhangkf</dc:creator>
				<category><![CDATA[Agile]]></category>
		<category><![CDATA[Tech]]></category>
		<category><![CDATA[TW]]></category>
		<category><![CDATA[Kata]]></category>
		<category><![CDATA[pair programming]]></category>
		<category><![CDATA[TDD]]></category>
		<category><![CDATA[ThoughtBlogs]]></category>

		<guid isPermaLink="false">http://kfzhang.thoughtworkers.org/?p=1098</guid>
		<description><![CDATA[上周四的中午饭后，我们team坐下来完成了一次Code Kata练习。跟之前的几次邀请PwC team同事过来pair和coach不同，这次是我们组自己内部完成一次练习，题目来自Yuheng之前的一个练习：文曲星上的猜数字游戏。 题目规则很简单： 游戏开始后，系统会随机给出四个不重复的数字。由用户输入自己猜测的四个数字。 如果数字猜对而且位置也对，就是1一个A。 如果数字猜对但位置不对，就是一个B。 返回结果是如“2A1B”这样的字串。 猜错6次，游戏提示结束。重来。 开始提出的要求简单：用TDD驱动出实际代码。 大家抽签后开始pair，Yuheng还会一边计时一边催促，pair的气氛基本保持紧张有序。 在我和XuChen pair开始代码后，我们很容易写出第一个测试1，期望返回结果是&#8221;4A0B&#8221;，最简单的代码实现让测试变绿。 当我们试图写下第二个测试2，试图期望返回结果是“2A1B”时，我们发现不得不面对如何这个游戏规则的最核心算法，但可惜的是，猛然间对这个算法没有头绪。 局面一时僵住，停顿了有两分钟。 直觉和一点经验告诉我们，这时该拆解任务了。很容易想到，如果计算出几个A和几个B是很直白的拆分。 我们可以很容易写出一个测试3，测试猜测的四个数字跟事先给定的四个数字相比，有几个A类数字（循环比较），我们称之为perfect number。 也很容易写出另外一个测试4，测试猜测的四个数字跟事先给定的四个数字相比，有几个B类数字（在上个算法的基础上再循环比较），我们称之为good number。 写完针对测试3和4的实现代码，我们发现我们已经完成了最基本的算法，功能完成了。剩下的是重构代码。 从我们这次的经验看，我有一些收获和心得： 测试就是代码的设计，你看测试3和4导致的结果就是我们有了对应的两个计算方法。你打算怎么测，你的实现代码就会是怎样的。 印证了在Wikipedia中那段话，pair programming尤其适合面对一些challenging的任务（至少开始的时候是）。 分解任务是王道。我们在不同的level拆分任务，从story拆分成task，从大问题拆分成小问题，莫不如是。 囿于经验，不期望由端到端的测试能逐步甚至一下子推导出完整、完善的代码实现。而这样的练习，恰恰是我们锻造自己经验必不可少的过程。 我们在实现代码时，仍然欠缺的是： 对于测试方法名的命名，不够清晰直白。 对于算法代码的实现，简单粗糙，还需要重构。]]></description>
			<content:encoded><![CDATA[<p>上周四的中午饭后，我们team坐下来完成了一次Code Kata练习。跟之前的几次邀请PwC team同事过来pair和coach不同，这次是我们组自己内部完成一次练习，题目来自Yuheng之前的一个练习：文曲星上的猜数字游戏。</p>
<p>题目规则很简单：</p>
<ol>
<li>游戏开始后，系统会随机给出四个不重复的数字。由用户输入自己猜测的四个数字。</li>
<li>如果数字猜对而且位置也对，就是1一个A。</li>
<li>如果数字猜对但位置不对，就是一个B。</li>
<li>返回结果是如“2A1B”这样的字串。</li>
<li>猜错6次，游戏提示结束。重来。</li>
</ol>
<p>开始提出的要求简单：用TDD驱动出实际代码。</p>
<p>大家抽签后开始pair，Yuheng还会一边计时一边催促，pair的气氛基本保持紧张有序。</p>
<p>在我和XuChen pair开始代码后，我们很容易写出第一个测试1，期望返回结果是&#8221;4A0B&#8221;，最简单的代码实现让测试变绿。</p>
<p>当我们试图写下第二个测试2，试图期望返回结果是“2A1B”时，我们发现不得不面对如何这个游戏规则的最核心算法，但可惜的是，猛然间对这个算法没有头绪。</p>
<p>局面一时僵住，停顿了有两分钟。</p>
<p>直觉和一点经验告诉我们，这时该拆解任务了。很容易想到，如果计算出几个A和几个B是很直白的拆分。</p>
<p>我们可以很容易写出一个测试3，测试猜测的四个数字跟事先给定的四个数字相比，有几个A类数字（循环比较），我们称之为perfect number。</p>
<p>也很容易写出另外一个测试4，测试猜测的四个数字跟事先给定的四个数字相比，有几个B类数字（在上个算法的基础上再循环比较），我们称之为good number。</p>
<p>写完针对测试3和4的实现代码，我们发现我们已经完成了最基本的算法，功能完成了。剩下的是重构代码。</p>
<p>从我们这次的经验看，我有一些收获和心得：</p>
<ol>
<li>测试就是代码的设计，你看测试3和4导致的结果就是我们有了对应的两个计算方法。你打算怎么测，你的实现代码就会是怎样的。</li>
<li>印证了在Wikipedia中那段话，pair programming尤其适合面对一些challenging的任务（至少开始的时候是）。</li>
<li>分解任务是王道。我们在不同的level拆分任务，从story拆分成task，从大问题拆分成小问题，莫不如是。</li>
<li>囿于经验，不期望由端到端的测试能逐步甚至一下子推导出完整、完善的代码实现。而这样的练习，恰恰是我们锻造自己经验必不可少的过程。</li>
</ol>
<p>我们在实现代码时，仍然欠缺的是：</p>
<ol>
<li>对于测试方法名的命名，不够清晰直白。</li>
<li>对于算法代码的实现，简单粗糙，还需要重构。</li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://kfzhang.thoughtworkers.org/2012/01/code-kata/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>为什么要结对编程？</title>
		<link>http://kfzhang.thoughtworkers.org/2011/10/why-pair-programming/</link>
		<comments>http://kfzhang.thoughtworkers.org/2011/10/why-pair-programming/#comments</comments>
		<pubDate>Sun, 09 Oct 2011 02:38:53 +0000</pubDate>
		<dc:creator>zhangkf</dc:creator>
				<category><![CDATA[Agile]]></category>
		<category><![CDATA[Tech]]></category>
		<category><![CDATA[pair programming]]></category>
		<category><![CDATA[ThoughtBlogs]]></category>

		<guid isPermaLink="false">http://kfzhang.thoughtworkers.org/?p=1091</guid>
		<description><![CDATA[以下内容摘自myThoughtWorks中对于结对编程（Pair Programming）的讨论。 结对编程与非结对编程相比那个效率会更高？ 这个问题没有一个明确的答案，没有人可以很肯定的说结对编程就是会比非结对编程更有效率。效率不单单是时间，还包含效果。 如 果对于一个技术难度不高，一个人几天就可以搞定，后期不需要维护的一个小项目来说可能结对编程在效率上会低于非结对编程。但是我们twer是关注代码质量 的，面临的项目一般都是需要持续发展，而且是具有一定规模的。对于这样的项目和我们，从长远来看，结对编程会带给我们长足的发展和更高的效率。对于这点我 总结了如下几点（欢迎补充）： 代码质量。结对编程与非结对编程相比，往往更加容易写出更短 的代码，做出更好的设计，产生的更少的bug。俗话说三个臭皮匠顶过一个诸葛亮，每个人的思维 都是有瓶颈的，两个人的合作通常会考虑更多的设计选项，达成更简单，更易维护的设计。研究发现结对编程bug率降低会15%到50%，这个会根据程序员的 经验以及任务的复杂度而不同，这样就会大大减少以后修bug的时间，降低维护成本。这样我们才敢一个项目只有一个QA或者没有QA呀！ 互相督促。 在结对编程的过程中我们可以相互督促，比如严格去TDD减少裸奔，提高注意力避免一个人注意力不集中或者花时间上网处理个人事宜，避免偷工减料 等等，从而也可以在某种程度上保证我们的代码质量。而且人们更不愿意打断两个结对编程的人，而单独工作的人却容易被打断，这样也增加了我们专注工作的时 间。 知识共享。在结对编程我们是知识共享的，还有我们会不停的switch pair，轮流与团队中的所有其他程序员结对编程，而不是仅与某个程序员编程，使得系统的知识在整个团队中传播，减少了程序员休假或者离开团队带来的风险，从而可以保证我们项目的可持续发展。 新人成长。 这是结对编程很重要的一个作用。曾经听大大说过，他和大熊发现，在别的公司毕业刚刚一年的毕业生在项目中可以承担的还很少，但是在我们公司很多 人已经成为了项目的骨干。这很大程度上要归功于结对。当新员工进入一个项目的时候，我们往往会安排有经验的老员工去跟他们结对，这样新员工可以更快熟悉项 目情况，更快的进入状态，更快的发现自己的不足，也可以学到更多的东西，更快的成长起来为项目做出贡献。 沟通能力。结对编程需要两个人一起讨论，一起把一件事情做完，也是对我们沟通能力的一种锻炼。让我们不再是很多人眼中只会闷头写代码的木讷的程序员了。 结对可以省钱：http://www.infoq.com/cn/news/2009/06/dollar-value-of-pair-programming 徐昊说结对还可以Simple Design：http://blog.vincentx.info/2007/03/agile-101-pair-programming-simple-design/]]></description>
			<content:encoded><![CDATA[<p><em>以下内容摘自myThoughtWorks中对于结对编程（Pair Programming）的讨论。</em></p>
<p>结对编程与非结对编程相比那个效率会更高？</p>
<p>这个问题没有一个明确的答案，没有人可以很肯定的说结对编程就是会比非结对编程更有效率。效率不单单是时间，还包含效果。</p>
<p>如 果对于一个技术难度不高，一个人几天就可以搞定，后期不需要维护的一个小项目来说可能结对编程在效率上会低于非结对编程。但是我们twer是关注代码质量 的，面临的项目一般都是需要持续发展，而且是具有一定规模的。对于这样的项目和我们，从长远来看，结对编程会带给我们长足的发展和更高的效率。对于这点我 总结了如下几点（欢迎补充）：</p>
<ol>
<li><strong>代码质量</strong>。结对编程与非结对编程相比，往往更加容易写出更短 的代码，做出更好的设计，产生的更少的bug。俗话说三个臭皮匠顶过一个诸葛亮，每个人的思维 都是有瓶颈的，两个人的合作通常会考虑更多的设计选项，达成更简单，更易维护的设计。研究发现结对编程bug率降低会15%到50%，这个会根据程序员的 经验以及任务的复杂度而不同，这样就会大大减少以后修bug的时间，降低维护成本。这样我们才敢一个项目只有一个QA或者没有QA呀！</li>
<li><strong>互相督促</strong>。 在结对编程的过程中我们可以相互督促，比如严格去TDD减少裸奔，提高注意力避免一个人注意力不集中或者花时间上网处理个人事宜，避免偷工减料 等等，从而也可以在某种程度上保证我们的代码质量。而且人们更不愿意打断两个结对编程的人，而单独工作的人却容易被打断，这样也增加了我们专注工作的时 间。</li>
<li><strong>知识共享</strong>。在结对编程我们是知识共享的，还有我们会不停的switch pair，轮流与团队中的所有其他程序员结对编程，而不是仅与某个程序员编程，使得系统的知识在整个团队中传播，减少了程序员休假或者离开团队带来的风险，从而可以保证我们项目的可持续发展。</li>
<li><strong>新人成长</strong>。 这是结对编程很重要的一个作用。曾经听大大说过，他和大熊发现，在别的公司毕业刚刚一年的毕业生在项目中可以承担的还很少，但是在我们公司很多 人已经成为了项目的骨干。这很大程度上要归功于结对。当新员工进入一个项目的时候，我们往往会安排有经验的老员工去跟他们结对，这样新员工可以更快熟悉项 目情况，更快的进入状态，更快的发现自己的不足，也可以学到更多的东西，更快的成长起来为项目做出贡献。</li>
<li><strong>沟通能力</strong>。结对编程需要两个人一起讨论，一起把一件事情做完，也是对我们沟通能力的一种锻炼。让我们不再是很多人眼中只会闷头写代码的木讷的程序员了。</li>
<li><strong>结对可以省钱</strong>：<a href="http://www.infoq.com/cn/news/2009/06/dollar-value-of-pair-programming">http://www.infoq.com/cn/news/2009/06/dollar-value-of-pair-programming</a></li>
<li><strong>徐昊说结对还可以Simple Design</strong>：<a href="http://blog.vincentx.info/2007/03/agile-101-pair-programming-simple-design/">http://blog.vincentx.info/2007/03/agile-101-pair-programming-simple-design/</a></li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://kfzhang.thoughtworkers.org/2011/10/why-pair-programming/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>2011 ThoughtWorks烽火传奇</title>
		<link>http://kfzhang.thoughtworkers.org/2011/09/2011-thoughtworks-cs/</link>
		<comments>http://kfzhang.thoughtworkers.org/2011/09/2011-thoughtworks-cs/#comments</comments>
		<pubDate>Wed, 28 Sep 2011 10:05:52 +0000</pubDate>
		<dc:creator>zhangkf</dc:creator>
				<category><![CDATA[TW]]></category>
		<category><![CDATA[game]]></category>

		<guid isPermaLink="false">http://kfzhang.thoughtworkers.org/?p=1087</guid>
		<description><![CDATA[Chapter1 树林外传来密集的枪声，由远及近，渐渐清晰。 山顶树丛后，迷彩的掩护下，几道焦急的目光投向了中心处的一位彪形大汉。 张凯峰队长抬手擦了擦额头上混在一起的血和汗，心中暗暗叹了口气，从枪声判断，敌人距离这里已经不远，这也就意味着一队高队长和二队月队长的防线已经溃败。时间已经不多，是时候来做最后的诀别了。 队长慢慢的抬头，沙哑的声音从干裂的嘴唇中缓缓吐出：“同志们，我想大家都明白，防线已被攻破，我们此次的失败已在所难免。” 说到这里，队长艰难的停下来，重重的喘息，仿佛“失败”二字就已经给了他巨大的负担。 身边的战士有人紧咬着嘴唇，有人摘下军帽，死死地攥在手里。 张队长用目光在所有人的身上环视一圈，然后继续开口：“很不甘心，是么？我也一样啊！一想到圣教的火焰或许会在此处熄灭，我的心就像被剖开一般疼痛。试问，还有什么，能比失去光明的指引更加痛苦！！！” 这样沉重的话语带给人们的是更深刻的悲痛，几个女孩子已经把持不住，相拥在一起低声的啜泣。 “但 是，我们的使命还未完结，如果死亡是我们注定的终结，我愿让这终结如烟花般绚烂，将我们不屈的斗志传达，哪怕只有一瞬间，也要照亮这黑暗的世间！！！同志 们冲啊！！！！！”张队长站起身来，大手一挥，从树丛中一跃而出，向着外漫山遍野的蓝色敌军冲去：“我愿将此身化为碉堡，在死后仍能为同志们挡去敌人的子 弹！日月神教!千秋永存！！！” “啊啊啊！冲啊！！！”紧跟着张队长，付莹参谋也迎向了敌军。 “铁甲依然在~ ”江荣冲出去了。 “我们的敌人必将被消灭！ ” 李斌冲出去了。 “女性！荣耀！梦想！”四眼冲出去了。 “啊啊啊啊啊啊~~~~~~”张桐也冲去了。 一点一点绿色的身影冲向了蓝色的防线，就像明亮的火焰冲进蔚蓝的大海。 这就是惊天动地的首次2011新员工真人CS第一战，史称红螺寺山体攻防战中，最为悲壮的一刻！天地为之变色，草木为之含悲，日月神教永垂不朽，荣光与我们同在！！！ &#160; Chapter2 天堂里，一群绿衣服的家伙蹲在地上，在角落里围成一个圈。中间还是我们熟悉的张队，正不耐烦的捻灭一只烟：“别吵别吵~ 死都死了，还不冷静。我们现在不是要推卸责任，而是要吸取经验，总结教训，从根部开始，源头开始，上起祖宗十八代，下数华夏五千年，深刻挖掘这次战争失败原因！怎么着我们就输了呢？！” “老 大，我先说！”二队的月队长率先起身，“我们的敌军既优秀又强大，有三成以上以前就参加过各种战役，有着丰富的经验，是我们所不能比拟的。而且此次战役 中，敌军又启用了先进的生化武器，将徐晨，侯斌轶改造为僵尸战士作战，无法杀死。从而轻而易举，气势如虹的击溃了我们的防线。老大您明鉴，不是兄弟们不努 力，实在是敌军太狡猾啊！” “去 去去，你这是给敌人开表彰大会呢吧！”张队长哄蚊子似的摆了摆手，“什么敌军太狡猾，分明就是我军太失水准。就说小月月你身为二队的队长，为了拉风非要穿 一件桔黄色的衣服，在绿色的树林里走到哪里都是活动靶，开场没三分钟就挂掉了，严重影响了我军的正常战略节奏，是导致最后失败的罪魁祸首。” “所以说不怕神一样的对手，就怕猪一样的队友。”角落里，平素最爱吐槽的四眼儿政委接着张老大的话茬，持续进行毒舌攻击。 “你也好不到哪儿去！”张老大没好气的开始数落小政委，“在背后开冷枪误伤一个顶仨，真正面对敌人了，子弹射程还没有唾沫星子喷的一半儿远。一场下来三条命全送出去了，可一枪都没打到敌人！” 听到老大点名自己，四眼哭丧着脸站起来：“老大，我我我，我错了。同为政委，蓝军的Magen那是战神加护雅典娜附体，上场先杀死4人。我是刚刚亮相就被人乱枪打死。我愧对祖国愧对党。为表羞愧之心我决定以死谢罪，大家你们都不要拦我啊啊啊~” 说罢，四眼儿政委不知从哪里变出一根半指来宽的麻绳，笨手笨脚地在身旁的歪脖树上打了个圈，抻着脖子想把那颗大脑袋套进去，作势要去见马克思。 “算了算了，又不是盗梦空间，你当能在死亡状态下再死二回啊。”张队长最不待见这种苦情戏，赶紧招呼旁边的娴静军长把四眼儿拦了下来。 几个人七首八脚的把四眼弄下来，这才发现不知什么时候起，四眼儿已经进入了发呆状态。张队长心说不好，该不会是刚才批评的太狠了给小孩儿整自闭了吧。 &#8230; <a href="http://kfzhang.thoughtworkers.org/2011/09/2011-thoughtworks-cs/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Chapter1</p>
<p>树林外传来密集的枪声，由远及近，渐渐清晰。 山顶树丛后，迷彩的掩护下，几道焦急的目光投向了中心处的一位彪形大汉。</p>
<p>张凯峰队长抬手擦了擦额头上混在一起的血和汗，心中暗暗叹了口气，从枪声判断，敌人距离这里已经不远，这也就意味着一队高队长和二队月队长的防线已经溃败。时间已经不多，是时候来做最后的诀别了。</p>
<p>队长慢慢的抬头，沙哑的声音从干裂的嘴唇中缓缓吐出：“同志们，我想大家都明白，防线已被攻破，我们此次的失败已在所难免。”</p>
<p>说到这里，队长艰难的停下来，重重的喘息，仿佛“失败”二字就已经给了他巨大的负担。</p>
<p>身边的战士有人紧咬着嘴唇，有人摘下军帽，死死地攥在手里。</p>
<p>张队长用目光在所有人的身上环视一圈，然后继续开口：“很不甘心，是么？我也一样啊！一想到圣教的火焰或许会在此处熄灭，我的心就像被剖开一般疼痛。试问，还有什么，能比失去光明的指引更加痛苦！！！”</p>
<p>这样沉重的话语带给人们的是更深刻的悲痛，几个女孩子已经把持不住，相拥在一起低声的啜泣。</p>
<p>“但 是，我们的使命还未完结，如果死亡是我们注定的终结，我愿让这终结如烟花般绚烂，将我们不屈的斗志传达，哪怕只有一瞬间，也要照亮这黑暗的世间！！！同志 们冲啊！！！！！”张队长站起身来，大手一挥，从树丛中一跃而出，向着外漫山遍野的蓝色敌军冲去：“我愿将此身化为碉堡，在死后仍能为同志们挡去敌人的子 弹！日月神教!千秋永存！！！”</p>
<p>“啊啊啊！冲啊！！！”紧跟着张队长，付莹参谋也迎向了敌军。</p>
<p>“铁甲依然在~ ”江荣冲出去了。</p>
<p>“我们的敌人必将被消灭！ ” 李斌冲出去了。</p>
<p>“女性！荣耀！梦想！”四眼冲出去了。</p>
<p>“啊啊啊啊啊啊~~~~~~”张桐也冲去了。</p>
<p>一点一点绿色的身影冲向了蓝色的防线，就像明亮的火焰冲进蔚蓝的大海。</p>
<p>这就是惊天动地的首次2011新员工真人CS第一战，史称红螺寺山体攻防战中，最为悲壮的一刻！天地为之变色，草木为之含悲，日月神教永垂不朽，荣光与我们同在！！！</p>
<p>&nbsp;</p>
<p>Chapter2</p>
<p>天堂里，一群绿衣服的家伙蹲在地上，在角落里围成一个圈。中间还是我们熟悉的张队，正不耐烦的捻灭一只烟：“别吵别吵~ 死都死了，还不冷静。我们现在不是要推卸责任，而是要吸取经验，总结教训，从根部开始，源头开始，上起祖宗十八代，下数华夏五千年，深刻挖掘这次战争失败原因！怎么着我们就输了呢？！”</p>
<p>“老 大，我先说！”二队的月队长率先起身，“我们的敌军既优秀又强大，有三成以上以前就参加过各种战役，有着丰富的经验，是我们所不能比拟的。而且此次战役 中，敌军又启用了先进的生化武器，将徐晨，侯斌轶改造为僵尸战士作战，无法杀死。从而轻而易举，气势如虹的击溃了我们的防线。老大您明鉴，不是兄弟们不努 力，实在是敌军太狡猾啊！”</p>
<p>“去 去去，你这是给敌人开表彰大会呢吧！”张队长哄蚊子似的摆了摆手，“什么敌军太狡猾，分明就是我军太失水准。就说小月月你身为二队的队长，为了拉风非要穿 一件桔黄色的衣服，在绿色的树林里走到哪里都是活动靶，开场没三分钟就挂掉了，严重影响了我军的正常战略节奏，是导致最后失败的罪魁祸首。”</p>
<p>“所以说不怕神一样的对手，就怕猪一样的队友。”角落里，平素最爱吐槽的四眼儿政委接着张老大的话茬，持续进行毒舌攻击。</p>
<p>“你也好不到哪儿去！”张老大没好气的开始数落小政委，“在背后开冷枪误伤一个顶仨，真正面对敌人了，子弹射程还没有唾沫星子喷的一半儿远。一场下来三条命全送出去了，可一枪都没打到敌人！”</p>
<p>听到老大点名自己，四眼哭丧着脸站起来：“老大，我我我，我错了。同为政委，蓝军的Magen那是战神加护雅典娜附体，上场先杀死4人。我是刚刚亮相就被人乱枪打死。我愧对祖国愧对党。为表羞愧之心我决定以死谢罪，大家你们都不要拦我啊啊啊~”</p>
<p>说罢，四眼儿政委不知从哪里变出一根半指来宽的麻绳，笨手笨脚地在身旁的歪脖树上打了个圈，抻着脖子想把那颗大脑袋套进去，作势要去见马克思。</p>
<p>“算了算了，又不是盗梦空间，你当能在死亡状态下再死二回啊。”张队长最不待见这种苦情戏，赶紧招呼旁边的娴静军长把四眼儿拦了下来。</p>
<p>几个人七首八脚的把四眼弄下来，这才发现不知什么时候起，四眼儿已经进入了发呆状态。张队长心说不好，该不会是刚才批评的太狠了给小孩儿整自闭了吧。</p>
<p>众人正琢磨着要不要弄个电击疗法刺激刺激四眼儿政委的时候，这边四眼突然大叫一声：“我知道了！”然后从地上一跃而起，跑到张队长面前，一把拉起张队的手：“队长，我知道了！我可以先复活，这样就可以继续死了。”</p>
<p>“额？你是说我们可以复活？”张队长问道。</p>
<p>“是啊是啊，队长你没听过信春哥死后原地满血满状态复活的！！”小政委乐颠颠的说。</p>
<p>“哇呀呀呀呀~ 有这等好事，那还等什么？！”张队长一把抄起地上的抢，举起高呼，“小的们，跟着我，复活继续跟他们拼一场啊！！！！！！”</p>
<p>&nbsp;</p>
<p>Chapter3</p>
<p>“怎么又死了呢！！”张队长的咆哮惊走了山林上飞禽走兽，“你们不是自称攻无不克战无不胜全灭敌军胜利手到擒来的无敌日月神教么！！！！！！怎么水平一个一个的比我还菜呢？身为军人却大脑壳小细脖还全带着眼镜！我要去军事法庭投诉征兵水平！”</p>
<p>“队长息怒，”旁边的杨锐狗腿的凑了上来，“虽然我们的战斗力可能有一点点的不够合格，但是我们这次从教官那偷来了秘密武器，你看~”说罢，神秘兮兮的从背包里掏出一个黑色物体。</p>
<p>“咦？复活遥控器！” 九强凑了上来，一看是好东西，两眼放光的在杨锐肩上拍了一下。</p>
<p>“老大，据说只要我们队里还有一个人活着，就能用这个遥控器无限次复活队友。” 胡悦也凑过来，献宝似的说道。</p>
<p>“哇哈哈哈，这次我们就无敌了！”终于得到了终极武器的张队长双手叉腰，仰天大笑。</p>
<p>“队队队长~~不好了！！”那边还没笑完，这边四眼就上气不接下气的冲了进来，“队长！龙珠队杀回来鞭尸了！”</p>
<p>话音未落，只见蓝队的先锋史磊和文迪踢开房门冲了进来，紧接着龙珠队长唱鑫一袭蓝衣飘然而至，后边跟着小虫、庆法、王健、王彪、徐晨、魏广程等众人。</p>
<p>但见狙击手肖然抬手一梭子弹打在唯一还生还的张队长身上。只听“啊~”的一声惨叫后，绿队里最后一个幸存者也被记入了死亡名单。</p>
<p>“我死不瞑目哇~~~~”张队长的怒吼声，伴随着落日的余辉，缓缓沉入地平线下。</p>
]]></content:encoded>
			<wfw:commentRss>http://kfzhang.thoughtworkers.org/2011/09/2011-thoughtworks-cs/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Mock, Stub, Fake</title>
		<link>http://kfzhang.thoughtworkers.org/2011/09/mock-stub-fake/</link>
		<comments>http://kfzhang.thoughtworkers.org/2011/09/mock-stub-fake/#comments</comments>
		<pubDate>Sat, 10 Sep 2011 14:04:49 +0000</pubDate>
		<dc:creator>zhangkf</dc:creator>
				<category><![CDATA[Agile]]></category>
		<category><![CDATA[Tech]]></category>
		<category><![CDATA[mock]]></category>
		<category><![CDATA[stub]]></category>
		<category><![CDATA[test]]></category>
		<category><![CDATA[ThoughtBlogs]]></category>

		<guid isPermaLink="false">http://kfzhang.thoughtworkers.org/?p=1084</guid>
		<description><![CDATA[上次郑晔给大家做游戏，徐昊问到台上的咨询师，Mock、Stub和Fake的区别是什么？ 自己虽然心里有点印象，但还是下来搜了一下： Wikipedia的解释是这样： Some authors[1] draw a distinction between fake and mock objects. Fakes are the simpler of the two, simply implementing the same interface as the object that they represent and returning pre-arranged responses. Thus a fake object merely provides a set of method stubs. &#8230; <a href="http://kfzhang.thoughtworkers.org/2011/09/mock-stub-fake/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>上次郑晔给大家做游戏，徐昊问到台上的咨询师，Mock、Stub和Fake的区别是什么？</p>
<p>自己虽然心里有点印象，但还是下来搜了一下：</p>
<p><a href="http://en.wikipedia.org/wiki/Mock_object#Mocks.2C_fakes_and_stubs">Wikipedia</a>的解释是这样：</p>
<blockquote><p>Some authors<sup id="cite_ref-0"><a href="http://en.wikipedia.org/wiki/Mock_object#cite_note-0">[1]</a></sup> draw a distinction between <em>fake</em> and <em>mock</em> objects. Fakes are the simpler of the two, simply implementing the same interface as the object that they represent and returning pre-arranged responses. Thus a fake object merely provides a set of <a title="Method stub" href="http://en.wikipedia.org/wiki/Method_stub">method stubs</a>.</p>
<p>In the book &#8220;The Art of Unit Testing&#8221;<sup id="cite_ref-1"><a href="http://en.wikipedia.org/wiki/Mock_object#cite_note-1">[2]</a></sup> mocks are described as a fake object that helps decide if a test failed or passed, by verifying if an interaction on an object occurred or not. Everything else is defined as a stub. In that book, &#8220;Fakes&#8221; are anything that is not real. Based on their usage, they are either stubs or mocks.</p>
<p>Mock objects in this sense do a little more: their method implementations contain <a title="Assertion (computing)" href="http://en.wikipedia.org/wiki/Assertion_(computing)">assertions</a> of their own. This means that a true mock, in this sense, will examine the context of each call— perhaps checking the order in which its methods are called, perhaps performing tests on the data passed into the method calls as arguments.</p></blockquote>
<p>这里还有<a href="http://stackoverflow.com/questions/346372/whats-the-difference-between-faking-mocking-and-stubbing">StackOverFlow的回答</a>。</p>
<p>扩展阅读：</p>
<ul>
<li><a href="http://www.infoq.com/cn/articles/thoughtworks-practice-partvi">Mock不是测试的银弹</a>，胡凯，InfoQ</li>
<li><a href="http://news.csdn.net/n/20060726/93003.html">不要把Mock当作你的设计利器</a>，李晓，CSDN</li>
<li><a href="http://martinfowler.com/articles/mocksArentStubs.html">Mocks Aren&#8217;t Stubs</a>，Martin Fowler</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://kfzhang.thoughtworkers.org/2011/09/mock-stub-fake/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>SAI项目小结</title>
		<link>http://kfzhang.thoughtworkers.org/2011/09/sai/</link>
		<comments>http://kfzhang.thoughtworkers.org/2011/09/sai/#comments</comments>
		<pubDate>Sat, 10 Sep 2011 13:49:08 +0000</pubDate>
		<dc:creator>zhangkf</dc:creator>
				<category><![CDATA[Tech]]></category>
		<category><![CDATA[TW]]></category>
		<category><![CDATA[ThoughtBlogs]]></category>

		<guid isPermaLink="false">http://kfzhang.thoughtworkers.org/?p=1082</guid>
		<description><![CDATA[其实这个我在TW的第一个项目还没结束，现在就总结还为时尚早。但我担心我会遗忘，而且既然有心思写下来，为什么要等那么一个时机呢？ JS代码组织结构和单元测试。按照客户要求，我们使用SmartClient作为客户端RIA库，这个库的优点是丰富的UI控件，但逻辑和视图耦合很紧。当我们发现JS端代码日渐庞大臃肿时，耦合紧导致维护很难，而这时已经过了第一个Release。在第二个Release中，我们讨论过用MVP来解耦，引入Jasmine作单元测试，讨论尽可能将代码做M、V、C三个角度分离并有了尝试，但仍未引起足够多的重视。我们是侥幸的，因为这个项目并不复杂，不管从技术上还是业务上，所以这个方面的技术债感受不深。我们知道我们应该做的。 代码静态分析和质量控制。我们直到第二个Release的后期，才试图引入cobertura和sonar来分析我们的所有代码，结果可想而知，一些测试没有覆盖，代码的逻辑有问题，有些是多余的分支，有些是永远不会走到的逻辑。这样又方便又能让我们学习的工具，为什么没能早点采用呢？ 成熟框架。因为Team半数以上是新TWer，从一开始team并未引入Hibernate和Spring等重量级框架，但在Domain Model分析上下了功夫，这样一直平静发展到Release 1结束。Release 2开始，因为团队学习的需求和客户要求架构统一，我们同时引入Spring和Hibernate，用到的多是框架最核心和基础的技术，除了遇到个别问题比如双向关联、继承和Proxy Bean，一切都还正常，业务和技术的双重相对简单性决定也用不了多复杂的框架技术。只是在临近Release 2结束时，客户要求集成双方的系统时，我们发现引入Hibernate和Spring在这时是一种风险，或者说累赘，我们不得不合并或者修改一些配置，以期避免冲突，这个过程不那么平滑。 代码合并。最后关头时间紧，我们却发现我们要merge一个超过一万两千行代码的类，这个类基本是一个Release才merge一次。过程痛苦，IDE自作主张的分析合并让我们无法相信它，我们能做的只是纯文本的手工对比，这时Beyond Compare帮了大忙，但即使这样也消耗了我们近半个下午的时间，这还只是不到十个类文件。我在想，如果能前瞻一点再果断一点，我们定不会在这个一万两千多行的类里面再添加我们全部的实现的代码，而是挪到自己的实现类里。 管理客户期望。系统集成，是客户在Release 2还剩一个半迭代时，强烈提出的。这个问题似乎从项目开始时可以预期，甚至中途客户也是偶尔提及，但我们似乎没有足够重视。我更认为这是业务理解和管理客户期望的问题。我还没有更好的想法，期待跟团队一起回顾。]]></description>
			<content:encoded><![CDATA[<p>其实这个我在TW的第一个项目还没结束，现在就总结还为时尚早。但我担心我会遗忘，而且既然有心思写下来，为什么要等那么一个时机呢？</p>
<ol>
<li><strong>JS代码组织结构和单元测试。</strong>按照客户要求，我们使用SmartClient作为客户端RIA库，这个库的优点是丰富的UI控件，但逻辑和视图耦合很紧。当我们发现JS端代码日渐庞大臃肿时，耦合紧导致维护很难，而这时已经过了第一个Release。在第二个Release中，我们讨论过用MVP来解耦，引入Jasmine作单元测试，讨论尽可能将代码做M、V、C三个角度分离并有了尝试，但仍未引起足够多的重视。我们是侥幸的，因为这个项目并不复杂，不管从技术上还是业务上，所以这个方面的技术债感受不深。我们知道我们应该做的。</li>
<li><strong>代码静态分析和质量控制。</strong>我们直到第二个Release的后期，才试图引入cobertura和sonar来分析我们的所有代码，结果可想而知，一些测试没有覆盖，代码的逻辑有问题，有些是多余的分支，有些是永远不会走到的逻辑。这样又方便又能让我们学习的工具，为什么没能早点采用呢？</li>
<li><strong>成熟框架。</strong>因为Team半数以上是新TWer，从一开始team并未引入Hibernate和Spring等重量级框架，但在Domain Model分析上下了功夫，这样一直平静发展到Release 1结束。Release 2开始，因为团队学习的需求和客户要求架构统一，我们同时引入Spring和Hibernate，用到的多是框架最核心和基础的技术，除了遇到个别问题比如双向关联、继承和Proxy Bean，一切都还正常，业务和技术的双重相对简单性决定也用不了多复杂的框架技术。只是在临近Release 2结束时，客户要求集成双方的系统时，我们发现引入Hibernate和Spring在这时是一种风险，或者说累赘，我们不得不合并或者修改一些配置，以期避免冲突，这个过程不那么平滑。</li>
<li><strong>代码合并。</strong>最后关头时间紧，我们却发现我们要merge一个超过一万两千行代码的类，这个类基本是一个Release才merge一次。过程痛苦，IDE自作主张的分析合并让我们无法相信它，我们能做的只是纯文本的手工对比，这时Beyond Compare帮了大忙，但即使这样也消耗了我们近半个下午的时间，这还只是不到十个类文件。我在想，如果能前瞻一点再果断一点，我们定不会在这个一万两千多行的类里面再添加我们全部的实现的代码，而是挪到自己的实现类里。</li>
<li><strong>管理客户期望。</strong>系统集成，是客户在Release 2还剩一个半迭代时，强烈提出的。这个问题似乎从项目开始时可以预期，甚至中途客户也是偶尔提及，但我们似乎没有足够重视。我更认为这是业务理解和管理客户期望的问题。我还没有更好的想法，期待跟团队一起回顾。</li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://kfzhang.thoughtworkers.org/2011/09/sai/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>ThoughtWorks有什么不同？</title>
		<link>http://kfzhang.thoughtworkers.org/2011/06/difference-of-thoughtworks/</link>
		<comments>http://kfzhang.thoughtworkers.org/2011/06/difference-of-thoughtworks/#comments</comments>
		<pubDate>Sun, 05 Jun 2011 14:12:39 +0000</pubDate>
		<dc:creator>zhangkf</dc:creator>
				<category><![CDATA[Agile]]></category>
		<category><![CDATA[TW]]></category>
		<category><![CDATA[ThoughtBlogs]]></category>
		<category><![CDATA[ThoughtWorks]]></category>

		<guid isPermaLink="false">http://kfzhang.thoughtworkers.org/?p=1075</guid>
		<description><![CDATA[仅仅入职两个月时间，就试图看清楚说明白新入职公司的不同，注定是浅陋的。但是这并不妨碍我说出目前我心目中的ThoughtWorks。 昨天和前同事聊天，被问起了ThoughtWorks跟之前公司有哪些不同的地方。我想了想说，你所知道的敏捷的全部，在ThoughtWorks都能找到；没有拖沓碎叨更像是status update的standup； 我看到了自组织的团队，每个人都在团队中承担自己的职责，自信且淡定；扁平的层级文化，没有看不到头的title层次，可以把精力聚焦在项目上和自己感兴趣的事情上；可以向整个公司发邮件，表达自己的担心和困惑，评论社会现实，公司的老大也会加入进来讨论；可以让自己承担起公司主人的角色，为公司的发展做出自己的努力和影响；还有ThoughtWorks对于利用软件和技术改善人类生活的社会责任的担当；ThoughtWorks一直致力于用最先进的技术和方法来帮助客户，这会让做技术的人很high。这些在别的公司都是很难见到的。 我之前的工作经历很有代表性，先是一家国内大型软件企业，然后是一家大型外资企业，这样的经历让我有在不同企业背景和文化下的体验，也让我现在有了相对的参照系，来比较现在所在的环境——ThoughtWorks有什么不同。 如果答案仅仅止步于上面那些不同，我想这是肤浅的。是什么造就了这些以及更多的不同？有一些线索可以帮助理清楚： 在TWI上徐昊提到了Martin Fowler写的一篇博客，讲的就是ThoughtWorks是Roy的社会化实践。Roy希望借这场实践来证明那些认定下面结论的观点是错误的： 你的公司不可能只由能力强的人们组成，必须存在能力差别 能力强的人往往无法合作 大型公司必须有强有力的管理结构，以避免分崩离析 不可能为考虑长远而做事 成为国际化公司是为了利用欠发达国家的人才 不能暴露自己的弱点，尤其对于公司外 不要赋予员工权利，否则会被滥用而伤害公司 文化是次要的，你需要一个优越的商业模型 “社会化实践”，是不是挺震撼的？事实是，ThoughtWorks的确在全球网罗到了一批才能很高的人，在共同致力发展这个公司，守护这样的文化。我们成为了Roy的实验品，但软件这个特殊的行业，工程师这个简单又复杂的职业，这样一群人，的确在印证着Roy的实验趋向成功。 另外还有一篇文章《为什么我要把公司做成扁平型》，作者是37signals的创始人之一，他讲述了公司确实发生过的事情，当试图为一些资深员工创造一个管理职位和职务来发展时，遇到的问题和冲突。经验证明，让团队自己管理自己是效率更高的方式，因为的确有这样的一些人，不介意有那样垂直发展的梯子供自己攀爬。 最后是今天看到的米高写的一篇《全面成功》，这跟我在团队同事那里听到的一样。怎样定义项目的成功，只顺利结项拿到款是肤浅和单薄的。客户满意，项目质量高，团队得到发展，不一而足。ThoughtWorks的文化追求，也导致了全面成功是每个项目组的诉求。在这样的环境下，团队才会是自组织的，个人最后也才是充实和成功的。]]></description>
			<content:encoded><![CDATA[<p>仅仅入职两个月时间，就试图看清楚说明白新入职公司的不同，注定是浅陋的。但是这并不妨碍我说出目前我心目中的ThoughtWorks。</p>
<p>昨天和前同事聊天，被问起了ThoughtWorks跟之前公司有哪些不同的地方。我想了想说，你所知道的敏捷的全部，在ThoughtWorks都能找到；没有拖沓碎叨更像是status update的standup； 我看到了自组织的团队，每个人都在团队中承担自己的职责，自信且淡定；扁平的层级文化，没有看不到头的title层次，可以把精力聚焦在项目上和自己感兴趣的事情上；可以向整个公司发邮件，表达自己的担心和困惑，评论社会现实，公司的老大也会加入进来讨论；可以让自己承担起公司主人的角色，为公司的发展做出自己的努力和影响；还有ThoughtWorks对于利用软件和技术改善人类生活的社会责任的担当；ThoughtWorks一直致力于用最先进的技术和方法来帮助客户，这会让做技术的人很high。这些在别的公司都是很难见到的。</p>
<p>我之前的工作经历很有代表性，先是一家国内大型软件企业，然后是一家大型外资企业，这样的经历让我有在不同企业背景和文化下的体验，也让我现在有了相对的参照系，来比较现在所在的环境——ThoughtWorks有什么不同。</p>
<p>如果答案仅仅止步于上面那些不同，我想这是肤浅的。是什么造就了这些以及更多的不同？有一些线索可以帮助理清楚：</p>
<p>在TWI上徐昊提到了Martin Fowler写的<a href="http://martinfowler.com/bliki/RoysSocialExperiment.html" target="_blank">一篇博客</a>，讲的就是ThoughtWorks是Roy的社会化实践。Roy希望借这场实践来证明那些认定下面结论的观点是错误的：</p>
<ul>
<li>你的公司不可能只由能力强的人们组成，必须存在能力差别</li>
<li>能力强的人往往无法合作</li>
<li>大型公司必须有强有力的管理结构，以避免分崩离析</li>
<li>不可能为考虑长远而做事</li>
<li>成为国际化公司是为了利用欠发达国家的人才</li>
<li>不能暴露自己的弱点，尤其对于公司外</li>
<li>不要赋予员工权利，否则会被滥用而伤害公司</li>
<li>文化是次要的，你需要一个优越的商业模型</li>
</ul>
<p>“社会化实践”，是不是挺震撼的？事实是，ThoughtWorks的确在全球网罗到了一批才能很高的人，在共同致力发展这个公司，守护这样的文化。我们成为了Roy的实验品，但软件这个特殊的行业，工程师这个简单又复杂的职业，这样一群人，的确在印证着Roy的实验趋向成功。</p>
<p>另外还有一篇文章《<a href="http://www.aqee.net/2011/04/12/jason-fried-why-i-run-a-flat-company/" target="_blank">为什么我要把公司做成扁平型</a>》，作者是37signals的创始人之一，他讲述了公司确实发生过的事情，当试图为一些资深员工创造一个管理职位和职务来发展时，遇到的问题和冲突。经验证明，让团队自己管理自己是效率更高的方式，因为的确有这样的一些人，不介意有那样垂直发展的梯子供自己攀爬。</p>
<p>最后是今天看到的米高写的一篇《<a href="http://michael.nona.name/archives/370" target="_blank">全面成功</a>》，这跟我在团队同事那里听到的一样。怎样定义项目的成功，只顺利结项拿到款是肤浅和单薄的。客户满意，项目质量高，团队得到发展，不一而足。ThoughtWorks的文化追求，也导致了全面成功是每个项目组的诉求。在这样的环境下，团队才会是自组织的，个人最后也才是充实和成功的。</p>
]]></content:encoded>
			<wfw:commentRss>http://kfzhang.thoughtworkers.org/2011/06/difference-of-thoughtworks/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Experience Design初体验</title>
		<link>http://kfzhang.thoughtworkers.org/2011/06/new-to-experience-design/</link>
		<comments>http://kfzhang.thoughtworkers.org/2011/06/new-to-experience-design/#comments</comments>
		<pubDate>Wed, 01 Jun 2011 08:49:53 +0000</pubDate>
		<dc:creator>zhangkf</dc:creator>
				<category><![CDATA[TW]]></category>
		<category><![CDATA[Experience Design]]></category>
		<category><![CDATA[Offering]]></category>

		<guid isPermaLink="false">http://kfzhang.thoughtworkers.org/?p=1064</guid>
		<description><![CDATA[打酱油的结果，就是有机会两次经历ThoughtWorks的Experience Design。一次是针对Climate Action的Social Impact Project，一次是Beijing Design Night。 在过程中，我领略到了跟之前的经验和了解完全不同的设计体验：如何拨开层层需求迷雾，抛弃虚妄的需求，找到潜在系统用户的真正痛点，实现和改进系统的功能，提升用户的内在体验。 我们会首先设计出目标系统的使用者——Persona，一个虚拟的用户，但有明确的生活和职业背景。 然后是依据这个Persona设计他/她的Empathy Map和User Journey。会根据模拟和假设Persona的所听所见所闻所想来发现Persona对系统的（甚至是潜在的）期望，模拟一个尽量真实的故事历程来找出Persona的痛点，从而找到可以实现和改进的地方。这个设计过程是整个团队和客户共同参与，进行头脑风暴的过程，合作的过程可以避免对Persona的误解以及以偏概全。 最后会用笔和纸快速地在纸上画出Sketching，也就是UI的原型，充分体现出设计过程产生的系统改进并解决痛点。 Experience Design会是ThoughtWorks未来很重要的一个Offering。 扩展阅读在这里。]]></description>
			<content:encoded><![CDATA[<p>打酱油的结果，就是有机会两次经历ThoughtWorks的Experience Design。一次是针对Climate Action的Social Impact Project，一次是Beijing Design Night。</p>
<p>在过程中，我领略到了跟之前的经验和了解完全不同的设计体验：如何拨开层层需求迷雾，抛弃虚妄的需求，找到潜在系统用户的真正痛点，实现和改进系统的功能，提升用户的内在体验。</p>
<p>我们会首先设计出目标系统的使用者——Persona，一个虚拟的用户，但有明确的生活和职业背景。</p>
<p>然后是依据这个Persona设计他/她的Empathy Map和User Journey。会根据模拟和假设Persona的所听所见所闻所想来发现Persona对系统的（甚至是潜在的）期望，模拟一个尽量真实的故事历程来找出Persona的痛点，从而找到可以实现和改进的地方。这个设计过程是整个团队和客户共同参与，进行头脑风暴的过程，合作的过程可以避免对Persona的误解以及以偏概全。</p>
<p>最后会用笔和纸快速地在纸上画出Sketching，也就是UI的原型，充分体现出设计过程产生的系统改进并解决痛点。</p>
<p><a href="http://kfzhang.thoughtworkers.org/wp-content/uploads/kfzhang.thoughtworkers.org/2011/06/2011-06-02_1359.png"><img class="alignnone size-full wp-image-1072" title="2011-06-02_1359" src="http://kfzhang.thoughtworkers.org/wp-content/uploads/kfzhang.thoughtworkers.org/2011/06/2011-06-02_1359.png" alt="" width="943" height="387" /></a></p>
<p>Experience Design会是ThoughtWorks未来很重要的一个Offering。</p>
<p>扩展阅读在<a href="http://www.tuzei8.com/tag/%E4%BD%93%E9%AA%8C%E8%AE%BE%E8%AE%A1/" target="_blank">这里</a>。</p>
]]></content:encoded>
			<wfw:commentRss>http://kfzhang.thoughtworkers.org/2011/06/new-to-experience-design/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>ThoughtWorks需要怎样的人？</title>
		<link>http://kfzhang.thoughtworkers.org/2011/05/those-thoughtworks-wants/</link>
		<comments>http://kfzhang.thoughtworkers.org/2011/05/those-thoughtworks-wants/#comments</comments>
		<pubDate>Mon, 30 May 2011 14:18:11 +0000</pubDate>
		<dc:creator>zhangkf</dc:creator>
				<category><![CDATA[Career]]></category>
		<category><![CDATA[TW]]></category>
		<category><![CDATA[ThoughtWorks]]></category>

		<guid isPermaLink="false">http://kfzhang.thoughtworkers.org/?p=1059</guid>
		<description><![CDATA[想知道如何才能做好软件的人 想学习最新前沿技术并应用在项目中的人 想在项目中自己做主承担责任的人 想跟大牛成为同事一起工作的人 厌恶大公司繁文缛节的人 厌恶低效无谓加班的人 厌恶没有进步空间的人 厌恶盛气凌人的老板的人 想用上最新版MacBook Pro甚至Air的人 想每天吃到新鲜水果喝可乐的人 想每天可以打PS3和街机的人 想每天都有session听的人 不想把薪水放在第一位的人 不一心追求升职的人 不沽名钓誉的人 不畏惧变化的人]]></description>
			<content:encoded><![CDATA[<p>想知道如何才能做好软件的人<br />
想学习最新前沿技术并应用在项目中的人<br />
想在项目中自己做主承担责任的人<br />
想跟大牛成为同事一起工作的人</p>
<p>厌恶大公司繁文缛节的人<br />
厌恶低效无谓加班的人<br />
厌恶没有进步空间的人<br />
厌恶盛气凌人的老板的人</p>
<p>想用上最新版MacBook Pro甚至Air的人<br />
想每天吃到新鲜水果喝可乐的人<br />
想每天可以打PS3和街机的人<br />
想每天都有session听的人</p>
<p>不想把薪水放在第一位的人<br />
不一心追求升职的人<br />
不沽名钓誉的人<br />
不畏惧变化的人</p>
]]></content:encoded>
			<wfw:commentRss>http://kfzhang.thoughtworkers.org/2011/05/those-thoughtworks-wants/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>DevOps之Puppet</title>
		<link>http://kfzhang.thoughtworkers.org/2011/05/devops-puppet/</link>
		<comments>http://kfzhang.thoughtworkers.org/2011/05/devops-puppet/#comments</comments>
		<pubDate>Sat, 28 May 2011 04:56:35 +0000</pubDate>
		<dc:creator>zhangkf</dc:creator>
				<category><![CDATA[Agile]]></category>
		<category><![CDATA[Tech]]></category>
		<category><![CDATA[TW]]></category>
		<category><![CDATA[DevOps]]></category>
		<category><![CDATA[puppet]]></category>

		<guid isPermaLink="false">http://kfzhang.thoughtworkers.org/?p=1057</guid>
		<description><![CDATA[Puppet在一款自动化系统配置管理的工具，它可以让你在很短的时间内对大量硬件和系统基本类似的系统，进行统一的系统配置管理。 说的简单点，就像开网吧，你需要对网吧的每一台机器安装操作系统，配置完全一样的软件，比如QQ和360，供网友上网，在系统和软件有损坏时，很简单的一个恢复操作就可以让机器回到刚刚安装好操作系统和软件的状态。 Puppet就是可以干这个事儿的，不同在于，Puppet是给网络管理员用的，而针对的系统多是*nix系统，因为Puppet目前对Windows支持的很少，但这不妨碍Puppet成为DevOps实现过程中的利器，另外一个类似的工具是Chef。 Puppet本身基于Ruby实现，但即使没有Ruby的经验也没甚大碍。Puppet自己提出了所谓Puppet Language，是一种DSL（Domain Specific Language）语言，用直白而描述性的语言，定义系统应该具有的状态，比如一个简单的例子tmpfile.pp： file { 'testfile': path =&#62; '/tmp/testfile',     ensure =&#62; present,     mode =&#62; 0640,     content =&#62; "I'm a test file.", } 在安装了Puppet了机器上运行： puppet apply tmpfile.pp 结果就会在/tmp下新增加一个testfile，内容是This is a test &#8230; <a href="http://kfzhang.thoughtworkers.org/2011/05/devops-puppet/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><a href="http://projects.puppetlabs.com/projects/puppet" target="_blank">Puppet</a>在一款自动化系统配置管理的工具，它可以让你在很短的时间内对大量硬件和系统基本类似的系统，进行统一的系统配置管理。</p>
<p>说的简单点，就像开网吧，你需要对网吧的每一台机器安装操作系统，配置完全一样的软件，比如QQ和360，供网友上网，在系统和软件有损坏时，很简单的一个恢复操作就可以让机器回到刚刚安装好操作系统和软件的状态。</p>
<p>Puppet就是可以干这个事儿的，不同在于，Puppet是给网络管理员用的，而针对的系统多是*nix系统，因为Puppet目前对Windows支持的很少，但这不妨碍Puppet成为DevOps实现过程中的利器，另外一个类似的工具是<a href="http://en.wikipedia.org/wiki/Chef_(software)" target="_blank">Chef</a>。</p>
<p>Puppet本身基于Ruby实现，但即使没有Ruby的经验也没甚大碍。Puppet自己提出了所谓Puppet Language，是一种DSL（Domain Specific Language）语言，用直白而描述性的语言，定义系统应该具有的状态，比如一个简单的例子tmpfile.pp：</p>
<pre>file { 'testfile':
    path =&gt; '/tmp/testfile',
    ensure  =&gt; present,
    mode    =&gt; 0640,
    content =&gt; "I'm a test file.",
}</pre>
<p>在安装了Puppet了机器上运行：</p>
<pre>puppet apply tmpfile.pp</pre>
<p>结果就会在/tmp下新增加一个testfile，内容是This is a test file。<br />
这个例子太简单。除了file这种类型外，Puppet提供了<a href="http://projects.puppetlabs.com/projects/puppet/wiki/Core_Types_Cheat_Sheet/" target="_blank">大量的资源类型</a>，供对系统的状态进行描述，比如打开（如果不存在会自动下载）某项服务，自动增加一个用户。当管理的机器成百上千，这样的自动化服务达到的效果就很可观了。</p>
<p>puppet apply是Puppet在单机上运行和测试的工具，真实的使用情景会是，一台机器（master）专门保留所有机器配置管理的状态信息，而每台机器（agent）会在指定的时间向master发起查询，从而更新自己的系统状态，以期与指定状态保持一致。</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://kfzhang.thoughtworkers.org/2011/05/devops-puppet/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

