近几期的考情来看,本章选择题稳定考4分,考案例的可能性有,需要重点学习。本章节专业知识点特别多。但是,只考课本原话,大家一定要把本章至少通读一遍,还要多刷题,巩固重点知识。
1 软件工程
- 软件工程是指应用计算机科学、数学及管理科学等原理,以工程化的原则和方法来解决软件问题的工程,其目的是提高软件生产率、提高软件质量、降低软件成本。
- 电气与电子工程师协会对软件工程的定义是:将系统的、规范的、可度量的工程化方法应用于软件开发、运行和维护的全过程及上述方法的研究。
- 软件工程由方法、工具和过程三个部分组成:
- ①软件工程方法是完成软件工程项目的技术手段,它支持整个软件生命周期;
- ②软件工程使用的工具是人们在开发软件的活动中智力和体力的扩展与延伸,它自动或半自动地支持软件的开发和管理,支持各种软件文档的生成;
- ③软件工程中的过程贯穿于软件开发的各个环节,管理人员在软件工程过程中,要对软件开发的质量、进度和成本进行评估、管理和控制,包括人员组织、计划跟踪与控制、成本估算、质量保证和配置管理等。
1.1架构设计
软件架构为软件系统提供了一个结构、行为和属性的高级抽象,由构件的描述、构件的相互作用(连接件)、指导
构件集成的模式以及这些模式的约束组成。
软件架构研究的主要内容涉及软件架构描述、软件架构风格、软件架构评估和软件架构的形式化方法等。解决好
软件的复用、质量和维护问题,是研究软件架构的根本目的。
1.软件架构风格
核心问题
软件架构设计的一个核心问题是能否达到架构级的软件复用
软件架构风格是指在设计和构建软件系统时所采用的一种高层次的组织模式,它定义了系统的基本结构、组件之间的交互方式以及用于指导设计决策的约束和原则。以下是对您列举的几种主要软件架构风格的简要描述:
数据流风格
批处理序列
批处理序列风格适用于那些处理大量数据且不需要即时响应的系统。在这种风格中,数据以批量形式(如文件或数据集)作为输入,系统按照预定义的顺序对这些数据进行一系列离散的处理步骤。每个步骤通常作为一个独立的任务运行,处理完一批数据后才开始处理下一批。批处理系统的特点是效率高,适合大规模数据处理,但其响应时间取决于整个处理链的长度。
管道/过滤器
管道/过滤器风格由一系列相互独立的处理单元(过滤器)组成,这些单元通过预先定义的接口(管道)连接在一起。数据以流的形式从一个过滤器的输出传递到下一个过滤器的输入,依次经过各个过滤器的处理。每个过滤器专注于执行特定的数据转换或分析任务。这种风格支持模块化、并行处理以及动态重组,非常适合需要灵活处理数据流和实时数据处理的场景。
调用/返回风格
主程序/子程序
主程序/子程序风格是早期程序设计中的经典结构,主程序负责控制流程,通过调用子程序来执行特定任务,子程序完成后返回控制权给主程序。这种风格强调功能划分和程序结构的清晰性。
数据抽象和面向对象
数据抽象风格通过定义抽象数据类型(ADT)来隐藏数据的具体实现细节,仅暴露操作接口供外部使用,从而提高系统的封装性和模块化程度。面向对象风格进一步扩展了这一思想,引入了类、对象、继承、封装、多态等概念,以对象为中心组织系统,通过消息传递实现对象间的交互。
层次结构
层次结构风格将系统划分为若干层次,每一层提供特定的服务给上一层,同时依赖于下一层提供的服务。这种风格有助于降低复杂性,实现模块化和职责分离,常见于操作系统、网络协议栈和企业应用架构中。
独立构件风格
进程通信
进程通信风格中,系统由多个并发执行的进程构成,这些进程通过明确的通信机制(如消息传递、共享内存、远程过程调用等)协作完成任务。这种风格支持高度并发和分布式计算,适用于需要并行处理和资源共享的复杂系统。
事件驱动的系统
事件驱动风格以事件为核心,系统组件(如对象、模块)对特定事件做出响应。事件源发出事件,事件处理器接收到事件后执行相应的处理逻辑。这种风格常用于图形用户界面(GUI)开发、实时系统、物联网(IoT)应用和消息中间件中,能够有效应对异步、非阻塞的操作需求。
虚拟机风格
解释器
解释器风格的系统包含一个解释引擎,该引擎接受某种高级语言(或脚本语言)编写的程序作为输入,并在运行时逐句解释执行。这种风格提供了灵活性和跨平台能力,但通常比编译型系统运行效率略低。
基于规则的系统
基于规则的系统(如专家系统)包含一个规则库,其中存储了一系列条件-动作规则。系统根据当前的事实状态,通过推理引擎匹配并触发满足条件的规则,执行相应的动作。这种风格适用于需要进行复杂逻辑判断和决策支持的应用领域。
仓库风格
数据库系统
数据库系统是专门用于存储、管理和检索数据的软件系统,提供了结构化的数据存储、查询优化、事务处理等功能。数据库作为中央数据仓库,为各种应用程序提供统一的数据访问接口。
黑板系统
黑板系统是一种知识密集型的架构风格,用于解决复杂问题求解。系统由知识源、黑板(共享数据结构)、控制组件组成。知识源根据黑板上的数据状态提出解决方案片段(即假设),控制组件协调知识源的活动,选择合适的假设进行验证或应用。黑板系统适用于需要整合多种知识源、处理不确定性和模糊信息的问题领域。
超文本系统
超文本系统是一种非线性的信息组织和导航风格,通过超链接将不同信息节点(如文档、图片、视频等)关联起来。典型的例子是万维网(WWW),用户可以通过点击链接在不同资源之间自由跳转。这种风格极大地丰富了信息的表达和获取方式,促进了信息的互联与共享。
2.软件架构评估
软件架构评估可以只针对一个架构,也可以针对一组架构,在架构评估过程中,评估人员所关注的是系统的质量属性
评估方式分类通常是指在不同领域或针对不同对象进行评估时所采用的不同方法论和策略。这里提到的分类聚焦于软件架构评估,主要包括以下三类:
基于调查问卷的评估方式
基于调查问卷的评估方式通过设计一套针对性的问卷或检查表,邀请系统相关人员(如开发人员、架构师、项目经理、利益相关者等)对软件架构的各个方面进行评价。问卷可能涵盖架构的各个关键特性、设计决策、遵循的原则、存在的风险、对业务需求的满足程度等方面。参与者根据自身经验和对架构的理解,填写问卷或检查表,提供对架构质量、成熟度、可维护性、可扩展性等属性的主观评价。这类评估方式能够系统地收集多方意见,便于综合分析架构的优点与不足,为后续改进提供依据。
基于场景的评估方式
基于场景的评估方式通常包括但不限于以下几种具体方法:
架构权衡分析法(Architecture Tradeoff Analysis Method, ATAM)
ATAM是一种结构化的方法,旨在理解软件架构如何支持系统的关键质量属性(QAs),以及在面临权衡时如何作出决策。它通过识别系统的重要使用场景(用例),分析这些场景如何影响QAs,并探讨架构决策如何在满足QAs之间达成平衡。ATAM过程中会进行架构评审会议,邀请所有利益相关者参与讨论,确保各方对架构的期望和权衡取舍有共同理解。
软件架构分析法(Software Architecture Analysis Method, SAAM)
SAAM是一种定性与定量相结合的评估方法,它侧重于通过模型化和模拟来量化评估架构对QAs的支持情况。这种方法通常包括建立架构模型、识别关键QAs、定义度量指标、执行模拟实验以及分析结果,以确定架构在特定场景下的性能、可靠性、安全性等属性的表现。
成本效益分析法
虽然成本效益分析法在软件架构评估中并不直接表现为一种基于场景的方法,但它可以通过评估架构决策对项目成本(包括开发成本、维护成本、迁移成本等)和预期效益(如提高生产力、减少故障时间、增加用户满意度等)的影响,间接反映架构在特定业务场景下的经济合理性。在某些情况下,成本效益分析可以与上述基于场景的评估方法结合使用,以全面评估架构的经济价值。
基于度量的评估方式
基于度量的评估方式侧重于使用量化指标来评价软件架构的属性和性能。这包括:
- 度量体系的建立:定义一套与架构相关的度量指标,如模块耦合度、代码复用率、接口复杂度、系统响应时间、资源利用率等,这些度量应与架构设计目标和质量属性紧密相关。
- 数据收集:通过工具自动化或手动方式收集度量数据,可能涉及源代码分析、性能测试、日志分析、用户反馈等多种数据来源。
- 数据分析与解释:对收集到的度量数据进行统计分析,计算平均值、标准差、趋势等统计量,识别异常值和模式,将度量结果与预先设定的标准或行业基准进行对比,以评估架构的健康状况、性能瓶颈、潜在风险等。
- 持续监控与改进:基于度量结果制定架构优化策略,实施改进措施,并持续跟踪度量变化,形成闭环反馈,推动架构的持续演化。
基于度量的评估方式强调客观、定量的证据,有助于提供更具说服力的评估结果,特别是在进行技术决策、性能优化、风险管理时具有重要价值。
1.2需求分析
需求的层次
- 业务需求:反映了组织或企业的战略目标和业务流程需求,是驱动软件项目立项的根本原因。
- 用户需求:从最终用户的角度出发,描述用户期望系统具备的功能、性能、易用性等特性,以满足其工作或生活中的具体任务需求。
- 系统需求:基于业务需求和用户需求,对软件系统应具有的功能、性能、接口、安全、兼容性、可维护性等进行全面、具体、规范的表述,是软件设计和实现的基础。
- **质量功能部署(QFD)**是一种将用户需求转化为软件需求的技术,旨在最大化提升用户满意度。QFD将软件需求分为:
- 常规需求:用户普遍期待并认为系统应该具备的基本功能和特性。
- 期望需求:用户希望系统拥有的、能显著提升使用体验或工作效率的额外功能或特性。
- 意外需求(或称为兴奋型需求):超出用户预期、能带给用户惊喜的高端功能或特性。
需求过程
需求获取:通过与项目干系人(尤其是用户)的有效沟通与合作,识别、理解和记录他们的需求与约束。常用方法包括用户访谈、问卷调查、采样、情节串联板(Storyboarding)、联合需求计划会议(JRP)等。
需求分析:将收集到的杂乱、零散的需求整理、提炼、规范化,转化为明确、一致、完整的需求规格。需求分析的关键在于深入理解问题域,建立准确的需求模型。
结构化分析:一种基于数据驱动的需求分析方法,核心是构建数据字典。构建三个层次的模型:
- 数据模型:描述系统所需处理的数据及其关系。
- 功能模型:展示系统应提供的功能及其逻辑关系。
- 行为模型(状态模型):刻画系统状态变迁及状态变迁触发的事件或动作。
面向对象的分析:利用面向对象的思维和建模技术进行需求分析。
- 用例模型:通过用例(Use Case)来描述系统对外提供的服务和用户与系统的交互过程,是系统功能需求的主要表达方式。
- 分析模型:包含静态模型(展现对象和类的结构,如类图、包图等)和动态模型(描述对象间的消息传递、协作行为,如序列图、协作图等),共同描绘系统的逻辑结构和行为特征。
需求规格说明书编制
**软件需求规格说明书(SRS)**是需求开发活动的重要输出,是软件生命周期中至关重要的文档之一,无论项目的规模大小或复杂程度,都应编制SRS以确保需求的清晰性和一致性。
SRS通常应包含以下主要内容:
- 范围:明确界定系统的边界,描述系统应做什么和不应做什么,以及与其他系统或组件的接口。
- 引用文件:列出所有与SRS内容相关的外部文档或标准,如业务规则、行业规范等。
- 需求:详细阐述系统功能需求、非功能需求(性能、安全性、可靠性等)、界面需求、数据需求等,可以采用自然语言描述、图表、用例等多种形式。
- 合格性规定:定义衡量系统需求是否满足的标准,包括性能指标、错误率、响应时间等具体量化要求。
- 需求可追踪性:建立需求之间的关联性,确保每个需求都可以追溯到其来源(如用户故事、业务需求),也可以追踪到设计、编码、测试等后续开发活动。
- 尚未解决的问题:记录在编制SRS过程中未确定或待讨论的需求项、疑问点或风险。
- 注解:对某些需求或条款进行解释、补充说明,以消除歧义或提供背景信息。
- 附录:包含支持性材料,如数据字典、词汇表、算法描述、示例场景等。
需求验证与确认
- 需求评审:是对SRS进行技术审查的过程,旨在识别并消除需求中的模糊性、不一致性、遗漏和错误。评审过程通常由多角色参与,包括开发人员、测试人员、项目经理、业务专家等,通过集体讨论、提问、建议改进等方式达成需求共识。
- 需求测试:在业务需求基本明确、用户需求部分确定的情况下,同步进行需求测试以尽早发现问题。需求测试可能包括静态检查、模型验证、原型验证、场景模拟等手段,旨在检验需求的可行性和有效性,确保需求在特定环境下能够被正确实现。相较于仅依赖阅读SRS,需求测试更直观地揭示系统在实际应用中的行为,能够在需求开发阶段以较低成本修正问题,避免后期设计与实现阶段产生高昂的变更成本。
UML(Unified Modeling Language,统一建模语言)
定义与特性:UML是一种定义良好、易于表达、功能强大且普遍适用于软件系统的建模语言。它提供了一套标准化的图形符号、规则和公共机制,使得不同角色的项目成员能够以可视化的方式交流复杂的软件设计思想和结构。
结构组成:
构造块:UML的核心组成部分,包括三个方面:
- 事物(Thing):代表模型中的基本元素,如类、接口、组件、用例、状态、活动等,它们分别对应软件系统中的不同概念或实体。
- 关系(Relationship):描述事物之间的联系或依赖,如关联、泛化、依赖、实现、组合、聚合等,这些关系明确了模型元素之间的交互、继承、依赖关系以及结构组成。
- 图(Diagram):是多个相互关联的事物的集合,每种图类型专注于展现系统某一方面的视角或特征,如类图展示类与类之间的结构关系,序列图展示对象间的交互序列,状态图描述对象状态变迁等。通过组合使用不同的图,可以全面、立体地展现软件系统的静态结构、动态行为以及它们之间的相互作用。
规则:规定了如何正确、一致地使用UML构造块来构建模型,包括但不限于:
- 命名规则:为构造块(如类名、属性名、操作名、关系名等)指定有意义且符合约定的标识符。
- 范围与可见性规则:定义模型元素的作用域及其对其他元素的可见性(如公有、私有、受保护等)。
- 完整性规则:确保模型元素之间的关系在逻辑上一致,没有冲突或遗漏。
- 执行规则:解释模型元素在运行时的行为或含义,特别是在动态图(如活动图、时序图)中描述系统执行过程。
公共机制:提供了一系列通用的方法和工具,以支持更精确、灵活的建模:
- 规格说明(详细说明):对模型元素的语义进行详细描述,包括其属性、操作、约束条件等,是模型真实意图的核心体现。
- 修饰:通过附加标记、注释、 stereotype(构造型)等手段,为模型元素添加额外的信息或细化其语义,增强模型的表达力。
- 公共分类(通用划分):如类与对象(类描述概念,对象是类的实例)、接口与实现(接口定义契约,实现提供具体功能)等,帮助对模型元素进行分类和组织。
- 扩展机制:包括约束(定义额外的规则或修改现有规则)、构造型(扩展UML词汇,创建新的模型元素类型)和标记值(扩展模型元素特性,携带特殊信息),允许用户根据特定领域或项目需求定制化UML模型。
UML关系
依赖(Dependency)
- 定义:依赖关系表示两个事物(通常是类、接口或组件)之间的一种语义关联。当一个事物(称为依赖者)的变化会影响到另一个事物(称为供应商)的语义时,就存在依赖关系。这种影响通常体现在依赖者使用了供应商提供的某些服务(如方法调用、属性访问、消息传递等),或者依赖者的实现依赖于供应商的定义或状态。
- 图形表示:依赖关系通常用带箭头的虚线表示,箭头指向供应商,表明依赖的方向。
关联(Association)
- 定义:关联关系描述了一组对象之间持久的结构关系,表示它们之间存在某种联系或交互。关联可以是有方向的(单向关联)或无方向的(双向关联),也可以是具有多重性的(如一对一、一对多、多对多)。
- 图形表示:关联关系通常用实线表示,线两端标注关联端的角色名称(如果有)和多重性(如“1”、“”、“0…”等)。如果关联有方向,箭头指向被拥有端或主动方。
泛化(Generalization)
- 定义:泛化关系是一种继承关系,表示类之间的“is-a-kind-of”或“is-subtype-of”关系。子类(或特殊化类)继承父类(或一般化类)的属性、操作和关联,同时可以添加自己的属性、操作或覆盖父类的行为。泛化关系体现了软件设计中的复用原则和抽象层次。
- 图形表示:泛化关系用带空心箭头的实线表示,箭头从子类指向父类。
实现(Realization)
- 定义:实现关系是类与接口之间的语义关系,表示一个类(称为实现者)承诺提供接口(称为合同)所定义的一组操作和属性。实现关系确保类实现了接口的所有抽象功能,使得接口可以在多个类之间共享,实现多态和解耦设计。
- 图形表示:实现关系用带空心箭头的虚线表示,箭头从实现类指向接口。
1.3软件设计♥♥♥
结构化设计 (SD)
方法论:结构化设计是一种基于数据流的软件设计方法,以软件需求规格说明书(SRS)和结构化分析(SA)阶段产生的数据流图(DFD)和数据字典等文档为基础,遵循自顶向下、逐步求精和模块化的设计原则。
基本原则:强调高内聚、低耦合。高内聚意味着模块内部各组成部分紧密相关,共同完成一个明确的功能;低耦合则要求模块间相互独立,减少不必要的相互影响,便于模块的独立开发、测试和维护。
面向对象设计 (OOD)
基本思想:继承自面向对象分析(OOA),核心理念包括抽象、封装和可扩展性,更贴近现实世界的思维方式,使软件设计更自然、直观。
常用设计原则:
- 单一职责原则 (SRP):一个类只负责一个功能领域,与结构化设计的高内聚原则相呼应。
- 开闭原则 (OCP):软件实体(如类、模块、函数等)应对扩展开放,对修改关闭,即允许在不修改原有代码的基础上增加新功能。
- 里氏替换原则 (LSP):子类对象可以透明地替换其父类对象,且不会影响程序的正确性。
- 依赖倒置原则 (DIP):高层模块不应该依赖底层模块,二者都应该依赖于抽象;具体实现应依赖于抽象接口,而非具体类。
- 接口隔离原则 (ISP):多个专用的接口优于一个通用的大接口,以降低客户端对不需要的方法的依赖。
- 组合/聚合复用原则 (CARP):优先使用对象组合而非类继承来达到复用目的,因为组合能更灵活地改变对象间的结构关系。
- 迪米特法则 (LoD),又称最少知识原则:一个对象应尽量减少与其他对象的交互,只与直接的朋友(即与之紧密相关的对象)通信,与结构化设计的低耦合原则一致。
设计模式
分类:设计模式按关注的对象关系分为两大类:
- 类模式:关注类和子类之间的关系,这些关系通过继承建立,设计决策在编译时确定,具有静态性。例如工厂方法模式、模板方法模式、代理模式等。
- 对象模式:关注对象之间的关系,这些关系在运行时动态变化,更具动态性。例如观察者模式、迭代器模式、策略模式、状态模式等。
1.4软件实现
软件配置管理
目标与作用:软件配置管理通过标识产品的组成元素、管理和控制变更、验证变更、记录变更信息以及报告配置状态,来控制软件产品的完整性和演进过程。它与软件质量保证活动紧密相关,有助于实现软件质量保证的目标,如确保软件产品的正确性、一致性、完整性及可追溯性。
主要活动:
- 软件配置管理计划:制定管理策略、规程、角色分工、工具选择、变更流程等,为配置管理工作提供指导。
- 软件配置标识:识别构成软件配置项的元素,为其分配唯一标识,并定义其版本号规则。
- 软件配置控制:对配置项的变更进行审批、跟踪、合并及回滚,确保变更的有序进行。
- 软件配置状态记录:维护配置项及其变更的历史记录,包括版本、变更理由、责任人、变更日期等信息。
- 软件配置审计:定期或不定期检查配置项及其管理过程的合规性,确保配置信息的准确性。
- 软件发布管理与交付:管理软件版本的打包、测试、批准发布及向用户或环境部署的过程。
软件编码
定义:编码是将软件设计成果转化为计算机可执行的程序,使用选定的程序设计语言编写源代码。
影响程序质量的因素:
程序设计语言:选择合适的编程语言是编码前的关键任务,它直接影响到代码的可读性、可维护性、性能及与目标环境的兼容性。
程序设计风格:良好的编程风格有助于提高代码可读性,从而提升整体质量。这包括:
- 源程序文档化:注释、文档字符串、API文档等,清晰阐述代码意图、功能和使用方法。
- 数据说明:合理命名变量、清晰定义数据结构和数据类型,确保数据含义明确。
- 语句结构:使用简洁、一致的语法结构,避免冗余和复杂嵌套。
- 输入/输出方法:清晰定义输入参数、返回值及错误处理,确保接口易于理解和使用。
程序复杂性度量:通过定量方法(如圈复杂度、Halstead复杂度等)度量程序结构,比较不同设计方案或算法的优劣,为模块规模设定合理的限制,防止过度复杂导致的维护困难。
编码效率:关注程序的多个方面效率,包括:
- 程序效率:代码执行速度,避免不必要的计算或循环,优化算法。
- 算法效率:选择或设计高效算法,降低时间复杂度或空间复杂度。
- 存储效率:合理使用数据结构和数据压缩技术,减少内存占用。
- I/O效率:优化数据读写、网络通信、文件操作等,减少系统资源消耗。
软件测试
目的:软件测试旨在验证软件产品是否符合软件开发合同、项目计划、系统/子系统设计文档、软件需求规格说明书(SRS)、软件设计说明和软件产品说明等规定的各项质量要求。通过测试发现并报告软件缺陷,为评估软件产品质量、决定其是否可接受提供依据。
测试方法分类:
静态测试:在不运行程序的情况下,通过人工检查和计算机辅助静态分析手段对软件进行测试。静态测试包括:
- 文档测试:以检查单等形式审查需求文档、设计文档、用户手册等非代码文档的完整性和一致性。
- 代码测试:通过以下方式进行:
- 桌前检查(Desk Checking):程序员个人对编写代码进行自我审查。
- 代码走查(Walkthrough):开发人员向同行或团队讲解代码,接受提问和建议。
- 代码审查(Code Review):正式的小组会议,对代码进行深度检查和讨论,查找潜在问题和改进点。
动态测试:在实际运行环境中执行程序进行测试,主要采用以下方法:
- 白盒测试(结构测试):测试人员了解程序内部结构和算法,依据控制流、数据流、程序逻辑等设计测试用例。白盒测试方法包括:
- 控制流测试:基于程序控制结构(如循环、条件分支、函数调用等)设计测试用例。
- 数据流测试:关注程序中数据的来源、流动路径和使用情况,检查数据处理的正确性。
- 程序变异测试:通过引入微小变化(变异)来测试代码对变化的敏感性和健壮性。
- 静态分析工具辅助的白盒测试:使用静态代码分析工具检测代码逻辑错误、数据流异常、不符合编程规范等问题,作为白盒测试的补充。
黑盒测试(功能测试):测试人员不了解或不考虑程序内部结构,仅依据SRS规定的功能规格设计测试用例。黑盒测试适用于集成测试、确认测试和系统测试阶段,旨在验证软件是否按预期功能正常工作。
1.5部署交付♥♥♥♥
软件部署与交付
定位:软件部署与交付是软件开发生命周期的后期阶段,涉及软件制品的配置、安装、激活等操作,确保其在目标环境中正常运行。
配置的重要性与挑战:软件配置过程对部署结果的正确性至关重要,同时也是部署过程中主要的错误源头。配置不当可能导致软件无法启动、功能缺失、性能下降等问题。
常见困境:
- 分支冗余与合并困难:过多的开发分支导致代码合并复杂度增加,可能引发冲突和遗漏。
- 缺陷阻塞测试:软件中存在的大量未修复缺陷阻碍测试进度,影响部署准备。
- 环境不统一引发未知错误:开发、测试、部署环境差异可能导致问题在某一环境中未被发现,而在其他环境中暴露。
- 版本混乱与回溯困难:代码提交版本管理不规范,导致无法准确追踪问题源头,影响问题修复和回滚操作。
- 上线周期长:从开发完成到实际部署到生产环境的时间过长,影响业务响应速度。
- 部署操作复杂且失败率高:部署过程复杂繁琐,易因人为错误导致部署失败。
- 上线后问题紧急回滚:新版本上线后立即出现严重问题,需迅速回滚至先前稳定版本。
- 架构设计不合理导致问题定位困难:架构设计不合理或缺乏足够的监控、日志机制,使得发生问题后难以精准定位和修复。
- 部署与交付最佳实践:介绍标准化的部署流程、工具选择、环境一致性管理等策略。
- 配置管理与自动化:研究如何通过自动化工具和标准化配置模板减少配置错误,提高部署成功率。
- 分支管理与代码合并策略:探讨有效的分支管理模式和合并策略,减少合并冲突,确保代码质量。
- 缺陷管理与测试集成:提倡尽早引入测试,实行持续集成,及时发现并修复缺陷。
- 环境一致性与持续部署:论述开发与运维环境统一的重要性,以及如何通过持续部署实现环境的快速同步。
- 版本控制与回滚机制:介绍版本控制系统在软件部署中的应用,以及如何设计有效的回滚策略。
- 架构设计与监控:探讨如何通过合理的架构设计和完善的监控体系提高问题定位与解决效率。
持续交付
定义与目标:持续交付是一种软件开发实践方法,旨在确保代码能够快速、安全地部署到生产环境中,整个过程高度自动化,一旦业务开发完成,即可一键部署。
相对于传统流程的优势:
- 需求阶段:摒弃传统的冗长需求文档,采用更易于开发人员理解的用户故事(User Story)来表述需求,促进开发团队与业务团队的有效沟通。
- 开发测试阶段:推行持续集成(Continuous Integration, CI),鼓励开发人员频繁提交代码并自动运行构建和测试,使测试人员能够尽早介入,及时发现并修复问题。
- 运维阶段:打破开发与运维之间的壁垒,实现DevOps文化,确保开发环境与运维环境的一致性,简化部署流程,提高部署频率和稳定性。
- 缩短部署周期:通过自动化构建、测试、部署流程,显著减少从代码提交到正式部署上线的时间,提升了软件交付的敏捷性,使组织能够更快地响应市场需求和用户反馈。
- 降低部署风险:通过持续集成、自动化测试和预发布验证,能在早期发现并解决问题,避免缺陷积累到生产环境。同时,由于部署过程高度自动化且经过多次验证,降低了手动操作错误和环境不一致带来的风险。
- 随时可部署状态:确保软件在开发过程中的任何时刻都能顺利部署到生产环境,这意味着软件始终处于可发布的状态,增强了对业务需求快速响应的能力。
- 简化部署步骤与版本清晰:通过标准化和自动化部署流程,减少了复杂的人工操作,使部署过程变得简单、高效。同时,清晰的版本管理和自动化流水线使得软件版本轨迹清晰可追溯,便于团队理解和管理软件演化过程。
- 过程可预期、可视化与可靠性:持续交付将软件交付过程转化为一种可预测、可视化的工作流,团队成员能够清晰地看到代码从提交到部署的全过程。这种透明性增强了团队对交付进度的掌控力,也提高了交付过程的可靠性,使得交付不再是神秘的“黑箱”操作。
在评价互联网公司软件交付能力时,常用的两个关键指标是:
- 部署前置时间(Lead Time):这是核心指标之一,指从代码提交到最终部署到生产环境所需的时间。仅涉及一行代码的改动所需的时间也能反映组织快速响应和部署变更的能力。理想的部署前置时间应尽可能短,因为它直接影响到产品迭代速度和市场竞争力。
- 部署一致性与可重复性:考察开发团队是否能以一种标准化、可重复、可靠的方式执行软件交付。这意味着团队应具备稳定的部署流程、一致的环境配置、健全的自动化测试和监控机制,确保每次部署的质量和结果可预期。高一致性和可重复性的交付能力是实现持续交付目标的关键,也是衡量DevOps成熟度的重要标志。
- 持续部署
重要性:持续部署是持续交付流程中的关键环节,其目标是在代码通过自动化测试后,自动将其部署到生产环境,实现软件更新的无缝、快速、风险可控的发布。
持续部署方案:
- 容器技术:当前最流行的部署技术之一,尤其在云计算和微服务架构中广泛应用。容器技术如Docker提供了轻量级、标准化、可移植的运行时环境,有利于实现一致的部署体验和高效的资源利用。
- Kubernetes(K8s):作为主流的容器编排平台,Kubernetes为大规模容器应用的部署、管理和扩展提供了强大的支持。Kubernetes通过声明式API、自动伸缩、故障恢复、服务发现等功能,极大地简化了持续部署过程,确保了服务的高可用性和弹性。
- Matrix系统:此处可能指的是Jenkins Matrix Project(矩阵项目),它允许在单个工作流中并行执行多个相似的构建任务,适用于多环境、多配置的部署场景。尽管Matrix系统本身并非持续部署方案,但在结合Docker等技术时,可以作为持续部署流程的一部分,实现对不同环境、不同版本的自动化部署。
部署原则:
- 部署包来自统一存储库:所有部署所需的软件包、配置文件、脚本等应存储在集中、版本化的存储库(如Git仓库、Artifactory等)中,确保部署过程使用的都是经过验证的最新或特定版本的资源。
- 所有环境使用相同部署方式:无论是开发、测试、预生产还是生产环境,均应遵循统一的部署流程和工具链,确保任何环境下的部署行为一致,降低环境差异引发的问题。
- 所有环境使用相同部署脚本:部署脚本(如Ansible Playbook、CloudFormation模板、Helm Chart等)应通用化,能够在不同环境中复用,避免为每个环境单独编写和维护部署脚本,确保部署过程的标准化和一致性。
部署层次
- 目的:部署的目标不仅是安装一个可工作的软件,更重要的是构建一个能够稳定、正常运行的环境。这个环境不仅包含软件本身,还应包括必要的依赖项、配置、基础设施等。
Build-Ship-Run模型:
- Build:将软件源代码编译、打包成可分发的格式,如RPM包(适用于Linux系统)或JAR包(适用于Java应用),这些包包含了软件运行所需的二进制文件、类库、资源文件等。
- Ship:将构建好的软件包以及第三方依赖库、插件等组件,通过适当的渠道(如网络分发、本地复制等)安装到目标环境中。这一步可能还包括配置管理、权限设置、依赖关系解决等工作。
- Run:在目标环境中启动和运行软件系统,包括服务注册、依赖服务启动、应用初始化、健康检查等步骤。确保软件在不同的运行环境(如开发环境、测试环境、生产环境)中都能正确启动和运行。
不可变服务器
- 定义:不可变服务器是一种部署策略,其中服务器实例一旦创建并配置完毕,其状态就被视为固定不变。除了定期的安全更新和必要的补丁安装之外,不再对服务器进行任何直接修改。
- 特点:任何对服务器的变更(如应用升级、配置调整、环境修复等)都通过创建新的服务器实例来实现,而不是在现有实例上进行修改。旧实例在新实例验证无误后被替换或退役,始终保持环境的一致性和可复现性。
- 优势:简化运维、提高故障恢复速度、易于横向扩展、增强安全性(通过避免直接对生产环境进行修改降低出错风险),以及有利于实现持续部署和自动化运维。
蓝绿部署与金丝雀部署
蓝绿部署:
- 原理:同时准备两套完全相同的生产环境(蓝色环境和绿色环境),其中一个(如蓝色环境)承载当前线上运行的版本,另一个(如绿色环境)部署新版本。通过DNS或负载均衡器将用户流量切换到新版本(绿色环境),旧版本(蓝色环境)保持运行但不接收新请求。若新版本出现问题,可迅速将流量回切到旧版本,确保服务连续性。
- 优点:风险较低,回滚快速,对用户影响较小,适用于大规模、高风险的版本更新。
金丝雀部署:
- 原理:新版本首先部署到一小部分(如1%~10%)的真实用户群体(称为“金丝雀用户”),观察新版本在实际生产环境中的表现。如果新版本表现良好,逐渐扩大部署范围直至全量用户;反之,若发现问题,及时回滚并修复新版本。
- 优点:能够及时发现并控制新版本潜在问题的影响范围,通过逐步推广降低风险,适用于对用户影响敏感、需逐步验证新版本稳定性的场景。
1.6过程管理
成熟度模型
CSMM软件过程能力成熟度模型:该模型旨在通过提升组织的软件开发能力,助力客户提升软件产品的业务价值。它融合了软件工程、项目管理、产品管理、组织治理、质量管理、卓越绩效管理以及精益软件开发等多个领域的最佳实践,为组织提供了一个用于改进和评估其软件过程能力的成熟度框架。
模型结构:CSMM模型由四个能力域、二十个能力子域以及一百六十一项能力要求构成。这种层次化的结构旨在全面覆盖软件开发过程中的关键活动、角色、职责、流程、工具和技术等要素,为组织提供详细的指导和评估标准。
能力域:能力域是模型中的顶层分类,代表软件过程能力的不同核心方面。具体包括:
- 治理:涵盖战略规划、决策制定、资源分配、风险管理等方面的组织层面管理活动。
- 过程:涉及软件开发生命周期中的具体过程,如需求管理、设计、编码、测试、部署、维护等。
- 组织:关注组织结构、团队建设、人才培养、知识管理等组织内部因素对软件过程能力的影响。
- 技术:涵盖软件开发、运维所使用的工具、平台、框架、标准等技术基础设施,以及技术选型、技术更新、技术债务管理等技术管理活动。
能力子域:每个能力域下进一步细分为多个能力子域,这些子域更加具体地描述了在某个能力域中需要关注的特定方面。例如,过程能力域可能包含需求工程、架构设计、编码规范、测试策略等子域。
能力要求:作为模型的最底层元素,能力要求是对组织在每个能力子域中应达到的具体标准或应执行的具体活动的详细描述。这些要求通常包括具体的实践、准则、指标或成果物,用于指导组织如何实施改进并衡量其在该子域的成熟度水平。