2 01 | 软件建模与文档:架构师怎样绘制系统架构蓝图?

Posted 程序杰杰

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2 01 | 软件建模与文档:架构师怎样绘制系统架构蓝图?相关的知识,希望对你有一定的参考价值。

你好,我是李智慧。

我在开篇词中说过,我们课程中的一系列软件架构设计是用设计文档的形式呈现的。所以,在拆解一个个案例之前,我们先来了解一些关于软件设计文档的基础知识,这样你在学习后面的具体案例时,就能更加清楚地理解文档是基于什么方式来组织的了。

首先,请你设想这样一个场景:如果公司安排你做架构师,要你在项目开发前期进行软件架构设计,你该如何开展你的工作?如何输出你的工作成果?如何确定你的设计是否满足用户需求?你是否有把握最后交付的软件是满足要求的?是否有把握让团队每个工程师清楚自己的职责范围并有效地完成开发工作……

这些问题其实都是软件开发管理与技术架构的核心诉求,而架构师的核心工作就是做好软件设计,解决这些诉求。这些问题搞定了,软件的开发过程和结果也就都得到了保证。那怎么实现这些诉求呢?我们主要的手段就是软件建模,以及将这些软件模型组织成一篇有价值的软件设计文档

软件建模

所谓软件建模,就是为要开发的软件建造模型。

模型是对客观存在的抽象,例如著名的物理学公式$E=mc^2$,就是质量能量转换的物理规律的数学模型。除了物理学公式以外,还有一些东西也是模型,比如地图是对地理空间的建模;机械装置、电子电路、建筑设计的各种图纸是对物理实体的建模。而软件,也可以通过各种图进行建模。

软件系统庞大复杂,通过软件建模,我们可以抽象软件系统的主要特征和组成部分,梳理这些关键组成部分的关系。在软件开发过程中依照模型的约束开发,系统整体的格局和关系就会可控。相关人员从始至终都能清晰了解软件的蓝图和当前的进展,不同的开发工程师会清晰自己开发的模块和其他同事工作内容的关系与依赖,并按照这些模型开发代码。

那么我们是根据什么进行软件建模的呢?要解答这个疑问,你需要先知道,在软件开发中,有两个客观存在。

一个是我们要解决的领域问题。比如我们要开发一个电子商务网站,那么客观的领域问题就是如何做生意,卖家如何管理商品、管理订单、服务用户,买家如何挑选商品,如何下订单,如何支付等等。对这些客观领域问题的抽象就是各种功能及其关系、各种模型对象及其关系、各种业务处理流程。

另一个客观存在就是最终开发出来的软件系统。软件系统要解决的问题包括软件由哪些主要类组成,这些类如何组织构成一个个的组件,这些类和组件之间的依赖关系如何,运行期如何调用,需要部署多少台服务器,服务器之间如何通信等。

而对这两个客观存在进行抽象化处理的手段,就是我们的软件模型。

一方面我们要对领域问题和要设计的软件系统进行分析、设计、抽象,另一方面,我们根据抽象出来的模型进行开发,最终实现出一个软件系统,这就是软件开发的主要过程。而对领域问题和软件系统进行分析、设计和抽象的这个过程,就是软件建模设计。

软件设计方法

因此,软件设计其实就是软件建模的过程。我们通过软件建模工具,将软件模型画出来,实现软件设计。

在实践中,通常用来进行软件建模画图的工具是UML,统一建模语言。UML包含的软件模型有10种,其中常用的有7种:类图、序列图、组件图、部署图、用例图、状态图和活动图。

下面我们简单了解下这7种常用UML图的使用场景和基本样例。在专栏后面的设计文档中,你会多次见到它们,看多了,你就懂了,也就自然会画了。当然,如果你想更详细地学习UML知识,我也非常鼓励,并且推荐你阅读马丁富勒的《UML精粹》一书。

类图

类图是最常见的UML图形,用来描述类的特性和类之间的静态关系

一个类包含三个部分:类的名字、类的属性列表和类的方法列表。类之间有6种静态关系:关联、依赖、组合、聚合、继承、泛化。把相关的一组类及其关系用一张图画出来,就是类图。

比如你在后面的课程中会遇到下面这幅图,它就是类图。你可以把我上面说的类图包含元素和图片一一对照,感受类图的用法。

时序图

类图之外,另一种常用的图是时序图,类图描述类之间的静态关系,时序图则用来描述参与者之间的动态调用关系

从图中可以看出,每个参与者有一条垂直向下的生命线。而参与者之间的消息从上到下表示其调用的前后顺序关系,这正是“时序图”这个词的由来。每个生命线都有若干个激活条,也就是那些细长的矩形条,只要这个条出现,就表示参与者是激活状态的。

时序图通常用于表示参与者之间的交互,这个参与者可以是类对象,也可以是更大粒度的参与者,比如组件、服务器、子系统等。总之,只要是描述不同参与者之间交互的,都可以使用时序图。

组件图

组件是比类粒度更大的设计元素,一个组件中通常包含很多个类。组件图有的时候和包图的用途比较接近,组件图通常用来描述物理上的组件,比如一个JAR、一个DLL等等。在实践中,我们进行模块设计的时候,用得更多的就是组件图。

组件图描述组件之间的静态关系,主要是依赖关系,如果你想要描述组件之间的动态调用关系,可以使用组件时序图,以组件作为参与者,描述组件之间的消息调用关系。

部署图

部署图描述软件系统的最终部署情况,比如需要部署多少服务器,关键组件都部署在哪些服务器上。

部署图是软件系统最终物理呈现的蓝图,根据部署图,所有相关者,诸如客户、老板、工程师都能清晰地了解到最终运行的系统在物理上是什么样子,和现有的系统服务器的关系,和第三方服务器的关系。根据部署图,还可以估算服务器和第三方软件的采购成本。

因此部署图是整个软件设计模型中,比较宏观的一种图,是在设计早期就需要画的一种模型图。根据部署图,各方可以讨论对这个方案是否认可。只有对部署图达成共识,才能继续后面的细节设计。

用例图

用例图通过反映用户和软件系统的交互,描述系统的功能需求

