【软考系统架构设计师】软件工程
1、 软件开发生命周期
软件定义时期:包括可行性研究和详细需求分析过程,任务是确定软件开发工程必须完成的总目标,具体分为问题定义、可行性研究、需求分析等
软件开发时期:软件的设计与实现,分为概要设计、详细设计、编码、测试等
软件运行和维护:把软件产品移交给用户使用
2、 软件系统的文档
分为用户文档和系统文档,用户文档主要描述系统功能和使用方法,不涉及功能怎样实现的,系统文档描述系统设计、实现和测试等内容
3、 软件工程过程是指为获得软件产品,在软件工具的支持下由软件工程师完成的一系列软件工程活动,包括以下4个方面
P(Plan)软件规格说明:规定软件的功能及其运行时的限制
D(Do)软件开发:开发出满足规格说明的软件
C(Check)软件确认:确认开发的软件能够满足用户的需求(有效性验证)
A(Action)软件演进:软件在运行过程中不断改进以满足用户的客户新的需求
4、 软件系统工具:
通常可以按软件过程活动将软件工具分为软件开发工具、软件维护工具 、软件管理和软件支持工具。
软件开发工具:需求分析工具、设计工具、编码与排错工具。
软件维护工具:版本控制工具、文档分析工具、开发信息库工具、逆向工程工具、再工程工具。
软件管理和软件支持工具:项目管理工具、配置管理工具、软件评价工具、软件开发工具的评价和选择。
按描述需求定义的方法可将需求分析工具分为基于自然语言或图形描述的工具和基于形式化需求定义语言的工具。
5、 可行性分析包括四个方面:经济可行性、技术可行性、法律可行性、用户使用可行性
6、 软件能力成熟度模型集成CMMI(Capability Maturity Model Integration for Software)
能力等级 | 特点 |
Level 1 初始级 | 过程通常是随意且混乱。组织的成功依赖于组织内人员的能力与英雄主义。常常也能产出能用的产品与服务,但它们经常超出在计划中记录的预算与成本。 |
Level 2 已管理级 | 组织要确保策划、文档化、执行、监督和控制项目级的过程,并且需要为过程建立明确的目标,并能实现成本、进度和质量目标。 |
Level 3 已定义级 | 企业能够根据自身的特殊情况定义适合自己企业和项目的标准流程,将这套管理体系与流程予以制度化,同时企业开始进行项目积累,企业资产的收集 |
Level 4 量化管理级 | 组织建立了产品质量、服务质量以及过程性能的定量目标,这一成熟度的特点是对过程性能的可预测性 |
Level 5 优化级 | 企业的项目管理达到了最高的境界。关注与通过增量式的创新式的过程与技术改进,不断改进过程性能。组织使用从多个项目收集来的数据对整体的组织绩效进行关注。 |
6、 软件项目管理:为了使软件项目能够按照预定的成本、进度、质量顺利完成,而对人员、产品、过程和项目进行分析和管理的活动。
范围管理过程:范围计划编制、范围定义(产品范围、工作范围)、创建WBS(工作分解结构,WBS树形结构中最底层的被称为工作包,是最低层次的可交付成果,它应当由唯一主题负责完成)、范围确认、范围控制
成本管理过程包括:成本估算、成本预算、成本控制。成本估算是对完成项目活动所需资金进行近似估算,估算方法有自顶向下估算、自底向上估算、差别估算;成本预算是将总的成本估算分配到各项活动和工作包上,来建立一个成本的基线,包含直接成本和间接成本;成本控制
进度(时间)管理过程:活动定义、活动排序、活动资源估算、活动历时估计、制定进度计划(涉及任务活动图,类似前驱图)、进度控制
质量管理:影响软件质量的因素分为3组,分别是产品运行、产品修改、产品转移。其中产品运行包含正确性、健壮性、效率、完整性、可用性、风险;产品修改包含可理解性、可维护性、灵活性、可测试性;产品转移包含可移植性、可再用性、互运行性
配置管理:一种标识、组织和控制修改的技术,应用于整个软件工程过程。配置管理核心内容包括版本控制(主要功能是追踪文件的变更,记录每个状态变更的日期和变更者)和变更控制(不是控制变更的发生,而是对变更进行管理,确保变更有序进行)。配置管理系统中管理的是配置项(包括各种文档、代码和运行所需数据,主要属性有名称、标识符、版本、作者、日期等),所有的配置项都被保存在配置库里,配置库分为开发库(随便修改)、受控库(修改需要走变更控制流程)、产品库(禁止修改)
变更控制流程
版本控制流程
风险管理:主要目标是预防风险。软件项目风险是指软件开发过程中遇到的预算和进度等方面的问题以及这些问题对软件项目的影响。软件项目风险分为项目风险、技术风险、商业风险。对风险排优先级是根据风险的曝光度来进行的,曝光度等于风险的产生后果乘以风险发生的概率。
7、 软件过程模型:为了使软件生命周期中的各项任务能够有序地按照规程进行,需要一定的工作模型对各项任务给予规程约束,这样的工作模型称为软件过程模型或软件开发模型,也叫软件生命周期模型。软件开发模型大体可以分为三类,第一种是以软件需求完全确定为前提的瀑布模型;第二种是在软件开发初始阶段只能提供基本需求时采用的迭代式或渐进式模型,例如喷泉模型、螺旋模型、统一过程模型和敏捷模型等;第三类是以形式化为基础的变换模型。
瀑布模型(SDLC):是典型的软件生命周期模型,一般将软件开发分为需求分析、系统设计、程序设计、编码实现、单元测试、集成测试、系统测试、运行维护
特点:
(1)严格区分阶段,每个阶段因果关系紧密相连
(2)只适合需求明确的项目
缺点:
(1)软件需求完整性、正确性难确定
(2)严格串行化,很长时间才能看到结果
(3)要求每个阶段一次性完全解决该阶段工作,不现实
原型化模型(Prototype Model)也叫快速原型
原型模型的两个阶段:原型开发阶段和目标软件开发阶段
原型分类:抛弃型原型和演化原型
特点:
(1)适合需求不明确的项目
V模型:用于需求明确和需求变更不频繁的项目
特点:
(1)测试贯穿于始终
(2)测试分阶段,测试计划提前
迭代与增量模型:首先开发核心模块功能,用户确认后再开发次核心模块,最终完成项目开发,即优先级最高的服务最先交付。每一个增量或迭代都是一个完整的开发过程。
增量型:一块一块增加
迭代型:一轮一轮变好
敏捷模型(Agile)
价值观:
核心思想:
(1)适应型而非可预测型
(2)面向以人为本而非以过程为本
(3)迭代增量式开发过程,以原型开发思想为基础
具体敏捷方法:
(1)极限编程(Extreme Programming,XP):提倡测试先行
4大价值观
沟通【加强面对面沟通】
简单【从简单做起,不过度设计】
反馈【及时反馈】
勇气【接受变更的勇气】
(2)水晶系列方法:提倡机动性的方法,拥有对不同类型项目非常有效的敏捷过程
(3)并列争球法(Scrum):侧重于项目管理,是迭代的增量化过程,把每段时间的一次迭代称为一个冲刺(Sprint)
(4)特征驱动开发方法(Feature Driven Development,FDD):
认为有效的软件开发需要3个要素:人、过程和技术
定义了6种关键的项目角色:项目经理、首席架构设计师、开发经理、主程序员、程序员和领域专家
5个核心过程:开发整体对象模型、构造特征列表、计划特征开发、特征设计和特征构建
螺旋模型(Spiral Model):是在快速原型的基础上扩展而成,它是瀑布模型与快速原型模型的结合。这种模型把整个软件开发流程分为多个阶段,每个阶段都由4部分组成:
(1)目标设定:确定目标、方案和约束
(2)风险分析:评价方案、识别风险、消除风险
(3)开发和有效性验证:风险评估后,为系统选择开发模型,开发软件产品
(4)评审:对项目进行评审,以确定是否需要进入螺旋线的下一次回路
特点:
(1)支持大型软件开发
(2)适用于面向规格说明、面向过程和面向对象的软件开发方法
统一过程模型(RUP):描述了如何有效地利用商业的、可靠的方法开发和部署软件,是一种重量级过程。RUP类似一个在线的指导者,它可以为所有方面和层次的程序开发者提供指导方针、模板以及事例支持
RUP软件开发生命周期是一个二维的软件开发模型,有9个核心工作流:
(1)业务建模:理解待开发系统所在的机构及商业运作,评估待开发系统对所在机构的影响
(2)需求:定义系统功能及用户界面,为项目预算及计划提供基础
(3)分析与设计:把需求分析的结果转化为分析与设计模型
(4)实现:把设计模型转换为实现结果,对开发的代码做单元测试,将不同实现人员开发的模块集成为可执行系统
(5)测试:检查各子系统件的交互、集成,验证所有需求是否均被正确实现,对发现的软件质量上的缺陷继续归档,对软件质量提出改进建议
(6)部署:打包、分发、安装软件,升级旧系统。培训用户及销售人员,并提供技术支持
(7)配置与变更管理:跟踪并维护系统开发过程中产生的所有制品的完整性和一致性
(8)项目管理:为软件开发项目提供计划、人员配置、执行、监控等方面的指导
(9)环境:为软件开发机构提供软件开发环境,及提供过程管理和工具的支持
RUP把软件开发生命周期划分为多个循环,每个循环生成产品的一个新版本,即每个迭代都是一个完整的开发过程。每个循环依次由4个连续的阶段组成,分别是:
(1)初始阶段:定义最终产品视图和业务模型,确定系统范围(生命周期目标)
(2)细化阶段:设计及确定系统的体系结构,制定工作计划及资源要求(生命周期架构)
(3)构造阶段:构造产品并继续演进需求、系统结构、计划直至产品提交(初始运作功能)
(4)移交阶段:把产品提交给用户使用(产品发布)
RUP模型特点:
(1)用例驱动:需求分析、设计、实现和测试等活动都是用例驱动的
(2)以体系结构为中心:多维的结构,采用多个视图来描述,典型的4+1视图模型如下
(3)迭代与增量:把整个项目开发分为多个迭代过程
形式化方法模型:建立在严格数学基础上的一种软件开发方法,它的优越性在于能够精确地表述和研究应用问题及软件实现
喷泉模型:一种以用户需求为动力,以对象作为驱动的模型,适合于面向对象的开发方法,体现了面向对象的迭代和无间隙性
快速应用开发模型(Rapid Application Development,RAD):基于构件化开发与瀑布模型,适用于模块化较高的系统开发,过程分为业务建模、数据建模、过程建模、应用生成和测试与交付
构件:软件构件是一 个独立可交付的功能单元,外界通过接口访问其提供的服务。软件构件可以被独立地部署并由第三方任意地组装。构件是一组通常需要同时部署的原子构件,一个原子构件是一个模块和一组资源。原子构件是部署、版本控制和替换的基本单位。原子构件通常成组地部署,但是它也能够被单独部署。大多数原子构件永远都不会被单独部署,尽管它们可以被单独部署。相反,大多数原子构件都属于一个构件家族,一次部署往往涉及整个家族。
模块、对象和构件的区别:模块是一组类和可能的非面向对象的结构体,比如过程或者函数,一个模块是不带单独资源的原子构件,一个构件可以包含多个类元素,但是一个类元素只能属于一个构件
面向构件的编程(COP)需要下列的基本支持:
多态性(可替代性)
模块封装性(高层次信息的隐藏)
后期的绑定和装载(部署独立性)
安全性(类型和模型安全性)
常用的构件标准主要有:
EJB规范:会话Bean(Session Bean)、实体Bean(Unity Bean)、消息驱动Bean(Message-driven Bean)
COM:微软公司,两种对象重用方式(包含、聚合)
CORBA:三个层次分别为对象请求代理、公共对象服务和公共设施
构件的复用过程:
(1)检索与提取构件
(2)理解与评价构件
(3)修改构件
(4)组装构件
从构件的外部形态来看,构成一个系统的构件可分为五类:
(1)独立而成熟的构件:得到实际运行环境多次检验的构件,该类构件隐藏了所有接口,用户只需用规定好的命令进行使用。比如数据库管理系统和操作系统等。
(2)有限制的构件:该类构件提供了接口,指出了使用的条件和前提,这种构件在装配时,会产生资源冲突、覆盖等影响,在使用时需要加以测试,例如各种面向对象程序设计语言中的基础类库等。
(3)适应性构件:该类构件进行了包装或使用了接口技术,处理了不兼容性、资源冲突等,可以直接使用。这种构件可以不加修改地使用在各种环境,例如ActiveX等。
(4)装配的构件:该类构件在安装时已经装配在操作系统、数据库管理系统或信息系统不同层次上,使用胶水代码就可以进行连接使用。目前一些软件商提供的大多数软件产品都属于这类。
(5)可修改的构件:这类构件可以进行版本替换。 如果对原构件修改错误、增加新功能,可以利用重新“包装”或写接口来实现构件的替换。这种构件在应用系统开发中使用得比较多。
构件组装模型
优点:易扩展、易重用、降低成本、安排任务更灵活
缺点:构件设计要求经验丰富的架构师、设计不好的构件难重用、强调重用可能牺牲其它指标、第三方构件质量难控制
基于构件的软件工程(Component-Base Software Engineering,CBSE):使得软件开发不再是一切从头开始,开发的过程主要就是构件组装的过程,维护的过程主要就是构件升级、替换和扩充的过程,其优点是提高了软件开发的效率。
CBSE方法由五个阶段组成:
(1)需求分析和定义。需要重点阐述本系统跟曾经开发过的其他系统的相似性,具有大量可复用的成熟构件。
(2)架构设计。根据上一阶段获得的需求和定义提出架构模型。
(3)构件库建立。构件获取的四种途径:
从现有构件库中获取符合要求的构件,直接使用或作适应性修改后使用。构件库中的构件分类方法有三种:关键字分类法、刻面(Facet)分类法和超文本组织方法。因此构件库的检索方法也有三种:基于关键字的检索法、刻面检索法、超文本检索法。
将遗产工程(Legacy Engineering)中具有潜在复用价值的构件提取出来,得到复用的构件。
从市场上购买现成的商业构件,即COTS(Commercial Off-The-Shelf)构件。
开发新的符合要求的构件。
(4)应用软件构建。应用软件的构建过程主要是构件的组装过程
组装技术有三种:
基于功能的组装技术
基于数据的组装技术
面向对象的组装技术
组装方式有三种:
顺序组装:按顺序调用已经存在的构件,可用两个已经存在的构件来创建一个新的构件。上一个构件的输出,与下一个构件的输入相兼容。
层次组装:通常发生在一个构件直接调用另一个构件所提供的服务时。被调用构件的提供接口必须和调用构件的请求接口完全兼容
叠加组装:通常发生在两个或两个以上构件放在一起来创建一个新构件的时候。多个构件合并形成新构件,新构件整合原构件的功能,对外提供新的接口。外部应用可以通过新接口来调用原有构件的接口,而原有构件不互相依赖,也不互相调用。
组装失配问题:
由构件引起的失配
由连接子引起的失配
由于系统成分对全局体系结构的假设存在冲突引起的失配
(5)测试和发布。增量和迭代的过程
用于CBSE的构件具备以下特征:
(1)可组装型:所有外部交互必须通过公开定义的接口进行
(2)可部署性:构件总是二进制形式的,无需在部署前编译,能作为一个独立实体在平台上运行
(3)文档化:用户根据文档来判断构件是否满足需求
(4)独立性:可以在无其他特殊构件的情况下进行组装和部署
(5)标准化:符合某种标准化的构件模型
8、 逆向工程:分析程序,力图在比源代码更高抽象层次上建立程序的表示过程,逆向工程是设计的恢复过程。分为四个级别:
实现级:包括程序的抽象语法树、符号表、过程的设计表示
结构级:包括反映程序分量之间相互依赖关系的信息,例如调用图、结构图、程序和数据结构
功能级:包括反映程序段功能及程序段之间关系的信息,比如数据和控制流模型
领域级:包括反映程序分量或程序诸实体与应用领域概念之间对应关系的信息,比如E-R模型
领域级抽象级别最高,完备性最低;实现级抽象级别最低,完备性最高。
软件复用是指在两次或多次不同的软件开发过程中重复使用相同或者相似软件软件元素的过程。软件元素包括需求分析文档、设计过程、设计文档、程序代码、测试用例、领域知识等。
与逆向工程相关的概念:重构、设计恢复、再工程和正向工程
重构是指同一抽象级别上转换系统描述形式
设计恢复是指借助工具从已有程序中抽象出有关数据设计、总体结构设计和过程设计等方面的信息
正向工程是指不仅从现有系统中恢复设计信息,而且使用该信息去改变或重构现有系统,以改善整体质量
再工程是指在逆向工程所获得信息的基础上,修改或重构已有的系统,产生系统的一个新版本。再工程是对现有系统的重新开发过程,包括逆向工程、新需求的考虑过程和正向工程三个步骤
9、 净室软件工程(Cleanroom Software Engineering,CSE):是一种应用数学与统计学理论以经济的方式生产高质量软件的工程技术,力图通过严格的工程化的软件过程达到开发中的零缺陷或接近零缺陷。净室方法不是先制作一个产品,再去消除缺陷,而是要求在规约和设计中消除错误。CSE是软件开发的一种形式化方法,使用盒结构规约进行分析和设计建模,强调正确性验证而不是测试,使用统计的测试来获取认证被交付的软件的可靠性所必需的出错率信息。
技术手段:
(1)统计过程控制下的增量式开发:控制迭代
(2)基于函数的规范和设计:盒子结构
定义3种抽象层次:行为试图(黑盒)->有限状态机视图(状态盒)->过程视图(明盒)
(3)正确性验证:净室工程的核心
(4)统计测试和软件认证:使用统计学原理,总体太大时必须采用抽样方法
10、 需求工程
软件需求是指用户对系统在功能、行为、性能、设计约束等方面的期望。
需求分类及获取方法
11、 需求分析
结构化方法(Structured Analysis,SA)
数据流图主要有以下几个部分组成:
数据流:由一组固定成分的数据组成,表示数据的流向。它可以是输入、输出或存储在系统中的数据。每个数据流通常有一个合适的名词,反映数据流的含义。
加工:描述了输入数据流到输出数据流之间的变换,也就是输入数据流做了什么处理后变成了输出数据流。
数据存储:用来表示暂时存储的数据,每个文件都有名字。流向文件的数据流表示写文件,流出的表示读操作。
外部实体:与系统进行信息交流的外部机构或个人
数据流图遵循的数据平衡原则:
(1)数据守恒原则:每个加工环节的输出数据流应该是对其输入数据流中的数据处理后的结果
(2)守恒加工原则:对同一个加工来说,输入数据流与输出数据流的名字必须不同,即使它们的组成成分相同
(3)每个加工环节都必须有输入与输出数据流
(4)外部实体与外部实体之间不存在数据流
(5)外部实体与数据存储之间不存在数据流
(6)数据存储与数据存储之间不存在数据流
(7)父图与子图的平衡原则:子图的输入输出数据流同父图相应加工的输入输出数据流必须一致
结构化分析方法中的功能模型建模过程如下:
(1)明确目标,确定系统范围
(2)建立顶层DFD图
(3)构建第一层DFD分解图
(4)开发DFD层次结构图
(5)检查确认DFD图
结构化分析方法中的数据模型建模过程(ER作图步骤):
(1)确定所有的实体集合
(2)确定每个实体集包含的属性
(3)确定实体集之间的联系
(4)确定实体集的关键字
(5)确定联系的类型
12、 软件设计包括体系结构设计、接口设计、数据设计和过程设计
(1)结构设计:定义软件系统各主要部件之间的关系
(2)数据设计:将模型转换成数据结构的定义,好的数据设计将改善程序结构和模块划分,降低复杂性
(3)接口设计(人机界面设计):软件内部、软件和操作系统之间,以及软件和人之间如何通信
(4)过程设计:系统结构部件转换成软件的过程描述
13、 软件设计的启发规则是对按照软件设计原则设计的结果进行优化的规则,具体包括:改进软件结构提高模块独立性;模块规模应当适中;深度、宽度、扇出和扇入都应适当;模块的作用域应该在控制域内;力争降低模块接口的复杂程度;设计单入口单出口的模块;模块功能应该可以预测
14、 结构化设计(Structured Design,SD)是一种面向数据流的设计方法,它以需求获取SRS和需求分析SA阶段所产生的数据流图和数据字典等文档为基础,是一个自顶向下、逐步求精和模块化的过程。
模块化要求模块独立性,因为有效的模块化(即具有独立性的模块)软件比较容易开发出来,另外独立的模块比较容易测试和维护。模块的独立程度可以由两个定性标准度量,分别是内聚和耦合。
耦合程度 | 耦合类型 | 描述 |
从上到下 由低到高 | 非直接耦合 | 两个模块之间没有直接关系,它们之间的关系完全通过上级模块的控制和调用来实现 |
数据耦合 | 一个模块传给另一个模块的参数是一个单个的数据项或者单个数据项组成的数组(值传递) | |
标记耦合 | 一个模块传递给另一个模块的参数是一个复合的数据结构(引用传递) | |
控制耦合 | 模块之间传递的信息中包含用于控制模块内部逻辑的信息 | |
通信耦合 | 一组模块共用了一组输入信息,或者它们的输出需要整合以形成完整数据,即共享输入或输出 | |
公共耦合 | 多个模块都访问同一个公共数据环境,比如数据结构 | |
内容耦合 | 一个模块直接访问另一个模块的内部数据;一个模块不通过正常入口转到另一个模块的内部;两个模块有一部分代码重叠;一个模块有多个入口等 |
内聚程度 | 内聚类型 | 描述 |
从上到下 由高到低 | 功能内聚 | 完成一个单一功能,各部分缺一不可 |
顺序内聚 | 处理元素相关,且必须顺序执行,即模块中某个成分的输出是另一个成分的输入 | |
通信内聚 | 模块中的成分引用共同的输入数据,或者产生相同的输出数据 | |
过程内聚 | 处理元素相关,且必须按特定的次序执行 | |
时间内聚 | 所包含的任务必须在同一时间间隔内执行 | |
逻辑内聚 | 完成逻辑上相关的一组任务,使用时由调用模块传递的参数确定执行的功能 | |
偶然内聚 | 完成一组没有关系或者松散关系的任务 |
15、 过程设计涉及到的图形工具包括:数据流程图、Jackson图、程序流程图(PFD,程序框图)、系统流程图、PAD图、N-S流程图(盒图)、PDL(伪码或结构化语言)、判定树、判断表、层次方框图、Warnier图、IPO图
16、面向对象方法:是一种以对象、对象关系等来构建软件系统模型的系统化方法。
优势:符合人类的思维习惯、稳定性好、可复用性好、可维护性好
类图展现了一组对象、接口、协作和它们之间的关系。定时图强调消息跨越不同对象或参与者的实际时间,而不仅仅只是关心消息的相对顺序。部署图描述软件和硬件组件之间的物理关系以及处理节点的组件分布情况。包图是一种将模型元素(如类、接口、用例等)组织成逻辑分组的机制,以便更好地管理和理解大型或复杂的模型。
对象模型描述系统数据结构
动态模型描述系统控制结构
功能模型描述系统功能
功能模型指明了系统应该做什么
动态模型明确规定了什么时候做
对象模型定义做事情的实体
3种模型都涉及数据、控制和操作等共同的概念,但侧重点不同,综合起来全面地反映了对目标系统的需求,都可用于软件的需求分析。
17、 面向对象分析步骤:
(1)确定对象和类(类与对象层)
(2)确定结构(结构层)
(3)确定主题(主题层)
(4)确定属性(属性层)
(5)确定方法(服务层)
在面向对象分析中,利用用例和用例图表示需求,从用例模型中提炼形成分析模型(领域模型),用例的实现可以用交互图表示。从领域模型和用例模型形成类图,用包图和类图形成体系结构图。
面向对象分析原则:
(1)抽象
(2)封装
(3)继承
(4)分类
(5)聚合
(6)关联
(7)消息通信
(8)粒度控制
(9)行为分析
面向对象需求分析建模:
(1)边界类:用于封装在用例内、外流动的信息或数据流,位于系统与外界的交接处。包括机器接口和人机交互,比如显示屏、窗体、打印机接口、通信协议、对话框、菜单、购物车、报表、二维码等。
(2)控制类:用于控制用例工作的类,一般由动宾结构的短语转化而来,包括应用逻辑、业务逻辑、数据访问逻辑,比如身份验证器。
(3)实体类:需要持久化的数据或者文件,比如学生类、课程类
用例之间的关系有以下三种:
泛化关系:一个用例可以被特别列举为一个或多个子用例。
包含关系:一个用例(基础用例)的行为包含了另一个用例(包含用例)的行为。基础用例可以看到包含用例,并依赖于包含用例的执行结果,但二者不能访问对方的属性。
扩展关系:把新的行为加入到已有的用例中,来获得新用例,其中新用例叫扩展用例,原有用例叫基础用例。扩展关系属于一种特殊的泛化关系,实际上是增加接口,是抽象类的泛化关系。
“登录系统”用例与“注册课程”用例之间是包含关系;“参加考试”用例与“参加补考”用例之间是扩展关系。
类之间的关系有:
依赖关系:当一个类使用了另一个类时,它们之间就存在依赖关系。这种关系可以是编译时的依赖,也可以是运行时的依赖。例如,一个类可能是另一个类的成员属性、方法返回值类型、方法参数类型或局部变量。
关联关系:是双向的依赖关系,表示类与类或类与接口之间的结构化关系,在代码中,关联类有一个成员变量保存的是被关联类的引用。
泛化关系:是依赖关系的一种特例,通常是指继承关系。
聚合关系:关联关系的一种特例,体现的是整体与部分的关系,整体与部分之间是可以分离的,各自具有各自的生命周期。部分可以属于多个整体对象,也可以为多个整体对象共享。
组合关系:是关联关系的一种特例,比聚合更强,同样体现整体与部分的关系,但整体与部分之间不可以分离的,整体的生命周期结束也就意味着部分的生命周期结束。
实现关系:当一个类实现一个接口时,它们之间存在的就是实现关系。
顺序图描述了对象之间交互过程中的时间顺序,侧重点在对象按时间顺序的消息交换。
协作图(通信图)描述了对象之间组织协作关系,侧重点在对象如何协同工作。
数据流图作为一种图形化工具,用来说明业务处理过程、系统边界内所包含的功能和系统中的数据流。
程序流程图以图形化的方式展示应用程序从数据输入开始到获得输出数据为止的逻辑过程,描述处理过程的控制流。
两者之间的区别主要有:
(1)数据流图中的处理过程可并行;程序流程图在某个时间点只能处于某一个处理过程
(2)数据流图展现系统的数据流;程序流程图展现系统的控制流
(3)数据流图展现全局的处理过程,过程之间遵循不同的计时标准;程序流程图中处理过程遵循一致的计时标准
(4)数据流图适用于系统分析中的逻辑建模阶段;程序流程图适用于系统设计中的物理模型阶段
活动图和状态图的差别:
(1)描述对象不同。状态图描述对象状态及状态之间的转移,以状态为中心;活动图描述从活动到活动的控制流,以活动为中心。
(2)使用场合不同。状态图描述对象在其生命期中的行为状态变化;活动图描述过程的流程变化。
活动图和流程图的区别:
(1)描述重点不同:流程图着重描述处理过程,它的主要控制结构是顺序、分支和循环,各个处理过程之间有严格的顺序和时间关系。而活动图描述的是对象活动的顺序关系所遵循的规则,它着重表现的是系统的行为,而非系统的处理过程。
(2)并发活动的表示:活动图能够表示并发活动的情形,而流程图则不能。
(3)面向对象与面向过程:活动图是面向对象的,而流程图是面向过程的。
(4)顺序指定:流程图明确地指定了每个处理过程的先后顺序,而活动图仅描述了活动和必要的工作顺序
18、 面向对象设计过程:
(1)建立软件体系结构环境图
(2)体系结构设计
(3)子系统设计
(4)对象设计
面向对象的分析模型主要由顶层架构图、用例与用例图、领域概念模型构成。设计模型包含以包图表示的软件体系结构图、以交互图表示的用例实现图、完整精确的类图、针对复杂对象的状态图和用以描述流程化处理过程的活动图等。
当采用面向对象的设计方法描述对象模型时,通常使用类图表达类的内部属性和行为,以及类集合之间的交互关系;采用状态图定义对象的内部行为。
19、 面向对象设计的7大原则
(1)单一职责原则(Single Responsibility Principle,SRP):类的职责主要包括数据职责和行为职责两个方面,数据职责通过属性来体现,行为职责通过方法体现。一个类承担的职责越多,它复用的可能性越小。一个对象应该只包含单一的职责,并且该职责应该被完整地封装在一个类中。单一职责原则是实现高内聚、低耦合的指导方针。
(2)开闭原则(Open-Closed Principle,OCP):一个软件实体应当对扩展开放,对修改关闭。也就是说在设计模块的时候,应当使这个模块可以在不被修改的前提下被扩展。软件实体可以指一个软件模块、一个由多个类组成的局部结构或一个独立的类。抽象化是开闭原则的关键。
(3)里氏代换原则(Liskov Substitution Principle,LSP):所有引用基类(父类)的地方必须能透明地使用其子类的对象。里氏代换原则是实现开闭原则的重要方式之一,由于使用基类对象的地方都可以使用子类,因此在程序中尽量使用基类类型来对对象进行定义,而在运行时再确定其子类类型,用子类对象替换父类对象(即常说的多态)。
(4)依赖倒转原则(Dependence Inversion Principle,DIP):高层模块不应该依赖于底层模块,它们都应该依赖抽象。抽象不应该依赖于细节,细节应该依赖于抽象。要针对接口编程,不要针对实现编程。开闭原则是面向对象设计的目标,依赖倒转原则是面向对象设计的主要手段。
(5)接口隔离原则(Interface Segregation Principle,ISP):使用多个专门的接口,而不使用单一的总接口。
(6)合成复用原则(Composite Reuse Principle,CRP):也叫组合/聚合复用原则,即尽量使用对象组合,而不是继承来达到复用的目的。
(7)迪米特法则(Law of Demeter,LoD)又称最少知识原则(Least Knowledge Principle,LKP):只与自己朋友之间通信,每个软件单位对其他的单位都只有最少的知识,而且局限于那些与本单位密切相关的软件单位。
20、 面向对象软件的测试分为4个层次:算法层(单元测试)、类层(模块测试)、模版层(集成测试)、系统层(系统测试)
21、 测试原则:
(1)尽早、不断地进行测试
(2)程序员避免测试自己设计的程序
(3)既要选择有效、合理的数据,也要选择无效、不合理的数据
(4)修改后应进行回归测试
(5)尚未发现的错误数量与该程序已发现错误数成正比
22、 测试分类
动态测试:通过运行被测试程序,对得到的运行结果与预期的结果进行比较分析,同时分析运行效率和健壮性等。包括黑盒测试、白盒测试和灰盒测试
静态测试:被测试程序不运行,只依靠分析或检查源程序的语句、结构、过程等来检查程序是否有错误。包括桌前检查、代码走查和代码审查
其它测试:AB测试、Web测试、链接测试、表单测试
23、 测试用例设计
黑盒测试用例测试方法:等价类划分、边界值分析、错误推测、因果图
白盒测试用例测试方法:基本路径测试、循环覆盖测试、逻辑覆盖测试(语句覆盖、判定(分支)覆盖、条件覆盖、判定条件覆盖、组合覆盖、路径覆盖)
24、 测试阶段
(1)单元测试:先用静态测试方法测试,再通过动态测试方法测试
(2)集成测试:一般采用白盒测试与黑盒测试的结合方法进行
(3)系统测试:本阶段测试内容包含功能测试、性能测试、健壮性测试、安装测试、压力测试、可靠性测试、安全性测试等
(4)验收测试:最后一阶段的测试,这阶段应进行Alpha测试和Beta测试。Alpha测试是指软件在开发环境下由用户进行的测试。Beta测试是指软件在实际环境中由多个用户进行的测试
25、 系统维护分为:纠错性维护、适应性维护、完善性维护、预防性维护
相关文章:
【软考系统架构设计师】软件工程
1、 软件开发生命周期 软件定义时期:包括可行性研究和详细需求分析过程,任务是确定软件开发工程必须完成的总目标,具体分为问题定义、可行性研究、需求分析等 软件开发时期:软件的设计与实现,分为概要设计、详细设计、…...
蓝桥杯单片机刷题——ADC测量电位器的电压
设计要求 通过PCF8591的ADC通道测量电位器RB2的输出电压,并使用套件上提供的USB转串口功能,完成下列程序设计要求。 串口每次接收包含5个字符的字符串, 1)若接收的5个字符中有字符’a’或’A’,则数码管显示一位小数…...
零基础上手Python数据分析 (12):DataFrame 数据清洗与预处理 (下) - 类型转换、格式化、文本与日期处理
写在前面 上一篇博客,我们学习了如何使用 Pandas 处理数据分析中最常见的 “脏数据”:缺失值、重复值和异常值。 这为我们处理数据质量问题打下了坚实的基础。 然而,数据清洗的挑战远不止于此。 在实际数据中,我们还会经常遇到 数据类型不一致、数据格式不规范、文本数据混…...
免费下载 | 2025清华五道口:“十五五”金融规划研究白皮书
《2025清华五道口:“十五五”金融规划研究白皮书》的核心内容主要包括以下几个方面: 一、五年金融规划的重要功能与作用 凝聚共识:五年金融规划是国家金融发展的前瞻性谋划和战略性安排,通过广泛听取社会各界意见,凝…...
制造一只电子喵 (qwen2.5:0.5b 微调 LoRA 使用 llama-factory)
AI (神经网络模型) 可以认为是计算机的一种新的 “编程” 方式. 为了充分利用计算机, 只学习传统的编程 (编程语言/代码) 是不够的, 我们还要掌握 AI. 本文以 qwen2.5 和 llama-factory 举栗, 介绍语言模型 (LLM) 的微调 (LoRA SFT). 为了方便上手, 此处选择使用小模型 (qwen2…...
Java中parallelStream并行流使用指南
Java中parallelStream并行流使用指南 在 Java 中,parallelStream() 是 Java 8 引入的一个用于并行处理集合数据的工具,它基于 Fork/Join框架 实现,能够自动将任务拆分成子任务并利用多核处理器并行执行。以下是对 parallelStream的详细说明和…...
Python及C++中的列表
一、Python中的列表(List) Python的列表是动态数组,内置于语言中,功能强大且易用,非常适合算法竞赛。 1. 基本概念 定义:列表是一个有序、可变的序列,可以存储任意类型的元素(整数…...
mybatis plus 分页查询出来数据后对他二次 修改数据 封装返回
mybatis plus 分页查询出来数据后对他二次 修改数据 封装返回 /*** 搜索问卷** param keyword* param pageNo* param pageSize* return*/AutoLog(value "v_survey-搜索")ApiOperation(value"v_survey-搜索", notes"v_survey-搜索")GetMapping(v…...
海洋大地测量基准与水下导航系列之八我国海洋水下定位装备发展现状
中国国家综合PNT体系建设重点可概括为“51N”,“5”指5大基础设施,包括重点推进下一代北斗卫星导航系统、积极发展低轨导航增强系统、按需发展水下导航系统、大力发展惯性导航系统、积极探索脉冲星导航系统;“1”是实现1个融合发展࿰…...
基于单片机的电梯智能识别电动车阻车系统设计与实现
标题:基于单片机的电梯智能识别电动车阻车系统设计与实现 内容:1.摘要 随着电动车在日常生活中的普及,将电动车带入电梯带来的安全隐患日益凸显,如引发火灾等。本研究的目的是设计并实现一种基于单片机的电梯智能识别电动车阻车系统。方法上,…...
什么是柜台债
柜台债(柜台债券业务)是指通过银行等金融机构的营业网点或电子渠道,为投资者提供债券买卖、托管、结算等服务的业务模式。它允许个人、企业及机构投资者直接参与银行间债券市场的交易,打破了以往仅限机构参与的壁垒。以下是综合多…...
.py文件和.ipynb文件的区别:完整教程
一、概述 Python开发者常用的两种文件格式.py和.ipynb各有特点,本教程将通过对比分析、代码示例和场景说明,帮助开发者全面理解二者的区别与联系。 二、核心区别对比 1. 文件格式本质 特性.ipynb文件.py文件文件类型JSON结构化文档纯文本文件存储内容…...
Python中NumPy的逻辑和比较
在数据科学和科学计算领域,NumPy是一个不可或缺的Python库。它提供了高效的多维数组对象以及丰富的数组操作函数,其中逻辑和比较操作是NumPy的核心功能之一。通过灵活运用这些操作,我们可以轻松实现数据筛选、条件判断和复杂的数据处理任务。…...
tt_Docker
快速上手 查看 Docker 服务运行状态;查看本地镜像;从 Docker Hub 拉取基础镜像, 我们此处选择 ubuntu:18.04 镜像;再次查看本地镜像;使用 ubuntu:18.04 镜像构建容器,并交互式运行容器;在容器内部执行 LS 命令;退出容器;查看本地容器实例;再次启动停止的…...
虚幻引擎5-Unreal Engine笔记之“将MyStudent变量设置为一个BP_Student的实例”这句话如何理解?
虚幻引擎5-Unreal Engine笔记之“将MyStudent变量设置为一个BP_Student的实例”这句话如何理解? code review! 文章目录 虚幻引擎5-Unreal Engine笔记之“将MyStudent变量设置为一个BP_Student的实例”这句话如何理解?理解这句话的关键点1.类(…...
compose map 源码解析
目录 TileCanvas ZoomPanRotateState ZoomPanRotate 布局,手势处理完了,就开始要计算tile了 MapState TileCanvasState telephoto的源码已经分析过了.它的封装好,扩展好,适用于各种view. 最近又看到一个用compose写的map,用不同的方式,有点意思.分析一下它的实现流程与原…...
IDEA202403 常用设置【持续更新】
文章目录 1、设置maven2、设置JDK3、菜单栏固定展示4、连接Gitee第一步、安装插件第二步、Gitee账号配置 IDEA 是程序员的编程利器,需要具备其的各种配置,提高工作效率。Java项目启动,两个关键设置:Maven 和 JDK设置。 1、设置mav…...
从零开始开发纯血鸿蒙应用之语音输入
从零开始开发纯血鸿蒙应用 〇、前言一、认识 speechRecognizer1、使用方式2、依赖权限3、结果回写 二、实现语音识别功能1、创建语音识别引擎2、设置事件监听3、启动识别4、写入音频数据5、操作控制 三、总结 〇、前言 除了从图片中识别文本外,语音输入也是一种现代…...
c++ STL常用工具的整理和思考
蓝桥杯后,我整理了这些常用的C STL工具 作为一个算法竞赛的中等生,以前总觉得STL“花里胡哨”,不如自己写数组和循环踏实。但这次蓝桥杯发现,合理用STL能省很多时间,甚至避免低级错误。下面是我总结的常用知识点和踩过…...
Go:复合数据结构
数组 定义:数组是固定长度、元素数据类型相同的序列 。元素通过索引访问,索引从 0 到数组长度减 1 。可用len函数获取元素个数 。 初始化:默认元素初始值为类型零值(数字为 0 ) 。可使用数组字面量初始化,…...
SQL 语句基础(增删改查)
文章目录 一、SQL 基础概念1. SQL 简介2. 数据库系统的层次结构 二、SQL 语句分类1. DDL(Data Definition Language 数据定义语言)1.1 CREATE1.1.1 创建数据库1.1.2 创建数据表1.1.3 创建用户 1.2 ALTER1.2.1 AlTER 添加字段名1.2.2 ALTER 修改字段名1.2…...
【蓝桥杯 CA 好串的数目】题解
题目链接 考虑令 p r e [ i ] pre[i] pre[i] 表示 [ p r e [ i ] , i ] [pre[i], i] [pre[i],i] 是连续非递减子串,这可以类似双指针 O ( n ) O(n) O(n) 预处理: std::vector<int> pre(n); for (int r 1, l 0; r < n; r) {if (s[r] ! s[…...
Oracle for Linux安装和配置(11)——Linux命令
11.1. Linux命令 Linux是目前比较常用和流行的操作系统,现在很多生产环境就会用到它。随着其功能、性能、稳定性和可靠性等方面的日渐增强和完善,加之其成本上的优势,其市场占有率逐日攀升,也得到越来越多广大用户的关注和青睐。但作为一种操作系统,其安装、配置、管理和…...
Linux基础7
一、逻辑卷管理 查看所有物理卷:pvs 查看当前系统卷组:vgs 查看所有逻辑卷:lvs 新创建系统卷组:vgcreate [参数] [volume name] url/sdb[1-2] eg:vgcreate vg_Test /dev/sdb{1,2} >…...
C#打开文件及目录脚本
如果每天开始工作前都要做一些准备工作,比如打开文件或文件夹,我们可以使用代码一键完成。 using System.Diagnostics; using System.IO;namespace OpenFile {internal class Program{static void Main(string[] args){Console.WriteLine("Hello, …...
Docker 镜像 的常用命令介绍
拉取镜像 $ docker pull imageName[:tag][:tag] tag 不写时,拉取的 是 latest 的镜像查看镜像 查看所有本地镜像 docker images or docker images -a查看完整的镜像的数字签名 docker images --digests查看完整的镜像ID docker images --no-trunc只查看所有的…...
Python数组学习之旅:数据结构的奇妙冒险
Python数组学习之旅:数据结构的奇妙冒险 第一天:初识数组的惊喜 阳光透过窗帘缝隙洒进李明的房间,照亮了他桌上摊开的笔记本和笔记本电脑。作为一名刚刚转行的金融分析师,李明已经坚持学习Python编程一个月了。他的眼睛因为昨晚熬夜编程而微微发红,但脸上却挂着期待的微…...
Vue 3 和 Vue 2 的区别及优点
Vue.js 是一个流行的 JavaScript 框架,广泛用于构建用户界面和单页应用。自 Vue 3 发布以来,很多开发者开始探索 Vue 3 相较于 Vue 2 的新特性和优势。Vue 3 引入了许多改进,优化了性能、增强了功能、提升了开发体验。本文将详细介绍 Vue 2 和…...
特殊定制版,太给力了!
今天给大家分享一款超棒的免费录屏软件,真的是录屏的好帮手! 这款软件功能可以录制 MP4、AVI、WMV 格式的标清、高清、原画视频,满足你各种需求。 云豹录屏大师 多功能录屏神器 它的界面特别简洁,上手超快,用起来很顺…...
Vue事件修饰符课堂练习
Vue事件修饰符课堂练习 题目:基于 Vue 2.0,使用事件修饰符 .stop、.prevent、.capture、.self 和 .once,为按钮绑定 click 事件,并展示每个修饰符的作用。 要求: 创建一个 Vue 实例,并绑定到一个 HT…...
Y1——ST表
知识点 ST表 只能询问,不能修改 ST表的预处理: 使用了DP的思想,设a是要求区间最值的数列,f(i,j)表示从第i个数起连续2^j个数中的最大值 状态转移方程 f [ i , j ]max( f [ i , j-1 ], f [ i 2 ^ j-1,j - 1]) 建立ST表 vo…...
Python Cookbook-5.14 给字典类型增加排名功能
任务 你需要用字典存储一些键和“分数”的映射关系。你经常需要以自然顺序(即以分数的升序)访问键和分数值,并能够根据那个顺序检查一个键的排名。对这个问题,用dict 似乎不太合适。 解决方案 我们可以使用 dict 的子类,根据需要增加或者重…...
第二十二: go与k8s、docker相关编写dockerfile
实战演示k8s部署go服务,实现滚动更新、重新创建、蓝绿部署、金丝雀发布-CSDN博客 go 编写k8s命令: 怎么在go语言中编写k8s命令 • Worktile社区 k8s中如何使用go 在K8s编程中如何使用Go-阿里云开发者社区 go build - o : -o:指定输出文件…...
Servlet、HTTP与Spring Boot Web全面解析与整合指南
目录 第一部分:HTTP协议与Servlet基础 1. HTTP协议核心知识 2. Servlet核心机制 第二部分:Spring Boot Web深度整合 1. Spring Boot Web架构 2. 创建Spring Boot Web应用 3. 控制器开发实践 4. 请求与响应处理 第三部分:高级特性与最…...
事件过滤器
1.简介 事件过滤器是指在程序分发到event事件之前进行的一次高级拦截。 2.使用步骤 给控件安装事件过滤器重写eventfilter事件 3.具体实现 3.1安装事件过滤器 代码: //给label1安装事件过滤器ui->label->installEventFilter(this); 3.2重写eventfilter…...
AI识别与雾炮联动:工地尘雾治理新途径
利用视觉分析的AI识别用于设备联动雾炮方案 背景 在建筑工地场景中,人工操作、机械作业以及环境因素常常导致局部出现大量尘雾。传统监管方式存在诸多弊端,如效率低、资源分散、监控功能单一、人力效率低等,难以完美适配现代工程需求。例如…...
Kubernetes nodeName Manual Scheduling practice (K8S节点名称绑定以及手工调度)
Manual Scheduling 在 Kubernetes 中,手动调度框架允许您将 Pod 分配到特定节点,而无需依赖默认调度器。这对于测试、调试或处理特定工作负载非常有用。您可以通过在 Pod 的规范中设置 nodeName 字段来实现手动调度。以下是一个示例: apiVe…...
Nacos注册中心
Nacos注册中心 本地环境搭建 准备挂载的文件夹 在拉取 Nacos 镜像之前,在 E:\docker 文件夹下,创建一个 /nacos 文件夹,等会运行容器时,用于将 Nacos 容器中的配置文件、持久化文件挂载出来,防止容器重启时数据丢失…...
除了 `task_type=“SEQ_CLS“`(序列分类),还有CAUSAL_LM,QUESTION_ANS
task_type="SEQ_CLS"是什么意思:QUESTION_ANS 我是qwen,不同模型是不一样的 SEQ_CLS, SEQ_2_SEQ_LM, CAUSAL_LM, TOKEN_CLS, QUESTION_ANS, FEATURE_EXTRACTION. task_type="SEQ_CLS" 通常用于自然语言处理(NLP)任务中,SEQ_CLS 是 Sequence Classif…...
二战蓝桥杯所感
🌴 前言 今天是2025年4月12日,第十六届蓝桥杯结束,作为二战的老手,心中还是颇有不甘的。一方面,今年的题目比去年简单很多,另一方面我感觉并没有把能拿的分都拿到手,这是我觉得最遗憾的地方。不…...
深度解析自动化工作流工具:n8n 与 Dify 的对比分析
深度解析自动化工作流工具:n8n 与 Dify 的对比分析 随着企业数字化转型的加速,自动化工具在提高工作效率、降低人工成本方面扮演着越来越重要的角色。市面上有多种自动化工作流工具可供选择,其中 n8n 和 Dify 是两个备受关注的开源和商业产品…...
深度剖析Python中的生成器:高效迭代的秘密武器
深度剖析Python中的生成器:高效迭代的秘密武器 在Python的编程世界里,生成器(Generator)是一个强大而又迷人的特性,它为开发者提供了一种高效处理大量数据的方式,尤其在涉及到迭代操作时,能显著…...
Mac 下载 PicGo 的踩坑指南
Mac 下载 PicGo 的踩坑指南 一、安装问题 下载地址:https://github.com/Molunerfinn/PicGo/releases 下载之后直接安装即可,此时打开会报错:Picgo.app 文件已损坏,您应该将它移到废纸篓。 这是因为 macOS 为了保护用户不受恶意…...
网页布局汇总
1. 盒模型 容器大小 内容大小 内边距(padding) 边框大小 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0">&l…...
基于 Maven 构建的 Thingsboard 3.8.1 项目结构
一、生命周期(Lifecycle) Maven 的生命周期定义了项目构建和部署的各个阶段,图中列出了标准的生命周期阶段: clean:清理项目,删除之前构建生成的临时文件和输出文件。validate:验证项目配置是否…...
MySQL 中为产品添加灵活的自定义属性(如 color/size)
方案 1:EAV 模型(最灵活但较复杂) 适合需要无限扩展自定义属性的场景 -- 产品表 CREATE TABLE products (id INT PRIMARY KEY AUTO_INCREMENT,name VARCHAR(100),price DECIMAL(10,2) );-- 属性名表 CREATE TABLE attributes (id INT PRIMA…...
C++语言程序设计——02 变量与数据类型
目录 一、变量与数据类型(一)变量的数据类型(二)变量命名规则(三)定义变量(四)变量赋值(五)查看数据类型 二、ASCII码三、进制表示与转换(一&…...
第三篇:Python数据结构深度解析与工程实践
第一章:列表与字典 1.1 列表的工程级应用 1.1.1 动态数组实现机制 Python列表底层采用动态数组结构,初始分配8个元素空间,当空间不足时按0,4,8,16,25,35...的公式扩容,每次扩容增加约12.5%的容量 通过sys模块可验证扩容过程&a…...
dcsdsds
我将为您在页面顶部添加欢迎内容,同时保持整体风格的一致性。以下是修改后的代码,主要修改了模板部分和对应的样式: vue 复制 <template><div class"main-wrapper"><!-- 新增欢迎部分 --><div class"…...
Vitis: 使用自定义IP时 Makefile错误 导致编译报错
参考文章: 【小梅哥FPGA】 Vitis开发中自定义IP的Makefile路径问题解决方案 Vitis IDE自定义IP Makefile错误(arm-xilinx-eabi-gcc.exe: error: *.c: Invalid argument)解决方法 Vitis 使用自定义IP时: Makefile 文件里的语句是需要修改的,…...