论程序设计方法Word文档格式.docx

上传人:b****5 文档编号:18350246 上传时间:2022-12-15 格式:DOCX 页数:10 大小:26.18KB
下载 相关 举报
论程序设计方法Word文档格式.docx_第1页
第1页 / 共10页
论程序设计方法Word文档格式.docx_第2页
第2页 / 共10页
论程序设计方法Word文档格式.docx_第3页
第3页 / 共10页
论程序设计方法Word文档格式.docx_第4页
第4页 / 共10页
论程序设计方法Word文档格式.docx_第5页
第5页 / 共10页
点击查看更多>>
下载资源
资源描述

论程序设计方法Word文档格式.docx

《论程序设计方法Word文档格式.docx》由会员分享,可在线阅读,更多相关《论程序设计方法Word文档格式.docx(10页珍藏版)》请在冰豆网上搜索。

论程序设计方法Word文档格式.docx

)这也许就是比尔对BASIC情有独忠的原因,每当微软推出(临摹)一个新技术,则他会立刻在BASIC中提供支持。

题外话2:

  在APPLE-II上有一款游戏软件“警察抓小偷”,当年熬夜玩游戏,乐趣无穷。

后来这款游戏被移植到了PC上,咳~~~根本没有办法玩,因为小偷还没跑就被警察抓到了。

硬件的速度提升,另我无法再回味以前的时光了。

二、结构化程序设计

  随着计算机的价格不断下降,硬件环境不断改善,运行速度不断提升。

程序越写越大,功能越来越强,讲究技巧的程序设计方法已经不能适应需求了。

记得是哪本书上讲过,一个软件的开发成本是由:

程序设计30%和程序维护70%构成。

这是书上给出的一个理论值,但实际上,从我十几年的工作经验中,我得到的体会是:

程序设计占10%,而维护要占90%。

也许我说的还是太保守了,维护的成本还应该再提高。

下面这个程序,提供了两种设计方案,大家看看哪个更好一些那?

题目:

对一个数组中的100个元素,从小到大排序并显示输出。

(BASIC)

方法1:

冒泡法排序,同时输出。

FORI=1TO100

FORJ=I+1TO100

IFA[I]>

A[J]THENT=A[J]:

A[J]=A[I]:

A[I]=T

NEXTJ

?

A[I]

NEXTI

方法2:

冒泡法排序,然后再输出。

NEXT

NEXT

  显然,“方法1”比“方法2”的效率要高,运行的更快。

但是,从现在的程序设计角度来看,“方法2”更高级。

原因很简单:

(1)功能模块分割清晰——易读;

(2)也是最重要的——易维护。

程序在设计阶段的时候,就要考虑以后的维护问题。

比如现在是实现了在屏幕上的输出,也许将来某一天,你要修改程序,输出到打印机上、输出到绘图仪上;

也许将来某一天,你学习了一个新的高级的排序方法,由“冒泡法”改进为“快速排序”、“堆排序”。

那么在“方法2”的基础上进行修改,是不是就更简单了,更容易了?

这种把功能模块分离的程序设计方法,就叫“结构化程序设计”。

三、对程序设计中技巧使用的思考

  我可以肯定,大家在开始学习程序设计的时候,一定都做过这样一个题目:

求100以内的素数。

老师在黑板上,眉飞色舞地写出了第一个程序:

(C程序)

for(i=1;

i<

100;

i++)

{

for(j=2;

j<

i;

j++)

if(i%j==0)break;

if(j>

=i)printf("

%d,"

i);

}

  然后,老师开始批判这个程序“这个叫什么呀?

太慢了!

因为我们都知道大偶数不可能是素数了,因此,要排除掉!

”于是,意尤未尽地写出了第二个程序:

printf("

2,"

);

for(i=3;

i+=2)

  老师说:

“看!

我们只改动了一点点,程序运行的速度就提高了一倍多”。

然后运用诱导式教学法继续提问“程序的效率,还能再提高吗?

能!

”,得意地写出第三个程序:

方法3:

i+=2)'

'

