2008年1月14日星期一

软件开发方法浅谈(三)

最近生了一场大病,浅谈的整理断了几天。我已经好几年没有生病了,没想到这次一下子来的这么猛。我整整吊了4天盐水,现在还没有恢复,但是班还是要上的,否则没钱看病了。现在自己觉得身体越来越差,希望和我一样做IT的朋友要注意自己身体了,每天至少要有半小时的锻炼,吃一些善存之类的维生素片,弥补饮食结构带来的隐患。好了,闲话不多说,继续。

浅谈(二)里面已经整理了一些需求获取的方法。那么这里就可以说说从需求到设计的过程了。软件设计是大家研究的最多的东西,至今为止有可以说无数中设计方法。从以前学校里面学的自上而下、模块化到现在主流的面向对象(OO)的设计方法。我现在主要使用模块化和OO这两种方法。前者用于设计小型的工具软件,后者用于设计公司的软件产品。但是从需求到设计的过渡,关注的人就少很多了。下面就仔细说说从需求到设计的过程,或者说--需求工程。因为据我的经验来说,这部分是最难的。Frederick Brooks在《没有银弹》中也充分说明了需求工程在软件项目中扮演的重要角色。这部分过了之后,再细分就是水到渠成的事情。就算小部分出错,也不会影响到系统全局。

1. 需求的层次
最为困难的概念性工作便是编写出详细技术需求,这包括所有面向用户、面向机器和其它软件系统的接口”。这句话充分说明这个过渡阶段的重要性。

一般来说,需求有两种:用户需求和软件需求[1]。这两种分类也是两种层次。前者就是我在浅谈(二)中所指的从用户那里搜集过来经过简单加工的关于系统行为和反应的要求。用户需求往往包含着两个目的。

  • 我要完成一项工作
  • 这项工作的流程和结果要符合业务规则
软件需求(或者说技术需求)就是为了达到这两个目的而对软件系统提出的要求。这种要求分为两类:功能性的要求和非功能性的要求。
  • 功能性需求规定了系统要实现的功能,使得用户可以完成他们的工作,并且符合业务规则。
  • 非功能性需求则指明了为了要使用户完成目标而需要满足的除了功能以外的要求。这些要求往往是涉及系统的性能、可靠性,安全性,可维护性等方面的要求。

2. 需求的粒度
需求获取到什么程度可以进行设计,这个度的把握不容易。如果无法获得足够的信息,就没法过渡到设计。如果要获得足够多的信息,时间却不允许。那么如何掌握这个度呢?我认为,能把用户的一个目标实现从输入到输出串得起来就可以了,也就是说得通,细节部分不用太关注,要关注得是搞清用户目标,以及现存的支持系统。

我相信实践出真知,检验知识也要靠实践,因此这里开始用一个贯穿全文的例子来说明如何精化需求的。

例子是这样的:我们刚刚获得了一个项目,这个项目是要为牛逼公司打造一个报表系统。首先从NB公司那里获得的需求。他们的要求很简单,“我们要一个报表系统,我们经理每天早上一上班就要看到报表打印出来放在他的办工桌上面。”。然后经过一连串的需求挖掘。我们整理出了初步的需求如下:

牛逼公司的生产部经理牛魔王每天早上需要看报表。报表的内容是前一天公司生产车间所有设备的生产计划、实际生产结果、运行情况、维修明细、产量、故障情况、员工生产率和库存情况。
是的,听起来很简单,但是我们很快会发现一些问题。比如数据从哪里来、有哪些种类的数据等等。然后继续获取需求。然后我们扩充了这个需求(通过上一篇文章中的方法)。

牛逼公司的生产部经理牛魔王每天早上需要看报表。报表的内容是前一天公司生产车间所有设备的生产计划、实际生产结果、运行情况、维修明细、产量、故障情况、员工生产率和库存情况。他要求每一种分类单独一张报表,然后把他们合起来打印成一张大报表(B3),使他能看得方便,快速。