图中小人形象的元素,被称为角色,角色可以是人,也可以是其他的系统。系统的功能可能会很复杂,所以一张用例图可能只包含其中一小部分功能,这些功能被一个矩形框框起来,这个矩形框被称为用例的边界。框里的椭圆表示一个一个的功能,功能之间可以调用依赖,也可以进行功能扩展。

状态图

状态图用来展示单个对象生命周期的状态变迁

业务系统中,很多重要的领域对象都有比较复杂的状态变迁,比如账号,有创建状态、激活状态、冻结状态、欠费状态等等各种状态。此外,用户、订单、商品、红包这些常见的领域模型都有多种状态。

这些状态的变迁描述可以在用例图中用文字描述,随着角色的各种操作而改变,但是用这种方式描述,状态散乱在各处,不要说开发的时候容易搞错,就是产品经理自己在设计的时候,也容易搞错对象的状态变迁。

UML的状态图可以很好地解决这一问题,一张状态图描述一个对象生命周期的各种状态,及其变迁的关系。如图所示,门的状态有开Opened、关Closed和锁Locked三种,状态与变迁关系用一张状态图就可以搞定。

活动图

活动图主要用来描述过程逻辑和业务流程。UML中没有流程图,很多时候,人们用活动图代替流程图。

活动图和早期流程图的图形元素也很接近,实心圆代表流程开始,空心圆代表流程结束,圆角矩形表示活动,菱形表示分支判断。

此外,活动图引入了一个重要的概念——泳道。活动图可以根据活动的范围,将活动根据领域、系统和角色等划分到不同的泳道中,使流程边界更加清晰。

我们上面介绍了UML建模常用的7种模型,那么这7种模型分别应用在软件设计的什么阶段?用来表达什么样的设计意图呢?

软件设计文档

软件设计文档就是架构师的主要工作成果,它需要阐释这节课开头提到的各种诉求,描绘软件的完整蓝图,而软件设计文档的主要组成部分就是软件模型。

软件设计过程可以拆分成需求分析、概要设计和详细设计三个阶段。

需求分析阶段,主要是通过用例图来描述系统的功能与使用场景;对于关键的业务流程,可以通过活动图描述;如果在需求阶段就提出要和现有的某些子系统整合,那么可以通过时序图描述新系统和原来的子系统的调用关系;可以通过简化的类图进行领域模型抽象,并描述核心领域对象之间的关系;如果某些对象内部会有复杂的状态变化,比如用户、订单这些,可以用状态图进行描述。

概要设计阶段,通过部署图描述系统最终的物理蓝图;通过组件图以及组件时序图设计软件主要模块及其关系;还可以通过组件活动图描述组件间的流程逻辑。

详细设计阶段,主要输出的就是类图和类的时序图,指导最终的代码开发,如果某个类方法内部有比较复杂的逻辑,那么可以将这个方法的逻辑用活动图进行描述。

我们在每个设计阶段使用几种UML模型对领域或者系统进行建模,然后将这些模型配上必要的文字说明写入到文档中,就可以构成一篇软件设计文档了。

我们专栏中的十几讲软件设计案例,都是按照这样的方式组织的,你可以在学习的过程中,一方面了解各种系统软件是如何设计的,一方面也可以借鉴设计文档是如何写作的。

同时也要说明一下,设计文档的写法并没有一定之规,最重要的是这个文档能否向阅读者传递出架构师完整的设计意图。而不同的阅读者关注点是不同的,老板、客户、运维、测试、开发这些角色都是设计文档的阅读者,他们想要看到的东西显然是不一样的。

客户和测试人员可能更关注功能性需求和实现逻辑,老板和运维人员可能更关注非功能需求和整体架构,而开发人员可能更关注整体架构与关键技术细节。

我们专栏的案例基本上是以开发人员作为阅读视角进行编写的,你在阅读这些案例时,会明显感觉到我的表达方式和其他专栏文章不太一样,措辞会更“坚硬”一点,文字和读者的距离也有点“疏离”,而这正是设计文档自身的特质。

架构、系统,文档、相关人员之间的关系可以参考下面这张图。

每个软件系统都需要有一个架构,每个架构都包含若干架构元素。架构元素就是前面提到的服务器、组件、类、消息、用例、状态等等。这些元素之间的关系是什么?如何把它们组织在一起?我们可以用部署图、组件图、时序图等各种模型图来描述。

架构最终需要一个文档来承载,把这些模型图放进这个文档,再配以适当的文字说明,就是一篇架构设计文档。而设计文档是给人阅读的,这些人就是系统的相关方。不同的相关方关注点不同,也需要由不同的模型图来进行表达,所以架构师应该针对不同的相关方,使用不同的模型图输出不同的架构文档

上面这张图是关于架构的架构图,也就是说,是关于软件模型的模型。我们下一篇会讲高并发系统的方法论,而方法论是关于方法的方法。

小结

软件设计就是在软件开发之前,对要解决的业务问题和对要实现的软件系统进行思考,并将这个思考的结果通过软件模型表达出来的过程。

人类作为万物之灵,最大的特点就是,在行动之前就已经在头脑中将行动的过程和行动的结果构建成了一个蓝图,然后将这个蓝图付诸实践。我们的祖先将第一块石头打磨成石器的时候,就已经拥有了这种能力。软件系统的开发是一个复杂的智力活动,参与其中的我们更需要拥有构建蓝图并付诸实践的能力。

目前有个很火的词叫“元宇宙”,“元”通俗地讲,就是一切开始的地方,是关于如何用自己描述自己,是抽象之上的抽象。这种“元”能力对架构师而言,非常重要。架构师只有掌握各种技术背后的技术,了解各种问题背后的问题,才能超越当下的种种羁绊,设计出面向未来的架构。

思考题

假设时光倒流,你回到2003年,成为淘宝的架构师,你将如何设计淘宝的系统架构?请使用在线绘图工具www.draw.io 或者你熟悉的其他UML建模工具绘制满足淘宝早期应用场景的用例图以及部署图。如果你有什么灵感,或者遇到什么问题,欢迎在评论区留言,我们一起探讨。

也欢迎把这节课分享给更多对高并发架构设计感兴趣的朋友,我们共同进步。