不考虑大偶数

for(j=3;

i/2;

j+=2)'

不考虑用偶数去测试,而且只验算到一半就足够了

  “大家看,我们又只改动了一点点,运行速度又提高了一倍多。

可以了吗?

不可以!

我们还能再提高”。

于是又高傲地写出了第四个程序:

方法4:

intk=sqrt(i);

=k;

j+=2)

=k)printf("

%d"

然后,开始证明为什么我们判断素数的时候,只需要验算到平方根就足够了:

  假设p是合数,那么令:

p=a*b。

反正法:

由于我们已经判断了p的平方根以内的整数都不能被p整除,于是a>

SQRT(p)。

基于同样的理由b>

于是p=a*b>

SQRT(p)*SQRT(p)=p得出矛盾,命题得正。

  的确,“方法4”的确比“方法1”的运行速度要提高了好几倍,甚至好几十倍。

但我们仔细分析测试看看。

(1)“程序4”到底比“程序1”快了多少那?

我在某台计算机上进行测试(P4,1.5G)得到的速度对比表:

计算范围

100

1000

10000

100000

速度差

0.00秒

0.01秒

0.18秒

15秒

(2)在10万以上,才会看出一些差别。

而这种差别根本就不够底偿程序设计阶段的付出。

如果计算的范围再大,那么不管是“方法1”,还是“方法4”都不是好的算法。

(计算素数的另外一个比较优秀的算法叫“漏筛法”)

(3)写出“方法1”,只要具有小学四年级的数学水平就够了,而“方法4”则需要初中三年级的水平并且还要具备一些“数论”的知识。

(4)从维护性看,如果你写的程序需要另外一个程序员来维护,或者若干时间以后,你重新来阅读这段程序,那么就会对这个程序产生很多疑问:

这个求平方根是干什么用的?

其实,就这个题目来说,使用到“方法3”就已经足够了。

总结发言:

∙I.计算机的价格每年下降一半,而运算速度每年提高一倍”,因此我们应该把速度提高的任务交给硬件实现。

∙II.从易读性、维护性出发,程序员只负责按定义给出软件实现。

算法的问题是数学家解决的。

题外话:

  多年以来,人们一直在寻找动态图象(影视)的存储和回放的算法,但效果都不理想。

直到有人发现,原来在200多年前的数学家早就帮我们解决了这个问题——傅立叶(Fourier)级数展开。

因此我要说,优秀的算法不是我们程序员要考虑的问题,我们的任务只要按照数学家给出的算法翻译为计算机程序语言而已。

(这句话恐怕要遭到大多数程序员抛出的板砖袭击)再比如,计算一元多次方程解的问题。

我们使用的就是牛顿的迭代算法。

不要怪我瞧不起你,你能发明这个方法的话,那就是当代的牛顿了。

四、程序的易读性与书写方法

  程序是否容易阅读和维护,与怎么书写有很大的关系。

说实在的,C语言中为了方便程序员书写,允许使用++,--,<

<

&

&

,?

......这些运算符号。

但很多人经常乱用,以为自己写的程序多么简洁,效率多高。

其实,当你分行书写的话则更加容易阅读和维护,效率也不会降低,因为编译程序早就帮你优化为最快捷的代码了。

先看一个简单的例子:

计算一个整数乘255(C语言)

a*=255;

因为移位运算比乘法运算要快很多倍,因此a*255的运算书写为:

a=(a<

8)-a;

//a*255=a*256-a=(a<

8)-a

  方法1的书写非常简单,直截了当,显然更容易维护。

而方法2的书写运用了移位的技巧,不容易阅读,但效率最高。

是不是真的是这样那?

把这两个程序编译为汇编代码看看。

原来无论是方法1还是方法2,它们的汇编代码都是一样的:

movecx,eax

shleax,8

subeax,ecx

  也就是说,你认为非常技巧的书写方法,其实编译器的优化功能早就帮你想到了。

那么方法2的方式就很值得批判了。

下面是几个有关C语言书写方面的重要原则:

 

1.尽量表达愿义,多加注释;

