不同的人使用敏捷一词的含义不同。在计算中,该术语最初用于描述执行项目开发的轻量级方法,而最初的术语极限编程(XP)未能激发受托管理开发项目的众多管理人员。
基本上,敏捷软件开发指的是一组松散集成的原则和实践,旨在以经济有效的方式完成软件开发工作。
文章首先考虑为什么我们需要敏捷的方法来进行软件开发,然后在实时和嵌入式系统的背景下讨论敏捷。然后,与更传统的方法相比,它转向了敏捷开发过程的优势。
敏捷宣言
的好地方开始理解敏捷方法与敏捷宣言。宣言是敏捷联盟的公开意向声明,由17个签署者组成,包括肯特·贝克,马丁·福勒,罗恩·杰弗里斯,罗伯特·马丁等。该宣言最初于2001年起草,总结为四个关键优先事项:
*通过流程和工具进行个人和交互
*通过综合文档进行工作软件
*通过合同谈判进行客户协作
*根据计划响应变更
为了支持这些声明,他们给出了12条原则。我将在此处说明它们,以设置以下讨论的上下文:
1)我们的首要任务是通过尽早并持续交付有价值的软件来满足客户。
2)即使在开发后期,也欢迎不断变化的需求。敏捷流程利用变更来获得客户的竞争优势。
3)经常交付工作软件,时间从几周到几个月不等,但最好选择较短的时间。
4)在整个项目中,业务人员和开发人员必须每天一起工作。
5)围绕有积极性的人建立项目。给他们提供所需的环境和支持,并信任他们来完成工作。
6)与开发团队内部交流信息的最有效方法是面对面的交谈。
7)工作软件是进度的主要衡量标准。
8)敏捷过程促进可持续发展。赞助者,开发者和用户应该能够无限期地保持恒定的步伐。
9)持续关注技术卓越和良好的设计可增强敏捷性。
10)简单性-最大化未完成工作量的艺术-是必不可少的。
11)最好的体系结构,需求和设计来自自组织团队。
12团队会定期思考如何提高效率,然后相应地调整和调整其行为。
敏捷方法起源于XP(极限编程)运动,很大程度上基于Kent Beck和Ward Cunningham的工作。敏捷和XP都最关注IT系统,并且都高度基于代码。
在本系列文章中,我将重点介绍如何有效地将宣言的声明和原则应用于实时和嵌入式应用程序,以及如何将它们与建模结合起来以获得模型驱动开发(MDD)方法的协同优势。(获得有关敏捷建模的更多信息的好地方是Scott Ambler的敏捷建模网站。
为什么要敏捷?
但是,为什么需要诸如“敏捷”之类的概念来描述软件开发呢?当前的软件开发流程还不够好吗?
不,不是。
在这种情况下,过程可以定义为“由具有特定角色的工人执行的一组计划的工作任务,导致一个或多个工作产品的属性,状态或其他特征发生变化。” 基本假设如下:
1)使用该过程的结果是可重复的,从而产生具有预期特性(例如功能和质量)的产品。
2)当根据项目(例如,成本,工作量,日历时间)和产品(例如,功能,及时性和健壮性)属性执行流程时,可以高度预测工作产品的目标状态的产生。
3)人们可以被视为匿名的,可互换的资源。
4)嵌入式软件开发的问题是无限扩展的;也就是说,将资源加倍总是会导致日历时间减半。
事实证明,很难开发软件。从以上意义上讲,大多数现有的开发过程肯定是不可重复的或不可预测的。为此提出了许多原因。对我自己而言,我认为软件从根本上讲是复杂的,也就是说,它体现了复杂性的“东西”。
这就是软件最擅长的功能-捕获算法和状态机如何在很大范围内操纵大量数据以实现一组计算结果。这是“思想的东西”,这很难。
我听说过的关于软件可预测性的最好的故事是来自Scott Westfall在SlickEdit网站上的一个博客,叫做“洞穴的寓言”。 估计软件项目与估计探索故事中提到的未知洞穴所需的时间非常相似,但管理人员通常坚持要求进行高度精确的估计。
另外,软件范围正在迅速增加。与过去数十年的软件功能范围相比,如今的软件的数量级要高出几个数量级。
当时,我的第一台IBM PC具有64kB的内存,并运行了一个称为DOS的基本磁盘操作系统。DOS可以放在单个360kB软盘上。(我知道我正在约会自己,但是我的IBM PC是我的第五台计算机。我仍然怀念着我拥有4kB内存的TRS-80型号的时代。)
Windows XP包含超过3000万行代码。驱动数百种不同的打印机,磁盘,显示器和其他外围设备;并需要1 GB的内存才能舒适地运行。这些软件密集型系统所提供的功能远远超过它们所取代的仅电子设备。
例如,将传统电话听筒与现代手机进行比较。或将传统的心电图(ECG)驱使像我在医学院使用的纸质记录仪与现代ECG机一样,来驱动它。
现代机器可以完成老机器所做的一切,此外还可以检测各种心律不齐,跟踪患者数据,生成报告,并测量无创血压,血氧浓度,各种温度甚至心输出量。
最后,嵌入式软件开发确实是发明,发明不是可预测的。在电子和机械工程中,大量工作从概念上讲就是简单地将各个部分组合在一起以实现期望的目标,但是在软件中,这些部分通常是每个项目的发明(或重新发明)。
这并不是要过分简化电子或机械设计的问题,而只是要指出这些学科的基础物理学比软件要成熟得多,并且要好得多。
但是,如果您相信我的解释,那并不重要。数十年来软件开发的经验结果是可用的。大多数产品迟到了。大多数产品交付时都有许多缺陷,而且往往存在重大缺陷。大多数产品未提供所有计划的功能。
我们已经习惯了重新启动设备,但是30年前,我们不得不关闭手机,取出电池,计数到30,重新插入电池,然后重新启动手机,这是无法想象的。(就像我爱我的BlackBerry一样,我惊讶于一位客户服务代表建议每天拆下电池以重新启动设备。)不幸的是,这就是当今的“最新技术”。
为此,许多聪明的人提出了解决问题的方法,以此来解决问题,并认为如果人们设计软件而不是破解软件,结果会更好。
而且它们在很大程度上已经变得更好。尽管如此,这些方法都是基于这样的前提,即软件开发可以与工业制造过程一样对待并获得相同的结果。
工业自动化问题是高度可预测的,因此,当很好地理解驱动过程的基本机制并且本质上是线性的时(例如,输入的微小变化导致输出的变化也同样小),这种方法就具有很大的意义。
当根本的机制不被完全理解或过程是高度非线性的时,它就没有意义了。不幸的是,软件开发既没有被完全理解,也没有远程线性化。
就像模糊逻辑和神经网络在非线性控制系统中的应用不同。模糊逻辑系统通过应用部分成员资格的概念并使用质心计算来确定输出来工作。
不同集合的部分隶属关系(映射到不同的方程式)是由集合隶属关系规则定义的,因此,当已知和理解规则时,例如在速度控制系统中,最好应用模糊逻辑系统。
另一方面,神经网络不了解或不在乎规则。他们通过训练简单但深度互连的处理单元(神经元)的集群来工作。培训包括应用已知的输入(“示例”)并调整连接的权重,直到获得预期的输出。
训练后,神经网络可以从以前看不见的数据输入集中产生结果,并产生控制输出。神经网络从实际数据中学习了潜在机制的影响,但是并没有以任何重要方式“理解”那些机制。当不能很好地理解底层机制时,最好使用神经网络,因为它们可以学习机制固有的数据转换。
严格计划的过程类似于模糊逻辑-它们对底层机制做出先验假设。当它们是正确的时,就会产生高度可预测的方案。
但是,如果这些先验 假设是错误的或遗漏的,那么它们将产生不太成功的结果。在这种情况下,该方法必须根据经验数据进行调整。为此,大多数传统流程都进行“额外”工作并生产“额外”产品来帮助管理流程。这些通常包括:
*进度表
*管理计划
*度量标准(例如,代码[SLOC]的源代码行或缺陷密度)
*对等和管理评审和演练
*进度报告
等等。
这个想法是,这些任务的执行和工作产品的生产与项目的及时性以及产品功能和质量密切相关。但是,即使很容易衡量,使用的许多任务和度量也没有很好的相关性。即使它们之间的相关性很好,也会招致额外的成本和时间。
敏捷方法是嵌入式开发工程师社区对这些工业方法进行软件开发的高昂成本和精力的一种反应。我们发明软件的机制还没有被很好地理解,因此很难预测。此外,需求或体系结构的微小变化会导致开发方法和工作量的巨大差异。
因此,经验,纪律,质量和利益相关者都必须存在于我们的开发过程中。为此,敏捷方法不是关于黑客代码,而是将精力集中在可证明增加价值的事情上,而不是将精力放在没有价值的事情上。
为什么实时嵌入式系统需要敏捷
性当然,软件开发很难。嵌入式软件开发更加困难。实时嵌入式软件比这还要难。这并不是为了最大程度地减少可靠开发应用软件的难度,但是对于实时和嵌入式系统而言,存在很多问题,这些问题并没有出现在典型应用的生产中。
嵌入式系统是指至少包含一个CPU但不向最终用户提供常规计算服务的系统。手机被认为是嵌入式计算平台,因为它包含一个或多个CPU但提供了专用的服务集(尽管在许多现代手机中这种区别是模糊的)。
我们的现代社会充满了嵌入式计算设备:洗衣机,空中交通管制计算机,激光打印机,电视,患者呼吸机,心脏起搏器,导弹,全球定位系统(GPS)甚至是汽车-列表几乎是无止境的。
实时嵌入式系统中出现的问题主要体现在四个方面。首先,有效运行在资源高度受限的环境中所需的优化使嵌入式系统的创建更具挑战性。的确,嵌入式系统的运行范围从洗碗机和类似机器中的8位进程到协作的64位计算机集。
但是,大多数(但不是全部)嵌入式系统在处理器速度,内存和用户界面(UI)方面受到限制。这意味着许多标准的应用程序开发方法本身是不够的,必须进行优化以适应计算环境并执行其任务。
因此,嵌入式系统通常比标准桌面应用程序需要更多的优化。我记得为心脏起搏器编写了一个实时操作系统(RTOS),该操作系统具有32kB的静态存储器,相当于嵌入式6502处理器。(它甚至还有一个小的文件系统来管理不同的节奏和监视应用程序)现在,这是一个嵌入式系统!
与高度受限的环境一起,通常需要为嵌入式系统编写比标准应用程序开发更多的设备驱动程序级软件。
这是因为这些系统更可能具有不存在驱动程序的自定义硬件,但是即使存在驱动程序,它们也常常不符合平台约束。这意味着不仅必须开发主要功能,而且还必须编写底层设备驱动程序。
许多嵌入式系统的实时性意味着可预测性和可调度性会影响应用程序的正确性。另外,许多这样的系统具有很高的可靠性和安全性要求。
这些特性需要其他分析,例如可调度性(例如速率单调分析或RMA),可靠性(例如故障模式和影响分析或FMEA)和安全性(例如故障树分析或FTA)分析。除了“做数学”之外,还必须努力确保满足这些附加要求。
最后,嵌入式应用程序与传统应用程序之间的最大区别是所谓目标环境的性质,即目标应用程序将在其上运行的计算平台。大多数桌面应用程序“托管”(编写)在用作目标平台的同一台标准桌面计算机上。这意味着可以使用一组丰富的测试和调试工具来验证和验证应用程序。
相反,大多数嵌入式系统是从台式机主机“交叉编译”到嵌入式目标的。嵌入式目标缺乏在主机上发现的可见性和对程序执行的控制,并且大多数台式机工具都无法在其嵌入式目标上调试或测试应用程序。
嵌入式系统开发中使用的调试工具几乎总是比台式机更原始,功能更弱。嵌入式应用不仅更加复杂(由于优化),而且不仅必须驱动低级设备,而且不仅必须满足其他服务质量(QoS)要求集,而且还必须进行调试工具的能力也远远不够。
应当指出,嵌入式和“ IT”软件开发之间还存在另一个差异。IT系统通常是不断提供服务的维护系统,软件工作在很大程度上包括为消除缺陷和增加功能而进行的少量增量工作。
嵌入式系统的不同之处在于它们可以即时发布并在该瞬间提供功能。实际上,更新嵌入式系统需要付出更大的努力,因此实际上,它们通常在IT方面被替换而不是“维护”。这意味着与嵌入式系统相比,IT软件可以以较小的增量进行维护,并且“发行版”在嵌入式软件开发中具有更大的意义。
“实时系统”是及时性对于正确性很重要的系统。许多开发人员错误地认为“实时”是指“实时”。显然没有。实时系统“足够快地可以执行任务”。
如果处理您的eBay订单多花了几秒钟,则服务器应用程序仍可以执行其工作。尽管可以优化此类系统以使其每秒处理数千个事务,但通常不将其视为实时系统,因为如果系统速度变慢,则不会影响系统的正确性。
实时系统是不同的。如果心脏起搏器未能在正确的时间感应通过心肌的电流,则患者的心脏可能会发生纤颤。如果导弹制导系统未能及时纠正其姿态,则可能会击中错误的目标。如果GPS卫星不能高度精确地测量时间,则基于其信号的位置计算将完全是错误的。
实时系统可以通过多种方式进行分类。最常见的是将“硬”和“软”分为大类。如果每个动作都没有在其时间范围内执行,则“硬”实时系统将表现出重大故障。及时性的度量标准称为截止期限 –行动启动后必须完成行动的时间。并非所有截止日期都必须在微秒级的时间范围内才能实时。
该F2T2EA (发现,修正,跟踪目标,参与,评估)杀伤链 是几乎所有作战系统的一个基本方面; 此复合动作的端到端截止日期可能在10分钟左右,但是飞行员绝对必须达到这些截止日期才能提高战斗力。
动作完成的价值随时间变化是实时系统中的重要概念,并表示为“效用函数”,如下图1.1所示。此图向系统用户表示完成操作的价值。实际上,效用函数是平滑曲线,但是最常被建模为不连续的阶跃函数,因为这简化了它们的数学分析。
图1.1实用程序功能
在图中,直到某个瞬间(即期限),动作完成的价值才很高。此时,该动作完成的值为零。从当前时间到截止日期的时间长度是对操作紧急性的度量。
功能的高度是完成动作的关键性或重要性的度量。紧急度和紧急度是任何实时系统中动作的重要正交属性。不同的调度模式优化了紧急性,其他调度模式优化了重要性,还有其他模式则支持公平性(所有动作以大约相同的速率前进)。
动作是并发单元(例如任务或线程)的原始构建块。并发单元是知道顺序的一系列动作;并发单元可能具有分支点,但是一组分支内的操作顺序是完全确定的。对于并发单元之间的操作,情况并非如此。在并发单元之间,除了明确的同步点外,操作顺序是未知的或不关心的。
下面的图1.2 说明了这一点。完全指定了这三个任务(在UML活动图上显示)中每一个的流程。例如,在任务1中,顺序是首先发生动作A,然后是动作B,然后是动作C或动作D。
同样,其他两项任务的顺序也已完全定义。没有定义任务之间的顺序。动作C发生在动作W或动作Gamma之前还是之后?答案是你不知道,你不在乎。
但是,我们知道在动作F,动作X和动作Zeta发生之前,动作E,动作Z和动作Gamma都已发生。这就是任务同步点的意思。
图1.2。并发单位
因为在实时系统中,同步点和资源共享是很常见的,所以它们需要在IT系统开发中很少发现的实时系统中特别注意。
在一个任务中,几个不同的属性很重要,必须对其进行建模和理解,以使该任务正确运行(下图1.3)。基于时间的任务以一定的频率(称为周期)发生。
图1.3。任务时间
该时间段是任务调用之间的时间。周期周围的变化称为抖动。对于基于事件的任务启动,任务调用之间的时间称为到达时间。对于大多数可调度性分析,使用最短的时间(称为最小到达时间)进行分析。
从任务启动到必须完成其一系列操作的时间,称为期限。当任务共享资源时,可能无法使用所需的资源。当较低优先级的任务锁定了必要的资源时,当前任务必须阻止并允许较低优先级的任务完成对资源的使用,然后才能运行原始任务。
阻止运行较高优先级任务的时间长度称为阻塞时间。即使已准备好运行较高优先级的任务,也必须运行较低优先级的任务这一事实被称为优先级倒置,并且是在任务线程之间共享资源的所有优先级调度系统的属性。当任务共享资源时,优先级倒置是不可避免的,但如果不受控制,则会导致错过截止日期。
实时系统必须做的一件事是绑定优先级反转(例如,将阻塞限制在单个任务的深度上)以确保系统的及时性。任务执行其动作所需的时间段,包括任何潜在的阻塞时间,称为任务执行时间。
为了进行分析,通常使用最长的时间段,即最坏的执行时间,以确保系统始终能够满足其截止日期。
最后,执行结束到最后期限之间的时间称为松弛时间。在实时系统中,捕获,表征和管理所有这些任务属性非常重要。
实时系统通常也是嵌入式系统,并承担那些开发负担。另外,实时系统具有及时性和可调度性约束。
实时系统必须及时-也就是说,它们必须满足任务完成时间的限制。如果所有任务都是及时的,则整个任务集可以调度。
实时系统不一定(或什至通常)是确定性的,但是它们必须在时间上可预测地受到限制。存在一些数学方法来分析系统的可调度性,并且有工具11可以支持这种分析。
关键安全性和高可靠性系统是实时和嵌入式系统的特例。安全一词的意思是“没有事故或损失”,通常涉及没有故障以及存在单点故障的安全性。可靠性通常是系统交付服务的时间百分比的随机度量。
对安全至关重要的系统是实时系统,因为安全分析包括容错时间的属性,即容错时间在导致事故之前可以容忍的时间。它们几乎也总是嵌入式系统,并提供关键服务,例如生命支持,飞机飞行管理,医疗监控等。
通过使用附加分析(例如FTA,FMEA,故障模式,影响和严重性分析(FMECA))可以确保安全性和可靠性,并且通常会生成称为危害分析的文档。
这将故障可能性,故障严重性,风险(前两者的乘积),危险条件,故障保护手段,容错时间,故障检测时间和故障保护动作时间结合在一起。对安全至关重要的高可靠性系统需要进行额外的分析和记录,以获取诸如FAA和FDA之类的监管机构的批准。
对于公司和项目而言,为此类系统的开发指定非常繁重的流程(安全关键,高可靠性,实时或嵌入式)作为向这些系统注入质量的一种方式并不少见。
它在一定程度上有效。但是,它的成本很高。敏捷方法为这类系统的开发提供了另一种观点,即重量轻但不牺牲质量。