(软考笔记) —— 系统架构设计师 - UML建模与架构文档化

UML建模与架构文档化

     UML(统一建模语言)一出现,以融合了多种面向对象建模方法,简洁的图形与符号,直观的表示和强大的表示能力,得到工业界与学术界认可。它通过统一的表示法,使不同知识背景的领域专家、系统分析和开发人员以及用户可以方便地交流。

UML 现状与发展

UML起源

     UML 成了实际上的工业标准。1996 年,一个由建模专家组成的国际性队伍"UML伙伴组织"开始同"三友"一起工作,计划将 UML提议作为 OMG(Object Management Group)的标准建模语言。最终草案,并于 1999年 6 月提交了一份最终报告。被推荐的规范随后被提交给组织委员会和平台技术委员会以获得批准。

UML 体系结构演变

     元模型的体系结构模式已被证明可以用来定义复杂模型所要求的精确语义,这种复杂模型通常需要被可靠地保存、共享、操作以及在工具之间进行交换。它的特点如下∶

  1. 它在每一层都递归地定义语义结构,从而使语义更精确、更加正规;
  2. 它可以用来定义重量级和轻量级扩展机制,如定义新的元类和构造类;
  3. 它在体系结构上将 UML. 元模型与其他基于 4 层元模型体系结构的标准(比如 MOF 和用于模型交换的 XMI Facility)统一起来。

     在元模型层,UML 元模型又被分解为三个逻辑子包;基础包、行为元素包和模型管理包。

  1. 其中基础包由核心、扩展机制和数据类型三个子包构成,它是描述模型静态结构的语言底层结构,支持类图、对象图和构件图和部署图等转构图。
  2. 行为元素包是描述模型动态行为的语言上层结构,支持不同的行为图,包括 Use Case(用况)图、顺序图、协作图、状态图和活动图。
  3. 模型管理包则定义了对模型元素进行分组和管理的语义,它描述了几种分组结构,包括包、模型和子系统。

UML1.3 解决UML1.1的遗留问题

  1. 完普活动图的语义和表示法 增加了状态的动态激发语义,定义了执行条件线程的语义和表示法,而且增加了对象流功能。为了做这些修订,还需要对活动图所依赖的状态机语义做以下修改∶为同步并发的活动加入"同步状态"、精化信号的语义、为合并状态转换定义附加的伪状态。
  2. 清理关系的标准元素。引入关系元类来组织各种类型的关系,并且把依赖构造型改造为依赖和流。此外,精练了泛化,不再需要以前的许多构造型(如继承、私有、子类、子类型等)。依赖和其他关系名称的一致性也有所改进。
  3. 体系结构的一致性。通过却入物理元模型和 XML(XML metadat lnterchange)、DTD(Docmemt Type Definition)定义,提高了UML 1.3 元模型的体系结构跟MOF 和XMFacility 的一致性。从 UML 语义逻辑元模型导出的物理元模型包含了一些支持产生IDL(Interface Definition Language)和 XML DTD 的修改(例如将关联类转化为类)。尽管这样做与严格的元模型方法相左,低它为未来 UML, 的修订达到这一目标提供了桥梁。

UML 的应用与未来

     UML 是在多种面向对象建模方法的基础上发展起来的建模语言,主要用于软件密集型系统的建模。总的来说目前的UML语言是一个庞大且一直在发展壮大的标准建模语言,能够在许许多多不同的领域提供各种不同的建模能力,当然UML目前也是存在一系列的缺点的,概括起来为:

  1. UML 己经取得重要成功,它已成为在软件工业中占支配地位的建模语言,并在许多领域的软件开发中得到应用。
  2. UML 还存在许多问题,自它产生之日起就从未离开过批评∶用户和教师抱怨它内容庞大、难学难教而且太过复杂;学者认为它缺少一个精练的核心和定义良好的外围,有些语义定义得不够精确而且带有二义性;建模实践者认为它缺少支持自己领域建模要求的机制;工具开发商则因为规范本身的不确定性而产生理解上的偏差,它们对 UML 的自行诠释有可能误导用户。
  3. UML 的关键问题是过于庞大和复杂,以及在语言体系结构、语义等方面存在理论缺陷。产生这些问题的一个重要原因是,在形成规范的过程中不得不照顾多种方法流派的观点和多家公司的利益。

UML基础

概述

     UML 通过图形化的表示机制从多个侧面对系统的分析和设计模型进行刻画。它共定义了10种视图,并将其分为以下4类:

  1. 用例图〔use case diagram)。从外部用户的角度描述系统的功能,并指出功能的执行者。
  2. 静态图。包括类图(class diagram)、对象图(object diagram)和包图(package diagram)。类图描述系统的静态结构,类图的节点表示系统中的类及其属性和操作,类图的边表示类之间的瘀系,包括继承、关联、依赖和聚合等。对象图是类图的一个实例,它描述在某种状态下或在某一时间段,系统中活跃的对象及其关系。包图描述系统的分解结构,它表示包(package)以及包之间的关系。包由子包及类组成。包之,间的关系包括继承、构成与依赖关系。
  3. 行为图,包括交互图(interactive diagram)、状态图(statechart diagram)与活动图(active digrwn),它们从不同的侧面刻画系统的动态行为。交互图描述对象之间的消息传递,它又可分为顺序图(sequence diagram)与合作图(collaboration diagram)两种形式。顾序图强识对象之间消息发送的时间序。合作图更强调对象间的动态协作关系。合作图也可通过消息序号来麦示消息传递的时间序,只不过这种表示不如颇序图那样直观。状态图描述类的对象的动态行为,它包含对象所有可能的状态、在每个状态下能够响应的事件以及事件发生时的状态迁移与响应动作。活动图描述系统为完成某项功能而执行的操作序列,这些操作序列可以并发和同步。活动图中包含控制流和信息流。
  4. 实现图(implementation diagram)。包括构件图(component diagramn)与部署图(deployment diagram),它们描述较件实现系统的组成和分布状况。构件图描述软件实现系统中各组成部件以及它们之间的依赖关系。部署图描述作为软件系统运行环境的硬件及网络的物理体系结构,其节点表示实际的计算机和设备,边表示节点之间的物理连接关系,也可显示连接的类型及节点之间的依赖性。