2.变量名称和函数名称,要使用有意义的符号,并且遵守“匈牙利命名法”;

3.不要为俭省内存,使一个变量在一个模块中表达多个含义。

在某个模块中,前半部分用i表示计数器,由于后半部分不再使用计数器了,于是又用i来保存某个中间的结果。

等你维护这段程序的时候,保证你肯定会犯傻的。

4.在使用条件表达式的时候,不要混合书写运算表达式;

经常有人在书写for循环的时候,使用这样的方式:

for(inta=1,s=0;

a<

=100&

(s+=a);

a++);

天呀,这样写是不会提高程序运行效率的,尤其是当运算表达式复杂的时候,就更不容易阅读了,还是把运算写到for的循环体中吧。

ints=0;

for(inta=1;

=100;

a++)

s+=a;

//计算1+2+...+100这不很好吗?

!

再比如,if(a=b)这个写法在语法上是允许的,但不要使用。

要使用也要if(0!

=(a=b))这样的方式。

还有值得一提的是慎用“,”(逗号运算符)。

5.不要连续使用++,--,<

,*,&

.....这样的运算符号。

a=b++-(--c<

1+e&

0x0f>

>

1);

//这个人有病。

出这个题目考试的老师,也有病。

6.常量要写在条件表达式的左边;

if(5==a)这是正确的写法,这样书写可以避免勿输入而导致的if(a=5)这样的错误。

7.避免程序中{}的嵌套层次太深;

最多4层。

如果必须大于4层,那么写成调用子函数或宏的方式。

8.尽量多地使用断言;

当你在书写程序的过程中,凭你的智慧,你一定是知道:

程序运行到我正书写的这行代码的时候某个变量一定是某个值。

好啦,那么不要忧郁,马上加上一句代码:

ASSERT(nnn==xxx);

将来在调式维护这段代码的时候,你会得到无限美妙的回报。

9.书写需要“成对匹配”使用的代码的时候,在写使用代码之前,就先把结束写出来;

10.file.Open(...);

//当要打开文件的时候char*lp=newchar[100];

//当要申请内存的时候

11.......//先不要写这段代码......//先不要写这段代码

12.file.Close();

//马上写关闭delete[]lp;

//马上写释放

13.

14.xxx.Loack();

//当某个对象需要锁定的时候for(....)

15.......//先不要写这段代码{//写大括号的时候

xxx.Unlock();

//马上写解锁}//马上写大括号结束

和这个道理相同,在C++的类中,如果需要申请内存,那么先在构造函数中给出lp=NULL;

然后马上在析构函数中书写if(lp)delete[]lp;

16.可以适当地使用goto;

在结构化程序设计中,goto是被排斥的。

但是,如果适当地使用goto不但不影响斜率,而且还能提高程序的可读性。

合并2个文件到一个新文件中。

(不要挑我的毛病呀~~~~~,我使用的是类C的方式书写的。

FILE*f1,*f2,*f3;

if(Open(f1)成功)

if(Open(f2)成功)

{

if(Open(f3)成功)

......//这里是真正干活的地方

Close(f1);

Close(f2);

Close(f3);

}

else//f3不成功

......

else//f2不成功

}

else//f1不成功

......

==========================================================

FILE*f1=NULL,*f2=NULL,*f3=NULL;

if(Open(f1)不成功)gotoerr;

if(Open(f2)不成功)gotoerr;

if(Open(f3)不成功)gotoerr;

......//这里是真正干活的地方

err:

if(f3)Close(f3);

if(f2)Close(f2);

if(f1)Close(f1);

  方法1是最最标准的结构化设计,好吗?

不好!

尤其是当{}的层次比较深的时候,估计你寻找真正干活的代码的地方都找不到。

而使用方法2的程序,不但程序容易读,而且没有{}的深度。

在C++中,又提供了异常try/catch的设计结构,而异常的结构则比goto的结构更好、更完善了。

五、面向对象的程序设计

  随着程序的设计的复杂性增加,结构化程序设计方法又不够用了。

