当前位置: 首页 > news >正文

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 个,还可以针对每个请求查看完整的调用链,对于排查慢请求的问题非常有帮助。

总结

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

相关文章:

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

上一讲主要介绍了看板方法以及如何使用看板方法来解决软件研发过程中出现的团队过载、工作不均、任务延期等问题。通过学习前面几个课时介绍的知识&#xff0c;你的团队开始源源不断地交付用户价值。用户对交付的功能非常满意&#xff0c;但等到系统上线后经常出现服务不可用的…...

vs 撤销本地 commit 并保留更改

没想到特别好的办法&#xff0c;我想的是用 vs 打开 git 命令行工具 然后通过 git 命令来撤销提交&#xff0c;尝试之前建议先建个分支实验&#xff0c;以免丢失代码&#xff0c; git 操作见 git 合并多个 commit / 修改上一次 commit...

深度解读NVMe计算存储协议-1

随着云计算、企业级应用以及物联网领域的飞速发展&#xff0c;当前的数据处理需求正以前所未有的规模增长&#xff0c;以满足存储行业不断变化的需求。这种增长导致网络带宽压力增大&#xff0c;并对主机计算资源&#xff08;如内存和CPU&#xff09;造成极大负担&#xff0c;进…...

CHS_06.2.3.4_2+用信号量实现进程互斥、同步、前驱关系

CHS_06.2.3.4_2用信号量实现进程互斥、同步、前驱关系 知识总览信号量机制实现进程互斥信号量机制实现进程同步信号量机制实现前驱关系 知识回顾 各位同学 大家好 在这个小节中 我们要学习怎么用信号量机制来实现进程的同步互制关系 知识总览 那么 我们之前学习了互斥的几种软…...

Web实战丨基于Django的简单网页计数器

文章目录 写在前面Django简介主要程序运行结果系列文章写在后面 写在前面 本期内容 基于django的简单网页计数器 所需环境 pythonpycharm或vscodedjango 下载地址 https://download.csdn.net/download/m0_68111267/88795604 Django简介 Django 是一个用 Python 编写的高…...

mysql8安装基础操作(一)

一、下载mysql8.0 1.查看系统glibc版本 这里可以看到glibc版本为2.17&#xff0c;所以下载mysql8.0的版本时候尽量和glibc版本对应 [rootnode2 ~]# rpm -qa |grep -w glibc glibc-2.17-222.el7.x86_64 glibc-devel-2.17-222.el7.x86_64 glibc-common-2.17-222.el7.x86_64 gl…...

MIT6.5830 实验0

前置 本次实验使用 Golang 语言实现&#xff0c;在之前的年份中&#xff0c;都是像 cs186 那样使用 Java 实现。原因&#xff1a; Golang 语言作为现代化语言&#xff0c;简单易上手但功能强大。 使参加实验的同学有同一起跑线&#xff0c;而不是像Java那样&#xff0c;有些同…...

【简便方法和积累】pytest 单元测试框架中便捷安装插件和执行问题

又来进步一点点~~~ 背景&#xff1a;之前写了两篇关于pytest单元测试框架的文章&#xff0c;本篇内容对之前的做一个补充 一、pytest插件&#xff1a; pytest 有非常多的插件&#xff0c;很方便&#xff0c;以下为插件举例&#xff1a; pytest&#xff0c;pytest-html&#x…...

Zabbix数据库分离与邮件报警

基础环境&#xff1a;要有zabbix服务端与被监控端实验目标&#xff1a;源数据库与服务端存放在一台服务器上&#xff0c;分离后源数据库单独在一台服务器上&#xff0c;zabbix服务端上不再有数据库。环境拓扑图&#xff1a; 实验步骤&#xff1a; 1.在8.7服务器上安装相同版本…...

mybatisplus-多数据源配置

1. 流程 pom文件yml配置多数据源具体服务添加注解DS(“***”) 1.pom文件 <!--mybatis plus 起步依赖--><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.4.0</vers…...

微信小程序(二十八)网络请求数据进行列表渲染

