UML软件工程组织

过程塑造: (五)活跃和混乱、严谨和死板
林星 ( iamlinx@21cn.com )
软件工程需要在科学和艺术之间求得权衡,科学的一面包括了软件开发规范、准则、实践、过程、方法;而艺术的一面则囊括了人员的激励、协调,组织的设计等因素。因此我们需要审视我们的规则、过程、方法,它们是否能够发挥出人的创新性?或是它是否足以约束人的行为?

意图

对开发人员的行为进行约束是必要的,但同时却限制了开发人员的创意。我们如何在这两的极端之间取得平衡呢?

示例

成达公司在以往的项目开发中,一般都不限制开发人员的行为――公司中开发人员都有各自的编码习惯,使用不同的开发工具,更不用说遵循什么开发过程了。因此一旦有人员离职,接手的人员往往都需要花费大力气来熟悉原先的系统,因为原先的人员几乎没有留下文档,或是仅有一些旧的、不能使用的文档。公司中也有软件人员向管理者提出过这方面的建议。但是由于软件开发并不是公司的主要盈利机构,公司不太注重这件事。因此这种情况就一直保持下去。由于公司中的软件人员大多数都有着多年的开发经验,所以日常的运作也算是基本正常。从今年开始,情况发生了改变,由于经营策略的改变,公司换了一位老总,新老总对软件部门非常重视,并投入资金,为软件部分引入了一套严格的规定,制定了统一的编码规则、开发环境,严格的作息制度、汇报机制。有位员工这样形容新过程,"就差没有制定上洗手间的时间了"。过程实施以来,员工怨声不断,由于个人原先熟悉的开发方式被打破,软件开发速度大大降低。客户的投诉也明显增加,甚至出现了项目中止的情况。过程实施6个月之后,发生了3位资深的开发人员离职的事件。最后,管理层不得不废除新过程,回到原先的开发方式上去。

上下文

开发过程有两种极端。我们可以看看下面的两种情况,你更愿意在哪一种环境中工作。

项目组的三个程序员分别开发项目的三个模块。需求仅仅持续了3天的时间。原定计划是1周,但是因为项目甲方人手紧缺,调走了需求调研的领域专家。三个程序员闷头开发,彼此隔绝。每位程序员都有自己的类库和开发包。没有文档,没有测试用例。突然,程序员甲喊道,"昨天我放在这里的需求说明书呢?就是那张上头有脚印的打印纸。"界面开发一半之后,用户发现似乎不同模块的界面相差极大,按钮的位置、菜单风格、窗口布局,没有一处相同的。更为糟糕的是,似乎程序员对用户需求的理解又错了。

程序员乙正在嘀嘀咕咕的修改他的代码,因为架构师在检查了他的代码之后,指出了100多处和标准规则不一致的地方。包括变量命名、注释规则等等。"烦死了!"程序员丙伸了个懒腰,他正在修饰他的设计类图。上次也是这样,模型已经画的尽善尽美了,结果又因为设计发生变化不得不重来一次。看来今天有没什么时间写代码了。项目经理正在审查昨天各个开发小组提交上来的文档,"这几份文档的格式都有问题!"他皱了皱眉头,看来在下午的例会上,他还要着重强调统一规格的问题。

问题

可以看到,上述的两种情形正是我们的模式名称的后半部分所描述的:混乱和死板。那么,我们如何达成模式名称的前半部分-活跃而且严谨呢?

方法

这又是一个需要权衡的问题。正是这种问题让人头疼不已。造成软件过程无效或束缚开发人员的结果有两种不同来源的因素。一是在过程选择和创建的时候,我们忽略了一些问题,一种是过程实施后的控制上我们没有仔细的思考。

软件过程的迷思

很明显的,上面所讨论的两种极端都不是优秀的软件过程。然而,就像我们看寓言故事一样,再取笑寓言故事中的人物的时候,可曾想过自己也犯过类似的错误,只是轻重程度不同而已。虽然我们不会犯上例中所有的错误,但是确实会出现其中的一些情形。那么,我们在建立软件过程的时候,如何防止出现上述的一些情境呢?

