软件开发如何应对非功能性需求变更?

历经数月的辛勤开发,软件项目终于接近尾声。系统功能已基本完成,正准备按部就班地进行最终测试时,客户突然提出变更某些非功能性需求(Non-Functional Requirements, NFR)。这对于软件开发团队而言,不亚于突发状况,也是令开发人员感到最为棘手的事情之一。因为在多数情况下,对非功能性需求的变更往往会演变成一个对系统无休止的修改过程,最终可能将客户和开发团队都拖入泥潭而难以自拔。

需求变更是客户的权力,若确有必要,理应尽量满足。但问题在于不能让变更权力被滥用,避免将一些无关痛痒的非功能性需求变更纵容成堂而皇之的正式变更。客户对于非功能性需求总会有新的想法,导致项目似乎永远无法终结。以前遇到这种情况时,我常感到沮丧,觉得自己不幸碰到了这样的客户。但在读了《设计模式精解(Design Patterns Explained)》一书中的段落后,我恍然大悟:这不是个人的错,世界本就是如此,唯一不变的就是变化。

令人烦恼的非功能性需求变更

在软件开发中,大家都会遇到这样的问题:客户的一个新想法,就推翻了之前经过再三讨论而确认定下来的需求。如果是功能性需求变更,相对容易接受一些,毕竟功能性需求若不实现,会大大影响软件产品的质量。但在实际负责的开发项目中,遇到的往往是一些非功能性变更,且许多看起来无关痛痒、细微琐碎。

什么是非功能性需求?

在 IEEE 标准中,软件需求的定义是:用户解决问题或达到目标所需的条件或功能。一般包含业务需求、用户需求、功能需求、行业隐含需求和一些非功能性需求。

  • 业务需求:反映了客户对系统、产品高层次的目标要求。
  • 功能需求:定义了开发人员必须实现的软件功能。
  • 非功能性需求:是指为满足用户业务需求而必须具有除功能需求以外的特性。

非功能性需求包括系统性能、可靠性、可维护性、易用性和对技术及业务的适应性等。其中最常见的是软件界面、操作方便等一系列要求。

非功能性需求变更的特点

让我们从客户角度和开发人员角度去看看非功能性需求的特点:

  1. 工作量评估差异:有些非功能性小需求从客户角度看起来工作量不大,但实际上开发人员要耗费比较长的时间去完成。
  2. 决策随意性:许多非功能性需求(如界面美观、操作方便等)往往是客户头脑一热,或管理层临时决策就部署下去的需求,通常是原来在需求分析阶段所没有注意的内容。

其实,非功能性需求常常被轻视,甚至被忽视。原因是非功能性需求描述很困难,它很难像功能性需求那样,可以通过结构化和量化的词语来描述清楚。在描述这类需求时,我们经常采用“软件性能要好”、“操作要方便”、“软件界面要美观大方”等较模糊的词语。例如,易用性就同时涉及到美工和 UI 界面、人机工程、交互式设计、心理学、用户行为模式等内容。这类描述词语都是脱离了软件的执行环境,是对人和相关场景的描述,因此很难体现到软件架构设计和具体的实现中。

为什么非功能性需求变更会频繁发生?

为什么非功能性需求不能固定下来?或定下来后就不许变了呢?通常有许多人会问这样的问题。实际上,当他变成了客户时,可能就不会问这个问题了。

非功能性需求容易产生理解分歧

在软件需求分析阶段,客户和开发人员对非功能性需求的理解呈现“大体上共识多,细节上差异多”的特点。这一般跟分析员的知识、背景,还有客户表述的标准程度、双方的交流情况有关。即使通过反复沟通,以实践经验来看,非功能性需求的描述还是永远不够清晰、不够明确的,主要是因为在这个阶段所谓的产品还只存在于大家的构思中。

作为一个客户,大多数情况下是不懂技术的,但他所需要的软件在心里还是有一个印象的。他会想象出软件的样子和功能,然后通过口头或者笔头的方式告诉需求分析人员。简单来说,在这个阶段用户往往不能确切地定义自己需要什么。用户常常以为自己清楚,但实际上他们提出的需求只是依据当前的工作所需,或者是他们想象出来的东西。结果是当客户向需求分析人员提出需求的时候,往往是通过自己的想法用自然语言来表达的。这样的表达结果对于真实的需求来说只是一种描述,甚至只是某个角度的描述,远远不能保证这样的描述可以得到百分之百的正确理解。

当客户提出要求之后,在双方认为理解大概没有分歧的时候,开发人员就开始工作了。但随着开发工作的不断进展,系统开始展现雏形,客户对系统的了解也逐步深入。这个时候,客户就会对系统的界面、操作、功能、性能等有一些了解,就有可能提出需求变更要求,而且这些要求很多是基于主观的、人为的因素。总之,他们了解得越多,新的要求也就会越多。

没有明确的需求变更管理流程

在软件开发中的常识是,一旦发生需求变更不要一味地抱怨,也不要一味地去迎合客户的新需求,而是要管理和控制需求变更。但令人不解的是,我们常常看到变更的提出、讨论和执行常常只停留在口头上。这样做有两个弊端:

  1. 追溯困难:时间一长,无论是当事人还是开发团队都说不清楚变更是因何发生以及结果怎么样了。显然,这对于提高项目质量、改进开发过程是很不利的。
  2. 缺乏约束:由于缺乏形式上的约束和对变更代价的定量分析,变更会被非常随意地提出、或被草率地执行,也会大大影响项目的进展和开发质量。

