﻿<?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>BlogJava-BlueDavy之技术Blog-随笔分类-软件工程</title><link>http://www.blogjava.net/BlueDavy/category/1367.html</link><description>不懂理论只懂实战的粗人。</description><language>zh-cn</language><lastBuildDate>Wed, 24 Oct 2007 09:39:50 GMT</lastBuildDate><pubDate>Wed, 24 Oct 2007 09:39:50 GMT</pubDate><ttl>60</ttl><item><title>敏捷实践场景探讨</title><link>http://www.blogjava.net/BlueDavy/archive/2007/10/24/155517.html</link><dc:creator>BlueDavy</dc:creator><author>BlueDavy</author><pubDate>Wed, 24 Oct 2007 03:01:00 GMT</pubDate><guid>http://www.blogjava.net/BlueDavy/archive/2007/10/24/155517.html</guid><wfw:comment>http://www.blogjava.net/BlueDavy/comments/155517.html</wfw:comment><comments>http://www.blogjava.net/BlueDavy/archive/2007/10/24/155517.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/BlueDavy/comments/commentRss/155517.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/BlueDavy/services/trackbacks/155517.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 在我现在的项目中出现了这么两个问题，大家可以来探讨下这样的两个问题的解决方法，:)<br>1、从开发环境到正式环境的部署/校验非常麻烦；<br>2、数据库的频繁移植/校验非常麻烦。<br>我的解决方法：<br>对于上面两个问题，我自己想到的解决方法是：<br>1、建立持续集成机制，编写环境部署脚本和文档，采用这两种方法可保证从开发环境到正式环境的部署是非常简单的；<br>   编写自动验收测试脚本，可以基于Selenium进行编写，这样每次在升级版本的时候就不需要再人工的进行回归测试了，这里面的问题是如何在测试完毕完毕后清除这些测试数据，因为这些测试数据是不能和正式数据共存的。<br>2、建立数据库升级移植机制，每次升级时做增量的升级，不过这需要建立在对原库建立版本记录，这个方法对于我们的项目而言不太可行；<br>   第二种方案就只能每次进行全面的重新移植了，但这个带来的一个巨大问题就是存储过程的重复修改，目前我还没想到什么解决方法，而且；<br>   至于如何校验数据库移植是否成功，我觉得可以建立数据库移植校验的Checkpoint，除了保证数据库结构、数据量等的&nbsp;&nbsp;<a href='http://www.blogjava.net/BlueDavy/archive/2007/10/24/155517.html'>阅读全文</a><img src ="http://www.blogjava.net/BlueDavy/aggbug/155517.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/BlueDavy/" target="_blank">BlueDavy</a> 2007-10-24 11:01 <a href="http://www.blogjava.net/BlueDavy/archive/2007/10/24/155517.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>由PHP CMS看Java业界</title><link>http://www.blogjava.net/BlueDavy/archive/2006/05/25/48183.html</link><dc:creator>BlueDavy</dc:creator><author>BlueDavy</author><pubDate>Thu, 25 May 2006 13:06:00 GMT</pubDate><guid>http://www.blogjava.net/BlueDavy/archive/2006/05/25/48183.html</guid><wfw:comment>http://www.blogjava.net/BlueDavy/comments/48183.html</wfw:comment><comments>http://www.blogjava.net/BlueDavy/archive/2006/05/25/48183.html#Feedback</comments><slash:comments>23</slash:comments><wfw:commentRss>http://www.blogjava.net/BlueDavy/comments/commentRss/48183.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/BlueDavy/services/trackbacks/48183.html</trackback:ping><description><![CDATA[
		<p>最近用了下在php业界中非常出名的wordpress和mambo，使用下来的感觉就是这两个东西易用性真的太好了，功能方面同样非常的强大，实在想不出java界的CMS哪个能和它们进行对比的，引发自己的一些思考，java界的技术人员特别容易以技术观点去评价一个东西的好坏，觉得这就是为什么java界的论坛、CMS这种东西总是无法和其他语言体系的相比的原因，并不是说java界就真的做不出象mambo这样易用的CMS。<br />java界开源的气氛非常好，好处就是促进了整个业界的技术的发展，使得java业界的很多技术思想成为整个软件界的领先思想，弊端就是导致了java界的人员容易陷入技术的盲目追求中，很多时候都脱离了需求，脱离了一套系统真正所需要的东西，这不能不说是java界的悲哀，以java界的技术积累，要做出易用的论坛、CMS并不会比其他语言体系难，也不一定就会慢多少，就象我一直认为的一个熟练的webwork+spring+hibernate的开发人员开发模块的速度必将快过用php、asp.net做开发的人员，但为什么java界在这种类型的系统给人的感觉总是开发效率远低于其他的语言体系呢，这是值得我们去思考的。<br />以响应速度来讲，我觉得发展到今天的java系统速度早就已经不比其他语言体系的慢，应该是快于其他语言体系的系统。<br />当然，不可否认，java语言最大的优势仍然是在企业级的应用上，也许这是一个java界不屑于做CMS、论坛这样东西的理由，但想想，这理由真的够充分吗？？<br />java语言的优势到底在哪？我觉得目前来说java最大的优势仍然是它良好的开源氛围，而这个氛围能够保证java在技术领域一直保持业界的领先地位，但软件是面向服务的，这个思想大家都接受的，^_^，不能总是想着从技术上降低开发的难度，而忽略对于用户而言很重要的易用性这点，易用性其实很多时候除了交互还体现在功能上，这些功能往往是需要有足够的经验积累才能形成出来的，而java界的系统往往是看起来功能强大，而那些功能其实很多未必是用户所想要的，再加上功能强大往往带来的另外一个弊端就是系统过于灵活，没法用，如何将领先的优势转化为真实的东西才是最为关键的....<br /><br />"做到以用户期待的操作方式的系统才是好系统"，呵呵，突然觉得引导用户交互习惯的系统才是真正有潜力的系统，^_^，让用户养成了习惯的系统是一种很可怕的系统，典型的莫过于windows、office<br /><br /><br /></p>
<img src ="http://www.blogjava.net/BlueDavy/aggbug/48183.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/BlueDavy/" target="_blank">BlueDavy</a> 2006-05-25 21:06 <a href="http://www.blogjava.net/BlueDavy/archive/2006/05/25/48183.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>面试杂谈</title><link>http://www.blogjava.net/BlueDavy/archive/2006/05/18/46927.html</link><dc:creator>BlueDavy</dc:creator><author>BlueDavy</author><pubDate>Thu, 18 May 2006 15:57:00 GMT</pubDate><guid>http://www.blogjava.net/BlueDavy/archive/2006/05/18/46927.html</guid><wfw:comment>http://www.blogjava.net/BlueDavy/comments/46927.html</wfw:comment><comments>http://www.blogjava.net/BlueDavy/archive/2006/05/18/46927.html#Feedback</comments><slash:comments>5</slash:comments><wfw:commentRss>http://www.blogjava.net/BlueDavy/comments/commentRss/46927.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/BlueDavy/services/trackbacks/46927.html</trackback:ping><description><![CDATA[
		<p>之前公司招高程，估计面试了不下30个人，觉得面试别人其实也是一种乐趣，和各种不同的人聊天会让自己也学到很多，而且由于还是面试阶段，会更容易进行没有隔阂的技术交流，每次面试其实我都觉得是一次很好的技术交流机会，所以我很乐意面试，同时我也希望被我面试的人能够享受着这种感觉.....<br />每次面试的时候我都是按照对方的简历来问问题，而不是固定的问某些问题，一般来讲是就对方熟悉的技术进行一些了解，并会提出一些问题试着让对方用他熟悉的技术去了解，问完这些后会稍微问些涉及的周边技术，每次面试我都尽力营造不让对方感觉紧张的气氛，要让对方觉得这就是次普通的技术交流而已，没什么的，而且我向来认为面试的时候面试官不是为了去和面试者比较什么，也不是为了显示自己在某些方面多么强，而是应该尽量的去挖掘面试者的能力，让面试者能够在短暂的面试时间内展示自己的能力....<br />面试了这么多人，我觉得在作为面试者，在面试的时候切忌的就是紧张，另外就是在自己不懂的方面随便瞎扯，另外就是要尽量的展示自己熟悉的领域，通常来讲面试官也不会要求你什么都懂....<br />^_^，当然，我知道，大公司面试通常都不是这样，大公司更在乎面试者的基础知识的扎实程度，而作为一些以项目为主的中小公司，我觉得更看重的是面试者的实战能力，另外，作为从业软件行业的人来说，我觉得对于技术的敏感能力、对于行业业务的理解能力、上进心、团队合作能力以及责任心都是我很看重的，尽管这些在面试的时候我还不能很好的去判断，不过也在不断的学习如何去判断，^_^，现在会采取一些场景式的试探方法...</p>
<img src ="http://www.blogjava.net/BlueDavy/aggbug/46927.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/BlueDavy/" target="_blank">BlueDavy</a> 2006-05-18 23:57 <a href="http://www.blogjava.net/BlueDavy/archive/2006/05/18/46927.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>业务的理解以及转化为电脑化操作的能力</title><link>http://www.blogjava.net/BlueDavy/archive/2006/05/16/46402.html</link><dc:creator>BlueDavy</dc:creator><author>BlueDavy</author><pubDate>Tue, 16 May 2006 06:48:00 GMT</pubDate><guid>http://www.blogjava.net/BlueDavy/archive/2006/05/16/46402.html</guid><wfw:comment>http://www.blogjava.net/BlueDavy/comments/46402.html</wfw:comment><comments>http://www.blogjava.net/BlueDavy/archive/2006/05/16/46402.html#Feedback</comments><slash:comments>9</slash:comments><wfw:commentRss>http://www.blogjava.net/BlueDavy/comments/commentRss/46402.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/BlueDavy/services/trackbacks/46402.html</trackback:ping><description><![CDATA[
		<p>以前的自己一直认为做技术化性质的框架、产品是自己的职业发展之路，逐渐的慢慢而改变，发现以前的自己很陷入技术，不断的追求技术，而忽略了软件的本质，软件的本质是为了提高在某种工作上的效率，其实就是让业务能够更高效的完成，而要做到这一点，依赖的重点并不是技术，而是对业务的理解以及将业务转化为电脑化操作的能力，而这点是非技术能解决的，在业界可以看到很多公司，象浪潮，它在烟草行业的成功让人叹服，从技术人员的角度去看它的系统可能会觉得不过尔尔，技术人员往往会认为自己要做出一套这样的系统来不过是小菜而已，但事实是如果让你现在进入烟草行业，也许你做出来的系统从技术上是超越了浪潮，但从业务的理解上以及转化为电脑化操作的能力上能超越浪潮吗？这个不是一两年的业务积累就够的，^_^，从现在国内的软件业界的情况来看，我觉得大部分技术人员的最佳发展方式还是深入理解业务，这才是自己的优势，同时掌握将业务转化为技术的能力，这样的技术人员必将是强势的，这样做出来的东西才是有足够的竞争力的，软件是面向服务的，^_^，不要忘记了这一本质。<br />技术只是一种辅助而已，切勿反客为主.......</p>
