`
java-mans
  • 浏览: 11424461 次
文章分类
社区版块
存档分类
最新评论

软件工程学习总结

 
阅读更多

大赞!写得非常好!他将软件工程当成自己的一项技能,而非软件工程。


未接触软件工程之前一直都非常想学这门课程,因为觉得这门课非常NB,是那些有工程师称号的高手才摆弄的东西。但学过之后,最大的感触却是:软件工程方法一定要从娃娃抓起,否则到了后面坏习惯已养成后再回过头来修正,那绝对是地狱般的磨难。下面就是我在近两个月的学习中一些总结和体会,希望对后来者有所补益。由于是初学这门课程,难免浅薄和有所错漏,还望大家多多指教。

软件工程的由来

据说上个世纪60年代的程式员都是天才,写程式就像写日记相同,吃过晚饭没事干随手就能写几个出来玩,第二天还能拿去卖钱。所以那时候程式员在大家眼中,跟那些搞美术,音乐的是一类的,被称为“艺术家”。

但事过境迁,就像所有人都不会嫌钱多相同,永远都不会有人嫌CPU快的。于是,随之而来的就是硬件的迅猛发展和越来越变态的软件。记得以前常去同学家拷游戏,通常几张软盘就能搞定,而目前的游戏,两三张CD-ROM都算少的了。像如此庞大复杂的怪物,就算你是怎么的天才,一个人肯定是搞不定的,否则,等你把程式写出来,人家Intel连奔腾N都研发出来了。既要研发大型的软件还要追求速度(这样才能赚钱),于是非常自然地,合作的概念被提了出来。

在开始合作的初期,由于大家都习惯了当非常有个性的“艺术家”,结果可想而知,一个是毕加索派的,而另一个是意大利印象派的,再加上一个画泼墨山水画的,要是像这样凑出来的东西都能不出问题的话,那么Bill早就转行了。所以,那时侯的大型软件,据说“蓝屏”比WINDOWS 98还多。

告诉我们,万物都是从量变到质变的。随着问题的不断涌现,一些master们开始尝试去总结经验,并归纳了一些规范去指导软件的分析,设计,实现,测试,维护,人员交流协作,项目预算及时限控制等方方面面,这就是软件工程的前身。

软件工程到目前已发展了30多年,能说是相当成熟的了。目前研发软件,据说都是一大帮人排排坐,按着一整套的规章制度来干活。于是,软件研发成了“工程”,程式员也就沦为“工人”了。

最初提出问题的是Dijkstra。他于1968年写给ACM的一封题为Goto Statement Considered Harmful 的信中,指出了GOTO语句的负面作用,并提出了解决之道,其引发的一系列效应最终带来了软件工程的诞生。(信的原文可在www.acm.org/classics/oct95 上看到,不过,当你看到本文的时候,天知道他还在不在那里!)

软件工程的核心

无论是在上个世纪还是在目前,软件研发所涉及的工作基本上都没有变化,他们都起始于一个实际需要或某个灵感,然后就是分析,设计,编码,调试,维护。这些任务以某种方式动态地结合起来就构成了软件研发的整个过程,这就是所谓的“软件研发周期”。

但对于这些工作,具体怎样做,什么时候做,每个人都有自己的一套方式,甚至有的人有几套方式。这样,当几个人合在一起干活的时候,最终的结果就只能是一片混乱。所以就需要一套规则,大家都按规则来办事,问题就会少得多。好的规则就叫做规范,规范都是由一些master们根据经验总结的,又经过长时间的历练,不断地被补充修正,能说都是精华,按照规范来干活,对于提高软件质量和工作效率自然大有帮助。

而软件工程,说白了,就是这样一套用于软件的团队研发,以提高软件质量和程式员工作效率为目的的规范。其核心就是,对于软件研发的5个重要组成部分:需求分析,设计,编码,调试,维护,怎么组织这5个部分的工作,及怎么完成每一个工作。简单来说,就是对于总体的组织和对于局部的实现。

规范只是提供一个好的例子,以描述一种思想,具体到每一个环节怎样实现,对于不同的公司或团体则是各有千秋,因为根本就不可能存在一套放之天下皆可行的标准。就像C++,也只是提供了一套标准,不同的编译器都有各自的实现,对标准的支持程度也互不相同。所以,在不同的公司或团体中,尽管核心思想都是大同小异,但具体到每一个步骤,往往都是不相同的。我手上就有一份GB8567-88的文件模板,对于那些顶多只有几千行的小程式来说,如果真按上面的需求全写上了,简直就是一种折磨!据说,当前业界最权威的标准是CMM

软件研发过程的组织

怎么组织软件研发过程中的每一个步骤,就是软件研发周期模型要解决的问题。

其实研发软件,就像是解决一个逻辑问题。想想自己平时是怎样写程式的。首先是要有一个想法,即我写的这个程式是要干什么的;然后就是对要实现的核心功能大概构思一种或多种实现方法,并从中选出一种自认为是较好的;接下来就是将涉及的各种主要或次要功能分成各个模块;最后就是分模块来编码和DEBUG。在我看来,除了第一步外,其余的步骤应该是个循环的过程。在编码的过程中,你总是需要不断地回过头来修改原先的模块设计,甚至最初选定的实现算法。例如,最简单的情况是,你通常都会忽然发目前两个成员函数中有相同的代码,这时,程式员的直觉告诉你,你应该为你的类再添加一个private成员函数并将公共的代码放于其中;又或是,你忽然发现一个模块中的某个功能具有非常高的通用性,完万能提取出来作为一个独立的功能组件,而你也确实应该这样做;要是倒霉一点的话,你非常有可能会在最后调试的时候忽然发现,你的程式跑得太慢了,连你自己都无法忍受。于是你找呀找,终于找到了80/20中的那段可恶的20,原来是用了一个ON)的算法,这时你就得老老实实地换一个更好的算法。

总之,除非你是先知,否则,对于一个具有一定规模和复杂度的软件来说,在“设计—编码”这个过程中,实在有太多的不可预知性和变化性,你根本不可能全盘地把握住每一个细节。当然,这是建立在我现时的水平之上的观点。我不知道是否成为高手以后会有所不同,因为我身边没有那样的人。

既然软件研发是个具有不可预知性和变化性的动态的过程,那么,对其每一个步骤的组织,即周期模型,就必须包容他的这种性质。

目前来看一下最古老,最经典,同时也是最倍受批评的瀑布模型。

瀑布模型是一种线性模型,其最大的特点就是简单直观。他将软件研发过程规划为“分析—设计—编码—测试—维护”的线性过程,也就是说,你必须首先把你的软件要干的每一件工作都分析得彻底完全,再对每一个模块,每一个接口,事无巨细,都设计得非常完美,然后才开始编码的工作,并且在编码的时候就像在对着图纸砌模型,根本不用再回头作所有修改,当然,是在把所有的代码都写完以后才开始测试的。

整个过程,光想一下就觉得冒冷汗!

瀑布模型完全忽视了软件研发过程的动态变化。恐怕只有那些已发展得非常成熟,且规模不大的系统,例如:用Access做后台,用VB画前端的数据库应用程式,才有瀑布模型一展拳脚的地方。

相比之下,目前常用的一些周期模型则更接近于人的自然思维,例如螺旋模型就是一种我比较喜欢的模型。

软件研发过程的实现

具体到每一步的工作要怎样完成,我前面已提到过,是非常灵活的,只要把握住大体的方向就行。在进行分析,设计,编码,调试,维护这几部分的工作的时候,最核心的就是文件的编写。文件的作用在于以下3个方面:一是能帮助整理思路。把要完成的目标,系统的结构,每一个模块的功能等整理一下,然后分门别类地写下来,这样在研发的过程中,就有据可依,在需要回过头来修改设计的时候,也有证可考。二是便于交流。想象一下开会时的情形。一大帮子人争先恐后,激烈辩论,然后会终人散,思想灵感也就随之散了,结果是开了半天会,什么也没讨论出来。这就是后来会议记录被发明出来的原因。在脑子里的东西一多,就会散而且乱,用语言表达的时候,非常容易会丢三落四,别人也非常难把握住你的思想。但经过整理写在纸上以后,则会清晰得多,无论是别人还是自己,看起来都能一目了然。三是能作为以后维护时的参考资料。有一句名言:“笔和纸永远都比大脑可靠”,意思就是说,放在大脑里的东西说不准哪天就忘了,但写在纸上的东西,只要不发生什么意外,一般是丢不了的。当过了一段时间,你需要再回过头来修改你的程式的时候,你就会发现,你以前写下的文件实在太有价值了。别指望你的原始码,对于复杂一点的程式来说,单纯的原始码几乎会扼杀掉你所有的时间。

至于文件怎样写,教科书上大多都是一条一条列得满满的,就像一些地方政府的规章制度相同,其实大可不必,只要能满足需要就行。如果是在公司,则每个公司大多都有一套自己内部的文件模板,个人没有选择的余地。而对于像我这种业余的,写个程式除了练练手艺,无非就是供自己和亲朋好友玩玩,则根本没必要搞得过于复杂。以下就是我自己的一份文件模板的概要,麻雀虽小,但五脏俱全。

可行性分析 就是关于当前项目能不能干的分析结果。主要考虑的方面包括:

1)是否能把这个项目研发出来;

2如果能的话,预计需要多少时间,能否满足客人的时间需求;

3需要多少人力和资金的投入;

4最重要的是,这个项目能否赚钱,能赚多少。

5还要对可能存在的风险进行评估,例如,万一项目主管被车撞了要怎么办。当然,这对于我来说毫无意义,我在这里写上只是为了保持完整而已。

= = =

项目描述 这是在决定立项以后,对当前项目的一份扼要说明。必须包括以下几个方面:

1)项目的名称或编号

2)对客户方的描述;

3)对研发人员的描述;

4工程任务的描述;

5)工程的输入和输出

6研发环境

7)其他的附加条件

在这里,对工程任务的描述是从整体的角度来说的,例如:能对当前的象棋棋局进行分析并作出最优决策的人工智能系统。而工程的输入输出则能这样写:输入当前的象棋棋局的数据描述;输出最优的棋步,包括选择行动的棋子和步法。

= = =

需求分析 就是对客户需求的功能的定义。注意这里用了“定义”这个词,这就意味着对客户需求的说明,尽管不一定要是形式定义,但也必须是精确,无歧义的。同时,还要列出程式的功能模块和逻辑流程,即和客户的每一项功能需求对应的程式功能模块有哪些及这些功能模块是按照怎样的逻辑步骤来逐项完成客户的需求的。注意这里所说的功能模块和编码时所说的程式模块的差别。对于客户的一个复杂的功能需求,一般能用分治法分为一个或多个子功能,每一个子功能对应一个功能模块(类:方法,行为,功能),而每一个功能模块则能由一个或多个程式模块来实现。功能模块是建立在设计逻辑上的,而程式模块则是直接面向实现的。在用OO编程的时候,我通常以类作为程式模块划分的基本单元。综上所述,这个部分的文件必须包括3个部分:

1)客户需求的周详描述;

2)程式功能模块的划分及其和客户需求的对应关系;

3)功能模块的逻辑流程。

= = =

软件设计 这就是对程式的每一个模块的周详设计的说明文件。其由以下几部分组成:

1)程式模块和功能模块的对应关系和相关描述;

2)实现每个功能模块的程式模块的逻辑流程和组织结构;

3)对每一个程式模块的周详描述。这个部分的文件是改动得最多的,如果和螺旋周期模型结合,甚至需要循环地对每一个模块进行深入设计和细化,所以,为了便于管理,我通常都对每一个较复杂的模块都独立立一份文件。至于模块的流程图或结构图,一直都是我最头疼的问题,那一大堆琳琅满目的画法和符号往往令人无所适从。其实对于个人来说,只要能把意思表达出来,想怎样画都无所谓,关键是自己要有一套标准,别在这个图中,矩形表示过程,而在另一个图中,则是表示I/O。对每个符号表示的意思进行说明那是必须的,不然别人看起来会一头雾水。如果嫌麻烦的话,就干脆使用那些被大多数人认可的标准,例如UML图。但以后如果进到公司,还是老老实实地按公司规矩办事吧。

= = =

研发日志 我一直都认为这是文件中最有趣的部分。研发日志相当于编码阶段的文件,他的形式能非常随意,主要是记录一些在写程式时忽然萌发的灵感,或对代码的一些微小的修改,或对程式结构的一些微小变动等,还要对上述这些修改动动作些说明,例如,为什么要改成目前的这个样子。别小看这些记录,他往往会成为你以后对程式进行维护时的重要依据。要知道,人的IQEQ等,是会随着人的生理和心理状态的不同而变化的。在某个时刻,你可能会灵光一闪,做出了一个非常伟大的改动,但过了一段时间,当你再回过头来重新阅读同一段代码的时候,你非常有可能只记得在这里的改动是非常明智的,可是却无论怎么也想不起其明智在哪里。这时,一份日志就会省却你不少的麻烦。

= = =

测试分析 用于指出程式存在或潜在的缺陷和错误,及程式性能的数字描述。其包括几个部分:

1)对被测模块的描述;

2)测试人员;

3)对该模块每个功能的测试的周详描述;

4)指出当前存在或潜在的问题。

在测试描述中应该包括输入的数据集和输出的结果,更有运行的时间等。对于公司来说,对测试分析的需求是非常严格的。但对于我个人来说,我只是将其作为一份模块测试的文字记录,以防会忽略掉某些已知的缺陷和错误,及对一些核心模块的时间和空间效率进行简单的测试,以便日后翻查。

= = =

个人感想

以前写程式的时候都是“自由主义”式的个人研发,想到哪里就写到哪里,整个过程包括最后的成品都是问题多多。在刚上完软件工程课的时候,曾雄心勃勃,现学现卖地写了几个东西,结果是但逢写文件就头痛,到最后都是先把程式写出来后才填的文件(汗)。究其原因,一是由于贪方便,使用的文件模板是从网上downloadGB文件,其复杂程度简直可用变态来形容,非常多东西都是不适合个人使用的;二是由于“自由”惯了,一下子实在无法适应那么多的框框条条。所以目前自己做了份文件模板,打算慢慢培养起好的习惯,尽管感觉还是非常难受!

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics