DevOps落地笔记-05|非功能需求:如何有效关注非功能需求

上一讲主要介绍了看板方法以及如何使用看板方法来解决软件研发过程中出现的团队过载、工作不均、任务延期等问题。通过学习前面几个课时介绍的知识,你的团队开始源源不断地交付用户价值。用户对交付的功能非常满意,但等到系统上线后经常出现服务不可用的情况,比如:服务出现单点故障,这个时候运维团队就要处理这些焦头烂额问题了。这是因为在软件开发过程中,团队关注的一直都是用户需要的功能,忽略了那些能够让产品维持工作的非功能需求。今天介绍的内容——有效关注非功能需求,就是教我们要在关注功能需求的同时,也要关注非功能需求。帮你彻底改善软件系统的可用性和性能。

什么是非功能需求
当谈起需求,很多人都认为是“用户需求”,需求也分为不同的种类。需求的分类可以参考由惠普的 Robert Grady 设计的 FURPS+ 需求分类模型:

& 功能性(Functionality);

& 易用性(Usability);

& 可靠性(Reliability);

& 性能(Performance);

& 可支持性(Supportabilit)。

FURPS+中的“+”号指的是其他需要关注的方面,比如:

& 设计需求(Design Requirements);

& 实现需求(Implementation Requirements);

& 接口需求(Interface Requirements);

& 物理需求(Physical Requirements)。

该需求分类模型包含了功能性需求和非功能性需求。功能性需求指的是产品功能,比如:聊天功能,支付功能等。非功能性需求是整个系统交付的标准,比如系统可靠,性能高等。

功能需求通常很容易定义、度量和测试,一般可以描述为特定系统执行特定功能的需求。就像前面课时中提到的用户故事,作为用户,当我在地址栏里输入内容时,显示所有可用的地址列表。因此,功能需求通常被视为系统“应该做什么(What)”。

非功能需求则较难定义、度量、测试和跟踪,这也是经常被忽略的原因。一般可以描述为系统如何提供功能。比如,当用户在地址栏里输入内容时,要快速的显示所有的地址列表(性能)。因此,非功能需求通常被视为系统“应该如何做(How)”。

为什么要关注非功能需求?
在《敏捷宣言》里讲到,“可工作的软件,胜过面面俱到的文档”。这里的“可工作”是对交付到用户手中的软件最重要的度量标准,软件不仅要具备用户需要的功能,还要能够持续不断的使用该功能。但实际情况却不尽如人意,这是因为我们在开发软件的时候,总是关注功能性的需求,而忽略非功能性的需求。我举个例子,下面这张图是一座冰山,当一个管理家庭地址的需求被提出后,用户需要的功能是新增、编辑、删除和查询家庭地址,但在这几个功能需求的背后却是表单重复提交验证、浏览器兼容、性能、用户身份认证等隐藏需求。没有这些隐藏需求,一般情况下用户也能使用该功能,但在使用的过程中,就会出现各种问题,令用户体验非常不好。
在这里插入图片描述
随着敏捷开发方法的采用,这一问题已经有所转变。比如,将非功能需求和功能需求一起纳入流程管控等措施。在 DevOps 实践中,这个转变更进了一步,产品负责人要关注整个产品需求,包括功能需求和非功能需求。只有从源头上重视非功能需求的开发,团队才能真正交付 “可工作” 的软件。下面介绍一下在软件开发流程中,如何关注并落实非功能需求。

如何关注非功能需求?

在软件开发过程中,明确定义的非功能需求的实现是用于评估整个软件成功的关键。功能需求的实现表示用户可以使用该软件提供的功能,非功能需求的实现表示用户可以一直使用该功能。定义明确的非功能需求,不仅容易度量和测试,而且团队也能更好地了解这个需求离实现还有多远。

非功能需求的管理

既然非功能需求对于系统交付非常重要,那么在系统一开始团队中的每个人都要考虑非功能需求,以及它们对系统架构,系统交付时间,测试策略和总成本的影响。

需求管理

非功能需求和功能需求一样,它们也有实际的业务价值,在需求管理阶段就要将其纳入统一的流程管理。比如“管理家庭地址”的需求,在进行“新增地址”功能需求排期的同时,也要考虑“表单验证”“表单重复提交验证”“身份认证和授权”“浏览器兼容性”等非功能需求。因此,需要创建一些具体的任务来管理这些非功能需求,或者在其他功能需求中加入非功能需求的验收条件。

