ImageVerifierCode 换一换
格式:DOCX , 页数:25 ,大小:732.80KB ,
资源ID:12532076      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/12532076.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(LabVIEW的软件工程方法.docx)为本站会员(b****0)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

LabVIEW的软件工程方法.docx

1、LabVIEW的软件工程方法LabVIEW的软件工程方法LabVIEW的软件工程方法1. 序言本文将会介绍一些关于LabVIEW的系统设计、实现的方法。我希望读者朋友们通过阅读本文,在仔细思考、比较后能得出自己的结论,形成自己独有的设计和实现方法。2. 软件设计的原则在讨论更进一步的细节之前,我们先思考一个问题:什么是好的软件我个人认为,好的软件必须:(1)对于小的需求变动,程序需要改动的地方少;(2)在(财政)预算范围内,程序能按时完成;(3)能实现(几乎)所有的预期功能;(4)使用简单;(5)方便维护;(6)运行良好;(7)错误处理得当;(8)安全;(9)可靠性好。你有过接手别人项目的经历

2、吗如果有的话,那么你肯定不会对以下情况陌生:(1)别人的程序总是显得结构复杂、编写的方式很奇怪;(2)几乎没测试过、没有文档说明、算法看不懂;(3)改动别人的程序总是比预期花费的时间长,甚至一个小小的改动就能导致整个程序的崩溃。我有过以上痛苦的经历,所以对我来说:简单的程序好,复杂的不好;能把复杂问题简单化的设计就是好设计。3. 改进设计的要点怎样尽量把复杂问题处理得简单呢虽然LabVIEW不是面向对象编程语言,但是我们可以借鉴面向对象的思维方法。例如耦合(Coupling)、黏合(Cohesion)、信息隐藏(Information hiding)和抽象(Abstraction)就是不错的思

3、维方法。关于耦合、黏合、信息隐藏和抽象的概念可以去查看面向对象方面的资料,我这里就不赘述了。 耦合图3-1 紧耦合(Bad)如图3-1中所示的VI有相当多的输入、输出参数,看起很复杂。请大家仔细的观察,然后思考这个问题:是否所有的参数对我们要解决的问题来说都是必不可少的不一定,也许作者只是想把它当“连接器”使用,通过它把其它的VI连起来而已。图3-2 松耦合(Good)如图3-2中所示,这个命名为“Meas System”的VI是一个松耦合的典型,它的设计思想是:让系统中所有的测试功能都包含在Meas 中。其中“Command”输入参数是一个类似下拉菜单的枚举型控件(自定义的枚举型控件更佳),

4、通过它你可以选择你想要完成的测量任务;“Measurement”和“error out”两个输出参数则分别输出测量的结果和状态。这样做的好处将在下面“黏合方式的对比”介绍。 黏合想象一下:如果一个程序中像图3-1中那样的VI有5、6个左右,并且它们从左到右像糖葫芦那样串起来连成一行,会是一个什么样情况这些VI之间的连线很难做到没有交叉,多半会彼此搅成一团。如果隔个一年半载后,让你对系统进行维护,而且这个系统中有n个像这样搅成一团的程序这将是一个噩梦。所以,站在系统维护性的角度来看,这样的系统它的黏合性是差的。图3-3 Word 如图3-3所示,“Word ”是一个利用ActiveX控制Word

5、的程序,它把系统必须用到的Word功能封装在了里面。同图3-2所示的程序类似:“Command”选择Word的功能; “error out”输出执行状态;因为Word的特殊性(与仪器相比),它多了一个输入参数“String In”(用来输入Word路径等),少了一个“Measurement”的输出参数。很显然,“Word ”也是典型的松耦合方式。图3-4 Word Control的前面板图3-4所示的是Word Control的前面板,它分成3块:Input、Local和Output。这三块分别对应输入、中间(局部)和输出变量。图3-5 Word Control的应用图3-5所示的是Word