注释很详细&#xff0c;直接上代码 上一篇 新增内容&#xff1a; 1.GET请求的规范 2.数据赋值的方法 源码&#xff1a; index.wxml <!-- 列表渲染基础写法&#xff0c;不明白的看上一篇 --> <view class"students"><view class"item">&…...

ubuntu22.04 安装conda

要在Ubuntu 22.04上安装Anaconda&#xff0c;可以遵循以下步骤&#xff1a; 首先&#xff0c;打开终端并更新系统包仓库&#xff0c;也需要安装curl工具&#xff0c;这可以通过以下命令完成&#xff1a; sudo apt update && sudo apt install curl -y使用curl命令行工具…...

W801学习笔记十:HLK-W801制作学习机/NES游戏机(总结)

本章总结一下整个开发过程中遇到的问题&#xff1a; 1、引脚的抗干扰问题&#xff1a; 屏幕显示的时候&#xff0c;概率出现花屏。无论怎么修改代码都不能解决&#xff0c;一个偶然的机会&#xff0c;发现当手触摸屏幕的WR和CS引脚时&#xff0c;屏幕会正常。查阅资料&#x…...

《HTML 简易速速上手小册》第6章:HTML 语义与结构(2024 最新版)

文章目录 6.1 语义化标签的重要性6.1.1 基础知识6.1.2 案例 1&#xff1a;使用 <article>, <section>, <aside>, <header>, 和 <footer>6.1.3 案例 2&#xff1a;构建带有嵌套语义化标签的新闻网站6.1.4 案例 3&#xff1a;创建一个带有 <mai…...

分析HarmonyOS应用/服务的CPU活动性能

CPU Profiler 性能分析是用来分析CPU性能瓶颈的工具&#xff0c;可以实时查看应用/服务的CPU使用率和线程活动&#xff0c;也可以查看记录的方法跟踪数据、方法采样数据和系统跟踪数据的详情。基于CPU性能分析&#xff0c;您可以了解在一段时间内执行了哪些方法&#xff0c;以及…...

Linux:理解信号量以及内核中的三种通信方式

文章目录 共享内存的通信速度消息队列msggetmsgsndmsgrcvmsgctl 信号量semgetsemctl 内核看待ipc资源单独设计的模块ipc资源的维护 理解信号量总结 本篇主要是基于共享内存&#xff0c;延伸出对于消息队列和信号量&#xff0c;再从内核的角度去看这三个模块实现进程间通信 共享…...

【ArcGIS微课1000例】0100:ArcGIS for CAD软件下载与安装(附安装包)

ArcGIS for CAD软件下载与安装(附安装包)。 文章目录 一、ArcGIS for CAD概述1. ArcGIS for CAD介绍2. 主要功能二、ArcGIS for CAD下载三、ArcGIS for CAD安装1. 安装CAD2. 安装ArcGIS for CAD3. 配置一、ArcGIS for CAD概述 1. ArcGIS for CAD介绍 ArcGIS for CAD是Esri提…...

Django模型(一)

一、介绍 模型&#xff0c;就是python中的类对应数据库中的表 1.1、ORM ORM 就是通过实例对象的语法&#xff0c;完成关系型数据库的操作的技术&#xff0c;是"对象-关系映射"&#xff08;Object/Relational Mapping&#xff09; 的缩写 ORM 把数据库映射成对象 1.…...

【ChatGPT】文本向量化与余弦相似度:揭开文本处理的神秘面纱(5)

1、引言 在这个数字化的时代&#xff0c;我们每天都会面对大量的文本信息&#xff0c;从社交媒体到新闻报道&#xff0c;文本无处不在。但是&#xff0c;计算机要如何理解和处理这些文字呢&#xff1f;本文将为大家揭开其中的一些奥秘&#xff0c;详细解释文本向量化的概念&am…...

计算机中丢失mfc100u.dll怎么解决,详细解析mfc100u.dll丢失的解决方法

