问题背景
敏捷开发中许多活动都是全员参与而非专人参与。需求分析同样也可以是全员参与 的一个活动。这反映了敏捷开发的"个人与交互胜过过程与工具"的价值观。需求分析是在需 求理解的基础上进行的。因此,全员参与需求分析有助于及时发现团队成员对同一个需求理解不一致的 问题,这很大程度上避免了缺陷的引入。另外,也有助于规避人力风险。比如,一个需求的开发者突然 需要请假,其他开发者可以马上顶替他,因为其他人也参与了其负责开发的需求的分析。此外,全员参 与需求分析也有助于全体成员的能力的提升。但问题是,通常多数的开发人员和测试人员他们的能力和 经验不足以胜任需求分析工作。这意味着全体成员参与的需求分析活动需要一个扮演导师角色的人带领 大家去进行有效的需求分析。本文以笔者带领团队成员做需求分析的实际经验分享了敏捷开发团队中需 求分析的一些关注点和方法。
区分“什么”与“怎么”
爱因斯坦曾说如果他有一个小时 来拯救世界,他将花 55 分钟去定义这个问题而只花5分钟去需求解决方案。
这句话道出了理解 问题本身对于解决问题而言的重要性。而软件开发可以看做解决问题的过程。软件开发所要解决的问题 就是如何将需求转换为代码。需求反映的是"什么"(What)的问题。开发人员在需求分析时 往往易犯的一个问题是急于考虑"怎么"(How)的问题,而这是设计所要解决的问题。
而从问题解决的角度来看,要解决一个问题首先要弄清楚的是"问题"究竟是什么。 这就好比两个人赛跑,先到终点的人有奖金。而终点明明在南边,而甲以飞快的速度跑到北边,结果他 还是输了。因此,项目经理应当引导团队成员在需求阶段先关注需求本身,而非过早得考虑设计的问题 。
分析需求的合理性与完整性的利器——需求背景
敏捷开发中往往采用 User Story 的 方式描述一个需求。一个 User Story 的典型格式如下:
作为 XX(角色),我希望……(系统 能够实现...),以便……(达成某业务目标)。
比如,下面是一个 User Story 的具体例子:
作为手机用户,我希望能够查阅我的通话记录,以便核实我的消费情况。
可见,User Story 是从两个方面对需求进行表述的:需求背景和需求陈述。需求陈述告诉我们系统要做什么,它反 映了客户所要(want)。而需求背景告诉我们系统为什么要做某件事,它反映了客户的业务需要(need )。结合一个需求的这两个方面,有助于分析需求的合理性。对于不合理的需求应该及时拒绝,否则不 仅浪费了团队资源,系统上线后还可能给利益干系人带了损失。
传说,牛顿有大小两只猫,为 了方便让这两只猫出入,他在墙上开辟了大小两个洞。这个故事里面描述了一个需求:要开辟大洞小洞 各一(需求陈述),以方便大小两只猫出入(需求背景)。
事实上,一个大的洞就可以满足实 际的需要了。可见,需求陈述可能和需求背景实际上是不吻合的,这也正是我们分析需求合理性的一个 着实点。
了解一个需求的背景对于理解和分析一个需求来说至关重要。因为需求背景不仅有助 于理解需求,回答我们的疑问,也有助于对需求进行进一步分析。比如,移动网络中的广告可能要求广 告内容的个性化定制,即每个用户看到的广告的内容可能都不一样,这些广告的内容因受众的年龄、性 别等个人信息而异。显然,系统需要先查询用户个人信息然后再根据终端用户的个人信息去查询广告内 容。那针对这样一个需求,我们可能会提出这样一个问题:如果用户个人信息查询失败,系统是否还需 返回广告内容呢? 而需求陈述中并没有提及这点。考虑需求背景可以帮助我们自行找到这类需求完整 性问题的答案——根据个人信息获取定制的广告其目的是更好地定位潜在消费者,若无法获取用户个人 信息,则返回适宜大众阅读的广告也无妨。
分析需求的一致性
即便是同一个迭代中的需 求,其描述也可能是前后矛盾的,或者前后不同的。这就产生了一致性的问题。只不过有些一致性问题 比较明显,如下文所描述的与前文并一致,文字描述与相关图片、附件不一致。而另外一下一致性问题 则比较隐蔽,需要通过逻辑推理和综合分析才能发现。
分析需求的兼容性
迭代开发中 ,当前迭代往往涉及对前面迭代中已经实现的的需求的变更,而在此次变更之前该需求可能已经经历若 干次变更了。这种情况下,我们特别需要关注这些变更间的兼容性。因为前些迭代中实现的这个需求可 能已经上线运行了,需求变更应当考虑到它对线上的系统可能带来的兼容性问题。否则,新的迭代发布 的版本若与线上的版本不兼容,很可能给客户带了重大损失。
区分知识层与操作层
我曾 经听说过这样一个例子。在一个医院管理信息系统中,客户信誓旦旦得说一个病人转科室最多只会出现 三次。于是,开发团队就把病人转科室的功能做成了只能转三次。后来这个系统上线后,有个病人转了 三次科室后又需要被转回到最初的科室。于是,用户开始抱怨为何只能转三次。
事实上,上面 故事中的功能从需求阶段上就已经引入了缺陷。其原因倒不在于客户是怎么说的。而在于需求分析时没 有区分需求的知识层和操作层。上面例子中,允许病人被一个科室转到另一个科室,这是知识层的问题 ,而转科室的具体次数则是操作层的问题。混淆知识层与操作层这两个层次往往会产生问题。因此,上 述例子中的需求应该正确得理解为:病人可以被从一个科室转到另一个科室。转科室的次数为 N 次 (N>0)。也就是说系统只要能够支持病人转科室即可,而具体一个病人会被转多少次科室,那是软 件上线后具体操作的问题。作为软件开发人员我们并不能也没有必要知道这个数量。
区分知识 层与操作层的具体实现往往可以采用系统参数化(如通过配置文件实现参数化)。比如,为了防止一个 系统被恶意登录。很多系统可能会在多次登录失败后,将相关的登录账号锁住。但具体的登录失败次数 应该是可以在系统运行过程中动态调整,因为这是个操作层的问题。
可见,区分需求的知识层 和操作层可以使交付的系统更具可用性,减少系统的不必要的改动量,节约团队资源。