因此,没有明确的需求变更管理流程,就会使需求变更变得泛滥。因为并不是所有的变更都要修改,也不是所有变更都要立刻修改。需求变更管理的目的是为了决定什么类型的变更需要修改和什么时候修改。比如界面风格问题,就可以先不修改,或者规划一下修改的时间待到以后进行优化。

没有让客户知道需求变更的代价

对变更的影响没有评估是需求变更泛滥的根本原因。变更都是有代价的,应该要评估变更的代价和要让客户了解需求变更的后果。如果客户不知道需求变更付出的代价,对开发人员的辛苦就会难以体会。

相比于需求开发人员而言,客户可能对需求变更认识不足,认为他们出钱,软件开发团队就要为它服务。因此,客户对需求变更往往会肆无忌惮,将需求变更视为儿戏,随个人喜好随意变更需求。所以,在和客户接触时应该挑明态度,特别是要让他们清楚需求随意变更所带来的代价和风险。如果客户认为代价太大,那么开发人员就没有必要及时修改,按原来的进度走,但仍要记录变更,待下一版本再修改。

如何有效控制非功能性需求的变更?

做任何变更之前,我们都要考虑后果。由于非功能性需求变更在开发中所处的重要地位,一旦需求发生变化,影响面是很广的。因此,有效控制非功能性需求频繁变更是一件不容小视的事情。

建立明确的非功能性需求基线

对于软件开发来说,变更无可避免,也无从逃避,只能积极应对。因此,在开发过程中,建立明确的非功能性需求基线是一件重要的事情。如果非功能性需求没做好,基线范围就含糊不清,就容易被客户抓住空子,往往要付出许多无谓的变更。如果非功能性需求基线做得好,文档清晰且又有客户签字,那么后期客户提出的非功能性需求变更就会大大减少。因此,在建立需求基线的时候千万不能手软,这并非要刻意针对客户,而是不能让客户养成经常变更的习惯,否则后患无穷。

建立需求变更管理流程

需求变更对软件开发成败有重要影响,既不能一概拒绝客户的变更要求,也不能一味地迁就客户,所以必须要做好需求变更的控制。有句通俗的话说得非常好:需求变更管理的目的不是控制变更的发生,而是对变更进行管理,确保变更有序进行。需求变更管理流程包括变更申请环节、审批人员、审批事项、审批流程等。

目的有两个:

  1. 规范化流程:将客户下达变更的流程尽可能地规范化,减少张嘴就来的非必要、非紧急、非合理、非高层领导意图的无效变更。
  2. 留存依据:留下书面依据,为今后可能的成本核算准备好变更账。

因此,凡未履行审批程序的变更,一律是无效变更不予受理。在实践中,人们往往不愿意为小的需求变更去执行正规的需求管理过程,认为降低了开发效率,浪费了时间。但正是由于这种观念才会使到需求变更逐渐变为不可控,最终导致项目的失败。

确认客户是否接受变更的代价

需求变更作为一个计划外的风险对项目肯定存在冲击,只是大小的差别。而且客户的需求是永远不会满足的,可能一天一个样。为了达到控制频繁的需求变更,需要将变更后产生的成本进行评估与量化,形成分析报告提交双方领导。否则,一味的妥协只会让项目进一步恶化。因此,要让客户认识到变更都是有代价的,不要让客户养成随意变更的毛病。一般来说,如果客户认为该非功能性变更是必须的,而不是其上级领导拍脑袋提出的,就会接受这些代价。通过与客户的沟通和协商,开发团队即使没有回报也不会招致客户的埋怨。

加强合同约束力

虽然软件开发合同很难在签订之初就能够精确定义每项需求,单靠合同是帮不上忙的,但也不能忽视合同的约束力。因为有时销售人员为使客户能够快速的签订合同,往往草率决定和片面同意客户提出的需求。当客户提出新的需求时,销售人员往往一看“应该”只是一个小小的修改,没有太大的影响,可能会直接答应能变更。所以,在与客户签订开发合同时,可以增加一些相关条款,如:

  • 限定客户提出需求变更的时间。
  • 规定何种情况的变更可以接受、拒绝接受或部分接受。
  • 规定发生需求变更时必须执行变更控制流程等。

加强感情沟通,注意沟通技巧

大多时候单靠合同的约束力是解决不了纷争的。客户着急了就是一句潜台词:做不做,若不想做可能面临终止合作的风险,想做的公司多着呢。例如,有时明明是不合理的要求,可是客户也会狡辩凭什么不给他们做,这可是合同范围内的工作。所以,单看合同是没用的。

那可怎么办呢?通常的做法是通过感情联络,争取客户的理解。我们常常对客户说的一句老生常谈的话,就是提需求也要讲究合情合理,这句话在变更管理中有着独特的意义。用我们的行话说是:做好需求变更管理控制只是做好了一半的工作,还有一半的工作就是去讲道理,去用心、用感情劝客户回头。

月有阴晴圆缺,潮涨潮落。变化并不一定总是给我们带来麻烦,有时也会带来惊喜。在软件开发中,对待客户提出的非功能性需求变更,我们需要用平常心去看待,不是一味拒绝,也不要一味答应。

说明:本文所述方法论主要基于传统软件工程视角,强调基线与流程控制。在现代敏捷开发(Agile)或 DevOps 实践中,需求变更更为频繁,建议结合迭代计划与用户故事地图(User Story Mapping)灵活调整变更管理策略。