软件项目实训及课程设计指导——系统概要设计中的程序类结构和类之间关系的设计示例

1、如何合理地进行软件系统中的各个程序类的设计

静可描"形"、动可描"行",动和静是辩证关系中的两个方面。在UML技术规范中与静态建模有关的各个视图可以描述软件应用系统的静态组织和体系结构,而与动态建模有关的各个视图则可描述出软件系统中的各个对象的行为和动作。构成面向对象模型的基本元素主要为:类和对象、类和类之间的关系等。

(1)合理地遵守面向对象程序类设计的五大原则

因为软件应用系统中的程序类设计直接对应于软件应用系统的功能实现设计,它的最终设计的质量将直接影响着软件应用系统的总体和整体的质量,所以这个设计阶段的工作是十分重要的。这就给软件应用系统的设计人员提出了一些挑战:

首先,程序类是如何确定的?

其次,如何合理地规划程序类?

最后,如何正确地建立程序类之间的关系?

因此,要求软件应用系统的设计人员要遵守一些软件应用系统程序类设计方面的"基本原则"、并合理地应用各种"设计模式",从而可以提高软件应用系统的总体设计的质量。

(2)合理地应用面向对象设计中的通用职责分配软件模式

软件应用系统的设计人员要应用面向对象设计中的通用职责分配软件模式(GRASP,General Responsibility Assignment Software Patterns)进行程序类的职责设计。因为GRASP设计模式能够为软件应用系统的设计人员提供如下方面的指导:

1)如何把现实世界的业务数据抽象成对应的对象;

2)如何决定一个软件应用系统中应该有多少程序对象(类);

3)每个程序对象(类)都包括什么方面的职责。

而对于上面的这些设计问题,GRASP设计模式都为软件应用系统的设计人员给出了最基本的指导思想和设计原则,并帮助软件应用系统的设计人员理解基本的面向对象的对象设计技术。

2、软件应用系统在设计和开发时必须"拥抱变化"和"适应变化"

(1)软件应用系统的用户需求在客观上是不断地变化的

在软件应用系统的组件模块的设计阶段最关键的问题是,用户的需求是变化的,软件应用系统的设计如何"拥抱变化"和"适应变化"?

(2)软件应用系统的需求分析并不能解决一切问题

从事软件应用系统设计工作的读者可能经常听到人们在抱怨,一个软件应用系统项目已经通过了交付测试,但软件系统投入运营以后用户又提出了新的系统需求,这时就会面临这样一个问题,修改一段代码就会需要几百个相关的程序代码跟着改变,因此软件应用系统的升级就变成几乎不可能的事情。于是,软件应用系统的开发者抱怨说,用户为什么当初不提出这些新的需求呢?而用户则抱怨说,随着企业经营的业务需求的不断变化,原有的软件应用系统将会逐渐不能满足企业经营的需要,而当初企业人员也是无法预料到的,当然也就无法在软件应用系统开发初期提出这些需求。

最后的结果,恐怕只能是一个,那就是这个软件应用系统将被弃之不用。其实,这个问题不在软件应用系统的使用方——用户,而是开发者在软件应用系统的设计、开发实现等方面存在一定的欠缺。

(3)比较困惑的事情

1)如果软件应用系统的设计和开发人员试图去发现用户的需求将会怎样或者如何地变化,那么软件应用系统的设计人员的工作将永远停留在软件应用系统的分析阶段——不断地在获得需求。

2)如果软件应用系统的设计和开发人员所开发出的软件应用系统能够面向未来的未知需求,那软件应用系统的设计人员的工作将永远处在软件应用系统的设计阶段——不断地完善系统设计以匹配变化的系统需求。

但软件应用系统的开发时间和预算是不允许开发方的相关人员面向未来设计软件应用系统,因为过分的系统分析和过分的系统设计,事实上都被称之为"分析瘫痪"。

3、软件应用系统在设计和开发时如何"拥抱变化"和"适应变化"

(1)软件应用系统的设计和开发人员应该遵守的几个原则

1)针对类接口编程而不是针对类实现编程。

2)优先使用对象组合关系,而不是类的继承关系。

3)考虑软件应用系统的设计有哪些是可变的,并考虑如果发生变化时,不会引起对软件应用系统的大幅度的修改或者重新的系统设计。

(2)封装变化的概念是模块设计的主题

为了解决这些问题,在软件应用系统的模块设计和对应的程序类设计、开发实现中需要充分地应用GoF的23种代码设计模式,而在GoF的23种代码设计模式中,把这些相关的设计模式分为结构型、创建型和行为型三大类型。而通过通用职责分配软件模式GRASP,软件应用系统的设计和开发人员又能够准确地进行各个程序类的各自的职责分配。

4、面向对象设计中所涉及的UML类与对象图的主要作用

(1)UML技术规范中的UML类与对象图能够体现和表现出软件应用系统的静态结构

