模块一:软件开发模型与方法论
核心:区分不同模型的特点和适用场景。
模块二:需求分析与系统设计
需求分析:
需求分类:功能需求(做什么)、性能需求(做到什么程度)、非功能需求(安全性、可靠性等)数据需求。
分析工具:
数据流图(DFD):描述数据在系统中的流动和处理。元素:外部实体、加工、数据存储、数据流。
数据字典(DD):定义DFD中所有元素的详细说明。
实体-关系图(ER图):用于数据建模。(与数据库设计直接相关)
系统设计:
阶段:概要设计(架构设计、模块划分)、详细设计(模块内部算法与数据结构)。
设计原则:高内聚、低耦合。
设计工具:结构图(SC图),用于描述软件的模块结构及调用关系。
模块三:软件测试与维护
核心:测试的分类、阶段、方法及维护类型。
测试阶段(按执行顺序和主体分):
测试方法:
黑盒测试:不关注内部结构,只检查功能。方法:等价类划分、边界值分析(最常用)、错误推测法。
白盒测试:关注内部逻辑结构。方法:逻辑覆盖(语句覆盖、判定覆盖、条件覆盖、路径覆盖等)。
系统测试内容非常广泛,主要可以归纳为以下几个核心类别:
一、功能性测试
这是系统测试的基石,验证软件是否实现了需求规格说明书中规定的所有功能。
示例:
用户注册、登录功能是否正常?
电商系统的下单、支付、退货流程是否完整畅通?
搜索功能返回的结果是否准确?
所有按钮、链接、表单提交是否按预期工作?
二、非功能性测试(质量属性测试)
这部分关注软件在“多好”的层面上运行,而非“能不能”运行。它决定了用户体验和系统可持续性。
- 性能测试:
负载测试:在正常和高峰预期用户负载下,系统表现如何?(如:1000人同时购物)
压力测试:超出极限负载时,系统何时会崩溃?如何崩溃?(如:5000人瞬间抢购)
稳定性/耐力测试:长时间(如24小时)运行,系统是否稳定,有无内存泄漏?
并发测试:多个用户同时操作同一功能或数据时,系统是否正确处理。 - 可用性测试:
用户界面是否直观、易用、美观?
导航是否清晰?用户能否在没有帮助的情况下完成任务?
是否符合目标用户的操作习惯? - 兼容性测试:
跨浏览器测试:在Chrome, Firefox, Safari, Edge等主流浏览器上是否表现一致?
跨平台/设备测试:在Windows, macOS, iOS, Android等不同操作系统或手机、平板、电脑上是否正常?
分辨率/屏幕适配测试。 - 安全性测试:
是否存在SQL注入、跨站脚本(XSS)等常见漏洞?
用户认证和授权机制是否牢固?(如普通用户能否访问管理员页面?)
敏感数据(如密码、银行卡号)是否加密传输和存储? - 可靠性测试:
系统在指定条件和时间内,无故障运行的能力如何?
发生故障后,能否优雅地恢复或提示?
三、其他专项测试
安装/卸载测试:软件的安装过程是否顺畅?安装后能否正常运行?卸载是否彻底?
文档测试:用户手册、帮助文档、在线提示等内容是否准确,且与软件实际功能一致?
备份与恢复测试:系统提供的备份和灾难恢复机制是否有效。
本地化/国际化测试:针对不同语言、地区(如日期、货币格式)的版本是否适配正确。
特别的,路径测试其实是白盒测试的一种经典技术,属于代码级测试。它关注的是程序内部逻辑路径的覆盖情况,比如判断分支的组合。这和系统测试的黑盒视角有本质区别——系统测试是把软件当整体,不关心内部路径,只关心输入输出是否符合需求。
软件维护:
改正性维护:修复发现的错误(约20%)。
适应性维护:使软件适应变化的环境(硬件、OS等)(约25%)。
完善性维护:扩充功能、改善性能(约50%)。
预防性维护:为未来改进打基础(约5%)。
模块四:项目管理与质量保证
软件度量 - McCabe环路复杂度:
公式:V(G) = m - n + 2。其中 m 是程序图的有向边数,n 是节点数。
意义:衡量程序逻辑复杂性,数值越高越复杂,可测试路径越多。(每年几乎必考1题计算)
质量模型:
ISO/IEC 9126 软件质量特性:6大特性(功能性、可靠性、易用性、效率、可维护性、可移植性)。
过程改进模型:
CMM/CMMI能力成熟度模型:5个等级。1-初始级,2-已管理级,3-已定义级,4-量化管理级,5-优化级。
重要知识点清单
McCabe环路复杂度的计算。
四种软件维护类型的定义与识别。
各测试阶段的执行者和依据文档(表格对比)。
瀑布模型 vs. 敏捷开发的特点对比。
黑盒测试 vs. 白盒测试的代表性方法。
软件设计原则:高内聚、低耦合。
CMMI的5个成熟度等级名称。
首先,理解两种模式:
无主程序员小组(民主式小组):所有成员之间相互平等,每个成员都可以与其他成员沟通。所以对于n个成员,沟通路径数是组合数C(n,2)= n*(n-1)/2,因为每两人之间有一条沟通路径。
主程序员负责制小组:有一个主程序员和若干成员,成员之间没有沟通,只能与主程序员沟通。所以沟通路径是主程序员与每个成员之间的路径,即如果有1个主程序员和m个成员,总人数n = 1+m,那么沟通路径数就是m(因为每个成员与主程序员有一条路径),或者说是n-1。