6、Control的一个应用程序,它依次实现的功能是:打开Word文件、跳转到书签、插入文字、保存文档、关闭Word文件。可以看到:每调用一次“Word ”,它就“专心”的完成一项功能。这样做的好处有3个:(1)如果在调试时出了问题,可以很方便的查出哪部分出了问题;(2)因为控制Word的功能都集成在一个VI中,所以如果要对这个VI进行测试,可以对每个Word的控制功能逐一测试,这样测试就条理清楚;(3)如果需要添加控制Word的功能,只需要在“Command”枚举变量里添加功能的名称,再添加一个新case分支就行了,其它地方不需要更改。 信息隐藏请先看一个常见的案例:某个系统需要用到DIO卡来控

7、制LED灯的亮灭和继电器的通断。在测试时,当继电器闭合后,系统的某个相应单元会连接到电源;继电器断开,这个单元就会与电源断开。此外,LED起指示灯的作用,它用来告诉用户某个单元是否通电。一般情况下,可以通过设置DIO卡端口(port)和通道(channel or byte)的值,来控制DIO的输出。为了更方便的说明问题,我们假设DIO卡对LED灯的控制是负逻辑(ture = 灭,false = 亮),对继电器的控制是正逻辑(ture = 闭合,false = 断开)。让我们来看看下图3-6中所编写的VI。初看起来会觉得还不错,除了LED的负逻辑稍微有点难理解外。图3-6 信息隐藏(bad)但是

8、如果这个系统有许多LED灯和继电器呢恐怕得把图3-6所示的编程任务量翻20倍还不止。另外,假设编写这个系统程序的人已经离职了,但是现在系统的硬件驱动有了更改,而且部分硬件驱动的逻辑也变了。现在由你接手这个项目,你需要对众多的端口和通道值重新进行修改和设置;而且,你还发现前任者对这个系统程序几乎没有任何注释说明。这时,你将会觉得这个工作量似乎不像想象中的那么小。DIO驱动不应该这样复杂,它仅仅只有0和1而已。但是如果所有的VI都像图3-6那样编写的话,恐怕这个系统会真的变得很复杂。上述问题的解决方法是,考虑把具体的信息隐藏在组件(component)里面。简单点说,就是考虑组件(componen

9、t)要做什么,而不是怎样去做。因此,我们可以把DIO要做的事分为4个(考虑到要与前面板命令保持一致,所以就用英文来写这4个事情):(1)Switch Power to unit X on.(2)Switch unit X Power indicator on.(3)Switch Power to unit X off.(4)Switch unit X Power indicator off.实际上还有个初始化的功能,但考虑到它对系统的问题解决影响不大,因此由部件自己“决定”是否需要初始化。图3-7 DIO组件前面板 图3-8所示的是DIO组件命令的说明。图3-8 DIO组件命令图3-9 信息隐

10、藏示例关于如何实现图3-9中所示VI编程,将在下节讨论。我们先来看信息隐藏后的好处。首先,它的可读性更好。DIO组件只有Command、Unit和error in三个输入。通过Command,你可以知道DIO组件现在要执行什么任务;通过Unit,你可以知道DIO组件现在对哪个单元进行操作;而error in,是典型的数据流操作,你可以通过它来传递DIO组件的状态。其次,它的维护性好。熟悉LabVIEW编程的读者可能已经猜到,DIO组件里面的程序结构是状态机,而Command则连接在case结构的select变量()上。显然,case结构必有4个分支对应DIO组件要完成的4件事。所以,如果要进行

11、前面所说的系统维护工作的话,只要把DIO组件里的4个case结构修改下就行了。此外,其实它的可扩展性和重复利用性也是很好的。但是现在还看不出什么苗头,所以这里我们暂不讨论。 抽象什么是抽象在我看来,把一个复杂的问题用一个“概念”来简称,这就叫抽象。例如,在LabVIEW编程中,如果我们想把一些文字保存到某个文件里,我们不会考虑直接用“0”和“1”的形式把文字数据保存到硬盘,而会调用“Save to ”,要保存的文字作为输入参数送到“Save to ”。此时,你就使用了抽象的方法,把复杂的问题进行了可视化管理。你把“0”和“1”数据保存抽象成“Save to File”这个概念。软件设计时有两种

