10-软件体系结构设计与构建
- 体系结构之间的接口:
- 重点还有根据分配的需求确定模块的对外接口
- 初步设计关键类
- 编写接口规范(提供服务和需要服务)
- 根据体系结构开发继承测试用例(Stub和Driver)
1. 体系结构设计过程(简略步骤) 重要
- 分析关键需求和项目约束:分析用例文档和需求规格说明书(包含需求规格和项目约束)。注意既要考虑功能性需求,又要考虑非功能性需求,甚至很大意义上体系结构设计是为了满足非功能性需求。
- 通过选择体系结构风格:选择分层风格(信息系统、并行开发、非web应用),进行评审。
- 进?软件体系结构逻辑(抽象)设计:产生逻辑包图
- 依赖逻辑设计进行软件体系结构(实现)设计:产生物理类图
- 完善体系结构设计:关键类图,持久化数据格式的定义等
- 添加构件接口:包、重要文件的创建,定义接口
- 迭代过程3-6
- 步骤1-3是逻辑设计,步骤4-7是物理设计
2. 第一步:分析关键需求和项目约束
- 软件需求规格说明
- 项目约束
- 体系结构设计必须落实所有的功能性需求和非功能性需求
2.1. 系统结构需求
- 需求
- a 概要功能需求:10 个功能
- b 非功能性需求
- 安全需求:Security1~3
- 约束:IC2
- 项目约束
- a 开发技术:Java
- b 时间较为紧张
- c 开发人员:不熟悉 Web 技术
3. 第二步:通过选择体系结构风格
3.1. 实践案例
- 将需求分配到子系统和模块
- 考虑功能的相同性:不同任务,但是相同功能
- 考虑可复用性:结构、数据、行为的可复用性
- 实践案例
- 销售与退货
- 产品调整、入库、出库与库存分析
- 会员发展与礼品赠送
- 销售策略
- 基本功能
- 销售
- 库存
- 会员
- 销售策略
- ?户
- 连锁超市管理系统的改进概要功能设计
- 初步设计方案二:
- 层与层之间就是一一对应了。
- 逻辑层对象进行一一交互,只要互相对应的进行通知即可。
- 进一步将业务层的功能进行切割划分
5.1. Common Closure Principle (CCP) 共同封闭原则
- 一起修改的类应该放在一起
- 最小化修改对程序员的影响
- 当需要更改时,对程序员有利
- 如果更改由于编译和链接时间以及重新验证而影响了尽可能少的软件包
- 示例
- 总结
- 为重用器分组组件(类)
- 单个类通常是不可重用的:几个协作类组成一个包
- 包中的类应构成可重用和可释放的模块:模块提供一致的功能
- 减少重新使用者的工作
- 和相关联的类一起发布,而不是单独进行发布
5.5. The Acyclic Dependencies Principle (ADP) 无环依赖原则
- 程序包的依赖关系结构必须是有向非循环图(DAG)
- 稳定并分批发布项目
- 以自上而下的层次结构组织程序包依赖关系
- 一旦形成环就可能会形成无限的修改(环中的包的修改会导致大量的修改的发生)
5.5.1. Dependencies are a DAG
5.5.3. 依赖循环打破循环:第二种方式:
- 另一情况,这种情况是互相依赖产生的闭环,A依赖于X,Y依赖于B
- 解决方案:从Y提供一个接口(这个接口被B实现,被Y持有)
- B实现BY:B依赖于BY
- 为什么X是稳定的,而Y是不稳定的(别人变化不会影响到我)
- String类(Instability、Abstraction原点)
- String类就是尴尬的处于原点的一个包,导致任何对String的修改都有可能导致之前开发的java程序无法运行。
5.8.2. 例子
6.2. 细节考虑
- 所有的 Presentation 层开发包都需要使?图形类型建?界?,都要依赖于图形界面类库包。
- 此外,Presentation 层实现时,由 mainui 包负责整个页面之间的跳转逻辑。其它各包负责各????身的功能。
- 开发包的循环依赖现象需要消除,对此可以使?依赖倒置原则(参? 15.2.3)将循环依赖变为单向依赖:
- Sales与Commodity:将部分 Commodity类抽象接口 commodityInfoService置? Sales 包, 这样 Commodity 单向依赖于 Sales(实现接?+调?)。
- Sales 与 Member:将部分 Member 类抽象接?置? Sales 包,这样 Member 单向依赖于 Sales(实现接?+调?)。
- 在 Logic 层中,?些关于初始化和业务逻辑层上下?的?作被分配到 utilitybl 包中去。
6.3. 连锁超市管理系统开发包图
- 客户端
6.4. 进程图
- 进程图主要是表明运行时的进程,以及个进程间如何进行通信的。
7. 第五步:完善体系结构设计
- 完善软件体系结构设计
- 细化软件体系结构设计
7.1. 完善启动和 络链接
7.3. 数据定义
- 接口的数据对象
- 关键类的重要数据结构
- Value Object (VO)
- Persistent Object(PO)
- ?POJO实现
7.3.1. Java 实体
- 实体是一个可以代表一个临时的业务实体的对象,比如一个账单或者用户
- 没有逻辑业务方法(行为)
- 实体必须在使用它们的会话或事务之间持久存在。
- 实体是存储在文件或者数据库中的
- 实体是一个Beans
- Simple or EJB.
7.3.2. POJO(Plain Old Java Objects)= Simple Java Entities
7.3.3. Value Objects(逻辑层向展示层传递数据)
- 价值对象(VO)包含一个或多个公共领域中实体的属性。
- 在层之间传递值对象,而不是实体。
- 应该考虑实现Serializable
- 值对象可以更新和创建实体。
- 实体可以创建价值对象。
7.3.4. 图书地址业务实体
- 有的接口是面向业务的
8.3. 编写接口规范
9.2. 重要文件的创建
- 可选
- 数据文件
- 系统文件
- 配置文件
9.2.1. 文件列表