用例和用例图

     用例有两个比较具有代表性的定义:

  1. 用例是对一个活动者(actor)使用系统的一项功能时所进行的交互过程的一个文字描述序列;
  2. 用例是系统、子系统或类和外部的参与者(actor)交互的动作序列的说明,包括可选的动作序列和会出现异常的动作序列;

     用例分析可以支持领域建模(domaim modeling),以确保定义正确的需求(right requirements),是保证OO(面向对象)软件开发成功的基础。本质上,用例分析是一种功能分解(functional decomposition)的技术,并未使用到面向对象的思想。但用例是 UML 的重要部分,确定一个系统的用例是开发 OO 系统的第一步,用例分析这步做得好,接着的交互图分析、类图分析等才有可能做得好,整个系统的开发才能顺利进行。编写用例的人必须识别以下的元素:

参与者

     角色(actor)是指系统以外的、需要使用系统或与系统交互的东西,包括人、设备、外部系统等。actor有很多不同的译名,包括参与者、活动者、执行者和行动者等。

在这里插入图片描述
用例之间的关系

     用例除了与参与者有关联(association)关系外,用例之间也存在着一定的关系(relationship),如泛化(generalization)关系、包含(include)关系、扩展(extend)关系等。

在这里插入图片描述

  1. 包含关系:指的是两个用例之间存在一定的联系,其中某一个用例的行为是包含了另外一个用例的完整行为的过程,那么称之为包含关系。包含关系是依赖关系的版型,也就是说包含关系是比较特殊的依赖关系,它们比一般的依赖关系多一些语义。
  2. 扩展关系:其基本含义与泛化关系类似。但是在扩展关系中,对于扩展用例存在更多的规则来限制它制,即基本用例必须声明若干"扩展点"(exension poimt),而扩展用例只能在这些扩展点上增加新的行为和含义。

在这里插入图片描述
用例图

     用例图(use case diagram)是显示一组用例、参与者以及它们之间关系的图。在 UML中,一个用例模型由若干个用例图描述。如图所示,是一个电话系统使用的用例图:

在这里插入图片描述
用例和描述

     用例的描述才是用例的核心部分,用例采用自然语言插述参与者与系统进行交互时双方的行为,不追求形式化的语青表达。以下是一种典型的描述的方式。
在这里插入图片描述

交互图

     交互图{interaction diagram)是用来描述对象之间以及对象与参与者(actor)之间的动态协作关系以及协作过程中行为次序的图形文档。它通常用来描述一个用例的行为,显示该用例中所涉及的对象和这些对象之间的消息传递。交互图包括顺序图〈sequencediagram)和协作图(collaboration diagram)两种形式:

  1. 顺序图着重描述对象按照时间顺序的消息交换;
  2. 协作图着重描述系统成分如何协同工作;

顺序图

     顺序图也称时序图。Rumbaugh 对顺序图的定义是∶顺序图是显示对象之间交互的图,这些对象是按时间顺序排列的。特别地,顺序图中显示的是参与交互的对象及对象之间消息交互的顺序。

在这里插入图片描述
协作图

     协作图是用于描述系统的行为是如何由系统的成分协作实现的图,协作图中包括的建模元素有对象〔包括参与者实例、多对象、主动对象等)、消息,链等。

类图和对象图

在这里插入图片描述
     一般来说,类之间的关系有关联、聚集、组合、泛化和依赖等。

关联关系

     关联(association)是模型元囊间的一种语义联系,它是对具有共同的结构特性、行为特性、关系和语义的链(ink) 的描述。通过关联类(association clas)可以进一步描述关联的属性、操作以及其他信息。关联类通过一条虚线与关联连接。如图
所示Contract 类是一个关联类,Contract 类中有属性 salary,这个属性描述的是 Corpany 类和Person 类之间的关联的属性,而不是描述Company 类或 Person类的属性。

在这里插入图片描述
     自返关联(reflexive association)又称递归关联(recursive Engnepert association),是一个类与自身的关联,即同一个类的两个对象间的关系。

聚集和组合

     聚集(aggregation)是一种特殊形式的关联。聚集表示类之间整体与部分的关系,在对系统进行分析和设计的时候,需求中描述的“包含”、“组成”、“分为……部分”等词语都意味着存在聚集关系。

     组合(composition)表示的也是类之间的整体与部分的关系,但组合关系中的整体与部分具有同样的生存期。也就是说,组合是一种特殊形式的聚集。

泛化关系

     泛化(generalization)定义了一般和特殊元素之间关系,如果从面向对象程序设计语言的角度来说,类与类之间的泛化关系就是平常所说的类与类之间的继承关系。

     UML中用一头为空心三角形的连接线表示泛化关系。

依赖关系

     假设有两个元素 X、Y,如果修改元素 X 的定义可能会导致对另一个元素 Y 的定义的修改,则称元素 Y 依赖于元素 X。

类图

     类图以直观、抽象形式展示了不同对象之间关系。例如下面的学校关系的类图的案例:

在这里插入图片描述

状态和活动图

状态图

     UML 中的状态图(state chart diagram)主要用于描述一个对象在其生存期间的动态行为,表现一个对象所经历的状态序列,引起状态转移的事件(event),以及因状态转移而伴随的动作(action)。。状态图是 UML 中对系统的动态行为建模的5个图之一,状态图在检查、调试和描述类的动态行为时非常有用。一般可以用状态机对一个对象的生命周期建模,状态圈是用予显示状态机的,重点在于描述状念之间的控制流。下面是一个简单的状态图的切换过程的例子:

在这里插入图片描述

活动图

     活动图是对系统的动态行为建模的 5 个图之一。活动图可以用于描述系统的工作流程和并发行为。活动图其实可看作状态图的特殊形式,活动图中一个活动结束后将立即进入下一个活动(在状态图中状态的转移河能需要事件的触发)。下面是一些关于活动图中的一些基本概念的描述和介绍:有活动、泳道、分支、分叉和汇合、对象流。