跨团队协作

非功能需求又被称为“跨功能需求”,因此在非功能需求的讨论、方案的制定,验证条件等方面,都需要其他团队一起来完成。安全性相关的需要安全团队,性能、可扩展性相关的需要架构团队,验收方面需要测试团队,监控告警方面需要运维团队。跨团队协作不容易,我的建议是将这件事情写到每个团队的 OKR 里,这样大家的目标就一致了,实施起来会更加容易。

权衡利弊

非功能需求的实现是有成本的,而且它们之间可能彼此排斥。比如,对安全性要求高的系统往往易用性就不会太好。在理想情况下,每个人都想开发出具有高安全性、高性能、高扩展性、高易用性的系统。但是,在实际开发中,考虑到系统的交付时间,系统的总成本,往往会根据非功能需求的实现难度,做出权衡。

非功能需求的分析

非功能需求的分析也是非常重要的一部分。在进行需求分析的时候,不仅要分析出系统所提供的功能需求,同时也要知道这些功能存在的限制条件。

这里介绍一个四层非功能需求分析法。该方法包含一些规则和非功能需求分析的过程。通过这种方法,我们可以确定系统提供的功能,子功能和每个子功能需要具备的非功能需求。有利于从不同的视图识别所有的非功能需求。这种方法的目标是找出任何系统中都非常重要的非功能需求。如下图所示。
在这里插入图片描述
任何一个系统的需求都可以总结为下面这句话:每个<系统>提供<功能>给<关系人>,每个<功能>必须满足<条件>才能满足<关系人>的需求。

正如前面提到,功能需求表示系统应该做什么(What),非功能需求表示系统应该如何做(How)。 上图利用分层的方法非常清晰地将系统具备的功能需求和非功能需求表示出来。前面三层是功能需求的拆解,第四层是每个子功能具备的条件,即非功能需求。

整个非功能需求的分析过程可以分为下面四个步骤:

step1:识别系统中的关系人;

step2:基于开发人员的知识和经验,从关系人角度制定功能目标;

step3:拆解功能为子功能;

step4:识别每个子功能中的非功能需求。

下面利用四层非功能需求分析法分析开头的 “管理家庭地址” 的需求,结果如下图所示:
在这里插入图片描述
经过这个分析过程,就非常清楚地知道哪些功能需求需要具备哪些非功能需求,可以基于分析结果编写用户故事以及验证标准。

非功能需求的度量

为了使系统能够达到验收的标准,在定义非功能性需求的时候就需要是可度量的,这样团队才能知道非功能性需求当前值是多少,离满足要求还差多少。上面提到非功能需求是指系统应该如何做,即对系统属性和质量的描述,比如:可扩展性、可靠性、高性能等,这些都属于定性的描述。定性的描述缺少量化的指标,是不可度量的,这一点团队在定义非功能性需求时应该注意。

还是以上面的例子为例:

“快速地显示所有的地址列表”,这就是一个定性的描述,它是不容易度量的,也是不容易测试的,不知道要达到多快才能满足要求。

修改后:

“0.1s显示所有的地址列表”,这就是一个定量的描述,提出了对该非功能需求的度量、测试和验收标准。只要能在 0.1s 内显示所有的地址列表,就能满足要求。假如在一次测试时得到的结果是 0.2s,团队也很清楚地知道还需要再提高 0.1s 才能满足要求。

常见非功能需求的度量指标有:

& 吞吐量: TPS(Transactions Per Second)每秒处理事务数,QPS(Queries Per Second)每秒查询数,RT(Response Time)响应时间。

& 可靠性: MTTF(Mean Time to Failure)平均无故障时间,MTTR(Mean Time to Repair)平均故障恢复时间,MTBF(Mean Time Between Failure)平均故障间隔时间等。

& 扩展性: 随着服务器数、服务数或线程数的增加,单个请求的响应时间和并发用户数。

目前在监控或统计系统中都会包含上面的度量指标,如下图是请求 QPS 变化趋势图:
在这里插入图片描述
非功能需求的设计
非功能需求在设计时可以遵循下面两个原则。

1. 面向对象设计的 SOLID 原则。

