当前课程知识点:软件理论与工程 >  第3章 软件设计 >  3.6 构件级设计 >  3.6 构件级设计

返回《软件理论与工程》慕课在线视频课程列表

3.6 构件级设计在线视频

下一节:3.7 UI设计

返回《软件理论与工程》慕课在线视频列表

3.6 构件级设计课程教案、知识点、字幕

大家好

今天我们来一起分享一下

软件设计当中的

构件级设计

完整的软件构件

是在体系结构设计过程中定义的

但是

没有在接近代码的抽象集上

表示内部数据结构

和每个构件的处理细节

构件级设计

定义了数据结构

算法

接口特征

和分给每个软件构件的通信机制

体系结构设计第一次迭代完成之后

就应该开始构件级的设计了

在这个阶段

全部数据和软件的程序结构

都已经建立起来

目的是把设计模型

转化为运行软件

但是

现有设计模型的抽象层次

还相对较高

而可运行程序的抽象层次

相对较低

那么这中间是有很大的一个差距

这种转化具有挑战性

因为可能会在软件过程后期

引入难以发现

和改正的微小错误

一位帮我们理解软件设计的主要贡献者

Edsgar Dijkstra在其著作中写道

软件似乎不同于很多其他的产品

对那些产品而言

一条规则是

更高的质量

意味着更高的价格

那些想要真正可靠软件的人发现

他们必须找到某种方法

来避免开始时的大多数的错误

结果程序设计过程的成本会更低

高效率的程序员

不应该把他们的时间浪费在调试上

应该在开始

就不引入错误

当设计模型被转化为源代码时

必须要遵循一系列的设计原则

才能够保证

不仅能够完成转化任务

而且

不在开始的时候

就引入错误

那么 什么是构件呢

通常来讲

构件是计算机软件中的

一个模块化的构造块

对象管理小组

OMG统一建模语言规范

是这样定义构件的

系统中

模块化的

可部署的

可替换的部件

该部件封装了实现

并暴露了一组接口

在面向对象的观点当中

构件是协作类的集合

为了说明设计细化的过程

我们来看一个例子

我们用这个例子来说明

面向对象的构件的设计

我们考虑一个高级的影印中心

构造软件

这个软件的目的是

收集前台的客户需求

对印刷业务进行定价

然后把印刷业务交给自动生产设备

那么 在这个任务的需求分析过程当中

得到了一个名为

PrintJob的分析类

分析过程中定义了

PrintJob这个

分析类的属性

操作

我们在图中给出了注释

那么 在体系结构设计中

PrintJob被定义为

软件体系结构的一个构件

用简化的UML符号表示的该构件

显示在图的右上方

它有两个接口

ComputerJob和initiateJob

其中ComputerJob接口

具有对任务进行定价的功能

而另一个接口initiatejob

能够把任务传给生产设备

这两个接口我们在图下方的左边给出了

然后我们的构件级设计就要由此开始了

我们必须对PrintJob这个构件的细节

进行细化

以提供指导实现的充分信息

并通过不断补充作为构件

PrintJob类的全部属性

和操作

来逐步细化我们最初的

分析类PrintJob

细化后的PrintJob包括

很多的属性信息

和构件实现所需要的更广泛的

操作的描述

ComputerJob和initiateJob接口

隐藏着与其它构件通信和协作

这个部分我们在图中并没有表示出来

例如

ComputePageCost这个操作

它是

ComputerJob接口的一个组成部分

这个ComputePageCost这个操作

可能与包含任务定价信息的

PricingTable构件进行协作

checkpriority这个操作呢

是initiate接口的一个组成部分

它可能与JobQueue构件进行协作

用来判断

当前等待生产的任务类型和优先级

对于体系结构设计组成部分的每个构件

我们都要实施细化

细化一旦完成

要对每个属性

每个操作

和每个接口

进行更进一步的细化

对适合每个属性的数据结构

必须予以详细的说明

另外

还要说明实现与操作相关的

处理逻辑的算法细节

那么 最后

就是实现结构所需要的机制的设计