12、抽象方法:(1)功能抽象 LabVIEW支持子函数(subVI)功能,因此在设计时,我们可以很方便的把一个复杂的程序分割成多个小块。LabVIEW的这种层次结构实际上就是提供的功能抽象:顶层的功能模块可以划分为几个子功能模块,而子功能模块又能含有它自己的子功能模块这种功能抽象是打破问题复杂性的主要途径。(2)数据抽象计算机处理“0”和“1”,但是编程语言会提供给我们更详尽的数据类型,例如整形(Integer)、实数型(Real Number)、字符型(String)等。这些数据类型实际上就实现了数据抽象的功能,它们把“0”和“1”抽象成了人们容易理解的整形(Integer)、实数型(Real

13、Number)、字符型(String)等。LabVIEW还提供了簇(Cluster)这个数据类型,它可以把相关的几个数据绑定在一个,而这些数据不一定是同一个类型。例如,要表示一个圆,它的属性为圆点坐标(X,Y)、半径R和颜色C,其中圆点坐标是一个双精度型的一维数组,半径R是一个双精度型的实数,而颜色是一个0255的整形。那么我们把圆点坐标(X,Y)、半径R和颜色C绑定成一个簇后(最好是自定义类型的簇),以后就可以用自定义的簇来表示这个圆。这也是一个数据抽象的过程,它把相关的圆点坐标(X,Y)、半径R和颜色C简化成一个数据簇,这样就方便了我们在应用程序中传递数据。通过把数据封装和隐藏在VI中,抽

14、象的程度可以达到类似面向对象(OOP)编程的水平。用发送信息的方式作为进入和修改数据的唯一途径,是数据抽象的好方法。而数据抽象则是一种模块化设计的好方法。下面我们将用几个例子来说明正确使用抽象的好处。例如,在某个测试系统中的项目中,我们需要编写一个控制继电器闭合、断开的组件,它的基本原理是利用一张继电器板卡来控制继电器的闭合和断开。一种低层次的抽象方法是:用几个subVI来实现初始化、设置和清除硬件卡端口的功能,测试系统的每次继电器操作都是通过调用相应的subVI来完成。这种抽象方法如图3-10所示,为了方便讨论,我们把这些实现初始化、设置和清除的VI称为“relay VIs”图3-10 低层

15、次的抽象高层次的抽象做法是:把继电器操作的细节和通道号封装在一个组件里面,例如,用一个命名为“Switch”的 VI来把所有的“relay VIs”封装在里面。这样,想进入“relay VIs”进行操作就只有通过“Switch”这个VI。高层次的抽象方法如图3-11所示。图3-11 高层次的抽象高层次抽象和低层次抽象相比,好处有哪些我们通过图3-12来比较一下。图3-11 抽象层次比较高层次抽象允许你修改Switch函数,而不改变它的函数接口。例如,如果发生继电器卡更换或者继电器的驱动函数、配置发生改变等情况,你不需更改程序的基本框架,只要用Switch组件把新的“relay VIs”重新封装

16、起来就行了。所以,在高层次抽象里,那个额外的抽象层可以防止软件设计的更改。另外,高层次抽象使你程序的可读性更好。另外,当你发送一个命令(例如“Initialize Switch System”、“Connect Mea1 Circuit”等)时,你想继电器进行的动作将是清楚明了的。模糊不清在软件中是坏现象,因为它容易导致bug的产生。4. LOCD的实现LCOD是LabVIEW Component Oriented Design的缩写,意思为面向对象的LabVIEW组件。组件(Component)是面向对象中一个常见的概念,我这里就不赘述了,对它有兴趣的读者可以自行去查阅C+ Builder的

