一致性原则是软件开发中重要原则,也是最令人困惑的原则。做到完全的一致性将会导致高昂的成本,而不一致又会导致项目出现各种各样的问题。可以想到,这又是一个需要权衡的问题。
意图
软件过程中的大部分工件都需要保持其相互之间的一致性。可是,工件越多,保持一致性的开销也就越大。我们需要在一致性和成本之间保持平衡。
示例
天利软件公司的项目经理正在为开发过程中出现的大量的不一致问题头疼不已。从软件过程一开始的需求阶段,版本问题就一直困扰着项目组的成员。项目组的成员并非没有经验,只是这一次的项目规模超过了以往的项目,因此公司决定采用严格的过程,以保证软件质量。开发过程中每个活动都必须产出文档。第一次的不一致发生在需求调研中期的一次研讨会上,当时的会议上发现了三种不同版本的需求规格书。之后情况越来越糟,文档的数量不断增多,由于所有的开发人员都需要编写文档、使用文档,因此发生了各种原先没有料到的事情,包括新文档被覆盖;设计人员手中的需求规格书不是最新的版本;设计书变更之后,代码却没有相应的变更;代码中的方法说明和设计模型中的方法说明不一致。为了对文档进行控制,公司不得不从项目组中抽调了两名开发人员来控制文档,并加强了文档的管理。但是随之而来的是开发周期的延长。
上下文
一致性包括两个方面:一是不同工件之间的一致性,二是使用同样的方法来处理问题。
软件过程的每个阶段都需要产出不同的工件。典型的例如需求分析阶段将产出需求规格书、用例模型、非功能需求等,设计阶段产出设计模型、类图。而在软件开发中,我们常常会遇到需求的变更的情况,因此我们需要依次对我们的需求模型、分析模型、设计模型、代码进行修改,以保持它们之间的一致性。如果项目处于前期阶段,这种修改量并不大,因为工件较少,如果项目进行到后期。需求的改变将会涉及到大量的工件。对于期限比较紧张的项目而言(这似乎是所有项目共同的特征),这种成本几乎是无法接受的。
另一方面,在同一个软件组织中,解决同样的问题有着不同的办法。不同的人有着不同的编码习惯、不同的目录组织方式、不同的类库、不同的框架。虽然我们并不反对同一问题的不同解法,但是当这种情况对项目的进展起到负面的效果的时候,我们就有必要来思考这个问题了。
问题
我们如何在一致性和一致性带来的成本之间做好平衡?我们如何保证不同工件之间的一致性,又该如何保证项目中解决方法的一致性。
方法
首先,我们应该肯定,一致性这个问题并没有标准的答案。不同的项目对一致性有着不同的要求。对于要求严格、规模庞大、涉及到一些重要领域的项目来说,一致性的要求是极为严格的。而对于一个小型的、较为无关紧要的项目来说,一致性的要求就低了许多。因此,和前面介绍的模式类似的,一致性的正确的答案只能够从读者自己的项目中去寻找。而这里提供的,是寻找该项标准的建议。
我们先从后者-解决方法一致性入手。
和这个标准答案相关的是一致性的程度。一致性的标准可大可小。大的标准包括了设计原则、软件架构;小的标准包括用例的书写格式、设计模型的注释格式等等。由于大的标准对开发过程的作用最大,因此在进行一致性处理的时候,应该先从大的标准入手。在 代码是最终目的模式中,我们提到了构架的概念。以构架为中心来制定标准,保证一致性是一种自然的思路。核心构架应该要能够确定软件开发的方向,这样可以最有效的保证一致性,但是不要涉及到过于具体的细节,除非你对它们已经有足够的经验。而标准的深入程度则要取决于组织经验、已有的软件过程、项目规模等因素。
对于项目来说,一致性存在一个逐步精化的过程。正如我们上面所讲的,一开始最重要的是引入核心原则,这里我们认为是可重用框架。对于可重用框架中已经明确确立的事项,必需要严格的遵守,因为框架中的内容是足够稳定的,已经经过验证的。这其实是重用思想的一种衍生。我们在 短期利益和长期利益的权衡模式中还会谈到。如果有必要,引入的核心原则需要针对项目进行部分调整。例如,框架中根据项目的规模大小定义了用例的三种写作模板,在项目开始的时候,我们会选择其中最接近的一种模板,并根据项目增删模板中的一些元素。而对于框架中不曾定义的,一些尚未明晰的事件,我们在项目初期不需要进行过于详细的处理,而是随着项目的进展来慢慢的完善它。例如,由于需求没有确定,我们并不知道最后的设计模型是什么样的,因此我们先根据框架定义,选择JSP和Servelet作为主要的技术基础,由JSP负责提供视图,由Servelet提供业务逻辑。其它的信息则等待进一步的精化。
在项目一开始的时候,不要过分注意工件的修饰。例如,我们选择的用例模板要求每一个用例都需要包括6种元素,包括主要角色、级别、前置条件、主要流程、备选流程、优先级。并规定引用其它用例的地方需要做出链接。但是在一开始需求调研的时候就按照这种标准完善用例将会提高成本,因为需求尚未稳定,我们主要的工作是尽可能完整的收集用例,而不是把时间花费在修饰用例上。因此一开始任何形式的用例描述都是允许的。你可以使用几句话来描述用例(事实上,利用自然语言来描述用例有着图形无法比拟的优势),并用着重号标记出其中可能和其它用例相关联的词汇。这样就已经足够了,修饰的工作可以等到下一步来做。其它的工件也是一样的。这时候的一致性的要求并不十分严格。
我们需要注意一些关键点(检查点),例如在 知识接力模式中提到的需求复审。在项目接近这个关键点的时候,用例应该是已经根据要求整理完毕,可以接受复审了。粗糙的工件能够迅速的创建,但是不容易让人理解,也违背了一致性。因此我们虽然可以延迟工件的精化,但是这个工作是不可以缺少的,当然,精化的程度是可以变化的。利用关键点来保证工件的一致性也保证了信息传递的一致性(参见 知识接力模式)。