对于面向对象的软件

还会包含对实现系统内部对象间的

消息通信机制的一些相关的描述

那么我们再看一下传统的构件

在传统的观点下

一个构件就是程序的一个功能的要素

程序由处理逻辑

以及实现处理逻辑所需的内部数据结构

以及能够保证构件被调用和

实现的数据传递的接口构成

与面向对象构件类似

传统的软件构件

也来自于分析模型

但是 不同的是

在这种情况下

是以分析模型争斗的构件细化

作为导出构件的一个基础

构件层次结构上的每个构件

都被映射为某一个层次上的模块

一般来讲

控制构件位于层次结构

也就是我们的体系结构的顶层附近

而问题域的构件

则倾向于位于层次结构的底层

为了有效的模块化

在构件细化的过程中

采用了功能独立性的设计概念

那我们再回过头来看一下 我们刚才的

影印中心的例子

我们在传统的构件的角度下

导出了

如图所示的层次体系结构

其中

绿色的构件的功能

相当于图中的面向对象构件中

PrintJob类

定义的一些操作

然而 在这种情况下

每个操作都被表示为如图所示的

能够被调用的单独的模块

其它模块

用来控制处理过程

也就是我们前面提到的

控制构件

在构件级设计中

每个构件都要被细化

需要明确的定义模块的接口

也就是

每个经过接口的数据

或控制对象

都需要明确的加以说明

同时 我们还需要定义模块内部

使用的数据结构

并使用逐步求精的方法

设计完成模块中相关功能的一些算法

为了说明这个过程

我们考虑ComputePageCost模块

这个模块的目的在于

根据用户提供的规格说明

来计算每页的印刷成本

为了实现这个功能

我们需要

文档的页数

文档的印刷份数

单面或者是双面印刷

颜色

纸张大小

等一些参数

这些数据通过该模块的接口

传递给ComputePageCost模块

然后

ComputePageCost模块呢

根据任务量和复杂度

使用传递进来的这些数据

来决定一页的成本

这是一个通过接口

将所有数据传递给模块的功能

图中是UML符号描述的构件级设计

其中ComputePageCost模块

通过调用getJobData

模块

允许所有的相关数据

都传递给该构件

和数据库接口

accessCostsDB

这个接口能够使

该模块访问

存放所有印刷成本的数据库

来访问相关的数据

接着

对ComputePageCost的模块

进一步细化

给出算法

和接口的细节描述

其中

算法的细节

可以由图中显示的伪代码

或者是UML的活动图来表示

我们的接口被表示为一组输入

和输出的数据对象

或者是数据项的集合

设计细化的过程

会一直进行下去

直到能够提供指导构件的足够细节

都已经提供出来为止

那么我们下面看一下内聚

在传统观点里面

内聚是指的构件的专一性

在面向对象的观点里面

内聚性意味着构件或类

指封装那些相互关联的 密切的

以及与构件或者类自身有密切关系的

属性和操作

那么 无论是面向对象的还是传统观点的

我们的内聚性

可以进行一些分类

可以包括功能内聚

分层内聚

还有通信内聚

那么 功能内聚主要是

通过操作来体现

当一个模块完成一组

且只有一组操作并返回结果时

我们就称此模块是功能内聚的

分层内聚

由包

构件和类来实现

高层能够访问低层的服务

但是低层不能访问高层的服务

通信内聚

访问相同数据的所有操作

被定义在一个类中

一般来说

这些类只着眼于数据的查询

数据的访问

和数据的存储

看完了内聚 我们再看一下

在传统观点和面向对象观点当中的耦合

传统观点的耦合指的是

一个组件连接到其它组件

和外部世界的程度

在面向对象的观点里面

耦合指的是

类之间彼此联系的程度的一种特性的度量

耦合 可以有内容耦合

控制耦合

还有外部耦合

通信和协作

是面向对象系统当中的基本元素

然而

这个重要特征存在着一个负面的影响

随着通信和协作数量的增长

也就是说

随着类之间的联系程度越来越强

系统的复杂性也会随之增长

