UML软件工程组织

过程塑造: (二)知识接力
林星 ( iamlinx@21cn.com )
在软件过程中,我们如何保证信息能够得到正确的传递呢?我们用什么方法来避免信息传递的失真呢?我们如何在这样一个过程中处理人与人之间的交互呢?在正确传递信息的情况下,我们又如何保证投入的最小化呢?

意图

软件开发过程是知识传递、知识转换的过程。注重知识转换中的完整性,保证知识经过各个阶段和活动,顺利的转换为软件是极为重要的。

示例

元朗公司是国内某银行的下属企业。从年初开始,公司就投入了大量的人力为银行开发新版本的国际收支系统。考虑到这是一个非常庞大的系统,因此公司把原先的软件开发团队扩大了一倍,补充的人员有些来自于其它的项目组,有些人员来自别的公司。为了保证开发的顺利进行,项目经理引入了软件过程。但是从一开始,麻烦的事情就出现了。项目组中的技术人员和银行的领域专家之间不断出现意见相左的情况。主要的问题是后加入的员工对目标领域不熟悉,难以配合领域专家的工作。最糟糕的是,某些领域专家身处异地,因此在需求分析的中期,开发团队邀请这些异地的领域专家来到开发所在地,进行了为期两天的讨论会。结果并不理想,讨论会上充满了对原先已定稿的需求的反对性意见,技术专家、领域专家吵成一团。需求分析阶段不得不在原先的基础上延长了50%的时间。在进入设计和编码阶段之后,问题少了许多。但在设计到编码的过程中仍是出了一些麻烦,原因是新加入的人员不熟悉开发团队的设计风格。经过一番周折,问题基本解决了。可等到项目进入到测试阶段,矛盾一下子就凸现出来了。测试报告指出,软件中存在着大量的问题,大部分的问题都被定性为无法满足需求的严重错误。经过对错误的复审,排除了其中17%的严重错误。经过分析,发现其中70%的错误都是发生在后加入人员负责的模块中。而产生大量错误的一个主要原因是在编码阶段,由于银行启用了新的会计制度,导致大量模块被修改,由于时间紧迫,因此没有进行正规的需求调研。现在看来,领域专家和技术专家对同一个问题的理解并不相同。最后,项目的开发周期延长了40%。

上下文

软件过程每经历一个阶段,就会发生一次知识转换的情况。这种转换是由人来完成的,这就是像是接力一样,一个人把脑中的知识以某种方式传递给另一个人,再有另一个人传递下去,直至编码人员把这些知识固化在最终的软件中。在软件成型之前,知识的主要载体是文档和模型。我们称它们为工件(Artifact)。例如,需求阶段时,领域专家在技术专家的帮助下,将自己脑中对领域的认识传递给技术人员,并最终形成需求规格书或是用例模型。而在分析设计阶段,技术专家借助需求规格书,把脑中对软件的初始认识进一步转换为分析模型、设计模型、数据模型等工件。最后,在编码阶段,编码人员把这些工件中隐藏的知识转化为软件的形式。经过测试和部署,软件将会交付到用户手中。这是非常典型的软件开发过程,再简单的软件开发也需要经历上述的这些阶段。

可以看到,在上述的软件开发过程中,知识形式发生了两次的重要转换,知识所属角色也改变了两次。知识完成第一次的形式转换之后,将成为需求规格书(或同类工件)的形式,知识从领域专家的脑中转换到技术专家的脑中。然后,知识开始了第二次的形式转换,形成设计模型(以及同类工件)。随着知识从技术专家转移到编码人员,知识转换为其最终的软件形式。在这些转换的过程中,最容易出现信息遗漏、信息失真的情况。保证转换过程中知识的完整性和正确性,对软件开发具有重要的意义。

问题

如果保证转换时知识的完整性和正确性?

方法

知识转换的主体是人,因此我们主要的对策也是针对人来展开的。我们知道,软件过程的特点就是:越早埋下祸根对项目的杀伤力越大。所以我们首先需要重点防范的对象应该是在初始需求分析阶段。需求分析阶段涉及的知识非常的多,大家如果有兴趣可以参看我的文章-需求的实践。但这里我们重点的任务是找出需求分析阶段中发生知识转移的关键点。