活动

     活动(activity)表示的是某流程中的任务的执行,它可以表示某算法过程中语句的执行。在活动图中需要注意区分动作状态(action stat)和活动状态(activity state)这两个概念。动作状态是原子的,不能被分解,没有内部转移,没有内部活动,动作状态的工作所占用的时间是可忽略的。动作状态的目的是执行进入动作(enty action),然后转向另一个状态。活动状态是可分解的,不是原子的,其工作的完成需要一定的时间。可以把动作状态看作活动状态的特例。

泳道

     泳道(swimlane)是活动图中的区域划分,根据每个活动的职责对所有活动进行划分,每个泳道代表一个贵任区。泳道和类并不是——对应的关系,泳道关心的是其所代表的职责,一个泳道可能由一个类实现,也可能由多个类实现。

分支

     在活动图中,对于同一个触发事件,可以根据不同的警戒条件转向不同的活动,每个可能的转移是一个分支(branch)。

分叉和汇合

     分支表示的是从多种可能的活动转移中选择一个,如果要表示系统或对象中的并发行为,则可以使用分叉(fork)和汇合(jom)这两种建模元囊。分叉表示两个或多个控制流经过分叉后,这些控制流并发进行;汇含正好与分叉相反。

对象流

     在活动图中可以出现对象。对象可以作为活动的输入或输出。活动圈中的对象流表示活动和对象之间的关系,如一个活动创建对象〈作为活动的输出)或使用对象(作为活动的输入)等。

在这里插入图片描述

构件图

     构件(componcnt)是系统中遵从一组接口且提供其实现的物理的、可替换的部分。构件图(componentdiagram)则显示一组构件以及它们之间的相互关系,包括编译、链接或执行时构件之间的依赖关系。下图是一个构件图的例子,表示.html文件、.exe文件、.dll文件这些构件之间的关系。

在这里插入图片描述
     构件其实就是一个实际的文件,可以分为以下几种类型:

  1. 部署构件(deployment component)):如 dll文件、exe 文件、COM+对象、CORBA对象、EJB、动态 Web 页和数据库表等。
  2. 工作产品构件(work product component) :,如源代码文件、数据文件等,这些构件可以用来产生部署构件。
  3. 执行构件(execution component) : 系统执行后得到的构件。

     构件图可以从以下几个方面进行建模:

  1. 对源代码文件之间的相互关系建模,如下图1所示;
  2. 对可执行文件之间的相互关系建模,如下图2所示;

在这里插入图片描述
在这里插入图片描述

部署图

     部署图也称为配置图、实施图,它可以用来显示系统中计算节点的拓扑结构和通信路径与节点上运行的软件构件等。一个系统只有一个部署图,部署图通常用于帮助理解分布式系统。下图是一个部署图的例子:

在这里插入图片描述

基于UML的软件开发过程

软件开发过程概述

     UML是独立于软件开发过程的,即 UML 能够在几乎任何一种软件开发过程中使用。迭代的渐进式软件开发过程包含 4 个阶段,即初启、细化、构建和部署。

初启

     在初启阶段,软件项目的发起人确定项目的主要目标和范围,并进行初步的可行性分析和经济效益分析。

细化

     细化阶段的开始标志着项目的正式确立。软件项目组在此阶段需要完成以下工作∶

  1. 初步的需求分析:采用 UML 的用例描述目标软件系统所有比较重要、比较有风险的用例,利用用例图表示参与者与用例以及用例与用例之间的关系。
  2. 初步的高层设计:如果目标软件系统的规模比较庞大,那么经初步需求分析获得的用例和类将会非常多。此时,可以考虑根据用例、类在业务领域中的关系,或者根据业务领域中某种有意义的分类方法将整个软件系统划分为若干个包,利用 UML 的包图刻画这些包及其间的关系。
  3. 部分的详细设计:对于系统中某些重要的或者风险比较高的用例,可以采用交互图进一步探讨其内部实现过程。同样,对于系统中的关键类,也可以详细研究其属性和操作,并在 UML 类图中加以表现。
  4. 部分的原型构造:在许多情形下,针对某些复杂的用例构造可实际运行的原型是降低技术风险、让用户帮助软件项目组确认用户需求的最有效的方法。为了构造原型,需要针对用例生成详尽的交互图,对所有相关类给出明确的属性和操作定义。

     综上所述,在细化阶段可能需要使用的 UML 语言机制包括描述用户需求的用例及用例图、表示领域概念模型的类图、表示业务流程处理的活动图、表示系统高层结构的包图和表示用例内部实现过程的交互图。

构建

     在实际开始构造软件系统之前,有必要预先制定迭代计划。计划的制定需遵循如下两项原则∶

  1. 用户认为业务价值比较大的用例应优先安排;
  2. 开发人员评估后认为开发风险较高的用例应优先安排;

     在迭代计划中,要确定迭代次数、每次迭代所需时间以及每次迭代中应完成(或部分完成)的用例。每次迭代过程由针对用例的分析、设计、编码、测试和集成5个子阶段构成。在集成之后,用户可以对用例的实现效果进行评价,并提出修改意见。

     综上所述,在构建阶段可能需要使用的 UML 语言机制包括∶

  1. 用例以及用例图:它们是开发人员在构建阶段进行分析和设计的基础;
  2. 类图:在领域概念模型的基础上引进为软件实现所必需的类、属性和方法;
  3. 交互图:表示针对用例设计的软件实习方法;
  4. 状态图:表示类的对象的状态-事件-响应行为;
  5. 活动图:表示复杂的算法过程,尤其是过程中的并发和同步;
  6. 包图:表示目标软件系统的顶层结构;
  7. 构件图;
  8. 部署图;

部署

     在部署阶段,开发入员将构造阶段获得的软件系统在用户实际工作环境(或接近实际的模拟环境)中试运行,根据用户的修改意见进行少量调整。

基于UML的需求分析

在这里插入图片描述

     在初步的业务需求描述已经形成的前提下,基于UML 的需求分析过程大致可分为以下步骤:

  1. 利用用例以及用例图表示需求。从业务需求描述出发获取执行者和场景;对场景进行汇总、分类、抽象,形成用例∶确定执行者与用例、用例与用例图之间的关系,生成用例图。
  2. 利用包图及类图表示目标软件系统的总体框架结构。根据领域知识、业务需求描述和既往经验设计目标软件系统的顶层架构;从业务需求播述中提取"关钱慨念",形成领址概念模型;从概念模型和用例出发,研究系统中主要的类之间的关系,生成类图。

