如同在 知识接力模式中提到的那样,让领域专家、架构师和高级开发人员对需求模型和设计模型进行复审。
原型方法能够有效的帮助最终软件的成功。所谓原型方法,就是选取系统的某个部分(最直接或风险最高的部分,通常是界面原型), 实现并呈现给用户,以获得反馈,为后续的活动提供指导。原型方法最大的好处是能够帮助用户认识软件,消除用户的疑虑,并发掘潜藏的需求。围绕着是否抛弃原型这一根本问题,原型方法可以分为渐进原型方法和舍弃型原型方法。前者是在一个软件原型的基础上不断的演进,并最终发展为可用的软件,后者则是在开发出原型之后就将它舍弃。渐进原型方法充分利用了原型,但是由于缺乏前期设计,可能会导致最终产品存在性能或设计问题。舍弃型原型克服了这个问题,但是它浪费了原型开发的那段时间。不论采用何种方法,最重要的是在项目一开始就决定采用哪一种原型方法。模棱两可的使用两种方法是兵家大忌。最终你无法利用任何一种方法的优点,而所有的缺点都将降临到你身上。相较而言,渐进型原型方法更适合于应用在小型项目上,因为项目并不复杂的话,设计的改进比较容易。对于一个拥有构架的团队而言,把原型方法纳入构架之中是很有意义的。如果构架足够成数,迅速开发出一个原型并不是什么很困难的事情。这样就可以在投入最小化的情况下获得原型方法的优势。如果情况是这样的话,舍弃型原型方法似乎更适合一些。
在知识接力模式中,我们简要的提到了设计模型信息和代码信息的转换问题。使用建模工具来自动从设计模型抽取信息,并生成项目的代码。这种方法能够大幅度的提高软件开发效率,并对软件的最终交付有很大的帮助。同样,将代码中的信息转回到设计模型中(属于反向工程的一部分)也是有意义的。如果缺少这样的工具,那么请人为的保证信息的同步,当然,并没有必要保持实时的同步(参见 一致性的思考模式)。
软件的成功和测试活动是无法区分的。我们前面简单的讨论过测试信息是来源于需求的。测试信息随着需求模型的生成而生成,并通过设计模型进行转换,在软件过程进入到实现阶段时,测试信息最终被转变为单元测试用例的形式。单元测试用例可能是针对单个方法的单个用例,也可能是针对某个开发包的几组用例。我们需要注意两点,首先是在软件过程中保证这个流程的顺畅和正确。就像在 知识接力模式中讨论的那样,正确、完整的信息传递保证了最终软件的成功出产,测试信息的成功传递保证了最终软件的可用性。测试是软件的保证。因此,我们需要几个活动来保证测试信息的成功:
从需求模型中生成接受测试。该活动把需求映射到测试上。在这个活动中,不但要注意功能性需求(如完成的功能),还需要注意非功能性需求(性能要求)。同样的,接受测试也需要接受复审。可以按照需求的组织方式来组织接受测试。
设计模型完成之后,接受测试已经细化到模型的各个元素上了(例如包、类)。该项活动和将需求映射到设计的活动是同步进行的。因为它们处理的信息是非常类似的。和接受测试一样,这两个活动都需要由团队来保证。
在进入编码阶段之后,开发人员根据接受测试和设计模型,将会为自己负责的部分设计编写单元测试。单元测试的编写顺序是否优先于编码,这取决于各人的看法。关于这方面的讨论,可以参看XP的单元测试实践。从我个人的经验来看,先写单元测试,再写代码不失为一个很好的办法,另一种做法是,让两个紧密合作的开发人员相互为对方编写单元测试。
其次,我们需要保证测试的最小单元-单元测试的成功。所谓皮之不存,毛将焉附。单元测试没有组织好,最后的软件是不会成功的:
需要注意单元测试的覆盖率。这里的覆盖率指的是是否能够完全检测出错误所在。比如边界条件的测试等。开发团队中的架构师之类的角色需要为此负责,如果无法检查所有的单元测试,那么可以进行抽查和代码复审会议的形式。后者是一种很优秀的做法。从代码中抽取出一段,开发人员一起分析单元测试存在哪些问题,会使得大家编写单元测试的功力不断的增长。
单元测试一定要是自动化的。Junit就是一个不错的自动化测试框架。保证单元测试的自动化,并且避免单元测试和特定环境相关,这样就可以顺利的进行回归测试。这对于迭代式的软件开发是非常必要的。同时,我们也应该认识到,单元测试的稳定性取决于设计的稳定性。我们可以想象,如果测试的类方法的参数、命名都发生改变,那么测试是肯定需要重新组织的。所以,面向对象的抽象思维对于现代软件开发而言是费产重要的。为了做到测试的自动化,尽量避免将逻辑硬编码在界面中,并小心的处理数据库。可以尝试着建立测试数据库。
如果测试的内容需要并入核心构架,那么这部分的测试工作需要增加,并对构架可能的修改进行测试。因此,学习开源软件的做法,将构架的稳定版本和开发版本相区分是比较保险的。
让测试活动随着软件开发的进行而进行,让测试活动贯穿整个开发周期。这有点类似于全面质量管理的思想。因为软件开发过程的失败并不是突然而至的,而是在平时的不经意间一点一点的积累起来的。使用测试活动来消除这种微小的不稳定性,能够大幅度的提高最终软件的质量。但是,在一个团队中引入正规的。频繁的测试活动是需要耐心的。可以先从单元测试着手,慢慢的普及这种做法。
测试活动可以衍生为日创建和冒烟测试。对于有复数的开发人员参与的软件项目,就无法避免正视集成测试的局面。有过类似经验的人都可以想象的到这种集成测试的难度。专门有一句话是描述这种局面的:"我们已经花了90%的时间来完成90%的软件,但我们还需要90%的时间来完成剩下的10%"。现代的软件往往都包括成百上千的文件,这些文件的编译链接的过程是很复杂的。而日创建的思想就是每天进行一次这样的过程,形成一个可执行文件。但这只是日创建第一部分内容。日创建还需要对软件进行冒烟测试,测试的主要内容就是单元测试中所编写的内容,保证软件可以通过所有的测试。
日创建需要留下一些调试的时间,尤其是在软件开发初期,不同开发人员的代码整合在一起出现问题的可能性极大。随着对这项实践的熟悉程度,问题会逐渐减少。日创建可以很明显的提高产品质量,以及提升团队的士气。虽然日创建活动需要付出额外的一些成本,但是相对于集成测试的不可控,这些成本还是值得的。
小结
投资于框架能够保证软件开发的成功。
应用有效的实践活动来完善框架。
将需求映射到核心框架上来。
使用原型法。
注意测试活动。
如果可能,使用日创建,并进行冒烟测试。
规则不同于指南。规则是目标受众所必须遵守的,而指南是建议目标受众遵守的。