数据来源于各个设备。设备每过一段时间会自动产生这段时间内的运行状况的数据。如果出现紧急问题,设备会直接发送事件。如果断线,设备在连接恢复之后自动上传断线期间的数据。

车间主任负责制定生产计划,核查实际生产结果,核对库存情况。他需要将这些数据记录下来,以备核查。

到了这个程度,所有的过程听起来似乎已经比较合理了。车间主任制定生产计划,然后工人使用设备进行生产。设备定时产生数据,我们只要获取这些数据,加上车间主任制定的计划,就可以自动产生报表。当然,把报表放到牛魔王经理的桌上这种工作还需要小秘玉面狐狸来做。

3.从需求过渡到设计
需求过渡到设计的最终目的就是完成可用的软件需求和设计。告诉开发人员该怎么开发,才能完成客户的要求。所以这一阶段需要和开发人员,测试人员进行讨论,一并决定如何设计。这在很多公司都不受到重视,甚至无视,这是一种完全错误的做法。这些公司的做法是由一个较为资深的人单独决定什么该做,什么不该做,该怎么做。听起来不错,但是实际上资深的人往往并不如表面上那么“资深”,他在做决定的时候往往对可行性,可测性考虑太少。说到底,资深的人考虑的是上层抽象,“资浅”的人考虑的是实现细节,两方面合起来,达到的效果才能最好。

实际的过渡方法有很多种,现在流行的是OO方法通过编写用例,转化为领域模型,然后设计E-R模型,然后用UML中的静态视图,活动视图,交互视图等方法来完成初步的设计。但是有一点要清楚,UML是工具,真正的产出是我们的设计思想。我们一步一步把需求转化为设计的思想才是我们真正要追求的。

这里是我自己以及和同事,同学讨论的一个简单的方法的总结。

第一步我们有了类似上面那段话一样的需求。这样的需求常常被称为场景(Scenario),或者有时候还不构成场景。但是最起码我们知道了要做一件什么事情。于是我们可以把用户做这件事情的步骤一步一步写下来,这就是所谓的用例(Use Case)。但是很多人常常犯一个错误,总是把UC写成软件规格说明,常常写系统第一步做什么,第二步做什么,最后输出什么等等。我到现在还会不由自主的犯这种错误。记住:用例和场景都是用户从系统外部使用系统的过程以及系统给出的反馈。所有用例的总和就是该系统需要完成的所有任务。

第二步我们需要把用例转化为软件规格说明,但是并不是一下子转过去的。在这里,有两种方法。第一种是首先把UC转化为粗粒度的领域模型,这时候领域模型中的各个元素都是系统的各个组件(物理或者逻辑),这些组件相互作用完成系统的所有任务。然后对各个组件的相互作用进行分析,设计出系统接口,也是功能需求,最后对各个组件内部进行细分,自上而下的分析,最后形成细粒度的软件设计。第二种则是在UC和场景的基础上,对软件进行全面的评估,然后写出特性列表(Feature List)。每个特性都由一到多个功能提供实现。然后对每个功能都写一个Func Spec描述这个功能的软件规格说明。

第三步,就是把软件规格说明变成软件详细设计。这一步的花样就很多了,可以用UML大展拳脚,也可以用传统的伪代码模块化实现,也可以把一个一个函数的实现写出来。反正这一部分对于程序员来说是最亲切的。

总得来说,需求分析中最复杂的还是第一步,这一步做好了,后面的事情就是按部就班,逐步细化。并没有太多的技巧。而需求分析却需要很多技巧和经验,需要想记者一样不停地挖掘客户的真正想法。

系列文章:
软件开发方法浅谈(一)--软件开发过程
软件开发方法浅谈(二)--需求工程之需求获取


[1] 有些分法是把需求分为业务需求,用户需求和软件需求三种。还有更甚者增加系统需求。但是在我看来,业务需求应该包括在用户需求里面。在真正做软件的时候,当然可以把一些很独立的,成体系的行业规范单独列出。但在需求工程中,这部分往往已经包含在用户需求之中。

没有评论: