1
面向对象软件工程实践指南
1.2.7.4 7.4 系 统 设 计
7.4 系 统 设 计

系统设计是围绕设计目标确定合理的系统构成和总体工作机制的过程。在总体设计中,也需要考虑系统实现的成本、时间、风险和质量因素。以下为典型的系统设计过程:

(1)确定设计目标:根据用户的需求或者市场的需求确定设计目标,这些设计目标通常是依据非功能需求而定的。

(2)确定子系统的分解结构:确定系统分为哪些子系统,各个子系统向外提供的接口,各个子系统之间是如何实现交互的。

7.4.1 系统设计中的概念

7.4.1.1 系统分解的概念

系统分解中涉及以下概念:

(1)子系统:子系统包含了一组紧密相关的类产生的对象。子系统一般具有定义良好的接口,因此具有整体的可替换性。

(2)服务:是由子系统提供的具有共同目标的一组相关的操作。

(3)子系统接口:经过完整定义的一组相关的接口。

系统分解就是定义具有良好接口的子系统的过程。

从大的角度看,系统分解有两种模式,即分层(layer)和拆分(partition)。

所谓“层”,也是一个子系统,该子系统向上层提供接口,同时利用下层系统的接口。分层体系结构使得各层有清晰的责任,并保持了实现上的独立性。因而,分层体系结构是目前的一种主流结构。典型的三层结构系统中各层分述如下。

(1)用户界面层:提供与用户交互的接口。用户界面层采用与UI设计相关的技术进行构造。

(2)应用逻辑和领域对象层:根据分析阶段得到的对象模型、动态模型而开发的软件对象模型,它们之间的协作能够实现业务功能。

(3)技术服务层:提供一些通用的对象或者子系统,负责与数据库、日志、网络等打交道,一般是与应用没有直接关系。在这一部分,我们经常会使用一些已有的类库、中间件甚至软件框架。

拆分是将系统从垂直的角度分成耦合度小的几个子系统,在多数情况下,拆分是按照功能进行的。

7.4.1.2 系统架构模式

系统架构模式是几种具有代表性的架构,在确定系统结构时,可以选用某种具有代表性的系统架构模式,根据它们,确定具体的结构方式。

1)客户机/服务器模式(client/server,C/S)

客户机/服务器结构是软件系统中最常见的一种。客户端向服务器方发送请求,服务器方根据接收到的请求向客户返回结果。这种模式随着数据库服务器的成熟而得到了推广,并且随着技术的发展,出现了许多不同的形态。

(1)两层C/S结构。该模式是最具代表性的客户机/服务器模式,也简称为“胖客户端”模式。在实际的系统设计中,该类结构主要是指前台客户端+后台数据库管理系统。

(2)三层C/S结构与B/S结构。在三层C/S结构中,其前台界面送往后台的请求中,先经过业务逻辑层处理,再进行数据库存取操作,前台界面与业务逻辑层之间可以采用TCP/IP协议,自定义的消息机制、基于RPC编程来实现、基于Java RMI,或者基于中间件如消息中间件来实现通信。

当前台采用Web页面,页面与Web服务器采用http协议通信时,这就是流行的B/S (brower/server,浏览器/服务器)模式。

(3)多层C/S结构。多层C/S结构一般是指三层以上的结构,在实践中主要是三层与四层,四层即前台界面(如浏览器)、Web服务器、中间件(或应用服务器)及数据库服务器,多层客户机/服务器模式主要用于较有规模的企业信息系统建设。

2)模型视图控制器模式(model,view and controller,MVC)

MVC既是一种架构模式也是一种设计模式,MVC可以带来更好的软件结构和代码重用。

在MVC中,将软件中处理输入、输出和处理功能的部分分开,使用MVC的软件分成三个核心部件:视图、模型和控制器。

(1)视图。视图是用户看到并与之交互的界面。例如,在Web程序中,视图就是浏览器中用户看到的页面。随着技术的发展,各种新型的用户交互形式不断出现,如语音接口、三维接口等,如何处理应用程序的界面变得越来越有挑战性。在MVC中,一个程序可以有多个视图,在视图中不包含处理逻辑。

(2)模型。模型表示企业数据和业务逻辑。在MVC的三个部件中,模型是最核心的部分。在面向对象的软件模式中,模型部分与具体的数据格式(返回给前端的结果)无关,这样一个模型能为多个视图提供数据。

(3)控制器。控制器接受用户的输入并调用模型和视图去完成用户的需求。在用户通过视图发出命令时,控制器本身不输出任何东西和做任何处理。它只是接收请求并决定调用哪个模型构件去处理请求,然后确定用哪个视图来显示模型处理返回的数据。

3)管道过滤器模式(piper-filter)

管道过滤器是一种比较经典的结构,它是从数据流的观点来观察系统。系统中包含的组件有管道和过滤器。需要处理的数据经过管道传送给过滤器,过滤器代表了一个处理步骤,提供了相对单一的功能。过滤器之间的顺序也可以配置。当数据通过所有的过滤器后,完成了所有的处理操作,得到了最终的处理结果。

管道过滤器体系结构的一个例子是以Unixshell编写的程序。Unix既提供一种符号,以连接各组成部分(Unix的进程),又提供某种进程运行机制以实现管道。

随着大数据的发展,管道 过滤器结构又得到了进一步的发展,现在的大数据处理平台Storm就是建立在管道过滤器模式的基础上。