同时 随着系统复杂度的增长

软件实现

测试

和维护的困难

也会随之增大

耦合是类之间

彼此联系程度的一种定性的度量

随着类之间的相互依赖越来越多

类之间的耦合程度也就会增加

在构件级设计中

一个重要的目标就是

尽可能的保持

低耦合

我们的内容耦合是指的

发生在当一个构件

暗中修改了其它构件的内部数据时

我们称之为内容耦合

这就违反了基本的设计概念当中的

信息隐蔽的原则

控制耦合

发生在当操作a

调用了操作b

并且向b传递了一个控制标记时

接着 这个控制标记

会指引b中的逻辑流程

这种耦合形式的主要问题会在于

b中的一个不相关的变更

往往能够导致

a所传递的控制标记的意义

也必须发生变更

如果你忽略了这个问题

就会引起错误

外部耦合

发生在当一个构件和基础设施构件

比如操作系统

数据库容量

无线通信功能等等

进行通信协作时

尽管这种类型的耦合是必要的

但是 在一个系统中

应该尽量将这种耦合限制在少量的构件

或者是类的范围内

软件必须要进行

内部和外部的通信

因此耦合是不可避免的

然而 我们要把不可避免的耦合

尽量降低

并且我们要充分理解

该耦合产生的后果

实施构件级设计

构件级设计

我们要经过一系列的步骤

进行

第一

我们要标识出

所有与问题域相对应的设计类

我们使用需求模型和架构模型

每个分析类和体系结构构件都要细化

第二

我们要确定

所有与基础设施域相对应的设计类

在需求模型中

并没有描述这些与基础设施相对应的设计类

并且在体系结构设计中

也经常会忽略这些类

但是此时

我们必须要对它们进行描述

这种类型的类

和构件包括

图形用户界面

GUI构件

操作系统构件

以及对对象

和数据

进行管理的构件

第三

我们要细化所有

不需要作为复用的构件的设计类

我们要详细的描述实现类

细化所需要的所有接口

属性和操作

在实现这个任务时

必须考虑采用设计的启发式原则

如构件的内聚和耦合

其中在类和构件协作时

我们要说明消息的细节

我们可以使用协作图

来说明

类和构件协作时的消息的细节

需求模型中

用协作图显示分析类之间的相互协作

在构件级设计过程中

某些情况有必要通过对系统中的对象间

传递消息的结构进行说明

来表现协作的细节

尽管这是一个可选的设计活动

但是

它可以作为接口规格说明的一个前提

这些接口显示了系统构件之间的通信

和协作的方式

我们还要为每个构件确定适当的接口

在构件级设计中

一个UML的接口是

一组外部可见的

公共的操作

接口不包括内部结构

没有属性

也没有关联

更正式的来讲

接口就是某个抽象类的等价物

该抽象类提供了设计类之间的可控连接

还有我们要细化属性

并且定义实现属性所需要的数据类型

和数据结构

描述属性的数据类型和数据结构

一般都需要在实现时

所采用的程序设计语言中来进行定义

另外 我们详细描述每个操作的处理流

详细描述每个操作中的处理流可能需要

有基于程序设计语言的伪代码

或者是UML的活动图来完成

每个软件构件

都要应用逐步求精的概念

通过很多次的迭代来进行细化

然后我们还要说明持久的数据源

比如数据库和文件

并确定管理数据源所需要的类

再有开发并且细化类

或构件的行为表示

UML的状态图

被用作需求模型的一部分

表示系统外部可观察到的行为

和更多的分析类个体的局部行为

在构件级设计过程中

有些时候

对设计类的行为进行建模也是必要的

我们也可以使用UML的状态图

对设计类的行为进行建模

对象

的动态行为受到外部事件

和对象的当前状态的影响

为了理解对象的状态行为

设计者必须检查

设计类生命周期中

所有相关的用例

这些用例提供的信息

可以辅助设计者描述

影响对象的事件

以及随着时间的流逝

和事件发生对象所处的状态

另外 我们要细化部署图

