第一篇:《软件项目管理方法与实践》课程设计报告
软件项目管理方法与实践 课 程 设 计 报 告
1006602-** ***
一、设计时间
2013年12月23日-----1月6日
二、设计地点
湖南城市学院信息楼406机房
三、设计目的1,2,3,四、设计小组成员
五、指导老师
阳王东老师、费雄伟老师
六、设计课题
七、基本思路及关键问题的解决方法
八、流程图
九、调试过程中出现的问题及相应解决办法
十、课程设计心得体会
十一、源程序
参考文献
第二篇:课程设计项目实践
项目实践、设计与产品制作
本专题实践是专为电气工程专业的高年级学生,进入专业学习前所进行的专题培训,目的是为了更好地使学生适应专业学习和毕业设计,重点培养同学们动手实践和自我规划课题的能力。
专业专题实践分硬件和软件两类。其中硬件类实践是在微机原理与应用、单片机、DSP等课程基础上,结合实际的小项目,通过项目调研、方案设计、实验调试、总结报告,进行具体项目的综合训练。在整个实践过程中,希望同学们有意识地注意以下几个方面的训练:调研,方案设计,系统,控制软件方法设计,调试,总结。
同学们首先要站在宏观角度审视一个具体项目,通过调研,制定技术方案;然后按照所确定的技术路线进行相应的设计、制作、编程、调试和测试,最后进行总结和提高。希望同学们以非常认真的态度,珍惜难得的实践机会,认真完成实践任务。
需要提醒的是,专业专题实践不同于其它课程,它是项目型教学,主要是发挥同学们自己的主观能动性,自主学习性,不要依赖教师。在实践中教师是在宏观上辅导(如帮助分析方案和解答疑惑问题),所起的作用是辅助性的。更多的是需要靠同学们自己主动去调研、设计方案、实验、总结。项目型实践课程与平时的实验课不同,实验课有详细、具体的实验指导书,告诉同学们具体的实验步骤。项目实践课并不给出具体详细实践步骤和方法,需要同学们自己通过调研、与老师或同学讨论、合理分工完成。这里不仅培养同学们的自主学习(自主研发)精神和能力,也培养大家主动型的学习习惯,同时更是培养大家相互协作精神、发现问题和解决问题的能力以及研究性学习的能力。
一、实践要求
1. 每个实验项目3人一组,分工进行,提倡好的合作精神; 2. 专题实践以设计、实践为主,共四周时间;
3. 爱护设备,不随意更换设备,如有要求,请与老师联系;
4. 做硬件实验时,注意断电操作,即所有的接线、改线及拆线操作均应在不带电的状态下进行,严禁带电操作;
5. 坚持复查制度,例如通电前的复查:一人接线另一人检查,重要结果和现象复查实行二人制;
6. 每天实验完毕(包括中午),请恢复桌椅原位,保持实验室的整洁,关闭所用实验设备电源,再离开实验室;
7. 注意人身、实验仪器和设备安全,防止发生事故。万一发生事故,应立即切断电源,保护人员,保存现场,并立即向教师报告,检查事故原因,总结并吸取教训;
8. 电热设备(如烙铁)用毕必须随手拔下电源插头,以免过热引起火灾;平时注意实验板上的带电情况,测量和调试中防止触电、短路;注意示波器高频探头的地极是通过示波器电源插头的中心端接地的,切勿将该地极与交流电源的火线相接,否则将发生短路事故;
9. 参考文献或芯片、器件手册阅读量要求:20篇以上; 10. 要求每日记录工作日志和实验情况,参见简要工作日志格式。
二、实践报告及成绩评定
1. 以小组(3人名义)形式需要完成3份报告:(1)开题报告;(2)中期报告;(3)结题报告。报告要求见后面要求。注意:
2. 每人需要完成1份个人小结,第5周五前前提交,延期扣分。报告格式见后面要求。3. 实施2次检查,(1)中期检查,第2周周5;(2)结题检查,第4周周5。4. 成绩评定依据:
开题10分;中期考核10分;态度10分; 项目工作完成情况40分:
项目完成的质和量是考核的重点,还要考核同学们专题实践的主动性,项目组成员之间的合作情况,仪器设备、芯片的正确使用情况,项目验收时汇报和答辩情况等; 项目报告30分:
报告质量情况、总结的深度是考核的重点,兼顾认真程度和格式等。建议结题报告按学位论文格式完成,要求有:摘要、综述(文献阅读、任务分析、工作安排等)、正文论述、项目结论、参考文献等。
鼓励同学们自主创新,如有专利、论文等的思路或草稿,可以考虑适当加分。
.结题报告格式(每组只交一份,第2周末交)要求按毕业设计论文模板书写结题报告。报告包括以下内容: 1. 报告摘要;
2. 课题论述:包括专题实验目的,文献阅读、项目的综述,项目要求、技术要点、难点;
3. 设计方案说明,包括设计方案研究、分析、总体方案思路,所采取的技术路线,工作和时间安排,人员分工;
4. 设计内容,包括具体的项目设计,软硬件设计,调试,讨论;
资源:单片机的选择论述,软件资源的利用等; 硬件:电路原理图、PCB图(如果有的话); 软件:结构、流程、源程序和程序注释; 调试:调试过程、问题的发现和解决;
5. 课题实验、调试记录,完成情况,存在问题及可能的解决方案,工作总结; 6. 项目结论(实验结果和结论、成果、遗憾、后续工作);
7. 附录(包括列出所用软件工具、找到的各种电子参考资料、参考文献等)
个人实践小结(每人交一份),第2周末交
主要写个人对项目的理解、投入、贡献、收获,并对自己的项目工作做简单评估,按五个等级自评:优(90~100),良(80~89),中(79~70),及格(60~69),差(60以下)。请实事求是评价个人工作,过高或过低评价都不推荐。
项目1 微机继电保护的设计与实现
一.实验目的
学习和实践交流信号数据采集和微机保护算法,学习微机保护的软、硬件原理,设计微机保护原理型样机,使用学校现有单片机教学实验箱或实验板完成原理型微机继电保护装置并实现其主要功能。
二.实验任务
1. 学习一种单片机(如Intel8051、MC、ARM、瑞萨9等)或DSP(2407、2812、28335等)原理和使用,学习其编程方法;
2. 学习A/D转换技术,搭建单片机外围模拟交流信号(A/D转换器外围信号)采集环节,用信号发生器模拟继电保护电流信号(互感器输出),测试瞬时性继电保护(如电流速断)动作特性(动作和返回,返回系数0.9); 3. 设计交流信号的数据采集和微机保护算法,设计数字滤波算法,编写继电保护软件,常用有效值算法,例如半周波积分算法、差分算法、傅立叶算法等;
4. 编写实时显示程序,实现显示功能:显示交流信号有效值(折算出虚拟CT原边电流,例如100/5A,5A/2V),如能设计通讯,使用PC机做上位监控计算机实时显示测量值最好;
5. 编写延时过电流保护逻辑的微机保护软件,并实现延时过电流保护; 6. 设计实验电路板(原理图和PCB电路板),并评估。
三.相关资料和实验平台
1. 单片机或DSP实验主板,单片机或DSP资料和datasheet; 2. 继电保护、微机继电保护参考书;
3. 微机继电保护参考文献,软件流程和交流采样算法文献; 4. 实验板、部分外围芯片(如运放)、信号发生器、示波器等 5. C++编程或Lab View界面编程语言。
四.提示
请同学编写继电保护软件,主要是设计交流数据采集策略和算法,让单片机实时显示被采集的交流信号有效值,比较保护定值,决定保护动作(驱动指示灯实时点亮)。
五.选题对象
限已经选修数字和模拟电子电路、单片机课程的同学,学习过微机继电保护最好。3人一组,合理分工。
项目2 变频器的设计与实现
暂缓
一、实验目的
学习变频调速原理,学习正弦波PWM控制方法,掌握设计和实现变频调试器的方法。本任务拟采用纸上谈兵方式进行,主要是考核同学们具体任务的分析问题和解决问题的能力。要求给出设计方案、方法、作出设计、以及实现方式。
二.实验任务
1. 利用IPM设计变频器的主电路;
2. 利用瑞萨单片机、MSP430或DSP设计变频器的控制系统(主要是PWM); 3. 调试变频器的软、硬件系统,最终能带三相小型异步电机;
4. 设计相关的控制算法、控制软件,产生变频PWM信号或功率输出,实现:
(1)变频器的变频输出、V/F特性(V/F=const);
(2)电机的起动和停止特性、电机运行中的变频控制、调压控制等;(3)评估逆变器输出波形。
三.实验平台和有关资料
1. 变频器样机(供设计参考,该样机资料有限,开放性较差,能开发的余地小); 2. 提供变频器主电路板及相关器件,可在此基础上完成变频器主电路系统;
3. 自选单片机(实验室已有的)做控制平台,依据该单片机Datasheet编写相关控制软件并调试;
4. 相关的一些网站:TI公司 DSP网站上面有许多介绍变频器控制的软件、方法、甚至源代码;三菱公司网站,介绍IPM模块、整流模块;
一些变频器网站介绍变频器:如http://www.xiexiebang.com等; 5. 图书馆可借阅一些变频器相关书籍、文献。
四.选题对象
限已经选修过电力电子、数字和模拟电子电路、单片机课程的同学。
第三篇:华中科技大学软件课程设计报告
软件课程设计报告
班 级:姓 名:学 号:
光 信0 8 0 4 廖 娟
U 2 0 0 8 1 3 1 9 7 光信0804廖娟
U200813197
目 录 软件设计............................................4
1.1 设计题目及目的.................................4 1.2 设计思想.......................................4 1.3 背景知识.......................................4(1).定义:.....................................4(2).存储结构:.................................5(3).遍历二叉树:...............................6 1.4 程序结构及功能划分.............................7(1).廖娟#注释.cpp..............................7(2).廖娟#软件课程设计.cpp......................8 1.5 程序流程......................................10 2 软件测试...........................................14
2.1 测试环境......................................14 2.2 廖娟#注释.cpp 的测试过程.......................14 2.3 廖娟#软件课程设计.cpp 的测试过程...............15(1).程序运行前的初始界面.......................15(2).输入数据及二叉树打印的画面.................16(3).选择操作的提示画面.........................16(4).程序测试时的画面..........................17 3 算法改进...........................................19
3.1问题发现......................................19 软件课程设计
2010年1月
(1).问题一:..................................20(2).问题二:.................................21 3.2解决方案......................................21(1).问题一改进方案:.........................21(2).问题二改进方案:.........................22 4 开发体会...........................................23 附录:源代码清单......................................25
廖娟#注释.cpp.....................................25 廖娟#软件课程设计.cpp.............................29 参考文献.............................................35 光信0804廖娟
U200813197软件设计
1.1 设计题目及目的
设计题目:二叉树的查找--用链表结构实现二叉树建立、查询、打印的源程序。
设计目的:基于C语言的基础,熟练运用结构体等扩展数据手段,定义应用数据、并进行运用。本题要求掌握数据的链式存储结构,并编程实践它们的实现、应用方法。
1.2 设计思想
利用结构体,链表等数据结构,以及折半查找、选择排序等基本算法,结合指针,文件等相关知识,利用C语言编写链式结构实现二叉树的建立、打印、查询、先序遍历、中序遍历、后序遍历等基本功能,并将这些功能用独立的子函数实现,通过主函数的调用实现相应的功能。
1.3 背景知识
(1).定义:
二叉树是由n(n>=0)个结点的有限集合构成,此集合或者为空集,或者由一个根结点及两棵互不相交的左右子树组成,并且左右子树都是二叉树。
这也是一个递归定义。二叉树可以是空集合,二叉树结点的子树 软件课程设计
2010年1月
要区分左子树和右子树,即使只有一棵子树也要进行区分,说明它是左子树,还是右子树。二叉树的定义方法:
Struct tree { char info;struct tree *left, *right;
}(2).存储结构:
存储结构分为顺序存储结构和链式存储结构。
a.顺序存储结构:从树根起,自上层至下层,每层自左至右的给所有结点编号缺点是有可能对存储空间造成极大的浪费,在最坏的情况下,一个深度为H且只有H个结点的右单支树确需要2h-1个结点存储空间。而且,若经常需要插入与删除树中结点时,顺序存储方式不是很好!光信0804廖娟
U200813197
b.链式存储结构:
存储二叉树经常用二叉链表法
(3).遍历二叉树:
假如以L、D、R分别表示遍历左子树、遍历根结点和遍历右子树,遍历整个二叉树则有DLR、LDR、LRD、DRL、RDL、RLD六种遍历方案。若规定先左后右,则只有前三种情况,分别规定为:
DLR——先(根)序遍历,LDR——中(根)序遍历,软件课程设计
2010年1月
LRD——后(根)序遍历。①.先序遍历二叉树的操作定义为: 若二叉树为空,则空操作;否则 A.访问根结点; B.先序遍历左子树; C.先序遍历右子树。
②.中序遍历二叉树的操作定义为: 若二叉树为空,则空操作;否则 A.中序遍历左子树; B.访问根结点; C.中序遍历右子树。
③.后序遍历二叉树的操作定义为: 若二叉树为空,则空操作;否则 A.后序遍历左子树; B.后序遍历右子树; C.访问根结点。
1.4 程序结构及功能划分
(1).廖娟#注释.cpp
主要分为主函数、创建二叉树子函数、二叉树查询子函数、二叉树打印子函数四个部分。其基本功能分块,如下图所示: 光信0804廖娟
U200813197
(2).廖娟#软件课程设计.cpp 在 廖娟#注释.cpp 的基础上进行了一些算法改进,进行了简单的界面设计,能够实现友好的交互,系统用户进入界面控制后,对不同的功能操作提示不同,此外加入了二叉排序树的前序遍历程序、中序遍历程序和后序遍历程序。
①.先序遍历源代码:
void PreorderTraversal(struct tree *root){ if(root==0)return;printf(“%c”,root->info);软件课程设计
2010年1月
PreorderTraversal(root->left);PreorderTraversal(root->right);} ②.中序遍历源代码:
void InorderTraversal(struct tree *root){ if(!root)return;InorderTraversal(root->left);printf(“%c”,root->info);InorderTraversal(root->right);} ③.后序遍历源代码:
void PostorderTraversal(struct tree *root){ if(!root)return;PostorderTraversal(root->left);PostorderTraversal(root->right);printf(“%c”,root->info);} 光信0804廖娟
U200813197
1.5 程序流程
廖娟#注释.cpp的主程序的流程图如下: 软件课程设计
2010年1月
创建二叉树的流程图如下: 光信0804廖娟
U200813197
二叉树查询的流程图如下: 软件课程设计
2010年1月
二叉树打印的流程图如下: 光信0804廖娟
U200813197软件测试
2.1 测试环境
Microsoft Visual C++
2.2 廖娟#注释.cpp 的测试过程
但是在测试的过程中也发现了一些问题,设计示例给出的源代码中存在几个问题在下图所示操作中暴露出来了:软件课程设计
2010年1月
具体的解决方案见算法改进。
2.3 廖娟#软件课程设计.cpp 的测试过程
输入50个数字(或字母),对 廖娟#软件课程设计.cpp 进行测试。(1).程序运行前的初始界面 光信0804廖娟
U200813197
(2).输入数据及二叉树打印的画面
(3).选择操作的提示画面 软件课程设计
2010年1月
(4).程序测试时的画面
①.选择1,进行先序遍历; ②.选择2,进行中序遍历; ③.选择3,进行后序遍历;
④.选择4,进行查询结点,再输入要查询的结点e,找到了,输出:
Successful search!!key=e
继续输入w,同样查询成功; ⑤.输入m,没找到,输出结果:
Search Failure!!光信0804廖娟
U200813197
⑥.再次选择3,进行后序遍历,与③输出相同;
再次选择2,进行中序遍历,与②输出相同; ⑦.再次选择4,进行查询结点,运行结果正常; ⑧.再次选择1,进行先序遍历,与①输出相同; ⑨.选择8,输入错误,没有对应的操作,输出:
您 的 输 入 有 误,请 重 新 输 入!!⑩.选择5,进行退出操作,输出:
光 信 0 8 0 4 ———— 廖 娟0 1 0 年 1 月软件课程设计
2010年1月算法改进
3.1问题发现
在完成第4项选做项目时,程序前面部分的创建、查询、打印二叉树的算法仍采用已给出的设计示例中的算法,但是在测试过程中发现存在问题。光信0804廖娟
U200813197
(1).问题一:
第一次先序遍历的输出结果为:edaf
第二次先序遍历的输出结果为:f 经过观察及调试发现问题在于查询二叉树子函数,其中root是根结点,运行查询后root就被移动了,所以再次要求先序遍历的结果就与第一次先序遍历的结果不同。
未改动前源代码如下: 软件课程设计
2010年1月
(2).问题二:
设计示例中给出的函数运行后,没有退出的方式,即没有出口,程序无法正常退出。
3.2解决方案
(1).问题一改进方案:
函数内部定义一个指针tree *t,用 *t指向根结点,这样进行查询操作后根结点就不会移动了。
改动后源代码如下: 光信0804廖娟
U200813197
(2).问题二改进方案:
在switch语句中增加:
case 5:
printf(“
光 信 0 8 0 4 ———— 廖 娟nn”);printf(“ 0 1 0 年 1 月nn”);return;来实现退出程序的操作,具体解决方案见
廖娟#软件课程设计.cpp 的源代码。软件课程设计
2010年1月开发体会
刚刚拿到软件课程设计的题目时,我震惊了,二叉树?这是什么东西,上学期学习C语言的时候好像没学到二叉树啊。听了老师的介绍才知道做这个题目的软件课程设计还要先学习一下数据结构中关于二叉树部分的知识,当时我真的是有些不知所措,本就不怎么好的C语言加上完全不会的数据结构二叉树使我开始怀疑:三个星期后我可以完成这份关于二叉树的查找的软件课程设计吗?
最初的几天也确实很没有头绪,只是想着想把老师给的资料都看了,看完了之后走一步算一步吧,可是看完了之后发现仍然没有很大的收获,连怎么二叉树到底有什么用都不知道,对于这个题目依然是十分陌生。可是时间紧迫啊,于是找了位学习过数据结构的同学借了本数据结构的书,研究了一番,在加上在网上搜索了一番终于有些头绪了,知道这份课设到底要我们做什么了!
接下来的几天,随着了解的加深,自己开始慢慢的做课设了,当然从和同学的交流中,我也学到了很多。这之后我一步步的完成了对设计示例的注释,对递归算法的理解,以及先序遍历、中序遍历、后序遍历程序的书写,最终完成了程序的开发。程序开发中我记忆最深刻的就是编写选择操作的提示界面和初始界面的时候,为了使界面更加友好,加入了一些人性化的语句,以及为了出现欢迎界面进行的许多次试验,慢慢的我觉得这个过程十分有趣,看着自己编排的界面出现在面前心中还是有些许成就感的。当然除了这些还有很令我头疼的 光信0804廖娟
U200813197
程序调试过程:在程序的调试阶段,发现程序中有许多问题,有的根本不知道从哪入手解决问题,甚至不知道为什么会出现错误,也因此耗费了很多时间,让我苦闷了很久。
在这段时间里,因为有软件课程设计,让我学到了很多知识,收获了很多我,自我感觉自己解决问题的能力提高了,并且掌握了软件开发的一些基本的方法和技巧。还记得写课设报告的时候,花了一天的时间把报告里面的所有图都画完了,从刚开始的不会用画图软件,到后来慢慢摸索最后熟练运用,画图的速度是越来越快了,让我后来甚是欣慰。
经过了这一次的软件课程设计,我感受到了C语言的魅力,也深切的体会到了“学海无涯”这四个字的分量。在以后的日子里,我所需要学习的东西还有很多很多,应了那句“书山有路勤为径,学海无涯苦作舟。” 软件课程设计
2010年1月
附录:源代码清单
廖娟#注释.cpp #include
*/ #include
/* 定义二叉树结构
*/ struct tree
{
char info;
// 定义char型变量,存放数据
struct tree *left,*right;
// 左子树指针,右子树指针
};/* 定义结构指针变量,作用创建二叉树
*/ struct tree *create_btree(struct tree *root,struct tree *r,char info);/* 定义结构指针变量,作用查询数据
*/ struct tree *search_btree(struct tree *root,char key);/* 定义子函数,作用打印二叉树
*/ void print_btree(struct tree *r,int l);
/* O(∩_∩)O~ O(∩_∩)O~ O(∩_∩)O~ O(∩_∩)O~ O(∩_∩)O~ O(∩_∩)O~ O(∩_∩)O~ O(∩_∩)O~ O(∩_∩)O~ O(∩_∩)O~ */ /* 主函数
*/ void main(){
char s[100],c,key=' ';
struct tree *root=0;
// 定义结构指针根结点,初始化为0
/* 读入二叉树的各个结点的值,并将其插入到二叉树中
*/
do {
printf(“Enter a letter:”);
gets(s);
// 数据输入过程
if(!root)
root=create_btree(root,root,*s);
// 如果二叉树还未建立,则建立根结点并保存数据
else
create_btree(root,root,*s);// 如果二叉树已建立,则建立新的子树
}
while(*s);
// 直到s字符串为空,停止输入
print_btree(root,0);光信0804廖娟
U200813197
/* 查找具有指定值的结点
*/ key='1';while(key){
printf(“Enter a key to find:”);
scanf(“%s”,&c);
root=search_btree(root,c);
printf(“press to continuen”);} }
/* Btree.C 结束
*/
/* O(∩_∩)O~ O(∩_∩)O~ O(∩_∩)O~ O(∩_∩)O~ O(∩_∩)O~ O(∩_∩)O~ O(∩_∩)O~ O(∩_∩)O~ O(∩_∩)O~ O(∩_∩)O~ */ /* 创建二叉树
*/ struct tree *create_btree(struct tree *root,struct tree *r,char info)/* struct tree *root:根结点
struct tree *r:要增加的结点
char info:要保存的数据
*/ {
if(r==0)
// 如果当前位置无结点,则将新结点插入此处
{
r=new(struct tree);
// same as function: malloc(sizeof())
if(r == 0)
{
printf(“Out of memoryn”);
return 0;
}
r->left= 0;
r->right=0;
r->info=info;
// root为空,则插入后保存至根结点处
if(root)
// 如果二叉树存在,则将新建结点与二叉树连接起来
{
if(info
root-> left=r;
else
root-> right=r;
// 按左结点<父结点<=右结点,保存数据
}
else
// 如果根结点不存在,即二叉树不存在,则将新建一个二叉树
{
r->right=0;
r->left=0;软件课程设计
2010年1月
}
return r;}
/* if = = 0 接下页
*/
/* 判断要插入的节点应该在当前节点的左子树或右子树,递归插入
*/ if(info < r->info)
create_btree(r,r->left,info);if(info>=r->info)
create_btree(r,r->right,info);}
/* create_btree(root,r,info)*/
/* O(∩_∩)O~ O(∩_∩)O~ O(∩_∩)O~ O(∩_∩)O~ O(∩_∩)O~ O(∩_∩)O~ O(∩_∩)O~ O(∩_∩)O~ O(∩_∩)O~ O(∩_∩)O~ */ /* 查询数据
*/ struct tree *search_btree(struct tree *root,char key)/* struct tree *root:要查询的二叉树首地址
char key:要查询的数据
*/ {
if(!root)
// 如果二叉树指针为空,输出Empty btree {
printf(“Empty btreen”);
return root;
}
while(root->info!=key)
{
if(key
// 按照“左结点<父结点<=右结点”查找
root=root->left;
else
root=root->right;
if(root==0)
// 如果指针为空,则退出查找
{
printf(“Search Failuren”);
break;
} } /* while(root->info!=key)*/ if(root!=0)
// 如果二叉树指针不为空,即查找成功给出信息,返回
printf(“Successful searchn key=%cn”,root->info);return root;} /* *search_btree(root,key)*/
/* O(∩_∩)O~ O(∩_∩)O~ O(∩_∩)O~ O(∩_∩)O~ O(∩_∩)O~ O(∩_∩)O~ O(∩_∩)O~ O(∩_∩)O~ O(∩_∩)O~ O(∩_∩)O~ */ 光信0804廖娟
U200813197
/* 打印二叉树
*/ void print_btree(struct tree *r,int l)/* struct tree *r:二叉树首地址
int l:当前结点的高度,根结点为0
输出的二叉树为正常树逆旋转90°后成镜像的结果
*/ {
int i;if(r == 0)
return;
//如果传入指针为0,则返回
print_btree(r->left,l+1);
//打印左结点
for(i=0;i printf(“ ”); //打印空格,用来排版控制格式 printf(“%cn”,r->info); //打印根结点 print_btree(r->right,l+1); //打印右结点 } /* *print_btree(root,0) */ 软件课程设计 2010年1月 廖娟#软件课程设计.cpp #include */ #include /* 定义二叉树结构 */ struct tree { char info; // 定义char型变量,存放数据 struct tree *left,*right; // 左子树指针,右子树指针 };/* 定义结构指针变量,作用创建二叉树 */ struct tree *create_btree(struct tree *root,struct tree *r,char info);/* 定义结构指针变量,作用查询数据 */ struct tree *search_btree(struct tree *root,char key);/* 定义子函数,作用打印二叉树 */ void print_btree(struct tree *r,int l);/* 定义子函数,作用先序遍历 */ void PreorderTraversal(struct tree *root);/* 定义子函数,作用中序遍历 */ void InorderTraversal(struct tree *root);/* 定义子函数,作用后序遍历 */ void PostorderTraversal(struct tree *root); /* O(∩_∩)O~ O(∩_∩)O~ O(∩_∩)O~ O(∩_∩)O~ O(∩_∩)O~ O(∩_∩)O~ O(∩_∩)O~ O(∩_∩)O~ O(∩_∩)O~ O(∩_∩)O~ */ /* 主函数 */ void main(){ char s[100],c; int n;struct tree *root=0; // 定义结构指针根结点,初始化为0 printf(“ ###”);printf(“## ##”);printf(“## 软件课程设计: 二叉树的查找 ##”);printf(“## ##”);printf(“## 班 级: 光 信0 8 0 4 ##”);光信0804廖娟 U200813197 printf(“## ##”);printf(“## 姓 名: 廖 娟 ##”);printf(“## ##”);printf(“## 学 号: U 2 0 0 8 1 3 1 9 7 ##”);printf(“## ##”);printf(“ ###”);printf(“n”);printf(“ 程 序 运 行 开 始 啦!!nn”); /* 读入二叉树的各个结点的值,并将其插入到二叉树中 */ do { printf(“ 请 输 入 一 个 字 符:”); gets(s); // 数据输入过程 printf(“n”); if(!root) root=create_btree(root,root,*s); // 如果二叉树还未建立,则建立根结点并保存数据 else create_btree(root,root,*s); // 如果二叉树已建立,则建立新的子树 } while(*s); // 直到s字符串为空,停止输入 printf(“ 打 印 的 二 叉 树 如 下:n”);print_btree(root,0); printf(“ ###”); printf(“## ##”); printf(“## ★★★★★★★★★ 请输入您想要执行的操作!: ★★★★★★★★★ ##”); printf(“## ##”); printf(“## 选择1—————————————进行先序遍历 ##”); printf(“## ##”);软件课程设计 2010年1月 printf(“## 选择2—————————————进行中序遍历 ##”); printf(“## ##”); printf(“## 选择3—————————————进行后序遍历 ##”); printf(“## ##”); printf(“## 选择4—————————————进行查询结点 ##”); printf(“## ##”); printf(“## 选择5—————————————进行退出操作 ##”); printf(“## ##”); printf(“## ★★★★★★★★★ 温馨提示:请选择数字键0~5 ★★★★★★★★★ ##”); printf(“## ##”); printf(“ ###”);while(1){ scanf(“%d”,&n); switch(n) { case 1: printf(“ 先 序 遍 历 为:n”); PreorderTraversal(root); printf(“nn”); break; case 2: printf(“ 中 序 遍 历 为:n”); InorderTraversal(root); printf(“nn”); break; case 3: printf(“ 后 序 遍 历 为:n”); PostorderTraversal(root); printf(“nn”); break; case 4: 光信0804廖娟 U200813197 printf(“ 请 输 入 您 要 查 询 的 结 点:n”); scanf(“%s”,&c); printf(“ 您 要 查 询 的 结 点 为:n”); root=search_btree(root,c); printf(“n”); break; case 5: printf(“ 光 信 0 8 0 4 ———— 廖 娟nn”); printf(“ 0 1 0 年 1 月nn”); return; default: printf(“ 您 的 输 入 有 误,请 重 新 输 入!!n”); break; } } } /* Btree.C 结束 */ /* O(∩_∩)O~ O(∩_∩)O~ O(∩_∩)O~ O(∩_∩)O~ O(∩_∩)O~ O(∩_∩)O~ O(∩_∩)O~ O(∩_∩)O~ O(∩_∩)O~ O(∩_∩)O~ */ struct tree *create_btree(struct tree *root,struct tree *r,char info)/* struct tree *root:根结点 struct tree *r:要增加的结点 char info:要保存的数据 */ { if(r==0) // 如果当前位置无结点,则将新结点插入此处 { r=new(struct tree); // same as function: malloc(sizeof()) if(r == 0) { printf(“ Out of memoryn”); return 0; } r->left= 0; r->right=0; r->info=info; // root为空,则插入后保存至根结点处 if(root) // 如果二叉树存在,则将新建结点与二叉树连接起来 软件课程设计 2010年1月 { if(info root-> left=r; else root-> right=r; // 按左结点<父结点<=右结点,保存数据 } else // 如果根结点不存在,即二叉树不存在,则将新建一个二叉树 { r->right=0; r->left=0; } return r;} /* if = = 0 接下页 */ /* 判断要插入的节点应该在当前节点的左子树或右子树,递归插入 */ if(info < r->info) create_btree(r,r->left,info);if(info>=r->info) create_btree(r,r->right,info);} /* *create_btree(root,r,info)*/ /* O(∩_∩)O~ O(∩_∩)O~ O(∩_∩)O~ O(∩_∩)O~ O(∩_∩)O~ O(∩_∩)O~ O(∩_∩)O~ O(∩_∩)O~ O(∩_∩)O~ O(∩_∩)O~ */ /* 查询数据 */ struct tree *search_btree(struct tree *root,char key)/* struct tree *root:要查询的二叉树首地址 char key:要查询的数据 */ { tree *t;t=root;if(!t) // 如果二叉树指针为空,输出Empty btree { printf(“ Empty btree!!n”); return root; } while(t->info!=key) { if(key // 按照“左结点<父结点<=右结点”查找 t=t->left; else t=t->right; if(t==0) // 如果指针为空,则退出查找 光信0804廖娟 U200813197 { printf(“ Search Failure!!n”); break; } } /* while(root->info!=key)*/ if(t!=0) // 如果二叉树指针不为空,即查找成功给出信息,返回 printf(“ Successful search!!n key=%cn”,t->info);return root;} /* *search_btree(root,key)*/ /* O(∩_∩)O~ O(∩_∩)O~ O(∩_∩)O~ O(∩_∩)O~ O(∩_∩)O~ O(∩_∩)O~ O(∩_∩)O~ O(∩_∩)O~ O(∩_∩)O~ O(∩_∩)O~ */ /* 打印二叉树 */ void print_btree(struct tree *r,int l)/* struct tree *r:二叉树首地址 int l:当前结点的高度,根结点为0 输出的二叉树为正常树逆旋转90°后成镜像的结果 */ { int i;if(r == 0) return; //如果传入指针为0,则返回 print_btree(r->left,l+1); //打印左结点 for(i=0;i printf(“ ”); //打印空格,用来排版控制格式 printf(“%cn”,r->info); //打印根结点 print_btree(r->right,l+1); //打印右结点 } /* *print_btree(root,0) */ /* O(∩_∩)O~ O(∩_∩)O~ O(∩_∩)O~ O(∩_∩)O~ O(∩_∩)O~ O(∩_∩)O~ O(∩_∩)O~ O(∩_∩)O~ O(∩_∩)O~ O(∩_∩)O~ */ /* 先序遍历 */ void PreorderTraversal(struct tree *root){ if(root==0) return;printf(“%c”,root->info);PreorderTraversal(root->left);PreorderTraversal(root->right);} 软件课程设计 2010年1月 /* O(∩_∩)O~ O(∩_∩)O~ O(∩_∩)O~ O(∩_∩)O~ O(∩_∩)O~ O(∩_∩)O~ O(∩_∩)O~ O(∩_∩)O~ O(∩_∩)O~ O(∩_∩)O~ */ /* 中序遍历 */ void InorderTraversal(struct tree *root){ if(!root) return;InorderTraversal(root->left);printf(“%c”,root->info);InorderTraversal(root->right);} /* O(∩_∩)O~ O(∩_∩)O~ O(∩_∩)O~ O(∩_∩)O~ O(∩_∩)O~ O(∩_∩)O~ O(∩_∩)O~ O(∩_∩)O~ O(∩_∩)O~ O(∩_∩)O~ */ /* 后序遍历 */ void PostorderTraversal(struct tree *root){ if(!root) return;PostorderTraversal(root->left);PostorderTraversal(root->right);printf(“%c”,root->info);} 参考文献 《数据结构》(c语言版)严蔚敏 吴伟民 编著 清华大学出版社 《C语言程序设计》 谭浩强 编著 清华大学出版社 《C程序上机指导》 谭浩强 编著 清华大学出版社 《标准c语言程序设计及应用》 周纯杰 编著 华中科技大学出版社 软件项目管理的理论与实践 摘要:本文在探讨CMM/CMMI、敏捷编程等相关理论的基础上,结合软件开发实践,提出了平衡敏捷与纪律的软件管理思想,并探讨了融合敏捷与CMM/CMMI的最佳实践。 关键词:CMM/CMMI,敏捷 当CMM遭遇敏捷 本世纪初,在国务院18号文件《鼓励软件产业和集成电路产业发展的若干政策》的推动,以及鼎新、东软等先驱软件企业的带动下,国内掀起了一阵CMM风暴(CMM于2000年升级为CMMI,文中在不特别针对某个具体版本时,使用CMM泛指CMM/CMMI),软件企业的CMM/CMMI评估形成了一股席卷全国的潮流。据CSDN统计,截止到2010年9月,我国通过CMM/CMMI评估的企业已达到1300家,全球排名第二。一时之间,CMM似乎成为了衡量软件企业开发能力的唯一标准,成了发展我国信息技术行业的银弹。然而,自2005年开始,一些有识之士就已经认识到CMM的局限性,纷纷撰文提出质疑。目前,随着越来越多软件企业CMM神话的破灭,CMM已经完全走下神坛。现在打开百度,搜索CMM的相关内容,除去概念、介绍性的文章外,对其持否定态度占了绝大部分,继续力挺CMM的文章几乎绝迹。由此可见,中国的软件界已经从CMM的狂热阶段转入理性阶段。 在CMM由盛转衰的同时,以强调人本、效率为核心的敏捷思想开始悄然兴起。从Kent Beck的极限编程(eXtreme Programing,简称XP)和敏捷联盟的敏捷宣言中,中国程序员开始听到CMM外的声音。而随着Martin Fowler、Robert Martin等敏捷大师登陆中国,数届敏捷大会在北京召开,整个中国软件界掀起了一股以务实、高效、简约为特征的敏捷风。目前,软件行业的媒体、杂志上,充斥着介绍XP、Scrum等敏捷方法的专题文章,秉承敏捷思想进行管理的软件企业随处可见,敏捷成了过程改进的最热门话题。 面对CMM的盛极而衰和敏捷的方兴未艾,我们不禁要问:CMM到底怎么了?敏捷真的适合我们吗?我们该何去何从? CMM怎么了 我第一次接触CMM是2000年。在此之前,我一直试图寻找一套软件开发标准,曾经学习过GB 85-88和IEEE-830、IEEE-12207等软件工程标准,但一知半解,远没有形成一个系统化过程的概念。CMM的丰富、广博确实让我眼前一亮,好象打开了一面通向世界软件技术的窗户,看到了从未想象过的世界。但是,CMM那些繁复的规定和要求,又让我望而却步,“可远观而不可亵玩焉”。2002年,在信产部政策的推动下,各地方政府纷纷出台了奖励政策,稍具规模的软件公司,都在跃跃欲试地准备CMM评估,CMM才真正走到我们面前,虽然当时还不完全了解CMM到底能带给我们什么。 其后几年,CMM/CMMI成了我工作的一部分,我对它有了更深刻的了解。可以说,CMM是中国软件行业规范化的启蒙者。CMMI-DEV 1.2的22个PA、48个特定目标、165个特殊实践,覆盖到了软件开发和管理的方方面面,让我们真正了解到什么是软件管理。每个职业软件人,无论是开发者还是管理者,都有必要了解、掌握这些内容。作为一个指导软件企业过程改进的框架,CMMI提供了阶段型和连续型两种方法论,并通过5个通用目标、17个通用实践,清晰地描绘了一条软件企业走向成熟的路线。比如CMMI-DEV 1.2 Ⅱ级的目标,就是“管起来”,无论你用什么方法,只要把计划、度量、需求、配置、质量保证等内容管起来,就认为是达到了Ⅱ级。当Ⅱ级积累到一定程度,认为各项目间有必要共享各自的经验的时候,就可以向Ⅲ迈进了。遗憾的是,我们在引进CMM的过程中,犯了急功近利的毛病,囫囵吞枣,没有真正按照框架的精神踏踏实实地进行过程改进,导致了CMM的水土不服。究其原因,我觉得问题应该出在以下几个方面: 1.CMM的移植问题。CMM起源于美国国防部和国家宇航局,所针对的都是大型项目。这些项目失败的成本巨大,对软件质量要求非常之高,因此,对过程的精细程度要求非常之高。在制定模型时,为了做到方法的完备性,所制定的过程框架又涵盖了各种情形,使过程模型更加复杂化。在移植到中国后,由于评估时间等的压力,我们并没有充分地消化CMM的精髓,没有考虑我们企业所能承受的成本,没有根据项目的实际情况进行有效裁剪,而是僵化地全套照搬,建立了过于复杂的管理流程,形成了大量面面俱到却无人问津的过程制品,反倒失去了对项目核心的掌控,导致生产效率降低,产品质量下降。而过程改进人员又普遍脱离了开发实践,CMM成了教条,使开发人员产生了反感情绪。 2.CMM缺少工程方法。CMM是一个能力标准,只讲要做什么,却没讲怎么做。例如CMMI-DEV 1.2 Ⅱ级的7个PA,全部是项目管理的内容,基本未提及工程方法。CMMI-DEV 1.2 Ⅲ的11个PA,虽然涉及到RD、TS、PI等技术领域的内容,但只提了宏观要求,并未涉及细节。这种设计方式,是因为CMM的创建者假定软件企业已经具备了适合本企业的、完整有效的软件工程方法论。我国企业在引进CMM前,基本上还没有形成自己的软件过程和文档体系,而是寄希望于CMM来改善这种情况。在CMM实施中,又普遍存在重管理轻技术的观点,忽视了企业资产的建立,通常是照办咨询公司提供的模板,没有进行有效的本地化,没有认真探索适合自身的工程方法,从而导致管理先进、技术落伍的不良状态,也从根本上违背了CMM“过程改进”的基本思想。 3.CMM不适合小型项目。CMM起点很高,对各个环节要求极严,是真正的重量级方法。对周期短、回报小、资源不足的小型项目来说,使用CMM的成本太高,可以说是得不偿失。这一点,在CMM刚刚进入中国时,SEI的专家们曾反复声明,CMM的创始人Watts Humphrey老先生也一再强调。在CMM之后,Humphrey先生又建立了用于小规模团队的TSP(Team Software Process)模型和用于个人的PSP(Personal Software Process)模型,作为CMM的补充。在为波音公司的IT部门进行CMM咨询时,Humphrey先生根据各部门的实际情况,分别制定了实施CMM Ⅲ、CMM Ⅱ、TSP、PSP的不同方案。由此可见,CMM并不是放诸四海而皆准的银弹,无论是公司还是项目,选择CMM,都应该根据自己的实际情况进行理性的选择,而不应该生搬硬套,以命令的形式强制推行。反过来,如果选择了CMM,就要提供足够的资源,否则就会事与愿违,反倒降低效率,影响产品进度和质量。 4.CMM的知识更新问题。CMM初稿是在1986年提出的,87年正式发布1.0版。它的基本内容,都是基于瀑布模型设计的。按照《人件》和《最后期限》的作者Tom DeMarco的说法,“CMM 已经有超过 20 年的历史,它的成功经验都是在 1985 年前获得的。CMM 试图将一个固定的模型强加于一个日新月异的行业之上,它鼓励你效仿 IBM 在 1970 年代所采用的软件开发方式。僵化,不敢面对变化,这是如今的软件业最忌讳的。”2006年8月发布的CMMI-DEV 1.2版本,开始寻求对这一局限进行突破,但是进展甚微。例如,目前迭代式开发已经被公认是先进的开发组织模式,可以有效应对变化。而CMM在某些方面却限制了迭代的应用。比如里程碑式的需求评审、设计评审,就是典型的瀑布模型的影响,与迭代方法中随着开发的深入逐步获取需求的思路完全矛盾,造成了两者的冲突,客观上限制了基于迭代的新式工程模型的应用。 5.实施过程中理论和实际的脱离。国内的CMM实施,最头疼的就是找不到合适的SEPG和QA人选。按照CMM的思想,SEPG和QA应该来自具有丰富开发经验的技术人员,能在开发过程中得到软件人员的尊重,并给予全方位的指导,从而得到客观的洞察力。而我们的软件企业通常比较年轻,人才积累少,SEPG和QA的软件经验普遍不足,兼之过于追求理论上的完美,不注重跟踪过程执行情况,不注重收集反馈信息,导致我们的流程、制度脱离开发实际,引起开发人员反感。正如软件界泰斗Boehm博士所说的那样,“过程改进黑暗面的诱惑力是巨大的,实施者们很容易受其诱惑而陷入只追求表面文章的黑暗面之中”。这样的过程改进只注重满足标准,片面追求过程与规范的符合度,脱离了软件开发实践,忽略了实践对理论的验证、反馈,违背了过程改进的初衷,偏离了提高效率、提高软件质量的根本目标。敏捷的特征 以CMM为代表的传统意义上的软件方法学描述,通常“能够”处理任何大小的项目,而实际上真正的困难就来自于如何对这些方法加以裁剪以适合较小的项目。针对这种理论与实际的脱节现象,敏捷方法应运而生。相对于CMM这样的重量级方法,敏捷方法常被认为是“轻量级”方法。敏捷的倡导者认为,软件产品开发无法一开始就能定义产品最终的规程,开发过程中需要研发、创意、尝试错误,所以没有一种固定的流程可以保证专案成功。开发团队应有明确的最高目标,熟悉开发流程中所需具备的最佳典范与技术,具有高度自主权,紧密地沟通合作,以高度弹性解决各种挑战,确保每天、每个阶段都朝向目标有明确的推进。 相对于传统方法,敏捷方法更重视“人”在软件研发中的作用,重视效率,重视对变化的积极响应,倡导迭代式开发,反对机械地盲从既有过程,反对面面俱到、堆积如山却无人问津的文档。自1996年敏捷先驱Kent Beck提出极限编程思想后,敏捷方法得到了广泛响应,敏捷爱好者于2001年成立了敏捷联盟,并发表了敏捷宣言: 注重个人及互动 胜于 过程和工具 注重可用的软件 胜于 详尽的文档 注重客户协作 胜于 合同谈判 注重响应变化 胜于 恪守计划 2002年后,敏捷方法得到了迅猛发展。其中影响至深、波及至广的当属极限编程(XP)和Scrum方法。 极限编程是敏捷理论的先驱,“极限”的含义是将在开发中总结的最佳实践发挥到极至。例如,如果你认为迭代是好的,那么就将迭代的周期压缩至最小,甚至几天、几小时一次迭代。严格来说,极限编程并不是一套完整的方法论,而是一组核心理念和一套最佳实践的组合。XP倡导沟通、反馈、简单、勇气四个核心价值观,主张项目的设计、结构要保持简单,要注重沟通和用户反馈,要有勇气接受变化、重构代码。XP提出了项目计划(The planning game)、小版本(Small releases)、隐喻(Metaphor)、简单的设计(Simple design)、重构(Refactoring)、测试驱动(Test-driven)、结对编程(Pair programming)、代码共享(Collective ownership)、持续集成(Continuous integration)、不加班(40-hour week)、现场客户(On-site customer)、编码标准(Coding standards)等十二个核心实践,其中重构、测试驱动、小版本(迭代)、持续集成等实践已经成了敏捷思想的核心,被现代软件工程理论广泛接受。XP作为敏捷方法的先驱,最大贡献是为敏捷方法提供了大量基础实践。它的基本思想被各种敏捷方法广泛接受、继承,为敏捷的盛行奠定了基础。 Scrum方法的名字取源于英式橄榄球争球队,其用意就是要把体育比赛中那种团结、拼搏的精神施加于软件团队。和XP相比,Scrum提供了更具体的工程管理机制,从而使Scrum的可操作性更强。这也是近年来Scrum方法盛行的原因。Scrum方法的核心,是将开发过程分解为一系列小的迭代,每次迭代称为一个Sprint(冲刺)。每个Sprint通过计划会议明确任务,通过每日例会掌控进度、问题,通过评审会议总结成果。如此反复,经过一系列可控的“冲刺”,最终达成项目目标。其基本流程描述如下: 1.列举可以预知的所有任务,包括功能性和非功能性任务,形成所谓Backlog。2.将整个产品的Backlog分解成一系列Sprint Backlog,这个Sprint Backlog是按照目前的人力物力条件可以完成的。3.召开Sprint计划会议,划分、确定这个Sprint内需要完成的任务,标注任务的优先级并分配给每个成员。Sprint的任务是以小时计算的,并不是按人天计算。 4.进入Sprint开发周期,在这个周期内,每天需要召开15分钟的每日Scrum例会。5.整个Sprint周期结束,召开Sprint review meeting,将成果演示给Product Owner。该会议为外部会议,邀请干系人参加,一般不超过4小时。 6.团队成员最后召开Sprint retrospective meeting,总结问题和经验。该会议为内部会议,时间不超过3小时。 7.这样周而复始,按照同样的步骤进行下一次Sprint。 无论是XP还是Scrum,其基本思想都是互通的。它们所倡导的最佳实践,看似一个个独立活动,实际上具有很高的耦合度,不能孤立地执行。例如,XP的共享代码权,如果没有编码标准、结对编程作为基础,是很难实现的;小版本没有重构作为保障,会导致结构的混乱;Scrum的每日例会,要以“站立会议”的方式进行,以保证效率;Scrum的Sprint要以持续集成、重构等实践作为保证,否则无法维护产品的完整性和可靠性,等等。 敏捷以一种充满活力的方式,挑战了传统软件工程思想的沉闷,激起了全球软件人员的强烈反响。然而,任何事情都有其不利的一面,敏捷也是如此。敏捷无法管理大型项目,即使对比较适合敏捷的中小项目来说,敏捷也有自身的弱点,例如: 1.敏捷过于依靠个人素质和Team leader的领导能力,因此在团队成员较新,缺乏足够的经验、技巧和敬业精神时,敏捷会失效; 2.敏捷经常会被误解成不写文档。事实上,敏捷反对的只是面面具到、求全责备的文档和过程,而不排斥必要的文档。例如XP的12个核心实践,就提到项目计划、隐喻和简单的设计三个涉及文档的活动。敏捷只是提倡用一种更直接、更轻量、更易于理解的方式编写文档,而不是一概否定文档。 由此可见,以CMM为代表的传统方法和敏捷思想实际是事务对立统一的两个方面。传统方法强调过程、强调纪律,而敏捷方法强调个体、强调创造。如果将两种思想有机结合起来,取长补短,达到平衡,就能找出更合适的过程改进之路。平衡敏捷与规范 在敏捷与传统为谁是谁非的问题争论的不可开交的时候,一些有识之士已经在考虑两者的融合。其中比较有代表性的一位,是以创造了COCOMO模型、螺旋模型和经典名著《软件工程经济学》而闻名的Boehm博士。Boehm博士在2003年出版了《Balancing Agility an Discipline》一书,对平衡敏捷和规范的问题进行了详细的论述。该书的中文版《平衡敏捷与规范》也已经于2005年由清华大学出版社出版。可见,平衡敏捷与规范,已经是被国内外学者所认同的发展之路。敏捷与规范之争,大致可以归结为以下两个方面: 1.人与过程孰重孰轻之争,或者软件到底是“工程”还是 “艺术”之争; 2.质量尺度的把握,或者说,需要为质量付出多少成本。 人与过程之争,焦点是软件开发过程创造性的地位问题。CMM把软件开发过程看作一个工程过程,希望利用在制造业等传统行业中获得的经验来管理软件开发,对开发中的“个人英雄主义”行为持明确的否定态度,倍加推崇正确的过程、严格的工序和绝对的纪律。而敏捷方法的核心就是强调发挥个人或团队的创造性,主张按照项目特点选择过程。在敏捷专家看来,没有什么规范是固定不变的,所有过程都由人而定,都是为项目成功服务的。敏捷和规范各有所长,以CMM为代表的规范过程更适合需求明确的大型项目,而敏捷更适合具有挑战性的研究项目。 质量尺度的把握。CMM强调质量至上,不会因为效率牺牲质量。敏捷强调效率,一些敏捷方法提出了“满意质量”的概念。满意质量基于“任何事情都带来成本,而我们所想要的总是超过我们的支付能力;质量在本质上是有条件的和主观的;为了在软件方面达到完美,我们不得不解决许多困难问题、达成许多折衷和解决相互冲突的价值,完美不会很容易或机械性地实现”的基本前提,提出了满意质量的定义:(1)可带来足够的利益;(2)不存在致命性问题;(3)所带来的利益超过问题所造成的损失;(4)在当前条件下综合考虑所有因素后,进一步的改进所带来的损害大于其带来的帮助。满意质量否定了质量至上的观念,说明了敏捷思想更加务实的价值观。应该说,CMM的质量目标更适合作为一种文化或信念,而满意质量是对质量目标更理性的思考,更具有说服力和实用性。 敏捷强调个体、强调效率,但同时对个体素质要求较高,局限性较大。而CMM强调过程,强调质量,更适合于简单、重复的生产活动,很难应付复杂多变的情况。事实上,敏捷与规范正是软件开发过程中两个不可或缺的方面。过分强调自由,开发过程就会失控,回到软件危机前的“混沌”状态;而过分强调规范,又会导致僵化,扼杀人的主动性和创造力。因此,软件管理的目标,就是平衡敏捷和规范的矛盾,使开发活动高效、有序地进行。对已经通过了CMM/CMMI评估,但仍希望持续改进的软件企业,我觉得最直接的平衡方法,是用敏捷的观点重新审视既有规范,用效率观点重新评价各种管理活动,逐步剔除其僵化、低效的部分,最终达到平衡。具体方法可概括如下。 1.对项目分类进一步精细化,提供更丰富的生命周期模型,并提供与之相适应的模板和规范要求,使之能够尽量适应不同类型项目的情况。通过CMM/CMMI评估的企业所采用的流程规范,大多是继承自咨询公司提供的模板。虽然在改进过程中有适当裁减,但并未真正接受实践的检验,而且普遍不能支持新的生命周期模型。要想让规范更好地支持开发过程,帮助企业提高开发效率、产品质量,就应该不断吸纳新知识、新思想,不断建立新模型,使企业资产库不断得到扩充。另一方面,企业资产库对开发部门应该是开放的。开发人员是推动企业知识更新最积极的因素,管理人员应该积极支持、帮助、配合项目组使用创新方法、过程,认真跟踪、观察新方法的执行效果,及时总结经验教训,将新方法及时合并到企业资产库。 2.提供更灵活的裁减条件,减少不必要的中间环节,给予项目经理更多的控制权限。任何过程都有其局限性,而每个项目都有其特殊性,不可能通过机械地复制既有过程就达到复制成功的目的。这一点,SEI的专家也是认同的,CMM的Ⅱ级命名为“可重复级”,升级到CMMI时更名为“管理级”,就隐含了这个道理。软件不同于简单的生产加工活动,是一个充满挑战和创造性的工作,软件管理也不可能完全照搬企业管理的经验,而必须强调“人”,特别是项目经理在整个过程中的主导作用。给予项目经理更多的控制权限,尤其是过程裁减的权限,更有利于发挥项目经理的聪明才智,引导项目走向成功。这是敏捷思想的精髓所在。对开发过程中的管理活动,要深入分析其对具体项目的作用,才能作出是否需要的合理判断。以专家评审为例。理论上,专家评审可以集中专家的智慧,对开发活动肯定是有益的。但某些企业由于环境、业务复杂度、技术复杂度、人际关系等等原因,专家可能不愿意或没能力提供有效意见,这样评审就不能达到预期目的。如果评审成了走过场,就要引发深度思考,考虑评审所带来的收益是否大于付出的成本,并决定是否裁减评审活动了。裁减的最终决策权应该交给项目经理,而不是SEPG人员。因为项目经理要对项目总体负责,只有他最了解、最关注项目的成本、进度、质量,其它人员的意见都具有局限性、片面性。 3.管理体制要从实践中来,到实践中去。所有针对软件开发的管理活动,都是为了让开发工作更有效、更可靠、更可控,都是为开发服务的。敏捷的最大魅力,就是所有最佳实践都是来自于开发活动的,所以才会得到开发人员的广泛拥戴。因此,管理制度的制定,尤其是过程、文档模板的制定,要坚持实践是检验真理唯一标准的原则,坚持从开发实践中总结经验,积累财富。要杜绝闭门造车式的过程改进,无论多么完美的理论,都要经过实践检验后,才能验证其正确性。软件管理人员必须具备软件开发经验,并不断深入开发实践,体会规范的实际运用效果。管理规范要经过实践检验后才能形成制度,并且要考虑是否能为开发人员所接受,所增加的管理成本是否物有所值等因素。如果脱离了实际,制度就会僵化,变成阻碍开发工作的束缚,达到适得其反的目的。 4.发现问题,量体裁衣,逐步实现过程改进。罗马不是一天建成的,任何进步都要有一个普及、接受、适应的过程。CMMI 的组织过程焦点(OPF)明确地列举了组织过程改进的方法。在CMM实施阶段,由于时间的压力,企业可能没有真正按照CMM的精神来实施过程改进,急于求全、求大,或多或少地存在制度与实际两层皮的情况。要改变这种状态,应该坚持持续改进的精神,改进要按照OPF的要求,评价组织过程,发现最薄弱环节,找出最紧迫的过程改进需要,制定改进计划,实施过程改进。按照这种方式,即使每次改进仅完成一个PA,只要真正落到实处,就会取得实际的进步。如此反复,企业就会得到真正的发展。如果违背了这个规律,一味求大求全,浮于表面,过程改进可能永远是一句空话。5平衡管理与技术 在平衡敏捷与规范的讨论中,还有一个不容忽视的问题,就是平衡管理与技术的关系。软件是一个技术密集型行业,是一种纯脑力劳动,技术对于项目成功的重要性,是不庸质疑的。在CMM登陆之前,我们普遍存在重技术、轻管理的现象。CMM作为一个管理框架,重点在于强调管理,正是对片面强调技术的纠正。然而,随着CMM思想的不断深入,又难免产生矫枉过正的情况,反倒让软件企业忘记了立身之本,忽略了技术的地位,造成管理至上的错误。管理与技术孰轻孰重?如何摆正管理与技术的关系?要想平衡管理与规范,这些问题都是不可避免的。 1.软件开发活动中技术的地位问题。软件不同于传统企业,软件产品的形成过程,主要依靠人的思维活动,是看不见、摸不着的。管理的目的,是为了引导人的思维活动按正确的方式发展,但是决不能替代人的思维。有人说,产生文档的根本原因,来自于项目经理的恐慌,因为项目经理无法感知、控制软件项目的进度和质量,只能依赖文档来进行监控。如果忽视了技术、技能的培养,忽视了软件人员的素质建设,思维就失去了基础,仅仅依靠管理、纪律,是不可能获得成功的。尤其在客户要求日益复杂、技术日新月异的今天,技术的重要性越发突出。一个良好的设计思路、技术决策,往往是觉得项目成功的关键。因此,应该正确认识技术在软件活动的地位,尊重知识,尊重技术,让管理为技术服务。 2.客观分析企业的状态。管理和技术是保证项目成功的两个决定因素,不能偏废。作为企业领导,要实现过程改进,就要客观分析企业的状态,分析清楚企业现在的弱项是管理还是技术,然后再制定相关政策,而不能想当然地片面强调某一方面,加剧不平衡状态。我个人认为,在没有实施任何认证的企业,忽视管理的可能性较大;在通过了ISO9000、CMM的企业,则往往夸大了管理,忽视了技术。 3.客观分析管理和技术的分别。面对企业在开发过程中暴露出来的问题,要进行客观、深入的分析,判断是管理问题还是技术问题,再采取相应措施。比如现在普遍存在的需求失控的问题,从表面上看,是需求开发(ReqD)和管理(ReqM)的问题。但是,如果深入到问题本质,可能会发现,需求变更是不可避免的。那么,就要从架构设计和开发过程方面找问题。例如可以采用组件式开发,让软件易于适应变化;可以使用原型法,让用户尽早看到产品;或者使用迭代式开发,及时规避风险,让产品逐步接近用户目标。如果死钻牛角尖,一味在需求调研、文档、评审上下功夫,就会事倍功半,降低效率。 4.注重技术人才的培养。“盖成非常之事,必待非常之人”。两千年前的汉武帝,就已经认识到人才的重要性。正是因为具有不拘一格用人才的非凡气魄,汉武帝才能挖掘出卫青、霍去病这样的军事天才,建立不世之功。在软件行业,也不乏盖茨、裘伯军、王江民这样以一己之力获得巨大成功的先例。因此,软件研发,尤其是开拓性软件的研发,必须要有大批具有专业知识、超凡能力的“非常之人”。软件企业要具备容纳百川的胸怀,重视技术人才的挖掘、培养,提供钻研技术的环境,打造尊重技术的企业环境,造就技术过硬的拔尖人才,才能提高自身素质,建立企业的核心竞争力,在市场上保持竞争优势。结束语 前文在剖析CMM的利弊的基础上,用敏捷观点重新审视了过程改进的方法,并阐述了软件企业中管理和技术的关系。最后,我们再回顾一下敏捷宣言,权作本文的结束语吧。 注重个人能力,注重创新,注重互动,反对僵化的过程和低效的工具 注重编写好用的软件,反对面面具到却无人问津的文档 注重客户协作,避免生硬的商务谈判 注重适应变化,响应变化,反对墨守成规,恪守计划 1自动化测试 传统的测试已经无法满足测试的需要,自动化测试应运而生,自动化测试是指在预设条件下运行,包括正常条件和异常条件,自动化主要研究的是自动化框架测试、自动化测试脚本技术、自动化用例生成。通过资料了解,C-ATFM模型。该模型基于C语言,面向对象集成环境,采用源码嵌入有效的分析软件的代码、词法、语法、策略、指令。并且随着软件工程及软件测试的发展,自动化的机器测试发展更有前景。 2下面简介软件测试的过程 2.1模块测试 模块测试主要针对软件设计中的程序模块,通过测试技术测试程序块是否正确,模块测试的主要目的是测试程序内部的错误,根据程序设计的结构检查代码和程序是否合理,是否符合设计思路和理念,是否能够正常运行。 2.2组装测试 在模块的基础上,需要将所有模块的功能全部测试完成后组装成为系统,组装测试的目的在于,连接所有模块之后,模块之间的接口、触发器是否能正常运行,并且计算显示的数据是否正确,模块之间的功能是否互相冲突,是否达到预期的目的和结果显示,是否构成正确的、预期的数据结构。不同模块之间的误差有多少,有多少可以解决,有多少不能解决。 2.3确认测试 确认测试的目的是验证软件的功能和特性是否达到预期的愿望,是否能按照预期的组织结构、系统结构、用例分析和时序分析运作,并且进行验收测试和安装测试。 2.4系统测试 系统测试是确认软件是否与硬件互相支持,是否能满足软件使用者对软件的需求和操作简便的愿望,比如说查询模块运行完后界面中查询条件应该为查询之间输入的查询条件。系统测试保证了系统的正常运行,另外很重要的就是权限测试,系统在研发之初定义的权限信息和权限功能是否实现,是否发现软件成品与软件定义不符合或者矛盾。 3软件测试技术的地位 一个成功的测试用例在于发现了至今尚未发现的缺陷。其实,软件编程的过程也会出现一些不可避免的错误,例如:对于用户需求的错误分析和编程出现的一些语法错误,如果软件与发票费用相关更是与测试密不可分。软件不断地接近成熟和完成以及投入使用阶段,软件测试工程师必须更加谨慎的检测每一部分程序,一段程序的完成,测试工作量占有总工作量40%以上,这就给我们说明:测试是软件开发成功的重要组成部分。第四篇:软件项目管理的理论与实践
第五篇:软件测试技术与管理方法探讨论文