SOLID 原则是由 Robert C. Martin 于 2000 年编写的面向对象设计的五个原则。后来,人们将这五个原则的首字母组成缩略词,也就是SOLID,并被业界广为流传。这五个原则是:

1.单一责任原则(Single responsibility principle),指一个类有且只有一个职责。这个原则增强了类的灵活性和可维护性;

2.开闭原则(Open/closed principle),指一个类对外扩展开放,对修改关闭。这个原则增强了类的可扩展性和可维护性;

3.**里氏代换原则(Liskov substitution principle),**指程序中使用基类进行定义,在运行时再确定其子类类型,用子类对象替换父类对象,这个原则增强了类的灵活性和可扩展性;

4.接口分离原则(Interface segregation principle),指类的依赖关系应该建立在最小接口上,即建立单一接口,而不是臃肿庞大的接口,这个原则增强了类的可维护性和可扩展性;

5.依赖倒置原则(Dependency inversion principle),指高层模块依赖抽象类或接口,而不是具体的类,这个原则增强了类的可扩展性。

SOLID 原则处理的是面向对象中的类、接口、继承等元素,能够更好地满足面向对象设计中的非功能性需求。

2. 微服务设计的 IDEALS 原则

如今,随着微服务架构的广泛应用,SOLID 原则并不能完全适用于分布式系统中的**“微服务”**这一元素。Paulo Merson 提出了一套微服务设计的核心原则,即 IDEALS 原则。IDEALS 是这几个原则首字母组成的缩略词。原则如下:

接口分离(Interface segregation) 指的是不同类型的客户端,如,移动应用程序、Web应用程序、CLI程序,能够通过适合其要求的协议与服务端交互;

可部署性(Deployability (is on you)) 指的是在微服务时代,也就是 DevOps 时代,开发人员需要在打包、部署和运行微服务方面做出关键的设计决策和技术选择;

事件驱动(Event-driven) 指的是在任何时候,都应该通过异步消息或事件进行调用,而不是同步调用;

可用性胜于一致性(Availability over consistency) 指的是最终用户更看重系统的可用性而不是强一致性,他们对最终一致性也很满意;

松耦合(Loose coupling) 指的是服务之间相互依赖的程度,对于基于服务的系统来说,传入耦合与传出耦合的设计是一个重要问题;

单一责任(Single responsibility) 指的是服务内聚性,一个服务只包含单一职责,功能庞大服务在维护和部署方面都会变得繁重。

SOLID 原则和 IDEALS 原则是在进行系统架构设计时需要遵循的核心原则,可以有效地提高系统在非功能性方面的质量要求。

非功能需求的测试

前面也提到,非功能需求是验证系统是否满足要求的衡量标准。这里以**“响应时间”**为例,简单介绍一下非功能需求的测试方法。

定义基准

目标明确的基准式测试有利于判断局部代码优化为系统带来的具体影响,例如,在添加数据缓存后,与基准数据比较,响应时间到底提升了多少。

定义场景

把系统的一个具体使用场景作为一个测试。不同使用场景对测试的要求和验收标准不一样,同样是响应时间这个指标,当数据量在 1000 和 1000 万时的标准是不一样的,当并发用户数在 1000 和 1000 万时的标准也是不一样的。

定义成功与失败

测试的成功与失败与场景也是强相关的,成功与失败不过是当前测试值与目标基准值的一个比较。因此,成功与失败不是关键,基于场景的基准值的设定是关键。该值的设定可以通过“预估+核验”的方式,在开始时先预估一个初始值作为最低验收标准,当测试通过了最低验收标准,就把验收标准提高一点,调整该测试的成功门槛。如果测试失败,如果最低验收标准高于需求中定义的门槛,那么只要降低最低验收标准是被接受的,直接降低就可以了,否则就要优化代码直到满足最低验收标准。

非功能需求的监控

当系统在生产环境运行时,对系统的监控是也是很重要的一部分。有一些开源APM(Application Performance Management,应用性能管理)工具能够追踪每个请求的完整调用链路,收集调用链路上的每个服务的性能数据,并通过页面进行展示。常用的有Skywalking、Zipkin、Pinpoint 等。如下图是 Pinpoint 的监控界面。
在这里插入图片描述
图中右侧显示的是 ApiGateway 这个服务的响应时间汇总信息,响应时间在 1s 内的有 600 个,大于 5s 的有 41 个,还可以针对每个请求查看完整的调用链,对于排查慢请求的问题非常有帮助。