17、资料。 组件的编写技巧当编写组件时,应该综合起来考虑系统中所有组件的内在需求,它们包括:(1)所有的组件,进入它们的公共函数(Public Function)和数据(data)的接口应该尽量简单明了;(2)增加、删除和修改组件的功能应该尽可能的轻松简单;(3)组件的任何修改,要尽量对整个系统几乎不产生影响;(4)组件的状态,要能不断被记录保持在自身内部;(5)组件要能自己初始化;(6)组件要有错误处理机制和输入和输出的检查机制。 消息发送消息发送(Message Sending)是一种控制组件的方法。例如,如果要让组件A要调用组件B,让组件B完成某件事情组件。那么组件A就可以通过发送消息给组件

18、B,告诉组件B该做什么,从而达到预定的目的。在LabVIEW中,消息放送的发式有很多种,但是我推荐利用枚举型控件来发送消息。因为它使用简单、方便,而且还能自动文档化。实际上,使用这种方法最大的好处是:当你在编程时,可以在程序框图里把组件拖出来,而且使用时只要点击枚举型控件,选择你想要实现的功能就行了。 枚举型控件的相关信息LabVIEW的在线帮助上提供了很全面的枚举型控件的信息,本文把它提取出来列成以下几点:(1)枚举型控件是一个有下拉框的控件;(2)下拉框里的选项在控件的属性里进行编辑;(3)枚举型控件的数据类型可以是U8、U16和U32,这些数据类型决定了枚举型控件下拉框里选择项的最大个数

19、。比如,如果一个枚举型控件它的数据类型是U8,那么它下拉框里的选择项最多可以达到256个;同理,一个U16型的枚举型控件,它下拉框里的选择项最多可以达到65536个。那么U32呢我想232对一般编程者来说应该是无数个。(4)如果把枚举型控件连接到case结构的选择变量(),那么case结构的分支名称将会由数字变成字符串了;(5)如果枚举型变量参与算术运算(除了“+1”和“-1”的运算外),它将会被当成一个无符号整型(U8、U16或U32)进行运算;(6)+1”和“-1”的运算,会让枚举型控件里的选择项被旋转,即选择项的开头到结尾的顺序被颠倒过来;(7)如果让数字作为输入,枚举型控件作为输出。那

20、么枚举型的输出为最接近数字的那个枚举号所对应的选项(比如数字为,那么枚举型显示第2个选择项)。如果数字大于枚举型控件里的选择项个数,那么枚举型控件将显示最后一个选择项。 枚举型控件的使用枚举型控件总共有7种使用方式:(1)格式化成字符窜把选择项的内容转换成文本形式,即字符串格式。当你想把状态保存到一个文件或数据库时,可以采用这个方法。具体用法参见图4-1。图4-1 枚举型转化成字符串(2)扫描字符串把输入的字符串转化成枚举型变量形式,这个与(1)的用法正好相反。图4-2字符串转化成枚举型(3)类型强制转换图4-3所示的是把一个数字转换成相应的枚举项。注意,如果枚举型控件里没有与数字“2”匹配的

21、表现形式(representation),那么在此例中,输出的默认显示结果为“Error State”;否则为“Test 2”。图4-3枚举型变量的类型强制转换(4)平化转换图4-4所示的是平化转换。当需要通过端口发送指令时,它是非常有用的。例如,在一个实时系统中,PC客户端和实时服务器之间的通讯协议采用TCP/IP协议,那么我们可以用平化转换的方法在PC客户端和实时服务器之间传送、接收命令。图4-4平化转换(5)case结构如图4-5所以,枚举型变量能增加case结构的可读性,实现自动化文档功能。这种方法经常在状态机里应用。图4-5 case结构(6)产生事件的序列如图4-6所示,由枚举型变