中间件的技术定义和核心作用
在计算机系统中,中间件是位于操作系统和具体应用程序之间的软件层。它为不同的应用程序、组件或服务提供通信、协调、管理和数据交换的通用服务。
它主要解决以下问题:
连接与通信:让运行在不同机器、用不同语言写的程序能互相“说话”。(就像服务员在客人和厨房之间传话)。
简化开发:程序员不用每次都从头写网络通信、安全认证、数据格式转换等复杂又通用的代码,直接使用中间件提供的功能就行。(就像餐厅不需要培训每个客人如何与厨师交流,有服务员代劳)。
解耦:让前端和后端相互独立。只要中间件的“接口”(菜单和服务规范)不变,厨房换了新厨师(后端系统升级)或APP换了新界面(前端改版),彼此都不受影响。(只要服务员还在,沟通方式不变,后厨和前厅可以各自优化)。
提供通用服务:比如消息队列(保证订单不丢失)、事务管理(保证“下单”和“扣款”要么都成功要么都失败)、安全控制、负载均衡(把大量订单合理分配给多个厨师)等。
常见的中间件类型(例子)
Web服务器/应用服务器:如 Nginx, Apache, Tomcat。它们是浏览器(客户端)和后台程序之间最重要的中间件,负责接收HTTP请求,转发给后端程序,再把结果打包成网页返回。
消息队列中间件:如 RabbitMQ, Kafka。像一个可靠的“快递柜”或“传话筒”。A服务把消息存进去就可以干别的事了,B服务有空的时候再来取。保证了系统在高峰时段不会崩溃,服务之间也不会互相等待。
数据库中间件:如 MyCat,各种数据库连接池。它管理应用程序和数据库之间的连接,就像“数据库连接的电话总机”,高效分配和复用连接资源。
远程过程调用框架:如 gRPC, Dubbo。它让你调用另一个机器上的服务,就像调用自己电脑上的一个函数那么简单,中间所有的网络通信细节都被它隐藏了。
API网关:如 Kong, Spring Cloud Gateway。它是所有外部请求进入系统的“总前台”和“安检口”,统一负责鉴权、限流、日志、路由到正确的内部服务。
我们需要判断哪个不是中间件技术。先回顾中间件技术的定义:中间件是位于操作系统和应用程序之间的软件,提供通信、协调、数据交换等通用服务,用于连接分布式系统中的不同组件。
A) JavaRMI (Java Remote Method Invocation):Java远程方法调用,是一种用于在Java虚拟机之间进行远程通信的机制,允许一个Java程序调用另一个Java虚拟机上的对象方法。它是典型的中间件技术,用于分布式对象通信。
B) CORBA (Common Object Request Broker Architecture):公共对象请求代理体系结构,是一种跨语言、跨平台的分布式对象通信标准,由OMG组织制定。它明确是中间件技术,提供了对象请求代理(ORB)作为中间件。
C) DCOM (Distributed Component Object Model):分布式组件对象模型,是微软的分布式组件技术,用于在不同机器上的组件间通信。它也是中间件技术。
D) JavaApplet:Java小应用程序,是一种嵌入在网页中运行在浏览器端的Java程序,主要用于客户端交互。它运行在客户端浏览器中,不提供分布式通信服务,也不属于中间件。中间件通常位于后台,连接不同组件,而Applet是前端客户端技术。
- 甘特图(Gantt Chart)
形式:一种横向条形图,横轴表示时间,纵轴列出项目活动,条形长度表示活动的起止时间和持续时间。
特点:
直观展示活动的时间安排、重叠关系和进度状态。
易于理解,适合用于资源分配和进度跟踪。
但无法清晰显示活动之间的逻辑依赖关系,也难以直接识别关键路径。 PERT图(Program Evaluation and Review Technique)
形式:一种网络图,用节点(通常表示事件)和箭线(表示活动)来描绘活动之间的逻辑关系。
特点:
强调活动之间的前后顺序和依赖关系。
通过三种时间估计(乐观、悲观、最可能)来计算活动工期和项目总工期,适用于不确定性较高的项目。
可以识别关键路径和浮动时间,便于进行风险分析和资源优化。开始 → A(3) → B(5) → C(4) ↘ D(2) → E(3) → F(6)关键路径法(CPM)图
形式:与PERT图类似,也是网络图,但通常用节点表示活动,箭线表示关系。
特点:
假设活动工期是确定的,侧重于计算项目的最短工期和关键路径。
与PERT的主要区别在于:CPM使用单一时间估计,而PERT使用概率时间估计。开始 | \ \ | \ \ A(3) B(5) C(4) | / \ | | / \ | D(2) E(3) F(6) \ / / \ \ / / \ H(1) I(3) \ / \ \ / \ J(2) K(2) \ / \ / L(2) | 结束- 其他工具
里程碑图(Milestone Chart):仅标记关键里程碑(重大事件)的时间点,用于高层汇报和总体进度控制。
工作分解结构(WBS):以层次化树状结构分解项目工作范围,不涉及时间安排,但是制定进度计划的基础。
时间线图(Timeline):类似简化的甘特图,通常只显示主要事件或活动的时间线。
在结构化分析中,DD(数据字典)中描述的数据对象通常被称为“数据元素”或“数据项”。
估算模型主要基于一个核心关系:
工作量 = (估算的软件规模) × (生产率相关的调节因子)
根据对 “软件规模” 的度量方式不同,主要分为以下几大类:
COCOMO模型(构造性成本模型)
COCOMO基本是静态单变量模型
COCOMO中级是静态多变量模型
详细COCOMO分三层级加额外考虑
功能点分析
从用户外部视角度量软件提供给用户的“功能”规模,与技术实现无关。
五类功能组件:
外部输入:用户输入的数据。
外部输出:系统输出的数据(报告、消息)。
内部逻辑文件:系统内部维护的数据。
外部接口文件:与其他系统交互的数据。
外部查询:输入后立即得到输出的简单交互。
计算步骤:
识别并计数上述五类组件的数量。
根据复杂度(低、中、高)为每个组件分配权重。
计算未调整功能点数。
考虑14个通用系统特性(如数据通信、性能要求等),计算值调整因子。
最终功能点数 = 未调整FP × VAF。
转换为工作量:
工作量(人月) = 最终FP数 / 生产率(FP/人月)
(生产率需根据组织历史数据或行业基准确定)
用例点分析法
适用于基于UML用例图进行需求分析的项目。
计算步骤:
计算未调整用例权重:根据参与者和用例的复杂度(简单、一般、复杂)分配权重并求和。
计算技术复杂度因子和环境复杂度因子。
计算调整后的用例点数。
根据一个用例点对应多少人时的生产率经验值,估算总工作量。
Putnam模型(SLIM)
一种基于瑞利曲线分布和经验数据库的动态多变量模型。
核心思想:工作量在项目生命周期中的分布符合特定曲线。
需要输入:规模、项目时长、一个称为“生产率指数”的环境常量。
可求解在给定规模下,理论上可能的最短开发时间。
建筑图纸 = UML图,让所有工人看懂同一套标准
地铁线路图 = 展示功能流转的路径
微信群聊记录 = 展示系统各部分如何按时间顺序"对话"
UML就是用一套全球通用的图形符号,把看不见摸不着的软件系统变成"可视化"的设计图,让产品经理、程序员、客户都能用同一种语言沟通。
UML到底有啥用?
- 团队沟通的"普通话"
避免开发中常见的"鸡同鸭讲":
产品经理说"要有个智能推荐功能"
程序员可能理解为"基于用户历史的推荐"
老板心里想的是"像抖音那样的算法推荐"
UML图把想法画出来,大家对着图讨论,一图胜千言。
- 编码前的"彩排"
没图纸就盖楼,容易盖到一半发现承重墙有问题。写代码前先画UML:
提前发现逻辑漏洞和设计缺陷
避免写完代码后大面积返工
让复杂系统变得清晰可拆解 - 项目的"设计日记"
半年后回看代码,你可能忘记"当时为什么这么设计"。UML图就是你的技术档案:
新人通过图快速理解系统架构
维护和升级时有据可查
降低人员交接的成本
例子:设计电商系统时
用用例图画出用户可以"浏览商品"、"下单"、"支付"
用类图设计"商品"、"订单"、"用户"这些核心对象的关系
用时序图分析下单时从前端到数据库的完整调用流程
UML是软件行业的"标准工程语言"——用图说话,让复杂系统变得清晰可见,磨刀不误砍柴工,前期画图越充分,后期返工就越少。
1.概要设计(高层设计):考虑 “系统由哪些部分组成,它们之间如何连接”。相当于画房屋的整体结构图(有几层、几个房间、楼梯在哪)。
2.详细设计(底层设计):考虑 “每个部分内部具体如何实现”。相当于画每个房间的详细装修图(插座位置、水管走向、墙面材料)。
两种设计方法的对比
举个例子:设计一个“在线购物系统”
结构化设计思路
概要设计:
模块划分:用户模块、商品模块、订单模块、支付模块。
数据设计:设计用户表、商品表、订单表。
接口设计:用户模块调用订单模块时需要传递哪些参数。
详细设计:
订单模块内部:用一个链表存储订单项,用快速排序对订单排序等。
面向对象设计思路
概要设计:
识别类:Customer、Product、Order、Payment。
类之间的关系:Order 包含多个 Product,Customer 拥有多个 Order。
详细设计:
细化 Order 类:属性 orderId、totalPrice;方法 calculateTotal()、generateInvoice()。
应用设计模式:比如用 Factory 模式创建 Payment 对象。
核心区别总结
结构化设计:像流水线,关注步骤和功能模块,模块通常是函数或过程。
面向对象设计:像乐高积木,关注事物和对象,模块通常是类和构件。

