﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-Impossible is nothing-文章分类-软件工程</title><link>http://www.cppblog.com/apollo/category/958.html</link><description>　　爱过知情重醉过知酒浓
　　花开花谢终是空
　　缘份不停留像春风来又走
　　女人如花花似梦</description><language>zh-cn</language><lastBuildDate>Mon, 19 May 2008 19:12:49 GMT</lastBuildDate><pubDate>Mon, 19 May 2008 19:12:49 GMT</pubDate><ttl>60</ttl><item><title>初为项目经理的经验与大家分享</title><link>http://www.cppblog.com/apollo/articles/10106.html</link><dc:creator>笑笑生</dc:creator><author>笑笑生</author><pubDate>Sat, 15 Jul 2006 13:03:00 GMT</pubDate><guid>http://www.cppblog.com/apollo/articles/10106.html</guid><wfw:comment>http://www.cppblog.com/apollo/comments/10106.html</wfw:comment><comments>http://www.cppblog.com/apollo/articles/10106.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/apollo/comments/commentRss/10106.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/apollo/services/trackbacks/10106.html</trackback:ping><description><![CDATA[
		<p>这一天终于来到了：你从一个一线开发人员被提拔为项目经理。也许你一直在期盼，也许你心里还忐忑不安，也许这是你的职业发展选择，也许你只是不情愿的答应老板“试一下”。不管哪种情况，可能你并没有项目和人员管理及领导的教育背景或者培训经历。</p>
		<p>领导和管理（这两者是不同的）远非简单的与Dilbert <br />的老板背道而驰（译者注：Dilbert 是一个漫画人物，以“拥有”一个“白痴老板”而著称）。当你计划如何做好项目管理时，考虑采取以下列出的行动。也许你想做的事情很多，但下面的这些建议会帮助你集中到那些能提高效率（你自己的效率和团队的效率）的事情上。</p>
		<p>设立优先级</p>
		<p>你要着手的第一件大事很可能就是有意识的设立你作为项目经理的优先级。尽管你可能因为各种原因还需要很大程度上参与软件的开发，但除此之外，你还有一些新的职责。很多新任的项目经理都摆脱不了技术的诱惑，以致忽略了项目成员向自己寻求的帮助。</p>
		<p>富有效率的项目经理知道，他们最高优先的就是为项目成员提供服务。这些服务包括：指导和教育，处理冲突，提供资源，设立项目目标和优先级等等，适当时也要提供技术指导。我发现，把自己视为为成员工作，而非监工是很有价值的。不管你正在做或者将要做多重要的事，来你这儿寻求帮助的项目成员应该有“非屏蔽中断” （译者注：非屏蔽中断是一个硬件术语，此处意即最优先的）优先级。</p>
		<p>你第二优先的是让你所在组织的客户满意。作为一个项目经理，如果你不再涉足产品的一线开发，也许你很少有直接的机会可以让客户满意。但你必须为你的项目成员创造一个环境，使得他们在这个环境下工作，可以最有效的满足客户的需求。这是项目经理的一个重要职能。</p>
		<p>你第三优先的是你自己的事情。可能是一个与项目有关的技术问题（当然也是你感兴趣的），也可能是你的老板要你做的某件事。但当这些事与上面两个较高优先级冲突时，你要做好延后处理的准备。</p>
		<p>
				<br />你最低优先的是那些纯粹取悦你的老板的事情。在一个正常的组织（非Dilbet 式的组织）中，如果你做好了前面所说的更重要的三件事情，你的老板已经是非常惊喜了。尽管并非每个人都那么幸运可以在一个“正常”的组织工作，但还是努力做好这三件最重要的事。把注意力放在尽可能的帮助下属富有效率-- <br />并且快乐-- 上，而不是取悦于那些“上面”的人。</p>
		<p>分析你的技能差距</p>
		<p>初为项目经理，通常你会意识到你在领导和管理技能方面的差距，除非你已经为这个新职位做了充分准备。你有很强的技术背景，可能这也是提拔你领导技术团队的一个原因，但你还需要一些其他的技能。你需要客观的评价自己的长处和短处，并且着手缩小自己的差距。</p>
		<p>做软件的人常常被认为缺乏出色的交际能力。你需要加强你的人际处理能，诸如调解矛盾、说服他人、“推销”自己。你需要应付一些不想应付的场面，比如解雇你的下属、在进度上“讨价还价”、为争取下属的绩效“吵架”。</p>
		<p>伴我开始经理职涯的是倾听（Listening）技能的课程，我觉得很有价值。一线开发时，往往我们都有过人的精力来表达自己的技术观点。但作为管理人员，更需要一种包容和聆听的工作风格和交流方式。然后，从“听”的位置走到“说”的位置，你需要提高你的演讲（Presentation）技能。如果你对在公众场合演讲感到不适，你需要接受一些专门的演讲培训。这对你今后的工作很有好处。</p>
		<p>作为一个项目经理，协调他人的工作、计划和跟踪项目、必要时进行项目回溯并采取纠正措施等等都是你的职责。可能的话，接受有关项目管理的培训，学习如何设立优先级、如何主持高效的会议、如何明白无误的沟通等等技能；多看一些项目管理和风险管理的书籍和杂志，比如Project Management Institute 的月刊《PM Network》（译者注：你也可以从《PMT 评论》获得大量有价值的软件项目知识）。你还可以从SWCMM（软件能力成熟度模型）中找到很多有关软件项目管理的有用建议。</p>
		<p>
				<br />定义“ 质量”</p>
		<p>尽管绝大多数人都认真对待质量，也想生产出优质的产品；但是，有关软件质量的定义仍存在很大争议，比如高质量是“足够好”还是更为经典的质量观点--“无缺陷”。为了领导你的团队走向成功彼岸，你需要花些时间和你的下属以及客户一起来明确，对于他们，质量意味着什么。</p>
		<p>你的下属和客户是不同的两帮人，他们很可能对质量没有一致的看法，也就容易抱有不同的目的。如果客户很强调交货期，那他很可能没有耐心听程序员解释为什么需要额外的时间去检查每一行代码。如果客户看重的是软件的可靠性，那他在增加功能和减少Bug之间多半会选择后者。如果客户习惯了老版本的键盘操作，那他很少会对新的图形操作界面感兴趣。</p>
		<p>在我曾经负责的一个项目中，为了更好的了解客户的质量要求，我举办了一次开放式讨论会（Open Forum），除了项目成员和客户参加外，我还客户的上司们一起来参加讨论。这次讨论很有价值，因为我们发现很多原有的想法是和客户真正的质量需求背道而驰的。了解这些想法的差异，使得我们可以把力量集中在让客户满意的事情上，而不是放在让“开发满意”的事情上。</p>
		<p>软件质量通常被理解为合乎规格说明，满足客户需求，以及在文档和代码中尽量少的缺陷（Defect）等等，这些都是比较“经典”的定义。“六西格码质量”（Six-sigma Quality，译者注：是一种质量标准及相应的质量管理方法）为缺陷密度（Defect Density）和/ 或失效率（Frequency of Failure）设定了一个很高的标准，但是，它没有涉及质量的其他方面，比如交货期、可用性、特性集和性能价格比等等。无论我们是作为生产者还是消费者，我们都希望产品的质量在所有这些方面都是尽量高的，但事实上，我们总要在其中做出权衡和选择。</p>
		<p>我们在需求阶段就考虑，对于客户哪些质量特性是重要的，并把它们列举出来（比如，交互性、正确性、易学性等）。然后，我们找来一些关键的客户代表，请他们对这些质量特性打分。这样，我们就可以掌握哪些质量特性是最主要的，哪些是次要的，从而就可以有的放矢，为这些质量特性而优化设计。</p>
		<p>我听说的更有意思的一种软件质量定义是“客户回来的，但产品没有”（the customer comes back, but the product does not）。和你的下属以及客户一起定义合适的质量目标，一旦定义了，则要不遗余力的为达成这些目标而努力。也要以身作则，以高标准要求自己。记住这句话： “非完美不争取，非卓越不满足”（Strive for perfection; settle for excellence）。</p>
		<p>表彰进步</p>
		<p>表扬和奖励项目成员的成绩是很重要的激励方式。你要把建立奖励计划Recognition Program）视为头等大事，除非你已经有了适当的奖励计划。奖励既可以是象征性的奖状、证书，也可以是实实在在的奖品和现金。发奖时记得说，“感谢您的帮助”，或者“祝贺您完成了...”。还要记得奖励的范围不要局限在你的项目组内部，客户代表和一些向你提供特别帮助的项目组外部人员也是要考虑的。</p>
		<p>奖励计划不仅需要你投入一小笔钱，也需要你多动动脑，想想以何种方式奖励。和你的下属多交流，了解他们在乎什么样的奖励。要把奖励活动变成团队文化的一部分。另外，尝试“隐形”的奖励，让你的下属明白你是真的知晓他们所做的贡献，并且对此心存感激。</p>
		<p>
				<br />前车之鉴，后事之师</p>
		<p>你负责的项目很可能是半途接手的，而且你的前任做的并不怎么好；或者，虽然是新项目，但从前有类似的项目完成，当然有成功的，也有失败的。不管是哪种情形，你作为项目的负责人，应该花些时间分析以往的成功经验和失败教训。你要了解这些项目曾经出现过什么问题，以此避免自己重蹈覆辙。失败是成功之母，但你没有太多的机会失败，所以你要多从别人的失败中学习。</p>
		<p>不要戴着有色眼镜去看以往的项目，或许某个你不喜欢的家伙出色的完成了他的项目，你当然可以把这归结为运气或者侥幸，但如果你客观的分析，或许更有助于你的成功。</p>
		<p>你也需要客观的去评价自己完成的一些项目（如果有的话），了解自己的团队究竟强在哪里，弱在何处。事实上，每个完成的项目都要进行项目回顾（Post-project Review），有时这种总结式的项目回顾也叫做“开棺验尸”（Postmortem）。注意项目回顾不是为了追究谁的责任，发现问题、剖析问题是为了以后做得更好。你可以采取头脑风暴的做法，鼓励项目组成员各抒己见。另外，这种项目回顾也可以扩展到项目进行中，在每个大的阶段结束时都进行回顾。</p>
		<p>除此之外，你需要了解被软件业界普遍认可的最佳实践（Best practice）。在SteveMcConnell 的《Rapid Development》（Microsoft Press，1996）中介绍了27 个最佳实践和36 个软件开发的“经典”问题。此书曾获Jolt Award，是一个很好的学习起点。当你想把一些好的方法、工具和流程引入到你的项目中时，其他人可能会排斥、反对，甚至抵制，而这恰恰是你的职责所在，你要让项目成员明白为什么要这样做，并且确保他们不折不扣的执行。在你的团队内部，也会产生一些最佳实践，所以你要采取一些措施，促使在项目成员之间交流和采纳这些实践。</p>
		<p>设立改进目标</p>
		<p>当你回顾了以往的项目，并且确定了“质量”的含义，你需要设立一些短期的和长期的改进目标。只要可能，这些目标应该是可以量化的，这样你可以通过一些简单的指标来衡量自己是否在朝着这些目标前进。 </p>
		<p>举个例子，你发现以往的项目由于需求多变而经常延后，于是，你可以设立一个半年的目标，力求将需求的稳定性提高50%。这样的一个目标要求你每周每月做实际的工作：统计需求的改变数，查明需求的来源和改变的原因，采取措施来控制改变。这很可能将改变你与那些需求更改者的交往方式。&lt; br&gt;<br />你的这些目标和指标构成了软件流程改进的一部分。尽管流程改进常被人指责为“官僚作风”的体现，但事实上，每个团队都能找到一些可以改进的地方。如果你停留在一贯以来的做事方法上，你最好不要指望能获得比以前更好的结果。</p>
		<p>改进流程的原因通常有两个：纠正错误和预防错误。你要把精力集中到威胁或者可能威胁项目成功的因素上；带领你的团队一起分析你们目前做法的长处和短处，以及所面临的威胁。</p>
		<p>我自己的团队就组织过一次两阶段的头脑风暴练习，以此来确认提高我们的产量和质量的障碍。在第一阶段，参与者将自己想到的障碍写在即时贴上，每张即时贴写一个想法；然后，协调者就把这些即时贴收集起来，并进行分类；于是我们得到了若干大的分类，我们就把这些分类写在一张大的白纸上。&lt; br&gt;<br />在第二阶段，同样还是这些参与者，针对前面写的障碍，把想到的克服方法写到即时贴上，并且粘贴到相应的分类上。经过进一步的讨论和分析，我们得以把这些障碍细化，并且获得了一系列可操作的应对方法。</p>
		<p>设立可度量的、可争取的目标将集中你为改进流程而付出的努力。你要和你的队员们一起定期检视改进的结果。记住流程改进的目的是为了项目和公司的成功，而不是为了满足书本上的条条框框。把流程改进当成项目来操作，有自己的进度、投入和产出。否则，流程改进总是得不到应有的重视，最终被琐碎的日常工作而淹没。</p>
		<p>不要急于求成</p>
		<p>本文所建议的一些做法将帮助你这个项目管理的新手和你的团队取得更大的成功，随着你每天面临的工作压力，你或许会沦为又一个“苟延残喘”者，但是，你要始终明白你肩负的一个任务（可能也是你获得成功的机会），那就是形成你的团队文化和一套做事的方法，这是一个长期的任务。你不可能一下子把想做的事都做到，你可以根据自己的处境有所选择，从容上路。</p>
		<p>祝你好运！</p>