<img src ="http://www.blogjava.net/BlueDavy/aggbug/46402.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/BlueDavy/" target="_blank">BlueDavy</a> 2006-05-16 14:48 <a href="http://www.blogjava.net/BlueDavy/archive/2006/05/16/46402.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>软件工程与团队</title><link>http://www.blogjava.net/BlueDavy/archive/2006/03/12/34919.html</link><dc:creator>BlueDavy</dc:creator><author>BlueDavy</author><pubDate>Sun, 12 Mar 2006 08:49:00 GMT</pubDate><guid>http://www.blogjava.net/BlueDavy/archive/2006/03/12/34919.html</guid><wfw:comment>http://www.blogjava.net/BlueDavy/comments/34919.html</wfw:comment><comments>http://www.blogjava.net/BlueDavy/archive/2006/03/12/34919.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.blogjava.net/BlueDavy/comments/commentRss/34919.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/BlueDavy/services/trackbacks/34919.html</trackback:ping><description><![CDATA[<P>每个团队都有它更为适合的软件工程，因此不可一概而论，谈谈自己对于XP以及重型软件工程象CMM这种更为适合的团队。<BR>XP，作为敏捷型软件过程的代表者，我觉得它志在于发挥团队的力量，挖掘团队成员的潜力，共同提升团队成员的能力，快速响应客户的需求，但就自己对XP实施的经验而言，我觉得XP对于团队成员有一定的要求，要求团队成员具备一定的职业水准，象基本的OO思想、TDD、重构技术，同时XP要求团队成员拥有一定的自主能力、足够的上进心以及责任心，如果不是一支这样的团队，实施XP会碰到很多的困难，甚至会导致项目的失败，对于XP，我认为它是一种攻击型的软件过程，^_^<BR>CMM，作为重型软件过程的代表者，它志在强调要做到对于软件过程步骤的可控性、计划性等，它强调的是明确的分工，每个步骤都需要通过一定的标准才算完成，每个步骤的成员和其他步骤的成员的接口为文档，CMM对团队成员的要求则为分开的，各个步骤需要相应的专业化人才，流水线式的作业，对于CMM，我认为它是一种防守型的软件过程。<BR>作为一个技术人员，以我自己对XP和CMM的各自了解来说，我认为一个技术方面的人员会更喜欢XP，因为XP可以让人自由的、快乐的工作着，去享受工作带来的乐趣，而作为公司而言也许会更喜欢CMM，因为公司会认为这样更可控制。<BR>但就像人件而言，我也同样认为软件开发过程中最重要的人，而不是过程，要充分的发挥人的作用，人的作用只有在快乐的、享受的开发环境中才可获得，在那样的情况下往往能发挥人最大的潜力，所以我推崇XP，我向往敏捷式的软件过程。<BR>但事实上来讲，我同样认为，对于一支不具备一定水准的团队来说，XP并不适合，而CMM则更为适合，而且如果团队成员不具备足够的上进心以及钻研精神的话，我同样认为实施CMM更为适合，让整个项目的运作只是变成流水线式的过程，让参与的项目组只是作为工人一般的工作。<BR>想快乐的享受技术带来的乐趣，想快速的响应客户的需求，就让我们拥抱XP吧，而且我认为真正的一支有能力实施XP的团队将是非常幸福的，技术人员的工作将是非常快乐的，同时他们输出的成果必然是高质量、高效的，这样就可以产生“客户满意、公司满意以及员工自己也满意”的良性结果，^_^<BR>但其实我们可以去思考下，国内有多少家公司具备这样的条件去实施XP呢，从业人士中有多少人具备可参与到XP这样的敏捷过程的能力呢....<BR></P><img src ="http://www.blogjava.net/BlueDavy/aggbug/34919.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/BlueDavy/" target="_blank">BlueDavy</a> 2006-03-12 16:49 <a href="http://www.blogjava.net/BlueDavy/archive/2006/03/12/34919.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>既然认为它是好的，就要发挥到极限－系列之三重构</title><link>http://www.blogjava.net/BlueDavy/archive/2006/01/26/29229.html</link><dc:creator>BlueDavy</dc:creator><author>BlueDavy</author><pubDate>Thu, 26 Jan 2006 02:58:00 GMT</pubDate><guid>http://www.blogjava.net/BlueDavy/archive/2006/01/26/29229.html</guid><wfw:comment>http://www.blogjava.net/BlueDavy/comments/29229.html</wfw:comment><comments>http://www.blogjava.net/BlueDavy/archive/2006/01/26/29229.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/BlueDavy/comments/commentRss/29229.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/BlueDavy/services/trackbacks/29229.html</trackback:ping><description><![CDATA[想改良一个烂设计为好设计吗？想增加或维护代码功能时更加简单吗？重构无疑是其中最好的方法之一，既然它是好的，我们就要把它发挥到极限，把重构发挥到极限的方法就像kent beck说的，采用两顶帽子的原则，工作中不断的交换帽子，^_^<BR><BR><FONT color=#008000 size=4><STRONG>重构的好处</STRONG></FONT><BR>1、改良设计<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 设计在一开始不可能做的很完善、很完美，只能是通过在开发的过程不断的去改良和完善，重构就是最好的方法之一，通过重构可将设计快速的改良。<BR>2、增加或维护代码功能时更加的简单<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 重构进行的原因主要还是因为在增加或维护代码时进行的很困难，这个时候重构原有代码就是为了让增加或维护代码功能变得更为的简单。<BR><BR><FONT color=#008000 size=4><STRONG>重构的实现</STRONG></FONT><BR>重构并不是什么新思想、新技术或者新方法，是一个50年代就已经有N多人融入他们的开发中形成习惯的过程，那么重构到底应该怎么去做呢？在这点上我觉得我没有什么多发言的意义，建议大家参考《重构》一书，书中阐述了很多优秀的编码习惯以及重构进行的场合、方法，重构不象设计模式，重构应该被形成习惯融入到开发中去，重构不是一项独立的任务。<BR>重构依赖于良好的测试体系，如之前讲过的单元测试的贯彻。<BR>Java的开发人员更是可以借助IDE来快速的完成重构的工作。<BR><BR><FONT color=#008000 size=4><STRONG>经验总结</STRONG></FONT><BR>慢慢的重构也变成了我的开发习惯，重构保证了简单设计的可行，同时也保证了软件的质量。<BR>有了重构，我在开发中就可以实行”不要求高质量的实现代码，但要求高质量的测试代码“，高质量的实现代码在任务完成时即可通过重构的技术去进行，就像我以前一篇blog提及过的一样，我在代码实现过程采用的就是：<BR>1、编写能够满足测试的代码。<BR>2、对代码进行重构。<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2.1&nbsp;按照《重构》的一些模式进行<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2.2 OO<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2.3 设计模式<BR><img src ="http://www.blogjava.net/BlueDavy/aggbug/29229.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/BlueDavy/" target="_blank">BlueDavy</a> 2006-01-26 10:58 <a href="http://www.blogjava.net/BlueDavy/archive/2006/01/26/29229.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>既然认为它是好的，就要发挥到极限－系列之二单元测试</title><link>http://www.blogjava.net/BlueDavy/archive/2006/01/22/28976.html</link><dc:creator>BlueDavy</dc:creator><author>BlueDavy</author><pubDate>Sun, 22 Jan 2006 15:43:00 GMT</pubDate><guid>http://www.blogjava.net/BlueDavy/archive/2006/01/22/28976.html</guid><wfw:comment>http://www.blogjava.net/BlueDavy/comments/28976.html</wfw:comment><comments>http://www.blogjava.net/BlueDavy/archive/2006/01/22/28976.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.blogjava.net/BlueDavy/comments/commentRss/28976.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/BlueDavy/services/trackbacks/28976.html</trackback:ping><description><![CDATA[既然测试是好的，那就把它发挥到极限。<BR>测试是好的，这一点无可厚非，几乎做软件的人都是认可的，本篇只是谈谈测试中的单元测试部分，单元测试的目的是为了保证类中的方法是符合设计时的需求的，需求驱动似的类实现，^_^<BR><BR><FONT color=#008000 size=4><STRONG>单元测试的好处<BR></STRONG></FONT>1、保证类对于设计以及需求的符合<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在没有单元测试的情况下，其实是很难保证类对于设计以及需求的符合的，很多情况往往会因为开发人员本身的因素将实现代码复杂化，并且编写出很多设计和需求根本不需要的东西。<BR>2、降低调试的复杂性<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 想想在没有单元测试的情况下，调试通常是集成时才做的，这个时候要通过慢慢的跟踪来查找问题的原因，而在web系统中就更痛苦了，总是要重启，如果不想那么痛苦，就采用单元测试吧。<BR>3、减少集成时出错的机率<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;单元测试可保证暴露给外部的API的正确性，减少要通过集成才发现错误的现象。<BR>4、保证重构和简单设计的可行<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 想想，如果没有单元测试，怎么敢对代码做重构呢，如果没有单元测试，简单设计很难通过重构去演变成为将来更好的设计。<BR><BR><STRONG><FONT color=#008000 size=4>单元测试的实现</FONT></STRONG><BR>单元测试的实现采取的方法通常是xUnit，在Java界就是junit了，最重要的仍然不是工具，而是怎么去实现单元测试的方法，测试驱动开发无疑是最佳的编写测试的方法，首先根据设计或需求编写测试，根据测试编写代码，直到测试通过为止。<BR>在代码出现bug时，一定要先把出现bug的情况补充到测试中去，接下来仍然是修改实现代码，直到测试通过。<BR>单元测试编写的原则其实很简单，就是测试一定情况下类的执行是否符合预期。<BR>还是举例来说：<BR>假设需要编写一个根据用户名和密码验证用户的服务，按照TDD我们首先编写单元测试类，我们应该怎么来编写这个单元测试类呢，一般可按照一个这样的步骤：<BR>1、分析类的输入。<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 这点通常是分析类依赖外部什么类，需要在测试类中提前注入。<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 以上面的服务来说，通常需要依赖的是用户的Dao类。<BR>2、分析方法的输入造成的输出的影响。<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 这点通常是分析方法输入的参数对执行结果造成的影响。<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 以上面的服务来说，输入的参数为用户名和密码，这个时候会有几种情况会出现：<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2.1 用户名或密码为null<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在这种情况下，假设期待的输出为false<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2.2 用户名和密码都为null<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在这种情况下，假设期待的输出为false<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2.3&nbsp;输入的用户名和密码在系统中存在<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在这种情况下，假设期待的输出为true<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2.4 用户名或密码其中一项输入不正确，验证不通过<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在这种情况下，假设期待的抛出AuthronizedException<BR>在经过这样的分析后，就可以开始编写测试类了，编写的测试类如下(示例代码而已)：<BR>
<DIV style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><IMG id=Codehighlighter1_46_1309_Open_Image onclick="this.style.display='none'; Codehighlighter1_46_1309_Open_Text.style.display='none'; Codehighlighter1_46_1309_Closed_Image.style.display='inline'; Codehighlighter1_46_1309_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align=top><IMG id=Codehighlighter1_46_1309_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_46_1309_Closed_Text.style.display='none'; Codehighlighter1_46_1309_Open_Image.style.display='inline'; Codehighlighter1_46_1309_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align=top><SPAN style="COLOR: #0000ff">public</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;UserServiceTest&nbsp;</SPAN><SPAN style="COLOR: #0000ff">extends</SPAN><SPAN style="COLOR: #000000">&nbsp;TestCase&nbsp;</SPAN><SPAN id=Codehighlighter1_46_1309_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><IMG src="http://www.blogjava.net/images/dot.gif"></SPAN><SPAN id=Codehighlighter1_46_1309_Open_Text><SPAN style="COLOR: #000000">{<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top><BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">private</SPAN><SPAN style="COLOR: #000000">&nbsp;UserDao&nbsp;dao</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #0000ff">null</SPAN><SPAN style="COLOR: #000000">;<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">private</SPAN><SPAN style="COLOR: #000000">&nbsp;UserService&nbsp;service</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #0000ff">null</SPAN><SPAN style="COLOR: #000000">;<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">private</SPAN><SPAN style="COLOR: #000000">&nbsp;User&nbsp;user</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #0000ff">null</SPAN><SPAN style="COLOR: #000000">;<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;<BR><IMG id=Codehighlighter1_203_269_Open_Image onclick="this.style.display='none'; Codehighlighter1_203_269_Open_Text.style.display='none'; Codehighlighter1_203_269_Closed_Image.style.display='inline'; Codehighlighter1_203_269_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><IMG id=Codehighlighter1_203_269_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_203_269_Closed_Text.style.display='none'; Codehighlighter1_203_269_Open_Image.style.display='inline'; Codehighlighter1_203_269_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">public</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">static</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">&nbsp;main(String[]&nbsp;args)&nbsp;</SPAN><SPAN id=Codehighlighter1_203_269_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><IMG src="http://www.blogjava.net/images/dot.gif"></SPAN><SPAN id=Codehighlighter1_203_269_Open_Text><SPAN style="COLOR: #000000">{<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;junit.textui.TestRunner.run(UserServiceTest.</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">);<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</SPAN></SPAN><SPAN style="COLOR: #000000"><BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top><BR><IMG id=Codehighlighter1_316_563_Open_Image onclick="this.style.display='none'; Codehighlighter1_316_563_Open_Text.style.display='none'; Codehighlighter1_316_563_Closed_Image.style.display='inline'; Codehighlighter1_316_563_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><IMG id=Codehighlighter1_316_563_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_316_563_Closed_Text.style.display='none'; Codehighlighter1_316_563_Open_Image.style.display='inline'; Codehighlighter1_316_563_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">protected</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">&nbsp;setUp()&nbsp;</SPAN><SPAN style="COLOR: #0000ff">throws</SPAN><SPAN style="COLOR: #000000">&nbsp;Exception&nbsp;</SPAN><SPAN id=Codehighlighter1_316_563_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><IMG src="http://www.blogjava.net/images/dot.gif"></SPAN><SPAN id=Codehighlighter1_316_563_Open_Text><SPAN style="COLOR: #000000">{<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">super</SPAN><SPAN style="COLOR: #000000">.setUp();<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dao</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #0000ff">new</SPAN><SPAN style="COLOR: #000000">&nbsp;UserDaoImpl();<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;user</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #0000ff">new</SPAN><SPAN style="COLOR: #000000">&nbsp;User();<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;user.setName(</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">TEST_BLUEDAVY</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">);<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;user.setPass(</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">JERRY</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">);<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dao.save(user);<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;service</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #0000ff">new</SPAN><SPAN style="COLOR: #000000">&nbsp;UserServiceImpl();<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;service.setDao(dao);<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</SPAN></SPAN><SPAN style="COLOR: #000000"><BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top><BR><IMG id=Codehighlighter1_613_671_Open_Image onclick="this.style.display='none'; Codehighlighter1_613_671_Open_Text.style.display='none'; Codehighlighter1_613_671_Closed_Image.style.display='inline'; Codehighlighter1_613_671_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><IMG id=Codehighlighter1_613_671_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_613_671_Closed_Text.style.display='none'; Codehighlighter1_613_671_Open_Image.style.display='inline'; Codehighlighter1_613_671_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">protected</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">&nbsp;tearDown()&nbsp;</SPAN><SPAN style="COLOR: #0000ff">throws</SPAN><SPAN style="COLOR: #000000">&nbsp;Exception&nbsp;</SPAN><SPAN id=Codehighlighter1_613_671_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><IMG src="http://www.blogjava.net/images/dot.gif"></SPAN><SPAN id=Codehighlighter1_613_671_Open_Text><SPAN style="COLOR: #000000">{<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">super</SPAN><SPAN style="COLOR: #000000">.tearDown();<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dao.delete(user);<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</SPAN></SPAN><SPAN style="COLOR: #000000"><BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;<BR><IMG id=Codehighlighter1_722_802_Open_Image onclick="this.style.display='none'; Codehighlighter1_722_802_Open_Text.style.display='none'; Codehighlighter1_722_802_Closed_Image.style.display='inline'; Codehighlighter1_722_802_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><IMG id=Codehighlighter1_722_802_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_722_802_Closed_Text.style.display='none'; Codehighlighter1_722_802_Open_Image.style.display='inline'; Codehighlighter1_722_802_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">public</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">&nbsp;testWhenNameAndPassAreNull()</SPAN><SPAN id=Codehighlighter1_722_802_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><IMG src="http://www.blogjava.net/images/dot.gif"></SPAN><SPAN id=Codehighlighter1_722_802_Open_Text><SPAN style="COLOR: #000000">{<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;assertEquals(</SPAN><SPAN style="COLOR: #0000ff">false</SPAN><SPAN style="COLOR: #000000">,service.login(user.getName(),user.getPass()));<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</SPAN></SPAN><SPAN style="COLOR: #000000"><BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top><BR><IMG id=Codehighlighter1_847_927_Open_Image onclick="this.style.display='none'; Codehighlighter1_847_927_Open_Text.style.display='none'; Codehighlighter1_847_927_Closed_Image.style.display='inline'; Codehighlighter1_847_927_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><IMG id=Codehighlighter1_847_927_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_847_927_Closed_Text.style.display='none'; Codehighlighter1_847_927_Open_Image.style.display='inline'; Codehighlighter1_847_927_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">public</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">&nbsp;testWhenNameOrPassIsNull()</SPAN><SPAN id=Codehighlighter1_847_927_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><IMG src="http://www.blogjava.net/images/dot.gif"></SPAN><SPAN id=Codehighlighter1_847_927_Open_Text><SPAN style="COLOR: #000000">{<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;assertEquals(</SPAN><SPAN style="COLOR: #0000ff">false</SPAN><SPAN style="COLOR: #000000">,service.login(user.getName(),user.getPass()));<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</SPAN></SPAN><SPAN style="COLOR: #000000"><BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;<BR><IMG id=Codehighlighter1_981_1060_Open_Image onclick="this.style.display='none'; Codehighlighter1_981_1060_Open_Text.style.display='none'; Codehighlighter1_981_1060_Closed_Image.style.display='inline'; Codehighlighter1_981_1060_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><IMG id=Codehighlighter1_981_1060_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_981_1060_Closed_Text.style.display='none'; Codehighlighter1_981_1060_Open_Image.style.display='inline'; Codehighlighter1_981_1060_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">public</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">&nbsp;testWhenNameAndPassAreCorrect()</SPAN><SPAN id=Codehighlighter1_981_1060_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><IMG src="http://www.blogjava.net/images/dot.gif"></SPAN><SPAN id=Codehighlighter1_981_1060_Open_Text><SPAN style="COLOR: #000000">{<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;assertEquals(</SPAN><SPAN style="COLOR: #0000ff">true</SPAN><SPAN style="COLOR: #000000">,service.login(user.getName(),user.getPass()));<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</SPAN></SPAN><SPAN style="COLOR: #000000"><BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;<BR><IMG id=Codehighlighter1_1110_1302_Open_Image onclick="this.style.display='none'; Codehighlighter1_1110_1302_Open_Text.style.display='none'; Codehighlighter1_1110_1302_Closed_Image.style.display='inline'; Codehighlighter1_1110_1302_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><IMG id=Codehighlighter1_1110_1302_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1110_1302_Closed_Text.style.display='none'; Codehighlighter1_1110_1302_Open_Image.style.display='inline'; Codehighlighter1_1110_1302_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">public</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">&nbsp;testWhenNameOrPassIsError()</SPAN><SPAN id=Codehighlighter1_1110_1302_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><IMG src="http://www.blogjava.net/images/dot.gif"></SPAN><SPAN id=Codehighlighter1_1110_1302_Open_Text><SPAN style="COLOR: #000000">{<BR><IMG id=Codehighlighter1_1123_1191_Open_Image onclick="this.style.display='none'; Codehighlighter1_1123_1191_Open_Text.style.display='none'; Codehighlighter1_1123_1191_Closed_Image.style.display='inline'; Codehighlighter1_1123_1191_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><IMG id=Codehighlighter1_1123_1191_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1123_1191_Closed_Text.style.display='none'; Codehighlighter1_1123_1191_Open_Image.style.display='inline'; Codehighlighter1_1123_1191_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">try</SPAN><SPAN id=Codehighlighter1_1123_1191_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><IMG src="http://www.blogjava.net/images/dot.gif"></SPAN><SPAN id=Codehighlighter1_1123_1191_Open_Text><SPAN style="COLOR: #000000">{<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;service.login(user.getName(),user.getPass());<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</SPAN></SPAN><SPAN style="COLOR: #000000"><BR><IMG id=Codehighlighter1_1219_1296_Open_Image onclick="this.style.display='none'; Codehighlighter1_1219_1296_Open_Text.style.display='none'; Codehighlighter1_1219_1296_Closed_Image.style.display='inline'; Codehighlighter1_1219_1296_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><IMG id=Codehighlighter1_1219_1296_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1219_1296_Closed_Text.style.display='none'; Codehighlighter1_1219_1296_Open_Image.style.display='inline'; Codehighlighter1_1219_1296_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">catch</SPAN><SPAN style="COLOR: #000000">(Exception&nbsp;e)</SPAN><SPAN id=Codehighlighter1_1219_1296_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><IMG src="http://www.blogjava.net/images/dot.gif"></SPAN><SPAN id=Codehighlighter1_1219_1296_Open_Text><SPAN style="COLOR: #000000">{<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;assertEquals(AuthronizedException.</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">,e.getClass());<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</SPAN></SPAN><SPAN style="COLOR: #000000"><BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</SPAN></SPAN><SPAN style="COLOR: #000000"><BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</SPAN></SPAN></DIV><BR>在编写完测试类后就可以开始编写实现代码了，实现代码在编写的时候很简单，只要能够保证测试通过就完事，在测试通过后可以开始考虑重构的事，重构仍然只要保证测试通过即可，其实这个时候就可以看到，简单设计就变得可行了，因为可以通过重构来提升设计。<BR>如果将来这段代码出现bug，就把bug中的输入情况也编写为一个测试方法进行测试，开始运行就应该和bug一样出现问题，这时只需去修正实现代码，直到测试通过为止，那么bug也就自然被修正了。<BR>简单的单元测试的编写较为简单，复杂的单元测试则可能需要使用Mock来模拟一些环境，Mock方面的工具有很多，大家可以去参考相关的开源工具的网站。&nbsp;&nbsp;&nbsp;&nbsp; <BR><BR><FONT color=#008000 size=4><STRONG>经验总结</STRONG></FONT><BR>对于单元测试通常很多人都有疑问，执行起来的时候经常是不够彻底，特别是在项目时间紧张的情况下，总是觉得编写测试是一种耽误时间的事，其实编写单元测试会为你节省非常多的时间，想想我们大部分的项目都是在集成、修改bug和维护上消耗了大量的时间，既然单元测试这么好，那么我们就实现单元测试吧。<BR>在单元测试中最重要的注意点就是不要依赖于正常的运行数据，所有的数据都要通过代码模拟出来，在测试完毕后清除，避免造成测试对于运行数据的依赖，同时也避免测试数据对于实际运行系统的影响。<BR><img src ="http://www.blogjava.net/BlueDavy/aggbug/28976.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/BlueDavy/" target="_blank">BlueDavy</a> 2006-01-22 23:43 <a href="http://www.blogjava.net/BlueDavy/archive/2006/01/22/28976.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>既然认为它是好的，就要发挥到极限－系列之一持续集成</title><link>http://www.blogjava.net/BlueDavy/archive/2006/01/21/28889.html</link><dc:creator>BlueDavy</dc:creator><author>BlueDavy</author><pubDate>Sat, 21 Jan 2006 11:14:00 GMT</pubDate><guid>http://www.blogjava.net/BlueDavy/archive/2006/01/21/28889.html</guid><wfw:comment>http://www.blogjava.net/BlueDavy/comments/28889.html</wfw:comment><comments>http://www.blogjava.net/BlueDavy/archive/2006/01/21/28889.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/BlueDavy/comments/commentRss/28889.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/BlueDavy/services/trackbacks/28889.html</trackback:ping><description><![CDATA[既然认为它是好的，就要发挥到极限，这是XP的思想。<BR>持续集成无疑是一种非常好的方法，那么在实际的软件开发过程中就应该把它的好发挥到极限，但就我自己经历过的项目以来，只在一个项目中真正的较好的实现了持续集成，不知道大家的情况是怎么样？持续集成的最出名的代表还是MS的Daily Build和冒烟测试了。<BR><BR><STRONG><FONT color=#008000 size=4>持续集成的好处</FONT></STRONG><BR>1、集成变得自动化，不依赖人工。<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 这点好处对于项目是多工程的情况下特别的明显，可以想想，一个项目在多工程的情况下，如果不是 自动集成部署，而需要人手工的话，需要耗费多大的精力，对于单工程的项目来说这点可能不是那么的明显。<BR>2、尽早的发现集成出现的错误。<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在不做持续集成的情况下，项目通常也许是在一个迭代的后期才开始将所有人做的东西进行集成，这个时候才暴露出集成的问题，这个时候再去查就已经非常困难了，因为东西已经很多了，采用持续集成可一定程度减少这个问题，因为持续集成保证了每次都只是小部分的集成，出现问题的话也知道范围被锁定在一个小的部分，而且通常可通过单元测试、功能测试以及集成测试来保证在持续集成进行时尽早发现错误，提醒导致持续集成失败的相关人员。<BR>3、不断的发布新的可运行版本。 <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 这点无论是对于开发人员、项目管理人员和客户带来的好处都是很明显的，对于开发人员来说每天可以通过这个版本看到自己所完成的任务，增强任务完成的满足感；对于项目管理人员来说则可以看到项目的开发在按计划的进行；对于客户来说，可以尽早的看到系统以确定和需求的符合性。<BR><BR><STRONG><FONT color=#008000 size=4>持续集成的实现</FONT><BR></STRONG>既然持续集成这么好，那就在项目中引入持续集成吧，怎么样让项目变得可进行持续集成呢？在开源界中对于持续集成有非常多的良好的支持工具，对于持续集成而言，通常是两个部分：<BR><STRONG><FONT color=#800080>项目自动部署</FONT></STRONG><BR>项目自动部署的工具可选择采用ant或maven，通过将之前项目手动部署的步骤翻译为ant或maven的编译脚本来完成项目的自动部署，当然，这要求对于ant或maven一定程度的熟悉，不过无论是ant还是maven都很容易上手，同时可能会需要对原有工程进行一定的改造，如采用maven一般都需要先把引用的包全部归入一个&nbsp;仓库中。<BR>一个项目的自动部署脚本有些时候可能很简单，有些时候会很复杂，所有有些自动部署脚本真的是可能需要写上个一天，但这是非常值得的。<BR>在自动部署脚本编写完毕后，就可以通过命令或在IDE中直接部署就可完成整个项目的自动部署的动作。<BR>通常项目自动部署的过程需要有这么几步：<BR>1、清空以往的编译。<BR>2、编译项目工程。<BR>3、运行项目工程中的单元测试。<BR>4、部署工程。<BR>5、如为多工程的项目则其他工程也需要重复上面的1、2、3、4步骤。<BR>6、运行功能测试。<BR>7、生成项目网站(以便查看项目的代码情况、测试运行情况等)(可选)。<BR>在自动部署完成时，即可看到项目的运行版本，同时从项目网站中可了解项目的代码情况、测试的运行情况等。<BR><STRONG><FONT color=#800080>项目持续集成</FONT></STRONG><BR>项目持续集成的工具可选择采用luntbuild或cruisecontrol(简称cc)，两者各有千秋，这里不进行比较。项目持续集成需要根据项目所需要的持续集成的情况来编写相应的持续集成脚本(luntbuild可通过web管理界面完成，cc通过编写脚本完成)，通常项目持续集成的脚本会涉及到这些：<BR>1、决定是采用版本管理工具(cvs)感知的方式或每日定时(nightly-build、daily-build)进行持续集成的方式，如决定采用版本管理工具感知的方式，需要确定对于版本管理工具状态获取的频率，如每隔20分钟检查一下是否有更新。<BR>2、持续集成进行，首先是从版本管理工具中获取最新的系统版本，接着就是调用项目自动部署脚本完成项目的自动部署(luntbuild和cc都可直接的调用ant或maven脚本)。<BR>3、合并自动部署后的测试结果到日志中(这点在cc中是要做的，对luntbuild不清楚)。<BR>4、根据自动部署的结果通知相关的人员(email、jabber等等都可以)。<BR>在脚本编写完成后，启动工具项目即可进行持续集成了，可以通过持续集成的网站去查看项目的持续集成情况，其中会包含持续集成执行过程的信息、测试执行的情况、持续集成的统计分析等。<BR>总的来说搭建项目的持续集成环境不会太困难，只要对ant或maven、luntbuild或cc有一定的熟悉，同时明白项目手动部署是如何进行的。<BR>关于工具的使用可以参见几个工具的网站，同时也可<A href="http://www.redsaga.com">满江红.开源</A>参考上的《持续集成实践之cruisecontrol》。<BR><BR><STRONG><FONT color=#008000 size=4>经验总结<BR></FONT></STRONG>从03年开始在自己所经历的项目中就开始实行持续集成，但最终执行的好的只有一个项目，到底是什么原因呢？在这些项目中项目的持续集成环境都是搭建好了的，但就是没执行好，总结下来发现的问题就在于：<BR>1、开发人员没有对持续集成形成足够的重视。<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在几个项目中都是因为持续集成在失败后就没人去调好，因为在开发人员本机运行是好的，放入CVS后由于持续集成进行时的环境不一样确实是有可能会造成失败的，但持续集成失败后无人重视，导致之后的持续集成一直就没什么意义。<BR>2、缺乏足够的测试。<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 导致了项目即使持续集成成功了但可运行版本中仍然是有N多的bug，这说明持续集成是非常需要单元测试、功能测试的支撑的，否则意义将大打折扣。<BR>还有一个是持续集成通常需要耗费很长的时间，web型系统的持续集成通常需要重启web应用服务器；第一个问题倒是可以通过采取增量方式进行持续集成来解决，但由于不是工具直接支持的，所以这块实现还是比较麻烦的；第二个问题就比较麻烦了，反正在我自己经历的项目中这个问题一直没很好的解决，通常是需要在持续集成结束后人工手动的启动web应用服务器(我试着在cc脚本的最后去启动应用服务器，仍然是无效的)。<BR>无论如何，持续集成带来的好处是非常明显的，值得去做，既然是好的，就要把它发挥到极限(对持续集成给予足够的重视、增加测试)，那就让我们在项目中实现持续集成吧！<img src ="http://www.blogjava.net/BlueDavy/aggbug/28889.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/BlueDavy/" target="_blank">BlueDavy</a> 2006-01-21 19:14 <a href="http://www.blogjava.net/BlueDavy/archive/2006/01/21/28889.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>软件开发中的质量保证</title><link>http://www.blogjava.net/BlueDavy/archive/2006/01/03/26435.html</link><dc:creator>BlueDavy</dc:creator><author>BlueDavy</author><pubDate>Tue, 03 Jan 2006 05:36:00 GMT</pubDate><guid>http://www.blogjava.net/BlueDavy/archive/2006/01/03/26435.html</guid><wfw:comment>http://www.blogjava.net/BlueDavy/comments/26435.html</wfw:comment><comments>http://www.blogjava.net/BlueDavy/archive/2006/01/03/26435.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/BlueDavy/comments/commentRss/26435.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/BlueDavy/services/trackbacks/26435.html</trackback:ping><description><![CDATA[<P>如何保证软件的质量一直就是令人头疼的事，这里列了一个自己实际运作的一套用于保证软件质量的体系，还望大家多加指点。<BR>软件的质量保证的关注点主要分为三个方面：<BR>1、对于需求的满足<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;保证软件的设计/实现对于需求是满足的。<BR>2、对于设计的满足<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 保证代码的实现是遵循设计的。<BR>3、代码的质量/性能<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;避免代码实现造成的性能或其他的一些非功能性问题。<BR><BR>为了保证这三点的达成，在实际的项目/产品中采用了一套这样的方法，涉及到的角色有项目经理/开发经理/需求人员/设计人员/开发人员/测试人员：<BR>1、对于需求的满足<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在对于需求的满足上，为避免代码的设计/实现与需求出现大的偏差，要求由需求人员提供验证的场景，同时根据每天早会大家的计划在下班时对计划的完成根据验证场景进行验证。<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 涉及到的角色：需求人员(负责验证场景的提供和需求实现的验证)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 测试人员(根据验证场景进行验证)<BR>2、对于设计的满足<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在对于设计的满足上，为避免出现代码和设计严重偏离的现象，要求设计人员和开发人员频繁的交流，确信开发人员对于设计意图的理解，开发人员在进行代码实现时根据设计人员提供的概要设计完成详细设计，在开发过程中采用TDD的方式进行，确保代码对于设计的符合，这样并不是说设计是不可修改的，但设计和代码的实现需要是可映射的。<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 要求设计人员对开发人员的代码进行频繁的Code Review，确定设计被正常的实现。<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;涉及到的角色：设计人员(提供对于设计验证的方法)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 开发人员(TDD)<BR>3、代码的质量/性能<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 为保证代码的质量，在PP不能完全执行的情况下也要求尽量的多采用PP的方式进行开发，同时通过设计人员对于开发人员以及开发人员互相的Code Review来保证代码的质量。<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 对于代码的性能更多的是通过单元测试执行的耗时来分析。<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 对于设计以及代码进行重构来提升代码的质量和性能。<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 涉及到的角色：设计人员(Code Review、性能分析、设计重构)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;开发人员(PP、Code Review、代码重构)<BR>4、任务完成情况/差距分析<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 为保证软件开发顺利完成，应不断的对任务完成的情况进行差距分析，以尽早做出应对措施并调整。<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 涉及到的角色：项目经理/开发经理<BR><BR>在开发过程中首先要求的是高质量的测试代码(满足需求/设计)&nbsp;，之后才是高质量的实现代码，对于实现代码在有了测试代码的情况下更多的可以通过重构去达到高质量。<BR><BR>总体而言，在软件开发过程中最重要的就是要保证各种角色人员的接口的明确、交流/反馈的畅通，同时采取小步前进的方式，通过重构来达到目标。</P><img src ="http://www.blogjava.net/BlueDavy/aggbug/26435.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/BlueDavy/" target="_blank">BlueDavy</a> 2006-01-03 13:36 <a href="http://www.blogjava.net/BlueDavy/archive/2006/01/03/26435.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>从足球赛谈软件开发</title><link>http://www.blogjava.net/BlueDavy/archive/2006/01/01/26282.html</link><dc:creator>BlueDavy</dc:creator><author>BlueDavy</author><pubDate>Sun, 01 Jan 2006 13:32:00 GMT</pubDate><guid>http://www.blogjava.net/BlueDavy/archive/2006/01/01/26282.html</guid><wfw:comment>http://www.blogjava.net/BlueDavy/comments/26282.html</wfw:comment><comments>http://www.blogjava.net/BlueDavy/archive/2006/01/01/26282.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.blogjava.net/BlueDavy/comments/commentRss/26282.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/BlueDavy/services/trackbacks/26282.html</trackback:ping><description><![CDATA[昨晚看切尔西的比赛的时候突然联想到了软件开发，呵呵，来看足球赛：<BR>1、根据比赛双方的实力、主客场、天气等等各方面因素来比赛双方都会制定自己的目标，战平、胜或别的目标。<BR>2、需要在有限的时间内(90分钟)达成目标。<BR>3、多种角色构成。(守门员、后卫、中场、前锋)<BR>4、一定的阵型(4-3-3、4-4-2)和战术(防守反击、短传渗透、长传冲吊)。<BR>5、多变的形式以及多种不定因素(裁判、球员状态等)。<BR><BR>球赛的整个过程需要由整个队共同努力去完成，而教练负责对于全局的把握、战术的调整等。<BR>软件开发和足球赛有很多类似的情况，也是在一定的时间内由多人协作共同去完成目标，在完成目标的过程中会碰到多种不定的因素和多变的需求，通过架构来制定开发过程的阵型，通过引入模式来作为实现目标的战术。<BR><BR>软件开发和足球赛一样，人是其中至关重要的因素，一样的阵型、战术在不同的球队中就会产生完全不同的效果，你不能去要求甲级联赛的球员拥有和超级联赛的球员同样的水平，也不能去要求一个球员永远保持良好的竞技状态，同时，阵型、战术直接影响到个体，也许个体的实力很强，但在一个不适合的阵型和战术中是无法发挥的。<BR><BR>从架构层次去看，球赛依靠4-3-3、4-4-2这样的阵型构成其架构，在实现目标的过程中需要保持阵型，在进展的过程根据实际情况进行调整，但不会频繁变化，教练就象一个优秀的架构师，会根据情况来决定出最佳的架构。<BR><BR>从实现角度去看，在球赛进展的过程中球员会采用多种协作模式，撞墙式配合、下底传中等，同时个体也会采用多种模式，穿档过人、人球分过、变向、踩单车等，好的球员能够纯熟的应用模式到合适的环境中去。<BR><BR>从团队管理角度去看，球赛需要多种角色的球员的共同合作，球员的合作是影响目标达成的重要因素。<BR><BR>从个体角度去看，个体的能力、状态以及对于架构的理解将会影响架构的实现和目标的达成。<BR><BR>某种程度上来讲，足球比软件开发更具难度，极为有限的时间，更多角色的合作，更多不定的因素。<img src ="http://www.blogjava.net/BlueDavy/aggbug/26282.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/BlueDavy/" target="_blank">BlueDavy</a> 2006-01-01 21:32 <a href="http://www.blogjava.net/BlueDavy/archive/2006/01/01/26282.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>这样的项目</title><link>http://www.blogjava.net/BlueDavy/archive/2005/12/17/24382.html</link><dc:creator>BlueDavy</dc:creator><author>BlueDavy</author><pubDate>Sat, 17 Dec 2005 09:25:00 GMT</pubDate><guid>http://www.blogjava.net/BlueDavy/archive/2005/12/17/24382.html</guid><wfw:comment>http://www.blogjava.net/BlueDavy/comments/24382.html</wfw:comment><comments>http://www.blogjava.net/BlueDavy/archive/2005/12/17/24382.html#Feedback</comments><slash:comments>7</slash:comments><wfw:commentRss>http://www.blogjava.net/BlueDavy/comments/commentRss/24382.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/BlueDavy/services/trackbacks/24382.html</trackback:ping><description><![CDATA[<P>面临一个这样的项目，项目目标是：<BR>1、提供一个框架，而且对这个框架要求还比较高，属于具备一定技术难度的项目，这样看来可列为研发类。<BR>2、完成一个实际项目的开发工作。<BR>项目团队组成是这样：<BR>1、高级程序员一名，兼任项目的开发经理，程序员一名(对Java不熟)，初级程序员四名(应届大学生)。<BR>在目前项目的进展情况看下来，发现这样的项目目标以及带领一支这样的团队要完成目标真的不容易，很难很难，分析的原因觉得很简单，研发类项目很多时候停留在技术角度的攻关上，需要的是高级技术人员，而同时的实际项目开发工作的那个目标则主要停留在了业务角度上，这个时候要求的是架构的稳定，团队承受高压力的能力以及一定的项目经验，而且我一直觉得在这样时间紧张、团队水平相差较大的情况下至少需要有一个能够顶得住的开发人员，目前在这样的情况下一个架构要同时面对两个这样有一定矛盾的目标，目前情况看来架构的表现并不是非常的好，整个团队在架构的接受上就花了不少的时间，而且在开发过程中仍然需要架构设计师的不断支持，从实际项目的角度去分析这样的架构其实是不成功的，但从研发项目角度去看又是成功的......<BR>自己在面对这样的情况下还是显得有些无能为力，经验不足，自己作为PM同时又作为系统设计师需要保证研发性质部分的完成，这势必要求投入大量的时间去进行研发性质部分的开发工作，而同时为了保证实际项目开发的顺利进展又必须对team给予足够的技术支持，而且实际项目来讲毕竟优先级高，在这样的情况下最后导致的就是研发性质的那个目标进展的比较慢，而同时实际项目的这个目标进展也不是非常的顺利。<BR>不过个人觉得在这样的情况下唯一有利的还是团队的培养，团队在经过一个这样时期的培养后能够较快的提升，也许能够成为后期真正的框架开发的团队，否则以目前团队能力来讲去做框架型的开发几乎是不太可能。</P><img src ="http://www.blogjava.net/BlueDavy/aggbug/24382.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/BlueDavy/" target="_blank">BlueDavy</a> 2005-12-17 17:25 <a href="http://www.blogjava.net/BlueDavy/archive/2005/12/17/24382.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>团队管理漫谈</title><link>http://www.blogjava.net/BlueDavy/archive/2005/12/16/24290.html</link><dc:creator>BlueDavy</dc:creator><author>BlueDavy</author><pubDate>Fri, 16 Dec 2005 13:43:00 GMT</pubDate><guid>http://www.blogjava.net/BlueDavy/archive/2005/12/16/24290.html</guid><wfw:comment>http://www.blogjava.net/BlueDavy/comments/24290.html</wfw:comment><comments>http://www.blogjava.net/BlueDavy/archive/2005/12/16/24290.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.blogjava.net/BlueDavy/comments/commentRss/24290.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/BlueDavy/services/trackbacks/24290.html</trackback:ping><description><![CDATA[<P>项目经过了迭代一阶段，总体来说我对team还是比较满意的，尽管也出现了不少的问题，但在这些问题暴露出来后领导们就认为我这样管理team是不正确的，我对team的过于信任导致了这次迭代一出现了目标偏差的现象，但我个人不这么认为，在团队管理上我一直坚信应该建立在对team的信任以及建立team的一致作战能力、一致荣誉感上，而不是步步对team进行制度性的防范和监控，这个我是不太认同的，尽管这样的做法通常来说确实能得到一个比较好的结果，但是我认为在那样的team中工作是不快乐的，会容易造成team的疲惫感，工作除了付出自己的辛苦得到物质收获外，我觉得最重要的还是让team得到精神上的快乐，我倡导快乐工作。<BR>不过当然，既然暴露出问题，自然值得总结，在总结后发现现在的team确实是有些松散，还不够紧密的团结，重要的是没形成统一的荣誉感，在这样的情况下我仍然认为并不是通过制度、监控等方法去控制team，而是仍然给team一定的空间，简单的说说这次出现的问题和自己的解决思路：<BR>1、<FONT color=#ff0000>迭代版本产生了偏离需求和UI的现象<BR></FONT>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 出现这个现象我觉得最主要的原因是在提炼用户故事时做的不够好，同时在用户故事的录入上的控制<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 也不够好，针对这次出现的现象，我觉得在用户故事上必须表达出一个成功的业务场景的详细描述(通<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 过附带UI来说明)、业务规则的说明以及用户故事验证的说明。<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 判断一个用户故事是否完成的标准就是成功的业务场景的执行、业务规则的满足以及是否能够通过用<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 户故事验证。<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 验证工作由on-site customer做，多数情况下on-site customer就是项目经理、BA或需求分析人员。<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 通过频繁发布的持续集成版本将自己实现的用户故事与用户故事验证人员进行频繁的沟通和交流。<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 开发人员往往对细节不够重视也是造成此现象的原因，开发人员往往只注重主体功能的完成，但把细<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 节却给忽略了，这个在以后的迭代中需要进行纠正，培养开发人员对于用户故事完成的概念的认识。<BR>2、<FONT color=#ff0000>开发人员在实现任务时出现了不知如何下手的现象</FONT><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;造成这种现象的发生我觉得最主要的仍然是CRC设计以及任务分解上出现了问题，按照CRC设计的要<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 求以及任务分解的要求这种现象出现的情况应该是不会发生的，尽管这次team的能力是有些欠缺，但<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CRC设计加上任务分解其实会形成非常明确的详细设计以及如何实现详细设计的任务，在这点上解<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 决方案就是在下一次迭代会议上加强CRC设计以及任务分解这两块，CRC设计一定要能通过情景测<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 试，任务分解一定要分解的足够清晰，让开发人员都能明白是怎么做的，至于碰到难点的地方自然是<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 先安排为Spike任务。<BR>3、<FONT color=#ff0000>开发人员在进行任务跟踪时出现偏离的现象<BR></FONT>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 开发人员仍然没能形成很好的任务跟踪的习惯，这点只能不断的纠正，培养开发人员形成这样的习<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 惯。<BR>4、<FONT color=#ff0000>接口依赖造成的瓶颈现象<BR></FONT>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;这是此次迭代出现的一个较大的问题，未形成一个迭代中的接口依赖的全貌图，导致了在任务分配后<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 接口依赖常常集中在一个人的身上，出现了瓶颈现象，这点在第二个迭代中需要改进，增加整个迭代<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 的接口依赖图，这个可根据CRC设计提取形成。<BR>5、<FONT color=#ff0000>任务自行挑选造成的任务完成有难度的现象<BR></FONT>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 此次迭代中出现了这个现象，部分人员挑选了超过其能力很多的任务，最后导致了任务完成的过程中<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 出现了很多的问题，这个我仍然觉得一方面是CRC设计的问题，另一方面是缺少PP的原因。<BR>6、<FONT color=#ff0000>持续集成失败次数过多的现象</FONT><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;此次迭代中造成持续集成失败的原因竟然多是测试代码编写的不正确以及测试代码对于运行数据的依<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 赖，这个我在项目总结会议上进行了讲解，由于这个项目压力太大，而且team能力确实有些不足，所<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 以我未强制执行TDD，不过仍然极度鼓励；第二个原因则是在造成了持续集成失败后未列为最高优先<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 级的事去做。<BR>这次出现这些问题虽然有些是和团队个人相关，但我更多的认为这就是整个团队的责任，而不是某个人的，因此在第二个迭代中我仍然是以培养整个团队的一致荣誉感为首，并且仍然给予团队足够的空间以及充分的信任；而且在第一次迭代中出现这些问题也是好事，毕竟这是一支全新的团队，在团队能力欠缺的情况下我对于团队的表现是比较满意的，在后续我仍然的更多是依靠交流、反馈以及共同作战来弥补上面的问题，而不是依靠制度和强制性的监督。<BR>比较可喜的是Team开始接受整个软件过程，TDD也开始得到接受，而且team成员的能力提升也是比较的明显，这其实对我而言就已经达到目标了，相信这样的一支团队是不会让我失望的。</P><img src ="http://www.blogjava.net/BlueDavy/aggbug/24290.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/BlueDavy/" target="_blank">BlueDavy</a> 2005-12-16 21:43 <a href="http://www.blogjava.net/BlueDavy/archive/2005/12/16/24290.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>反思</title><link>http://www.blogjava.net/BlueDavy/archive/2005/12/01/22161.html</link><dc:creator>BlueDavy</dc:creator><author>BlueDavy</author><pubDate>Thu, 01 Dec 2005 13:33:00 GMT</pubDate><guid>http://www.blogjava.net/BlueDavy/archive/2005/12/01/22161.html</guid><wfw:comment>http://www.blogjava.net/BlueDavy/comments/22161.html</wfw:comment><comments>http://www.blogjava.net/BlueDavy/archive/2005/12/01/22161.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/BlueDavy/comments/commentRss/22161.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/BlueDavy/services/trackbacks/22161.html</trackback:ping><description><![CDATA[今天有人对我现在进行项目的几个方面提出了疑问，认为是几点值得考虑的风险，自己在仔细考虑后觉得确实值得反思：<BR>1、为什么要采用hibernate，采用OO设计取代传统数据库设计？<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;觉得这个问题对我而言没什么可值得仔细思考的部分，采用hibernate利大于弊，这点对我而言毫无疑问，一是因为即使不采用hibernate，在代码中仍然要对获取的resultset做转化为对象的步骤，二是hibernate对通用CRUD的良好支持，三是数据库无关性，四是对象关联的支持。<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 但以提问的人的观点来看，一是他个人对于hibernate并不熟，认为他无法掌控，这就是风险，二是他认为采用hibernate反而增加了项目的实现难度。<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 综合自己的观点和提问人的观点来看，觉得在项目中采用什么样的技术才是合适的技术确实是个值得思考的问题，怎么样从可满足项目的多种技术实现方案中进行选择？<BR>2、项目中采用XP是否合适？<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 我采用XP被人置疑的地方竟然是项目成员的交流合作问题...... 这点让我挺震惊的，这点我都不知道到底是我做的不对还是被人误解，至少我认为我现在team的交流绝对比一般重型软件过程的团队交流做的好很多很多，早会、迭代会议、不时的讨论等等，这些交流我觉得应该不会差吧，呵呵，不过被人疑问，我觉得至少就说明自己做的仍然不够好。<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 另外竟然还被看成是不做设计直接编码的行为，在这点上我真的是觉得让别人误解了，CRC设计难道不是设计？？？而且我觉得CRC设计绝对是超越传统的那种做详细设计的方法的。<BR>&nbsp;<BR>总而言之，我觉得有人提出疑问是好事，只有这样才能真正仔细的去反思自己的很多做法。<BR><BR>另外，说说关于TDD，觉得自己现在才是真正的做TDD，今天在给一个同事讲的时候真正的自己也去领悟TDD的好处，在写一个对象的实现的时候，通常会在实现的过程漏掉一些边缘性的检测或别的问题，更突出的就是在集成的时候才发现问题，今天在实践的时候突然觉得TDD的好处就在于迫使了开发人员在写一个对象的实现之前仔细的考虑那个方法的功能、边缘性的一些东西，这个时候通过编写测试代码就完全可以体现了，然后再去写实现其实就比较简单了，把握针对测试写实现的原则，更不用说对于集成测试的好处了，呵呵，这样才能发挥XP的很多优点，比如简单设计、重构、持续集成等等。<img src ="http://www.blogjava.net/BlueDavy/aggbug/22161.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/BlueDavy/" target="_blank">BlueDavy</a> 2005-12-01 21:33 <a href="http://www.blogjava.net/BlueDavy/archive/2005/12/01/22161.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>回顾XP</title><link>http://www.blogjava.net/BlueDavy/archive/2005/11/30/22035.html</link><dc:creator>BlueDavy</dc:creator><author>BlueDavy</author><pubDate>Wed, 30 Nov 2005 13:49:00 GMT</pubDate><guid>http://www.blogjava.net/BlueDavy/archive/2005/11/30/22035.html</guid><wfw:comment>http://www.blogjava.net/BlueDavy/comments/22035.html</wfw:comment><comments>http://www.blogjava.net/BlueDavy/archive/2005/11/30/22035.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/BlueDavy/comments/commentRss/22035.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/BlueDavy/services/trackbacks/22035.html</trackback:ping><description><![CDATA[<P>在项目中正式的执行XP中的过程，除了PP由于暂时没实施，其他的都在实施中，虽然这点会被很多xper说，^_^，其实我也知道PP非常好，毕竟以前经历过，但由于某些原因，在现在的team中我还不好去执行，以后找到机会，呵呵.....<BR>自己接触XP说起来也有两年多了，而且在以前的团队中也是采用这样的过程，但现在自己带team真的执行的时候却发现碰到一些问题，一方面可能是因为自己太久没温习XP，^_^，有些过程都不是那么记得了，另一方面是在执行的时候有些步骤确实不好走，在这样的情况下，回顾了手头的几篇XP的文档，从XP中对于整个软件过程的推行来看自己实施过程中的问题。<BR>XP中对于整个软件过程的推行是这样的：<BR>1、和客户一起分析需求，产生User Story，User Story的定义为用户对于需求的一段描述。<BR><FONT style="BACKGROUND-COLOR: #ffffff" color=#ff0000>实际执行情况：由PM充当客户，由Team Leader根据PM的描述进行User Story的编写，而且由于User Story的定义不是那么明确，实际执行过程中有些迷惑，在这点上我现在的定义就是一个不可分解的独立、成功业务场景，此场景由场景过程和业务规则共同构成，现在的做法是根据Use Case，拿出其中那些不可分解的独立、成功的业务场景作为用户故事。</FONT><BR>2、由团队中的Senior成员对User Story进行完成时间以及技术风险的评估，同时再给团队中的Junior成员对User Story进行完成时间以及技术风险的评估，最后合并两人的取平均值构成此User Story的完成时间以及技术风险的评估，如此时产生的User Story大于三周，则进行分解，如小于一周则进行合并。(注: 如出现无法评估的User Story，先进行Spike)<BR><FONT color=#ff0000>实际执行情况：之前对此过程不够明确，所以没有这么做，觉得以后可以考虑执行，不过疑问就在于Junior能做出评估吗？</FONT><BR>3、由客户对用户故事进行商业价值以及商业风险的评估。<BR><FONT color=#ff0000>实际执行情况：恩，这步可行。</FONT><BR>4、根据用户故事的技术风险、完成时间评估、商业价值、商业风险的评估来制定发布计划，制定的原则为商业价值优先。<BR><FONT color=#ff0000>实际执行情况：由于现在缺少步骤2，所以只是依照商业价值来制定。</FONT><BR>5、根据发布计划以及用户故事团队共同想出系统隐喻。<BR><FONT color=#ff0000>实际执行情况：我认为系统隐喻其实就是架构设计，在这个步骤上在team中由架构设计小组完成。</FONT><BR>6、根据发布计划制定迭代目标以及迭代计划，迭代控制在1－－3周。<BR><FONT color=#ff0000>实际执行情况：基本是这样的。</FONT><BR>7、Team对迭代中的User Story进行CRC设计和任务分解，任务控制在大于一天小于三天的范围。<BR><FONT color=#ff0000>实际执行情况：由于没做步骤2，在迭代会议上首先是列出User Story，但并不进行完成时间的估计，而是先进行CRC设计，CRC设计中也有个疑点，可能是执行的不好，我对于CRC的做法是拿出用户故事中所出现的名词，并构成名词中的属性和方法，此时进行情景测试，此时自然就受架构约束才能完成，比如UI---&gt;Action---&gt;Service---&gt;Dao这样一种过程才可通过情景测试(根据情景测试来弥补整个过程中不符合的设计)，就产生了CRC设计的UI、业务对象、Action、Service、Dao这些任务，在这个时候出现问题，就是在简单的User Story中这些任务就同样非常简单，甚至所有任务合在一起也才1天的这种情况，这对于XP来说其实是不符合的，这个时候再去做合并任务、合并User Story发现不是那么好做.......</FONT><BR>8、由团队成员自行挑选任务。<BR><FONT color=#ff0000>实际执行情况：完整执行。</FONT><BR>9、任务承担者进行TDD实现，每天挑选Pair一起进行。<BR><FONT color=#ff0000>实际执行情况：TDD方面由于我的理解不是很好，未良好执行，今天专门看了手头XP文档中TDD的部分，发现以前的做法确实很不正确，以后一定好好执行，就像编写一个简单的增加用户这样的方法，在TDD中首先应该考虑这个方法到底有哪些功能，然后在单元测试中进行编写，最后方法的实现完全根据单元测试来实现，而不编写超出单元测试范围的代码，PP由于目前team以及环境的原因，暂未执行，在将来我决定推行。</FONT><BR>10、提交代码进行持续集成。<BR><FONT color=#ff0000>实际执行情况：完整执行，不过缺少TDD其实这块的意义已经不显得那么重要，不过我仍然觉得对于功能测试以及作为一个集成测试环境来讲非常重要，毕竟这是自动的。</FONT><BR>11、迭代任务完成后发布迭代版本。<BR><FONT color=#ff0000>实际执行情况：完整执行。</FONT><BR>12、进入下一个迭代。<BR>上面只是对XP过程的一个简单描述，XP中还有很多重要的思想和原则都是值得分开了详细阐述和分析的：<BR>简单、交流、反馈、勇气、站立早会、TDD等等。<BR>以后有时间的时候一个一个来写写感触，呵呵。<BR><BR>在目前的团队实施的软件过程情况来看，个人觉得有几个方面是有非常好的效果的：<BR>1、早会。耗不了多长时间却能起到很好的作用。<BR>2、迭代会议。耗费时间是很长，但对于整个团队任务完成的情况来看是非常值得的，增加了团队的交流气氛，从而提升了整个团队的水平，让团队成员自行挑选任务可以让团队成员主动的去提高自己，提高工作方面的兴趣。<BR>3、持续集成。非常有好处，至少避免总是要依靠一个人去做集成，而且项目组所有成员都能看到项目的进展，对于团队来说是种鼓励，呵呵，我在持续集成中还生成项目网站，觉得这个对于项目组以及领导层来说都很有效果。<BR>4、xplanner进行任务跟踪。通过xplanner的任务跟踪提升整个团队对于任务完成时间的评估准确度，同时也比较准确的统计了团队的工作量。<BR><BR>ps：总体看下来，自己在XP整个实施上还是存在很多的问题，要吸取教训，以后努力改进，其实我一直坚持的一点，其实对于一个中小型项目来说，我真的不认为采用什么软件过程必然就是最好的，关键是需要一套适合团队的完整、规范的软件过程，这个很重要。</P><img src ="http://www.blogjava.net/BlueDavy/aggbug/22035.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/BlueDavy/" target="_blank">BlueDavy</a> 2005-11-30 21:49 <a href="http://www.blogjava.net/BlueDavy/archive/2005/11/30/22035.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>碰到关心技术的客户咋办？</title><link>http://www.blogjava.net/BlueDavy/archive/2005/11/10/19198.html</link><dc:creator>BlueDavy</dc:creator><author>BlueDavy</author><pubDate>Thu, 10 Nov 2005 09:55:00 GMT</pubDate><guid>http://www.blogjava.net/BlueDavy/archive/2005/11/10/19198.html</guid><wfw:comment>http://www.blogjava.net/BlueDavy/comments/19198.html</wfw:comment><comments>http://www.blogjava.net/BlueDavy/archive/2005/11/10/19198.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/BlueDavy/comments/commentRss/19198.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/BlueDavy/services/trackbacks/19198.html</trackback:ping><description><![CDATA[<P>本来作为客户而言，它需要关心的是自己想基于系统做什么，实现什么样的功能，而不会关心到技术层面，但如果碰到了关心技术的客户怎么办呢，客户关心到你用的是什么平台、什么框架、为什么要用以及它如果要基于平台做自主开发要怎么做，感觉在这种情况下挺棘手的，客户往往就变成了对于你实现需求的技术进行干预，而很多时候又没法向用户解释清楚，而且在这种情况下往往是客户根据你的介绍和讲解来做出基于这样的平台是否能实现他们需求的评估，这就挺难搞了，也许是自己的技术不过关，不过觉得最缺乏的是沟通的方法，大家觉得在这种情况下会有什么比较好的方法呢？求教.......</P><img src ="http://www.blogjava.net/BlueDavy/aggbug/19198.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/BlueDavy/" target="_blank">BlueDavy</a> 2005-11-10 17:55 <a href="http://www.blogjava.net/BlueDavy/archive/2005/11/10/19198.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>公司级技术团队建设</title><link>http://www.blogjava.net/BlueDavy/archive/2005/11/07/18669.html</link><dc:creator>BlueDavy</dc:creator><author>BlueDavy</author><pubDate>Mon, 07 Nov 2005 15:54:00 GMT</pubDate><guid>http://www.blogjava.net/BlueDavy/archive/2005/11/07/18669.html</guid><wfw:comment>http://www.blogjava.net/BlueDavy/comments/18669.html</wfw:comment><comments>http://www.blogjava.net/BlueDavy/archive/2005/11/07/18669.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/BlueDavy/comments/commentRss/18669.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/BlueDavy/services/trackbacks/18669.html</trackback:ping><description><![CDATA[从公司级来讲，自己的资格是远远的不够，在这里主要也是根据自己的项目经验阐述下自己对中小型企业技术团队的一种观点，个人觉得对于中小型企业来讲三级团队的构成是比较理想的，就是支撑平台团队+应用系统开发团队+实施团队，从三级团队的构成来讲切忌企业的面铺的太广，那这三级团队就很难形成了，但在国内大部分中小型企业仍然处于盈利为上的策略，这也是没办法的，毕竟求生才是最重要的，在这种情况下，我觉得在这样的公司不如干脆由应用系统开发团队+实施团队来组成，而支撑平台则选用开源的或进行采购，当然，选用开源的概念是某个可直接用的或者不需要进行太多集成工作的，这样在公司发展到一定程度的情况下，在适当的时机下再进行升级到三级团队的建设。<BR>觉得现在中国很多中小型企业的问题就在于，既想构成这种三级的团队，但同时又不舍得投入，这样造成的后果其实是不言而喻的。<BR>觉得其实在国外的很多公司的技术团队都是类似这种三级团队的构成，更为优秀的公司则可逐步的脱离为只有支撑平台研发团队，而同时产生了一个新的咨询服务团队，而由别的公司作为应用开发团队+实施团队。<BR>^_^，我个人觉得仍然是中小型企业的定位问题，其实中小型企业的支撑平台的研发并没有想像中的那么的困难，舍得投入招进4--6个比较有经验的人来进行大概4--6个月的研发，当然，这对团队的要求是比较的高，同时需要公司有一定的项目经验积累，并形成公司主营业务的需求，所以一开始就要组成三级团队确实是比较的困难。<BR>但同时在国内的企业中还存在另外的问题，就是对于此类研发性质的项目干系人过于的多，而且关注的人多，很多企业毕竟是从二级团队开始升级为三级团队的，此时带来的问题就是企业内部利益斗争，这个从根本上决定了支撑平台进展的困难，由于没有在外企呆过，不知道国外的企业是否会有这样的问题，呵呵<img src ="http://www.blogjava.net/BlueDavy/aggbug/18669.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/BlueDavy/" target="_blank">BlueDavy</a> 2005-11-07 23:54 <a href="http://www.blogjava.net/BlueDavy/archive/2005/11/07/18669.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>软件过程规范</title><link>http://www.blogjava.net/BlueDavy/archive/2005/11/03/17949.html</link><dc:creator>BlueDavy</dc:creator><author>BlueDavy</author><pubDate>Thu, 03 Nov 2005 05:36:00 GMT</pubDate><guid>http://www.blogjava.net/BlueDavy/archive/2005/11/03/17949.html</guid><wfw:comment>http://www.blogjava.net/BlueDavy/comments/17949.html</wfw:comment><comments>http://www.blogjava.net/BlueDavy/archive/2005/11/03/17949.html#Feedback</comments><slash:comments>6</slash:comments><wfw:commentRss>http://www.blogjava.net/BlueDavy/comments/commentRss/17949.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/BlueDavy/services/trackbacks/17949.html</trackback:ping><description><![CDATA[<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: 150%; TEXT-ALIGN: center" align=center><B style="mso-bidi-font-weight: normal"><SPAN lang=EN-US style="FONT-SIZE: 16pt; LINE-HEIGHT: 150%"><SPAN style="mso-field-code: ' TITLE   \* MERGEFORMAT '"><SPAN lang=EN-US style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><SPAN lang=EN-US>软件过程规范</SPAN></SPAN></SPAN><?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /><o:p></o:p></SPAN></B></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 21.25pt; TEXT-INDENT: -21.25pt; LINE-HEIGHT: 150%; tab-stops: list 21.25pt; mso-outline-level: 1; mso-list: l1 level1 lfo1"><B style="mso-bidi-font-weight: normal"><SPAN lang=EN-US style="FONT-SIZE: 14pt; LINE-HEIGHT: 150%; mso-bidi-font-family: 宋体"><SPAN style="mso-list: Ignore">一.<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp; </SPAN></SPAN></SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-SIZE: 14pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">概述</SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN lang=EN-US style="FONT-SIZE: 14pt; LINE-HEIGHT: 150%"><o:p></o:p></SPAN></B></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 21.25pt; LINE-HEIGHT: 150%"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">本文主要对于软件过程的整体规范进行较为完整的描述，来源于个人的项目经验、所在</SPAN><SPAN lang=EN-US>team</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">使用的软件过程以及个人的一些想法总结而成。</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 21.25pt; LINE-HEIGHT: 150%"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">文章按照对项目中采用的软件过程进行描述，之后对保证整个软件过程有效执行的工具、制度等进行描述。</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 21.25pt; LINE-HEIGHT: 150%"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">本文意并不在标明这个软件过程是多么的优秀，关键是要找到适合自己团队的软件过程，没有最优秀的，只有最合适的。</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 21.25pt; TEXT-INDENT: -21.25pt; LINE-HEIGHT: 150%; tab-stops: list 21.25pt; mso-outline-level: 1; mso-list: l1 level1 lfo1"><B style="mso-bidi-font-weight: normal"><SPAN lang=EN-US style="FONT-SIZE: 14pt; LINE-HEIGHT: 150%; mso-bidi-font-family: 宋体"><SPAN style="mso-list: Ignore">二.<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp; </SPAN></SPAN></SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-SIZE: 14pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">软件过程</SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN lang=EN-US style="FONT-SIZE: 14pt; LINE-HEIGHT: 150%"><o:p></o:p></SPAN></B></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 21.25pt; LINE-HEIGHT: 150%"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">此软件过程是根据</SPAN><SPAN lang=EN-US>Team</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">以及</SPAN><SPAN lang=EN-US>XP</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">制定的，图示如下：<IMG height=437 alt="Triones产品系列软件过程 1.0.jpg" src="http://www.blogjava.net/images/blogjava_net/bluedavy/Triones产品系列软件过程%201.0.jpg" width=641 border=0><BR></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: 150%; TEXT-ALIGN: center" align=center><SPAN lang=EN-US><?xml:namespace prefix = v ns = "urn:schemas-microsoft-com:vml" /><v:shapetype id=_x0000_t75 stroked="f" filled="f" path="m@4@5l@4@11@9@11@9@5xe" o:preferrelative="t" o:spt="75" coordsize="21600,21600"><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:connecttype="rect" gradientshapeok="t" o:extrusionok="f"></v:path><o:lock aspectratio="t" v:ext="edit"></o:lock></v:shapetype></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 1cm; TEXT-INDENT: -1cm; LINE-HEIGHT: 150%; tab-stops: list 1.0cm; mso-outline-level: 2; mso-list: l1 level2 lfo1"><B style="mso-bidi-font-weight: normal"><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; mso-fareast-font-family: 'Times New Roman'"><SPAN style="mso-list: Ignore">2.1.<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN></SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">里程碑计划制定</SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%"><o:p></o:p></SPAN></B></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 1cm; LINE-HEIGHT: 150%"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">控制在一个月范围内，每个里程碑应有突出性进展的部分，里程碑版本的发布具有很强的意义，每个里程碑版本在功能或非功能性方面应有明确的对比。</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 1cm; LINE-HEIGHT: 150%"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">在每个里程碑结束时发布里程碑版本并同时给予项目组一定的休息时间。</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 1cm; TEXT-INDENT: -1cm; LINE-HEIGHT: 150%; tab-stops: list 1.0cm; mso-outline-level: 2; mso-list: l1 level2 lfo1"><B style="mso-bidi-font-weight: normal"><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; mso-fareast-font-family: 'Times New Roman'"><SPAN style="mso-list: Ignore">2.2.<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN></SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">迭代计划制定</SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%"><o:p></o:p></SPAN></B></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 1cm; LINE-HEIGHT: 150%"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">控制在一至两周范围内，每个迭代周期结束后对客户发布迭代版本。</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 1cm; TEXT-INDENT: -1cm; LINE-HEIGHT: 150%; tab-stops: list 1.0cm; mso-outline-level: 2; mso-list: l1 level2 lfo1"><B style="mso-bidi-font-weight: normal"><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; mso-fareast-font-family: 'Times New Roman'"><SPAN style="mso-list: Ignore">2.3.<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN></SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">迭代过程</SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%"><o:p></o:p></SPAN></B></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 35.45pt; TEXT-INDENT: -35.45pt; LINE-HEIGHT: 150%; tab-stops: list 35.45pt; mso-outline-level: 3; mso-list: l1 level3 lfo1"><B style="mso-bidi-font-weight: normal"><SPAN lang=EN-US style="mso-fareast-font-family: 'Times New Roman'"><SPAN style="mso-list: Ignore">2.3.1.<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN></SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">需求分析</SPAN><SPAN lang=EN-US><o:p></o:p></SPAN></B></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 35.45pt; LINE-HEIGHT: 150%"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">在迭代的需求分析中主要为对划定在此迭代阶段的需求进行详细的分析，产生出用户故事。</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 35.45pt; TEXT-INDENT: -35.45pt; LINE-HEIGHT: 150%; tab-stops: list 35.45pt; mso-outline-level: 3; mso-list: l1 level3 lfo1"><B style="mso-bidi-font-weight: normal"><SPAN lang=EN-US style="mso-fareast-font-family: 'Times New Roman'"><SPAN style="mso-list: Ignore">2.3.2.<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN></SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">设计</SPAN><SPAN lang=EN-US><o:p></o:p></SPAN></B></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 35.45pt; LINE-HEIGHT: 150%"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">设计主要通过对用户故事进行</SPAN><SPAN lang=EN-US>OOAD</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">产生出符合此用户故事的领域设计，以此建立的领域模型结合架构构成完成用户故事的设计，产生</SPAN><SPAN lang=EN-US>CRC Card</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，最后进行情景测试</SPAN><SPAN lang=EN-US>(Scene Test)</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">。</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 35.45pt; LINE-HEIGHT: 150%"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">设计时需要遵循的三个原则：</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 56.45pt; TEXT-INDENT: -21pt; LINE-HEIGHT: 150%; tab-stops: list 56.45pt; mso-list: l0 level1 lfo2"><SPAN lang=EN-US style="FONT-FAMILY: Wingdings; mso-fareast-font-family: Wingdings; mso-bidi-font-family: Wingdings"><SPAN style="mso-list: Ignore">l<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN></SPAN><SPAN lang=EN-US>Domain Model</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">驱动</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 56.45pt; LINE-HEIGHT: 150%"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">以</SPAN><SPAN lang=EN-US>Domain Model</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">作为驱动进行设计，通过对用户故事的</SPAN><SPAN lang=EN-US>OOAD</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">产生用户故事的</SPAN><SPAN lang=EN-US>Domain Model</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，基于此根据架构完成整个用户故事的设计。</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 56.45pt; TEXT-INDENT: -21pt; LINE-HEIGHT: 150%; tab-stops: list 56.45pt; mso-list: l0 level1 lfo2"><SPAN lang=EN-US style="FONT-FAMILY: Wingdings; mso-fareast-font-family: Wingdings; mso-bidi-font-family: Wingdings"><SPAN style="mso-list: Ignore">l<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN></SPAN><SPAN lang=EN-US>Simple</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 56.45pt; LINE-HEIGHT: 150%"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">简单够用，这个是最为难掌握的，说的直白点就是先采用能够想到的一个最简单的设计去实现功能，至于这个设计是不是那么的合理先不要太多的去理会，在完成了功能后可以不断的对其进行重构，其实其原理就是</SPAN><SPAN lang=EN-US>”</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">一步一个台阶，直至云霄，而不是一步登天</SPAN><SPAN lang=EN-US>”</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，每个团队的不同仅在于这一个台阶能迈多高而已。</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 56.45pt; TEXT-INDENT: -21pt; LINE-HEIGHT: 150%; tab-stops: list 56.45pt; mso-list: l0 level1 lfo2"><SPAN lang=EN-US style="FONT-FAMILY: Wingdings; mso-fareast-font-family: Wingdings; mso-bidi-font-family: Wingdings"><SPAN style="mso-list: Ignore">l<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">集体参与</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 56.45pt; LINE-HEIGHT: 150%"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">迭代过程的设计由项目组共同参与，项目组成员可随意的发表各自对于系统实现的设计的想法。</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 35.45pt; TEXT-INDENT: -35.45pt; LINE-HEIGHT: 150%; tab-stops: list 35.45pt; mso-outline-level: 3; mso-list: l1 level3 lfo1"><B style="mso-bidi-font-weight: normal"><SPAN lang=EN-US style="mso-fareast-font-family: 'Times New Roman'"><SPAN style="mso-list: Ignore">2.3.3.<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN></SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">开发</SPAN><SPAN lang=EN-US><o:p></o:p></SPAN></B></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 35.45pt; LINE-HEIGHT: 150%"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">开发过程中涉及的有：</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 56.45pt; TEXT-INDENT: -21pt; LINE-HEIGHT: 150%; tab-stops: list 56.45pt; mso-list: l0 level1 lfo2"><SPAN lang=EN-US style="FONT-FAMILY: Wingdings; mso-fareast-font-family: Wingdings; mso-bidi-font-family: Wingdings"><SPAN style="mso-list: Ignore">l<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">编码规范</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 56.45pt; LINE-HEIGHT: 150%"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">编码规范需在项目开始时即制定，这个需要根据每个公司以及团队的情况来决定，在</SPAN><SPAN lang=EN-US>Java</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">编码规范中通常要涉及的有类文件规范</SPAN><SPAN lang=EN-US>(</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">主要是文件的版权、文件格式等</SPAN><SPAN lang=EN-US>)</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">、命名规范</SPAN><SPAN lang=EN-US>(</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">包名、类名、方法名、变量名等</SPAN><SPAN lang=EN-US>)</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">、注释规范。</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 56.45pt; TEXT-INDENT: -21pt; LINE-HEIGHT: 150%; tab-stops: list 56.45pt; mso-list: l0 level1 lfo2"><SPAN lang=EN-US style="FONT-FAMILY: Wingdings; mso-fareast-font-family: Wingdings; mso-bidi-font-family: Wingdings"><SPAN style="mso-list: Ignore">l<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN></SPAN><SPAN lang=EN-US>TDD</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 56.45pt; LINE-HEIGHT: 150%"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">按照先编写单元测试后进行代码编写的原则，在单元测试中主要需要对代码的逻辑、性能以及边缘进行测试。</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 56.45pt; TEXT-INDENT: -21pt; LINE-HEIGHT: 150%; tab-stops: list 56.45pt; mso-list: l0 level1 lfo2"><SPAN lang=EN-US style="FONT-FAMILY: Wingdings; mso-fareast-font-family: Wingdings; mso-bidi-font-family: Wingdings"><SPAN style="mso-list: Ignore">l<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN></SPAN><SPAN lang=EN-US>PP</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 56.45pt; LINE-HEIGHT: 150%"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">双人编程，在进行代码编写时必须两人一起进行，一人操作键盘，一人旁边观看，同时进行思考。</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 56.45pt; TEXT-INDENT: -21pt; LINE-HEIGHT: 150%; tab-stops: list 56.45pt; mso-list: l0 level1 lfo2"><SPAN lang=EN-US style="FONT-FAMILY: Wingdings; mso-fareast-font-family: Wingdings; mso-bidi-font-family: Wingdings"><SPAN style="mso-list: Ignore">l<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN></SPAN><SPAN lang=EN-US>Code Review</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">规范</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 56.45pt; LINE-HEIGHT: 150%"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">代码复查规范需要按照各个公司以及代码规范来进行制定。</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 35.45pt; TEXT-INDENT: -35.45pt; LINE-HEIGHT: 150%; tab-stops: list 35.45pt; mso-outline-level: 3; mso-list: l1 level3 lfo1"><B style="mso-bidi-font-weight: normal"><SPAN lang=EN-US style="mso-fareast-font-family: 'Times New Roman'"><SPAN style="mso-list: Ignore">2.3.4.<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN></SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">重构</SPAN><SPAN lang=EN-US><o:p></o:p></SPAN></B></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 35.45pt; LINE-HEIGHT: 150%"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">在开发结束后需要考虑代码的重构，主要从</SPAN><SPAN lang=EN-US>OO</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的各原则以及设计原则来进行提升，复用性、性能等都是考虑的因素。</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 35.45pt; LINE-HEIGHT: 150%"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">重构时可采用</SPAN><SPAN lang=EN-US>IDE</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">提供的重构支持来快速完成，对于设计的重构可以通过设计会议来共同讨论，在重构时甚至可考虑推翻原有所有的设计而进行。</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 35.45pt; TEXT-INDENT: -35.45pt; LINE-HEIGHT: 150%; tab-stops: list 35.45pt; mso-outline-level: 3; mso-list: l1 level3 lfo1"><B style="mso-bidi-font-weight: normal"><SPAN lang=EN-US style="mso-fareast-font-family: 'Times New Roman'"><SPAN style="mso-list: Ignore">2.3.5.<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN></SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">持续集成</SPAN><SPAN lang=EN-US><o:p></o:p></SPAN></B></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 35.45pt; LINE-HEIGHT: 150%"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">持续集成采用感应版本控制工具变化而进行的原则，即有变化提交至版本控制工具时即进行持续集成，在持续集成失败或成功的情况下均发送邮件通知相关人员，项目组所有人员均可通过网站查看持续集成的情况。</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 35.45pt; LINE-HEIGHT: 150%"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">持续集成中主要需要进行的工作是编译所有源码、运行单元测试、按照系统手动部署方式自动完成部署工作、运行功能测试、发布测试报告并通知相关人等。</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 35.45pt; LINE-HEIGHT: 150%"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">持续集成的原则为谁造成失败谁负责。</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 21.25pt; TEXT-INDENT: -21.25pt; LINE-HEIGHT: 150%; tab-stops: list 21.25pt; mso-outline-level: 1; mso-list: l1 level1 lfo1"><B style="mso-bidi-font-weight: normal"><SPAN lang=EN-US style="FONT-SIZE: 14pt; LINE-HEIGHT: 150%; mso-bidi-font-family: 宋体"><SPAN style="mso-list: Ignore">三.<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp; </SPAN></SPAN></SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-SIZE: 14pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">任务规范</SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN lang=EN-US style="FONT-SIZE: 14pt; LINE-HEIGHT: 150%"><o:p></o:p></SPAN></B></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 1cm; TEXT-INDENT: -1cm; LINE-HEIGHT: 150%; tab-stops: list 1.0cm; mso-outline-level: 2; mso-list: l1 level2 lfo1"><B style="mso-bidi-font-weight: normal"><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; mso-fareast-font-family: 'Times New Roman'"><SPAN style="mso-list: Ignore">3.1.<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN></SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">任务分配</SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%"><o:p></o:p></SPAN></B></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 1cm; LINE-HEIGHT: 150%"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">在对用户故事完成设计时即可进行任务的分配，每个任务拆分到</SPAN><SPAN lang=EN-US>1—2</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">天的范围内，对于难以估计的任务先进行</SPAN><SPAN lang=EN-US>spike</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">之后再行分配，</SPAN><SPAN lang=EN-US>spike</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的时间限制在</SPAN><SPAN lang=EN-US>1</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">周以内。</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 1cm; LINE-HEIGHT: 150%"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">由项目组成员自行挑选任务。</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 1cm; TEXT-INDENT: -1cm; LINE-HEIGHT: 150%; tab-stops: list 1.0cm; mso-outline-level: 2; mso-list: l1 level2 lfo1"><B style="mso-bidi-font-weight: normal"><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; mso-fareast-font-family: 'Times New Roman'"><SPAN style="mso-list: Ignore">3.2.<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN></SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">任务完成</SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%"><o:p></o:p></SPAN></B></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 1cm; LINE-HEIGHT: 150%"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">在完成任务的过程中成员需进行任务完成时间的跟踪，原则为在开始任务时填写任务开始时间，在停止编写任务的时候填写时间点，在任务完成时勾选完成任务。</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 1cm; LINE-HEIGHT: 150%"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">此时间也将作为将来分配任务时时间的估计，以使得对于任务的完成时间的估计能够越来越精确。</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 1cm; TEXT-INDENT: -1cm; LINE-HEIGHT: 150%; tab-stops: list 1.0cm; mso-outline-level: 2; mso-list: l1 level2 lfo1"><B style="mso-bidi-font-weight: normal"><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; mso-fareast-font-family: 'Times New Roman'"><SPAN style="mso-list: Ignore">3.3.<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN></SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">任务跟踪</SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%"><o:p></o:p></SPAN></B></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 1cm; LINE-HEIGHT: 150%"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">任务跟踪通过任务跟踪工具来完成，主要是任务完成的时间、任务统计等。</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 21.25pt; TEXT-INDENT: -21.25pt; LINE-HEIGHT: 150%; tab-stops: list 21.25pt; mso-outline-level: 1; mso-list: l1 level1 lfo1"><B style="mso-bidi-font-weight: normal"><SPAN lang=EN-US style="FONT-SIZE: 14pt; LINE-HEIGHT: 150%; mso-bidi-font-family: 宋体"><SPAN style="mso-list: Ignore">四.<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp; </SPAN></SPAN></SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-SIZE: 14pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">工具</SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN lang=EN-US style="FONT-SIZE: 14pt; LINE-HEIGHT: 150%"><o:p></o:p></SPAN></B></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 21.25pt; LINE-HEIGHT: 150%"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">涉及的工具主要有：</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 56.45pt; TEXT-INDENT: -21pt; LINE-HEIGHT: 150%; tab-stops: list 56.45pt; mso-list: l0 level1 lfo2"><SPAN lang=EN-US style="FONT-FAMILY: Wingdings; mso-fareast-font-family: Wingdings; mso-bidi-font-family: Wingdings"><SPAN style="mso-list: Ignore">l<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">任务跟踪工具</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 56.45pt; TEXT-INDENT: -21pt; LINE-HEIGHT: 150%; tab-stops: list 56.45pt; mso-list: l0 level1 lfo2"><SPAN lang=EN-US style="FONT-FAMILY: Wingdings; mso-fareast-font-family: Wingdings; mso-bidi-font-family: Wingdings"><SPAN style="mso-list: Ignore">l<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">版本控制工具</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 56.45pt; TEXT-INDENT: -21pt; LINE-HEIGHT: 150%; tab-stops: list 56.45pt; mso-list: l0 level1 lfo2"><SPAN lang=EN-US style="FONT-FAMILY: Wingdings; mso-fareast-font-family: Wingdings; mso-bidi-font-family: Wingdings"><SPAN style="mso-list: Ignore">l<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">持续集成工具</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 56.45pt; TEXT-INDENT: -21pt; LINE-HEIGHT: 150%; tab-stops: list 56.45pt; mso-list: l0 level1 lfo2"><SPAN lang=EN-US style="FONT-FAMILY: Wingdings; mso-fareast-font-family: Wingdings; mso-bidi-font-family: Wingdings"><SPAN style="mso-list: Ignore">l<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN></SPAN><SPAN lang=EN-US>Bug</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">跟踪工具</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 56.45pt; TEXT-INDENT: -21pt; LINE-HEIGHT: 150%; tab-stops: list 56.45pt; mso-list: l0 level1 lfo2"><SPAN lang=EN-US style="FONT-FAMILY: Wingdings; mso-fareast-font-family: Wingdings; mso-bidi-font-family: Wingdings"><SPAN style="mso-list: Ignore">l<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">开发工具</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 21.25pt; TEXT-INDENT: -21.25pt; LINE-HEIGHT: 150%; tab-stops: list 21.25pt; mso-outline-level: 1; mso-list: l1 level1 lfo1"><B style="mso-bidi-font-weight: normal"><SPAN lang=EN-US style="FONT-SIZE: 14pt; LINE-HEIGHT: 150%; mso-bidi-font-family: 宋体"><SPAN style="mso-list: Ignore">五.<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp; </SPAN></SPAN></SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-SIZE: 14pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">制度</SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN lang=EN-US style="FONT-SIZE: 14pt; LINE-HEIGHT: 150%"><o:p></o:p></SPAN></B></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 1cm; TEXT-INDENT: -1cm; LINE-HEIGHT: 150%; tab-stops: list 1.0cm; mso-outline-level: 2; mso-list: l1 level2 lfo1"><B style="mso-bidi-font-weight: normal"><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; mso-fareast-font-family: 'Times New Roman'"><SPAN style="mso-list: Ignore">5.1.<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN></SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">早会</SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%"><o:p></o:p></SPAN></B></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 1cm; LINE-HEIGHT: 150%"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">早会时间大概在</SPAN><SPAN lang=EN-US>10---15</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">分钟，主要是对昨日任务的回顾、难点的提出、今日的计划以及</SPAN><SPAN lang=EN-US>partner</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的挑选。</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 1cm; TEXT-INDENT: -1cm; LINE-HEIGHT: 150%; tab-stops: list 1.0cm; mso-outline-level: 2; mso-list: l1 level2 lfo1"><B style="mso-bidi-font-weight: normal"><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; mso-fareast-font-family: 'Times New Roman'"><SPAN style="mso-list: Ignore">5.2.<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN></SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">发布会议</SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%"><o:p></o:p></SPAN></B></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 1cm; LINE-HEIGHT: 150%"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">发布会议为里程碑计划的宣布，以使项目组成员能够明确里程碑的目标以及时间点，同时也听取项目组成员的意见。</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 1cm; TEXT-INDENT: -1cm; LINE-HEIGHT: 150%; tab-stops: list 1.0cm; mso-outline-level: 2; mso-list: l1 level2 lfo1"><B style="mso-bidi-font-weight: normal"><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; mso-fareast-font-family: 'Times New Roman'"><SPAN style="mso-list: Ignore">5.3.<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN></SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">迭代会议</SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%"><o:p></o:p></SPAN></B></P>
<P clas