以提供一些额外的细节

部署图作为体系结构设计的一部分

采用描述符形式来表示

在这种表示形式中

主要的系统功能

通常是子系统

或者是构件

都表示 在容纳这些功能的计算环境当中

那么这些构件和计算环境的细节

我们就可以通过细化部署图来获得

最后

考虑每个构件设计时

我们要时刻的考虑其它

可选的更优的方案

经过这样一系列的步骤

我们才能够完成构件级设计的相关工作

那么我们再通过影印系统的例子

我们来看一下协作图

来显示类

对象之间协作之间的消息传递的细节

比如图中我们有

ProductionJob

WorkOrder和JobQueue

这三个对象相互协作

为生产线准备印刷作业

图中的箭头表示对象间传递的消息

在需求建模时

消息说明如图所示

然而 随着设计的进行

我们消息要通过扩展

语法来进行细化

在前面的面向对象的构件

那个

PPT上

我们的initiateJob接口

由于没有展现出足够的内聚性而存在争议

实际上

在上一个面向对象的构件的图中

initiateJob接口

完成了三个不同的子功能

建立工作单

检查任务的优先级

将任务传递给生产线

为了实现接口的内聚性

我们的接口设计应该进行重构

重新检查设计类

并定一个新类WorkOrder

这个类的作用是

处理与装配工作单相关的所有活动

操作buildWorkOrder()

成为这个类的一个部分

类似的

我们可能需要定义包括操作

checkPriority()

在内的JobQueue这样的类

我们的ProductionJob类

包括给生产线传递生产任务的

所有相关的信息

那我们的initiateJob接口

就会采用图中所示的形式

现在我们的initiateJob接口

就是内聚的

集中在一个功能上

与ProductionJob

WorkOrder和JobQueue

相关的接口

几乎都是内聚的

实现专一的一个功能

经过重构的接口

如图所示

下面我们再看一下

我们要描述每个操作的处理流

每个操作的处理流

这个可能需要有

基于程序设计语言的伪代码

或者由UML图来完成

每个软件构件都要应用逐步求精的概念

通过

很多次的迭代

来添加相关的细节

来进行细化

图中的活动图

展现了我们刚才的操作处理流的细节

我们为了表现对象的行为的时候

可以使用状态图

状态图描述从

一种状态到另一种状态的转化

它可以表示为

event-name

括号里面放上

parameter-list

然后我们要加上我们的

guard-condition条件

和我们的action expression

我们的动作表示

我们开发并且细化类

或者是构件的行为的时候

可以使用我们的状态图

其中

event-name表示事件

parameter-list包含了

与事件相关的

所有的数据参数

我们的guard-condition

采用对象约束语言

OCL来书写

描述了事件发生前

必须满足的条件

我们的action expression定义了

状态转换时

会发生的动作

针对状态的进入和离开两种情形

每个状态

都可以定一个entry

和exit两个动作

在大多数的情况下

这些动作与正在建模的类

的相关的操作是相对应的

另外 我们可以使用do

提示符提供一种机制

用来显示伴随此种状态的相关活动

而我们的include提示符则提供了

通过在状态定义中

嵌入更多的状态图的细节的方式

来进行细化的一种手段

下面我们看一下基于构件的软件工程的流程

我们刚才解释了

构件级的一些设计

如果我们可以设计好很多

优秀可复用的构件的话

我们基于构件的软件工程

就可以重用这些构件

基于构件的软件工程是一种强调

使用可复用的软件构件

来设计与构造计算机系统的过程

领域工程的目的是识别 构造

分类

和传播一组软件 构件

这些构件在某一特定的领域中

可以适用于现在

和未来的软件

基于构件的软件工程的流程

如这张图所示

这张图的上半部分是

领域工程的工作

在领域工程中

首先要进行领域分析

领域分析

可以产生一些领域模型

同时

领域分析当中

我们会产生软件架构开发

软件架构开发会用到

刚才分析出来的领域模型

软件架构开发的产出物

可以是一些复用的产品

也可以产生一些结构模型

结构模型