- 非直接耦合
关系:两个模块之间没有直接联系,它们通过一个主控模块或中间模块来协调。
比喻:两个人完全不认识,他们所有的沟通和任务交接都通过一个项目经理(第三方) 来完成。他们彼此独立,互不影响。
代码示例:模块A和模块B都只被主程序调用,它们之间不互相调用,也不共享任何数据。
评价:最理想的耦合,独立性最强。
- 数据耦合
关系:模块之间通过参数传递基本数据类型的数据进行通信。
比喻:一个人(A)需要另一个人(B)帮忙计算。A把原始数据(比如一串数字)交给B,B算好后把结果(一个数值)返回给A。A不关心B怎么算,B也不需要知道A的更多信息。
代码示例:result = calculateTax(income, rate); 这里只传递了收入和税率两个基本数据。
评价:理想的耦合,是设计时应该追求的主要方式。
- 标记耦合
关系:模块之间通过参数传递一个数据结构(如记录、对象),但被调用模块只用到该结构中的一部分数据。
比喻:A把一个完整的公文包(数据结构)递给B,但B只需要里面的一份文件。公文包里的其他文件对B来说是无用信息。
代码示例:传递一个完整的 Student 对象给 printStudentName() 函数,而这个函数其实只需要 student.name 属性。
评价:比数据耦合稍差,因为产生了不必要的依赖(如果Student结构改变,即使printStudentName逻辑不变,也可能需要重新编译或检查)。
- 控制耦合
关系:一个模块向另一个模块传递了控制信息(如标志、开关),目的是直接影响后者的内部逻辑流程。
比喻:A对B说:“这是数据,另外,如果遇到情况X,你就按方案1处理;否则按方案2。” A在控制B的决策。
代码示例:processData(data, isUrgent),其中 isUrgent 是一个布尔标志,会改变 processData 的内部行为(如走快速通道还是普通通道)。
评价:较强的耦合,因为调用者需要了解被调用者的内部逻辑分支。应尽量避免。
- 外部耦合
关系:多个模块都依赖同一个外部环境或全局约定,如共享的通信协议、数据格式、硬件接口等。
比喻:A和B都使用同一种“行业黑话”或同一种特定工具进行交流。他们之间不直接依赖,但都依赖这套外部规则。
代码示例:多个模块都读写同一个特定格式的XML文件,或者都调用同一个操作系统提供的特定API。
评价:耦合度较高,但有时不可避免。关键在于将外部依赖集中管理。
- 公共耦合
关系:多个模块都全局性地访问和修改同一块公共数据区(如全局变量、共享数据库表、公共内存)。
比喻:A和B都在一块公共白板上读写信息。A写的东西可能被B无意擦掉或覆盖,反之亦然。他们的行为通过这块白板紧紧绑在一起。
代码示例:多个函数都直接读写一个全局变量 globalConfig。
代码影响:极难调试和理解,因为任何一个模块的行为都可能被远处另一个模块的修改所影响。
评价:糟糕的设计,应严格限制使用。
- 内容耦合
关系:一个模块直接修改或依赖另一个模块的内部内容(如直接跳转到另一个模块的内部标号、修改另一个模块的内部数据)。
比喻:A不仅给B下指令,还直接动手篡改B的笔记或大脑里的想法。
代码示例:模块A使用 goto 语句跳转到模块B内部的某个标签;或者通过指针黑客手段直接修改模块B的私有变量。
评价:最差、最致命的耦合,完全破坏了模块的封装性。现代编程语言(如Java, C#)的语法特性已基本杜绝了这种情况。
核心设计原则
在软件设计中,我们的目标是:追求低耦合(松耦合),尤其是数据耦合;警惕并减少控制耦合;尽可能避免公共耦合和内容耦合。 低耦合的系统就像用乐高积木搭成的建筑,一块坏了可以轻松替换,而不像用水泥浇灌的一整块墙体,牵一发而动全身。
一、核心思想:像认识世界一样认识系统
OOA 的核心是 “对象” —— 一种将数据(属性) 和行为(方法) 封装在一起的实体。它模拟了人类认知现实世界的方式:
世界由各种对象组成(如:学生、课程、订单)。
对象具有特征(属性)和能力(方法)。
对象之间通过消息传递进行交互。
对象可以分类,形成类(具有相同属性和行为的对象的抽象)。
二、四大基本原则(支柱)
多态性允许我们以统一的方式处理不同的对象,而客户端代码不需要知道具体是哪个子类。
一个对象对应多张数据库表描述的是数据持久化模式
子类必须覆盖父类中的抽象方法(否则子类也是抽象类),并且可以覆盖非抽象方法(重写)。这属于继承的规则
对象在运行时可以改变其类型(如某些动态语言),但这属于动态类型或反射特性
三、OOA的主要产出模型(UML图)
OOA 使用一套标准化的可视化模型来描述系统,最常用的是 UML(统一建模语言) 的以下图表:
四、OOA的一般步骤
OOA 是一个迭代和增量的过程,通常包括以下活动:
需求获取与用例建模:
与用户沟通,识别 参与者(Actor)和 用例(Use Case)。
绘制 用例图,编写主要的 用例描述(基本事件流、备选事件流)。
识别对象与类:
从用例描述、需求文档中寻找名词短语,初步筛选出候选对象。
将对象抽象成 类,确定其 职责(应该做什么)。
建立静态模型(类图):
为每个类识别 属性 和 操作。
分析类之间的关系:关联(一个学生选多门课)、聚合/组合(汽车由发动机和轮子组成)、泛化(研究生是一种学生)、依赖。
建立动态模型:
针对重要的或复杂的用例,绘制 序列图 或 协作图,详细描述对象之间的交互过程。
对于状态复杂的类(如订单、账户),绘制 状态图。
对于涉及复杂业务流程的用例,绘制 活动图。
定义系统行为与规则:
使用 文本补充 或 OCL(对象约束语言) 描述业务规则、约束条件和非功能性需求。
五、OOA vs. 结构化分析
六、优势总结
与现实一致:更贴近人类对现实世界的认知方式,易于与领域专家沟通。
稳定性高:对象相对于功能更为稳定,使得分析模型在需求变化时更具弹性。
可复用性好:识别出的类和分析模式,可在后续项目或同一项目的其他部分复用。
支持迭代开发:OOA模型天然支持增量式、迭代式的开发过程。
贯穿整个生命周期:从分析到设计、实现,概念和模型可以平滑过渡,降低了阶段转换的损耗。
总而言之,面向对象的分析方法是一种以对象为核心、通过一系列可视化模型来系统化地理解和定义系统需求的强大方法。它是现代软件工程,尤其是复杂系统开发中不可或缺的一环。
动态绑定:过程调用与具体执行的代码在程序运行时才确定,常见于面向对象中的多态(如虚函数调用)。
静态绑定:过程调用与具体执行的代码在编译时即可确定,如普通函数调用或非虚方法调用。
这两个概念体现了程序设计中绑定时间的差异,动态绑定提供了灵活性,而静态绑定效率更高。
你可以把它想象成 “给一辆高速行驶的汽车更换发动机” —— 必须保证汽车不停下来,且新发动机要能无缝接替工作。
一个生动的例子:银行核心系统升级
一家银行要升级其最核心的存取款交易系统。
直接转换?绝对不行!万一新系统宕机,全国所有ATM和柜台都将瘫痪,引发社会危机。
并行转换?这是最可能的选择。尽管成本极高(需要双倍算力、人力核对每一笔交易),但能保证万无一失。在并行期,每一笔交易既走旧系统,也走新系统,结果必须完全一致。运行一个月后,数据100%吻合,再在某个周末凌晨,切断旧系统。
分段转换?可能按业务分(先换存款,再换贷款),或按地区分(先换上海分行,再换北京分行)。
试点转换?可以先选择一个信息化基础好的二级分行进行试点。
总结
系统转换是技术、管理和心理的综合工程。成功的转换 = 正确的策略 + 详尽的数据迁移计划 + 充分的用户培训 + 周全的应急预案。其终极目标是:让新系统平稳“着陆”,用户无感或体验提升,业务连续不中断。
在项目管理(如PMP)和风险管理体系中,设定优先级最常用的指标是风险暴露(也叫风险敞口或风险重要度)。它是一个综合值,计算公式通常为:
风险暴露 = 风险概率 × 风险影响
为什么不是单纯的“影响”或“概率”?
风险影响:只考虑后果的严重程度。但如果一个“灾难级”影响几乎不可能发生,优先级其实不高。
风险概率:只考虑发生的可能性。但如果一个“极可能”发生的事故影响很小,同样不需要优先处理。
风险控制:这是应对措施,不是设定优先级的依据。
简单对比记忆:
风险影响:这事有多惨?
风险概率:这事多大概率发生?
风险暴露:综合以上两者,算出这笔风险账到底有多大。优先级正是依据这个综合值从高到低排的。
因此,虽然“影响”和“概率”是重要参数,但题目问的是“设定优先级的根据”,标准答案是两者的乘积——风险暴露。
评论 (0)