领域专家和技术专家是需求阶段中最重要的两种人,不论你的项目和团队规模属于哪一种层次,一定都包含这两种角色。如果你的团队中领域专家和技术专家是同一种人,那么恭喜你,你可以不用阅读这一段的内容了。可惜在强调分工协作和软件规模不断扩大的今天,这种人已经非常难找了。领域专家是知识的最初持有者,其职责是为项目提供准确的、完整的需求信息。技术专家的职责则是帮助领域专家完成这一项工作。所以,首先请保证领域专家和技术专家是能够沟通的,示例中的项目的第一个问题就是团队的新成员和领域专家之间存在沟通壁垒。在我们的经验中,就发生过一位优秀的技术人员和一位资深的领域专家争吵的事情。剖析原因之后,我们发现,最主要的原因是他们两个人都太优秀了,技术人员有一定的领域经验,领域专家有一定的开发经验,这导致了双方在讨论中的强硬立场。因此,如果遇到类似的情况,请对你的组织进行岗位调整。但在执行这项工作之前,请小心你的说辞,不要伤害到任何一个人。"我们的某个小组有麻烦,那边非常需要你的经验和能力"会是一句不错的说辞。其次,技术专家不应该提出任何可能影响领域专家的问题。只有领域专家才能够提出需求,技术专家起到的只是辅助作用。因此请杜绝这种情况。再次,如果你的领域专家不只一个人,那么你需要考虑领域专家之间可能出现的不一致。为领域团队指定一位领导者是一种不错的做法。在我们的一个项目中,就曾邀请对方公司的财务总监担任这一角色。理由有二:1、财务总监具有权威性;2、财务总监了解公司的全部运作。此外,如果领域专家分布在不同地点的话,你需要在该阶段的某个时期,安排需求讨论会,并考虑一种能够沟通的方式,以便随时能够了解身处异地的领域专家的意见。这种情况对于那些拥有分公司的公司(例如银行、证券、保险、销售公司等等)而言非常的普遍。因此,我们在需求分析阶段,首先要处理好领域专家和技术专家之间的关系。应该说,这里提到的内容不仅仅适用于需求阶段,在整个的开发过程中都有用处。

需求不是实现。需求表示的是有什么(What),并不关心如何做(How)。如果在需求分析阶段把精力分散到了如何实现需求上,那么需求分析的效果就会受到影响。这体现在需求的完整性和正确性两个方面。领域专家和技术专家都可能犯类似的错误。领域专家往往只能够针对自己的工作来描述需求,而他会很容易的把自己对于需求实现看法参杂到需求描述中。从项目的整体范围来看,这种需求描述有时候是有问题的。如果你开发的是一个定制应用,那问题还不大,如果你开发的是一个产品,那么问题就很严重了。领域专家描述的需求一定是你需要的内容吗?例如,你打算开发一个配送的管理应用,但是领域专家把大量的精力花在了他在原先的公司中如何实现配送的流程上,这个过程可能适合于他的公司,但是对于产品而言,可能就不合适,因为并非所有的配送公司都使用这种流程的。好吧,你想要的内容和你不想要的内容混合在一起,这使得你不得不花费精力对需求进行进一步的整理。因此,好的做法是,一开始就明确领域专家应该提供什么,而且,尽可能的提供需求,而不是需求实现。多问一些诸如"如果环境发生变化,你该如何做"之类的问题,否则你会发现,用户的需求变化将会对你的软件造成很大的影响。再说技术专家,技术专家常常犯的毛病是把分析参杂到需求调研中来,从需求描述中精练出一些业务实体(或进行CRC讨论)是可以的,但是过早的考虑实现方式将会限制你的思维。因此,请确保需求只是需求,这样才能够尽可能保证需求的完整性和正确性。

需求复审是非常重要的检查点。请确保你正确的使用它。需求复审需要领域专家和技术专家、以及管理者的参与。需求复审是保证需求完整性和正确性的最后一道防线。在很多的文章(包括我的需求的实践一文)、过程都对需求复审进行了论述,我们这里就不赘述了。在实践过程中,我们发现,需求复审还有一个好的方式,为了能够通过需求复审,需求分析人员(包括领域专家和技术专家)会非常努力的找出需求中的问题。所以,在你的过程中加入这个检查点是非常有必要的。

好的,如果这一切都进行顺利的话,最后的需求规格书应该是比较完美的,而技术专家也已经从领域专家那里了解到了足够的信息,可以开始下一阶段的开发了。这里,我们再花一些笔墨来讨论迭代过程中,我们如何处理需求。实践中,我们认为迭代次数并不是越多越好,应该根据项目规模和团队特点进行区分,每一次的迭代都可能有自己的目标。例如首次迭代的周期可能比较短,其主要的目标定为提供软件原型、验证主要设计思路等。第二次的迭代的周期可以长一些,目标可以定位为实现主要功能。如果软件规模比较大,也可以为每次迭代设定需求范围(或主要场景),这样就能够防止需求扩散的情况。这已经超出了本文的范围,因此我们这里只是简单的提一下。