<img src ="http://www.cppblog.com/apollo/aggbug/10106.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/apollo/" target="_blank">笑笑生</a> 2006-07-15 21:03 <a href="http://www.cppblog.com/apollo/articles/10106.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>张瑞敏管理箴言100句　管理无小事</title><link>http://www.cppblog.com/apollo/articles/9505.html</link><dc:creator>笑笑生</dc:creator><author>笑笑生</author><pubDate>Thu, 06 Jul 2006 11:40:00 GMT</pubDate><guid>http://www.cppblog.com/apollo/articles/9505.html</guid><wfw:comment>http://www.cppblog.com/apollo/comments/9505.html</wfw:comment><comments>http://www.cppblog.com/apollo/articles/9505.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/apollo/comments/commentRss/9505.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/apollo/services/trackbacks/9505.html</trackback:ping><description><![CDATA[ 1、管理者要是坐下，部下就躺下了。
<p>　　2、管理就是行动。</p><p>　　3、管理就是树立榜样。</p><p>　　4、高层管理不等于高高在上。</p><p>　　5、管理者必须进行问题管理，而不是危机管理。</p><p>　　6、干部怕的就是不知道自己怕什么。</p><p>　　7、没思路的领导不想互动，没控制力的领导不敢互动。</p><p>　　8、干部怎样对待问题?要100%地落实责任，即“见数也见人”的原则。每个1%的问题都可以转化为100%的责任，100%的责任人。</p><p>　　9、干部怎样对员工?创造一个充满活力的氛围。</p><p>　　10、干部怎样对市场?创与闯。既要创新、创造;又要有闯劲、冲劲。</p><p>　　11、干部怎样对待管理?悟性和韧性。</p><p>　　12、干部的目标:做超级领导，即你的领导水平达到了能够让下属在没有领导的时候仍能够正常工作。形成有活力的员工，有合力的组织。</p><p>　　13、干部是事业成败的关键。</p><p>　　14、如果你或你的部门没有了上升的空间，也将失去生存空间。</p><p>　　15、终端的问题就是领导的问题。</p><p>　　16、看不出问题是最大的问题。</p><p>　　17、重复出现的问题是作风上的问题。</p><p>　　18、部下素质低不是你的责任，但是不能提高部下的素质是你的责任。</p><p>　　19、观念不变原地转，观念一变天地宽。</p><p>　　20、管事先管人，管人带作风。</p><p>　　21、渐进就是守旧。所以经营理念创新，就要反渐进，必须一步到位。</p><p>　　22、不只做一颗螺丝钉，要经营一部机器。</p><p>　　23、先画靶子再打枪。</p><p>　　24、特殊论就是给问题放行。</p><p>　　25、“立刻办”是奔着有预算的目标立刻办;“想想看”是没有预算的闭门造车。<br /><br />　　26、开发的是市场而不是产品。</p><p>　　27、市场目标的确定不是以个人能力为限，而是以用户满意度为准。</p><p>　　28、对市场目标的确定就是以在市场上有竞争力增值为标准。</p><p>　　29、带动全球经济增长的火车头减速并不意味着所有的车厢都减速。</p><p>　　30、零增长不等于零需求。</p><p>　　31、有效供给才能创造出市场。</p><p>　　32、海尔人只有创业没有守业。</p><p>　　33、海尔国际化战略能否成功，主要是靠每一个海尔人的国际化，有了每一个人的国际化才能保证海尔集团的国际化。</p><p>　　34、企业竞争力的实现取决于创新的细胞——SBU。</p><p>　　35、企业核心竞争力就是获取用户资源的能力。</p><p>　　36、一个企业的竞争力是看一个企业的员工是增值的资产还是负债。</p><p>　　37、要以秒为计算单位。</p><p>　　38、客户的要求不等于客户的需求。</p><p>　　39、造势产品输入的是用户的需求，输出的是用户的满意。</p><p>　　40、企业一旦站立到创新的浪尖上，维持的办法只有一个，就是要持续创新。</p><p>　　41、要持续造势，就要把企业做成一条流动的河。源头是创新的SBU，河的终点是用户的满意度，即对企业忠诚的用户。</p><p>　　42、把每位员工经营成创新的SBU并不断经营出高素质的人才的决定性因素就是管理者能否经营自我。</p><p>　　43、成为SBU的四个要素是:市场目标、市场定单、市场效果、市场报酬。</p><p>　　44、SBU具体的体现就是速度和创新。</p><p>　　45、经营企业就是要经营人，经营人首先要尊重人。</p><p>　　46、止谤莫如自修。战胜非议的唯一途径就是战胜自我。</p><p>　　47、挑战目标首先要挑战自我。</p><p>　　48、工作要简化，不要简单化。</p><p>　　49、求人不如求己。</p><p>　　50、“想干与不想干”是有没有责任感问题，是“德”的问题;“会干与不会干”是“才”的问题，但是不会干是被动的，是按照别人的要求去干;“能干与不能干”是创新的问题，即能不能不断提高自己的目标。</p><p>　　51、没有市场定单的管理者就是不要管理的管理者;没有市场定单的员工就是不干工作的员工，责任不在员工身上，而在于管理者;没有市场定单的工作就是无效工作。</p><p>　　52、决胜在终端。</p><p>　　53、流程再造就是先要再造人。</p><p>　　54、企业内部管理革命是为了创造企业外部的市场。</p><p>　　55、不是因为有些事情难以做到，我们才失去了斗志，而是因为我们失去了斗志，那些事情才难以做到。</p><p>　　56、我们所有的质量问题，都是人的问题，设备不好是人不好;零部件不合格是人不合格;我们所有发展不起来的问题都是思路问题，不是缺人是缺思路;不是缺件是缺思路。</p><p>　　57、企业发展的空间无限大，企业与用户的距离无限小。</p><p>　　58、有价值的定单是企业发展的永恒的主题，企业要发展必须有定单而且是有价值的定单。</p><p>　　59、质量无止境，企业无边界，名牌无国界。</p><p>　　60、“一站到位”的服务，“一票到底”的流程。</p><p>　　61、员工齐心，管理用心，对用户真心。</p><p>　　62、企业生命之树的土壤是用户。</p><p>　　63、企业做到极致，满足用户需求，无有他奇，只是本然。</p><p>　　64、要在国际市场竞争中取胜，第一是质量，第二是质量，第三还是质量。</p><p>　　65、质量不打折、服务不打折、信誉不打折。</p><p>　　66、质量一次就做对。</p><p>　　67、有缺陷的产品就是废品。</p><p>　　68、在一个管理好的企业内部没有激动人心的事情发生。</p><p>　　69、管理的关键不在于知而在于行。</p><p>　　70、没有定单就没有目标，没有目标就没有工资。</p><p>　　71、盘活资产首先要盘活人。</p><p>　　72、在别人否定自己之前先自我否定。</p><p>　　73、只有自己才能打倒自己。</p><p>　　74、突破自我，突破思维定势，突破昨天。</p><p>　　75、智力比知识重要，素质比智力重要，觉悟比素质更重要。<br /><br />　　76、创新的目标是创造有价值的定单;创新的本质是创造性的破坏，破坏所有阻碍创造有价值定单的枷锁;创新的途径是创造性的模仿和借鉴，即借力。</p><p>　　77、监控就是爱护，委任就是信任。</p><p>　　78、观念创新就是目标创新，目标创新就是提出别人认为不可能达到的目标，并用创新的办法实现它。</p><p>　　79、每个中高级管理人员只有自己先找到市场才能找到市场中竞争的方向。</p><p>　　80、不能用职能管理的手推职能管理的山。</p><p>　　81、永远战战兢兢，永远如履薄冰。</p><p>　　82、职能签字是事先没有市场目标的签字，事先无人负责的签字。用户的签字才是有效的签字。</p><p>　　83、用户的钞票才是企业的选票，用户的口碑才是企业的金杯。</p><p>　　84、只有真正实现了问题清零和买断损失，才能卖出有价值的定单。</p><p>　　85、要效果，不要借口。</p><p>　　86、没有思路就没有出路。</p><p>　　87、举一纲而万目张，失一机而万事毁。</p><p>　　88、管理无小事。</p><p>　　89、物流以时间消灭空间，商流以空间消灭时间。</p><p>　　90、什么是不简单?能够把简单的事千百遍都做对，就是不简单;什么不容易?大家公认的非常容易的事情认真地做好，就是不容易。</p><p>　　91、图难于其易，为大于其细。</p><p>　　92、把不可能变成可能。</p><p>　　93、昨天的成功经验与辉煌可能是明天成功的阻碍。</p><p>　　94、要做到实事求是，有两点很重要:其一是能不能实事求是，即思维方式的改变问题;其二是敢不敢实事求是，即思想境界的提高问题。</p><p>　　95、解决无效管理，首先要在思想观念上树立以几何级数去提高工作效果的信心;其次，要有创新是无止境的观念，创新的空间存在于每个地方、每个人、每件事上。</p><p>　　96、一切结论产生在调查研究之后;在调查研究中，如果找不出原因和解决办法就不能放过。</p><p>　　97、抓管理肯定要数，但如果就数抓数，最后连数也得不到，或者只抓到一个假数。抓好提高人的素质工作，数自然会产生;不抓人的工作，数就会越来越差，不能见数不见人。</p><p>　　98、以人为本的管理就是管理人员的创新精神。</p><p>　　99、真正的人才是在寻找实现自我的机遇。</p><p>　　100、市场是每个人的上级。</p><img src ="http://www.cppblog.com/apollo/aggbug/9505.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/apollo/" target="_blank">笑笑生</a> 2006-07-06 19:40 <a href="http://www.cppblog.com/apollo/articles/9505.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>熟练人员编码</title><link>http://www.cppblog.com/apollo/articles/9504.html</link><dc:creator>笑笑生</dc:creator><author>笑笑生</author><pubDate>Thu, 06 Jul 2006 11:39:00 GMT</pubDate><guid>http://www.cppblog.com/apollo/articles/9504.html</guid><wfw:comment>http://www.cppblog.com/apollo/comments/9504.html</wfw:comment><comments>http://www.cppblog.com/apollo/articles/9504.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/apollo/comments/commentRss/9504.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/apollo/services/trackbacks/9504.html</trackback:ping><description><![CDATA[
		<div>熟练人员经过多年的积累加上自己的CodeSnip的总结，基本不用额外再查找资料。而一般的开发人员在开发过程中会花掉10-20%时间去查找资料。</div>
		<div>?</div>
		<div>熟练人员注意代码复用，并且时刻注意重构和抽取公用代码。一般开发人员是代码拷来拷去完成功能。</div>
		<div>?</div>
		<div>熟练人员非常注意查找，定位，标签等各种快捷键的使用，定位查找方便快捷，IDE环境也根据习惯定义到最方便状态。</div>
		<div>?</div>
		<div>熟练人员编码前先思考清楚整个流程，在头脑或纸张上规划好整个实现方式和方法函数的划分。一般人员想到哪里写到哪里。</div>
		<div>?</div>
		<div>熟练人员写了50行以上或更多代码才Debug一两次，一般人员写了几行代码就要Debug多次，完全通过Debug来验证代码正确性。</div>
		<div>?</div>
		<div>熟练人员注重代码的质量，单元测试和可维护性，注重各种业务逻辑的验证和边界条件的校验。一般人员只注重简单功能的简单完成。</div>
		<div>?</div>
		<div>熟练人员提交测试的代码BUG很少，返工工作量很小。一般开发人员由于自测不完善BUG较多，造成大量的返工工作量。</div>
		<div>?</div>
		<div>熟练人员合理分配自己的时间，规划好每天工作任务，开发过程各位专注。一般开发人员一心多用，边开发边聊Q。</div>
		<div>?</div>
		<div>熟练人员善于知识的总结和积累，形成自我的知识库和经验库。</div>
		<div>?</div>
		<div>熟练人员善于发现问题，分析不足而自我持续改进。一般人员在外力干预侠被动改进。</div>
		<div>?</div>
		<div>熟练开发人员开发重点已经专业到对业务的深刻理解，一般开发人员考虑的是开发上编程的语言和工具。</div>
		<div>?</div>
		<div>熟练人员善于从各种影响自己开发效率的因素中挤时间，善于使用各种辅助开发工具。而一般人员则不善于这种总结。</div>
		<a href="/apollo/">
		</a>