生成用例

     从外部用户的视角看,一个用例是执行者(actor)与目标软件系统之间的一次典型的交互作用。从软件系统内部的视角出发,一个用例代表系统执行的一系列动作,动作执行的结果能够被外部的执行者所察觉。例如我们可以参考如下的用例:

在这里插入图片描述
用活动图表示用例

     针对前面所述的"传感器监测"用例,其活动图表示如图所示。
在这里插入图片描述
生成用例图

     执行者与用例之间的关系有两种∶触发执行与信息交换。执行者与用例之间可能兼具这两种关系。在 UML 用例图中,从执行者指向用例的边表示触发执行和/ 或信息交换,从用例指向执行者的边则表示用例将其生成的信息传递给执行者。

建立顶层架构

     顶层架构的主要目的是为后续的分析和设计活动建立一种结构和分划,以便开发人员在不同的开发阶段,以及同一开发阶段的不同开发人员,能够聚焦于系统的不同部分。

UML包图

     包是 UML 对类进行分组的一种机制。可以从某种视角将具有比较密切的关联的一些类划分为一个包,分属于不同包的两个类之间的关联则比较松散。由此可见,对于大型软件系统而言,包的划分是实现"分而治之"的重要技术手段。包之间存在两种依赖关系:依赖和构成。包之间存在两种依赖关系∶依赖和构成。如果对类 A 的修改将导致类 B 的改变,则称B依赖于A。如果两个包中存在具有依赖关系的两个类,则认为这两个类分属的包之间存在依赖关系。

顶层架构设计

     软件系统顶层架构的基本方法是,结合实际需求,从既往的架构设计经验模式中选取适当者,再进行微调或局部改造。目前有如下几种主要的架构模式:

  1. 流程处理模式:流程处理系统以算法和数据结构为中心,其系统功能由一系列的处理步骤构成,相邻的处理步骤之间以数据流通管道相互连接。
  2. 客户/服务器模式:客户端负责用户输入和处理结果的呈现,服务器端负责后台的业务逻辑处理。
  • 模型——视图——控制器(Model、View、Controller,MVC)模式:该模式将整个软件系统划分为模型、视图和控制器三个部分。模型负责维护并保存具有持久性的业务数据,实现业务处理功能,并将业务数据的变化情况及时通知视图;视图负责呈现模型中包含的业务数据,响应模型变化通知,更新呈现形式,并向控制器传递用户的界面动作;控制器负责将用户的界面动作映射为模型中的业务处理功能并实际调用之,然后根据模型返回的业务处理结果选择新的视图。MVC模式特别适合于分布式应用软件,尤其是 Web 应用系统。
  • 分层模式:分层模式将整个软件系统分为若干层次,最顶层直接面向用户提供软件系统的操作界面,其余各层为紧邻其上的层次提供服务。分层模式可以有效地降低软件系统的耦合度,因此其应用十分普遍。

     事实上,大型软件的顶层架构往往需要符合使用多种架构样式,在确立顶层架构的过程中需要综合考虑一下因素:

  • 架构中包的数量: 原则上,如果母个包中包含的软件元素(例如类)的数量过多,应考虑将其进一步细分;如果过少,则说明架构过早地陷入了细节,架构划分返工的可能性较大,同时也不合理地限制了后续分析和设计活动的自由空间。
  • 架构中包之间的耦合度:包之间的依赖关系和连接关系应尽量简单、稀疏。
  • 软件系统的稳定性:要尽量抽取不稳定的软件元素之中相对稳定的部分,将不稳引起的软件元素分类聚集于少数几个包中,以提高软件系统的可维护性。
  • 软件系统的必然性:可以将可选功能和必须实现的功能分置于架构中不同的包或子包之中。
  • 作为软件系统运行环境的物理网络拓扑。根据软件元素在分布环境中的部署情况。区分顶层架构中的包,可以使包之间的消息传递与物理节点之间的通信相吻合,使后续的分析和设计活动受益于顶层架构中明确定义的通信关系。
  • 软件元素的安全、保密级别:根据安全访问的权限划分顶层架构中的包或者子包。
  • 开发团队的技术专长。根据开发人员在问题领域和软件技术领域不同的专长划分顶层架构中的包,使每个包都能分配给最适合的开发人员进行后续的分析、设计、编码和测试等,从而有利于并行开发。

建立概念模型

     “家庭保安系统”的概念模型如下图所示:

在这里插入图片描述

对象的设计方法

     面向对象的软件设计过程如图所示:

在这里插入图片描述
设计用例实现方案

     UML 的交互图(顺序图、协作图)适于用例实现方案的表示。该设计方法包含如下三个步骤:

  • 提取边界类、实体类和控制类。

     边界类用于描述目标软件系统与外部环境之间的交互,并负责实现如下的功能:

  1. 界面控制。包括输入数据的格式及内容转换、输出结果的呈现以及软件运行过程中界面的变化写切换等。
  2. 外部接口。实现目标软件系统与外部系统或外部设备之间的信息交流和互操作。主要关注跨越目标软件系统边界的通信协议。
  3. 环境隔离。将目标软件系统与操作系统、数据库管理系统、应用服务器中间件等境软件进行交互的功能与特性封装于边界类之中,使目标软件系统的其余部分尽可能地独立于环境软件。

在 UML 类图中,边界类往往附加 UAL 构造型<< boumdary >>作为特别标识。

  • 构造交互图

     UML 交互图,以交互图作为用例的精确实现方案。对于比较复杂的用例而言,仅仅依靠控制类、边界类和实体类并不能很好地解决问题,因为我们不能使单个控制类过于庞大和复杂,让它既承担控制、协调的任务,又承担复杂的计算任务。因此,在设计复杂用例的实施方案时,应考虑为控制类设置一些独立的辅助类,让控制类将一些任务委托给辅助类完成。那么,典型布局规则下的顺序图如图所示:

