<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom"><title type="text">博客园_TAOWEN的闲言碎语</title><subtitle type="text">翻来覆去就那么一点事</subtitle><id>http://feed.cnblogs.com/blog/u/1867/rss</id><updated>2010-03-10T02:22:11Z</updated><author><name>taowen</name><uri>http://www.cnblogs.com/taowen/</uri></author><generator>CNBlogs BlogServer</generator><link rel="alternate" type="text/html" href="http://www.cnblogs.com/taowen/"/><link rel="self" type="application/atom+xml" href="http://feed.cnblogs.com/blog/u/1867/rss"/><entry><id>http://www.cnblogs.com/taowen/archive/2010/03/10/1682104.html</id><title type="text">为什么我的敏捷项目有如此多的问题？</title><summary type="text">OK，敏捷哈。不争论什么是敏捷。我们来看一些现象，然后你来告诉我，你有没有遇到过这些问题。没人提真正的Feedback每个迭代结束之后，我都会做Showcase。但是从Showcase上收集到最多的，就是UI的问题，字体太小之类的。每个Release发布之后，项目都会部署一个试用版本。但就是不见真正的用户来&amp;ldquo;试用&amp;rdquo;，就更别提Feedback了。敏捷不是强调Feedback吗...</summary><published>2010-03-10T02:22:00Z</published><updated>2010-03-10T02:22:00Z</updated><author><name>taowen</name><uri>http://www.cnblogs.com/taowen/</uri></author><link rel="alternate" href="http://www.cnblogs.com/taowen/archive/2010/03/10/1682104.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/taowen/archive/2010/03/10/1682104.html"/><content type="html">&lt;p&gt;OK，敏捷哈。不争论什么是敏捷。我们来看一些现象，然后你来告诉我，你有没有遇到过这些问题。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;没人提真正的Feedback&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;每个迭代结束之后，我都会做Showcase。但是从Showcase上收集到最多的，就是UI的问题，字体太小之类的。每个Release发布之后，项目都会部署一个试用版本。但就是不见真正的用户来&amp;ldquo;试用&amp;rdquo;，就更别提Feedback了。敏捷不是强调Feedback吗？客户（Customer）时间不够，同时他们也不是最终用户，提不出足够有深度的Feedback。而最终用户呢，压根就没兴趣。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;架构咋弄啊&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;每个迭代都要被催着出东西，哪里有时间弄架构哦。一开始就一个劲的加功能。前几个迭代大家都很Happy，功能出来的特别快。后来就越来越慢了，团队情绪也很差。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;客户说没有不是Must Have的&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;事情实在太多了，做不完呀。那让客户来排优先级吧，把哪些是Must Have的找出来。但是客户说了，这些都很重要，没有这个Feature，或者那个Feature系统就压根没有用处。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;路漫漫其修远兮，我到底在往哪走&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;团队的成员越来越多地在抱怨，天天做Story。但是这些Story都是干什么用的呢？这做一点，那做一点，根本就整合不到一个Vision里去。客户说，我给了你Vision啊，你看这个Feature那个Feature，这些要做的东西就是我们的Vision啊（心里还在犯嘀咕呢，你们干活的吵什么吵）。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;这些问题都有一个相同的最终根源。我们先来看最明显的Feedback问题。为什么客户和最终用户都不提Feedback？因为不关他们的事！做Showcase不过就是在眼前晃两下，有深度的Feedback不是那么容易及时地想到的。而Release又有多少是真正部署到产品环境的？最终用户一方面还用这旧的系统，天天忙着四脚朝天的，哪里有时间来试用我们的新系统呢？无论你是设置了一个测试机在他的桌子旁边，还是一天三次的发Email提醒。只要你的系统不是完成他工作必须的一部分，他就不会理你。&lt;/p&gt;&#xD;
&lt;p&gt;为什么Release出来的系统不能部署到Production环境呢？这不是很奇怪吗。是的，确实很奇怪。但是，假如你是客户，你被你的组织委任了一个替换现有系统的差事。现有的系统有100个功能，完全开发完这些功能可能需要两年。但是，每三个月都有一次绩效考核。你会不会希望每三个月，就让领导看到你都弄出了点了啥？于是你找到了一个号称可以做敏捷开发的外包公司，要求他们每三个月给你出一个版本。但是这个版本能真正上Production么？不能！现有系统有100个功能，那么多用户在用呢。你三个月弄出来的系统怎么替换这么大一个系统啊？一个&amp;ldquo;成熟的企业&amp;rdquo;，对于一个这样系统的GO OR NOT GO MEETING都要开三个月呢。&lt;/p&gt;&#xD;
&lt;p&gt;也许你要说，我们是真正的Green Field开发，彻底重头写的。那么有你开发的系统之前，这家企业是怎么运作的？至少有一个Paper Process吧。没有电子系统，人们就用纸笔，各种单据来工作呗。IT系统不过是Paper Process的自动化而已。再说了，这年头还真没几个请得起我们，而且现在还没有一个IT系统的，需要从Paper Process开始的？&lt;/p&gt;&#xD;
&lt;p&gt;除非你做的是非常有创新性的企业开发。通过创新性的IT系统，开发新的业务。比如通过新的交易应用来辅助新的Margin Loan产品的市场投放。大部分时间来说，我们都是被引入进来&amp;ldquo;替换&amp;rdquo;现有的Paper Process，或者现有的遗留应用的。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;假设我们要替换的就是一个有100个功能的遗留应用，我们是怎么来&amp;ldquo;玩&amp;rdquo;敏捷的呢？基本上来说，我们假设了一个温室的环境。在这个环境里，你可以假设你做的是Green Field的开发。把100个功能，分成多个Release，每个Release又分成多个Iteration。在每个Release之后都会发布一个Pilot版本给测试用户试用。这样就可以迭代式地添加Feature，直到最后能够替换原有的系统。从我的经验看来，正是这种做法，部分导致了以上问题（甚至有些情况下是根源）。前面已经提到了，这样会导致缺少来自最终用户的，真正的Feedback。其次，由于少了一个Feature都无法替换旧的系统，客户很难做出优先级的正确选择。以替换旧的系统为目的，所有的Feature都是Must Have。同时这样会导致每个Release缺乏明确的，唯一的Goal。经常是这个Feature做一些，那个Feature做一些，Team会觉得没有明确的目标。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;如果我们不以替换旧的系统为目标？那么应该以什么为目标？这个时候你可以去看看Eric Evan的&lt;a href="http://www.infoq.com/presentations/strategic-design-evans"&gt;Strategic Design&lt;/a&gt;。他说，你应该想想What drives you to spend million dollars on this project in the first place（你为什么在最开始要在这个项目上决定花上一百万美元）。这个背后一定是原因的。基于对这个原因的理解，我们可以选定一定的Feature来实现。然后就开始实现，然后把实现部署了让所有的用户去用。用这种策略，而不是前面那种策略，这样就逼着我们去做很多事情。而我相信这些事情，很有可能就有助于解决前面四个问题。特别是，其中的架构问题。为什么呢？架构是什么？架构就是对问题的一种分解方式。怎么样才能迫使我们去思考架构问题呢？在现有的系统上打个洞，然后挖掉一块，围一道墙，里面再把新的Feature做出来。没有对系统整体的了解，没有对模块的分解，没有对模块之间耦合依赖关系的分析，是不可能做到这些的。这样就迫使我们做出一个低耦合高内聚的架构！&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;把这种策略做到极致就是之前我说过的&lt;a href="http://www.cnblogs.com/taowen/archive/2010/03/08/1680521.html"&gt;持续部署才是王道&lt;/a&gt;。不但每个Release都和旧的系统集成起来，然后真正的部署。甚至，我们可以做到每个迭代都部署。在Fred George描述的团队里，甚至都没有迭代。一个Feature开发出来就立马被部署了。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/taowen/aggbug/1682104.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/taowen/archive/2010/03/10/1682104.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/taowen/archive/2010/03/08/1681166.html</id><title type="text">提高程序员的准入门槛？</title><summary type="text">效仿敏捷宣言，有人也搞了一个软件工艺（Craftsmanship）宣言。在标题的下面是一行小字，提高准入门槛（Raising the bar）。UncleBob就这个Topic在世界各地发表演讲。他曾经把程序员与医生做比较：既然程序员与医生一样都是提供职业服务（Professional Service），那么他们就应该遵守类似的行为准则。医生在做手术之前需要洗手洗三遍以防止病人被细菌感染，而且需要...</summary><published>2010-03-08T15:45:00Z</published><updated>2010-03-08T15:45:00Z</updated><author><name>taowen</name><uri>http://www.cnblogs.com/taowen/</uri></author><link rel="alternate" href="http://www.cnblogs.com/taowen/archive/2010/03/08/1681166.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/taowen/archive/2010/03/08/1681166.html"/><content type="html">&lt;p&gt;效仿敏捷宣言，有人也搞了一个&lt;a href="http://manifesto.softwarecraftsmanship.org/"&gt;软件工艺（Craftsmanship）宣言&lt;/a&gt;。在标题的下面是一行小字，提高准入门槛（Raising the bar）。&lt;/p&gt;&#xD;
&lt;p&gt;UncleBob就这个Topic在世界各地发表演讲。他曾经把程序员与医生做比较：既然程序员与医生一样都是提供职业服务（Professional Service），那么他们就应该遵守类似的行为准则。医生在做手术之前需要洗手洗三遍以防止病人被细菌感染，而且需要用特殊的方式内搓三下外搓三下。假如病人说，我不希望你洗手。医生会拒绝这样的要求，因为这是他们的职业准则。程序员给代码做整理，不屈服于客户（在医生例子就是病人）的不合理的时间要求，因为程序员相比客户来说，程序员是职业的（Professional），应该知道什么样才是正确的事情，什么样才是真正为客户好（在医生的例子里就是怎样才能保护病人）。相反，如果我们屈服于时间压力了，没有对代码做整理，没有坚持更广泛的那些&amp;ldquo;正确的事情&amp;rdquo;，那么我们就不是职业的（Professional）。&lt;/p&gt;&#xD;
&lt;p&gt;他在世界各地做演讲之前都会问一个问题，多少人被Bad Code困扰过。结果自然是所有人。然后第二个问题就是，这些Bad Code都是谁写的。他的结论是，我们这个行业充斥了大量的Bad Code，而根源就是有太多不合格的人在从事这个行当。所以，这才有了那标题下的一行小字：提高准入门槛。但是，这有用吗？&lt;/p&gt;&#xD;
&lt;p&gt;我们来看看参加软件工艺北美大会（SCNA）的Speaker名单。假设这些人都是合格的Professional。他们都是在什么样的公司呢？&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;1、Small Group 咨询公司或者独立咨询&lt;br /&gt;Robert C. Martin，Michael Feathers ～ Object Mentor&lt;br /&gt;Ken Auer ～ RoleModel Software&lt;br /&gt;Ward Cunningham ～ 一个人干的产品 AboutUs.Org，曾经的&lt;a href="http://c2.com/" &gt;c2.com&lt;/a&gt;&lt;br /&gt;Jim Weirich ~ EdgeCase&lt;br /&gt;Christopher Avery ～ 貌似独立咨询&lt;br /&gt;Cory Foy ~ 独立咨询&lt;br /&gt;Kevin Taylor，Dave Hoover ～ obtiva&lt;br /&gt;Micah Martin，Paul Pagel ~ 8th Light&lt;br /&gt;Carl Erickson ～ AtomicObject&lt;br /&gt;2、高Value的产品&lt;br /&gt;Fred George ～ TrafficBroker&lt;br /&gt;Dave Astels ～ Engine Yard&amp;nbsp;&lt;br /&gt;Bobby Norton ~ DRW Trading&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;那么所谓的不合格的Professional都在什么公司呢？这个就不用问了。显然不是那些精英咨询公司和高Value的产品公司。他们广泛分布于印度中国的外包企业内，而且这个行当每年都在以更快的速度制造这些不合格的Professional。那如何提高准入门槛呢？&lt;/p&gt;&#xD;
&lt;p&gt;但是有什么门槛好提高的？因为门槛已经在那了。如果你不是合格的Professional，像TrafficBroker，DRW Trading的公司会招聘你吗？如果你不是合格的Professional，UncleBob他自己的咨询公司ObjectMentor会招聘你吗？这是一个金字塔。一个人从塔基进入，先从不规范的民企，最次的外包企业开始，然后到好一些的外包企业，然后开始去做咨询，然后要么独立咨询要么就是被Google的Wave Team挖去，要么就是一帮人聚集到DRW Trading这样的小公司，给资本家写期权模型。如果我们只看塔尖，这个门槛已经在那了。Dan North, Bobby Norton这些人自己的道路，就已经说明了走到塔尖是多么的不容易了。那为什么还要提高准入门槛呢？难道是让Tata这样的外包公司不再招聘不合格的毕业生来堆砌代码？且不说其他方面的可行性。哪里来的合格的毕业生？Professional之所以成为Professional，肯定不是一毕业就是Professional的。那么提高门槛的目的就是不再让毕业生加入到写代码的行列来吗？&lt;/p&gt;&#xD;
&lt;p&gt;如果没有这巨大的塔基，如果没有大量的公司招聘大量的Unprofessional。你们塔尖上的人到哪里去招聘人？我同意Software Craftsmanship强调的价值，但是提高准入门槛却是一个很无聊的事情。关键不在于让谁进来，不让谁进来。而是我们这个行业，如何才让像律师和医生一样提供给毕业生在职的锻炼，而不是两三天买一个证书的培训。按照经济规律，牛人扎堆在了牛人一起，而Unprofessional扎堆在塔基在广大的外包软件公司里。那么我们除了牛人从塔尖向下望，摇头还是摇头。那么我们除了塔基的人向上望，摇头还是摇头。还能有什么其他的结果？&lt;/p&gt;&#xD;
&lt;p&gt;到底是环境造就了这样一批人，还是 这样一批人造就了现在这样一个环境呢？到底是什么让这些product owner相信软件可以由non-professional写出来，继而创造了一个可以创造更多non-professional的环境。是我们，还是他们，还是the damn god？&lt;/p&gt;&lt;img src="http://www.cnblogs.com/taowen/aggbug/1681166.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/taowen/archive/2010/03/08/1681166.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/taowen/archive/2010/03/08/1680521.html</id><title type="text">持续部署才是王道</title><summary type="text">原话是&amp;ldquo;Continuous Deployment is the holy grail&amp;rdquo;。在听到的这句话的时候，我的灯泡突然被点亮了。说得实在是太对了。有一句老话是&amp;ldquo;纲举目张&amp;rdquo;。意思是提起渔网上总绳，一个个网眼就会被张开。我们的很多实践，就像这渔网上的网眼，琳琅满目。我们缺乏的就是这样一个总绳来把所有的实践联系起来。No，No，No，你错了。你可能要...</summary><published>2010-03-08T00:48:00Z</published><updated>2010-03-08T00:48:00Z</updated><author><name>taowen</name><uri>http://www.cnblogs.com/taowen/</uri></author><link rel="alternate" href="http://www.cnblogs.com/taowen/archive/2010/03/08/1680521.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/taowen/archive/2010/03/08/1680521.html"/><content type="html">&lt;p&gt;原话是&amp;ldquo;&lt;a href="http://scna.softwarecraftsmanship.com/schedule#fred_george"&gt;Continuous Deployment is the holy grail&lt;/a&gt;&amp;rdquo;。在听到的这句话的时候，我的灯泡突然被点亮了。说得实在是太对了。有一句老话是&amp;ldquo;纲举目张&amp;rdquo;。意思是提起渔网上总绳，一个个网眼就会被张开。我们的很多实践，就像这渔网上的网眼，琳琅满目。我们缺乏的就是这样一个总绳来把所有的实践联系起来。No，No，No，你错了。你可能要说，我们有这样的一个总绳，它的名字叫Agile。那是昨天的名字了，今天的名字叫Lean，天晓得明天的名字会是啥。这个总绳，还叫Pragmatic，还叫Value Driven。这些确实是可以起到概括一切的作用，但是你怎么知道你做的是不是&lt;br /&gt;Agile呢？是不是Lean呢？是不是Pragmatic呢？是不是Value Driven呢？这些都缺乏一个实际的可测性。Continuous Deployment，强大之处就在于，他很直白，甚至是缺乏内涵的。所以很容易知道，你到底做到了没有。这就是我们所需要的总绳，能够时刻时刻地把我们所有的实践团结在一起，纲举目张。&lt;/p&gt;&#xD;
&lt;p&gt;那么持续部署为什么就是王道了？这里有两个可以产生歧义的地方，持续部署与王道。什么是持续部署？而王道又是什么？Holy grail，王道其实就是说this thing is good。我们经常在口头上对某件事物表示赞叹，常用的词汇就是&amp;ldquo;好&amp;rdquo;。王道就是特别好。好是主观的，我认为软件开发这个领域中，好就意味能够从投入产生出持续的真金实银的回报。好也不在于界面如何友好，不在于code有多优美，所有这些指标都是间接的。唯一的指标就是到底产生了多少金钱上的回报。如果我们假设，软件开发产生回报的唯一手段就是把软件部署到产品环境，去提供服务（另外一个方面，如果不用部署就能产生回报，也许就不是一个软件开发项目，也许是某些政府部门的政治项目）。可以得出一个结论就是，要持续的产生回报就必须持续地进行部署。这看似是一个很浅显的道理，但是浅显的问题的可怕之处就在于，不是所有的人都意识到了这一点。&lt;/p&gt;&#xD;
&lt;p&gt;持续部署又是什么？持续意味着一直在部署，相对的就是偶尔部署。持续与偶尔部署的区别就在于，你把部署看做一种常态，还是一种偶然发生的事情。如果部署在所有的开发行为中，所在占到了10%而不是1%，那么就不再是偶尔才做的事情了。要想朝着持续部署的方向前进，意味着以前开发向前10步做一次部署，就得朝着5步一次部署，2步一次部署前进。持续并不是很难理解的问题，难度在于How？前面说了持续部署只是一个总绳，而渔网上的那么多的网眼就是How的答案。我们有SOA的架构，有高耦合低内聚的设计，有Domain Driven Design。有在线的Migration。给持续部署找出具体于你的Context的解决方案，就是整个Team需要努力的事情，它只是一个方向，而不是一个具体的solution。&lt;/p&gt;&#xD;
&lt;p&gt;最容易在实践中被混淆的就是&amp;ldquo;部署&amp;rdquo;。这似乎是另外一个很浅显的问题，但同样你会惊讶于到底有多少次我们做到了真正的部署。部署不仅仅是把软件包安装到某台机器上 ，让人可以来用。部署意味着，确实给业务提供服务。最容易检测的方法就是，把你部署好的软件反部署之后，会有多少业务无法运行，有多少比例的用户受到影响。根据这样的定义，部署到Staging环境不是部署，部署成为一个只有1%用户使用的Pilot版本也不是部署，部署到服务器上，但是所有用户仍然再用旧的系统，只是出于好奇才来用一两下的情况也不是部署。只有部署到产品环境上，给绝大部分用户使用，提供别的系统无法提供的服务时，才算是真正的部署。不要拿什么用户体验改进来搪塞了，不要再喊什么这只是一个Pilot了。只要不是真正地提供无可替代的服务，就根本不可能产生一个子的价值。&amp;ldquo;部署&amp;rdquo;成一个测试环境，只不过是给将来真正的部署，去赚那真真的一个子的钱，做准备而已。在此之前，都是投入，而不是产出。在产出真正实现之前，都是浪费。&lt;/p&gt;&#xD;
&lt;p&gt;你有没有问过你自己，你过去一年写的代码，有现在是部署了的。你过去三个月写的代码，现在是部署了的。你过去一个月写的代码，现在是部署了的。你过去两个星期的代码，现在是部署了的？不在于代码的多少，以及功能是否强大，只要是部署了，起码就有提供价值的可能。我们需要的就是，每天都问自己一遍这个问题。不但要个人的reflection，整个团队都要问这个问题。最重要的是，product owner，也就是我们乙方所谓的甲方，是不是也在问自己这个问题？如果是，那么很好，那么我们在追求卓越软件的道路上了，至少已经开始上路了。之前，只不过是在泥沼中爬行而已。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/taowen/aggbug/1680521.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/taowen/archive/2010/03/08/1680521.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/taowen/archive/2010/03/03/1676863.html</id><title type="text">企业定制软件开发的两个核心问题</title><summary type="text">企业定制软件开发不是计算机科学，需要解决的不是编译原理也不是组合数学。那么，企业定制软件开发的核心问题是什么？越来越感觉到，从事一个领域不需要有特别深刻的理解，但起码要知道做这个领域的事情，需要解决的核心问题是什么。比如说，开发C/S结构软件，状态同步（C/S状态同步以及窗口之间的状态同步）就是核心问题之一，而开发B/S结构的软件，状态同步就不是那么核心的问题。如果事先知道需要有这些核心问题需要考...</summary><published>2010-03-02T19:20:00Z</published><updated>2010-03-02T19:20:00Z</updated><author><name>taowen</name><uri>http://www.cnblogs.com/taowen/</uri></author><link rel="alternate" href="http://www.cnblogs.com/taowen/archive/2010/03/03/1676863.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/taowen/archive/2010/03/03/1676863.html"/><content type="html">&lt;p&gt;企业定制软件开发不是计算机科学，需要解决的不是编译原理也不是组合数学。那么，企业定制软件开发的核心问题是什么？&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;越来越感觉到，从事一个领域不需要有特别深刻的理解，但起码要知道做这个领域的事情，需要解决的核心问题是什么。比如说，开发C/S结构软件，状态同步（C/S状态同步以及窗口之间的状态同步）就是核心问题之一，而开发B/S结构的软件，状态同步就不是那么核心的问题。如果事先知道需要有这些核心问题需要考虑，在日常应对接踵而来的具体的事务的时候，就能够把解决问题的层次抬到更宏观的层面。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;目前而言，个人感觉企业定制软件开发的核心问题有两个：&lt;/p&gt;&#xD;
&lt;p&gt;1、如何保证所有参与者（包括客户在内的开发团队，以及最终用户）的沟通强度，使其能够满足完成开发目标的需要&lt;/p&gt;&#xD;
&lt;p&gt;2、如何管理企业定制带来的软件自身内在的高复杂度，使得复杂度不会超过团队的维护能力范围&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;在前面一篇&lt;a href="http://www.cnblogs.com/taowen/archive/2010/02/21/1670621.html"&gt;介绍组织的Blog&lt;/a&gt;中，谈到了核心问题中的第一个，沟通强度问题。团队而言，刨去个人能力，最重要的就是人与人之间的沟通。没有好的沟通，即便团队的个体能力都超级强，也无法形成合力。但只要有好的沟通，至少可以做到人尽其用。假设一个标准人的生产力是1/day。某些特别强的人可以达到3/day。但是如果需要达到10/day的生产力才能在市场允许的时间下完成项目，那么就无法用一个人来完成之间事情，所以才会有团队存在的必要。但是有两个标准人，并不会达到1+1=2/day的生产力。可能只有1.5。有三个标准人，更加不会达到1+1+1=3/day的生产力，很有可能有1.8。那么是什么制约了团队的整体生产力，那就是沟通。当两个相关联的任务A和B是一个人做的时候，关于任务A的知识存在于左脑，关于任务B的知识存在于右脑。那么结合两个任务的知识把其组装起来的沟通效率就是大脑内部的电信号的速度。但是如何任务A是由Dev甲完成的，任务B是由Dev乙完成的，那么整合两个任务的效率就受到人嘴皮的震动频率的约束，受到表达能力的约束，受到理解能力的约束。有人研究过，两个人即便是面对面，传输的比特率也要低于最早的拨号式Modem。更不用说，有的时候开发团队是分布式的。在无法看到表情，肢体语言，无法共享白板，只能在越洋电话里听到声音，而且其中还有一方是非工作时间，在这种情况下，1+1几乎很难达到1/day的生产力。什么是高效的团队，就是能够让1+1的值尽可能大的团队。如何变得高效，让沟通变得更加高效。怎么样让沟通变得高效高强度？这就是我们要处理的核心问题。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;第一个问题可以应用于所有的人的团队行为之中。人只要聚集成群，就会有沟通问题。所谓，有人的地方就有江湖。第二个问题则特定于企业定制软件开发。对于互联应用开发，也许复杂度的管理是其次的，最需要关注的是大用户量下的可扩展性。但是对于企业定制软件开发，由于业务自身的复杂度，导致了定制软件的复杂度。特别是业务的组合，导致的组合复杂性。假设在理想情况下，一个系统可以分解为模块A，B，C，其复杂度都是2。在复杂度管理良好的情况下 ，这些模块是被明确划分的，要理解A，只需要关注A，以及B与C少量与A交互的部分，也许理解的复杂度只是2 + 0.5.。但是在复杂度没有管理的情况下，所有的&amp;ldquo;逻辑&amp;rdquo;（也就是复杂度）都是随意地放置的。那么也就是没法办法保证，读A的逻辑只需要关注A，甚至这个A都是不存在的，你看到的知识一个系统，包含了A，B，C的功能，是完整的一块。这个时候要真正了解这个系统行为，可能就需要2 * 2 * 2 = 8这么高的代价了。随着模块（变量，方法，类，包，模块，Bundle）的增加，我们需要同时理解的东西也在不断增加。不去可以地管理复杂度，很有可能，我们需要了解一块功能，就需要把所有的代码都去阅读一遍。或者说，改动了一个方法，使得整个项目都需要重新被测试，因为没有地方是可以被信任的。如何管理复杂度？这就是我们要处理的核心问题。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;有意思的事情是，这两个核心问题是重叠的。把人，角色等同于类，接口，都抽象地看成点。把沟通理解为人与人之间的联系问题。把复杂度也理解为类与类的依赖问题。那么沟通问题和复杂度的管理问题都是如何把这些点联上线，组成一个高效的图的问题。这个图，就是一张关于&amp;ldquo;依赖&amp;rdquo;的图。人与人之间的依赖，类与类之间的依赖，包与包之间的依赖。依赖的另外的一个名字就是Coupling。而我们追求的就是Cohesion。Coupling（耦合）/ Cohesion（内聚）这两个词的妙处在于，明白的人根据自己的经验，一看就点头。不明白的人，由于没有对应的经验，无论怎么解释，都是摸不着头脑。正是因为其&amp;ldquo;妙不可言&amp;rdquo;性，所以我可以说这两个词就是所有问题的答案（你也无法反驳）。但至少我们可以知道企业定制软件开发的核心问题其实就是一个：就是管理好人与人之间的Dependency，包与包之间的Dependency，使得信息可以在高度依赖的人与人之间快速传递（强调Coupling带来的消息传递的效率），而理解又可以局限在高度内聚的模块内部（强调Cohesion带来的维护便利），但同时又不能让某人过度被依赖倒置工作过劳死了，被依赖得越多要求其体能越好，对于包的内聚也一样，高内聚做到极致就是最小的编译单元（类？），又会导致包的粒度过小，使得包的数量变得巨大，失去了维护的便利性。我们需要做的，就是在To Depend or Not To Depend中，根据场景作出取舍。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;那么抽象而言，无论是解决沟通问题还是复杂度问题都可以归纳为：&lt;/p&gt;&#xD;
&lt;p&gt;1、设置目标指标&lt;/p&gt;&#xD;
&lt;p&gt;2、度量现有的指标，观测现有的依赖图&lt;/p&gt;&#xD;
&lt;p&gt;3、做出依赖图的调整计划，并执行&lt;/p&gt;&#xD;
&lt;p&gt;4、观察指标的变化&lt;/p&gt;&#xD;
&lt;p&gt;5、重复步骤3，4，直到目标达到&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;但是问题是：&lt;/p&gt;&#xD;
&lt;p&gt;1、如何度量指标？沟通的效率？代码的质量？都很能度量。&lt;/p&gt;&#xD;
&lt;p&gt;2、如何观测现有的依赖图？包的依赖还可以观测，但是团队的协作是比较难观测的。&lt;/p&gt;&#xD;
&lt;p&gt;3、如何对依赖图做调整？重构？Change Agent？人不比代码那么容易改变。&lt;/p&gt;&#xD;
&lt;p&gt;4、如果指标不是简单数字，怎么比较？怎么知道指标是朝着目标发生变化？&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;这四个问题，几乎没有硬的科学问题。管理复杂系统的复杂度，可能是一门硬的科学。但是夹杂了人的因素的企业定制软件开发，一定不是一门硬的科学。那么，数学公式不是这些问题的答案。那么该朝哪个方向努力？&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;TO BE CONTINUED&lt;/p&gt;&lt;img src="http://www.cnblogs.com/taowen/aggbug/1676863.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/taowen/archive/2010/03/03/1676863.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/taowen/archive/2010/02/21/1670621.html</id><title type="text">组织模式 - Introduction</title><summary type="text">当Agile已经变成一个贬义词的时候，我们是要把Lean变成下一个贬义词吗？还是脚踏实地去做一些改进？ </summary><published>2010-02-21T08:57:00Z</published><updated>2010-02-21T08:57:00Z</updated><author><name>taowen</name><uri>http://www.cnblogs.com/taowen/</uri></author><link rel="alternate" href="http://www.cnblogs.com/taowen/archive/2010/02/21/1670621.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/taowen/archive/2010/02/21/1670621.html"/><content type="html">&lt;p&gt;当Agile已经变成一个贬义词的时候，我们是要把Lean变成下一个贬义词吗？还是脚踏实地去做一些改进？&amp;nbsp;&#xD;
&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;在这里，向大家推荐 James Coplien 的 Organizational Patterns。它不是一套新的过程，一上来弄十几个实践，也不知道为什么就开始结对开始 TDD 了。它也不是什么大师思想，只有大师才能领会。它更像一个中药柜，里面列了许多药方，更重要的是还告诉你了什么时候用什么药，相关的药有哪些，吃了药有副作用的话用什么药去化解。&amp;nbsp;&lt;/p&gt;&#xD;
&lt;p&gt;在Oredev 2008上有一个相关的演讲视频（原视频地址被墙，这是我放在Youku里的）：&amp;nbsp;&lt;br /&gt;&lt;a style="color: #006699; text-decoration: underline;" target="_blank" href="http://v.youku.com/v_show/id_XMTUxNzgyOTI0.html"&gt;http://v.youku.com/v_show/id_XMTUxNzgyOTI0.html&lt;/a&gt;&amp;nbsp;&lt;/p&gt;&#xD;
&lt;p&gt;这本书在电驴上有。国外的朋友可以去买纸版的：&amp;nbsp;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a style="color: #006699; text-decoration: underline;" target="_blank" href="http://www.amazon.com/Organizational-Patterns-Agile-Software-Development/dp/0131467409"&gt;http://www.amazon.com/Organizational-Patterns-Agile-Software-Development/dp/0131467409&lt;/a&gt;&amp;nbsp;&lt;br /&gt;在他的主页上有Top 10 Patterns：&amp;nbsp;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a style="color: #006699; text-decoration: underline;" target="_blank" href="http://users.rcn.com/jcoplien/Patterns/Top10OrgPatterns.html"&gt;http://users.rcn.com/jcoplien/Patterns/Top10OrgPatterns.html&lt;/a&gt;&amp;nbsp;&lt;/p&gt;&#xD;
&lt;p&gt;本来有一个wiki的，不过现在已经挂掉了。利用web.archive.org还可以找回来。&amp;nbsp;&lt;br /&gt;&lt;a style="color: #006699; text-decoration: underline;" target="_blank" href="http://orgpatterns.wikispaces.com/"&gt;http://orgpatterns.wikispaces.com/&lt;/a&gt;&amp;nbsp;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;模式有很多。在我看来最重要的就两个：&amp;nbsp;&lt;br /&gt;第一个是要有Unity of Purpose，大家必须要朝一个方向努力。另外一个是Distribute Work Evenly，工作必须在所有组员之间平均分担。不过最重要的也是最无用的，因为只要达到了这两个状态，基本上也没有项目管理问题了。所以我把其他的模式都看成达到Unity of Purpose &amp;amp; Distribute Work Evently的手段。&amp;nbsp;&lt;br /&gt;关于Distribute Work Evently这个模式特别有意思。Coplien用CRC卡记录了组员的角色，职责以及互相沟通的频率。然后标以红黄绿的颜色表示连接强度。这个非常有意思。让我想其了包之间的依赖。让我想起了玩Bridge游戏时钢铁受力图。也许协作问题根本要解决的就是如何平均分摊受力吧？&amp;nbsp;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/img/taowen/201002/2010022116475284.png" /&gt;&lt;/p&gt;&#xD;
&lt;p&gt;Cope总结得非常好，他说软件开发组织有多高效，主要就是取决于沟通的强度。上面那张图就很形象地标榜出了什么是高强度，健康的沟通。健康的人际关系网络，就是没有瓶颈的网络。信息能够及时地传达到需要的人的手上。在上面的图我看到的是平衡负载的人际关系，没有人是Overloaded的。&amp;nbsp;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/img/taowen/201002/2010022116504372.png" /&gt;&lt;/p&gt;&#xD;
&lt;p&gt;在这张图里，我们就明显的可以发现有人是Overloaded的。在你的团队里有这样人吗？很多项目里的项目经理，不但要管项目，管需求还要管技术，显然是会Overloaded。有的项目专门有人负责&amp;ldquo;沟通&amp;rdquo;，就是他去和客户沟通，然后回来和程序员沟通，然后和QA沟通。很快，沟通就变成他的全职工作，那么他的附加值是什么呢？只要团队内有这样的Overloaded的角色，他们就会变成薄弱点。一旦团队的规模变大，外部的压力变大，就会整体垮掉。所以，平均负载是关键。&amp;nbsp;&lt;/p&gt;&#xD;
&lt;p&gt;有一个非常形象的类比。就是Bridge游戏。这个游戏让你设计钢铁互相搭配的形状，设计一座桥梁，然后让汽车从上面通过。如果受压大的钢条就会变红，超过负载就会断掉。&amp;nbsp;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/img/taowen/201002/2010022116512067.jpg" /&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;但是这个是模式吗？James Coplien认为这个是，这个模式叫Distribute Work Evenly。但是我觉得这个不是常规意义上的模式。至少我理解的模式是为了解决特定问题在特定上下文中的特定解决方案。而Distribute Work Evenly只能说是一个愿望，并没有具体可实际操作的解决方案。我有一个想法是&amp;ldquo;&lt;span style="color: #ff0000;"&gt;如果不能轻易地想出一个不适用的场合，那么这个模式就不是一个模式&lt;/span&gt;&amp;rdquo;。按照这个想法，我把组织模式的四个Pattern Language几十个模式做了一些整理。下一篇，我们就来看看，组织模式都包含哪些内容。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/taowen/aggbug/1670621.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/taowen/archive/2010/02/21/1670621.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/taowen/archive/2010/02/20/1669940.html</id><title type="text">学习模式，不如先了解问题</title><summary type="text">从设计模式开始，已经有很多人尝试总结了各方个面的很多模式。不管是写的人多，读的人也多。甚至考的人也多。数年前去IBM面试实习生，Mentor问我的问题就是知道什么是Visitor模式不。但是模式为什么出现，这些牛人为什么花这么多时间精力去讨论，去总结，我还是最近才开始有所领悟。事情的起源是公司内部的一些讨论。我们公司（ThoughtWorks）是做敏捷咨询的。很多咨询师都是非常有经验的开发人员，但...</summary><published>2010-02-20T12:58:00Z</published><updated>2010-02-20T12:58:00Z</updated><author><name>taowen</name><uri>http://www.cnblogs.com/taowen/</uri></author><link rel="alternate" href="http://www.cnblogs.com/taowen/archive/2010/02/20/1669940.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/taowen/archive/2010/02/20/1669940.html"/><content type="html">&lt;p&gt;从设计模式开始，已经有很多人尝试总结了各方个面的很多模式。不管是写的人多，读的人也多。甚至考的人也多。数年前去IBM面试实习生，Mentor问我的问题就是知道什么是Visitor模式不。但是模式为什么出现，这些牛人为什么花这么多时间精力去讨论，去总结，我还是最近才开始有所领悟。&lt;/p&gt;&#xD;
&lt;p&gt;事情的起源是公司内部的一些讨论。我们公司（ThoughtWorks）是做敏捷咨询的。很多咨询师都是非常有经验的开发人员，但是做开发有经验未必做咨询有经验。在国内做过几个大的咨询项目之后，不少同事都有一些咨询方面的经验收获。个人都想做一些总结，以帮助咨询经验不多的后加入者。领导层也非常支持，觉得这个事情非常好。&lt;/p&gt;&#xD;
&lt;p&gt;我想很多人都有类似的&amp;ldquo;文档化经验&amp;rdquo;的想法吧。但是这种事情一旦落实到如何去做的时候，就争议颇多。有人就建议，不如来一个工作手册。把第一天做什么，第二天做什么都写下来。此论一出立马引来非常多的反对。反对的意见是非常有道理的，如果按照这样的做法做下去，只会有两个结果。要么，实践者变得僵化，没法给客户提供他们真正要的价值。要么，按照手册去做解决不了客户的问题，客户下次就不请我们了。总之，这种记录&amp;ldquo;我们过去是怎么做&amp;rdquo;的东西都觉得没什么用。大家最常提的一个说法就是，&amp;ldquo;每个地方的情况都不一样&amp;rdquo;。&lt;/p&gt;&#xD;
&lt;p&gt;既然这种包含太多工作细节的工作手册不行，那么我就来个Check List吧。把咨询中能够用到的工具都列出来。比如说，团队访谈，比如说，复盘。这个说法呢，大家都觉得行。至少在研究问题的时候可以把Check List看看。这种做法其实是效仿XP。极限编程其实就是一个Check List，包含了各种有用的Best Practices。这种做法又很类似Pattern，包含了各种各样的经典的应对之策。&lt;/p&gt;&#xD;
&lt;p&gt;所以模式是什么？模式就是一种&amp;ldquo;记录经验&amp;rdquo;的工具。无数前辈大拿觉得自己有经验可以和整个行业共享，他们选择的方式就是模式。但是，模式在实际的应用效果中是并不尽人意的。最主要的问题就是模式的误用。而这种误用的根源，我觉得就是他们的名字。模式本身的内涵是非常丰富的，完整的模式包括Context，Solution, Forces, Resulting Context。但是统领所有内容的标题却只是Solution。这样就容易让人只记住Solution，而忘记了它所适用的场合。或者因为不是完全理解适用的场合，而在适合的场合错过了应用模式的机会。&lt;/p&gt;&#xD;
&lt;p&gt;另外一个缺点是模式的整理不是按问题分类。经常我们会发现，对同一个问题，其实有好几个适合的模式。比如，提供了一个扩展点，我们既可以用Template Method，也可以用Strategy。但是由于模式是按照解决方案分类的，这样就没法对问题进入深入的讨论。而我们在应用模式的时候，首先面对的是手上的问题。从问题，到解决方案，这才是真正的经验所在。而模式本来的意图就是&amp;ldquo;记录经验&amp;rdquo;，却把这经验最重要的一部分没整理好。并不能说模式没有包含这一块的内容，好的模式书都有对什么问题适合什么模式的深入讨论。只是问题出在了整理方式上。&lt;/p&gt;&#xD;
&lt;p&gt;James Coplien经常强调一个Pattern Language。其实就是尝试把Pattern按照其服务的Context组织成一个Language。有点把模式按照问题组织起来的意识。但是他归纳的Pattern Language都比较高层，比如说Organization Construction Pattern Language。但是我觉得对于具体问题更好。比如说，项目上要培养新人怎么办？这个时候就可以去比较DayCare和PairProgramming这些组织模式在处理这个问题上的适用性。&lt;/p&gt;&#xD;
&lt;p&gt;所以我觉得很多模式，都应该按照所处理的问题做一个重新的整理。整理出来的结果就是一个&amp;ldquo;问题清单&amp;rdquo;。我觉得这比&amp;ldquo;模式清单&amp;rdquo;要有用的多。即便这个问题清单不去写解决方案，光是深入地讨论这些问题就非常的有价值。问题分为两类，一种是错误，那么我们可以&amp;ldquo;有则改之，无则加勉&amp;rdquo;；另外一种是常见的挑战，那么我们可以在真正遇到的时候敏锐地发觉我们已经有前人的经验可以利用了。&lt;/p&gt;&#xD;
&lt;p&gt;虽然这似乎只是认识上一小步进步。但是让我却非常激动：）最近对组织模式非常感兴趣。下一篇就从问题入手，尝试把组织模式给重新整理一下。Oh了。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/taowen/aggbug/1669940.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/taowen/archive/2010/02/20/1669940.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/taowen/archive/2009/07/10/1520308.html</id><title type="text">ESXi 入门配置</title><summary type="text">主板：泰安 S4981CPU：Operton 8350内存：南亚 4G * 2硬盘：Runcore 箭鱼四代 32G * 2RAID卡：PERC 6/i电源：台达 DPS-700mb机箱：道和D416</summary><published>2009-07-10T02:04:00Z</published><updated>2009-07-10T02:04:00Z</updated><author><name>taowen</name><uri>http://www.cnblogs.com/taowen/</uri></author><link rel="alternate" href="http://www.cnblogs.com/taowen/archive/2009/07/10/1520308.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/taowen/archive/2009/07/10/1520308.html"/></entry><entry><id>http://www.cnblogs.com/taowen/archive/2008/11/11/1328900.html</id><title type="text">难以实践敏捷：估算</title><summary type="text">谈到敏捷，人们往往都非常高调地打探TDD与持续集成。同时很多实践，非常低调。比如，估算。学习TDD，你有很多具体例子可以学习。但是学习估算，却无从下手。在&amp;ldquo;搞砸&amp;rdquo;了几个项目之后，貌似我摸着了一些门道了。估算的目的在我看来，估算有两个截然不同的目的。第一个是报价，第二个是规划。为了报价，我们追求的是所有故事卡的总体的绝对大小。为了指导发布规划和在迭代开发中做调整，我们追求的是...</summary><published>2008-11-11T03:32:00Z</published><updated>2008-11-11T03:32:00Z</updated><author><name>taowen</name><uri>http://www.cnblogs.com/taowen/</uri></author><link rel="alternate" href="http://www.cnblogs.com/taowen/archive/2008/11/11/1328900.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/taowen/archive/2008/11/11/1328900.html"/></entry><entry><id>http://www.cnblogs.com/taowen/archive/2008/11/07/1328734.html</id><title type="text">我应该用哪种虚拟机？（终）</title><summary type="text">以下是我个人的一些主观感受，没有任何客观数据支持。&amp;mdash;&amp;mdash;&amp;mdash;&amp;mdash;&amp;mdash;&amp;mdash;&amp;mdash;&amp;mdash;按实现方式来划分，从下面几个方面做一个比较CPU效率：软虚拟和硬件虚拟基本差不多，但是模拟的CPU速度最慢，而且不是慢一点半点。内存效率：大家都差不多，即便是QEMU这样的模拟器加上了KQEMU的加速，也能凑合。内存占用：硬虚拟的一大软肋...</summary><published>2008-11-07T04:56:00Z</published><updated>2008-11-07T04:56:00Z</updated><author><name>taowen</name><uri>http://www.cnblogs.com/taowen/</uri></author><link rel="alternate" href="http://www.cnblogs.com/taowen/archive/2008/11/07/1328734.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/taowen/archive/2008/11/07/1328734.html"/></entry><entry><id>http://www.cnblogs.com/taowen/archive/2008/11/06/1327362.html</id><title type="text">我应该用哪种虚拟机？（二）</title><summary type="text">上回我们是从硬件下手了。经历了一个从纯模拟，到半虚拟化，到全虚拟化，最终又半虚拟化的过程。但是，它们都是在同一个地方插了一脚:现在，我们把目光往上移，从应用程序到硬件之间，还有一层，那就是操作系统。虚拟机的第二个流派就是OS-Level Virtualization（操作系统级别的虚拟化），Application Virtualization（应用程序虚拟化）。说到硬件，作为应用程序开发人员的我们...</summary><published>2008-11-06T02:54:00Z</published><updated>2008-11-06T02:54:00Z</updated><author><name>taowen</name><uri>http://www.cnblogs.com/taowen/</uri></author><link rel="alternate" href="http://www.cnblogs.com/taowen/archive/2008/11/06/1327362.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/taowen/archive/2008/11/06/1327362.html"/></entry></feed>