不够用的根本原因是“代码重用”的时候不方便。

面向对象的方法诞生了,它通过继承来实现比较完善的代码重用功能。

很多学生在应聘工作,面试的时候,常被问及一个问题“你来谈谈什么是面向对象的程序设计”,学生无言,回来问我,这个问题应该怎么回答。

我告诉他,你只要说一句话就够了“面向对象程序设计是对数据的封装;

范式(模板)的程序设计是对算法的封装。

”后来再有学生遇到了这个问题,只简单的一句对答,对方就对这个学生就刮目相看了(学生后来自豪地告诉我的)。

为什么那?

因为只有经过彻底的体会和实践才能提炼出这个精华。

  面向对象的设计方法和思想,其实早在70年代初就已经被提出来了。

其目的就是:

强制程序必须通过函数的方式来操纵数据。

这样实现了数据的封装,就避免了以前设计方法中的,任何代码都可以随便操作数据而因起的BUG,而查找修改这个BUG是非常困难的。

那么你可以说,即使我不使用面向对象,当我想访问某个数据的时候,我就通过调用函数访问不就可以了吗?

是的,的确可以,但并不是强制的。

人都有惰性,当我想对i加1的时候,干吗非要调用函数呀?

算了,直接i++多省事呀。

呵呵,正式由于这个懒惰,当程序出BUG的时候,可就不好捉啦。

而面向对象是强制性的,从编译阶段就解决了你懒惰的问题。

  巧合的是,面向对象的思想,其实和我们的日常生活中处理问题是吻合的。

举例来说,我打算丢掉一个茶杯,怎么扔那?

太简单了,拿起茶杯,走到垃圾桶,扔!

注意分析这个过程,我们是先选一个“对象”------茶杯,然后向这个对象施加一个动作——扔。

每个对象所能施加在它上面的动作是有一定限制的:

茶杯,可以被扔,可以被砸,可以用来喝水,可以敲它发出声音......;

一张纸,可以被写字,可以撕,可以烧......。

也就是说,一旦确定了一个对象,则方法也就跟着确定了。

我们的日常生活就是如此。

但是,大家回想一下我们程序设计和对计算机的操作,却不是这样的。

拿DOS的操作来说,我要删除一个文件,方法是在DOS提示符下:

c:

del文件名<

回车>

注意看这个过程,动作在前(del),对象在后(文件名),和面向对象的方法正好顺序相反。

那么只是一个顺序的问题,会带来什么影响那?

呵呵,大家一定看到过这个现象:

Filenotfound.“啊~~~,我错了,我错了,文件名敲错了一个字母”,于是重新输入:

del文件名2<

不幸又发生了,计算机报告:

Filereadonly.哈哈,痛苦吧:

所以DOS的操作其实是违反我们日常生活中的习惯的(当然,以前谁也没有提出过异议),而现在由于使用了面向对象的设计,那么这些问题,就在编译的时候解决了,而不是在运行的时候。

obj.fun(),对于这条语句,无论是对象,还是函数,如果你输入有问题,那么都会在编译的时候报告出来,方便你修改,而不是在执行的时候出错,害的你到处去捉虫子。

  同时,面向对象又能解决代码重用的问题——继承。

我以前写了一个“狗”的类,属性有(变量):

有毛、4条腿、有翘着的尾巴(耷拉着尾巴的那是狼)、鼻子很灵敏、喜欢吃肉骨头......方法有(函数):

能跑、能闻、汪汪叫......如果它去抓耗子,人家叫它“多管闲事”。

好了,狗这个类写好了。

但在我实际的生活中,我家养的这条狗和我以前写的这个“狗类”非常相似,只有一点点的不同,就是我的这条狗,它是:

卷毛而且长长的,鼻子小,嘴小......。

于是,我派生一个新的类型,叫“哈巴狗类”在“狗类”的基础上,加上新的特性。

好了,程序写完了,并且是重用了以前的正确的代码——这就是面向对象程序设计的好处。

我的成功只是站在了巨人的肩膀上。

当然,如果你使用VC的话,重用最多的代码就是MFC的类库。