在这里插入图片描述

  • 根据交互图精化类图

     在 UM 交互图中,对每个类的对象都规定了它必须响应的消息以及类的对象之间的消息传递通道。前者对应于类的操作,后者则对应于类之间的连接关系。因此,可以利用交互图精化分析模型中的类图,将交互图中出现的新类添加到原有类图中,并日对相关的类进行精化,定义其属性和操作。

设计技术支撑方案

     在许多软件项目中,应用功能往往都需要一组技术支撑机制为其提供服务。技术支撑方案应该为多个用例的软件实现提供技术服务,所以,它应该成为整个目标软件系统中全局性的公共技术平台。当用户需求发生变化时,技术支撑方案应具有良好的稳定性。这就要求软件设计者选用开放性和可扩充性较好的技术支撑方案。如果目标款件系统的顶层架构采用分层方式,那么技术支撑方案应该位于层次结构中的较低层次。技术支撑方案的设计一方面取决于目标软件系练对公共技术服务的需求。另一方面取决于设计人员对软件技术手段的把握和选取。

设计用户界面

     用户界面设计的策略与步骤如下∶

  1. 熟悉用户并对用户分类。设计人员应深入用户环境,考虑用户需要完成的任务、完成这些任务需要什么工具支持以及这些工具对用户是否适用。事实上,不同类型的用户要求也不同,一般可按技术熟练程度、工作性质和访问权限对用户进行分类,以便尽量照顾到所有用户的合理要求,并优先满足某些特权用户。
  2. 按用户类别分析用户的工作流程与习惯。在用户分类的基础上,从每类中选取一个用户代表,建立包括内容的调查表,并通过对调查结果的分析判断用户对操作界面的需求和喜好。
  3. 设计命令系统并优化。在设计一个新命令系统时,应尽量遵循用户界面的一般原则和规范,必要时可参考一些优秀的商品软件。根据用户分析结果确定初步的命令系统,然后再优化。命令系统既可为若干菜单、菜单栏,也可为一组按钮。
  4. 设计用户界面的各种细节。此步骤包括设计一致的用户界面风格、耗时操作的状态反馈、undo 机制、帮助用户记忆的操作序列和自封闭的集成环境等。
  5. 增加用户界面专用的类与对象。用户界面专用类的设计与所选用的图形用户界面(GUI)工具或者支持环境有关。一般而言,需要为窗口、菜单、对话框等界面元素定义相应的类,这些类往往继承自 GUI工具或者支持环境提供的类库中的父类。最后,还需要针对每个与用户命令处理相关的界面类,定义控制设计模型中的其他类的方法。

     利用快速原型演示,改进界面设计。为人机交互部分构造原型,是界面设计的基本技术之一。为用户演示界面原型,让他们直观感受目标软件系统的使用方法,并评判系统是否功能齐全、方便好用。

精细化设计模型

     对模型进行改进的活动可以分为精化和合并两种,一般先从精化开始。首先,由干初始架构模型已经包括了总原则和层结构两部分的内容。现在要做的工作是根据需求和架构原则来划分不同的粗粒度组件。粗粒度组件来源于分析活动中的业务实体。把具有很强相关性业务实体组合起来,形成一个集合。集合内部存在错综复杂的关系,同时集合向外部提供服务接口。这样的集合就称为粗粒度组件。粗粒度组件对外的接口和内部的实现是相区分的。

     在得到了粗粒度组件模型之后,我们需要对其进行进一步的分析,以得到细粒度的组件。细粒度的组件具有更好的重用性,并使得架构设计的精化工作更进一步。按Jacobgon推荐的面向对象软件工程(Object Oriented Software Enginerring,OOSE)的做法,我们需要从软件的目标领域中识别出关键性的实体,或者说是领域中的名词。

系统架构文档化

模型概述

     软件架构用来处理软件高层次结构的设计和实施。它以精心选择的形式将若干结构元素进行装配,从而满足系统主要功能和性能需求,并满足其他非功能性需求,如可靠性、可伸缩性、可移植性和可用性。Perry 和 Wolfe 使用一个精确的公式来衰达,该公式由 Boehm 做了进一步修改。

软 件 架 构 = 元 素 , 形 式 , 关 系 / 约 束 软件架构={元素,形式,关系/约束} =/

     软件架构涉及到抽象、分解和组合、风格和美学。我们用由多个视图或视角组成的模型来描述它。为了最终处理大型的、富有挑战性的架构,该模型包含 5个主要的视图如图所示:

在这里插入图片描述

  • 逻辑视图:设计的对象模型(使用面向对象设计方法时);
  • 过程视图:捕捉设计的并发和同步特征;
  • 物理视图:描述了软件到硬件的映射,反映了分布式特性;
  • 开发视图:描述了在开发环境中软件的静态组织结构;

     架构的描述,即所做的各种决定,可以围绕着这 4个视图来组织,然后由一些用例(use cases)或场景(scenarios)来说明,从而形成了第 5个视图。正如将看到的,实际上软件架构部分从这些场景演进而来。

逻辑结构

     逻辑架构主要支持功能性需求,那在为用户提供服务方面系统所应该提供的功能。系统分解为一系列的关键抽象,(大多数)来自于问题域,表现为对象或对象类的形式。它们采用抽象、封装和继承的原理。分解并不仅仅是为了功能分析,而且用来识别遍布系统各个部分的通用机制和设计元囊。我们使用 Ratiomal/ooch 方法来表示逻辑架构,借助于类图和类模板的手段。类图用来显示一个类的集合和它们的逻辑关系,关联、使用、组合、继承等。相似的类可以划分成类集合,基本的逻辑蓝图表示法如图所示。

在这里插入图片描述
逻辑视图风格

     逻辑视图的风格采用面向对象的风格,其主要的设计准则是试图在整个系统中保持单一的、一致的对象模型,避免就每个场合或过程产生草率的类和机制的技术说明。

逻辑结构蓝图的样例

在这里插入图片描述