分析阶段是发生职责转换的重要阶段。该阶段的成败对软件开发至关重要。对于面向对象开发而言,这个过程最主要的任务是对领域进行建模。比较好的方式是使用UML来描述领域知识,例如,我比较经常使用类图来建立分析模型,使用顺序图来描述动态流程。请确保技术团队中最出色的分析建模人员参与这个初始分析建模的过程。他的职责包括指导建模和对模型进行审查。如果在一个迭代过程中,这个模型是不断演进的,这可以减少一些风险。在这个过程中,建模人员可以吸收领域知识,这对于后续阶段中指导其他开发人员是很重要的,对公司的长远目标也具有重要意义(参见短期利益和长期利益的权衡模式)。如果建模人员缺少面向对象开发的经验,他会很容易把对象变成一个数据容器。这种方式并不是不好,但它把数据和行为区分开来,无法站在一个抽象的高度上对领域进行分析。

很难严格的区分分析阶段和设计阶段,至少我是这么觉得的。他们的差别仅仅是在分析的详细程度上(有点类似于以往的概要设计和详细设计)。在实践中,我们发现,并没有必要严格的区分它们,但是你需要保证模型已经完整的描述了需求。这里可以设置检查点来验证,也可以在设计模型出来之后再进行检查,这取决于具体的项目。因此,我们在分析阶段和设计阶段结束之前需要进行设计复审。

从Martin Fowler提出分析模式的概念之后(现在他的第二本分析模式正在写作中),它就成为分析建模的有利助手之一--对领域概念进行分析和建模,并描述它们之间的关系(我在点空间上的一篇读书笔记反应了需求和分析之间的关系)。但是请千万注意,不要误用和滥用分析模式。因为任何分析模式的提出,都是基于某个上下文环境中的需求的,如果上下文环境不同,那么模式就需要改进或改造。因此,分析模式是一个好的开始,但需要你针对实际需求具体分析。在应用模式方面,Frank Buschmann的Applying Patterns是一篇不错的参考文章,其中文版发布在点空间上。

请按照逐步精化(迭代)的方式来完善、改进你的分析模型。优秀的设计一定不会过于复杂。如果你的分析模型出现过于复杂的情况,到处充斥着复杂的关系网。那么,你需要对你的设计进行结构上的改进。例如,采用分层(参见敏捷架构设计一文中的分层模式)、组件技术、或是使用单向联系。坚持这一过程,你会发现最后的设计是简洁的、完美的。

在设计阶段,要注意的事项和分析阶段相差不多,例如不要误用和滥用设计模式。但是有一点是需要额外强调的。当分析模型已经能够完整、正确的描述需求之后,我们就需要在设计模型中添加设计资料。例如对包、组件、类、方法的描述。这时候,需求的信息已经被打散到软件的各个部分中了。而设计模型在被实现时,设计模型中的信息又将进入到代码中。因此,保持这些信息的一致性就显得非常的关键。而由于设计模型处在中间地带,它的重要性又是不言而喻的。基本的处理思路分为两步:在需求发生改变时,请同步更改设计模型以及设计模型中的信息。再由设计模型驱动代码的修改。第一个步骤是需要手动实现的,但是第二个步骤可以由计算机辅助实现,即保持设计模型和代码信息的一致性(将在一致性的思考模式中讨论)。目前有很多的建模工具都可以做到这一点,甚至能够实现产生最终的API文档。善用这项功能,它能令你事半功倍。

在软件过程中设立反馈活动,可以有效的减少项目的偏差。就像我们骑自行车,很少能够走一条直线,一般我们是根据对目标的偏差进行忽左忽右的调整。这就是反馈的机理。原型法是一种不错的反馈机制,根据我们的经验,视觉刺激对用户是最为关键的,因此不论你的需求文档做的如何的优秀,仍然比不上一个能够看得见的软件原型有效。这一实践很多的软件工程资料中都有叙述,我们就不深入了解了。另一种反馈机制是渐进交付。把软件产品分为多个迭代周期,每个周期交付一个可运行的软件,在获得用户的反馈意见之后,在下一个迭代周期进行改进,最后一个迭代周期交付的就是完整的软件了。

对可重用框架的改进

在找到了适合软件企业自身的知识接力方法之后,应当将其作为规范或指导意见,加入到现有的软件过程中。例如,在需求分析完成之后强制要求进行需求评审。加入到过程中的方法,小心不要流于形式。这样,既付出了成本,又收不到应用的效果。使用工具也是保持知识顺利交接的重要方法。例如,采用自动产生源代码的工具,模型设计工具、帮助产生工具、对象-关系映射工具等等。如果这些工具对你的过程起到了润滑的作用,请规范和普及工具的使用。

小结

  • 请确保领域专家和技术专家之间的顺畅沟通。
  • 完整、准确的描述需求。
  • 进行需求复审和设计复审。
  • 保证分析模型(设计模型)能够完整的描述需求。
  • 保持需求信息到设计信息到代码注释的一致。
  • 使用反馈机制。
 
 

版权所有:UML软件工程组织