支撑复用产品的开发

然后在领域工程最终可以产生知识库中

可复用的产品和构件

在这张图的下半部分是软件工程的工作

那么我们软件工程是起始于用户的需求

进行系统分析

由于我们是基于构件的软件开发

我们在系统分析的时候

可以去参考领域模型

进行系统分析

系统分析会产生一些系统原型

会产生一些规范与设计

在规范与设计的阶段

我们同样可以参考领域工程

输出的结构模型

规范与设计的部分

可以产生一些构件

和分析设计模型

在软件工程领域产生构件的时候

我们可以复用在领域工程里面的

产品库中的可复用的产品和构件

通过以下软件工程中的

构件

最终我们可以生成

我们的目标的应用软件

这张图显示了我们

基于构件的软件工程开发的

整体的流程

那么基于构件的软件工程

我们是有一些可用的构件库

然后我们的构件应该具有一致的结构

应该具有软件的构件标准

例如 我们可以参考OMG的CORBA标准

和Microsoft COM标准

或者是Sun公司的JavaBeans标准

参照了一定的标准

我们才能支持它的复用

以上是我们关于

构件级设计分享的所有相关内容

这一部分我们分析了

构件级设计

还分析了基于构件的软件工程

今天的内容就到这里

谢谢大家

软件理论与工程课程列表:

课程概述

-课程概述

第1章 软件与软件工程

-1.1 软件的本质

--1.1 软件的本质

-1.2 软件工程

--1.2 软件工程

-1.3 软件过程结构

--1.3 软件过程结构

-1.4 过程模型

--1.4 过程模型

-1.5 敏捷开发方法

--1.5 敏捷开发方法

-第1章 习题

--第1章 习题

第2章 需求分析

-2.1 需求工程过程

--2.1 需求工程过程

-2.2 需求获取

--2.2 需求获取

-2.3 需求分析

--2.3 需求分析

-2.4 过程建模

--2.4 过程建模

-2.5 面向对象建模

--2.5 面向对象建模

-第2章 习题

--第2章 习题

第3章 软件设计

-3.1 设计概述

--3.1 设计概述

-3.2 设计的概念

--3.2 设计的概念

-3.3 设计模型元素

--3.3 设计模型元素

-3.4 体系结构概述

--3.4 体系结构概述

-3.5 体系结构风格

--3.5 体系结构风格

-3.6 构件级设计

--3.6 构件级设计

-3.7 UI设计

--3.7 UI设计

-3.8 基于模式的设计

--3.8 基于模式的设计

-第3章 习题

--第3章 习题

第4章 UML方法

-4.1 UML概述

--4.1 UML概述

-4.2 UML 及UML中的事物

--4.2 UML 及UML中的事物

-4.3 UML关系和图

--4.3 UML关系和图

-4.4 UML 图细节(上)

--4.4 UML 图细节(上)

-4.4 UML 图细节(下)

--4.4 UML 图细节(下)

-第4章 习题

--第4章 习题

第5章 软件测试

-5.1 软件测试策略

--5.1 软件测试策略(上)

--5.1 软件测试策略(下)

-5.2 测试传统的应用系统

--5.2 测试传统的应用系统

-5.3 测试面向对象的应用系统

--5.3 测试面向对象的应用系统

-5.4 测试web应用系统

--5.4 测试web应用系统

-5.5 测试移动应用系统

--5.5 测试移动应用系统

-第5章 习题

--第5章 习题

第6章 项目管理

-6.1 软件项目估算

--6.1 软件项目估算

-6.2 软件过程管理

--6.2 软件过程管理

-6.3 软件配置管理

--6.3 软件配置管理

-6.4 项目版本控制及调试

--6.4 项目版本控制及调试

-第6章 习题

--第6章 习题

3.6 构件级设计笔记与讨论

也许你还感兴趣的课程:

© 柠檬大学-慕课导航 课程版权归原始院校所有,
本网站仅通过互联网进行慕课课程索引,不提供在线课程学习和视频,请同学们点击报名到课程提供网站进行学习。