软件工程之面向对象分析深度解析
前文基础:
1.软件工程学概述:软件工程学概述-CSDN博客
2.软件过程深度解析:软件过程深度解析-CSDN博客
3.软件工程之需求分析涉及的图与工具:软件工程之需求分析涉及的图与工具-CSDN博客
4.软件工程之形式化说明技术深度解析:https://lzm07.blog.csdn.net/article/details/147803429
5.软件工程之详细设计深度解析:https://blog.csdn.net/lzm12278828/article/details/147807034
一、面向对象分析的基本过程
(一)概述
面向对象分析(Object-Oriented Analysis, OOA)是通过抽象问题域中的实体及其关系,建立系统精确模型的过程。其核心思想是将现实世界中的事物映射为对象(Object),通过封装、继承、多态等机制描述系统行为。与传统结构化分析相比,OOA更贴近人类认知方式,能有效降低复杂系统的开发难度。
OOA的目标是形成软件需求规格说明书,主要由三个子模型构成:
(1)对象模型:描述系统静态结构(类、对象及其关系)。
(2)动态模型:描述系统动态行为(状态变化、事件交互)。
(3)功能模型:描述系统数据变换和处理逻辑。
实际分析过程需反复迭代,通常遵循“理解→表达→验证”的循环:
(1)理解需求:与用户、领域专家协作,明确系统边界和功能。
(2)建立模型:通过三个子模型逐步细化需求,形成可验证的规格说明。
(2)验证模型:检查模型的一致性、完整性和可实现性,确保符合用户需求。
(二)3 个子模型与 5 个层次
1. 三个子模型
(1)对象模型:
以类图为核心,描述系统中对象的静态结构。例如,在线购物系统中的“用户”“商品”“订单”等类,以及它们之间的关联(如“用户下单”“订单包含商品”)。对象模型是系统的基础,其他模型依赖其提供的类和关系。
(2)动态模型:
以状态图和事件跟踪图为工具,描述对象的状态变化和事件交互。例如,订单的状态从“已提交”变为“已支付”再到“已发货”,需通过状态图明确触发状态转换的事件(如“用户支付”“仓库发货”)。
(3)功能模型:
以数据流图(DFD)为核心,描述系统的数据处理逻辑。例如,在线购物系统的“订单处理”功能可分解为“验证库存”“计算总价”“生成发票”等子处理,通过数据流图展示数据流动和处理过程。
2. 五个层次
复杂系统的对象模型通常包含五个层次,形成逐层细化的结构:
(1)主题层:将系统划分为若干主题(如“用户管理”“订单管理”),便于理解大型模型。
(2)对象类层:识别系统中的类与对象(如“用户”“商品”)。
(3)结构层:定义类之间的关系(如继承、关联)。
(4)属性层:为类添加属性(如“用户”的姓名、邮箱)。
(5)服务层:定义类的操作(如“用户”的登录、注册)。
二、需求陈述
(一)书写要点
需求陈述是OOA的起点,需清晰、准确地描述系统功能和约束。关键要点包括:
(1)问题范围:明确系统边界,区分系统内外部实体。
(2)功能需求:列出系统必须完成的任务(如“用户可查询订单状态”)。
(3)性能需求:定义响应时间、吞吐量等指标(如“订单查询响应时间≤2 秒”)。
(4)应用环境:描述系统运行的软硬件环境(如“支持 Windows 和 macOS”)。
(5)假设条件:说明未经验证的前提(如“用户输入数据格式正确”)。
书写时应避免歧义,采用结构化语言(如“系统应允许用户……”),并优先使用动词短语描述功能。例如,“用户提交订单后,系统应发送确认邮件”比“系统要处理订单”更明确。
(二)例子:在线购物系统需求陈述
项目背景:
某电商平台需开发在线购物系统,支持用户浏览商品、下单、支付,以及管理员管理商品库存和订单。
需求陈述:
1.功能需求:
用户可注册、登录系统,浏览商品列表,查看商品详情。
用户可将商品加入购物车,修改购物车中商品的数量或删除商品。
用户提交订单后,系统应生成唯一订单号,并发送确认邮件。
管理员可添加、修改、删除商品信息,查看订单状态并更新物流信息。
2.性能需求:
商品搜索响应时间≤1 秒(数据量≤10 万条)。
订单处理吞吐量≥100 笔 / 分钟。
3.应用环境:
服务器端:Linux 操作系统,MySQL 数据库,Tomcat 应用服务器。
客户端:支持 Chrome、Firefox 等主流浏览器,移动端适配 iOS 和 Android。
4.假设条件:
用户已安装最新版本浏览器,网络连接稳定。
支付接口由第三方支付平台提供,系统无需处理支付安全问题。
三、建立对象模型
(一)确定类与对象
从需求陈述中提取名词短语,筛选出与问题域相关的类。例如,在线购物系统中的候选类包括“用户”“商品”“购物车”“订单”“支付”等。需排除冗余(如“系统”)、无关(如“网络”)或笼统(如“数据”)的类。
筛选原则:
(1)冗余类:重复表示同一概念的类(如“顾客”和“用户”)。
(2)无关类:与系统功能无关的类(如“操作系统”)。
(3)笼统类:过于抽象的类(如“实体”)。
(4)属性类:应作为属性而非类的概念(如“商品颜色”)。
(5)操作类:应作为方法而非类的概念(如“支付处理”)。
(二)确定关联
识别类之间的关系,如“用户下单”(用户与订单的关联)、“订单包含商品”(订单与商品的关联)。关联需明确重数(如“一个订单包含多个商品”)和方向(如“用户提交订单”)。
关联类型:
(1)普通关联:如“用户拥有购物车”。
(2)聚合关联:如“购物车由多个商品项组成”。
(3)继承关联:如“管理员是特殊用户”。
(三)划分主题
将类分组为主题,降低模型复杂度。例如,在线购物系统可划分为“用户管理”“商品管理”“订单管理”三个主题。主题应具有高内聚性,组内类关系紧密,组间耦合度低。
(四)确定属性
为类添加描述性属性。例如,“用户”类的属性包括姓名、邮箱、地址;“商品”类的属性包括名称、价格、库存。属性应满足原子性(不可再分)和完整性(无遗漏关键信息)。
常见错误:
(1)误把对象当属性:如将“地址”作为“用户”的属性,而非独立类。
(2)属性冗余:如“订单总价”可通过“商品价格 × 数量”计算,无需存储。
(3)属性不一致:如“商品价格”在不同类中单位不统一(元 / 美元)。
(五)识别继承关系
通过泛化 - 特化关系(继承)简化类结构。例如,“管理员”是“用户”的子类,继承“用户”的属性和方法,并添加“权限管理”等特有功能。继承可减少代码冗余,提高可维护性。
继承策略:
(1)自底向上:从具体类中提取公共属性和方法,形成父类。
(2)自顶向下:从抽象父类逐步细化为具体子类。
(六)反复修改
对象模型需多次迭代优化。例如,初始模型中“订单”和“支付”是独立类,后续发现“支付”可作为“订单”的一个状态,从而合并为“订单”类的属性或子状态。
优化方法:
(1)分解复杂类:如将“现金兑换卡”分解为“卡信息”和“交易记录”。
(2)合并冗余类:如“分行”和“分行计算机”可合并为“分行”类。
(3)调整关联关系:如将三元关联拆分为二元关联。
四、建立动态模型
(一)编写脚本
描述系统典型交互场景(如“用户下单流程”),明确事件顺序和参与者。脚本需覆盖正常流程和异常情况,例如:
用户下单脚本:
(1)用户登录系统,浏览商品列表。
(2)用户选择商品,添加到购物车。
(3)用户确认订单信息,提交订单。
(4)系统验证库存,若库存不足,提示用户;否则生成订单。
(5)用户选择支付方式,完成支付。
(6)系统更新订单状态为“已支付”,并发送确认邮件。
(二)设想用户界面
设计系统的交互界面,确定用户操作方式(如按钮、菜单)和反馈机制(如提示信息)。例如,订单提交后显示“订单已提交,预计 24 小时内发货”。
(三)画事件跟踪图
以竖线表示对象,箭头表示事件,展示对象间的交互顺序。例如,用户下单的事件跟踪图如下:
用户 → 购物车:添加商品
购物车 → 商品:查询库存
商品 → 购物车:返回库存信息
用户 → 系统:提交订单
系统 → 订单:生成订单
系统 → 支付接口:发起支付
支付接口 → 系统:返回支付结果
系统 → 用户:发送确认邮件
以下是一个示例:
(四)画状态图
为关键类绘制状态图,描述其状态转换。例如,“订单”类的状态图:
初始状态 → 已提交
已提交 → 已支付 [用户支付]
已支付 → 已发货 [管理员发货]
已发货 → 已完成 [用户确认收货]
已提交 → 已取消 [用户取消订单]
以上是一个示例:
(五)审查动态模型
检查状态图和事件跟踪图的一致性,确保事件触发的状态转换符合逻辑。例如,“已取消”状态不能直接转换为“已支付”,需通过“重新提交订单”事件触发。
五、建立功能模型
(一)画出基本系统模型图
用数据流图(DFD)描述系统与外部实体的交互。例如,在线购物系统的基本模型图:
外部实体:用户、管理员、支付平台
处理:订单处理
数据流:商品信息、订单请求、支付结果
数据存储:商品库、订单库
(二)画出功能及数据流图
逐层分解基本模型,细化处理逻辑。例如,“订单处理”可分解为“验证库存”“计算总价”“生成发票”等子处理,并用数据流连接各处理框。
0层数据流图:
用户 → 验证库存:商品ID、数量
验证库存 → 商品库:查询库存
商品库 → 验证库存:库存信息
验证库存 → 计算总价:商品价格、数量
计算总价 → 生成发票:订单金额
生成发票 → 订单库:保存订单
以下是数据流图的一个示例:
(三)描述处理框功能
用结构化语言或判定表详细说明每个处理框的逻辑。例如,“验证库存”处理框的逻辑:
IF 库存 ≥ 订单数量 THEN
返回“库存充足”
ELSE
返回“库存不足”
ENDIF
六、定义服务
(一)常规行为
为类定义通用操作,如“用户”类的“登录”“注册”,“订单”类的“提交”“取消”。这些操作直接对应动态模型中的事件和状态转换。
(二)从事件导出的操作
根据事件跟踪图中的交互,确定对象需提供的方法。例如,“用户添加商品到购物车”事件对应“购物车”类的“添加商品”方法。
(三)与数据流图对应
将数据流图中的处理框映射为对象的操作。例如,“计算总价”处理框对应“订单”类的“计算总价”方法,该方法调用“商品”类的“获取价格”方法。
(四)利用继承减少冗余
通过继承机制复用父类服务。例如,“管理员”类继承“用户”类的“登录”方法,并添加“修改商品信息”等特有方法。
java代码示例:
// 父类:用户 public class User { private String name; private String email; public void login(String username, String password) { // 登录逻辑 } } // 子类:管理员 public class Admin extends User { public void updateProduct(Product product) { // 修改商品信息逻辑 } }
七、结语
面向对象分析通过三个子模型和五个层次,将用户需求转化为可执行的系统模型。实际应用中需注意:
(1)模型迭代:分析过程需反复优化,避免过早陷入细节。
(2)工具辅助:使用 UML 类图、状态图、DFD 等工具提高建模效率。
(3)跨模型关联:确保对象模型、动态模型、功能模型的一致性,例如对象的属性和操作需在数据流图中体现。
(4)领域知识:结合行业经验识别关键类和关系,例如金融系统需重点关注“账户”“交易”等类。
未来,随着AI辅助建模工具的发展,面向对象分析将更高效、智能化,进一步降低复杂系统的开发门槛。