总结

本课时从非功能需求会导致哪些问题入手,描述了目前软件开发中过于关注功能需求,而忽略非功能需求的现象,从而提议软件开发人员在进行软件开发时要关注非功能需求。并在随后的内容里,从非功能需求的管理、分析、度量、设计、测试和监控等方面,简单而全面地描述了如何关注非功能需求。由于篇幅有限,并不能面面俱到,以非功能需求作为一个课题来讲,也是希望软件从业人员能够对非功能需求引起重视,开发出满足用户需要的、“可工作” 的软件。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/661029.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C程序设计(第5版)谭浩强习题解答 第6章 利用数组处理批量数据

C程序设计(第5版)谭浩强习题解答 第6章 利用数组处理批量数据 1.用筛选法求100之内的素数 #include <stdio.h> #include <math.h> int main() {int i, j, n, a[101];for (i 1; i < 100; i)a[i] i;a[1] 0;for (i 2; i < sqrt(100); i)for (j i 1; j …

笔记--扩展欧几里得算法

AcWing.877.欧几里得算法 给定 n n n 对正整数 a a ai, b b bi&#xff0c;对于每对数&#xff0c;求出一组 x x xi, y y yi&#xff0c;使其满足 a a ai x x xi b b bi y y yi g c d ( a gcd(a gcd(ai , b ,b ,bi ) ) )。 输入格式 第一行包含整数 n n n。 接下来 …

【Spring框架】@Cacheable注解:缓存最佳实践

在Java开发中&#xff0c;性能优化是一个永恒的话题。对于使用Spring框架的应用程序来说&#xff0c;Cacheable 注解提供了一种简单有效的方式来提升性能&#xff0c;特别是对于那些计算成本高或数据变化不频繁的操作。本文将深入探讨 Cacheable 的使用方法和注意事项&#xff…

在Vue 3中,理解使用defineEmits函数来定义组件的事件。

在Vue 3中&#xff0c;可以使用defineEmits函数来定义组件的事件。defineEmits函数接受一个对象作为参数&#xff0c;该对象的键是事件名&#xff0c;值是一个回调函数或一个函数数组。这些回调函数将被组件中的$emit方法触发。 以下是一个示例&#xff1a; import { defineC…

C#使用OpenCvSharp4库中5个基础函数-灰度化、高斯模糊、Canny边缘检测、膨胀、腐蚀

C#使用OpenCvSharp4库中5个基础函数-灰度化、高斯模糊、Canny边缘检测、膨胀、腐蚀 使用OpenCV可以对彩色原始图像进行基本的处理&#xff0c;涉及到5个常用的处理&#xff1a; 灰度化 模糊处理 Canny边缘检测 膨胀 腐蚀 1、测试图像lena.jpg 本例中我们采用数字图像处…

Java玩转《啊哈算法》解密QQ号之队列

行有不得&#xff0c;反求诸己 文章目录 开头代码地址引子案例分析代码 队列封装升级演示 开头 各位好&#xff01;本人在看《啊哈算法》&#xff0c;写的确实不错。 但略微遗憾的是&#xff0c;书籍示例代码是c语言&#xff0c;不是本人常用的Java。 那就弥补遗憾&#xff…

【C语言】va_list(可变参数处理)

C 语言中的 va_list 类型允许函数接受可变数量的参数&#xff0c;这在编写需要处理不定数量参数的函数时非常有用。va_list 类型是在 stdarg.h 头文件中定义的&#xff0c;它允许函数处理可变数量的参数。下面我们将详细介绍 va_list 的用法以及实际应用示例。 一、va_list的用…

【力扣刷题练习】415. 字符串相加

题目描述&#xff1a; 给定两个字符串形式的非负整数 num1 和num2 &#xff0c;计算它们的和并同样以字符串形式返回。 你不能使用任何內建的用于处理大整数的库&#xff08;比如 BigInteger&#xff09;&#xff0c; 也不能直接将输入的字符串转换为整数形式。 题目解答&am…

分布式搜索引擎_学习笔记_3