- SalesBLService的定义
9.3. 定义构件之间的接口
- 在包和文件定义之后,我们可以着力开始定义构件之间的接口
9.4. 关键需求的实现
- 实现一些关键功能需求。
- ?如连锁超市系统中销售用例就是?个关键的用例。它所覆盖的面广,如果销售用例可以实现的话,其它?例的实现就?较有信?了。?且这个需求需要做到端到端的实现。
- ?如,连锁超市系统中存在客户端和服务器端。那么我们就需要在客户端通过 GUI 界?发出指令,通过客户端的业务逻辑处理,访问服务器端的数据,对数据进行修改。只有这样才能表明当前的体系结构可以胜任功能性需求。
- 对原型的非功能性指标进?估算和验证。如果出 现不符合非功能性需求和项目约束的情况,我们还需要重新对体系结构设计进?调整。
- ?如,连锁超市系统中我们?问难来保存数据,?当数据越来越多,特别是销售记录要保存 1 年。这时候,客户端跨?络对服务器上?件的查找就?较慢,可能会使得我们不满?实时性的要求。
- 这时候,可能我们就要调整体系结构中数据存储的?案,?如换成数据库。或者在客户端的逻辑层和数据层之间,加设数据映射层。在客户端运?初始化时,将数据从服务器端载?到客户端的内存中去。
10. 体系结构集成与测试
10.1. 集成的策略
- 当体系结构中原型各个模块的代码都编写完成并经过单元测试之后,需要将所有模块组合起来形成整个软件原型系统, 这就是集成。
- 集成的目的是为了逐步让各个模块合成为?个系统来?作,从而验证整个系统的功能、性能、可靠性等需 求。对于被集成起来的系统?般 主要是通过其暴露出来的接?,伪装?定的参数和输?,进?黑盒测试。
- 根据从模块之间集成的先后顺序,?般有下列?种常?的集成策略:
- 大爆炸式(所有放在一起,看能不能过)
- 增量式
- 自顶向下式
- 自底向上式
- 三明治式
- 持续集成
- 模块开发完成后我们进行开发集成测试用例
10.1.1. 大爆炸集成
- 大爆炸集成:将所有模块一次性组合在一起。
- 优点:可以在短时间内迅速完成集成
- 缺点:一次运行成功可能性不高,不容易发现bug
10.1.2. 自顶向下集成
- 自顶向下集成是对分层次的架构,先集成和测试上层的测模块,下层的模块用伪装的具体接口的桩程序。
- 自顶向下集成的优点:
- 按深度优先可以?先实现和验证?个完整的功能需求;
- 只需顶端?个驱动(Driver);
- 利于故障定位。
- 自顶向下集成的缺点:
- 桩的开发量大;
- 底层验证被推迟,且底层组件测试不充分。
- 但是一般会带来比较好的顶层设计的优势。
- 自顶
声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!