4)协调器架构模式(mediator)

当对象之间需要相互集成时,如果让它们直接进行集成,可能会形成复杂的网状调用关系。这样,当某一个对象发生改变时,许多对象都会受到影响。在系统设计时,我们希望它们可以较松散地耦合。这样可以保证这些对象彼此独立地变化。

通过引入协调器,可以把网状的系统结构变成一个星型结构,在这个星型结构中,对象之间不直接联系,而是都通过协调器进行联系。这样当某一个对象发生修改时,其他对象都不会受到影响。

5)点对点模式(peer to peer)

在C/S结构中,通常服务器承受了比较集中的负载,当请求量越来越大时,服务器也往往会成为瓶颈。在点对点模式中,系统中的节点都处于平等的地位,每个节点都可以连接其他节点,这样,系统中的节点越多,能力越强大。在这种架构中,一般需要由一个中心服务器完成发现和管理节点的操作。

6)黑板模式(blackboard)

在这种架构中,相互独立的构件对中心数据进行操作,就好像多位不同的专家在同一黑板上交流思想,每个专家都可以获得别的专家写在黑板上的信息,同时也可以用自己的分析去更新黑板上的信息,从而影响其他专家。

黑板系统主要由以下三部分组成。

(1)知识源(相互独立的构件):包含独立的、与应用程序相关的知识,知识源之间不直接进行通讯,它们之间的交互只通过黑板来完成。

(2)黑板数据结构:按照与应用程序相关的层次来组织并解决问题的数据,知识源通过不断地改变黑板数据来解决问题。

(3)控制:完全由黑板的状态驱动,黑板状态的改变决定了需要使用的特定知识。

黑板模式可用于非确定性问题求解、启发式解决过程。但是系统也存在可维护性、可重用不足,效率低下等问题。

7)面向服务的体系架构模式(service oriented architecture,SOA)

面向服务的架构是一个组件模型,它将应用程序的不同功能单元——服务(service),通过服务间定义良好的接口和契约(contract)联系起来。接口采用中立的方式定义,独立于具体实现服务的硬件平台、操作系统和编程语言,使得构建在此系统中的服务可以使用统一和标准的方式进行通信。这种具有中立的接口定义(没有强制绑定到特定的实现上)的特征称为服务之间的松耦合。

服务是整个SOA实现的核心。SOA架构的基本元素是服务,SOA指定一组实体(服务提供者、服务消费者、服务注册表、服务条款、服务代理和服务契约),这些实体详细说明了如何提供和消费服务。遵循SOA观点的系统必须要有服务,这些服务是可互操作的、独立的、模块化的、位置明确的、松耦合的并且可以通过网络查找其地址。

SOA的灵活性给企业带来了好处。如果把企业的IT架构抽象出来,将其功能以粗粒度的服务形式表示出来,每种服务都清晰地表示其业务价值,那么,这些服务的顾客(可能是公司的内部人员,也可能是公司的某个业务伙伴)就可以得到这些服务,而不必考虑其后台实现的具体技术。更进一步,如果顾客能够发现并绑定可用的服务,那么在这些服务背后的IT系统能够提供更大的灵活性。

7.4.2 确定系统设计目标

确定系统的设计目标是系统设计的第一步。显然系统目标的确定是依据需求而定的,而且主要是依据非功能需求而定的。

系统设计目标的具体依据可以是:

(1)依据领域中的客观需要而得出:通过与客户的交谈,提炼客户对系统的设计目标。

(2)通过对目前系统中存在问题的分析而得出:通过记录客户对目前系统的意见,对现有的一些指标进行进一步的提升得到对未来系统的目标。

(3)通过对市场上类似系统的对比而得出:对比市场上的先进系统确定合适的目标。

为了确定系统的设计目标,可以采用一个通用的性能列表,这个列表中列出了一些通常要考虑的性能方面的问题,通过回答这些问题就可以确定系统的设计目标。

7.4.3 子系统的识别

子系统识别的依据是软件设计的各项原则。每一个识别出来的子系统应该是功能内聚、对外接口清晰的对象集合。为了达到这一点,可以采用以下一些策略。

(1)按照架构模式来识别子系统:在确定了采用的架构模式后,按照架构中的子系统划分方式来确定子系统,比如说采用三层架构,就可以划分出三个子系统,即前台界面层、业务逻辑层和数据库层。

(2)重用的外部软件作为子系统:许多时候我们可能会重用某一个外部的软件,要开发的软件与该系统通过接口进行集成。因此,将这样的一个软件作为子系统是一个自然的选择。

(3)具有整体可重用性的部分作为子系统:在开发系统时,某些部分可能在未来具有通用性。企业中开发软件时可能围绕某一领域开发多个系统,为了提高系统的可维护性包括开发效率,我们会抽取可重用的部分构成相对独立的子系统。

(4)观察设计类图,将关联密切并且功能相关的类作为子系统:在设计类图中如果明显呈现出分块的特点,那么可以考虑将这些块作为子系统。

(5)将一个用例中涉及的类放在相同的子系统中:这种方法是按照功能进行系统的分解。

(6)专门的子系统负责数据管理、底层服务:可以把一些向上提供公共服务的类放在一起作为一个子系统。

检验子系统是否划分合理的判断依据主要是:

(1)子系统之间的关联要少。

(2)子系统内部的对象功能相关。