遭遇“无法找到mfc100u.dll”的错误不必过分担忧&#xff0c;这是一个普遍现象。许多用户在启动某些软件或游戏的时候可能会碰到这样的情况。通常&#xff0c;这个错误信息表明你的计算机系统中缺失了一个关键的动态链接库(DLL)文件&#xff0c;它可能会妨碍应用程序的顺利启动…...

[2025CVPR]DeepVideo-R1:基于难度感知回归GRPO的视频强化微调框架详解

突破视频大语言模型推理瓶颈,在多个视频基准上实现SOTA性能 一、核心问题与创新亮点 1.1 GRPO在视频任务中的两大挑战 ​安全措施依赖问题​ GRPO使用min和clip函数限制策略更新幅度,导致: 梯度抑制:当新旧策略差异过大时梯度消失收敛困难:策略无法充分优化# 传统GRPO的梯…...

uni-app学习笔记二十二---使用vite.config.js全局导入常用依赖

在前面的练习中&#xff0c;每个页面需要使用ref&#xff0c;onShow等生命周期钩子函数时都需要像下面这样导入 import {onMounted, ref} from "vue" 如果不想每个页面都导入&#xff0c;需要使用node.js命令npm安装unplugin-auto-import npm install unplugin-au…...

Objective-C常用命名规范总结

【OC】常用命名规范总结 文章目录 【OC】常用命名规范总结1.类名&#xff08;Class Name)2.协议名&#xff08;Protocol Name)3.方法名&#xff08;Method Name)4.属性名&#xff08;Property Name&#xff09;5.局部变量/实例变量&#xff08;Local / Instance Variables&…...

汽车生产虚拟实训中的技能提升与生产优化​

在制造业蓬勃发展的大背景下&#xff0c;虚拟教学实训宛如一颗璀璨的新星&#xff0c;正发挥着不可或缺且日益凸显的关键作用&#xff0c;源源不断地为企业的稳健前行与创新发展注入磅礴强大的动力。就以汽车制造企业这一极具代表性的行业主体为例&#xff0c;汽车生产线上各类…...

零基础设计模式——行为型模式 - 责任链模式

第四部分&#xff1a;行为型模式 - 责任链模式 (Chain of Responsibility Pattern) 欢迎来到行为型模式的学习&#xff01;行为型模式关注对象之间的职责分配、算法封装和对象间的交互。我们将学习的第一个行为型模式是责任链模式。 核心思想&#xff1a;使多个对象都有机会处…...

MySQL用户和授权

开放MySQL白名单 可以通过iptables-save命令确认对应客户端ip是否可以访问MySQL服务&#xff1a; test: # iptables-save | grep 3306 -A mp_srv_whitelist -s 172.16.14.102/32 -p tcp -m tcp --dport 3306 -j ACCEPT -A mp_srv_whitelist -s 172.16.4.16/32 -p tcp -m tcp -…...

Unity | AmplifyShaderEditor插件基础(第七集:平面波动shader)

目录 一、&#x1f44b;&#x1f3fb;前言 二、&#x1f608;sinx波动的基本原理 三、&#x1f608;波动起来 1.sinx节点介绍 2.vertexPosition 3.集成Vector3 a.节点Append b.连起来 4.波动起来 a.波动的原理 b.时间节点 c.sinx的处理 四、&#x1f30a;波动优化…...

Linux离线(zip方式)安装docker

目录 基础信息操作系统信息docker信息 安装实例安装步骤示例 遇到的问题问题1&#xff1a;修改默认工作路径启动失败问题2 找不到对应组 基础信息 操作系统信息 OS版本&#xff1a;CentOS 7 64位 内核版本&#xff1a;3.10.0 相关命令&#xff1a; uname -rcat /etc/os-rele…...

uniapp手机号一键登录保姆级教程(包含前端和后端)

目录 前置条件创建uniapp项目并关联uniClound云空间开启一键登录模块并开通一键登录服务编写云函数并上传部署获取手机号流程(第一种) 前端直接调用云函数获取手机号&#xff08;第三种&#xff09;后台调用云函数获取手机号 错误码常见问题 前置条件 手机安装有sim卡手机开启…...

【Android】Android 开发 ADB 常用指令

查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...