<img src ="http://www.cppblog.com/apollo/aggbug/9504.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/apollo/" target="_blank">笑笑生</a> 2006-07-06 19:39 <a href="http://www.cppblog.com/apollo/articles/9504.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>怎样成为优秀的软件模型设计者？</title><link>http://www.cppblog.com/apollo/articles/8744.html</link><dc:creator>笑笑生</dc:creator><author>笑笑生</author><pubDate>Tue, 20 Jun 2006 05:30:00 GMT</pubDate><guid>http://www.cppblog.com/apollo/articles/8744.html</guid><wfw:comment>http://www.cppblog.com/apollo/comments/8744.html</wfw:comment><comments>http://www.cppblog.com/apollo/articles/8744.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/apollo/comments/commentRss/8744.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/apollo/services/trackbacks/8744.html</trackback:ping><description><![CDATA[ 
<p><font size="4"><strong>                    </strong>来自：blog　  雪茶技术</font></p><p>我们期待自己成为一个优秀的软件模型设计者，但是，要怎样做，又从哪里开始呢？ </p><p>将下列原则应用到你的软件工程中，你会获得立杆见影的成果。 </p><p>1. 人远比技术重要 </p><p>你开发软件是为了供别人使用，没有人使用的软件只是没有意义的数据的集合而已。许多在软件方面很有成就的行家在他们事业的初期却表现平平，因为他们那时侯将主要精力都集中在技术上。显然，构件（components），EJB（Enterprise Java Beans）和代理（agent）是很有趣的东西。但是对于用户来说，如果你设计的软件很难使用或者不能满足他们的需求，后台用再好的技术也于事无补。多花点时间到软件需求和设计一个使用户能很容易理解的界面上。 </p><p>2. 理解你要实现的东西 </p><p>好的软件设计人员把大多数时间花费在建立系统模型上，偶尔写一些源代码，但那只不过是为了验证设计过程中所遇到的问题。这将使他们的设计方案更加可行。 </p><p>3. 谦虚是必须的品格 </p><p>你不可能知道一切，你甚至要很努力才能获得足够用的知识。软件开发是一项复杂而艰巨的工作，因为软件开发所用到的工具和技术是在不断更新的。而且，一个人也不可能了解软件开发的所有过程。在日常生活中你每天接触到的新鲜事物可能不会太多。但是对于从事软件开发的人来说，每天可以学习很多新东西（如果愿意的话）。 </p><p>4. 需求就是需求 </p><p>如果你没有任何需求，你就不要动手开发任何软件。成功的软件取决于时间（在用户要求的时间内完成）、预算和是否满足用户的需求。如果你不能确切知道用户需要的是什么，或者软件的需求定义，那么你的工程注定会失败。 </p><p>5. 需求其实很少改变，改变的是你对需求的理解 </p><p>Object ToolSmiths公司（<a href="http://www.objecttoolsmiths.com/">www.objecttoolsmiths.com</a>）的Doug Smith常喜欢说：“分析是一门科学，设计是一门艺术”。他的意思是说在众多的“正确”分析模型中只存在一个最“正确”分析模型可以完全满足解决某个具体问题的需要（我理解的意思是需求分析需要一丝不苟、精确的完成,而设计的时候反而可以发挥创造力和想象力 - 译者注）。 </p><p>如果需求经常改动，很可能是你没有作好需求分析，并不是需求真的改变了。 </p><p>你可以抱怨用户不能告诉你他们想得到什么，但是不要忘记，收集需求信息是你工作。 </p><p>你可以说是新来的开发人员把事情搞得一团糟，但是，你应该确定在工程的第一天就告诉他们应该做什么和怎样去做。 </p><p>如果你觉得公司不让你与用户充分接触，那只能说明公司的管理层并不是真正支持你的项目。 </p><p>你可以抱怨公司有关软件工程的管理制度不合理，但你必须了解大多同行公司是怎么做的。 </p><p>你可以借口说你们的竞争对手的成功是因为他们有了一个新的理念，但是为什么你没先想到呢？ </p><p>需求真正改变的情况很少，但是没有做好需求分析工作的理由却很多。 </p><p>6. 经常阅读 </p><p>在这个每日都在发生变化的产业中，你不可能在已取得的成就上陶醉太久。 </p><p>每个月至少读2、3本专业杂志或者1本专业书籍。保持不落伍需要付出很多的时间和金钱，但会使你成为一个很有实力的竞争者。 </p><p>7. 降低软件模块间的耦合度 </p><p>高耦合度的系统是很难维护的。一处的修改引起另一处甚至更多处的变动。 </p><p>你可以通过以下方法降低程序的耦合度：隐藏实现细节，强制构件接口定义，不使用公用数据结构，不让应用程序直接操作数据库（我的经验法则是：当应用程序员在写SQL代码的时候，你的程序的耦合度就已经很高了）。 </p><p>耦合度低的软件可以很容易被重用、维护和扩充。 </p><p>8. 提高软件的内聚性 </p><p>如果一个软件的模块只实现一个功能，那么该模块具有高内聚性。高内聚性的软件更容易维护和改进。 </p><p>判断一个模块是否有高的内聚性，看一看你是否能够用一个简单的句子描述它的功能就行了。如果你用了一段话或者你需要使用类似“和”、“或”等连词，则说明你需要将该模块细化。 </p><p>只有高内聚性的模块才可能被重用。 </p><p>9. 考虑软件的移植性 </p><p>移植是软件开发中一项具体而又实际的工作，不要相信某些软件工具的广告宣传（比如java 的宣传口号write once run many ? 译者注）。 </p><p>即使仅仅对软件进行常规升级，也要把这看得和向另一个操作系统或数据库移植一样重要。 </p><p>记得从16位Windows移植到32位windows的“乐趣”吗 ？当你使用了某个操作系统的特性，如它的进程间通信(IPC)策略，或用某数据库专有语言写了存储过程。你的软件和那个特定的产品结合度就已经很高了。 </p><p>好的软件设计者把那些特有的实现细节打包隐藏起来，所以，当那些特性该变的时候，你的仅仅需要更新那个包就可以了。 </p><p>10. 接受变化 </p><p>这是一句老话了：唯一不变的只有变化。 </p><p>你应该将所有系统将可能发生的变化以及潜在需求记录下来,以便将来能够实现（参见“Architecting for Change”，Thinking Objectively, May 1999） </p><p>通过在建模期间考虑这些假设的情况，你就有可能开发出足够强壮且容易维护的软件。设计强壮的软件是你最基本的目标。 </p><p>11. 不要低估对软件规模的需求 </p><p>Internet 带给我们的最大的教训是你必须在软件开发的最初阶段就考虑软件规模的可扩充性。 </p><p>今天只有100人的部门使用的应用程序，明天可能会被有好几万人的组织使用，下月，通过因特网可能会有几百万人使用它。 </p><p>在软件设计的初期，根据在用例模型中定义的必须支持的基本事务处理，确定软件的基本功能。然后，在建造系统的时候再逐步加入比较常用的功能。 </p><p>在设计的开始考虑软件的规模需求，避免在用户群突然增大的情况下，重写软件。 </p><p>12. 性能仅仅是很多设计因素之一 </p><p>关注软件设计中的一个重要因素--性能，这好象也是用户最关心的事情。一个性能不佳的软件将不可避免被重写。 </p><p>但是你的设计还必须具有可靠性，可用性，便携性和可扩展性。你应该在工程开始就应该定义并区分好这些因素，以便在工作中恰当使用。性能可以是，也可以不是优先级最高的因素，我的观点是，给每个设计因素应有的考虑。 </p><p>13. 管理接口 </p><p>“UML User Guide”（Grady Booch，Ivar Jacobson和Jim Rumbaugh ,Addison Wesley, 1999）中指出，你应该在开发阶段的早期就定义软件模块之间的接口。 </p><p>这有助于你的开发人员全面理解软件的设计结构并取得一致意见，让各模块开发小组相对独立的工作。一旦模块的接口确定之后，模块怎样实现就不是很重要了。 </p><p>从根本上说，如果你不能够定义你的模块“从外部看上去会是什么样子”，你肯定也不清楚模块内要实现什么。 </p><p>14. 走近路需要更长的时间 </p><p>在软件开发中没有捷径可以走。 </p><p>缩短你的在需求分析上花的时间，结果只能是开发出来的软件不能满足用户的需求，必须被重写。 </p><p>在软件建模上每节省一周，在将来的编码阶段可能会多花几周时间，因为你在全面思考之前就动手写程序。 </p><p>你为了节省一天的测试时间而漏掉了一个bug，在将来的维护阶段，可能需要花几周甚至几个月的时间去修复。与其如此，还不如重新安排一下项目计划。 </p><p>避免走捷径，只做一次但要做对（do it once by doing it right）。 </p><p>15. 别信赖任何人 </p><p>产品和服务销售公司不是你的朋友，你的大部分员工和高层管理人员也不是。 </p><p>大部分产品供应商希望把你牢牢绑在他们的产品上，可能是操作系统，数据库或者某个开发工具。 </p><p>大部分的顾问和承包商只关心你的钱并不是你的工程（停止向他们付款，看一看他们会在周围呆多长时间）。 </p><p>大部分程序员认为他们自己比其他人更优秀，他们可能抛弃你设计的模型而用自己认为更好的。 </p><p>只有良好的沟通才能解决这些问题。 </p><p>要明确的是，不要只依靠一家产品或服务提供商，即使你的公司（或组织）已经在建模、文档和过程等方面向那个公司投入了很多钱。 </p><p>16. 证明你的设计在实践中可行 </p><p>在设计的时候应当先建立一个技术原型， 或者称为“端到端”原型。以证明你的设计是能够工作的。 </p><p>你应该在开发工作的早期做这些事情，因为，如果软件的设计方案是不可行的，在编码实现阶段无论采取什么措施都于事无补。技术原型将证明你的设计的可行性，从而，你的设计将更容易获得支持。 </p><p>17. 应用已知的模式 </p><p>目前，我们有大量现成的分析和设计模式以及问题的解决方案可以使用。 </p><p>一般来说，好的模型设计和开发人员，都会避免重新设计已经成熟的并被广泛应用的东西。 <br /><a href="http://www.ambysoft.com/processPatternsPage.html">http://www.ambysoft.com/processPatternsPage.html</a> 收藏了许多开发模式的信息。 </p><p>18. 研究每个模型的长处和弱点 </p><p>目前有很多种类的模型可以使用,如下图所示。用例捕获的是系统行为需求，数据模型则描述支持一个系统运行所需要的数据构成。你可能会试图在用例中加入实际数据描述，但是，这对开发者不是非常有用。同样，数据模型对描述软件需求来说是无用的。每个模型在你建模过程中有其相应的位置，但是，你需要明白在什么地方，什么时候使用它们。 </p><p>19. 在现有任务中应用多个模型 </p><p>当你收集需求的时候，考虑使用用例模型，用户界面模型和领域级的类模型。 </p><p>当你设计软件的时候，应该考虑制作类模型，顺序图、状态图、协作图和最终的软件实际物理模型。 </p><p>程序设计人员应该慢慢意识到，仅仅使用一个模型而实现的软件要么不能够很好地满足用户的需求，要么很难扩展。 </p><p>20. 教育你的听众 </p><p>你花了很大力气建立一个很成熟的系统模型，而你的听众却不能理解它们，甚至更糟－连为什么要先建立模型都不知道。那么你的工作是毫无意义的。 </p><p>教给你开发人员基本的建模知识；否则，他们会只看看你画的漂亮图表，然后继续编写不规范的程序。 </p><p>另外， 你还需要告诉你的用户一些需求建模的基础知识。给他们解释你的用例(uses case)和用户界面模型，以使他们能够明白你要表达地东西。当每个人都能使用一个通用的设计语言的时候（比如UML-译者注），你的团队才能实现真正的合作。 </p><p>21. 带工具的傻瓜还是傻瓜 </p><p>你给我CAD/CAM工具，请我设计一座桥。但是，如果那座桥建成的话，我肯定不想当第一个从桥上过的人，因为我对建筑一窍不通。 </p><p>使用一个很优秀的CASE工具并不能使你成为一个建模专家，只能使你成为一个优秀CASE工具的使用者。成为一个优秀的建模专家需要多年的积累，不会是一周针对某个价值几千美元工具的培训。一个优秀的CASE工具是很重要，但你必须学习使用它，并能够使用它设计它支持的模型。 </p><p>22. 理解完整的过程 </p><p>好的设计人员应该理解整个软件过程，尽管他们可能不是精通全部实现细节。 </p><p>软件开发是一个很复杂的过程，还记得《object-oriented software process》第36页的内容吗？除了编程、建模、测试等你擅长工作外，还有很多工作要做。 </p><p>好的设计者需要考虑全局。必须从长远考虑如何使软件满足用户需要，如何提供维护和技术支持等。 </p><p>23. 常做测试，早做测试 </p><p>如果测试对你的软件来说是无所谓的，那么你的软件多半也没什么必要被开发出来。 </p><p>建立一个技术原型供技术评审使用，以检验你的软件模型。 </p><p>在软件生命周期中，越晚发现的错误越难修改，修改成本越昂贵。尽可能早的做测试是很值得的。 </p><p>24. 把你的工作归档 </p><p>不值得归档的工作往往也不值得做。归档你的设想，以及根据设想做出的决定；归档软件模型中很重要但不很明显的部分。 给每个模型一些概要描述以使别人很快明白模型所表达的内容。 </p><p>25. 技术会变，基本原理不会 </p><p>如果有人说“使用某种开发语言、某个工具或某某技术，我们就不需要再做需求分析，建模，编码或测试”。不要相信，这只说明他还缺乏经验。抛开技术和人的因素，实际上软件开发的基本原理自20世纪70年代以来就没有改变过。你必须还定义需求，建模，编码，测试，配置，面对风险，发布产品，管理工作人员等等。 </p><p>软件建模技术是需要多年的实际工作才能完全掌握的。好在你可以从我的建议开始，完善你们自己的软件开发经验。 </p><p>以鸡汤开始，加入自己的蔬菜。然后，开始享受你自己的丰盛晚餐吧。</p><img src ="http://www.cppblog.com/apollo/aggbug/8744.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/apollo/" target="_blank">笑笑生</a> 2006-06-20 13:30 <a href="http://www.cppblog.com/apollo/articles/8744.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>三个代表</title><link>http://www.cppblog.com/apollo/articles/8588.html</link><dc:creator>笑笑生</dc:creator><author>笑笑生</author><pubDate>Thu, 15 Jun 2006 05:36:00 GMT</pubDate><guid>http://www.cppblog.com/apollo/articles/8588.html</guid><wfw:comment>http://www.cppblog.com/apollo/comments/8588.html</wfw:comment><comments>http://www.cppblog.com/apollo/articles/8588.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/apollo/comments/commentRss/8588.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/apollo/services/trackbacks/8588.html</trackback:ping><description><![CDATA[
		<div class="postText">
				<p>
						<font size="4">   说道“三个代表”，纯粹是拿来吸引眼球的，俺准备这篇Blog能够给俺的访问数目提升一下，鹅滴神啊。闲话少说书归正传，让我们来看看到底是那三个代表：<strong>代表客户的利益、代表员工的利益、代表公司的利益</strong>。</font>
				</p>
				<p>
						<font size="4">      没有利益的事情是不会有人去做的，只是不同的时间、地点、空间和人员，利益的定义和取舍不同。资本论里面把利益这个东西描述的相当清楚。在这里提出这个“利益”其实是想强调一个网络和相关性。一个项目的存在就有这三方的利益互相挂钩在一起.当然还有一方的利益没有说在这里，我将会在本文的最后一段阐述第四个代表。</font>
				</p>
				<p>
						<font size="4">
								<strong>第一个代表：客户的利益</strong>
						</font>
				</p>
				<p>
						<font size="4">      “为客户考虑的同时就是为企业的生存考虑”这是鹅多年前提出的一个口号，一个软件产品是一个空洞的东西，大家都是在空中楼阁，从无到有的画圆，只是画这个圆的时候客户告诉你了一个方的框架；然后就看你是否能够画一个圆出来，是椭圆还是正圆，还是一个不规则的多边形？？？</font>
				</p>
				<p>
						<font size="4">      软件产品不同于修楼和盖房子，这是一个很纯粹的空想和冥想的智力活动的结晶。这个结晶没有产生前大家都只能互相描述这个结晶的样子，然后互相在脑海中YY出一个形象，这个大家包括所有人：客户、设计人员、需求人员、编码人员等等。一直到完工拿这个结晶给客户，客户左看三圈，右看三圈。哎呀呀，好像不是我要的那个样子，你们怎么做成这样呢？？？于是大家重新合计了一下，回去再修改了一下这个结晶再拿给客户，客户看了一下：嗯，好像是这个样子。不要高兴太早了，过几天你又被客户叫过去了：你们弄出来的这个东西不好用，会去再改改... ... ... ...嗯，我想加一些功能... ... ...</font>
				</p>
				<p>
						<font size="4">      （我不知道我写到这里的时候各位看官有没有兴趣继续看下去，虽然俺写的不是很累，好歹你也给鹅一点Face抢一个沙发嘛！）</font>
				</p>
				<p>
						<font size="4">      如我上面描述的那样，一个软件项目的大概情况就是这样，按照那本软件工程的书里面所说或许可以同那个什么“螺旋式上升”挂钩；但是这种螺旋不是项目管理人员愿意看到的：项目周期加长，成本增加等等，很多问题产生（当然有些螺旋是始终避免不了的）。</font>
				</p>
				<p>
						<font size="4">      软件这个东西始终不同于修房子，人类从群居以来有了几千年的修房子的经验，而软件开发管理的过程从整个人类学来说也不过几十年，再来到中国也真正不过几年。中国人都喜欢热闹，那里热闹就瞅那里，也喜欢一步登天，考，好歹中国人飞天也是这么几年的事情，大家急个P.</font>
				</p>
				<p>
						<font size="4">      说了一点废话，我有点混乱和偏题了，其实我的想法就是一个项目管理人员不能只为了完成项目而完成项目。项目管理人员要真正为客户考虑，为客户解决问题，站在客户的角度考虑问题，从客户的角度来看这个正在进行中的软件项目，把客户的需求变为管理人员的需求（把自己变为客户人员），拿这些需求去完善和要求项目。这样才能真正保证这个项目是客户要的，才能保证客户使用起来不会有生涩感。才能避免一些螺旋的产生，主动解决问题比消极应战好。如果项目管理人员不能把自己放在客户的位置，对于软件的要求始终都是存在一定差距的。</font>
				</p>
				<p>
						<font size="4">     第二个代表：代表员工的利益</font>
				</p>
				<p>
						<font size="4">      我一直有些看法：软件产品不是测试出来的，他是制造出来的，测试只是辅助手段。保证软件产品质量的非常重要因素是一个团队。软件是一个智力性的产品，而载体就是人，项目管理的人。</font>
				</p>
				<p>
						<font size="4">      在我看来（根据我这么多年经验），最能表达软件质量的是人员的积极性、主动性。人这种动物是非常有惰性的，而且依附性比较强，很多时候都是得过且过；但是当这种动物对什么感兴趣的时候这种最能燃烧小宇宙。</font>
				</p>
				<p>
						<font size="4">     而一个项目管理人员要做的就是协调和沟通，提高他们的积极性和主动性，取得他们的信任，了解他们对于自己价值的体现。有正对性的给他们提供相应的利益服务。</font>
				</p>
				<p>
						<font size="4">     其实大部分智力性人员一般需要的是两个方面：一种被需要认可的价值；一种被金钱认可的价值。前者需要导向，这个导向没有什么好说的，我认为不同的管理人员方法不一样。后者分为两个方面工资和项目奖金，工资这块我就不多说了，我说的是项目奖金问题：</font>
				</p>
				<p>
						<font size="4">     还记得大锅饭不，没有项目奖惩制度的项目就是一个大锅饭，做好做坏一个样，质量问题很严重，没有项目奖惩制度就是对于项目确少可控制的细节，项目管理人员手中无权，就缺少控制手段。管理，即要管，又要理。项目管理人员手里必须要有权啊，有人事权，财权。胡萝卜没有，大棒也没有哪能做什么事情???</font>
				</p>
				<p>
						<font size="4">     大家出来混其实都是混口饭吃，所以根本就是一个钱，钱啊。一个项目的利益分配方案必须让项目人员认可，否则改项目就是一个松散型的项目：质量问题、进度问题、沟通问题... ...</font>
				</p>
		</div>
<img src ="http://www.cppblog.com/apollo/aggbug/8588.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/apollo/" target="_blank">笑笑生</a> 2006-06-15 13:36 <a href="http://www.cppblog.com/apollo/articles/8588.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title> 论软件系统分析的方法和策略</title><link>http://www.cppblog.com/apollo/articles/8567.html</link><dc:creator>笑笑生</dc:creator><author>笑笑生</author><pubDate>Wed, 14 Jun 2006 13:51:00 GMT</pubDate><guid>http://www.cppblog.com/apollo/articles/8567.html</guid><wfw:comment>http://www.cppblog.com/apollo/comments/8567.html</wfw:comment><comments>http://www.cppblog.com/apollo/articles/8567.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/apollo/comments/commentRss/8567.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/apollo/services/trackbacks/8567.html</trackback:ping><description><![CDATA[
		<dl class="ReadArticle">
				<dt>
						<strong>
								<font size="4">论软件系统分析的方法和策略 </font>
						</strong>
				</dt>
				<dd class="ArticleInfo">                          来自：Sawin　   
</dd>
				<dd class="ArticleContent">
						<p>当一个软件项目摆在人们面前时，进行系统的分析是首当其冲的,正如我们的一句古语:三思而后行。因此，无论做任何事都应考虑是否有意义以及它的可行性。在过去，人们将“软件”与“程序”、“开发软件”与“编程序”划等号，粗略的进行估计和设计软件产品势必会影响软件的质量和生产效率。然而现在，随着信息化产业的发展，软件企业的增多,尤其是当面对一些大中型的软件项目，对软件生命周期的各个环节进行系统详细的分析将更加重要,而且会提高软件的质量和效率。</p>
						<p>
								<strong>一、软件系统开发<br /></strong>无论动物、植物，作为一个完整的事物,都有它的生命周期、或者说它的轨迹。作为先进高科技的产物---软件产品,自然也不例外。这期间,要经过一系列的过程,例如,开发者首先要考虑它的可行性,是否能坚决当前问题或是将来是否能有更大的发展,当然要有详细的规划和设计,要形成书面的文档记录下来,以便开发员之间的交流。其次关键的是能否满足用户的需求,因为判断开发出来的软件是否成功的标准之一就是看它有无实用性。之后便是一系列的实施,例如程序设计,系统测试,以及接下来的后续工作---维护与修改工作。<br />软件生命周期的各个环节将软件系统开发大致分为四个阶段，用图示的方式表现出来即通常所说的“瀑布模型”，如图：</p>
						<p>
								<strong>二、系统分析</strong>
								<br />系统分析是软件生命周期的一个关键环节，其目标是将对计算机应用系统的需求转化成实际的物理实现。然而实际面太多，增加了软件分析的复杂度，那么究竟在系统分析的过程中需要考虑那些因素呢？</p>
						<p>1、系统目的。在考虑系统目的时，应更多的侧重于系统的最终目标考虑，因为一个系统不可能在最初就是完美的，要为系统留些余地。<br />2、系统参与者。在整个项目中，要考虑有哪些方面参与了系统，这些参与者人可能在系统建设中起重要作用，他们采取什么样的态度将会对系统有一定的影响。另外，还要了解各参与者的初衷是什么。<br />3、明确的评价标准。最好从参与的各方面都进行考虑，要知道他们对这个系统是否有一个明确的评价标准。<br />4、系统开发计划的完善度。计划表要有明确的阶段，每一阶段要有详细的完成计划，以及对阶段完成情况进行的评价。<br />当然还有很多因素值得考虑，可以根据面对的项目的不同而改变,譬如与软件开发人员的交流等等。</p>
						<p>
								<strong>三、开发内容</strong>
								<br />开发软件系统最为困难的部分，就是准确说明开发什么。这就需要在开发的过程中不断的与用户进行交流与探讨,使系统更加详尽,准确到位。这就需要确定用户是否需要这样的产品类型以及获取每个用户类的需求。需求类型包括三个: </p>
						<p>1、业务需求（business requirement）反映了组织机构或客户对系统、产品高层次的目的要求，它们在项目视图与范围文档中予以说明。<br />2、用户需求(user requirement) 文档描述了用户使用产品必须要完成的任务，这在使用实例文档或方案脚本说明中予以说明。<br />3、功能需求(functional requirement)定义了开发人员必须实现的软件功能，使得用户能完成他们的任务，从而满足了业务需求。<br />总之，无论是商业性或非商业目的的产品，都应具备完整的说明书,以避免发生状况时引起不必要的损失。</p>
						<p>
								<strong>四、分析设计和系统方案<br /></strong>在考虑完各方面的实际因素后，就要对项目进行总体的分析设计。简单的讲，总体设计需要确定的内容应当包括：</p>
						<p>1、系统需要实现哪些功能；<br />?2、开发使用什么软件，在什么样的硬件环境；<br />3、需要多少人，多少时间； <br />4、需要遵循的规则和标准有哪些。 </p>
						<p>一般情况下，在总体设计出来后，就需要给客户一个系统的方案。如果在客户需求不是十分明确的情况下提交方案，往往和实际制作后的结果会有很大差异。所以应该尽量取得客户的理解，在明确需求并总体设计后提交方案，这样对双方都有益处。而方案则应包括以下几个部分： </p>
						<p>1.客户情况分析； <br />2.系统需要实现的目的和目标； <br />3.系统各个模块与结构；<br />4.使用软件，硬件和技术分析说明； <br />5.开发时间进度表； <br />6.维护方案； <br />7.制作费用。</p>
						<p>总之，总体设计阶段是以比较抽象概括的方式提出了解决问题的办法；而详细设计阶段的任务，也就是把解法具体化。详细设计主要是针对程序开发部分来说的，但这个阶段的不是真正编写程序，而是设计出程序的详细规格说明。这种规格说明的作用很类似于其他工程领域中工程师经常使用的工程蓝图，它们应该包含必要的细节，例如：程序界面、表单、需要的数据等，程序员可以根据它们写出实际的程序代码；而至于后续的工作,就有程序员来完成编写程序,系统测试员来完成测试,还有之后的维护和修改。</p>
						<p>
								<strong>五、运用策略<br /></strong>伟人有治国的策略,商人有致富的财路,巧妇有理家的本领,鹤发童颜的老人有长生的秘诀。在进行软件开发系统分析时，也要本着一些策略：</p>
						<p>1．“简单—复杂—简单”。这是技术型分析人员经常碰到的情况，认为分析出错综复杂的关系，花哨的图表才能显示出分析水平高，其实，分析经常要经历"简单-复杂-简单"的过程，前一个简单表现为分析人员"认为简单"；随着分析的深入，原以为简单的问题会越来越复杂；最后，经过概括、消化、分解，使得需求简单明了。<br />2．软件复用技术。新开发的软件，要从一开始就考虑其可演化性，以便以后的再工程和构件提取。随着软件复用技术的不断发展，从头开始的软件大量减少，使用的遗产系统相应增多,这就避免了重复的工作,使得已完善的模块遗传下去。<br />3．模块化概念。模块化可以增强系统的独立性，使耦合度降低，实现“高内聚-松耦合”。对于模块的内部，使其高度集中，而模块与模块间的联系相对减少，这样使系统各模块独立的进行运转。</p>
						<p>任何雄才伟略的人都能纵观全局,有一览众山小之气魄。若想有出色的成果必然要有对事物进行总的分析的能力,这就包括是否着眼于长远利益,是否能对其很好的管理掌控。系统并不是简单的计算机代替手工劳作的一种方式，它是一种高于现实的管理模式。因此,系统分析是软件开发过程中必不可少的一个环节，它为高质量软件产品的开发奠定了基础。 </p>
						<p> </p>
				</dd>
		</dl>