以我们自己为例子。在建立过程的时候,我们选择是以RUP为基础。为什么不选择XP之类的敏捷方法呢?原因有二:i)敏捷方法的实践很优秀,但是作为完整的过程,它仍然有其不充分的地方。ii)XP中有很多优秀的实践,但另一些我们并不完全赞同。在选择了RUP之后,为了保证过程的灵活,我们删减了大量的活动和工件,仅保留了一些关键的。但是我们清楚,如果现有的团队规模发生变化,删除的这些活动和工件可能需要重新添加到过程中来。此外,我们引入了XP中的一些优秀的实践。例如测试优先、重构和结对编程。对于结对编程这项实践,我们没有完全采纳XP的建议,而是在一些关键的活动上,例如指导、模块设计、单元测试,采用了结对编程实践。

好的,首先,在阅读了这个例子之后,我希望大家不要都去选择RUP或是XP,这样的话说明你并没有领会这个例子的意思。根据自己的特色来选择软件过程是这个例子所要表达的第一个意思。有些团队原先就已经拥有运作的差强人意的过程,因此并没有必要一股脑转换到RUP或是XP上去。Alistair Cockburn在他的敏捷软件开发(该书已有中文译本,Alistair Cockburn的网站上有英文原版的草稿可供下载)一书中讨论了如何根据软件团队选择敏捷过程。事实正是如此,在开发性命攸关的系统时(例如急救系统),被认为是快餐式的实践活动,在开发业务系统时,可能就显得过于死板了。因此,在我们选用RUP的同时,删除了其中的很多活动,因为我们不需要它们。例子要表达的第二个意思是,请选用一个现成的软件过程,而不是自己开发一个。现成的软件过程往往都经过精心的设计和实践的验证,而且,如今的大部分软件过程都可以对其进行剪裁,不至于说找不到完全不合适的过程。其实,例子中还隐含了第三个意思,以往合适的过程未必就适合现在的情况。在代码是最终目的模式中的例子吗?没有永远合用的过程,让你的过程随着你的组织的成长而成长,随着环境的变化而变化。

不要过于在乎你的过程过轻或过重,只需要关注它是否合适,开发人员能否接受。新的过程是否要求开发人员改变原先的习惯,而他们的反应如何?很多时候,正是对旧习惯的挑战导致了开发过程的失败或不顺利。这里需要非常小心的处理。

在引入软件过程的时候,不要花费大量的时间来编写描述过程的文档,尽量利用现成的。有编写文档的时间,倒不如用来对开发人员进行培训,并获取他们的支持。在实践中,我们发现,人们往往不会去真正阅读并理解大量的文档。文档过多也将使得工作失去重点。从一些比较简单的、容易见效的、最好是能够结合现有的一些流行技术的(程序员们都喜欢)。例如,使用用例技术来改进需求、使用UML来改进设计。这样做的好处还在于,这些技术往往都有较多的资料,利用这些资料可以节省编写指南的时间。

开发人员应该要成为过程的主人,至少部分有能力和意愿的开发人员应该成为。单凭管理人员或是外部顾问的力量是很难完成过程的创建的。因此必须令开发人员主动投入到这项工作中来。我们认为软件过程必须要能够结合具体的技术,因为这样,才能够吸引开发人员。例如,版本控制工具的配置、集成测试环境的开发、单元测试技术、设计模型等等。从技术出发,扩展到整个的软件过程,是一种渐进的,但行之有效的方法。事实上,我们正是采用从定义面向对象软件框架出发,来开始和完善过程定义的。这其实就是我们在代码是最终目的模式和短期利益和长期利益的权衡模式中讨论的构架的形成过程。不同的软件组织会有自己的路,但目标是一致的,就是通过一些有效的活动,逐步引入软件过程,并令其在组织中开花结果。

如何把握过程控制的尺度