UML类与对象图是面向对象分析和设计方法的核心内容之一,它们能表达面向对象模型的主要概念和各个组件类之间的关系,也是软件应用系统开发的基础;它们主要用以表达面向对象设计中的对象模型的静态结构——因为它们不仅能够定义软件应用系统中的功能类的内部结构(类的属性和类的操作),也可以表示类之间的关系(关联、依赖、聚合等)。

软件架构设计课程(软件项目实训及课程设计指导)(1)

(2)对象模型是对真实世界中的问题的抽象

由于以面向对象方法建造出的对象模型是基于真实世界的基本概念和业务流程的,并且与真实世界中的问题非常接近。从而使得该对象模型易于交流、易于验证和易于维护。

软件架构设计课程(软件项目实训及课程设计指导)(2)

5、熟悉软件应用系统中的程序类与类之间的各种关系形式

(1)结构性关系

主要反映出软件应用系统的静态结构方面的关系——如程序类之间的聚合(表示事物的部分与整体关系的较弱情况)、组合(表示事物的部分与整体关系的较强情况)、泛化(体现类之间的继承关系)等形式的关系。

在下图所示的代表通用的计算机概念的抽象类Computer与其他类之间关系的UML类中,可以了解到Computer类与CPU和HDDisk(代表计算机硬盘)等类是组合包含关系(紧密构成关系),而Computer类与Print类是聚合包含关系(松散构成关系),代表微型计算机概念的类PCComputer是Computer的子类,因此两者之间存在泛化关系,Computer类和该计算机的拥有者ComputUser类之间存在一对一的关联。

软件架构设计课程(软件项目实训及课程设计指导)(3)

(2)行为性关系

主要反映出应用系统的动态行为方面的关系——如类之间可以通过消息或者通过系统预定义、用户自定义的语义关系,主要的关系形式为依赖(类之间的"使用/调用"关系)和关联(关联是一种结构化的关系,指一个类和另一个类有关系)。

通常情况下,依赖关系体现在目标类的对象出现在局部变量或者方法的参数中以及静态方法的调用。依赖与关联关系是不同的,首先依赖关系总是单向的,其次依赖关系一般都体现有"使用"或者"调用"形式的关系。

在上图所示的Computer计算机类与其他类之间关系的UML类图中,Computer抽象类中的calculateData()功能方法带有一个Data类型的参数(代表计算机所要处理的各种数据),该calculateData()功能方法的执行依赖于所提供的参数Data对象。因此,Computer抽象类和Data类之间存在依赖关系。如下示图为某个软件应用项目中的相关程序类之间关系的局部截图:

软件架构设计课程(软件项目实训及课程设计指导)(4)

6、合理地分配软件应用系统中程序类的职责

(1)什么是程序类的职责

程序类所担任的任务和所要完成的功能称为该程序类的职责。但问题是,软件应用系统的设计人员如何正确地分配程序类的职责?

(2)遵守"单一职责"的原则进行程序类的职责分配设计

在程序类的职责设计和分配时,软件应用系统的设计人员应该要遵守面向对象程序类设计中所倡导的"单一职责"原则,这样将有利于该程序类的重用。当软件应用系统中的各个程序类在设计时如果不满足这一原则,设计人员就需要对软件应用系统中的有关功能类进行设计重构以拆分这个功能类为多个不同的程序功能类——这可以通过使用提取接口和提取方法等形式的重构方法加以实现。如下示图为某个软件应用系统中利用数据访问服务组件隔离系统的业务处理层和数据持久层之间直接耦合关系的类图局部截图,此时的数据访问服务组件为门面组件,该门面组件遵守面向对象设计中的"单一职责"设计原则进行程序类的职责分配设计。

软件架构设计课程(软件项目实训及课程设计指导)(5)

7、画出软件应用系统中的各个程序类所构成的类图

构成面向对象模型的基本元素是"类和对象"、"类和类之间的关系"等。因此UML中的"类图"与"对象图"是面向对象分析和设计工作的核心内容之一,因为它们能表达面向对象模型的主要概念和各个组件类之间的关系,也是软件系统开发的基础;而且它们主要用来表达对象模型的静态结构。如下示图为体现工厂设计模式中各个程序类之间关系的类图局部截图,应用产品接口定义各个产品的"共性"方法,并根据不同的应用需要实现该产品接口从而产生出满足不同应用需要的产品类。

软件架构设计课程(软件项目实训及课程设计指导)(6)

另外,在面向对象的设计方法中,设计阶段的一个十分重要的工作是进行"类"设计。下图所示为体现银行账户信息管理系统项目中的"粗粒度"的概要设计中的业务逻辑处理层中的各个类之间关系的类图——概要设计中的类图一般只体现类之间的关系,而不需要反映出类的内部结构和组成——对于各个类中的成员属性和成员方法的设计,一般可以通过在详细设计阶段进一步细化设计结果而获得。

软件架构设计课程(软件项目实训及课程设计指导)(7)

,