<img src ="http://www.cppblog.com/apollo/aggbug/8567.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/apollo/" target="_blank">笑笑生</a> 2006-06-14 21:51 <a href="http://www.cppblog.com/apollo/articles/8567.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>普通开发人员与软件工程师的区别</title><link>http://www.cppblog.com/apollo/articles/8543.html</link><dc:creator>笑笑生</dc:creator><author>笑笑生</author><pubDate>Wed, 14 Jun 2006 05:13:00 GMT</pubDate><guid>http://www.cppblog.com/apollo/articles/8543.html</guid><wfw:comment>http://www.cppblog.com/apollo/comments/8543.html</wfw:comment><comments>http://www.cppblog.com/apollo/articles/8543.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/apollo/comments/commentRss/8543.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/apollo/services/trackbacks/8543.html</trackback:ping><description><![CDATA[
		<p>普通开发人员与软件工程师的区别：</p>
		<p>
				<strong>对比1：</strong>
		</p>
		<p>
				<strong>A、普通开发人员：</strong>
		</p>
		<p>掌握了计算机基础知识；<br />熟悉计算机资源，学会了编程语言，喜欢卖弄技巧，喜欢比较编程语言的优劣；<br />以能编出某种特殊功能的程序为荣，不懂原理，不求甚解；<br />喜欢个人开发，不重视文档编写；</p>
		<p>
				<strong>B、软件工程师：</strong>
		</p>
		<p>计算机基础知识扎实；<br />掌握两门以上编程语言，很少停留在表面比较编程语言的优劣；<br />以编写出用户满意的高质量软件为荣。<br />懂得个人开发和团队开发的利弊，文档规范，齐全。</p>
		<p>
				<strong>对比2：</strong>
		</p>
		<p>
				<strong>A、普通开发人员：</strong>
		</p>
		<p>
				<strong>
				</strong>
				<br />只重视功能的实现，不重进度和质量的把握。<br />怕被“管”得太死，动不动就说限制了思路，没有发挥空间。<br />不喜欢做测试工作，认为测试低人一等，从来没有做过测试工作。<br />只根据自己的爱好学习技术；</p>
		<p>
				<strong>B、软件工程师：</strong>
		</p>
		<p>懂得在进度、质量（功能）和成本之间平衡。<br />懂得规范的目的在于重用，重用有利于提高效率和集中精力创新。<br />认为测试工作比编码更具挑战性，自己经常为同伴的代码做白盒测试。<br />根据企业项目的需求和自己发展目标的共同点选择学习内容和方向；</p>
		<p>
				<strong>对比3：</strong>
		</p>
		<p>
				<strong>A、普通开发人员：</strong>
		</p>
		<p>认为别人程序很差，不喜欢看别人的代码；<br />总认为自己比业务专家还更理解需求。<br />项目开始时，喜欢说:“没问题，SO EASY”。<br />项目大大延期时，喜欢说：“设计太烂，没法编程”。</p>
		<p>
				<strong>B、软件工程师：</strong>
		</p>
		<p>喜欢为同事走查代码，并以此获得学习他人优点的机会；<br />懂得自己只是可能比业务专家更懂编程。<br />项目开始时，喜欢问:“那是什么？这是为什么？”。<br />项目大大延期时，喜欢说：“我为什么就没想到…”。<br /></p>