其实软件过程设计的思路和面向对象程序的设计思路是非常相似。例如,在进行设计和程序的控制的之后,我们比较注重类的公有方法部分和包的外观类部分,而对于类或包的内部实现并不很在意。因为我们认为对于面向对象设计来说,公有方法或接口是最重要的,它们设计的好坏直接关系到软件的好坏。因此,我们的思路是,把握关键的检查点(就像我们在上一篇中提到的KPI的思路)。软件过程也是类似。活动内部的信息交互并不是我们所关心的,只要活动能够产生最终需要的信息就可以了。例如,在需求阶段,我们最关心最后的工件――需求说明书。包括它的内容和外观。因为一方面它是后续活动的基础,另一方面它需要交付给客户。为保证其顺利开发,我们设置了需求审查会议。至于会议之前,开发人员喜欢用什么样的技术和方式进行需求调研,并不是我们所关心的,而且,我们也乐意看到开发人员尝试使用一些新的技术,这样才能够既保证了严谨,又保证了活跃。因此,在开发过程中,把精力放在那些检查点上,只有力气用在刀刃才才能达到最好的效果。在知识接力模式中我们就谈到了检查点的问题,此外,一些重要的活动,例如日创建和交付点,都是关键的检查点。

如果你的过程比较严谨,开发人员并没有什么创新的机会或环境,想办法制造一个。软件开发人员喜欢研究新的技术,这是他们的优点,但是在项目中应用新技术是存在风险的(参见短期利益和长期利益的权衡模式)。鼓励并支持开发人员进行新技术的研究,并让其负责这方面的事务。对团队,对个人都是有益的。

在一致性的思考模式中,我们分析了工件和过程不一致时的对策,并简单的谈到了推迟文档的实现的问题。这里我们继续这个话题。没有多少程序员喜欢文档(这里的文档是广义的文档,包括模型、图例、文字处理器文件、注释,它等同于我们在知识接力模式中提到的工件),而经理们则对文档又爱又恨,没有文档不行,这会造成知识的流失;文档太多也不行,因为它需要大量的投入,并招致开发人员的反感。因此,我们的建议是坚持以够用就好的思路对待文档,并使用三种指导原则:

  • 区分关键文档和普通文档。关键文档的信息收集工作应该不断进行,虽然文档并不需要额外的修饰(就像一致性的思考模式中所说的),但是你要保证它把必要的信息都记录下来了。典型的关键文档包括了需求模型、设计模型。普通文档的信息可以从关键文档中取得,因此可以尽可能的延迟它的创建。例如用户指南之类的文档。但是请注意,关键文档和普通文档只是相对的概念,例如,你开发的如果是一个设计类的软件,那么用户指南可能就成为关键文档,需要从一开始就考虑编写的工作。如果有必要,你应当在软件过程中加入文档制作的活动,以保证有充分的时间来处理它们。
  • 在关键的检查点上保证文档的完整性和一致性。上文中我们提到了检查点的概念。就像在需求复审这个检查点上,我们需要保证需求模型完整的再现了用户或领域专家的思路,而在设计复审这个检查点上,我们则需要保证设计模型和需求模型的一致性,并确保开发人员和设计人员都同意当前的设计模型。只在检查点上同步文档可以大大减少文档的负担,但文档需要进行同步的检查点则要好好的考虑。例如,帮助文件需要同步的检查点,界面原型需要同步的检查点。
  • 使用工具来减轻文档的工作量。我们在知识接力模式和一致性的思考模式中都提到了工具,这里我们再一次的强调它,但我们不再这个问题上多费口舌了,大家可以参看两个模式中相关部分的讨论。

总之,小心的处理文档,不要让文档成为开发人员怒气的焦点,不要让编写文档变成一种应付了事的工作。这样的话,既花费了精力,又得不到应有的效果。

最后一点,千万不要相信过程能够解决一切。"我们采用了最先进的过程,我们一定能够成功的"这种话无异于痴人说梦。开发软件的是人,而不是过程。好的过程对于软件的成功来说,只是一个必要条件,而不是充分条件。永远依靠你的开发人员。当人的行为和过程冲突或不一致的时候,想想过程的目的,再做最后的定论。

小结

  • 在创建软件过程时,从现有的软件过程中选择一个适合自己的。
  • 水无常形,软件过程也是一样,确保它随着时势而变。
  • 注意引入软件过程的开始阶段,让开发人员参与到软件过程中来。
  • 重点关注检查点。
  • 保持文档活动的敏捷性。
  • 过程不是仙丹,人才是。
作者简介
林星,辰讯软件工作室项目管理组资深项目经理,有多年项目实施经验。辰讯软件工作室致力于先进软件思想、软件技术的应用,主要的研究方向在于软件过程思想、Linux集群技术、OO技术和软件工厂模式。您可以通过电子邮件 iamlinx@21cn.com 和他联系。

 
 
 

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