软件的非功能需求
在互联网的世界里,“用户就是上帝”这句话只体现在支付环节。
而在日常生活中,几乎每一个人都清楚的知道,不论是产品还是服务,品质决定竞争力,而对于一个软件、应用或者App来说,功能是生命线,确定能否安身立命,而非功能需求则是它的品质。
一个软件、应用或者App的特性表现在两个方面,功能性与非功能性。功能性好理解,硬指标,开发过程中的里程碑,一定要啃下的山头,而非功能性需求更偏“软”,如App好不好用,速度快不快,设计是否反人类等。在我们的日常生活中,非核心、非会员,只要带了一个“非”字,往往都不是那么重要的,可不能因为非功能性带了一个“非”字就常规鄙视它,。在遥远的古代(10年前),IT市场上的物资(应用)十分匮乏,这个时候,生存是文明的第一需要,能够实现主线功能就有能力去市场上冲冲浪,占占山头,用户也普遍具有超高的容忍度和耐心,即使有些许不爽也只能忍受着用着“卡/丑/难”的App;但在App如过江之卿的今天,用户们翻身奴隶把歌唱,分分钟可以卸载掉一个哪怕只有一点点让自己不爽的App,转身下载一个同类的,所需的成本不过滑动几下手指头。
所以,在这个用户心目中最好的信息时代里,即使是历史巨头如故步自封,也会在一日之间山河破碎,动摇根基,同样的,哪怕名不见经传的App,如视用户为上帝,想起所难,及其所及,可能会一朝成名天下知。
在当下的App爆发式增长,并且同质化严重的情况下,非功能需求这些个“软服务”会更好的体现出App差异化的特点,向用户传递特定观点,提供优质服务,从而能够俘获用户的“芳心”。
说了这么多,让我们来看看非功能需求都包括哪些“软”指标。下面是ISO/IEC 25010 软件质量管理模型:
可以看到,除了功能性外,影响软件产品质量的关键因素还包括效率、兼容性、易用性、安全性、可靠性、可维护性和可移植性7个维度,每个维度又包括了许多方面,涉及到架构、内容、交互、运营、安全等,这些都属于非功能需求的范畴。
非功能需求服务化
我们先来看一看非功能需求场景化的一些例子,这些例子只是我个人考虑到的,真实的场景数量会远远超出这些:
乍得一看,其实也没什么,无非的各种对开发者严厉,对用户友好的要求,但若是要仔细想一想,这些需求怎么样去一一实现它,就会觉得比较头疼了,放在哪里、哪个部门、哪个阶段貌似都不能一劳永逸,高枕无忧,因为有的需求需要的是服务器资源,如“支持动态用户1500以上”,有些需求需要的是开发过程解决,比如“系统支持多种浏览器”,还有的需求是需要应用发布之后,运维团队来实现,比如“普通修改一天内完成”,再有甚者,需要多种资源,多个团培配合着来,比如“应用热点/流量热点分析”等。
仔细想想,这可能也是非功能需求这一块普遍做的不如预期的原因,一个定义在软件质量模型里面的属性,竟然要指挥架构、运维甚至运营部们协作工作,可以想象其中的难度。
可以预见,要在非功能需求这块下功夫,甚至要打穿部门之间的壁垒,让不同的部门同时参与,互相协作,这是一个也过往完全不同的文化氛围,这不由让我们想到了DevOps这个炙手可热的名词,这算不算是殊途同归呢?
弄清了需要参与哪些人和部门后,我们再进一步来剖析具体的非功能需求应该放在软件生命周期的哪个阶段,亦或是以哪种形式存在:
效率
效率,关注点是业务量与资源容量的占比,以及业务流量的合理分配,对这一块提出的要求是宜尽量贴近适应实际的生产需求,并且具备应对业务量的变化(快速增长或者下降)的能力,不宜资源闲置浪费或因为资源调度的不灵活造成的生产影响,这两点开起来似乎有些矛盾,不过那是放在姿态的资源分配上,如果采用动态的资源分配方法,那么就像三维看二维一样,是有合理的解决途径的。关于效率的需求在开发和运维过程中都存在,并且是一个动态的需求;
兼容性
兼容性,软件之间是否能够正确地交互和共享信息。兼容性对于软件的意义取决于开发小组用什么来定义,以及软件运行的系统要求的兼容性级别。兼容性包括向后和向前兼容:向后兼容是指可以使用软件的以前版本。向前兼容是指可以使用软件的未来版本。在特定的时间内,可能存在多个版本同时存在的情况,并因此诞生出新的用户需求,如易用性需求,通俗来说就是用户体验;
易用性
易用性,是非功能需求里面最火的一个话题,也是最能体现软件是否按“用户就是上帝”的态度来设计的评判标准之一,易用性是与一组规定或者潜在的用户为使用其软件所需做的努力和对这样的使用所作的评价有关的一组属性。具体包括:易理解性、易学习性、易操作性等。这类非功能需求是与UI/UE设计有着直接关系的,也就是说这类属性会关联到具体的技术性功能需求,也因此,UE到底是划分在功能性需求还是非功能性需求上,尚有一些争议,但是主流观点都认为,这是非功能性需求的一个典型部分;
安全性
安全性,包括传输加密,存储加密,可破解性,以及各种未被授权的用户行为如何防范和控制等,这里的安全不单针对外部普通用户,也针对内部不同级别的权限用户的的控制,不单指服务端,也包括传输通道,客户端,细到精巧的技术渗透如慢速撞库,粗到混合流量的DDoS攻击,都需要考虑在内,在生活中我们做任何事情都需要安全感,在信息世界中这种需要更被放大了许多。在安全性的考虑上,需要综合考虑架构层、网络层和应用层的安全,还有一个非常重要的因素就是安全的ROI,这里不单单指投入的金钱,更指投入的资源,因为,往往安全性和易用性可能是成反比的,所以,灵活适用是安全的一个重要前提;
可靠性
可靠性,在规定的一段时间和条件下软件维持其性能水平的能力有关的一组属性。具体包括:
成熟性
与有软件故障引起失效的频度有关的软件属性。
容错性
与在软件故障或违反指定接口的情况下维持规定的性能水平的能力有关的软件属性。如离线录入支持等。
易恢复性
与在是小发生后重建其性能水平并恢复直接受影响数据的能力,以及为达到此目的所需时间和努力有关的软件属性。如表单数据自动保存等。
这类非功能需求通常是全局的,他除了与系统运行环境、平台选择、代码质量相关之外,还会涉及部分技术性功能需求,他别是容错性、易恢复性的实现都需要一些具体的功能来支持;
可维护性
可维护性,维护性是指与进行指定的修改所需的努力有关的一组属性。具体包括:
易分析性
与为诊断缺陷或者失效原因及为判定待修改的部分所需努力有关的软件属性。如日志记录系统等。
易改变性
与进行修改排除错误或者适应环境变化所需努力有关的软件属性。
稳定性
与修改所造成的未预料结果的风险有关的软件属性。
易测试性
与确认已修改软件所需的努力有关的软件属性。
这部分通常是开发团队最容易投入时间和成本的地方,诸如动态属性支持、UI界面生成、流程引擎等都是为了提高系统的可维护性,因此它显然是会引申出相关的技术性功能需求的。更进一步的时,在应用发布的运维和运营工作中,对可维护性的需求也是越来越来,因此,一些需要频繁变化或者做安全隔离的非功能需求的实现可以从软件开发包里单拉出来,形成单独的服务交付层,用来实现更多的对可维护性要求高的目标;
可移植性
可移植性,简单来说是软件是否具备在不同的环境中转移的能力,具体包括:
适应性
与软件无需采用有别于为该软件准备的活动和手段就可能适应不同的规定环境有关的软件属性。如全球技术支持等。
易安装性
与在指定的环境下安装软件所需努力有关的软件属性。如在线更新、安装包自动生成等。
遵循性
使软件遵循与可移植性有关的标准或约定的软件属性。
易替换性
与软件在该环境中用来替代指定的其他软件的机会和努力有关的软件属性。
这部分除了需要通过选择正确的开发工具、平台来支持外,也会涉及一些技巧性的功能需求,如全球语言支持等。
好了,上述我们分析了这么多,我们发现非功能需求的有一些共同点:
1.当不仅存在于开发阶段,还存在于运维阶段与运营阶段;
2. 在实现自身需求的同事,会涉及或者引发新的需求;
3.对实现手段的灵活程度和后续的管理与维护的便捷度有要求。
基于以上三个特点,我们发现基于非功能性需求的实现不论是单单放在开发阶段,还是只放在运维阶段,都是不完美的,因此,我们大胆假设,独立设计一个应用服务层,用户实现非功能需求的场景,并且贯穿与开发与运维的生命周期内。
非功能需求在运维工作中的体现
在日常的运维工作中,我们经常面对非功能需求的目标场景,只是也许我们意识不到,大到多活中心应用发布与运维,跨云中心应用发布与运维,DNS智能解析,跨中心Cookie会话保持,小到用户身份识别与流量˙转发,长连接MBLB的拆分及转发,Http参数优化又或者是URL重写,以及加强认证授权管理等,都属于可靠性、安全性、易用性的范畴,还有更多数不完的实际工作任务都可以归到肺功能需求这一块,为什么原来仅仅是在软件质量模型里的需求现在已经延伸到了运维工作中,是因为开发与运维的界限慢慢模糊化了,对应用品质的追求的过程中人们也慢慢找到了规律,积攒了经验。而在运维工作里,我们早就已经有了一个概念,叫做应用交付层,这一层能够提供计算、分流、安全、卸载等功能,并且能够无视数据中心数量与形态的变化,与应用紧密结合在一起,旨在为用户提供高品质的应用和服务。
但是,目前来说这部分的工作还是存在着明显的不足,因为这些仅仅还是属于运维部门的工作,而且效率也远远谈不上高效,通常都是以在固定的工程时间窗口里完成有限的变更这种手段来完成,而对于应用的不了解导致能完成的工作也极其有限,这种方式让我们看到了企业追求卓越品质的意愿,但是与实际上用户与市场的需求想去甚远。
针对运维工作中提供非功能需求实现与维护的场景,我们为了弥补环境多样化、效率低、需求不明确等诸多不足,应该做到以下几点:
01.构建跨平台的应用服务交付层,建设一致交付的能力,满足可靠性的要求;
02.应用服务交付层应具备优秀的应用交付服务能力,满足效率的要求;
03.实现应用的部分非功能性需求解耦,满足易用性与可维护性的要求。
完成了上面三点,还不够,前文已经提到,非功能性需求不是在一个环节、一个阶段内能够完美搞定的,所以,我们要打通渠道开发的那条线,想要打通开发那条线,不是说说就可以了的,必须具备开发的一些“属性”:
01.要能够实现服务交付即代码,及所有运维平面的工作,能够通过代码来实现;
02.要能够与运维平面的服务等级与能力保持一致性;
03.实现的非功能需求的服务能力要是安全的,可控的;
04.所有开发测代码实现的非功能需求,可以无缝转化为服务交付层的服务能力。
非功能需求在开发工作中的体现
前面谈了运维工作中的非功能需求的实现,以及如何与开发工作中的肺功能需求结合,那么下面我们来谈谈在开发工作中如何较好的实现和管理非功能需求场景。
我见过不少的互联网应用,在本身的代码层里已经写入了一些非功能需求的实现,但是可谓是惨不忍睹,稍好一些的一个例子是,在前端页面用JS来监听事件,判断用户的行为,来做一些安全的审查和表格填写的审计,比如,用户输入了类似注入攻击的字段,又或者是有些输入没有输入必须要填的信息等,这样的实现手段落后不说,实际上还存在多重风险:
1如果在业务发布的时候有经过WAF,那么这里的代码实际上就重复了,不但没有提高应用的品质,反而降低了效率;2较多的js事件监听,会造成潜在的安全风险;3不能适应敏捷的变更,如果涉及到这里写死了的策略需要更改,就需要改应用。
除了上述的例子,还有数不清的类似的情况,因为开发人员关心的是主线功能的设计与实现,而现在的敏捷开发更是引入了Sprint的概念,时间分秒必争,到了非功能需求的实现的时候就可能会出现敷衍了解,亦或者锁边从一些公共的或者缺乏有效管理的库或者源拉一个就用,这样不论是对效率、安全、以及维护的便捷性来说都不是一个好的办法。
那么,按照在运维侧的思路,我们是否也可以为我们的应用独立设计一个服务交付层,将非功能性的需求实现放在这里,而这些需求可以采用更专业的实现的同时,同时也隔离了一些公共代码和库的安全问题,更妙的因为代码实现的场景能够无缝的部署在运维侧,所以能够和运维打通,互通有无,能做更多的事情,提升应用的品质。
如上图,我们可以在代码code阶段就设计为App code 和ADC Code,然后再build阶段先集成App的code,然后做测试,在Deploy阶段的时候由CI Server从github上拉取ADC的code,然后一起部署App和ADC Service到服务器或者容器平台,ADC的code部门还可以再细分成ADC code 和Security Code,后者用来做应用层的安全防护,在这样的情境下,在每一次code的阶段就设计好ADC 和Security的实现,和App Code 同时Deploy,实现了整体应用和安全交付的CI/CD和快速迭代,极大的提高了生产和运维效率。
如果想实现开发侧的应用交付层的设计,需要具备以下的能力:
1要能够实现独立的服务交付层,与应用核心代码解耦;
2要够无缝的集成CI/CD;
3实现的功能无开发语言无关为佳。
DevOps提升App品质
前文提到,软件的非功能需求决定了软件的品质,在某些程度上与DevOps是不谋而合的。在DevOps的文化里,不紧紧的打通了运维与开发的屏障,更是将各个阶段形成了一个生生不息的循环,形成一个持续集成、持续交付的生态,如果说DevOps是一种文化,一种氛围,追求高品质的App是目的,那么,努力发展非功能需求的实现及优化则是一种行之有效的手段。
由于实现了非功能需求的服务化,在一个良好的DevOps的氛围里,我们甚至可以利用这些服务来做在线BI甚至精准营销,由运营侧提出需求,指定基于App的用户行为分析图,然后分析收集的数据,反向推动优化非功能需求的实现甚至是主线功能需求的优化,从而达到提升客户满意度,提升市场占有率的目的。由于我们已经打通了应用交付服务的关节,所以这些数据和分析与每个部门各自为战比起来,要精准、快速、高效的多。
原文转自:http://www.uml.org.cn/RequirementProject/201910312.asp