<img src ="http://www.cppblog.com/apollo/aggbug/8543.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/apollo/" target="_blank">笑笑生</a> 2006-06-14 13:13 <a href="http://www.cppblog.com/apollo/articles/8543.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>80／20效率法则”的人力制度</title><link>http://www.cppblog.com/apollo/articles/8000.html</link><dc:creator>笑笑生</dc:creator><author>笑笑生</author><pubDate>Wed, 31 May 2006 15:06:00 GMT</pubDate><guid>http://www.cppblog.com/apollo/articles/8000.html</guid><wfw:comment>http://www.cppblog.com/apollo/comments/8000.html</wfw:comment><comments>http://www.cppblog.com/apollo/articles/8000.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/apollo/comments/commentRss/8000.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/apollo/services/trackbacks/8000.html</trackback:ping><description><![CDATA[ 
<script language="javascript"><![CDATA[ocument.title="“80／20效率法则”的人力制度 - "+document.title]]&gt;</script><div class="postText"><font face="Verdana" size="4">　　80／20效率法则(the 80／20 principle)，又称为帕累托法则、帕累托定律、最省力法则或不平衡原则。 </font><p> </p><p><font face="Verdana" size="4">　　早在19世纪末，帕累托研究英国人的收入分配问题时发现，大部分财富流向小部分
人一边。还发现某一部分人口占总人口的比例，与这一部分人所拥有的财富的份额，具有比较确定的不平衡的数量关系。而且，进一步研究证实，这种不平衡模式会
重复出现，具有可预测性。经济学家把这一发现称为“帕累托收入分配定律”，认为是“帕累托最引人注目的贡献之一”。</font></p><p><font face="Verdana" size="4">　　管理学家从帕累托的研究中归纳出了一个简单的结果：如果20％的人占有80％的
社会财富，由此可以预测，
10％的人所拥有的财富为65％，5％的人享有的财富为50％。管理学家看重的是这一结果体现的思想，即不平衡关系存在的确定性和可预测性。正如里查德·
科克有一个精彩的描述：“在因和果、努力和收获之间，普遍存在着不平衡关系。典型的情况是：80％的收获来自20％的努力；其他
80％的力气只带来20％的结果。”</font></p><p><font face="Verdana" size="4">　　总之，“80／20效率法则”告诉人们一个道理，即在投入与产出、努力与收获、原因和结果之间，普遍存在着不平衡关系。少的投入，可以得到多的产出；小的努力，可以获得大的成绩；关键的少数，往往是决定整个组织的效率、产出、盈亏和成败的主要因素。</font></p><p><font face="Verdana" size="4">　　将“80／20效率法则”所内涵的理念和规律运用于组织人力资本管理活动之中，管理者必须明确人力资本使用的特殊性，以及提高人力资本使用效率的重要性与可行性。</font></p><p><font face="Verdana" size="4">　　首先，人力资本的存在形式和作用方式不同于物力资本。人力资本以人为载体。使用权主体只能间接控制，无法直接支配。运用权主体具有永久的唯一性。人力资本的使用效率，完全由载体个人劳动努力的供给决定。(王建民，2001．5；2001．12)</font></p><p><font face="Verdana" size="4">　　其次，人力资本是最重要的生产要素。不仅因为生产的可持续发展对人力资本要素需求的比例不断扩大，而且其中非人力资本要素的使用也完全取决于人力资本。</font></p><p><font face="Verdana" size="4">　　第三，人力资本完全可以通过管理方式的改变而提高使用价值和价值。在一种“游戏
规则”下默默无闻的“平庸之辈”，在另一种规则下却有可能成为闻名遐迩的栋梁之才。“游戏规则”就是制度，即规定或影响主体行为的正式和非正式规则。制度
是资本，是生产力的创造者。通过构建或创新管理制度，完全有可能提高组织中人力资本的生产力。</font></p><p><font face="Verdana" size="4">　　 第四，“80／20效率法则”适用于人力资本管理。实践表明，一个组织的生产效率和未来发展，往往决定于少数(比如20％)关键性的人才。对一个股份制企业组织而言，从董事会的角度考虑，关键人才一般包括以下人员：</font></p><p><font face="Verdana" size="4">　　(1)CEO、CFO等高级的管理人员，</font></p><p><font face="Verdana" size="4">　　(2)开发、生产、营销、人力资源等重要部门经理或项目负责人；</font></p><p><font face="Verdana" size="4">　　(3)高级研究与开发(R&amp;D)人员；</font></p><p><font face="Verdana" size="4">　　(4)具有创造发明高级技能型人力资本的技术、工艺及制度设计人员；</font></p><p><font face="Verdana" size="4">　　(5)其他极具发展潜力的高素质员工。</font></p><p><font face="Verdana" size="4">　　基于此，如何构建“80／20效率法则”的组织人力资本管理制度就十分有意义。下面五项行动建议，供人力资本决策者和管理者参考，也许可助一臂之力。 </font></p><p><font face="Verdana" size="4">　　一、精挑细选，发现“关键少数”成员</font></p><p><font face="Verdana" size="4">　　所谓发现“关键少数”成员，实际上是要发现“关键的”人力资本。人力资本无色无
味、无形无态、无影无踪，本来就难以“发现”，更何况是对特定组织具有关键作用的人力资本?为了找到合适人选，许多组织不仅要支付发现成本，而且还得冒因
“招聘失败”而导致价值损失的风险。一般而言，所选人员职位越高，所付成本或所冒风险越大。招聘CEO、CFO等“最关键”的高级管理人员，可以委托专业
“猎头公司(Head
Hunter)”进行。为此需要付出的服务费可达所获人才年薪的25％，甚至35％。尽管费用不低，但对组织来说还是比亲自操作来得方便、保险、便宜。
2002年6、7月间，国内媒体“爆炒”了“哈佛博士年薪百万落户民办高校”，不到三个月因怀疑“博士身份有假”及“沟通困难”等原因被解聘的新闻。假定
校方(山东外事翻译学院)和“哈佛博士(陈琳)”动机纯正，那么，这件事可以看作是“招聘失败”的一个典型案例。由此给双方带来的损失，要大于使用“猎
头”服务的成本。CEO、CFO等以下层次“关键少数”，主要以组织中的人力资源部门在内部市场和外部市场“发现”为主。有多种方法与技术可供参考。申请
表考察、测试、面谈是三种常见的方法。能力测试、操作技能测试、身体技能测试、人格测试、兴趣测试、成就测试、工作样本测试等，是常用的测试类型。招聘面
谈需要经过准备、实施、评估三道程序。面谈的方法有非结构化、半结构化和结构化等多种类型。 </font></p><p><font face="Verdana" size="4">　　然而，即使经过了多道程序、使用了多种方法与技术精挑细选，也不能保证每次招聘
均万无一失，更不能保证所甄选的员工日后个个称心如意。好在普遍实行试用期和短期合同聘用制度，可以比较有效地降低甄选失误的成本。保证“关键少数”的甄
选质量，除了依赖正式规则，还需要注意避免认识上的误区。举例来说，像大才出自名校、选人用人唯名校是举，就是目前许多企业和事业组织深陷其中的误区。古
语说得好：“夜光之珠，不必出于孟津之河；盈握之壁，不必采于昆仑之山。”(南朝宋·刘义庆《世说新语·言语》)广开才路，招贤纳士，才是寻获“关键少
数”的正确选择。</font></p><p><font face="Verdana" size="4">　　二、千锤百炼，打造核心成员团队</font></p><p><font face="Verdana" size="4">　　发现“关键少数”成员十分重要，但更重要的，是把“关键少数”整合起来，从中选择核心成员，建立决策、管理、创新工作团队(teams)。</font></p><p><font face="Verdana" size="4">　　建立团队，就是要把“每个人的能力、经验、态度和价值交织在一起，创造出一个内
容丰富的结构。”团队结构具有紧密、完整、协调特征，通常可以产生大大优于离散个体或松散群体之和的效率或力量。因而，在日趋激烈和国际化的竞争环境中，
团队正逐步成为经济和社会活动主流的工作方式。</font></p><p><font face="Verdana" size="4">　　一个组织的存在与发展，取决于多种内生与外生变量。但是，在决策、管理和创新三个最重要的环节贯彻团队精神，落实团队工作机制，无论对于企业组织还是事业组织，都是成功的必要条件。</font></p><p><font face="Verdana" size="4">　　团队决策是第一步。“一言堂”、“家长制”、“一把手说了算”，是小农经济性质
的决策方式。这种方式，不止流行于计划经济时期，时至今日，在竞争机制、价格制度和权力平衡结构尚未建立或不完善的国有垄断部门、事业单位、私营企业、官
僚化的“群众团体”中，甚至在一些学术团体中，仍然普遍存在着决策权高度集中的现象。决策权高度集中，效率损失通常在所难免，资产流失的概率必然大大增
加。</font></p><p><font face="Verdana" size="4">　　明晰产权边界，建立权力结构平衡的决策团队，实行团队决策，是组织成功的最优选择。</font></p><p><font face="Verdana" size="4">　　同样，在生产要素交易、生产作业、产品营销、人力资源等管理环节，团队工作方式
的收益必然大于非团队方式。技术、工艺与产品创新，是组织核心竞争力的决定因素。在知识分类全面精细化和劳动分工高度专业化的今天，单打独斗、闭门造车，
最终只能以失败告终。配置优质人力资本，建立高效率研发(R&amp;D)团队，强化合作博弈机制，是组织实现创新的必然选择。</font></p><p><font face="Verdana" size="4">　　三、锻炼培训，提高“关键少数”成员的竞争力</font></p><p><font face="Verdana" size="4">　　核心竞争力是组织在激烈的市场竞争中获胜的必要条件。竞争环境的变化，要求组织
不断调整和强化核心竞争力。组织的核心竞争力，表面上看，是体现在产品开发、性能改进和生产成本节约等一系列过程中的领先技术与工艺，但实际上，应该是创
造、掌握和(或)运用技术与工艺的人，即组织中“关键少数”成员所具有的人力资本。</font></p><p><font face="Verdana" size="4">　　人力资本有自学习功能和使用的价值增值性。但是，人力资本的自学习活动，并不一
定沿着组织所希望的方向发展，使用价值的增加也不一定能够满足组织发展的需要。因此，为了保持、扩大或者赢得生存与发展空间，组织必须采取措施，不断提高
“关键少数”成员组织专用性人力资本的竞争力。</font></p><p><font face="Verdana" size="4">　　专用性人力资本，可以通过挑战性实际工作的“锻炼”和专用性技能的“培训”两条
途径来获得。在锻炼与培训过程中，应该注意发挥“皮格马力翁效应 (Pygmalion
effect)”的作用，即要相信、鼓励、支持、肯定受训员工。常对他们说：你行!你能做到!你一定会成功!事实证明，此法可以大大激励员工取得显著的培
训绩效。 </font></p><p><font face="Verdana" size="4">　　在锻炼与培训过程中，更应该注意成本—收益分析，争取收益最大化。如果人力资本
产权关系确定、边界明晰、使用权和收益权的实现有保证，就可以放任“马太效应”，即使强者更强；如果组织对于其所投资人力资本的使用权、收益权实现没有十
分把握，那么，就应该在强化人力资本产权关系的同时，注意采取分散投资策略，避免“把鸡蛋放在一个篮子里”——把锻炼与培训的机会集中于某一位或某几位员
工。因为人力资本质量越好、品位越高，越容易成为“猎头公司”的目标，流失的可能性越大。而一旦流失，将使组织的投资付诸东流。而且，还有可能发生泄露组
织技术或商业秘密的情况，使组织蒙受更大损失。</font></p><p><font face="Verdana" size="4">　　投资“关键少数”成员的人力资本是必要的，但需要建立有效的收益权实现机制，防
止人员流失所带来的损失。在目前的条件下，投资方与被投资方自愿选择，签约投资(与接受组织安排的出国进修、在职专向技能培训的成员事先签订合约)，履约
使用，违约赔偿，应该是组织维护收益权的最佳选择。</font></p><p><font face="Verdana" size="4">　　四、有效激励，强化“关键少数”成员的工作动力</font></p><p><font face="Verdana" size="4">　　按照人力资本产权理论家的观点，组织通过市场交易招募到员工，是获得了在合约期
内以一定代价使用员工人力资本的权利。获得了使用权，并不意味着就可以随心所欲地使用人力资本，就能够享受到人力资本带来的效用。人力资本由唯一的主体
(载体本人)直撩控制、具体操作，任何载体之外的权利主体(包括所有权主体)，只能间接利用。要想比较充分地利用人力资本的价值和使用价值，必须使得载体
本人感受到有强度的激励，产生努力工作的动力。</font></p><p><font face="Verdana" size="4">　　激励根源于需要。当行为主体的需要未满足时，就会出现心理紧张，进而在身体内产
生内驱力，去寻找能够满足需要的目标。目标一旦找到，需要得到满足，心理紧张即告消除。然而，人的需要是无限的，旧的需要得到满足，新的、更高层次的需要
就会产生。需要的层次越高，满足的难度越大，激励的因素越复杂。</font></p><p><font face="Verdana" size="4">　　“关键少数”成员的需要非同一般，按照亚伯拉罕·马斯洛(Abraham
Maslow)的需要层次理论(Hierarchy of Needs
Theory)，应该是达到最高和次高层次的需要——自我实现需要和尊重需要。因此，只有提供满足这两种需要的条件或机会，才可能产生有效激励。这些条件
或机会主要包括：</font></p><p><font face="Verdana" size="4">　　(1)获得荣誉、提升地位、受到尊重；</font></p><p><font face="Verdana" size="4">　　(2)分享决策权、管理权；</font></p><p><font face="Verdana" size="4">　　(3)进修、提高业务水平；</font></p><p><font face="Verdana" size="4">　　(4)确定的、令人满意的个人职业发展计划；</font></p><p><font face="Verdana" size="4">　　(5)发挥潜能、实现个人价值。</font></p><p><font face="Verdana" size="4">　　五、优胜劣汰，动态管理“关键少数”成员团队</font></p><p><font face="Verdana" size="4">　　对组织中的“关键少数”成员和由“关键少数”成员构成的团队，要实行动态管理，即实行优胜劣汰制度。</font></p><p><font face="Verdana" size="4">　　保持组织员工的流动性十分必要。有二位美国学者，从理论上对员工流动的必要性作
了较有说服力解释。一位是心理学家勒温(K．Lewin)。他提出了“场论”，认为个人的工作绩效B，是个人的能力和条件P，以及个人所处环境E(个人的
“场”)的函数：B=f(P，E)。个人与环境之间一般总有一个从相互“适应”到“不适应”的发展过程。由于个人无法左右环境，环境通常也不会因为少数个
人而发生改变，因此，当适应程度下降至不适应程度时，新的环境无论对于个人还是组织都是最佳选择。另一位是卡兹(Katz)。他在大量调查统计的基础上提
出了“组织寿命学说”。他发现，1．5～5年是科研组织的最佳年龄区。期间，科研人员之间信息沟通水平最高，成果最多。之前，“新面孔”之间交流有限；之
后，“老相识”之间“老话”连篇。信息沟通水平下降，组织成果必然减少。解决问题的办法就是人员流动。数年流动一次，一生流动7～ 8次是合理选择。</font></p><p><font face="Verdana" size="4">　　“流水不腐，户枢不蠹”。以绩效考核为依据，对“关键少数”成员群体和核心成员团队实行末位淘汰制或者按比例(比如5％～10％)淘汰制，同时，不断发现、引进优秀成员。这是维持组织人力资本活力，并进而保持组织核心竞争力的必要条件。</font></p><!-- #EndEditable --></div><img src ="http://www.cppblog.com/apollo/aggbug/8000.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/apollo/" target="_blank">笑笑生</a> 2006-05-31 23:06 <a href="http://www.cppblog.com/apollo/articles/8000.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>《写出质量好软件的75条体会》暨答案ZT</title><link>http://www.cppblog.com/apollo/articles/7903.html</link><dc:creator>笑笑生</dc:creator><author>笑笑生</author><pubDate>Tue, 30 May 2006 13:48:00 GMT</pubDate><guid>http://www.cppblog.com/apollo/articles/7903.html</guid><wfw:comment>http://www.cppblog.com/apollo/comments/7903.html</wfw:comment><comments>http://www.cppblog.com/apollo/articles/7903.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/apollo/comments/commentRss/7903.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/apollo/services/trackbacks/7903.html</trackback:ping><description><![CDATA[VM曾经发了篇题为《<a href="http://blog.joycode.com/mvm/posts/21899.aspx">如何用正确的方法来写出质量好的软件的75条体会</a>》的blog，后来他又给出了相应的回答：<a id="_ctl0__ctl3_HomePageDays_DaysList__ctl7_DayItem_DayList__ctl0_TitleUrl" href="http://blog.joycode.com/mvm/posts/22328.aspx">《七十五条》的解释</a> 。而我亦给出了我自己的答案，有些不错，有些差强人意，有些则非常不足了。为便于比较，我的答案附在了MVM答案的后面。
<br /><p>1. 你们的项目组使用源代码管理工具了么？<br />MVM : 应该用。VSS、CVS、PVCS、ClearCase、CCC/Harvest、FireFly都可以。我的选择是VSS。<br /><strong>郁也风</strong> : 公司使用的是VSS，在网上与朋友玩的就是CVS了。 </p><br /><p>2. 你们的项目组使用缺陷管理系统了么？<br />MVM : 应该用。ClearQuest太复杂，我的推荐是BugZilla。<br /><strong>郁也风</strong> : 嫌BugZilla安装太费事，界面太简陋，我选择的是Jira的破解版。</p><br /><p>3. 你们的测试组还在用Word写测试用例么？<br />MVM : 不要用Word写测试用例（Test Case）。应该用一个专门的系统，可以是Test Manager，也可以是自己开发一个ASP.NET的小网站。主要目的是Track和Browse。<br /><strong>郁也风</strong> : 用Word，而且测试工作很是不上台面（中国软件的通病，所以我们公司也没少得了犯）。</p><br /><p>4. 你们的项目组有没有建立一个门户网站？<br />MVM : 要有一个门户网站，用来放Contact Info、Baselined
Schedule、News等等。推荐Sharepoint Portal Server 2003来实现，15分钟就搞定。买不起SPS
2003可以用WSS (Windows Sharepoint Service)。<br /><strong>郁也风</strong> : 没有，不过看你这么介绍，回头试试去。</p><br /><p>5. 你们的项目组用了你能买到最好的工具么？<br />MVM : 应该用尽量好的工具来工作。比如，应该用VS.NET而不是Notepad来写C#。用Notepad写程序多半只是一种炫耀。但也要考虑到经费，所以说是“你能买到最好的”。<br /><strong>郁也风</strong> : 我一向认为所谓的Notepad开发是自虐狂的不良嗜好。我们使用Eclipse，不要钱的，但我认为是java开发最好的工具了。</p><br /><p>6. 你们的程序员工作在安静的环境里么？<br />MVM : 需要安静环境。这点极端重要，而且要保证每个人的空间大于一定面积。<br /><strong>郁也风</strong> : 看来这位兄台是看过人件了，可惜我们公司的办公环境只能说是一般，极为一般。</p><br /><p>7. 你们的员工每个人都有一部电话么？<br />MVM : 需要每人一部电话。而且电话最好是带留言功能的。当然，上这么一套带留言电话系统开销不小。不过至少每人一部电话要有，千万别搞得经常有人站起来喊：“某某某电话”。《人件》里面就强烈谴责这种做法。<br /><strong>郁也风</strong> : 你果然看了人件了，但请认清形式吧，那是美国，这是中国，“中国国情”四个字会噎死你的，现在的实际情况是很多公司都不让用QQ，MSN（肯定包括我们公司了）。</p><br /><p>8. 你们每个人都知道出了问题应该找谁么？<br />MVM : 应该知道。任何一个Feature至少都应该有一个Owner，当然，Owner可以继续Dispatch给其他人。<br /><strong>郁也风</strong> : 我们知道去找谁，但这不代表就能解决问题。</p><br /><p>9. 你遇到过有人说“我以为…”么？<br />MVM : 要消灭“我以为”。Never assume anything。<br /><strong>郁也风</strong> : 我也经常说“我认为”，尤其在我验证之前。当然，我会考虑改正。</p><br /><p>10. 你们的项目组中所有的人都坐在一起么？<br />MVM : 需要。我反对Virtual Team，也反对Dev在美国、Test在中国这种开发方式。能坐在一起就最好坐在一起，好处多得不得了。<br /><strong>郁也风</strong> : 需要，很多问题不是面对面的话，还真无法解决，或是有时候面对面更能开拓思路，也能更好地交互。</p><br /><p>11. 你们的进度表是否反映最新开发进展情况？ <br />MVM : 应该反映。但是，应该用Baseline的方法来管理进度表：维护一份稳定的Schedule，再维护一份最新更改。Baseline的方法也应该用于其它的Spec。Baseline是变更管理里面的一个重要手段。<br /><strong>郁也风</strong> : 这是我一直很头疼的问题，如何维护一个有效的进度表不亚于任何一个模块的开发啊。</p><br /><p>12. 你们的工作量是先由每个人自己估算的么？<br />MVM : 应该让每个人自己估算。要从下而上估算工作量，而不是从上往下分派。除非有其他原因，比如政治任务工期固定等。<br /><strong>郁也风</strong> : 可惜我们的任务多是政治任务，工期固定的就像螺丝钉。</p><br /><p>13. 你们的开发人员从项目一开始就加班么？<br />MVM : 不要这样。不要一开始就搞疲劳战。从项目一开始就加班，只能说明项目进度不合理。当然，一些对日软件外包必须天天加班，那属于剥削的范畴。<br /><strong>郁也风</strong> : 我们加班是很多是因为资源的到位晚导致的，无可奈何。谁都知道问题的所在，谁都找不到解决问题的方法。</p><br /><p>14. 你们的项目计划中Buffer Time是加在每个小任务后面的么？<br />MVM : 不要。Buffer Time加在每个小任务后面，很容易轻易的就被消耗掉。Buffer Time要整段的加在一个Milestone或者checkpoint前面。<br /><strong>郁也风</strong> : 我们尽量这么做了。</p><br /><p>15. 值得再多花一些时间，从95%做到100%好<br />MVM : 值得，非常值得。尤其当项目后期人困马乏的时候，要坚持。这会给产品带来质的区别。<br /><strong>郁也风</strong> : 我们多是在客户的逼迫下完成那最后的5%的。而且100%并不代表Over，而是另一个100%的开始，成就了一个完美的恶性循环。</p><br /><p>16. 登记新缺陷时，是否写清了重现步骤？<br />MVM : 要。这属于Dev和Test之间的沟通手段。面对面沟通需要，详细填写Repro Steps也需要。<br /><strong>郁也风</strong> : 绝对要，理由同上。</p><br /><p>17. 写新代码前会把已知缺陷解决么？<br />MVM : 要。每个人的缺陷不能超过10个或15个，否则必须先解决老的bug才能继续写新代码。<br /><strong>郁也风</strong> : 没别的说的，一定要。</p><br /><p>18. 你们对缺陷的轻重缓急有事先的约定么？<br />MVM : 必须有定义。Severity要分1、2、3，约定好：蓝屏和Data Lost算Sev 1，Function Error算Sev 2，界面上的算Sev 3。但这种约定可以根据产品质量现状适当进行调整。<br /><strong>郁也风</strong> : 知道需要，但是做的相当不够，需要努力改进。</p><br /><p>19. 你们对意见不一的缺陷有三国会议么？<br />MVM : 必须要有。要有一个明确的决策过程。这类似于CCB (Change Control Board)的概念。<br /><strong>郁也风</strong> : 要由最后拍板的。而且不能陷入争论的泥淖。</p><br /><p>20. 所有的缺陷都是由登记的人最后关闭的么？<br />MVM : Bug应该由Opener关闭。Dev不能私自关闭Bug。<br /><strong>郁也风</strong> : 同意。</p><br /><p>21. 你们的程序员厌恶修改老的代码么？<br />MVM : 厌恶是正常的。解决方法是组织Code Review，单独留出时间来。XP也是一个方法。<br /><strong>郁也风</strong> : Code Review？我们老板不喜欢。</p><br /><p>22. 你们项目组有Team Morale Activity么？<br />MVM : 每个月都要搞一次，吃饭、唱歌、Outing、打球、开卡丁车等等，一定要有。不要剩这些钱。<br /><strong>郁也风</strong> : 这点绝对不会少的，至少我带过的团队的凝聚力还是不错的。</p><br /><p>23. 你们项目组有自己的Logo么？<br />MVM : 要有自己的Logo。至少应该有自己的Codename。<br /><strong>郁也风</strong> : 没想过，今天头要搞个我们部门的文化衫，我强烈反对了。不过Logo可以考虑。</p><br /><p>24. 你们的员工有印有公司Logo的T-Shirt么？<br />MVM : 要有。能增强归属感。当然，T-Shirt要做的好看一些，最好用80支的棉来做。别没穿几次就破破烂烂的。<br /><strong>郁也风</strong> : 哦，前一个我说了，我反对了。我不喜欢千人一面的感觉。</p><br /><p>25. 总经理至少每月参加次项目组会议<br />MVM : 要的。要让team member觉得高层关注这个项目。<br /><strong>郁也风</strong> : 好像是个不可能完成的任务。不知别的公司如何。</p><br /><p>26. 你们是给每个Dev开一个分支么？<br />MVM : 反对。Branch的管理以及Merge的工作量太大，而且容易出错。<br /><strong>郁也风</strong> : 反对，管理困难，也没有必要，可以加Lable。</p><br /><p>27. 有人长期不Check-In代码么？<br />MVM : 不可以。对大部分项目来说，最多两三天就应该Check-In。<br /><strong>郁也风</strong> : 不可以，我每天都监控VSS的。</p><br /><p>28. 在Check-In代码时都填写注释了么？<br />MVM : 要写的，至少一两句话，比如“解决了Bug No.225”。如果往高处拔，这也算做“配置审计”的一部分。<br /><strong>郁也风</strong> : 要写！</p><br /><p>29. 有没有设定每天Check-In的最后期限？<br />MVM : 要的，要明确Check-In Deadline。否则会Build Break。<br /><strong>郁也风</strong> : 没有，整合就是个明确的Deadline了。</p><br /><p>30. 你们能把所有源码一下子编译成安装文件吗？ <br />MVM : 要的。这是每日编译（Daily Build）的基础。而且必须要能够做成自动的。<br /><strong>郁也风</strong> : 当然，我不喜欢出现源码和类文件不匹配。</p><br /><p>31. 你们的项目组做每日编译么？<br />MVM : 当然要做。有三样东西是软件项目/产品开发必备的：1. bug management; 2. source control; 3. daily build。<br /><strong>郁也风</strong> : 至少项目负责人要做。</p><br /><p>32. 你们公司有没有积累一个项目风险列表？<br />MVM : 要。Risk Inventory。否则，下个项目开始的时候，又只能拍脑袋分析Risk了。<br /><strong>郁也风</strong> : 没有。也是一个需要考虑的内容。</p><br /><p>33. 设计越简单越好<br />MVM : 越简单越好。设计时候多一句话，将来可能就带来无穷无尽的烦恼。应该从一开始就勇敢的砍。这叫scope management。<br /><strong>郁也风</strong> : 不同意，过度简单就成了简陋了。而且什么样的叫简单？没有一个量的界定。设计是需要让别人看明白的。</p><br /><p>34. 尽量利用现有的产品、技术、代码<br />MVM :
千万别什么东西都自己Coding。BizTalk和Sharepoint就是最好的例子，有这两个作为基础，可以把起点提高很多。或者可以尽量多用现成
的Control之类的。或者尽量用XML，而不是自己去Parse一个文本文件；尽量用RegExp，而不是自己从头操作字符串，等等等等。这就是“软
件复用”的体现。<br /><strong>郁也风</strong> : 同意，我的原则是：有稳定的，经过实践验证的开源组件或产品的话，绝对不再自己搭炉灶。</p><br /><p>35. 你们会隔一段时间就停下来夯实代码么？<br />MVM : 要。最好一个月左右一次。传言去年年初Windows组在Stevb的命令下停过一个月增强安全。Btw，“夯”这个字念“hang”，第一声。<br /><strong>郁也风</strong> : 肯定做了，不过可能并不是有意识地去做的。</p><br /><p>36. 你们的项目组每个人都写Daily Report么？<br />MVM : 要写。五分钟就够了，写10句话左右，告诉自己小组的人今天我干了什么。一则为了沟通，二则鞭策自己（要是游手好闲一天，自己都会不好意思写的）。<br /><strong>郁也风</strong> : 这是公司的规定。也是少有的能让我支持的规定。</p><br /><p>37. 你们的项目经理会发出Weekly Report么？<br />MVM : 要。也是为了沟通。内容包括目前进度，可能的风险，质量状况，各种工作的进展等。<br /><strong>郁也风</strong> : 也是公司的规定。</p><br /><p>38. 你们项目组是否至少每周全体开会一次？<br />MVM : 要。一定要开会。程序员讨厌开会，但每个礼拜开会时间加起来至少应该有4小时。包括team meeting, spec review meeting, bug triage meeting。千万别大家闷头写code。<br /><strong>郁也风</strong> : 要，至少这点我们实施的还可以。</p><br /><p>39. 你们项目组的会议、讨论都有记录么？<br />MVM : 会前发meeting request和agenda，会中有人负责主持和记录，会后有人负责发meeting minutes，这都是effective meeting的要点。而且，每个会议都要形成agreements和action items。<br /><strong>郁也风</strong> : 有记录，最后要形成会议纪要的。</p><br /><p>40. 其他部门知道你们项目组在干什么么？<br />MVM : 要发一些Newsflash给整个大组织。Show your team’s value。否则，当你坐在电梯里面，其他部门的人问：“你们在干嘛”，你回答“ABC项目”的时候，别人全然不知，那种感觉不太好。<br /><strong>郁也风</strong> : 我们公司的项目开始时要求所有的技术骨干坐在一起评审的，别人想不知道都难。</p><br /><p>41. 通过Email进行所有正式沟通<br />MVM : Email的好处是免得抵赖。但也要避免矫枉过正，最好的方法是先用电话和当面说，然后Email来确认。<br /><strong>郁也风</strong> : 很少使用Email，更多是当面解决问题，毕竟都在一个办公室。</p><br /><p>42. 为项目组建立多个Mailing Group<br />MVM : 如果在AD+Exchange里面，就建Distribution
List。比如，我会建ABC Project Core Team，ABC Project Dev Team，ABC Project All
Testers，ABC Project Extended
Team等等。这样发起Email来方便，而且能让该收到email的人都收到、不该收到不被骚扰。<br /><strong>郁也风</strong> : 没有这个条件，这个更应该根据项目组的规模来进行吧。</p><br /><p>43. 每个人都知道哪里可以找到全部的文档么？<br />MVM : 应该每个人都知道。这叫做知识管理（Knowledge Management）。最方便的就是把文档放在一个集中的File Share，更好的方法是用Sharepoint。<br /><strong>郁也风</strong> : 所有需要的开发文档都放在一个统一的地方，这是规定。</p><br /><p>44. 你做决定、做变化时，告诉大家原因了么？<br />MVM : 要告诉大家原因。Empower team
member的手段之一是提供足够的information，这是MSF一开篇的几个原则之一。的确如此，tell me why是人之常情，tell
me
why了才能有understanding。中国人做事喜欢搞限制，限制信息，似乎能够看到某一份文件的人就是有身份的人。大错特错。权威、权力，不在于
是不是能access information/data，而在于是不是掌握资源。<br /><strong>郁也风</strong> : 对我们来说，需做变化时，也就是临时会议的需要进行的时候。</p><br /><p>45. Stay agile and expect change<br />MVM : 要这样。需求一定会变的，已经写好的代码一定会被要求修改的。做好心理准备，对change不要抗拒，而是expect change。<br /><strong>郁也风</strong> : 这点只能说谈何容易。希望能做到吧。</p><br /><p>46. 你们有没有专职的软件测试人员？<br />MVM : 要有专职测试。如果人手不够，可以peer test，交换了测试。千万别自己测试自己的。<br /><strong>郁也风</strong> : 我们都知道需要，可是往往实际情况差强人意。</p><br /><p>47. 你们的测试有一份总的计划来规定做什么和怎么做么？<br />MVM : 这就是Test Plan。要不要做性能测试？要不要做Usability测试？什么时候开始测试性能？测试通过的标准是什么？用什么手段，自动的还是手动的？这些问题需要用Test Plan来回答。<br /><strong>郁也风</strong> : 知道需要，可实际情况同46。</p><br /><p>48. 你是先写Test Case然后再测试的么？<br />MVM : 应该如此。应该先设计再编程、先test case再测试。当然，事情是灵活的。我有时候在做第一遍测试的同时补上test case。至于先test case再开发，我不喜欢，因为不习惯，太麻烦，至于别人推荐，那试试看也无妨。<br /><strong>郁也风</strong> : 至少目前的习惯和你类似，将来打算试试TDD。</p><br /><p>49. 你是否会为各种输入组合创建测试用例？<br />MVM : 不要，不要搞边界条件组合。当心组合爆炸。有很多test case工具能够自动生成各种边界条件的组合——但要想清楚，你是否有时间去运行那么多test case。<br /><strong>郁也风</strong> : 不会，没那个精力先。</p><br /><p>50. 你们的程序员能看到测试用例么？<br />MVM : 要。让Dev看到Test Case吧。我们都是为了同一个目的走到一起来的：提高质量。<br /><strong>郁也风</strong> : 当然能够，项目中所有的东西都是对大家透明的。</p><br /><p>51. 你们是否随便抓一些人来做易用性测试？ <br />MVM : 要这么做。自己看自己写的程序界面，怎么看都是顺眼的。这叫做审美疲劳——臭的看久了也就不臭了，不方便的永久了也就习惯了。<br /><strong>郁也风</strong> : 我是非常推荐这样的测试的，很多时候，客户也会参与进来。</p><br /><p>52. 你对自动测试的期望正确么？<br />MVM : 别期望太高。依我看，除了性能测试以外，还是暂时先忘掉“自动测试”吧，忘掉WinRunner和LoadRunner吧。对于国内的软件测试的现状来说，只能“矫枉必须过正”了。<br /><strong>郁也风</strong> : 从不期望。</p><br /><p>53. 你们的性能测试是等所有功能都开发完才做的么？<br />MVM : 不能这样。性能测试不能被归到所谓的“系统测试”阶段。早测早改正，早死早升天。<br /><strong>郁也风</strong> : 同意，非常同意。</p><br /><p>54. 你注意到测试中的杀虫剂效应了么？<br />MVM : 虫子有抗药性，Bug也有。发现的新Bug越来越少是正常的。这时候，最好大家交换一下测试的area，或者用用看其他工具和手法，就又会发现一些新bug了。<br /><strong>郁也风</strong> : 同意。</p><br /><p>55. 你们项目组中有人能说出产品的当前整体质量情况么？<br />MVM : 要有。当老板问起这个产品目前质量如何，Test Lead/Manager应该负责回答。<br /><strong>郁也风</strong> : 这当然是TL/PM的活了。</p><br /><p>56. 你们有单元测试么？<br />MVM : 单元测试要有的。不过没有单元测试也不是不可以，我做过没有单元测试的项目，也做成功了——可能是侥幸，可能是大家都是熟手的关系。还是那句话，软件工程是非常实践、非常工程、非常灵活的一套方法，某些方法在某些情况下会比另一些方法好，反之亦然。<br /><strong>郁也风</strong> : 我同意，虽然我们做的很不好。</p><br /><p>57. 你们的程序员是写完代码就扔过墙的么？<br />MVM : 大忌。写好一块程序以后，即便不做单元测试，也应该自己先跑一跑。虽然有了专门的测试人员，做开发的人也不可以一点测试都不做。微软还有Test Release Document的说法，程序太烂的话，测试有权踢回去。<br /><strong>郁也风</strong> : 这样的选手是要挨骂的。</p><br /><p>58. 你们的程序中所有的函数都有输入检查么？<br />MVM : 不要。虽然说做输入检查是write secure code的要点，但不要做太多的输入检查，有些内部函数之间的参数传递就不必检查输入了，省点功夫。同样的道理，未必要给所有的函数都写注释。写一部分主要的就够了。<br /><strong>郁也风</strong> : 更多的时候是在最外面进行检查。太多的检查没有意义。</p><br /><p>59. 产品有统一的错误处理机制和报错界面么？<br />MVM : 要有。最好能有统一的error message，然后每个error
message都带一个error number。这样，用户可以自己根据error number到user
manual里面去看看错误的具体描述和可能原因，就像SQL
Server的错误那样。同样，ASP.NET也要有统一的Exception处理。可以参考有关的Application Block。<br /><strong>郁也风</strong> : 有，这也是j2ee 的规范了。</p><br /><p>60. 你们有统一的代码书写规范么？<br />MVM : 要有。Code Convention很多，搞一份来发给大家就可以了。当然，要是有FxCop这种工具来检查代码就更好了。<br /><strong>郁也风</strong> : 有，首先是IDE的format工具，然后是Checkstyle之类的检查工具在每天的day build之前使用。</p><br /><p>61. 你们的每个人都了解项目的商业意义么？<br />MVM :
要。这是Vision的意思。别把项目只当成工作。有时候要想着自己是在为中国某某行业的信息化作先驱者，或者时不时的告诉team
member，这个项目能够为某某某国家部门每年节省多少多少百万的纳税人的钱，这样就有动力了。平凡的事情也是可以有个崇高的目标的。<br /><strong>郁也风</strong> : 刚才说了，我们的项目的每个部分对每个人都是透明的。</p><br /><p>62. 产品各部分的界面和操作习惯一致么？<br />MVM : 要这样。要让用户觉得整个程序好像是一个人写出来的那样。<br /><strong>郁也风</strong> : 需要，这也是规范的一部分。</p><br /><p>63. 有可以作为宣传亮点的Cool Feature么？<br />MVM : 要。这是增强团队凝聚力、信心的。而且，“一俊遮百丑”，有亮点就可以掩盖一些问题。这样，对于客户来说，会感觉产品从质量角度来说还是acceptable的。或者说，cool feature或者说亮点可以作为质量问题的一个事后弥补措施。<br /><strong>郁也风</strong> : 同意，我前一个项目的界面风格，被客户定为其它项目的参考标准了^_^。</p><br /><p>64. 尽可能缩短产品的启动时间<br />MVM : 要这样。软件启动时间（Start-Up time）是客户对性能好坏的第一印象。<br /><strong>郁也风</strong> : 需要，另外一方面，等待对我们开发方也是一种折磨。</p><br /><p>65. 不要过于注重内在品质而忽视了第一眼的外在印象<br />MVM : 程序员容易犯这个错误：太看重性能、稳定性、存储效率，但忽视了外在感受。而高层经理、客户正相反。这两方面要兼顾，协调这些是PM的工作。<br /><strong>郁也风</strong> : 这也是我在最近的项目中转变最大的方面。</p><br /><p>66. 你们根据详细产品功能说明书做开发么？<br />MVM : 要这样。要有设计才能开发，这是必须的。设计文档，应该说清楚这个产品会怎么运行，应该采取一些讲故事的方法。设计的时候千万别钻细节，别钻到数据库、代码等具体实现里面去，那些是后面的事情，一步步来不能着急。<br /><strong>郁也风</strong> : 我更喜欢迭代，你的设计是根据需求，而需求是来自客户，而客户。。。永远不变的是变化。</p><br /><p>67. 开始开发和测试之前每个人都仔细审阅功能设计么？<br />MVM : 要做。Function Spec review是用来统一思想的。而且，review过以后形成了一致意见，将来再也没有人可以说“你看，当初我就是反对这么设计的，现在吃苦头了吧”<br /><strong>郁也风</strong> : 要做，而且要求每个人都提出意见，这是开发工作开始之前，开始之后，我更倾向于“一言堂”了。</p><br /><p>68. 所有人都始终想着The Whole Image么？<br />MVM : 要这样。项目里面每个人虽然都只是在制造一片叶子，但每个人都应该知道自己在制造的那片叶子所在的树是怎么样子的。我反对软件蓝领，反对过分的把软件制造看成流水线、车间。参见第61条。<br /><strong>郁也风</strong> : 我也同样反对“软件蓝领”，一向唾弃这个学院派制造的名词。我们采取的方式也同样可以参加61。</p><br /><p>69. Dev工作的划分是单纯纵向或横向的么？<br />MVM : 不能单纯的根据功能模块分，或者单纯根据表现层、中间层、数据库层分。我推荐这么做：首先根据功能模块分，然后每个“层”都有一个Owner来Review所有人的设计和代码，保证consistency。 <br /><strong>郁也风</strong> : 同意。</p><br /><p>70. 你们的程序员写程序设计说明文档么？<br />MVM : 要。不过我听说微软的程序员1999年以前也不写。所以说，写不写也不是绝对的，偷懒有时候也是可以的。参见第56条。<br /><strong>郁也风</strong> : 做的不够，我们从来没写过。</p><br /><p>71. 你在招人面试时让他写一段程序么？<br />MVM : 要的。我最喜欢让人做字符串和链表一类的题目。这种题目有很多循环、判断、指针、递归等，既不偏向过于考算法，也不偏向过于考特定的API。<br /><strong>郁也风</strong> : 我认为交流更能看出一个人的实际情况。</p><br /><p>72. 你们有没有技术交流讲座？<br />MVM : 要的。每一两个礼拜搞一次内部的Tech Talk或者Chalk Talk吧。让组员之间分享技术心得，这笔花钱送到外面去培训划算。<br /><strong>郁也风</strong> : 同意，也在着手准备启动。</p><br /><p>73. 你们的程序员都能专注于一件事情么？<br />MVM :
要让程序员专注一件事。例如说，一个部门有两个项目和10个人，一种方法是让10个人同时参加两个项目，每个项目上每个人都花50%时间；另一种方法是5
个人去项目A，5个人去项目B，每个人都100%在某一个项目上。我一定选后面一种。这个道理很多人都懂，但很多领导实践起来就把属下当成可以任意拆分的
资源了。<br /><strong>郁也风</strong> : 我也懂，可实际情况是，现在有4个项目和我有关联。</p><br /><p>74. 你们的程序员会夸大完成某项工作所需要的时间么？<br />MVM : 会的，这是常见的，尤其会在项目后期夸大做某个change所需要的时间，以次来抵制change。解决的方法是坐下来慢慢磨，磨掉程序员的逆反心理，一起分析，并把估算时间的颗粒度变小。<br /><strong>郁也风</strong> : 会的，就算我在上报工作量的时候也会夸大的。对下，我采取的措施同你；上面对我，采取的措施是打折。</p><br /><p>75. 尽量不要用Virtual Heads<br />MVM : 最好不要用Virtual Heads。Virtual
heads意味着resource is not secure，shared
resource会降低resource的工作效率，容易增加出错的机会，会让一心二用的人没有太多时间去review spec、review
design。一个dedicated的人，要强过两个只能投入50%时间和精力的人。我是吃过亏的：7个part
time的tester，发现的Bug和干的活，加起来还不如两个full-time的。参见第73条。73条是针对程序员的，75条是针对
Resource Manager的。<br /><strong>郁也风</strong> : 我想说的同73。</p><img src ="http://www.cppblog.com/apollo/aggbug/7903.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/apollo/" target="_blank">笑笑生</a> 2006-05-30 21:48 <a href="http://www.cppblog.com/apollo/articles/7903.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title> 程序开发团队---团队精神篇 (藏)</title><link>http://www.cppblog.com/apollo/articles/7690.html</link><dc:creator>笑笑生</dc:creator><author>笑笑生</author><pubDate>Fri, 26 May 2006 05:26:00 GMT</pubDate><guid>http://www.cppblog.com/apollo/articles/7690.html</guid><wfw:comment>http://www.cppblog.com/apollo/comments/7690.html</wfw:comment><comments>http://www.cppblog.com/apollo/articles/7690.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/apollo/comments/commentRss/7690.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/apollo/services/trackbacks/7690.html</trackback:ping><description><![CDATA[
		<div class="postTitle"> </div>
		<div class="postText">
				<font size="2">
						<font face="宋体">混了这么多年，从</font>
						<span lang="EN-US" style="COLOR: black; mso-bidi-font-size: 10.5pt">
								<font face="Times New Roman">BOSS</font>
						</span>
						<span style="COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">们口中听到的最多的教诲词语估计就是“团队精神”了，尽管部分</span>
						<span lang="EN-US" style="COLOR: black; mso-bidi-font-size: 10.5pt">
								<font face="Times New Roman">BOSS</font>
						</span>
						<span style="COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">实际上并不了解什么是团队精神，但他们了解中国革命的最终成功是离不开“团结就是力量”这句出自伟人之口的话语，中华民族历来都具有勤劳、团结的优秀品质，小时候在农村混，看到很多团结的现象，家属里的兄弟姐妹无论平时如何地大吵大闹动刀动枪，但一旦外部力量比如别的家属侵犯到本家属，他们会不顾从前，团结起来，一致对外，还有一个村对另一村，平时不管大家有什么矛盾，对另一村时都会团结起来，共同面对敌人，所以农村里经常发生打群架的宏大场面，一个胡同对另一个胡同的小孩，一个村的对另一村的人，场面混乱，男女老少，刀光棍影，乱石飞扬，声势浩大，老谋子什么时候有空来拍一部诸如此类题材的电影，说不定在奥斯卡颁奖大会上能扬眉吐气一把，呵呵。</span>
						<span lang="EN-US" style="COLOR: black; mso-bidi-font-size: 10.5pt">
								<?XML:NAMESPACE PREFIX = O /?>
								<o:p>
								</o:p>
						</span>
						<br />
				</font>
				<p class="MsoNormal" style="MARGIN: 0cm 22pt 0pt 0cm">
						<span lang="EN-US" style="COLOR: black; mso-bidi-font-size: 10.5pt">
								<o:p>
										<font face="Times New Roman" size="2"> </font>
								</o:p>
						</span>
				</p>
				<br />
				<p class="MsoNormal" style="MARGIN: 0cm 22pt 0pt 0cm; TEXT-INDENT: 21pt">
						<font size="2">
								<span style="COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">回到程序开发团体的话题，在以前的工作过程中，我有时会发现一个很怪的现象，一个程序由一个程序员开发时，程序员总是敷衍了事，效果较差，如果由两个人来开发，他们又经常性地互相推诿，效果也不好，由三个或更多的程序员负责时，效果更差，永无成事之日，真是让人烦恼，这不是程序员的技术问题，而更多的是管理问题，比如不科学的分工，或过分强调个人的责任，或程序员之间的性格冲突等原团，导致团队如同一盘散沙，没有凝聚力，这是可怕的事情，直接的结果就是项目的彻底失败。</span>
								<span lang="EN-US" style="COLOR: black; mso-bidi-font-size: 10.5pt">
										<o:p>
										</o:p>
								</span>
						</font>
				</p>
				<br />
				<p class="MsoNormal" style="MARGIN: 0cm 22pt 0pt 0cm">
						<span lang="EN-US" style="COLOR: black; mso-bidi-font-size: 10.5pt">
								<o:p>
										<font face="Times New Roman" size="2"> </font>
								</o:p>
						</span>
				</p>
				<br />
				<p class="MsoNormal" style="MARGIN: 0cm 22pt 0pt 0cm; TEXT-INDENT: 21pt">
						<font size="2">
								<span style="COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">那么如何避免发生以上的情况，如何形成出色的团队精神，提高团队的凝聚力，让团队发挥更大的力量呢？</span>
								<span lang="EN-US" style="COLOR: black; mso-bidi-font-size: 10.5pt">
										<o:p>
										</o:p>
								</span>
						</font>
				</p>
				<br />
				<p class="MsoNormal" style="MARGIN: 0cm 22pt 0pt 0cm">
						<span lang="EN-US" style="COLOR: black; mso-bidi-font-size: 10.5pt">
								<o:p>
										<font face="Times New Roman" size="2"> </font>
								</o:p>
						</span>
				</p>
				<br />
				<p class="MsoNormal" style="MARGIN: 0cm 22pt 0pt 0cm">
						<font size="2">
								<span style="COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">要形成出色的团队精神，我觉得应在工作团队中达到以下几个方面的一致：</span>
								<span lang="EN-US" style="COLOR: black; mso-bidi-font-size: 10.5pt">
										<o:p>
										</o:p>
								</span>
						</font>
				</p>
				<br />
				<p class="MsoNormal" style="MARGIN: 0cm 22pt 0pt 0cm">
						<span lang="EN-US" style="COLOR: black; mso-bidi-font-size: 10.5pt">
								<o:p>
										<font face="Times New Roman" size="2"> </font>
								</o:p>
						</span>
				</p>
				<br />
				<p class="MsoNormal" style="MARGIN: 0cm 22pt 0pt 36pt; TEXT-INDENT: -36pt; mso-list: l0 level1 lfo1; tab-stops: list 36.0pt">
						<font size="2">
								<span lang="EN-US" style="COLOR: black; mso-bidi-font-size: 10.5pt; mso-bidi-font-family: 宋体">
										<span style="mso-list: Ignore">
												<font face="Times New Roman">第一，<span style="FONT: 7pt 'Times New Roman'">   </span></font>
										</span>
								</span>
								<span style="COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">在目标上达成一致；</span>
								<span lang="EN-US" style="COLOR: black; mso-bidi-font-size: 10.5pt">
										<o:p>
										</o:p>
								</span>
						</font>
				</p>
				<br />
				<p class="MsoNormal" style="MARGIN: 0cm 22pt 0pt 0cm">
						<span lang="EN-US" style="COLOR: black; mso-bidi-font-size: 10.5pt">
								<o:p>
										<font face="Times New Roman" size="2"> </font>
								</o:p>
						</span>
				</p>
				<br />
				<p class="MsoNormal" style="MARGIN: 0cm 22pt 0pt 42pt; TEXT-INDENT: 21pt">
						<font size="2">
								<span style="COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">我们都喜欢交一些志同道合的朋友，因为志不同道不合的人，让我们很难沟通与交流，也很难在思想上有火花冒出，共同的目标是一种意境，在程序开发团队中，只要有一名程序员与团队的目标不致，那么该团队的整体水平将受到影响，这种影响不仅仅来自于这个程序员本身，而也来自于团队内部其他程序员的绩效下降，在心理上，其它程序员总能感觉到团队内部的分歧或者某个同伴漠不关心的态度；因此，为了实现团队目标的一致，最好的办法莫过于让程序组自已来确定其目标，这样做的好处有：首先，在目标的制定时的广泛参与，可以确保目标能被大家充分理解，而不是某个</span>
								<span lang="EN-US" style="COLOR: black; mso-bidi-font-size: 10.5pt">
										<font face="Times New Roman">LEADER</font>
								</span>
								<span style="COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的个人行为；另外，目标制定的过程使团队中的每个程序员可以有机会对共同的目标做出公开的承诺，提高目标的可接受性，增加目标的清晰程度。团队成员即程序员广泛也参与到目标的制定、讨论，让他们感受到自已在团队中的重要性，以及团队的成功就是他们自已的成功，以后不论遇到任何困难，他们都会团结一致，勇往直前。</span>
								<span lang="EN-US" style="COLOR: black; mso-bidi-font-size: 10.5pt">
										<o:p>
										</o:p>
								</span>
						</font>
				</p>
				<br />
				<p class="MsoNormal" style="MARGIN: 0cm 22pt 0pt 42pt; TEXT-INDENT: 21pt">
						<span lang="EN-US" style="COLOR: black; mso-bidi-font-size: 10.5pt">
								<o:p>
										<font face="Times New Roman" size="2"> </font>
								</o:p>
						</span>
				</p>
				<br />
				<p class="MsoNormal" style="MARGIN: 0cm 22pt 0pt 36pt; TEXT-INDENT: -36pt; mso-list: l0 level1 lfo1; tab-stops: list 36.0pt">
						<font size="2">
								<span lang="EN-US" style="COLOR: black; mso-bidi-font-size: 10.5pt; mso-bidi-font-family: 宋体">
										<span style="mso-list: Ignore">
												<font face="Times New Roman">第二，<span style="FONT: 7pt 'Times New Roman'">   </span></font>
										</span>
								</span>
								<span style="COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">共同承担责任；</span>
								<span lang="EN-US" style="COLOR: black; mso-bidi-font-size: 10.5pt">
										<o:p>
										</o:p>
								</span>
						</font>
				</p>
				<br />
				<p class="MsoNormal" style="MARGIN: 0cm 22pt 0pt 0cm">
						<span lang="EN-US" style="COLOR: black; mso-bidi-font-size: 10.5pt">
								<o:p>
										<font face="Times New Roman" size="2"> </font>
								</o:p>
						</span>
				</p>
				<br />
				<p class="MsoNormal" style="MARGIN: 0cm 22pt 0pt 42pt; TEXT-INDENT: 21pt">
						<font size="2">
								<span style="COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">建立一个环境，使每个团队成员在这个环境中都感到自已应对团队的绩效负责，除了勇于承担自已的那部分责任，而敢于承担团队的共同责任，遇到问题或困难时，勇于接受挑战，而不是互相推诿，这样，团队的目标才能继续前进。</span>
								<span lang="EN-US" style="COLOR: black; mso-bidi-font-size: 10.5pt">
										<o:p>
										</o:p>
								</span>
						</font>
				</p>
				<br />
				<p class="MsoNormal" style="MARGIN: 0cm 22pt 0pt 36pt">
						<span lang="EN-US" style="COLOR: black; mso-bidi-font-size: 10.5pt">
								<o:p>
										<font face="Times New Roman" size="2"> </font>
								</o:p>
						</span>
				</p>
				<br />
				<p class="MsoNormal" style="MARGIN: 0cm 22pt 0pt 36pt; TEXT-INDENT: -36pt; mso-list: l0 level1 lfo1; tab-stops: list 36.0pt">
						<font size="2">
								<span lang="EN-US" style="COLOR: black; mso-bidi-font-size: 10.5pt; mso-bidi-font-family: 宋体">
										<span style="mso-list: Ignore">
												<font face="Times New Roman">第三，<span style="FONT: 7pt 'Times New Roman'">   </span></font>
										</span>
								</span>
								<span style="COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">一位值得尊重的团队领导；</span>
								<span lang="EN-US" style="COLOR: black; mso-bidi-font-size: 10.5pt">
										<o:p>
										</o:p>
								</span>
						</font>
				</p>
				<br />
				<p class="MsoNormal" style="MARGIN: 0cm 22pt 0pt 0cm">
						<span lang="EN-US" style="COLOR: black; mso-bidi-font-size: 10.5pt">
								<o:p>
										<font face="Times New Roman" size="2"> </font>
								</o:p>
						</span>
				</p>
				<br />
				<p class="MsoNormal" style="MARGIN: 0cm 22pt 0pt 42pt; TEXT-INDENT: 21pt">
						<font size="2">
								<span style="COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">在实际工作中，遇到一名糟糕的主管要比找到一名出色的程序容易得多。在我前些的编程工作中，我的部分领导是通过外部力量而任命的，比如老板觉得那个搞市场或搞工程或搞行政的人很能干，就派他来做程序团队的</span>
								<span lang="EN-US" style="COLOR: black; mso-bidi-font-size: 10.5pt">
										<font face="Times New Roman">LEADER</font>
								</span>
								<span style="COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，事实上他们可能了解一些规范化的玩意，但并不具备为了在开发团队中实施自已的影响所必需的能力，这种</span>
								<span lang="EN-US" style="COLOR: black; mso-bidi-font-size: 10.5pt">
										<font face="Times New Roman">LEADER</font>
								</span>
								<span style="COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">往往喜欢不懂装懂，手提长鞭高高在上，就象一个不可一世的军官那样发号施令，不难想象，极少程序员会服他听他，一种最典型的反应就是“消极怠工”，严重的还会造成</span>
								<span lang="EN-US" style="COLOR: black; mso-bidi-font-size: 10.5pt">
										<font face="Times New Roman">LEADER</font>
								</span>
								<span style="COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">与</span>
								<span lang="EN-US" style="COLOR: black; mso-bidi-font-size: 10.5pt">
										<font face="Times New Roman">PROGRAMMER</font>
								</span>
								<span style="COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的冲突，以致于有一方辞职不干了，多般是程序员，呵呵，因此程序开发团队的</span>
								<span lang="EN-US" style="COLOR: black; mso-bidi-font-size: 10.5pt">
										<font face="Times New Roman">LEADER</font>
								</span>
								<span style="COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">最好是一位具有优秀的开发能力和管理能力的资深程序员，他不仅仅得到团队中程序员的尊敬或崇拜，而且他也可借助自已的专业判断力量，来支撑自已作为领导者的地位，基于对开发技术与流程的了解，他会根据程序员的特点进行科学分工，并在开发过程中作出正确的判断与决策。</span>
								<span lang="EN-US" style="COLOR: black; mso-bidi-font-size: 10.5pt">
										<o:p>
										</o:p>
								</span>
						</font>
				</p>
				<br />
				<p class="MsoNormal" style="MARGIN: 0cm 22pt 0pt 36pt">
						<span lang="EN-US" style="COLOR: black; mso-bidi-font-size: 10.5pt">
								<o:p>
										<font face="Times New Roman" size="2"> </font>
								</o:p>
						</span>
				</p>
				<br />
				<p class="MsoNormal" style="MARGIN: 0cm 22pt 0pt 36pt; TEXT-INDENT: -36pt; mso-list: l0 level1 lfo1; tab-stops: list 36.0pt">
						<font size="2">
								<span lang="EN-US" style="COLOR: black; mso-bidi-font-size: 10.5pt; mso-bidi-font-family: 宋体">
										<span style="mso-list: Ignore">
												<font face="Times New Roman">第四，<span style="FONT: 7pt 'Times New Roman'">   </span></font>
										</span>
								</span>
								<span style="COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">关系融洽；</span>
								<span lang="EN-US" style="COLOR: black; mso-bidi-font-size: 10.5pt">
										<o:p>
										</o:p>
								</span>
						</font>
				</p>
				<br />
				<p class="MsoNormal" style="MARGIN: 0cm 22pt 0pt 0cm">
						<span lang="EN-US" style="COLOR: black; mso-bidi-font-size: 10.5pt">
								<o:p>
										<font face="Times New Roman" size="2"> </font>
								</o:p>
						</span>
				</p>
				<br />
				<p class="MsoNormal" style="MARGIN: 0cm 22pt 0pt 42pt; TEXT-INDENT: 21pt">
						<font size="2">
								<span style="COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">团队成员之间应该优势互补、性格互补、相互支持、善于沟通，彼此之间坦诚相待、相互信任，并勇于表达自我，这样的团队就会齐心协力，成为一个强有力的集体。</span>
								<span lang="EN-US" style="COLOR: black; mso-bidi-font-size: 10.5pt">
										<o:p>
										</o:p>
								</span>
						</font>
				</p>
				<br />
				<p class="MsoNormal" style="MARGIN: 0cm 22pt 0pt 0cm">
						<span lang="EN-US" style="COLOR: black; mso-bidi-font-size: 10.5pt">
								<o:p>
										<font face="Times New Roman" size="2"> </font>
								</o:p>
						</span>
				</p>
				<br />
				<p class="MsoNormal" style="MARGIN: 0cm 22pt 0pt 0cm">
						<font size="2">
								<span lang="EN-US" style="COLOR: black; mso-bidi-font-size: 10.5pt">
										<span style="mso-tab-count: 1">
												<font face="Times New Roman">       </font>
										</span>
								</span>
								<span style="COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">阿蒙从事程序开发工作数年，庆幸曾在若干出色的团队中工作，并学到了许多的知识，体会了很多的感动，感谢过去每一位与我努力奋斗过的程序员，尽管我们中的很多人离理想还很远很远，但只要相信自已，相信团队，执着并努力着，未来一定会更好！祝朋友们五一玩得开心快乐！</span>
						</font>
				</p>
		</div>