进程架构

     进程架构考虑一些非功能性的需求,如性能和可用性。它解决并发性、分布性、系统完整性、容错性的问题,以及逻辑视图的主要抽象如何与进程结构相配合在一起——即在哪个控制线程上,对象的操作被实际执行。

     接着,我们可以区别主要任务、次要任务。主要任务是可以唯一处理的架构元素;次要任务是由于实施原因而引入的局部附加任务(如周期性活动、缓冲、暂停等)。主要任务的通讯途径是良好定义的交互任务通信机制∶基于消息的同步或异步通信服务、远程过程调用、事件广播等。次要任务则以会见或共享内存来通信。在同一过程或处理节点上,主要任务不应对它们的分配做出任何假定。消息流、过程负载可以基于过程蓝图来进行评估,同样可以使用哑负载来实现"中空"的进程架构,并测量在目标系统上的性能。正如Filarey etal 在他的 Eurocontrol实验中描述的那样。

在这里插入图片描述

开发架构

     开发架构关注软件开发环境下实际模块的组织。软件打包成小的程序块(程序库或子系统),它们可以由一位或几位开发人员来开发。子系统可以组织成分层结构,每个层为上一层提供良好定义的接口。系统的开发架构用模块和子系统图来表达,显示了"输出"和"输入"关系。完整的开发架构只有当所有软件元素被识别后才能加以描述。但是,可以列出热制开发架构的规则∶分块、分组和可见性。

     大部分情况下,开发架构考虑的内部鹅求与以下几项因紊有关∶开发难度、软件管理、重用性和通用性及由工具集、编程语言所带来的限制。关于开发视图的风格,推荐使用分层(layered)的风格,定义 4~6个子系统层。每层均具有良好定义的职责。设计规则是某层子系统依赖同一层或低一层的子系统,从而最大程度地减少了具有复杂模块依赖关系的网络的开发量,得到层次式的简单策略。

在这里插入图片描述
     第一层和第二层组成了独立于域的覆盖整个产品线的分布式基础设施,并保护其免受不同硬件平台、操作系统或市售产品(如数据库管理系统)的影响。第三层为该基础设施增加了 ATC(Adaptive Transfom Coding,自适应变换编码方法)框架,形成一个特定领域的软件架构(domain-specific sofware architecture)。使用该框架,可以在第四层上构建一个功能选择板。层次5则非常依赖于客户和产品,包含了大多数用户接口和外部系统接口。72 个子系统分布于5个层次上,每层包食了10~50个模块,并可以在其他蓝图上表示。

物理架构

     物理架构主要关注系统非功能性的需求,如可用性、可靠性(容错性),性能(吞吐量)和可伸缩性。物理蓝图的表示方法如上图所示:

在这里插入图片描述
     TRW(Thompson Ramo Wooldridge Lnc)公司的 UNAS(Universal NetworkArchitecture Services)提供了数据驱动方法将过程架构映射至物理架构,该方法允许大量的映射的变更而无需修改源代码。

在这里插入图片描述
     下面两个图显示了两种不同的物理架构上的进程映射,分别对应的是一个小型和一个大型PABX
在这里插入图片描述
在这里插入图片描述

场景

     4种视图的元素通过比较少的一组重要场景(更常见的是用例)进行无缝协同工作。关于场景的例子里,显示了对于小型PABX的场景片段,相应的脚本如下:

在这里插入图片描述

  1. Joe 的电话控制器检测和校验摘机状态的变换,并发送消息唤醒相应的终端对象。
  2. 终端分配一些资源,并要求控制器发出拨号音。
  3. 控制器接收拨号并传递给终端。
  4. 终端使用拨号方案来分析数字流。
  5. 有效的数字序列被键入,终端开始会话。

迭代过程

     在进行文档化时,提倡一种更具有迭代性质的方法———架构先被原形化、测试、估量、分析,然后在一系列的迭代过程中被细化。该方法除了减少与架构相关的风险之外,对于项目而言还有其他优点∶团队合作、培训,加深对架构的理解,深入程序和工具等(此处提及的是演进的原形,逐渐发展成为系统,而不是一次性的试验性的原形)。这种迭代方法还能够使需求被细化、成熟化并能够被更好地理解。

场景驱动(scenario-driven)的方法

  • 开始阶段
  1. 基于风险和重要性为某次迭代来选择一些不同的场景,场景可能是被归纳为对若干用户的需求的抽象。
  2. 形成"褶草人式的架构"。然后对场景进行"描述",以识别主要的抽象(类、机制、过程、子系统)。
  3. 所发现的架构元素被分布到4个蓝图中,即逻辑蓝图、进程蓝图、开发蓝图和物理蓝图。
  4. 然后实施、测试、度量该架构,这项分析可能检测到一些缺点或潜在的增强要求。
  5. 捕获经验教训。
  • 循环阶段
  1. 下一个迭代过程开始进行。
  2. 重新评估风险。
  3. 扩展考虑的场景选择板。
  4. 选择能减轻风险或提高结构覆盖的额外的少量场景。
  5. 然后试着在原先的架构中播述这些场景。
  6. 发现额外的架构元素,或有时还需要找出适应这些场贯所需的重要架构变更。
  7. 更新 4个主要视图;逻辑视图、进程视图、开发视图和物理视图。
  8. 根据变更修订现有的场景。
  9. 升级实现工具(架构原型)来支持新的、扩展了的场景集合。
  10. 测试。如果可能的话,在实际的目标环境和负载下进行测试。
  11. 然后评审这5 个视图来检测简洁性、可重用性和通用性的潜在问题。
  12. 更新设计准则和基本原理。
  13. 捕获经验教训。
  14. 终止循环。

个人格言

用心去感受你自己需要坚持的生活,未来慢慢会给你答案的。

在这里插入图片描述

以上是关于2 01 | 软件建模与文档:架构师怎样绘制系统架构蓝图?的主要内容,如果未能解决你的问题,请参考以下文章

李智慧 · 高并发架构实战课课程大纲

架构师之路 — 软件架构 — 架构软件的过程

软件架构师UML简介

[架构之路-96]:《软件架构设计:程序员向架构师转型必备》-6-需求与用户用例User Case/Senario建模

(软考笔记) —— 系统架构设计师 - UML建模与架构文档化

(软考笔记) —— 系统架构设计师 - UML建模与架构文档化