六、组件(COM)程序设计

  有了面向对象程序设计方法,就彻底解决了代码重用的问题了吗?

答案是:

否!

硬件越来越快,越来越小了,软件的规模却也越来越大了,集体合作越来越重要,代码重用又出现的新的问题。

1.我用C++写的类,不能被BASIC重用——不能夸语言;

2.你要干什么,想重用我的代码?

不行,这样你就看见了我的设计思想——只能在源程序级别重用,不能在二进制级别(可执行代码及)重用;

3.我耗尽毕生的精力,写了一个包罗万象的类库,但没有人用。

因为他们说:

你这个太大了,我的程序只有1K,你却给我一个10000MB的库——MFC的尴尬;

4.太好了,我终于找到了程序中的一个BUG,已经修改完成,而且是只改动了一个字节。

接下来我要重新向我的用户分发新的版本,我的用户有......10万个——升级的非鲁棒性,不是我分发累死了,就是用户重新安装累死了。

(鲁棒:

robust。

意为强壮性的,平顺的,顺滑的.....鬼知道是哪个不懂计算机的人翻译的这个词汇。

5.我想写一个集大成的软件,这个软件的功能是我中有你,你中有我。

既能实现文字编辑,又能实现电子表格计算,又能实现自动翻译,还能画图,还能实现数据库检索,还可以看电影.....只要用了我的这个软件,想要什么就有什么,我要强占整个软件的市场------OLE实现的重用功能,只要学会了COM,这些都不是问题了;

6.用户甲要求我的软件窗口上下分割,用户乙要求我的软件窗口左右分割......我需要在我的软件基础上,派生出100个类型,可怎么办呀?

将来怎么维护呀?

------在脚本的支持下,实现同一程序的的灵活配置而重用,问题迎刃而解了;

7.我是个老板,你知道我有多痛苦吗?

我手下的员工向我提出加工资的要求,我不得不答应呀。

因为如果这个员工跳槽了,他的代码要维护起来有多难!

——现在好啦,我要求员工统统用组件写模块,想加工资?

门都没有,威胁我要走?

那你走吧,这个月的工资也不发了。

反正用组件写的代码,我可以很容易地进行包容和聚合实现维护。

(老板的福音,程序员的悲哀);

8.还有好多那,现在想不起来了......

  COM程序设计方法,就是解决以上问题的一个方式。

有很多朋友觉得COM非常复杂难懂,不想学习了。

你一定学习过程序设计的最基本的方法(非结构化设计:

汇编、gwBasic......),然后,你又学习了结构化程序设计(C、Pascal......),然后,你又努力学习并熟练掌握了面向对象的程序设计方法(C++、Delphi、Java......),那么不要怕,要有信心去学习组件程序设计,它只是一个设计方法和思想,并且是目前较高级的方法,如果不掌握,就太可惜了。

学习了结构化程序设计,你就会“藐视”那些不遵守结构化设计思想而写出的代码;

学习了面向对象设计,你就会“嘲笑”那些为找BUG而晕头转向的程序员;

同样,学习了组件程序设计,你就会站在更高的层次看待程序设计。

七、结束语

  写程序的目的是什么?

养家糊口、兴趣使然、我的事业......这些都对。

但我要强调的是:

写程序的目的是为了修改程序。

在这个观点上,那么写注释、写文档、选择语言、选择结构......都是为这个服务的。

本文从软件设计方法的进化角度来反复阐述这个观点,希望爱好者能有所体会和思考。

文中所讨论的技术和观点,适合于大多数情况下的程序设计,而对于特殊的应用的(驱动开发,嵌入式开发,网络通讯,实时视频......),这些领域中,由于硬件环境的限制和极限效率的要求,有些观点就不合适了,需要具体情况具体分析。

另外就是对于程序设计的初学者,可以先不考虑这么多问题,以掌握基本技巧方法和思想为要。

欢迎大家批评指正。

文中一些调侃的部分,也请勿对号入坐^_^。

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 农林牧渔 > 水产渔业

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

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