软件工程——期末复习(2)
Part1:软件工程基本概念
- 软件=程序+文档+数据
在软件工程中,软件通常被定为程序、文档和数据的集合。程序是按事先设计的功能和性能要求编写的指令序列;程序是完成指定功能的一段特定语言代码。文档是描述程序操作和使用的文档,是与程序开发、维护和使用有关的图文材料;数据是程序运行时需要使用的信息,是使程序能正常操纵信息的数据结构,是软件实现其功能的基础。这三部分相互关联、相互依存,共同构成了完整的软件系统。
- 软件复杂程度的提高给软件开发带来的影响
- 开发难度增加:需要处理的问题和细节大幅增大,可能涉及多个模块和组件的协同工作,增加系统集成的难度
- 开发周期和维护成本增加:需要更多的时间和资源来设计、实现、测试软件
- 质量控制更加困难:软件复杂度程度提高,可能存在大量交互和依赖关系,软件更容易出现缺陷和漏洞
- 安全风险增加:软件复杂程度提高,存在更多潜在的漏洞和攻击面,增加了被恶意攻击的风险。
- 软件工程的定义与工程思想p4~5
工程思想
工程思想是软件工程的基础理念,指的是将工程化的原则应用到软件开发中,以提高开发过程的可管理性、可控性和可靠性。工程思想的关键特点包括:
1. 系统性
软件开发应从系统的角度出发,考虑各个组成部分及其之间的相互关系,形成一个完整的、可操作的系统。每个开发阶段都是全局系统的一部分,必须保证各部分的协调性和一致性。
例子:在开发一个大型电商平台时,开发团队不仅仅关注具体的支付模块,还需要从系统整体的角度考虑与库存管理、订单处理、用户数据等模块的交互。
2. 规范性
软件开发需要遵循一系列标准、方法和流程,以保证开发过程的可控性和可重复性。规范化的开发流程有助于提高团队协作效率、减少错误和提高软件质量。
例子:使用敏捷开发方法、版本控制、代码审查、单元测试等规范化措施,以保证软件的稳定性和可维护性。
3. 可重用性
工程思想强调代码的复用和模块化设计,以降低开发成本、提高开发效率,并增强系统的灵活性和可扩展性。
例子:通过设计通用的API和服务组件,避免重复造轮子,使得相同的功能可以在不同的项目中复用。
4. 过程管理
工程思想强调对开发过程的管理和控制。软件开发过程通常是复杂的、跨团队的工作,因此需要通过明确的流程和规范进行管理,确保项目按计划推进,达到预期目标。
例子:使用项目管理工具(如JIRA、Trello)进行任务分配和进度跟踪,确保开发进度和资源的合理配置。
5. 质量保障
软件工程不仅仅关注软件的开发,还要确保软件的质量能够满足用户的需求。质量保证包括设计、编码、测试、部署等多个环节,确保软件产品能够高效、安全、稳定地运行。
例子:通过进行代码审查、单元测试、集成测试、性能测试等环节,确保软件能够稳定运行,并且满足预期的性能要求。
6. 风险管理
在软件工程中,风险管理是非常重要的。开发过程中可能会遇到技术风险、人员风险、时间风险等,因此需要识别、评估并采取措施应对这些风险。
例子:在一个项目初期识别出潜在的技术难点,提前进行技术验证,或通过迭代开发降低项目的风险。
7. 可维护性
随着软件系统的使用,维护成为了一个重要的环节。良好的工程化实践能够确保软件在后续的生命周期中易于维护、扩展和升级。
例子:设计时考虑模块化、松耦合,编写清晰的文档,遵循代码规范等,有助于未来的维护和升级工作。
把软件当作一种工业产品、采用工程化的方法对软件进行计划、开发和维护
- 软件产品与项目管理p48~49
考核要点:对相应概念的理解,以及综合应用相应概念对相应观点进行辨析。
样例:
Q:试说明“软件=程序+文档+数据”中的文档和建模存在什么样的关系。
答:文档是描述程序操作和使用的文档,是与程序开发、维护和使用有关的图文材料;建模是软件开发过程中一个重要的环节,通过图形化或者文字化的方式描述软件的结构和行为。两者之间相互依赖建模产生的各种图形和文档是文档编写的重要参考,而文档则是对建模成果的详细解释和补充;同时两者是相互补充的,例如:开发人员使用UML图对软件系统进行建模,而文档中的文字描述可以对UML图进行解释和补充,更好的表达软件系统的设计。
Part2:软件开发过程模型
- 软件开发典型阶段及其方法、任务与制品(里程碑)p362
- 软件开发分阶段进行的意义
①降低开发成本:将整个软件开发过程分解为多个独立的阶段,可以更好地控制项目进度,从而降低了开发成本。
②提高开发效率:每个开发阶段都有明确的目标和工作内容,开发人员可以更加
专注地完成自己的任务,从而提高开发效率。
③提高软件质量:通过分阶段进行软件开发,可以更好地控制软件开发流程,提高软件质量。
④确保项目成功:将整个软件开发过程分解为多个独立的阶段,可以更好地控制
项目进度,并及时识别和解决问题,从而确保项目成功。
⑤更好地管理项目:软件开发分阶段进行可以更好地管理项目,帮助管理人员更
好地了解项目进展情况和问题,及时采取措施调整方案,保证项目按计划进行。
综上所述,软件开发分阶段进行是软件开发过程中非常重要的一环,能够提高软
件质量和开发效率,降低开发成本和项目风险,从而最终确保项目成功。
- 典型软件开发过程模型p364-p376
Q:在软件开发过程中分阶段建立里程碑有何意义?
①目标设定和进度控制:里程碑可以帮助团队明确目标,并将开发过程分解为可管理的阶段。
②项目规划和资源分配:每个里程碑代表一个阶段的完成,可以帮助项目经理进行详细的项目规划和资源分配。
③提供可测量的进展指标:里程碑定义了具体的目标和交付物,使得项目进展可以被量化和测量。
④风险管理和问题解决:每个阶段的里程碑标志着一个重要的节点,可以帮助团队及时发现和解决问题。
⑤沟通和协作:里程碑可以作为沟通和协作的重要工具,帮助团队成员之间更好地理解项目进展和目标。
Part3:需求工程
- 需求工程与需求分析p67/69
软件需求的特性:软件需求包括以下六个特性:功能性、可用性、可靠性、性能、可支持性和设计约束
功能性:功能性需求是软件最重要的需求,可分普通功能和全局功能。普通功能泛指软件完成的一个功能或提供的一个服务。全局功能是适用于软件所有应用场景的功能
可用性:泛指能使最终用户方便使用软件的相关需求
可靠性:包括与系统可靠性相关的各种指标,主要有正常运行率、平均无故障时间、平均修复时间、精确度、最高错误或缺陷率等
性能:记录与系统性能相关的各种指标,其中包括对事务的响应时间、吞吐量、容量、降级模式、资源可利用情况
可支持性:定义所有与系统的可支持性或可维护性相关的需求,其中包括编码标准、命名约定、类库以及如何对系统进行维护操作和维护实用工具等
设计约束:设计约束代表以及批准并必须遵循的设计约定,其中包括软件开发流程、开发工具、系统构架、编程语言、第三方构件库、运行平台和数据库系统
需求分析的步骤
软件需求分析一般包括如下的四个步骤:需求获取、需求建模、需求描述(即编写 SRS)和需求验证。
1.需求获取
顾名思义,需求获取就是得到正确的需求信息,常规的需求获取方法有建立联合分析小组、用户访谈与问题分析与确认等。快速原型法也可以用作一种有效的需求分析方法。在分析阶段,开发人员利用快速开发工具先建立一个系统原型,然后让用户参加评估并提出修改意见,进而逐步、准确地确定软件系统的外部行为和特征
2.需求建模
建立分析模型是需求分析的首要任务,是可视化的说明软件需求的最好手段。其中占主导地位的需求建模方法有结构化分析建模和面向对象分析建模两种,这里主要介绍面向对象需求模型
面向对象需求模型由三部分组成:用例模型、补充规约和术语表,其中用例模型又包括用例图和用例规约。用例图主要用于显示软件系统的功能,它包括用例和参与者两方面内容,而用例图下方的用例规约则是对软件系统中每个功能的具体描述。补充规约用于对全局性功能和可靠性、性能等非功能性需求进行文字性描述;后者则用于描述与系统需求相关的术语的定义。基于用例的面向对象需求建模方法,包括画用例图、写用例规约、描述补充规约和编写术语表等四步
3.软件需求描述
编写软件需求规格说明书(SRS),必须用统一格式的文档进行描述,是开发人员在分析阶段需要完成的用于描述需求的文档,包括引言信息描述、功能描述、行为描述、质量保证、接口描述、其他描述
4.需求验证
确保需求规格说明书可作为软件设计和最终系统验收的依据
2、需求的定义、层次与分类 p71/75
(1)需求层次
1.业务需求(描述为什么要开发系统(why))
业务需求是指反映组织机构或客户对系统、产品高层次的目标要求,通常问题定义本身就是业务需求 。
举个例子,背景描述:XX保险公司希望充分利用日益完善的移动通信技术,在原有的办公系统的基础上进行扩展,使得在外的业务人员能够及时地获得客户、业务相关的动态信息,与此同时,实现企业内部的即时通信。
业务需求/目标 :通过该系统的实施,将人工保费续缴、投保手续办理两项业务运转周期缩短10%以上,使企业内部沟通效率大幅改善,以帮助企业运转效率得以提高。
2.用户需求(描述系统能够帮用户做什么(what))
用户需求是指描述用户使用产品必须要完成什么任务,怎么完成的需求,通常是在问题定义的基础上进用户访谈、调查,对用户使用的场景进行整理,从而建立从用户角度的需求。
3.系统需求(描述达到用户要求的具体流程(How))
系统需求(system requirement)用于描述包含多个子系统的产品(即系统)的顶级需求。系统可以只包含软件系统,也可以既包含软件又包含硬件子系统。人也可以是系统的一部分,因此某些系统功能可能要由人来承担。
从系统实现的角度描述的需求。
开发人员(设计及分析人员)在业务需求、用户需求的基础上生成的。
(2)软件需求分类
1.功能需求
定义了开发人员必须实现的软件功能
描述系统应该提供的功能或服务,通常涉及用户或外部系统与该系统之间的交互,一般不考虑系统的实现细节。
描述软件系统所应具有的外部行为
2.非功能需求
描述了系统展现给用户的行为和执行的操作等。它包括外部界面的具体细节、性能要求及质量属性。
非功能需求是产品必须具备的品质,他们可以让产品有吸引力、易于使用、快速、可靠或者安全。
功能性需求是让产品工作的需求,非功能需求是为工作赋予特性的需求。
3.设计约束
设计约束是指对开发人员在软件产品设计和构造上的限制,产品必须遵从的标准、规范和合约。包括:非技术因素的技术选型、预期的软硬件环境和预期的使用环境三大类型。
3、需求分析与建模:UML(用例图与用例描述、概念类图、系统顺序图)
考核要点:对相应概念的理解,以及综合应用相应概念对相应观点进行辨析,能针对具体问题建立需求分析模型(如根据需求完成用例图与用例描述、概念类图、系统顺序图等UML模型的建立)。
样例:
Q:高“吞吐量(Throughput)”是否意味着高“负载(Load)”,请举例说明?试给出自己的判断及理由。
高“吞吐量(Throughput)”并不一定意味着高“负载(Load)”。吞吐量指的是系统单位时间内处理的数据量,而负载则反映了系统资源的消耗程度,如CPU、内存和I/O等。在一些情况下,系统可以保持高吞吐量同时负载较低。例如,采用缓存或负载均衡机制时,系统可以快速处理大量请求,但每台服务器的负载并不高。相反,如果吞吐量很高,系统的负载可能也很大,尤其是当瓶颈在磁盘I/O或网络带宽时。所以,吞吐量和负载之间没有固定的直接关系,它们受系统设计、资源分配及瓶颈等因素影响。
吞吐量(Throughput)
吞吐量通常是指系统在单位时间内成功处理的数据量或请求数。比如,网络带宽中的吞吐量表示每秒钟可以传输的数据量;数据库系统中的吞吐量表示每秒能够处理的事务数量。
负载(Load)
负载则通常指的是系统在运行时所承受的压力或资源消耗。例如,CPU负载表示系统的计算能力被占用的程度,内存负载表示内存的使用情况,或指的是用户请求的数量及复杂度。
吞吐量与负载的关系
高吞吐量不一定意味着高负载,反之亦然。它们之间的关系取决于系统的设计和优化水平。我们可以通过以下几个例子来分析:
1. 高吞吐量但低负载
一个系统如果经过良好的优化,可能在负载较低的情况下仍能实现较高的吞吐量。例如,在分布式系统中,通过合理的负载均衡与缓存机制,可以大幅提高吞吐量,而系统的计算资源消耗保持较低。
例子:一个网站通过缓存静态内容和数据库查询结果,减少了服务器的计算压力和IO操作,使得即便在高并发的情况下,吞吐量仍然很高,但CPU和内存的负载较低。
2. 高吞吐量同时伴随高负载
在一些场景下,为了实现高吞吐量,系统可能需要消耗更多的计算资源和带宽,导致负载也随之增加。例如,在数据中心进行大量数据处理或大规模并发请求时,系统的吞吐量提高的同时,CPU、内存等资源的使用量也会显著增加。
例子:一个处理大量实时交易数据的系统,随着交易数量的增多,它的吞吐量也在增长,但由于系统需要进行大量计算和存储,CPU和内存负载也会变得非常高。
3. 低吞吐量但高负载
有时候,系统的负载很高,但吞吐量却较低。这通常发生在系统资源分配不均或性能瓶颈未解决的情况下。虽然系统正在处理大量任务,但由于资源瓶颈(如数据库锁争用、网络延迟等),吞吐量无法有效提高。
例子:一个数据库系统可能因为过度的磁盘IO或锁竞争而出现高负载,尽管它的吞吐量(每秒处理事务的数量)依然较低。
Part4:软件设计
1、软件设计核心思想:分解与抽象p134
试说明什么是分解(decomposition)和抽象(abstraction),并简要说明为什么分解与抽象是软件设计的核心思想。(课件上的标准答案)
分解是将系统分割为几个相对简单的子系统,以及各子系统之间的关系。
抽象则是通过接口将系统与具体的实现分离,是整个系统的关键所在、本质所在。
因为现代软件设计的核心问题在于控制由于软件复杂性引起的“系统复杂度”,为此“分而治之”是软件设计解决复杂度难题的主要思路,抽象和分解正是“分治”“解耦'的体现,在软件工程实践中也得到了大量应用,故此是软件设计的核心思想。
2、软件体系结构的定义以及对应的软件实现机制p148/p150
定义:软件体系结构由组件、连接件和属性组成,以组件和组件交互的方式定义系统,说明需求和成品系统之间的对应关系,描述系统级别的可伸缩性、能力、吞吐量、一致性和兼容性等属性。
对应的软件实现机制:
1.组件实现:
通过模块化、类、服务等方式实现系统功能。
在微服务架构中,使用服务来实现独立的业务功能。
2.数据流和控制流:
数据在组件之间流动,通过消息队列、函数调用等方式传递。
控制流通过事件或调度机制管理。
3.接口和协议:
组件通过接口和协议(如HTTP、gRPC)进行交互。
4.解耦与模块化:
通过接口实现松耦合,减少组件间的直接依赖。
5.技术栈和框架:
根据架构需求选择合适的技术栈,如数据库、前端框架、容器化技术等。
6.性能优化:
使用负载均衡、缓存机制、并发处理等技术提升系统性能。
7.安全性:
实现身份验证、授权和数据加密等安全机制。
- 体系结构的集成与测试、桩代码与驱动代码的编写p175/p177
1. 体系结构集成
定义:体系结构集成是将各个独立开发的组件、模块或者服务集成到一起,确保它们在整个系统中协调工作,达到预期的功能和性能要求。
集成过程中的关键问题通常包括:
1.组件集成:确保各个系统组件(如前端、后端、数据库等)能够正确协同工作。这可能包括数据库与应用程序之间的集成、API与前端之间的集成等。
2.系统集成:将所有的组件集成成一个完整的系统,确保各部分能够无缝地协作。
3.接口和协议验证:集成过程中需要检查组件之间的接口和协议是否兼容。不同组件之间的接口(如 RESTful API、gRPC等)需要符合规定的协议和数据格式,避免通信失败。
4.集成环境搭建:为了进行集成测试,需要搭建集成测试环境,通常涉及到配置测试服务器、数据库、网络和其他中间件服务。
5.自动化集成:使用自动化工具(如 Jenkins、GitLab CI等)进行持续集成(CI),自动构建、测试和部署集成后的系统。
2. 体系结构的测试
定义:体系结构测试是对系统架构进行验证,确保其符合预期的功能、性能和可靠性要求。
在软件工程中,体系结构测试通常包括以下几个方面:
2.1 单元测试
定义:对系统中最小的独立单元(如函数或方法)进行测试,确保其按预期工作。
工具:JUnit(Java)、PyTest(Python)等。
目标:确保每个单元的功能正确,并且在修改代码时不会引入新的缺陷。
2.2 集成测试
定义:测试多个模块、组件或服务的集成部分,确保它们可以协同工作。
关键点:
测试组件间的接口,确保数据流和控制流能够正确传递。
测试系统不同层级的集成,如前端与后端的集成、服务与数据库的集成等。
验证组件间的消息传递是否符合协议(如 REST API的请求和响应是否正确)。
工具:
Postman(用于测试API接口)。
Spring Test(用于测试Spring框架中的组件集成)。
Mocking(如 Mockito,用于模拟外部依赖组件)。
2.3 系统测试
定义:验证整个系统是否能够按预期工作,涵盖所有集成模块和接口。
目标:确保整个系统在集成后的工作符合用户需求和技术规范。
范围:不仅仅是功能验证,还包括性能、负载、可用性等非功能性测试。
2.4 验收测试
定义:由最终用户或客户进行的测试,用于确认系统是否符合需求和业务目标。
类型:包括功能验收测试、用户界面验收、性能验收等。
关键点:确保系统满足用户需求和期望,通常在系统测试之后进行。
2.5 回归测试
定义:在系统集成或修改后,重新进行的一轮测试,确保新功能或修复不会引入新的问题或破坏现有功能。
关键点:回归测试是确保软件稳定性的重要手段,尤其在大规模系统中,修改一个模块可能影响到其他模块。
2.6 性能测试
定义:测试系统的响应速度、负载能力、并发处理能力等,以确保系统在高负载下依然能够保持良好的性能。
类型:
负载测试:模拟不同用户访问系统,检查系统是否能够承受预期的负载。
压力测试:模拟系统在极端负载下的表现,寻找系统的瓶颈和脆弱点。
稳定性测试:长时间运行系统,检查是否有内存泄漏、崩溃等问题。
2.7 安全测试
定义:确保系统架构符合安全标准,防止潜在的安全漏洞。
类型:
身份验证与授权测试:检查用户权限控制是否严格。
数据保护与加密:确保数据传输和存储过程中的安全性。
漏洞扫描:使用工具扫描系统的安全漏洞,如SQL注入、跨站脚本攻击(XSS)等。
桩代码和驱动代码编写的例子:
//驱动测试
public static void main(String[] args) {
Attendance a=new Attendance();
a.query();
}
//待测试的方法
public void query(){
int value=this.Stub1()+this.Stub2();
System.out.println("我方法的值是:"+value);
}
//桩1
public int Stub1(){
int output=3;
System.out.println("my stub的值是"+output);
return output;
}
//桩2
public int Stub2(){
int output=4;
System.out.println("my stub的值是"+output);
return output;
}
- 典型的体系结构与详细设计模型: UML(包图、构件图、部署图、类图、顺序图)
- 设计质量、模块化与信息隐藏p215/p217/p222
设计质量定义:
设计质量是指在软件系统的设计阶段,所做出的设计决策和设计方案的有效性、可维护性、可扩展性、性能和一致性等特性的综合体现。设计质量直接影响软件系统的结构、模块之间的关系、代码的可读性和可测试性等,进而影响软件的长期可维护性和性能表现。
设计质量可以从以下几个方面来衡量:
功能性
可维护性
可读性和可理解性
性能
可扩展性
可复用性
可靠性和鲁棒性
一致性与规范
可测试性
安全性
模块化定义:
模块化是指解决一个复杂问题时,自顶向下逐层把系统划分成若干模块的过程。对于整个系统来说,模块是可组合、分解和更换的单元。
把代码进行模块化拆分的好处:
① 提高了代码的复用性
② 提高了代码的可维护性
③ 可以实现按需加载
信息隐藏
1.基本思想:每个模块都隐藏了重要设计决策的实现,因此只有该模块的组成部分才知道详细信息:特别是如果存在所有可能的设计更改的列表-隐藏假设列表
2.所有设计决策彼此独立
3.两种常见的信息隐藏:
一是根据需求分配的职责,因为实践表明,需求是经常变化的,频率和幅度都很大;
二是内部实现机制,常见的变化主题包括硬件依赖,输入输出形式,非标准语言特征和库,负责的设计和实现,复杂的数据结构,复杂的逻辑,全局变量。数据大小限制等。
6、耦合/解耦与内聚p219
Part5:软件构造、测试与维护
- 软件构造及代码设计的准则
Open Closed Principle:开闭原则
Dependence Inversion Principle:依赖倒置原则
Single ResponsibilityPrinciple:单一职责原则
Interface Segregation Principle:接口隔离原则
Law of Demeter:迪米特法则
Liskov Substitution Principle:里氏替换原则
Composite/Aggregate Reuse Principle:合成复用原则
一、开闭原则
定义
开闭原则(0pen-ClosedPrinciple,0CP)指一个软件实体如类、模块和函数应该对扩展开放,对修改关闭。所谓开闭,就是在不修改原有代码的前提下对原有功能进行扩展。开闭原则是面向对象设计中最基础的设计原则。强调的是用抽象构建框架,用实现扩展细节。它指导我们如何建立稳定灵活的系统,例如系统版本更新,我们尽可能做到不修改源码,但是通过扩展方式增加新功能。
优点:提高软件系统的可复用性及可维护性。
二、依赖倒置原则
依赖倒置原则(DependenceInversionPrinciple,DIP)指设计代码结构时,遵循如下原则:高层模块不应该依赖低层模块,二者都应该依赖其抽象,抽象不应该依赖细节,细节应该依赖抽象。通过依赖倒置,可以降低类与类之间的耦合性,提高系统的稳定性,提高代码的可读性和可维护性,并降低修改程序带来的风险。
优点:可以减少类间的耦合性、提高系统稳定性,提高代码可读性和可维护性,可降低修改程序所造成的风险。
三、单一职责原则
定义:单一职责原则(Simple ResponsibilityPrinciple,SRP)指不要存在多于一个导致类变更的原因。简单的理解就是一个模块只做一件事情。庞大的代码肿瘤是代码屎山的重要原因。我们要把所有的模块都小型化,变成一个小的不能再小的积木,这样可以使代码更灵活,更容易维护。假设有一个 C1ass 负责两个职责,一旦发生需求变更,修改其中一个职责的逻辑代码,有可能会导致另一个职责的功能发生故障。这样一来,这个Class 就存在两个导致类变更的因素。
如何解决这个问题呢?我们就要分别用两个Class来实现两个职责,进行解耦。后期需求变更维护互不影响。总体来说就是一个类、接口、方法只负责一项单一的职责。也可以理解为:相同的职责放到一起,不同的职责分解到不同的接口和实现中去,这个是最容易也是最难运用的原则,关键还是要从业务出发,从需求出发,识别出同一种类型的职责。
优点:降低类的复杂度,提高类的可读性,提高系统的可维护性,降低变更引起的风险。
四、接口隔离原则
定义:接口隔离原则(Interface SegregationPrinciple,ISP)指用多个专门的接口,
而不使用单一的总接口,客户端不应该依赖它不需要的接口。这个原则指导我们在设计接口时,应当注意以下几点。
(1)一个类对另一个类的依赖应该建立在最小接口上。
(2)建立单一接口,不要建立庞大臃肿的接口。
(3)尽量细化接口,接口中的方法尽量少(不是越少越好,一定要适度)。
在设计接口的时候,要多花时间思考,要考虑业务模型,包括还要对以后可能发生变更的地方做一些预判。所以,在实际开发中,我们对抽象、业务模型的理解是非常重要的。
优点:接口隔离原则符合“高聚合、低耦合”的设计思想,使得类具有很好的可读性可扩展性和可维护性。
五、迪米特法则
定义:迪米特原则(LawofDemeter LoD)是指一个对象应该对其他对象保持最少的了解,又叫最少知道原则(Least Knowledge Principle,LKP),尽量降低类与类之间的耦合度。
迪米特原则主要强调:只和朋友交流,不和陌生人说话。出现在成员变量、方法的输入、输出参数中的类都可以称为成员朋友类,而出现在方法体内部的类不属于朋友类。
优点:降低类与类之间的耦合度
六、里氏替换原则
定义:里氏替换原则(Liskov Substitution Principle,LSP)指如果对每一个类型为
T1的对象01,都有类型为T2的对象02,使得以T1定义的所有程序P在所有对象01都替换成02时,程序P的行为没有发生变化,那么类型T2是类型T1的子类型。T2是T1的父类,里氏替换原则是继承复用的基石,只有当子类可以替换父类,软件功能不受影响时,父类才能真正被复用。而子类也能在父类的基础上增加新的行为。里氏替换原则是对开闭原则的一个补充。定义看上去比较抽象,我们重新解释一下,可以理解为一个软件实体如果适用于一个父类,则一定适用于其子类,所有引用父类的地方必须能透明地使用其子类的对象,子类对象能够替换父类对象,而程序逻辑不变。也可以理解为,子类可以扩展父类的功能,但不能改变父类原有的功能。根据这个理解,我们对里氏替换原则的定义总结如下。
(1)子类可以实现父类的抽象方法,但不能覆盖父类的非抽象方法;
(2)子类中可以增加自己特有的方法;
(3)当子类的方法重载父类的方法时,方法的前置条件(即方法的输入参数)要比父类的方法更宽松;
(4)当子类的方法实现父类的方法时(重写/重载或实现抽象方法),方法的后置条件(即方法的输出/返回值)要比父类的方法更严格或相等。
优点:①约束继承泛滥,开闭原则的一种体现②加强程序的健壮性,同时变更时也可以做到非常好的兼容性,提高程序的维护性、扩展性。降低需求变更时引入的风险。
- 软件测试与软件质量的关系
软件测试与软件质量的关系:
(1)提高软件质量:软件测试通过发现和修复缺陷,确保软件按预期功能运行,从而提升软件的质量。
(2)衡量软件质量:测试是衡量软件质量的重要手段,测试覆盖度和缺陷密度等指标能反映软件的质量水平。
(3)提高可靠性:测试帮助发现潜在的可靠性问题,确保软件在各种条件下稳定运行。
(4)保证可维护性:通过测试,开发人员可以确保软件的修改不会引入新问题,提高系统的可维护性。
(5)促进用户满意度:测试确保软件满足用户需求和性能要求,从而提高用户的满意度。
总的来说,软件测试是确保软件质量的关键手段,两者相辅相成,测试提升质量,质量反过来影响测试的有效性。
样例:
Q:为什么要“设计易读的代码”?
设计易读的代码是为了让团队成员(包括自己)更容易理解代码的含义,从而更方便地对代码进行修改、维护和扩展。易读的代码有如下一些优点
(1)提高开发效率和可维护性:代码好理解,也就提高了项目的开发效率,也增强了项目的可维护性
(2)便于发现、减少错误:开发人员更容易发现代码中的错误,减少代码中的潜在缺陷和bug。
(3)便于团队合作:易读的代码让团队成员更容易互相理解和协作,从而提高团队的协作效率。
(4)便于代码重用:开发人员可以很快的找到需要的代码,重用起来也方便
综上来说,易读的代码对于提高代码质量、减少错误、提高开发效率和促进团队合作都具有重要的作用,所以我们要设计易读的代码。
其他
- 软件工程方法学:包括三个要素:方法、工具和过程。软件工程方法是完成软件开发的各项任务的技术方法,为软件开发提供了“如何做”的技术;软件工程工具为软件工程方法提供了自动的或半自动的软件支撑环境;软件工程过程则是将软件工程的方法和工具综合起来以达到合理、及时地进行计算机软件开发的目的。
- 为什么进行边界值分析
(1) 等价类划分忽略掉了某些特定类型的高效测试用例,而边界值分析可以弥补其中的一些不足;
(2)编程的很多错误是发生在定义域或值域的边界上。因此针对边界情况设计测试用例,可以更好的检查错误,具有更高的测试回报率;
(3) 边界值数据本质上是属于某个等价类的范围,测试时确实有些重复,但是为了更好的测试质量(边界值特别容易出bug),适当的重复是可以接受的。
相关文章:
软件工程——期末复习(2)
Part1:软件工程基本概念 软件程序文档数据 在软件工程中,软件通常被定为程序、文档和数据的集合。程序是按事先设计的功能和性能要求编写的指令序列;程序是完成指定功能的一段特定语言代码。文档是描述程序操作和使用的文档,是与…...
RAID1技术是什么?它的发展和工作原理如何?
RIAD1是一种先进的数据存储与冗余技术,设计用于解决现代分布式系统中常见的数据安全、数据一致性和高可用性等问题。随着云计算和大规模分布式存储系统的兴起,如何保障数据在高效传输与存储过程中仍然能具备足够的安全性和可靠性,成为了各大企…...
【Apache Paimon】-- 8 -- flink 创建 paimon connecor 的两种方式
目录 1、使用 catalog 创建非临时表 2、使用 with 创建 temporary 表 3、对比 4、参考 1、使用 catalog 创建非临时表 CREATE CATALOG my_catalog WITH (type = paimon,warehouse = hdfs:///path/to/warehouse );USE CATALOG my_catalog; CREATE TABLE `<your-paimon-…...
js进阶-关于运算符++
一、运算符与表达式 运算符按参与的运算单元数量分为:一元运算符、二元运算符和三元运算符;表达式是运算单元和运算符一起构成的;每个表达式都有一个运算后的返回值。 二、关于运算符 1.概述 运算符分为两部分,第一部分是返回运…...
三维地图,智慧城市,商业智能BI,数据可视化大屏(Cesiumjs/UE)
绘图工具 三维地图:Cesiumjs 建模方式:激光点云建模、航拍倾斜摄影建模、GIS建模、BIM建模、手工建模 建模工具:C4D Blender GeoBuilding ArcGIS Cesiumjs <!DOCTYPE html> <html lang"en"> <head><meta …...
通过EPEL 仓库,在 CentOS 7 上安装 OpenResty
通过EPEL 仓库,在 CentOS 7 上安装 OpenResty 通过EPEL 仓库,在 CentOS 7 上安装 OpenResty步骤 1: 安装 EPEL 仓库步骤 2: 安装 OpenResty步骤 3: 启动 OpenResty步骤 4: 设置开机自启步骤 5: 验证安装说明 通过EPEL 仓库,在 CentOS 7 上安装…...
每日一题 LCR 054. 把二叉搜索树转换为累加树
LCR 054. 把二叉搜索树转换为累加树 使用后序遍历即可 class Solution { public:TreeNode* convertBST(TreeNode* root) {int temp 0;dfs(root,temp);return root;}void dfs(TreeNode* root,int &temp){if(!root){return ;}dfs(root->right,temp);temp root->val;…...
【贪心算法】贪心算法五
贪心算法五 1.跳跃游戏 II2.跳跃游戏3.加油站3.单调递增的数字 点赞👍👍收藏🌟🌟关注💖💖 你的支持是对我最大的鼓励,我们一起努力吧!😃😃 1.跳跃游戏 II 题目链接&…...
vue2播放视频和预览文件的组件以及使用方法
##文件预览组件 按照组件 解决展示pdf的问题 npm install pdfh5 npm install canvas2.8.0 --ignore-scripts npm install --save dommatrix npm install --save web-streams-polyfill解决excel和docx预览的问题 npm install vue-office/docx vue-demi0.14.6 npm inst…...
记录一下,解决js内存溢出npm ERR! code ELIFECYCLEnpm ERR! errno 134 以及 errno 9009
项目是个老项目,依赖包也比较大,咱就按正常流程走一遍来详细解决这个问题,先看一下node版本,我用的是nvm管理的,详细可以看我的其他文章 友情提醒:如果项目比较老,包又大,又有一些需…...
【批处理脚本】更改Windows系统中的 hosts 解析文件
概述 作用 修改 Windows 系统中的 hosts 文件,可以实现 插入 或 删除 条目。该脚本允许用户以管理员权限执行,将特定的域名解析到指定的 IP 地址 应用场景 非常适用于需要频繁或批量修改 hosts 文件的场景: 屏蔽网站、域名重定向、DNS 污染防…...
AIGC 与艺术创作:变革与机遇
在当今数字化时代,人工智能生成内容(AIGC)正以惊人的速度重塑着艺术创作的格局,为艺术家们带来了令人振奋的新机遇。 一.AIGC 的崛起与艺术领域的变革 随着人工智能技术的不断进步,AIGC 逐渐在艺术领域崭露头角。它依…...
String IP和Int IP的互相转换
android中,wifiManager.connectionInfo.ipAddress 可以获取到wifi的ip地址,但这是一个int值,如何转换为常见的如192.168.1.129这种形式,以及这种形式如何转换回int值的形式。 这里ip分为4段,每一段的值都是0 ~ 255&am…...
【大数据学习 | 面经】yarn的资源申请和分配的单位-Container
在yarn中,资源的申请和分配是以container为单位进行的,而不是直接以application和task为单位。 每个提交到yarn上的应用程序(application)都有一个对应的ApplicationMaster(AM)。这个AM负责与ResourceMana…...
php基础:文件处理2
1.文件属性 当我们在程序中操作文件时,可能会使用到文件的一些常见属性,比如文件的大小、类型、修改时间、访问时间以及权限等等。PHP 中提供了非常全面的用来获取这些属性的内置函数,如下表所示。 2.目录操作 新建目录:mkdir(路…...
gradle下载慢解决方案2024 /12 /1android studio (Windows环境)
gradle下载慢解决方案2024 /12 /1 默认环境配置好了,环境配置和程序安装请出门右转 打开软件,点击右上角设置,找到如下设置页 选择本地安装并制定好你已经安装好的 gradle 应用保存即可 全局插件环境配置(新版本可以直接在设置中添加了) 找对应位置添加国内源并把前面的内置源…...
使用Java将PDF文件解析成Excel文件
安装pom依赖 <!-- 解析pdf--><dependency><groupId>org.apache.pdfbox</groupId><artifactId>pdfbox</artifactId><version>2.0.27</version> <!-- 请检查并使用最新版本 --></dependency>测试读取pdf文件…...
怎么区分直线模组中的导程和行程?
直线模组是一种直线传动装置,安装方便,精度高,其使用范围广。直线模组中的导程和行程是两个不同的概念,它们分别描述了直线模组的不同性能参数。 直线模组的行程指的是模组能够正常移动的最大距离,即滑块预期移动的有效…...
算法日记 42 day 图论
今天来看看广度优先搜索,并且写几个题。刷到这里我才想起来,当时第一次面试的时候问的就是这个题,当时大概知道一点思路,但不清楚是图论方面的,更别说写出来了。 广度优先搜索(BFS) 不同于深度…...
STM32 GPIO 8种工作模式的应用场景
目录 一、四种输入模式1、模拟输入:2、浮空输入:3、上拉输入:4、下拉输入: 二、四种输出模式1、推挽输出:2、开漏输出:3、复用推挽输出:4、复用开漏输出: 一、四种输入模式 1、模拟…...
JVM 类加载器有哪些?双亲委派机制的作用是什么?如何自定义类加载器?
类加载器分类 大家好,我是码哥,可以叫我靓仔,《Redis 高手心法》畅销书作者。 先回顾下,在 Java 中,类的初始化分为几个阶段: 加载、链接(包括验证、准备和解析)和 初始化。 而 类加载器&#x…...
揭秘:短视频矩阵源码功能开发分析!!!
一、短视频矩阵系统源码概述 短视频矩阵系统源码旨在为内容创作者及企业提供一种高效的工具,以实现对多个短视频账户的一站式管理。该系统支持同时管理、发布、监控和优化多达1000个短视频账户,显著提升了操作效率。 二、主要功能 1. 多账号管理 该系…...
leetcode - 2337. Move Pieces to Obtain a String
Description You are given two strings start and target, both of length n. Each string consists only of the characters ‘L’, ‘R’, and ‘_’ where: The characters ‘L’ and ‘R’ represent pieces, where a piece ‘L’ can move to the left only if there i…...
第九篇:k8s 通过helm发布应用
什么是helm? Helm 是 Kubernetes 的包管理器。Helm 是查找、分享和使用软件构建 Kubernetes 的最优方式。 在红帽系的Linux中我们使用yum来管理RPM包,类似的,在K8s中我们可以使用helm来管理资源对象(Deployment、Service、Ingress…...
MySQL:锁机制
锁是计算机协调多个进程或线程并发访问某一资源的机制(避免争抢)。 在数据库中,除传统的计算资源(如 CPU、RAM、I/O 等)的争用以外,数据也是一种供许多用户共享的资源。如何保证数据并发访问的一致性、有效…...
在lio_sam中融入GPS
文章目录 概要GPS里程计GPS因子反算后的GPS里程计概要 在LIO(激光惯性里程计)系统中,将GPS信息融合到里程计中,借助GTSAM(Georgia Tech Smoothing and Mapping)库进行因子图优化,可以有效提升全局定位精度。 GPS里程计 利用GeographicLib第三方库将经纬度投影到局部笛…...
快速构建NLP理论知识体系
NLP理论知识体系 一句话解释NLPNLP模型及原理简述1、Rag 一句话解释NLP 如果我们要实现机器翻译、情感分析、问答系统、文本摘要、聊天机器人、构造智能化的辅助文件填写模板,NLP可以通过现成的模型对输入的语音、文字、图片进行处理(分词、标词性、去停…...
长期稳定境外号码解决方案:内地用户如何打电话、接收短信和验证码
文章目录 📖 介绍 📖🏡 演示环境 🏡📒 三大方案对比 📒📝 免费且稳定的境外号码📝 长期稳定且符合本地政策📝 适合低频使用者⚓️ 相关链接 ⚓️📖 介绍 📖 许多用户在日常生活中需要拨打境外电话、接收短信或验证码,尤其是跨境电商从业者,更是对境外号…...
SpringCloud 与 SpringBoot版本对应关系,以及maven,jdk
目录 SpringCloud 与 SpringBoot各版本的对应关系 方式一 Learn 方式二 OverView SpringBoot与JDK、maven 容器等对应关系 SpringCloud 与 SpringBoot各版本的对应关系 SpringCloudSpringBootFinchley2.0.xFinchley.SR1Spring Boot >=2.0.3.RELEASE and <=2.0.9RELEAS…...
FSMC实验
FSMC ,即灵活的静态存储控制器,能够与同步或异步存储器和 16 位 PC 存储器卡连接, STM32 的 FSMC 接口支持包括 SRAM 、 NAND FLASH 、 NOR FLASH 和 PSRAM 等存储器。 从上图我们可以看出, STM32 的 FSMC 将外部设…...
K8s命令大全(Complete List of K8s Commands)
💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 本人主要分享计算机核心技…...
C++学习笔记
小甲鱼学习课程 02 #include <iostream> 头文件 iostream iostream 翻译为IO流 输入输出流 using namespace std; 引入命名空间 c标准库所使用的所有标识符都是在同一个特殊的名字空间std中来定义的; 偷懒使用这句话; std::cout <…...
伺服控制电机多大功率合适?
随着现代工业自动化的发展,伺服控制电机在各个行业的应用愈加广泛。伺服电机以其精确的控制、高效的运行和高响应速度,成为许多机械设备中不可或缺的组成部分。然而,在选择伺服电机时,确定其功率大小是一个关键环节。那么…...
《OpenCV 基础全攻略:从入门到精通》
《OpenCV 基础全攻略:从入门到精通》 一、OpenCV 简介(一)特点(二)优势(三)应用场景 二、安装与配置三、OpenCV 函数详解1. 图像读取函数 cv2.imread ()2. 图像显示函数 cv2.imshow ()3. 图像保…...
spring ai如何使用function call调用第三方模型
这里写自定义目录标题 背景什么是function call怎么用function call?总结 背景 一直困惑于ai是如何使用插件或者其他一些功能的,后来发现,很多大模型都支持function call功能,如何让大模型能够联网查询呢,function ca…...
2024 数学建模国一经验分享
2024 数学建模国一经验分享 背景:武汉某211,专业:计算机科学 心血来潮,就从学习和组队两个方面指点下后来者,帮新人避坑吧 2024年我在数学建模比赛中获得了国一(教练说论文的分数是湖北省B组第一࿰…...
javaweb-Mybaits
1.Mybaits入门 (1)介绍 (2) 2.Mybaits VS JDBC 3.数据库连接池 (1)SpringBoot默认连接池为hikari,切换为Druid有两种方式 方式一:加依赖 方式二:直接修改配置文件 …...
108.【C语言】数据结构之二叉树查找值为x的节点
目录 1.题目 代码模板 2.分析 分类讨论各种情况 大概的框架 关键部分(继续递归)的详解 递归调用展开图 3.测试结果 其他写法 4.结论 5.注意事项 不推荐的写法 1.题目 查找值为x的节点并返回节点的地址 代码模板 typedef int BTDataType; typedef struct BinaryT…...
Ant-Design-Vue 全屏下拉日期框无法显示,能显示后小屏又位置错乱
问题1:在全屏后 日期选择器的下拉框无法显示。 解决:在Ant-Design-Vue的文档中,很多含下拉框的组件都有一个属性 getPopupContainer可以用来指定弹出层的挂载节点。 在该组件上加上 getPopupContainer 属性,给挂载到最外层盒子上。 <temp…...
sec啥意思
sec的基本含义是秒,是时间的基本单位之一;在数学中表示正割函数;在计算机科学中有时指安全;在法语中意为干的等。 sec的多重含义与应用 sec在数学中的定义 在数学领域,尤其是三角学中,sec代表正割函数&a…...
云计算vspere 安装过程
1 材料的准备 1 安装虚拟机 vmware workstation 2 安装esxi 主机 3 在esxi 主机上安装windows 2018 dns 服务器 4 在虚拟机上安装windows 2018 服务器 6 安装vcenter 5 登入界面测试 这里讲一下,由于部署vspere 需要在windows 2012 服务器上部…...
spring-boot打包前重新拉取maven依赖
在使用 Maven 构建 Spring Boot 项目时,如果希望在每次打包时都强制拉取依赖,可以通过以下方法实现。 方法一:在命令行强制更新依赖 在执行 mvn package 或 mvn install 等命令时,添加 -U 参数: mvn clean package -…...
华为云域名网站,域名切换到Cloudflare CDN出现访问报错:DNS 重定向次过多
网站域名切换到Cloudflare出现访问报错:重定向次过多,应该如何处理? 最近我自己已经遇到很多次这个情况了,将网站域名DNS切换到Cloudflare之后,网站会打不开,出现重定向次数过多报错。 网站域名切换到Clo…...
浔川AI翻译v5.1.0版本正式亮相!
浔川 AI 翻译 v5.1.0 版本正式亮相! 在科技浪潮汹涌澎湃的今天,浔川 AI 翻译以其卓越的技术实力和对用户需求的精准把握,自豪地向全球用户宣布:浔川 AI 翻译 v5.1.0 版本正式闪耀登场!这一全新版本在继承以往优势的基础…...
Merkle 树 应用在 代码工程
将 Merkle 树 应用在 代码工程 中,尤其是在大型项目中,可以帮助管理和验证代码的完整性、追踪代码变更、提高版本控制的效率等。通过将代码文件、类、函数等结构映射到 Merkle 树中,我们可以高效地验证代码库的任何变更,确保每个部…...
如何将表中存储的 JSON 数据转换为新表
如何将表中存储的 JSON 数据转换为新表 引言 本文介绍如何使用 PostgreSQL 的 JSON 函数,将 log_table 表中的 param_json 字段(存储为 JSON 数组)转换为一张新的表,并提取出具体的字段值。 表结构说明 假设 log_table 表的结…...
鸿蒙开发——使用ArkTs处理XML文本
1、概 述 XML(可扩展标记语言)是一种用于描述数据的标记语言,旨在提供一种通用的方式来传输和存储数据,特别是Web应用程序中经常使用的数据。XML并不预定义标记。因此,XML更加灵活,并且可以适用于广泛的应…...
借助vector实现进制转换详解
进制转换,没什么可说的,大一级别的水平,不过在某些考研题目中可能会涉及到顺序栈的实现,本贴不使用顺序栈,用STL里面的vector模拟一下:关键在于想清楚【除留取余】的逻辑,至于用什么结构存放中间…...
混合云策略在安全领域受到青睐
Genetec 发布了《2025 年物理安全状况报告》,该报告根据超过 5,600 名该领域领导者(其中包括 100 多名来自澳大利亚和新西兰的领导者)的回应,揭示了物理安全运营的趋势。 报告发现,澳大利亚和新西兰的组织采用混合云策…...
Jackson - 序列化和反序列化Java集合对象
在本文中,我将向您展示如何使用Jackson API来序列化和反序列化Java集合对象,如List、Set和Map。 我们将通过具体的示例演示如何利用ObjectMapper类的方法进行这些操作。 主要内容 添加Maven依赖项使用Jackson API进行List序列化使用Jackson API进行Se…...