22、量构成的数组,如果连到for循环让其自动索引,就能产生一个事件的序列。当然,这些事件的先后顺序可以通过简单的下拉菜单选择二改变。而枚举型变量构成的数组,可以从数据库或者保存的文件中产生获得,这样一个完全可配置的系统只需要少数几个步骤就可以实现。图4-5 事件序列(7)状态机如图4-6所示,把枚举型控件连接到while循环的寄存器(register),就构成了LabVIEW中极其重要的一种结构状态机。图4-6 状态机 严格自定义类型的枚举型控件请大家思考这种情况:当你在编写组件时,创建了一个枚举型控件,采用了中所述的使用方法,而且这种方式始终贯穿在你的整个程序中。现在,你需要在组建中添加一个新功

23、能,你双击了枚举型控件后添加新功能的名称,接着你就会发现你的程序框图的运行箭头断了。你的把所有的枚举型变量、常量都得改,这是个很繁琐的工作,程序越大越明显。上述问题的解决方法就是:创建一个严格自定义类型的枚举型控件。在LabVIEW菜单中点击“新建”“自定义控件”,就可以创建它严格自定义类型的枚举型控件了,图4-7所示的就是严格自定义类型的枚举型控件。在编写组件时,一律采用这个自定义的枚举型控件。当你需要修改它时,在自定义控件的面板里修改选择内容就可以了。修改这个等于把你组件中所有的枚举型控件都修改了。图4-7 严格自定义的枚举型控件 局部变量的保存我们希望组件在完成一次动作后,能够保持住它此

24、刻的状态信息。这些状态信息是私有变量,它们是隐藏的。从组件外部你不能直接改变它们,只能通过发送消息给组件的方式才能进入这些数据。保存组件状态信息的有效方法是:利用LabVIEW的for循环或while循环的移位寄存器,把状态信息保存到VI中。图4-8所示的就是移位寄存器的此种用法。图4-8 移位寄存器移位寄存器是一种局部变量,它最初的目的用来传递循环时产生的某些值。它有一个重要的特性持续性。即使移位寄存器所在的VI运行完后,移位寄存器中存储的值仍保留在里面。我们利用这个特性来保持组件的状态信息,使组件保持独立性,从而达到松耦合、数据私有的目的,这些都是有利于信息隐藏(本文节中有详细说明)的。

25、组件的基本结构图4-9所示的是一种最简单的组件结构:图4-9 组件的基本结构首先,在while循环框里放一个case结构;接着,在while循环框外,用一个枚举型常量连接到while循环框,并把连接点改为一个的移位寄存器;然后把移位寄存器连接到case结构的选择变量上。这样就组成了一个最简单的组件结构。在节中介绍了一些组件编写技巧,以下我们来逐一论述:(1)组件要能自己初始化回到图4-9,在右边的程序框图中,我们用到了一个功能函数“首次调用”(在LabVIEW函数面板中点击“编程”“同步”“首次调用”即可)。在while循环框左边,有一个小圆轮,那就是“首次调用”。当这个组件作为subVI第一

26、被调用时,“首次调用”的返回值为真。此时,枚举型常量里的“Initialize”就会被传送到case结构中,使case结构执行名称为“Initialize”分支里的代码。“Initialize”分支里的代码一般用来完成文件加载、数组大小设置、仪器设置,或者与初始化相关的功能。值得注意的是,当你从前面板按“箭头”执行该程序时,“首次调用”返回值总是为真。另外,如果你的组件不需要初始化,可以不用“首次调用”这个功能。(3)组件要有错误处理机制和输入和输出的检查机制图4-10 组件的各状态图4-10所示的是某个组件的各个状态,它有6个状态:UnderRange、Command1、Command2、C

27、ommand3、Finish、OverRange。其中,UnderRange和OverRange两个状态的作用是用来做异常处理:当枚举量的输入超过范围时,它将会反馈一个错误信息给调用这个组件的程序。这样做是为了让组件具备错误处理能力,从而保证组件运行的流畅性。Finish状态可以用来检查后置条件,甚至你还可以添加一个Start状态来检查前置条件。关于前置条件和后置条件的检查将会在下节中介绍。(4)增加、删除和修改组件的功能应该尽可能的轻松简单;组件的任何修改,要尽量对整个系统几乎不产生影响如果要在组件中增加一个新功能,首先把新功能的名称添加到枚举量里面,接着在case结构中复制或添加一个新ca

