目前,ROPES已经成为应用广泛、能成功构建具有不同复杂度系统的手段,适合于个人从事的小项目或数百名开发人员参加的大型软件项目。在大型嵌入式软件工程中,必须保证数量庞大的需求在分析和设计中得以正确实施,并且将大型复杂系统中出现的大量细节联系起来。本文介绍的ROPES线程将有助于(中国)工程师开发复杂的嵌入式软件系统。
Bruce Powel Douglass
I-Logix公司
Email: bpd@
面向对象的设计是整个开发线程的重要一环,工程师普遍关心的问题是:如何有效地应用统一建模语言UML?要创建何种任务图(artifact)?何时采用状态表?如何从结构化的方法向ROPES方法转移?ROPES是嵌入式系统设计中面向对象的高速线程(process),优良的设计开发线程将加速你的设计进度。
这些问题都关心UML线程的应用而不是UML本身。事实上,线程的好坏是设计优化的关键,本文将对于嵌入式系统设计线程的优化作深入的讨论。
为什么要关心线程
作为一个软件开发工程师或嵌入系统开发人员,线程的意义在于能有效地实现以下目标:1.在产品的开发和交付线程中为工作人员提供一个项目模板。 2. 从以下几方面提高产品的质量:a. 减少缺陷的数量;b. 降低缺陷的严重性;c. 提高可重用性;d. 稳定性和可维护性。3. 从以下几方面提高项目的可预期性:a. 开发所需的投入;b. 开发时间安排;4. 与不同的项目管理者进行适当的项目信息交流。
如果一个线程不能达到上述目标,那么它就不是一个好的线程,应该进行修正和优化。
ROPES中将线程定义为由一组相互协作的设计人员所执行的一系列任务的集合,这些行为将产生一系列相应的目标结果,其中之一就是实现符合设计要求的系统。
线程由不同角色的设计人员组成,各角色执行各种不同的项目行为(activity),每种行为产生一种或多种任务图。一般在设计开始之前需要对设计进行技术规范的设定,该部分由专人完成。其结果是规范要求、一系列用例(use case)以及详细的序列图表(任务图)。一个完整线程的设定步骤更多,如图1所示。
一个线程要具有弹性,既可有效地应用于单人完成的小项目,也可应用于由数百名开发人员参加的大型项目,做到这点并不容易。通过定义一系列核心行为、工作人员角色和任务图以及许多可选行为、人员角色和任务图可以实现这样的进程。这些共有特性可以定义为一组ROPES类。
多级进程规划和管理
在过去的20年里,尽管多级进程规划和管理(waterfall lifecycle)一直受到相当激烈的批评,但是迄今为止它仍然是用于项目计划和管理的一种最普遍的方法。然而,由于它会在开发线程中产生一些问题,实际上没有任何项目完全遵循这一进程。多级进程规划和管理最根本的问题是,在线程的后期才能发现或修正线程前期引入的缺陷。在规范和架构方面产生的缺陷尤为严重,因为这种缺陷的影响范围很宽,系统的其它部分也会受到该部分的影响。为了消除这种缺陷的影响,有必要查出系统中所有会受到这种缺陷影响的部分。由于多级进程规划和管理在进程结束时才进行测试,这是一个固有的缺点。
为减少或消除多级进程规划和管理中存在的问题,螺旋式或迭代式进程规划和管理逐渐受到欢迎。螺旋式进程的根本优点是在早期进行频繁的系统测试,因此能较早发现重大缺陷,从而减少重复工作。这是通过将开发项目分解为一系列较小的子项目而实现的,通过编排,一个子项目构建在它前面的子项目的基础之上,而它自身也为后面的那些子项目提供构建部件,从而形成一种“螺旋”结构。在这里,每个子项目的影响范围更加有限,其生成也更容易,子项目的任务重点也更为明确。从每个子项目或螺旋式项目可以得到一个迭代的原型,它是一个高质量的功能系统,尽管它并不十分完整。然而,这一原型确实正确实现了一部分需求并/或降低了出错风险。
ROPES线程同时在三个不同的等级或时间段上进行,它们是宏周期(macrocycle)、微周期(microcycle)和纳周期(nanocycle)。宏周期的时间跨度可以是几个月甚至几年,包括从概念生成到最后交付的整个开发线程。ROPES的宏线程包括四个互相交叠的阶段,而每个宏阶段(marcophase)实际上包含多个微周期,每个微周期之后生成一个迭代的原型。
微周期要比宏周期短得多,通常从四个星期到六个星期。它主要用于生成和推出一个有限功能的设计原型,主要处理一个或几个用例,但也有可能包含特定的降低风险的功能。
纳周期的时间跨度最小,一般为30分钟到一天。在纳周期中,设计思路要进行每天几次的反复尝试、建模、执行和修改。图2所示为标准的ROPES周期模型。
基于诸多原因,真正的螺旋式模型对于某些企业而言可能并不是很理想,或者并不实用,通常的原因是由于客户的需求(要求遵守DoD 2167A),或者由于螺旋式模型这种设计思想不符合当前的商业氛围。对于这些企业,ROPES线程也为它们提供了另一种线程规划和管理方法,即半螺旋式方法,如图3所示。
由于需求分析和系统工程并不属于整个大螺旋线程的一部分,所以称之为半螺旋线程。从内部来看,它们确实是以一种螺旋方式工作的,然而一旦各部分生成了自己的任务图,该部分将不会再作任何改动。工程以及子系统模型部分确实是以一种螺旋方式实现的,而且常常将多个学科的子系统整合在一起。对于习惯使用多级线程规划和管理来开发大型系统的组织,通常更喜欢采用这种半螺旋式方法,它具有全螺旋式线程规划和管理的某些好处。在半螺旋式线程规划和管理中,确实存在着系统设计的变化和反复,但是如果当系统中存在未知因素或出现需求变化时,螺旋式线程规划和管理就不具备足够的弹性来适应这种变化,所以在子系统开发小组启动工作之前,必须保证高层系统工程模型已经确定下来。
螺旋微周期
图4为标准的ROPES微周期。与大多数其他螺旋线程相比,ROPES螺旋线程的不同有两点:首先,要注意分析中的系统工程的子阶段(subphase)。这个子阶段并不总是必要的,但对于复杂的软件系统,或者具有硬件和软件的协同设计,必须配备这个子阶段。系统工程对一个高级子系统或组成架构进行识别,并将系统级的用例分解为映射到单个子系统的子系统级用例。然后,这些子系统再被进一步分解为软件、电子、机械以及化学工程等各种不同的学科。
在分组阶段对项目进行初始规划,并对进行中的线程进行改进以及对项目重新定位。这个阶段将确定最初的所有原型,当然在进行需求分析之后,其具体内容才能完全定义。一般的原则是,原型应该每隔三周到六周时间计划一次。在最初的规划中还应该制定软件开发计划、配置管理计划以及复用计划等等,以便开发小组能够知道完成工作的过程。
需求子阶段(requirement subphase)确定需求,将它们归纳为用例、脚本、状态图以及约束条件。在整个螺旋进程中,通常在第一次迭代时将所有或大多数用例确定下来。但是,在每一个螺旋线程中,只对少数(1到3个)用例进行深入的研究。在半螺旋模型中,将需求和系统工程子阶段去掉,但是在每个螺旋线程期间都要进行对象分析。在原型中还可能加入一些降低风险的行为和目标,例如在对特定编译器或中间件的性能进行研究时。
然后,系统工程子阶段识别整个系统的子系统和/或构件,并利用“includes”和“extends”用例关系,将系统用例分解为子用例(sub-use case)。每个子系统级用例都分别映射到单个子系统。然后再通过子系统集配合来实现系统用例。各子系统使用它自己的子系统级用例(从系统级用例获得)和它的接口规范来说明。子系统分解的充分性可以通过在每次降阶分解时执行递归调用的简单规则检验而得知。
当且仅当在使用新的更详细的抽象集合能够实现所有的n-1阶脚本时,n阶结构模型才是充分的。这意味着,当所有系统级脚本(用执行机构1和系统来定义)可以使用新确定的子系统来实现时,这个子系统结构模型是充分的。这些修改后的脚本与前一抽象级的描述呈现相同的特性。
系统工程中的下一个步骤是将子系统分解为单一学科(软件、机械、电子和化学)构件,并弄清楚这些单一学科构件之间的相互作用,这常称为“硬件-软件分解”。
对象分析子阶段属于软件范畴,它要确定对解决问题至关重要的对象。例如,如果要构建一个导航系统或子系统,则基准点、向量、位置等信息都是必不可少的构件,可行性方案中要包括这些内容。每个用例通过一系列相互配合的对象来实现,对象确定过程中,每个用例使用一次。对象分析也将这些对象具体化为各种类,然后确定它们之间的结构关系,并定义它们之间相互配合以及单独的行为特征。
一种可选的方法是每次给对象指定一个域(domain)。在ROPES中,“域”是由通用指令表构成的从属事件的集合。实时和嵌入式系统中的典型域为用户接口、器件I/O、报警管理以及总线通信。系统的每一个语义类都可归入一个单独的域,实际上,所有的广义层也可归入一个单独的域。域使用UML数据包来建模,并可在内部分解为子包以便于管理。域还负责组织ROPES中称为逻辑模型的系统类型和级别,这一点与物理模型不同,在运行时物理模型负责组织对象、子系统和构件。
如果说分析是定义一个系统的本质属性,设计则是选择一种特定的解决方案,设计是对系统和项目的服务需求质量进行最优化。需求有两种,即功能需求以及服务质量(QoS)需求。QoS需求定义某种功能被实现的程度。在一个特定的系统或项目中,设计必须根据各QoS需求在特定系统或项目中的重要性来对所有的重要QoS需求进行优化。某些应用对最坏情况的性能和安全性要求极为苛刻,例如核电厂控制器或者航空控制计算机系统的开发。而在有些项目中,上市时间和可重用性可能更为重要。设计方案要根据系统的每一个QoS特性相对于系统或项目的重要性来进行优化。
设计的子阶段
ROPES线程将设计分为三个子阶段。结构设计的决策要从系统范畴全面考虑。结构设计分为五个重要的子模型:1. 子系统或构件模型;2. 协同模型;3. 分布式模型;4. 安全和可靠性模型;5. 配置模型。
虽然它们都称为“模型”,但是实际上只是单一系统模型的视图或透视图,它们侧重于系统的特定方面。所有各部分都必须和谐地整合在一起工作,以实现系统的整体设计目标。
子系统或构件模型已经讨论过了,它定义了系统的主要组成部分,每个组成部分包含更小的对象,并对每个对象的行为进行组织和安排。在最底层,有基本或语义对象执行系统的实际工作。定义语义对象的类要在域中进行了定义。我们并不认为定义子系统模型的类具备语义特征,因为它们的存在只是为了组织运行时的对象满足一些功能目标,而这种模型可能很多。以这种方式区分逻辑和物理结构的好处是不必改变逻辑模型就可以改变系统的配置方式(例如,从一个处理器改变为几个处理器)。
协同模型定义了任务线程和它们将包含的语义对象,以及选择待执行的任务和解决相互排斥问题的规则等等。ROPES线程定义了识别任务线程的十多项策略。引出协同模型的典型方法是应用1到3项任务识别策略来识别任务线程,然后分别给每个线程添加一个“激活”对象。在激活对象的任务帧内执行的语义对象通过合成关系法则来累加。
分布式模型定义对象之间通过通信媒介进行通信和协作,它采用CORBA、COM/DCOM等中间件或“publish-subscribe”机制来实现。分布式模型有不对称(对象都被装载到单一处理器)、对称(根据当前的处理器加载情况将对象动态地加载到任意类别处理器)或半对称(在引导时计算对象装载映射)三种。
安全性和可靠性模型对缺陷的识别、定位和处理方式以及系统可靠性和安全性的原则进行定义。许多人认为,安全性和可靠性之间的区别很小,但是对于多数系统而言,这一区别至关重要。安全性是指系统避免事故和损失的能力,而可靠性则是指系统恢复正常功能的概率。例如,手枪是一种非常可靠的设备,但它并不很安全,而一辆老式车可能非常安全,因为它几乎无法开出车库,但它并不可靠。一般而言,如果系统具有抗出错状态(一个总是安全的状态),则它的安全性和可靠性是相对立的两个方面。而如果系统不具有抗出错状态,那么提高安全性,也就提高了可靠性,反之亦然。
最后,配置模型将其它模型映射到下层的物理硬件。映射有静态和动态两种,在不对称多处理策略应用场合为静态;在对称多处理策略应用场合为动态。
结构设计子阶段包含上述五个方面,但没有必要包括在同一个螺旋线程或原型中。设计的下一个子阶段称为机制设计,其重心是优化各种协作关系,因此它与结构设计相比,更侧重于局部优化。
结构设计和机制设计主要通过应用设计模式进行,尽管这不具备排他性。详细设计重点在单个对象的内部。通常在一个系统中只有5%到10%的类需要特别予以关注,因为它们或者算法丰富,或者结构多样。大部分类相当简单,但有一小部分类可能要复杂一些。
编译和测试
编译阶段将设计模型编译为计算机能够执行的代码,可以从设计模型自动生成代码,也可以人工编写代码,或者结合这两种方式来实现。在这个阶段也融合了软件复用和第三方软件。在允许开发小组使用对象和构件组建系统之前,ROPES线程要执行单个类级的单元测试。根据经验,与系统构建完成后相比,这种查找故障的方法能够节省大量时间。
测试阶段有两个子阶段。第一个叫做整合与测试子阶段,这一子阶段利用在编译阶段经过单元测试的构件,将它们结合在一起构建成原型。在这个线程中,测试这些部件间的所有接口以使系统符合子系统和构件模型的设计。这意味着不仅仅测试接口信号(较容易的部分),还测试接口的前后状况和异常情况。这个整合与测试根据一个预先规划好的整合与测试计划完成,只要原型的子系统和构件结构已知,该规划就可以在后续的系统工程子阶段编制出来。
测试阶段的最后部分是有效性检查,此时将已构建的原型对任务进行测试。有效性测试按照有效性测试计划执行,该计划可在定义原型需求之后编制,亦即在需求分析子阶段之后编制。
本文小结
ROPES线程具有高度的弹性,适合于个人从事的小项目或数百名开发人员参加的大型项目,主要是通过选择需要生成任务图来实现弹性设计。在一个小项目中,由于所有开发人员都在同一个地点,而且系统也比较简单,小开发团队间的交流可能只需要少量的任务图,而且不需要太详细。对于大型系统,必须具备更多的细节。因为开发组成员的情况将会有更大的多样性,开发小组可能不在同一个地点,因而当系统很复杂时出现缺陷的危害将非常严重(相对于生成任务图的成本)。为了保证数量庞大的需求在分析和设计中得以正确实施,并且将大型复杂系统中出现的大量细节联系起来,对系统需求进行规划将更加严格。
现在ROPES已经成为应用广泛、能成功构建具有不同复杂度系统的手段,但是ROPES线程管理方法仍然在不断演变。
[Embedded Systems Programming]
作者简介:Bruce Powel Douglass在设计安全性要求苛刻的实时应用系统设计中拥有20多年的经验。他的著作包括:“Real-Time UML: Efficient Objects for Embedded Systems”和“Doing Hard Time: Developing Real-Time Systems with UML, Objects, Frameworks, and Patterns”。他现在是I-Logix公司首席讲师。