<img src ="http://www.cppblog.com/apollo/aggbug/7690.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/apollo/" target="_blank">笑笑生</a> 2006-05-26 13:26 <a href="http://www.cppblog.com/apollo/articles/7690.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>封装变化</title><link>http://www.cppblog.com/apollo/articles/encapsulation.html</link><dc:creator>笑笑生</dc:creator><author>笑笑生</author><pubDate>Thu, 23 Feb 2006 06:52:00 GMT</pubDate><guid>http://www.cppblog.com/apollo/articles/encapsulation.html</guid><wfw:comment>http://www.cppblog.com/apollo/comments/3441.html</wfw:comment><comments>http://www.cppblog.com/apollo/articles/encapsulation.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/apollo/comments/commentRss/3441.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/apollo/services/trackbacks/3441.html</trackback:ping><description><![CDATA[<DIV class=postText><SPAN style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'">
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN style="FONT-SIZE: 10.5pt; FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'; mso-font-kerning: 1.0pt; mso-bidi-font-family: 'Times New Roman'; mso-bidi-font-size: 12.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">软件设计最大的敌人，就是应付需求不断的变化。变化有时候是无穷尽的，于是项目开发就在反复的修改、更新中无限期地延迟交付的日期。变化如悬在头顶的达摩克斯之剑，令许多软件工程专家一筹莫展。正如无法找到解决软件开发的“银弹”，要彻底将变化扼杀在摇篮之中，看来也是不可能完成的任务。那么，积极地面对“变化”，方才是可取的态度。于是，极限编程（XP）的倡导者与布道者Kent Beck提出要“拥抱变化”，从软件工程方法的角度，提出了应对“变化”的解决方案。而本文则试图从软件设计方法的角度，来探讨如何在软件设计过程中，解决未来可能的变化，其方法就是——封装变化。</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN style="FONT-SIZE: 10.5pt; FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'; mso-font-kerning: 1.0pt; mso-bidi-font-family: 'Times New Roman'; mso-bidi-font-size: 12.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">设计模式是“封装变化”方法的最佳阐释。无论是创建型模式、结构型模式还是行为型模式，归根结底都是寻找软件中可能存在的“变化”，然后利用抽象的方式对这些变化进行封装。由于抽象没有具体的实现，就代表了一种无限的可能性，使得其扩展成为了可能。所以，我们在设计之初，除了要实现需求所设定的用例之外，还需要标定可能或已经存在的“变化”之处。封装变化，最重要的一点就是发现变化，或者说是寻找变化。</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN style="FONT-SIZE: 10.5pt; FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'; mso-font-kerning: 1.0pt; mso-bidi-font-family: 'Times New Roman'; mso-bidi-font-size: 12.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">GOF对设计模式的分类，已经彰显了“封装变化”的内涵与精髓。创建型模式的目的就是封装对象创建的变化。例如Factory Method模式和Abstract Factory模式，建立了专门的抽象的工厂类，以此来封装未来对象的创建所引起的可能变化。而Builder模式则是对对象内部的创建进行封装，由于细节对抽象的可替换性，使得将来面对对象内部创建方式的变化，可以灵活的进行扩展或替换。</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN style="FONT-SIZE: 10.5pt; FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'; mso-font-kerning: 1.0pt; mso-bidi-font-family: 'Times New Roman'; mso-bidi-font-size: 12.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">至于结构型模式，它关注的是对象之间组合的方式。本质上说，如果对象结构可能存在变化，主要在于其依赖关系的改变。当然对于结构型模式来说，处理变化的方式不仅仅是封装与抽象那么简单，还要合理地利用继承与聚合的方法，灵活地表达对象之间的依赖关系。例如Decorator模式，描述的就是对象间可能存在的多种组合方式，这种组合方式是一种装饰者与被装饰者之间的关系，因此封装这种组合方式，抽象出专门的装饰对象显然正是“封装变化”的体现。同样地，Bridge模式封装的则是对象实现的依赖关系，而Composite模式所要解决的则是对象间存在的递归关系。</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN style="FONT-SIZE: 10.5pt; FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'; mso-font-kerning: 1.0pt; mso-bidi-font-family: 'Times New Roman'; mso-bidi-font-size: 12.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">行为型模式关注的是对象的行为。行为型模式需要做的是对变化的行为进行抽象，通过封装以达到整个架构的可扩展性。例如策略模式，就是将可能存在变化的策略或算法抽象为一个独立的接口或抽象类，以实现策略扩展的目的。Command模式、State模式、Vistor模式、Iterator模式概莫如是。或者封装一个请求（Command模式），或者封装一种状态（State模式），或者封装“访问”的方式（Visitor模式），或者封装“遍历”算法（Iterator模式）。而这些所要封装的行为，恰恰是软件架构中最不稳定的部分，其扩展的可能性也最大。将这些行为封装起来，利用抽象的特性，就提供了扩展的可能。</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN style="FONT-SIZE: 10.5pt; FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'; mso-font-kerning: 1.0pt; mso-bidi-font-family: 'Times New Roman'; mso-bidi-font-size: 12.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">利用设计模式，通过封装变化的方法，可以最大限度的保证软件的可扩展性。面对纷繁复杂的需求变化，虽然不可能完全解决因为变化带来的可怕梦魇，然而，如能在设计之初预见某些变化，仍有可能在一定程度上避免未来存在的变化为软件架构带来的灾难性伤害。从此点看，虽然没有“银弹”，但从软件设计方法的角度来看，设计模式也是一枚不错的“铜弹”了。<BR></P>
<DIV class=postText>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /><o:p></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'">考虑一个日志记录工具。目前需要提供一个方便的日志</SPAN><SPAN lang=EN-US>API</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'">，使得客户可以轻松地完成日志的记录。该日志要求被记录到指定的文本文件中，记录的内容属于字符串类型，其值由客户提供。我们可以非常容易地定义一个日志对象：</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN lang=EN-US>public class Log</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN lang=EN-US>{</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN lang=EN-US><SPAN style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>public void Write(string target, string log) </SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN lang=EN-US>{</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN lang=EN-US><SPAN style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>//</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'">实现内容</SPAN><SPAN lang=EN-US>;</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN lang=EN-US>}</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN lang=EN-US>}</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'">当客户需要调用日志的功能时，可以创建日志对象，完成日志的记录：</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN lang=EN-US>Log log = new Log();</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN lang=EN-US>log.Write(“error.log”, “log”);</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'">然而随着日志记录的频繁使用，有关日志的文件越来越多，日志的查询与管理也变得越不方便。此时，客户提出，需要改变日志的记录方式，将日志内容写入到指定的数据表中。显然，如果仍然按照前面的设计，具有较大的局限性。</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'">现在我们回到设计之初，想象一下对于日志</SPAN><SPAN lang=EN-US>API</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'">的设计，需要考虑到这样的变化吗？这里存在两种设计理念，即渐进的设计和计划的设计。从本例来分析，要求设计者在设计初就考虑到日志记录方式在未来的可能变化，并不容易。再者，如果在最开始就考虑全面的设计，会产生设计上的冗余。因此，采用计划的设计固然具有一定的前瞻性，但一方面对设计者的要求过高，同时也会产生一些缺陷。那么，采用渐进的设计时，遇到需求变化时，利用重构的方法，改进现有的设计，又需要考虑未来的再一次变化吗？这是一个见仁见智的问题。对于本例而言，我们完全可以直接修改</SPAN><SPAN lang=EN-US>Write()</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'">方法，接受一个类型判断的参数，从而解决此问题。但这样的设计，自然要担负因为未来可能的再一次变化，而导致代码大量修改的危险，例如，我们要求日志记录到指定的</SPAN><SPAN lang=EN-US>Xml</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'">文件中。</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'">所以，变化是完全可能的。在时间和技术能力允许的情况下，我更倾向于将变化对设计带来的影响降低到最低。此时，我们需要封装变化。</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'">在封装变化之前，我们需要弄清楚究竟是什么发生了变化？从需求看，是日志记录的方式发生了变化。从这个概念分析，可能会导致两种不同的结果。一种情形是，我们将日志记录的方式视为一种行为，确切的说，是用户的一种请求。另一种情形则从对象的角度来分析，我们将各种方式的日志看作不同的对象，它们调用接口相同的行为，区别仅在于创建的是不同的对象。前者需要我们封装“用户请求的变化”，而后者需要我们封装“日志对象创建的变化”。</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'">封装“用户请求的变化”，在这里就是封装日志记录可能的变化。也就是说，我们需要把日志记录行为抽象为一个单独的接口，然后才分别定义不同的实现。如图一所示：</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; TEXT-ALIGN: center; mso-char-indent-count: 2.0" align=center><SPAN lang=EN-US><?xml:namespace prefix = v ns = "urn:schemas-microsoft-com:vml" /><v:shapetype id=_x0000_t75 coordsize="21600,21600" o:spt="75" o:preferrelative="t" path="m@4@5l@4@11@9@11@9@5xe" filled="f" stroked="f"><v:stroke joinstyle="miter"></v:stroke><v:formulas><v:f eqn="if lineDrawn pixelLineWidth 0"></v:f><v:f eqn="sum @0 1 0"></v:f><v:f eqn="sum 0 0 @1"></v:f><v:f eqn="prod @2 1 2"></v:f><v:f eqn="prod @3 21600 pixelWidth"></v:f><v:f eqn="prod @3 21600 pixelHeight"></v:f><v:f eqn="sum @0 0 1"></v:f><v:f eqn="prod @6 1 2"></v:f><v:f eqn="prod @7 21600 pixelWidth"></v:f><v:f eqn="sum @8 21600 0"></v:f><v:f eqn="prod @7 21600 pixelHeight"></v:f><v:f eqn="sum @10 21600 0"></v:f></v:formulas><v:path o:extrusionok="f" gradientshapeok="t" o:connecttype="rect"></v:path><o:lock v:ext="edit" aspectratio="t"></o:lock></v:shapetype></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; TEXT-ALIGN: center; mso-char-indent-count: 2.0" align=center><SPAN style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'"><BR><IMG height=239 alt=change01.jpg src="http://wayfarer.cnblogs.com/images/cnblogs_com/wayfarer/change/change01.jpg" width=361 border=0><BR>图一：封装日志记录行为的变化</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'">如果熟悉设计模式，可以看到图一所表示的结构正是</SPAN><SPAN lang=EN-US>Command</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'">模式的体现。由于我们对日志记录行为进行了接口抽象，用户就可以自由地扩展日志记录的方式，只需要实现</SPAN><SPAN lang=EN-US>ILog</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'">接口即可。至于</SPAN><SPAN lang=EN-US>Log</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'">对象，则存在与</SPAN><SPAN lang=EN-US>ILog</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'">接口的弱依赖关系：</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN lang=EN-US>public class Log</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN lang=EN-US>{</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN lang=EN-US><SPAN style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>private ILog log;</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN lang=EN-US><SPAN style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>public Log(ILog log)</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN lang=EN-US><SPAN style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>{</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN lang=EN-US><SPAN style="mso-tab-count: 2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>this.log = log;</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN lang=EN-US><SPAN style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>}</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN lang=EN-US><SPAN style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>public void Write(string target, string logValue)</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN lang=EN-US><SPAN style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>{</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN lang=EN-US><SPAN style="mso-tab-count: 2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>log.Execute(target, logValue);</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN lang=EN-US><SPAN style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>}</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN lang=EN-US>}</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'">我们也可以通过封装“日志对象创建的变化”实现日志</SPAN><SPAN lang=EN-US>API</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'">的可扩展性。在这种情况下，日志会根据记录方式的不同，被定义为不同的对象。当我们需要记录日志时，就创建相应的日志对象，然后调用该对象的</SPAN><SPAN lang=EN-US>Write()</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'">方法，实现日志的记录。此时，可能会发生变化的是需要创建的日志对象，那么要封装这种变化，就可以定义一个抽象的工厂类，专门负责日志对象的创建，如图二所示：</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; TEXT-ALIGN: center; mso-char-indent-count: 2.0" align=center><SPAN lang=EN-US></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'"><BR><IMG height=202 alt=change02.jpg src="http://wayfarer.cnblogs.com/images/cnblogs_com/wayfarer/change/change02.jpg" width=519 border=0><BR>图二：封装日志对象创建的变化</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'">图二是</SPAN><SPAN lang=EN-US>Factory Method</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'">模式的体现，由抽象类</SPAN><SPAN lang=EN-US>LogFactory</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'">专门负责</SPAN><SPAN lang=EN-US>Log</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'">对象的创建。如果用户需要记录相应的日志，例如要求日志记录到数据库，需要先创建具体的</SPAN><SPAN lang=EN-US>LogFactory</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'">对象：</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN lang=EN-US>LogFactory factory = new DBLogFactory();</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'">当在应用程序中，需要记录日志，那么再通过</SPAN><SPAN lang=EN-US>LogFactory</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'">对象来获取新的</SPAN><SPAN lang=EN-US>Log</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'">对象：</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN lang=EN-US>Log log = factory.Create();</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN lang=EN-US>log.Write(“ErrorLog”, “log”);</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'">如果用户需要改变日志记录的方式为文本文件时，仅需要修改</SPAN><SPAN lang=EN-US>LogFactory</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'">对象的创建即可：</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN lang=EN-US>LogFactory factory = new TxtFileLogFactory();</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'">为了更好地理解“封装对象创建的变化”，我们再来看一个例子。假如，我们需要设计一个数据库组件，它能够访问微软的</SPAN><SPAN lang=EN-US>Sql Server</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'">数据库。根据</SPAN><SPAN lang=EN-US>ADO.Net</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'">的知识，我们需要使用如下的对象：</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN lang=EN-US>SqlConnection, SqlCommand, SqlDataAdapter</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'">等。</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'">如果仅就</SPAN><SPAN lang=EN-US>Sql Server</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'">而言，在访问数据库时，我们可以直接创建这些对象：</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN lang=EN-US>SqlConnection connection = new SqlConnection(strConnection);</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN lang=EN-US>SqlCommand command = new SqlCommand(connection);</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN lang=EN-US>SqlDataAdapter adapter = new SqlDataAdapter();</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'">如果在一个数据库组件中，充斥着如上的语句，显然是不合理的。它充满了僵化的坏味道，一旦要求支持其他数据库时，原有的设计就需要彻底的修改，这为扩展带来了困难。</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'">那么我们来思考一下，以上的设计应该做怎样的修改？假定该数据库组件要求或者将来要求支持多种数据库，那么对于</SPAN><SPAN lang=EN-US>Connection</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'">，</SPAN><SPAN lang=EN-US>Command</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'">，</SPAN><SPAN lang=EN-US>DataAdapter</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'">等对象而言，就不能具体化为</SPAN><SPAN lang=EN-US>Sql Server</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'">的对象。也就是说，我们需要为这些对象建立一个继承的层次结构，为他们分别建立抽象的父类，或者接口。然后针对不同的数据库，定义不同的具体类，这些具体类又都继承或实现各自的父类，例如</SPAN><SPAN lang=EN-US>Connection</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'">对象：</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; TEXT-ALIGN: center; mso-char-indent-count: 2.0" align=center><SPAN lang=EN-US></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; TEXT-ALIGN: center; mso-char-indent-count: 2.0" align=center><SPAN style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'"><BR><IMG height=229 alt=change03.jpg src="http://wayfarer.cnblogs.com/images/cnblogs_com/wayfarer/change/change03.jpg" width=333 border=0><BR>图三：</SPAN><SPAN lang=EN-US>Connection</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'">对象的层次结构</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'">我为</SPAN><SPAN lang=EN-US>Connection</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'">对象抽象了一个统一的</SPAN><SPAN lang=EN-US>IConnection</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'">接口，而支持各种数据库的</SPAN><SPAN lang=EN-US>Connection</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'">对象都实现了</SPAN><SPAN lang=EN-US>IConnection</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'">接口。同样的，</SPAN><SPAN lang=EN-US>Command</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'">对象和</SPAN><SPAN lang=EN-US>DataAdapter</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'">对象也采用了相似的结构。现在，我们要创建对象的时候，可以利用多态的原理创建：</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN lang=EN-US>IConnection connection = new SqlConnection(strConnection);</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'">从这个结构可以看到，根据访问的数据库的不同，对象的创建可能会发生变化。也就是说，我们需要设计的数据库组件，以现在的结构来看，仍然存在无法应对对象创建发生变化的问题。利用“封装变化”的原理，我们有必要把创建对象的责任单独抽象出来，以进行有效地封装。例如，如上的创建对象的代码，就应该由专门的对象来负责。我们仍然可以建立一个专门的抽象工厂类</SPAN><SPAN lang=EN-US>DBFactory</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'">，并由它负责创建</SPAN><SPAN lang=EN-US>Connection</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'">，</SPAN><SPAN lang=EN-US>Command</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'">，</SPAN><SPAN lang=EN-US>DataAdapter</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'">对象。至于实现该抽象类的具体类，则与目标对象的结构相同，根据数据库类型的不同，定义不同的工厂类，类图如图四所示：</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; TEXT-ALIGN: center; mso-char-indent-count: 2.0" align=center><SPAN lang=EN-US></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; TEXT-ALIGN: center; mso-char-indent-count: 2.0" align=center><SPAN style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'"><BR><IMG height=287 alt=change04.jpg src="http://wayfarer.cnblogs.com/images/cnblogs_com/wayfarer/change/change04.jpg" width=439 border=0><BR>图四：</SPAN><SPAN lang=EN-US>DBFactory</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'">的类图</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'">图四是一个典型的</SPAN><SPAN lang=EN-US>Abstract Factory</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'">模式的体现。类</SPAN><SPAN lang=EN-US>DBFactory</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'">中的各个方法均为</SPAN><SPAN lang=EN-US>abstract</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'">方法，所以我们也可以用接口来代替该类的定义。继承</SPAN><SPAN lang=EN-US>DBFactory</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'">类的各个具体类，则创建相对应的数据库类型的对象。以</SPAN><SPAN lang=EN-US>SqlDBFactory</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'">类为例，创建各自对象的代码如下：</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN lang=EN-US>public class SqlDBFactory: DBFactory</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN lang=EN-US>{</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN lang=EN-US><SPAN style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>public override IConnection CreateConnection(string strConnection)</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN lang=EN-US><SPAN style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>{</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN lang=EN-US><SPAN style="mso-tab-count: 2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>return new SqlConnection(strConnection);</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN lang=EN-US><SPAN style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>}</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN lang=EN-US><SPAN style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>public override ICommand CreateCommand(IConnection connection)</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN lang=EN-US><SPAN style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>{</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN lang=EN-US><SPAN style="mso-tab-count: 2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>return new SqlCommand(connection);</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN lang=EN-US><SPAN style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>}</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN lang=EN-US><SPAN style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>public override IDataAdapter CreateDataAdapter()</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN lang=EN-US><SPAN style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>{</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN lang=EN-US><SPAN style="mso-tab-count: 2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>return new SqlDataAdapter();</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN lang=EN-US><SPAN style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>}</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN lang=EN-US>}</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'">现在要创建访问</SPAN><SPAN lang=EN-US>Sql Server</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'">数据库的相关对象，就可以利用工厂类来获得。首先，我们可以在程序的初始化部分创建工厂对象：</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN lang=EN-US>DBFactory factory = new SqlDBFactory();</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'">然后利用该工厂对象创建相应的</SPAN><SPAN lang=EN-US>Connection</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'">，</SPAN><SPAN lang=EN-US>Command</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'">等对象：</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN lang=EN-US>IConnection connection = factory.CreateConnection(strConnection);</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN lang=EN-US>ICommand command = factory.CreateCommand(connection);</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'">由于我们利用了封装变化的原理，建立了专门的工厂类，以封装对象创建的变化。可以看到，当我们引入工厂类后，</SPAN><SPAN lang=EN-US>Connection</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'">，</SPAN><SPAN lang=EN-US>Command</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'">等对象的创建语句中，已经成功地消除了其与具体的数据库类型相依赖的关系。在如上的代码中，并未出现</SPAN><SPAN lang=EN-US>Sql</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'">之类的具体类型，如</SPAN><SPAN lang=EN-US>SqlConnection</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'">、</SPAN><SPAN lang=EN-US>SqlCommand</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'">等。也就是说，现在创建对象的方式是完全抽象的，是与具体实现无关的。无论是访问何种数据库，都与这几行代码无关。至于涉及到的数据库类型的变化，则全部抽象到</SPAN><SPAN lang=EN-US>DBFactory</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'">抽象类中了。需要更改访问数据库的类型，我们也只需要修改创建工厂对象的那一行代码，例如将</SPAN><SPAN lang=EN-US>Sql Server</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'">类型修改为</SPAN><SPAN lang=EN-US>Oracle</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'">类型：</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN lang=EN-US>DBFactory factory = new OracleDBFactory();</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'">很显然，这样的方式提高了数据库组件的可扩展性。我们将可能发生变化的部分封装起来，放到程序固定的部分，例如初始化部分，或者作为全局变量，更可以将这些可能发生变化的地方，放到配置文件中，通过读取配置文件的值，创建相对应的对象。如此一来，不需要修改代码，也不需要重新编译，仅仅是修改</SPAN><SPAN lang=EN-US>xml</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'">文件，就能实现数据库类型的改变。例如，我们创建如下的配置文件：</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN lang=EN-US>&lt;appSettings&gt;</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN lang=EN-US><SPAN style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>&lt;add key=”db” value=”SqlDBFactory”/&gt;</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN lang=EN-US>&lt;/appSettings&gt;</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'">创建工厂对象的代码则相应修改如下：</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN lang=EN-US>string factoryName = ConfigurationSettings.AppSettings[“db”].ToString();</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN lang=EN-US>//DBLib</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'">为数据库组件的程序集：</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><SPAN lang=EN-US>DBFactory factory = (DBFactory)Activator.CreateInstance</SPAN><SPAN lang=EN-US>(“DBLib”,factoryName).Unwrap();</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><SPAN style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'">当我们需要将访问的数据库类型修改为</SPAN><SPAN lang=EN-US>Oracle</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'">数据库时，只需要将配置文件中的</SPAN><SPAN lang=EN-US>Value</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'">值修改为“</SPAN><SPAN lang=EN-US>OracleDBFactory</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'">”即可。这种结构具有很好的可扩展性，较好地解决了未来可能发生的需求变化所带来的问题。</SPAN></P></DIV></SPAN></SPAN></DIV><img src ="http://www.cppblog.com/apollo/aggbug/3441.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/apollo/" target="_blank">笑笑生</a> 2006-02-23 14:52 <a href="http://www.cppblog.com/apollo/articles/encapsulation.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>