分布式搜索引擎03 0.学习目标 1.数据聚合 **聚合&#xff08;aggregations&#xff09;**可以让我们极其方便的实现对数据的统计、分析、运算。例如&#xff1a; 什么品牌的手机最受欢迎&#xff1f;这些手机的平均价格、最高价格、最低价格&#xff1f;这些手机每月的销售…

Postgresql使用update

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 解决问题一、关联表更新1.关联一张表2.关联多张表 二、根据状态更新为不同的值 解决问题 通过多张关联表更新主表的字段&#xff0c;根据状态更新为不同的值。 一、…

2670--------找出不同元素数目差数组

题目&#xff1a; 给你一个下标从 0 开始的数组 nums &#xff0c;数组长度为 n 。 nums 的 不同元素数目差 数组可以用一个长度为 n 的数组 diff 表示&#xff0c;其中 diff[i] 等于前缀 nums[0, ..., i] 中不同元素的数目 减去 后缀 nums[i 1, ..., n - 1] 中不同元素的数…

matlab中的图窗属性和坐标轴的属性

图窗的Position和Outerposition Position 指定窗口的尺寸和窗口在屏幕中的位置。 Outerposition 指定窗口外轮廓的大小和位置。 两者都是用一个4维向量来定义&#xff0c;格式为[左 底 宽 高]。 可通过set函数修改Position和Outerposition&#xff0c;如下&#xff1a;在屏幕左…

跨平台销售策略:通过API同步不同市场的商品数据

在数字化时代&#xff0c;零售商和品牌经常需要在不同的在线市场上展示和销售商品。为了保持竞争力并确保一致的客户体验&#xff0c;商家必须确保其商品信息在所有渠道上保持同步和准确。这种需求催生了跨平台销售策略&#xff0c;其中一个关键组成部分就是利用应用程序编程接…

spice-gtk注册glib错误信息

首先生成spice统一的错误域 #define SPICE_CLIENT_ERROR spice_client_error_quark()GQuark spice_client_error_quark(void) {return g_quark_from_static_string("spice-client-error-quark"); } 方法1&#xff1a;通过g_set_error()函数 g_set_error(err, SPICE_C…

color - 让你的输出带点颜色

color color 是一个可以让你输出带颜色文本的库。 安装 go get github.com/fatih/color示例 输出到控制台 // 这会直接输出到控制台 color.Cyan("Prints text in cyan.")// 每个调用末尾会自动加上换行 color.Blue("Prints %s in blue.", "text&…

VMware vCenter告警:vSphere UI运行状况警报

vSphere UI运行状况警报 不会详细显示告警的具体内容&#xff0c;需要我们自己进一步确认告警原因。 vSphere UI运行状况警报是一种监控工具&#xff0c;用于检测vSphere环境中的潜在问题。当警报触发时&#xff0c;通常表示系统遇到了影响性能或可用性的问题。解决vSphere UI…

软件测试之软件缺陷管理

什么是软件缺陷 标准的定义&#xff1a;从产品内部看&#xff0c;缺陷是软件产品开发或维护过程中存在的错误、毛病等各种问题&#xff1b;从产品外部看&#xff0c;缺陷是系统所需要实现的某种功能的失效或违背 软件缺陷的生命周期 一个缺陷的正常生命周期是 新建&#xff…

【Java】Java的对象参数踩坑总结

文章目录 前言失败的修改成功的修改原理分析基本类型参数对象引用参数 举一反三&#xff1a;不修改对象参数怎么写&#xff1f; 前言 今天写代码的时候&#xff0c;犯了一个很基础很低级的错误。实在惭愧&#xff0c;在此花点顺手记录一下&#xff0c;养成习惯。 需求是需要把…

如何分辨坏信息?

每当有社会热点&#xff0c;大家也许都会遇到一个困扰&#xff1a; 铺天盖地的信息&#xff0c;实在是太多了。究竟哪一些值得信任&#xff0c;哪些不值得信任&#xff1f;哪些可以接受&#xff0c;哪些最好保持怀疑&#xff1f; 我想用这篇文章&#xff0c;彻底把这个问题讲清…

CSS定位

定位的组成&#xff1a; 这个属性只有当position属性设置为absolute、fixed、relative时才有效。而且在position属性取值不同时&#xff0c;它们的含义也不同。left和right属性值除了可以设置为绝对的像素数外&#xff0c;还可以设置百分数。 定位模式&#xff1a; 静态定位st…