28、se分支,最后把新功能的动作添加到新的case分支里就行了。反之,如要删除一个功能,只要删除对应的case分支和枚举量里面的功能名称。同理,修改功能的话,也只需把相应的case分支做修改就行了。(5)进入组件的公共函数(Public Function)和数据(data)的接口应该尽量简单明了5. 软件工程概要 到目前为止,本文主要是围绕设计及其实现问题来进行阐述。诚然,设计在软件工程中占了很大一部分,但不是全部。 软件工程是一个巨大的学科,在这一章我们将更全面的讨论这个问题。之前,因为我们想专注于“设计”这个问题, 所以其它问题我们没有讨论。但是,为了更深入的进行研究,我们需要先讨论一些软件工

29、程方面其它相对次要点的问题。要明白世界上没有“万灵丹”,具体问题需要具体分析。现在所有软件工程的理论都是根据最新的信息而发展起来的,这也意味着软件工程的理论是不停变化的。 什么是软件工程 软件,是指用于计算机的程序或操作信息;工程,就是应用科学的方法去设计、去构造事物,包括使用机器、运用构造学等。所以,按照我的理解,软件工程就是运用科学的方法去设计程序或操作信息。换句话说,软件工程就是运用某种“科学的方法”来设计软件。它的反面就是不运用任何科学方法来设计软件。我主张的“科学的方法”,就是前面几章叙述的“LCOD” 。不运用任何科学方法来设计软件,有很大可能将导致任务失败。 那么,除了设计以外,

30、软件工程中还有哪些需要注意的问题呢所有的系统开发都将经过这样的阶段:需求分析、设计、构造、验证和维护。不同的公司有不同的方法来走这些流程,下面将简单叙述我们是怎么做这些的。我们这样做是因为它行之有效。实际上,我们在本章讨论的软件工程方面,都是我们在工作中直接运用的方法。 我们需要注意的是软件童话和悲剧。避免童话,从悲剧中学习经验,它们对软件工程都没有帮助。 童话故事: 最近的软件太容易编了,谁都能完成它; 最近出来的xx语言功能强大,能保证这个项目的成功; 这种新设计方法将能保证所有的软件都成功实现; xx公司新出的项目管理软件能使失败的软件开发成为过去式; 最新的案例工具包将使软件开发人员显

31、得多余 采用xx模型能解决所有问题; 软件需求是固定不变的。 恐怖故事: 这份清单可能够详细了。最近出版了很多的新书,告诉我们软件开发过程中各种糟糕的情况。但是猜猜看发生了什么大多数的悲剧都与直接或间接相信童话故事有关。Robert Glass的书Software Runaways(又名软件开发的滑铁卢 ),就充分阐述了这一点:不要被凶恶的大灰狼吃掉,也不要相信童话故事。 那么怎样保证我们的项目不会成为悲剧呢应该从实际出发,选择正确的软件工程方法。我们经常遇到那些对某种工具、方法等迷信的人(经验主义者),但是我们更应该相信“不管黑猫白猫,抓到老鼠就是好猫”。 普遍的质疑声 任一本书或者文章在讨论软件生存周期的时候,总会以质疑经典的瀑布式生存周期为开头。如图5-1所示图5-1 Waterfall life cycle 生命周期显示了一个基本的项目由开始到交付直至以后的全过程。瀑布式只是最早几个用书面表达的生存周期之一。但是,没过多久时间,瀑布式生存周期就被实践证明是难以实现的模式。瀑布式生存周期,从表面看起来没有问题,但是它要求周期中前一个阶段完全实现后才能进入下一个阶段。不管是需求改变、设计改变、执行还是单元测试,都能反映出存在的问题:只要在生命周期过程中产生变化,那

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1