第二章 程序设计基础.docx
《第二章 程序设计基础.docx》由会员分享,可在线阅读,更多相关《第二章 程序设计基础.docx(12页珍藏版)》请在冰豆网上搜索。
第二章程序设计基础
第二章程序设计基础
2.1程序设计方法与风格
程序设计是一门技术,需要相应的理论,技术,方法和工具来支持。
就程序设计方法和技术的发展而言,主要经过了结构化程序设计和面向对象的设计阶段。
除了好的程序设计方法和技术之外,程序设计风格也是很重要的。
因为程序设计风格会深刻的影响软件的质量和可维护性,良好的程序设计风格可以使程序结构清晰合理,使程序代码便于维护,因此,程序设计风格对保证程序的质量是很重要的。
一般来讲,程序设计风格是指编写程序时所表现出的特点,习惯和逻辑思路。
程序是由人来看的,为了测试和维护程序,往往还要阅读和跟踪程序,因此程序设计的风格总体而言应该强调简单和清晰,程序必须是可以理解的。
可以认为,著名的“清晰第一,效率第二”的论点已成为当今主导的程序设计风格。
要形成良好的程序设计风格,主要应该注重和考虑下述一些因素。
1.源程序文挡化
源程序文挡化应考虑如下几点:
(1)符号名的命名:
符号名的命名应具有一定的实际含义,以便于对程序功能的理解。
(2)程序注解;正确的注解能够帮助读者理解程序。
注解一般分为序言性注解和功能性注解。
序言性注解通常位于每个程序的开头部分,它给出了程序的整体说明,主要描述内容可以包括:
程序标题,程序功能说明,主要算法,接口说明,程序位置,开发简历,程序设计者,复审者,复审日期,修改日期等。
功能注解的位置一般嵌在源程序体中,主要描述其后的语句或程序做什么。
(3)视觉组织:
为使程序的结构一目了然,可以在程序中利用空格,空行,缩进等技巧使程序层次清晰。
2.数据说明的方法
在编写程序时,需要注意数据说明的风格,以便使程序中的数据说明更易于理解和维护。
一般注意如下几点:
(1)数据说明的次序规范化。
鉴于程序理解,阅读和维护的需要,使数据说明次序固定,可以使数据的属性容易查找,也有利于测试,排错和维护。
(2)说明语句中变量按排有序化。
当一个语句说明多个变量时,变量按照字母顺序排序为好。
(3) 使用注解来说明复杂数据的结构。
3.语句的结构
程序应该简单易懂,语句构造应该简单直接,不应该为了提高效率而把语句复杂花。
一般注意如下:
(1)在一行内只写一条语句;
(2)程序编写应优先考虑清晰性;
(3)除非对效率有特殊要求,程序编写要做到清晰第一,效率第二;
(4)首先要保证程序正确,然后才要求提高速度;
(5)避免使用临时变量而使程序的可读性下降;
(6)避免不必要的转移;
(7)尽可能使用库函数;
(8)避免采用复杂的条件语句;
(9)尽量减少使用“否定”条件语句;
(10)数据结构要有利于程序的简化;
(11)要模块化,使模块功能尽可能单一化;
(12)利用信息隐蔽,确保每一个模块的独立一性;
(13)从数据出发去构造程序;
(14)不要修补不好的程序,要重新编写;
4.输入和输出
输入和输出信息是用户直接关心的,输入和输出方式应尽可能方便用户的使用,因为系统能否被用户接受,往往取决于输入和输出的风格。
无论是批处理的输入和输出方式,还是交互式的输入和输出方式,在设计和编程时都应该注意以下你点:
(1)对所有的输入数据都要检验数据的合法性;
(2)检查输入项的各种重要组合的合理性;
(3)输入格式要简单,以使得输入的步骤和操作尽可能简单;
(4)输入数据时,允许使用自由格式;
(5)应允许缺省值;
(6)输入一批数据时,最好使用输入结束标志;
(7)在以交互式输入/输出方式进行输入时,要在屏幕上使用提示符明确提示输入的请求,同时数据输入过程中和输入结束时,应在屏幕上给出状态信息;
(8)当程序设计语言对输入格式有严格要求时,应保持输入语句的一致性;给所有的输出加注解,并设计输出报表格式。
2.2 数据结构的基本概念
由于软件危机的出现,人们开始研究程序设计方法,其中最受关注的是结构化程序设计方法。
20世纪70年代提出了“结构化程序设计(structuredprogramming)”的思想和方法。
结构化程序设计方法引入了工程思想和结构化思想,使大型软件的开发和编程都得到极大的改善。
2.2.1结构化程序设计的原则
2.2.2结构化程序的基本结构与特点
2.2.3结构化程序设计原则和方法的应用
2.2.1结构化程序设计的原则
结构化程序设计方法的主要原则可以概括为自顶向下,逐步求精,模块画,限制使用goto语句。
1.自顶向下:
程序设计时,应先考虑总体,后考虑细节;先考虑全局目标,后考虑局部目标。
不要一开始就追求众多的细节,先从最上层总目标开始设计,逐步使问题具体化。
2.逐步求精:
对复杂的问题,应设计一些子目标作过渡,逐步细化。
3.模块化:
一个复杂问题,肯定是由若干个稍简单的问题构成。
模块化是把程序要解决的总目标分解为分目标,再进一步分解为具体的小目标,把每个小目标称为一个模块。
4.限制使用goto语句
实际上,结构化程序设计方法的起源来自对GOTO语句的的认识和争论。
肯定的结论是,在块和进程的非正常出口往往需要用GOTO语句,使用GOTO语句会使程序执行效率较高;在合成程序目标时,GOTO语句往往是有用的,如返回语句用GOTO。
否定的结论是,GOTO语句是有害的,是造成程序混乱的祸根,程序的质量与GOTO语句的数量成反比,应该在所有高级程序设计语言中取消GOTO语句。
取消GOTO语句后,程序易理解、易排错、易维护,程序容易进行正确性证明。
作为争论的结论,1974年Knuth发表了令人信服的总结,并证实了:
(1)滥用GOTO语句确实有害,应尽量避免;
(2)完全避免使用GOTO语句也并非是个明智的方法,有些地方使用GOTO语句,会使流程更清楚、效率更高;
(3)争论的焦点不应该放在是否取消GOTO语句,而应该放在用什么样的程序结构上。
其中关键的是,肯定以提高程序清晰性为目标的结构化方法。
2.2.2结构化程序的基本特点
结构化程序设计方法是程序设计的先进方法和工具。
采用结构化程序设计方法编写程序,可使程序结构良好、易读、易理解、易维护。
1966年,Boehm和Jacopini证明了程序设计语言仅仅使用顺序、选择和重复三种基本控制结构就足以表达出各种其他形式结构的程序设计方法。
1.顺序结构:
顺序结构是一种简单的程序设计,它是最基本、最常用的结构,如图2.1所示。
顺序结构是顺序执行的结构,所谓顺序执行,就是按照程序语句行的自然顺序,一条语句一条语句地执行程序。
2.选择结构:
选择结构又称为分支结构,它包括简单选择和多分支选择结构,这种结构可以根据设定的条件,判断应该选择哪一分支来执行相应的语句序列。
图2.2列出了包含2个分支的简单选择结构。
图2.1 顺序结构 图2.2选择结构
3.重复结构:
重复结构又称为循环结构,它根据给定的条件,判断是否需要重复执行某一相同的或类似的程序段,利用重复结构可以简化大量的程序行。
在程序设计语言中,重复结构对应两类循环语句,对先判断后执行循环体的称为当性循环结构,如图2.3所示。
对先执行循环体后判断的称为直到型循环结构,如图2.4所示。
图2.3 当型循环 图2.4 直到型循环
总之,遵循结构化的程序的设计原则,按结构化程序设计方法设计出的程序具有明显的优点,其一,程序易于理解、使用和维护。
程序员采用结构化编程方法,便于控制、降低程序的复杂性,因此容易编写程序。
便于验证程序的正确性,结构化程序清晰易读,可理解性好,程序员能够进行逐步求精、程序证明和测试,以确保程序的正确性,程序容易阅读并被人理解,便于用户使用和维护。
其二,提高了编程工作的效率,降低了软件开发的成本。
由于结构化编程方法能够把错误控制到最低限度,因此能够减少调试和查错的时间。
结构化程序是由一些为数不多的基本结构模块组成,这些模块甚至可以由机器自动生成,从而极大地减轻了编程工作量。
2.2.3结构化程序设计原则和方法的应用
基于结构化程序设计原则、方法以及结构化程序基本构成结构的掌握和了解,在结构化程序设计的具体实施中,要注意把握如下要素:
1.使用程序设计语言中的顺序、选择、循环等有限的控制结构表示程序的控制逻辑;
2.选用的控制结构只准有一个入口和一个出口;
3.程序语句组成容易识别的块,每块只有一个入口和一个出口;
4.复杂结构应该用嵌套的基本控制结构进行组合嵌套来实现;
5.语言中没有的控制结构,应该采用前后一致的方法来模拟;
6.严格控制GOTOYUJU的使用。
其意思是指:
(1)用一个非结构化的程序设计语言去实现一个结构化的构造;
(2)若不使用GOTO语句会使功能模糊;
(3)在某种可以改善而不是损害程序可读性的情况下。
2.3面向对象的程序设计
2.3.1关于面向对象方法
2.3.2面向对象方法的基本概念
2.3.1关于面向对象方法
今天,面向对象(objectoriented)方法已经发展成为主流的软件开发方法。
面向对象方法的形成同结构化方法一样,起源于实现语言,首先面向对象的程序设计语言开展研究,随之形成面向对象分析和设计方法。
面向对象方法和技术经历30多年的研究和发展,已经越来越成熟和完善,应用也越来越深入和广泛。
面向对象的软件开发方法在20世纪60年代后期首次提出,以60年代末挪威奥斯陆大学和挪威计算中心共同研制的SIMULA语言为标志,面向对象的基本要点首次在SIMULA语言中得到了表达和事项。
后来一些著名的面向对象语言(如Smalltalk、C++、Java、Eiffel)的设计者都曾从SIMULA得到激发。
随着80年代美国加州的Xeror研究中心推出Smalltalk语言和环境,使面向对象程序设计方法得到比较完善的事项。
Smalltalk-80等一系列描述能力较强、执行效率较高的面向对象编程语言的出现,标志着面向对象的方法于技术开始走向实用。
面向对象方法的本质,就是主张从客观世界固有的事物出发来构造系统,提倡用人类在现实生活中常用的思维方法来认识、理解和描述客观事物,强调最终建立的系统能够影射问题域,也就是说,系统中的对象以及对象之间的关系能够如实反映问题域中固有事物及其关系。
面向对象程序方法之所以日益受到人民的重视和应用,成为流行的软件开发方法,是源于面向对象方法的以下主要优点。
1.与人类习惯的思维方法一致
传统的程序设计方法是面向过程的,其核心方法是以算法为核心,把数据和过程作为相互独立的部分,数据代表问题空间中的课题,程序则用于处理这些数据,在计算机内部数据和程序是分开存放的,这样的做法往往会发生使用错误的数据调用正确的程序模块的情况。
其原因是,传统的程序设计方法忽略了数据和操作之间的内在联系,用这种方法设计出来的软件系统其解空间与问题空间不一致,使人感到难于理解。
实际上,用计算机解决的问题都是现实世界中的问题,这些问题无非由一些相互间存在一定联系的事物所组成,每个具体的事物都具有行为和属性两方面的特征。
因此,把描述事物静态属性的数据结构和表示事物动态行为的操作防在一起构成一个整体,才能完整、自然地表示客观世界中的实体。
面向对象方法和技术以对象为核心。
对象是由数据和容许的操作组成的封装体,与客观实体有直接对应关系。
对象之间通过传递消息互相联系,以模拟现实世界中不同事物彼此之间的联系。
面向对象的设计方法与传统的面向过程的方法有本质不同,这种方法的基本原理是,使用现实世界的概念抽象地思考问题从而自然地解决问题。
它强调模拟现实世界中的概念而不强调算法,它鼓励开发者在软件开发的绝大部分过程中都用应用领域的概念去思考。
2.稳定性好
面向对象方法基于构造问题领域的对象模型,以对象为中心构造软件系统。
它的基本作法是用对象模拟问题领域中的试题,以对象间的联系刻画实体间的联系。
因为面向对象的软件系统的结构是根据问题领域的模型建立起来的,而不是基于对系统应完成的功能的分解,所以,当对系统的功能需求变化时并不会引起软件结构的整体变化,往往仅需要作一些局部性的修改。
由于现实世界中的实体是相对稳定的,因此,以对象为中心构造的软件系统也是比较稳定的。
而传统的软件开发方法以算法为核心,开发过程基于功能分析和功能分解。
用传统方法所建立起来的软件系统的结构紧密地依赖于系统所要完成的功能,当功能需求发生变化时将引起软件结构的整体修改。
事实上,用户需求变化大部分是针对功能的,因此,这样的软件系统是不稳定的。
3.可重用性好
软件重用是指在不同的软件开发过程中重复使用相同或相似软件元素的过程。
重用是提高软件生产率的最主要的方法。
传统的软件重用技术是利用标准函数库,也就是试图用标准函数库中的函数作为“预制件”来建造新的软件系统。
但是,标准函数缺乏必要的“柔性”,不能适应不同应用场合的不同需要,并不是理想的可重用的软件成分。
实际的库函数往往仅提供最基本、最常用的功能,在开发一个新的系统时,通常多数函数是开发者自己编写的,甚至绝大多数函数都是新编的。
使用传统方法学开发软件时,人们强调的是功能抽象,认为具有功能内聚性的模块是理想的模块,也就是说,如果一贯模块完成一个且只完成一个相对独立的子功能,那么这个模块就是理想的可重用,而且这样的模块也跟容易维护。
基于这种认识,通常尽量把标准函数库中的函数做成功能内聚的。
但是,事实上具有功能内聚性的模块并不是自含的和独立的,相反,它必须在数据上运行。
如果要重用这样的模块,则相应的数据也必须重用。
如果新产品中的数据与最初产品中的数据不同,则要么修改数据要么修改这个模块。
事实上,离开了操作数据便无法处理,而脱离了数据的操作也是毫无意义的,我们应该对数据和草同样重视。
在面向对象的方法中所使用的对象,其数据和操作是作为平等伙伴出现的。
因此,对象具有很强的自含性,此外,对象所固有的封装性,使得对象的内部实现与外界隔离,具有较强的独立性。
由此可见,对象提供了比较理想的模块化的机制和比较理想的可重用的软件成分。
面向对象的软件开发技术在利用可重用的软件成分构造新的系统软件的时候,有很大的灵活性。
有两种方法可以使用一个对象类:
一种方法是创建该类的实例,从而直接使用它;另一种方法是从它派生出一个满足当前需要的新类。
继承性机制使得子类不仅可以重用其父类的数据结构和程序代码,而且可以在父类代码的基础上方便地修改和扩充,这种修改并不影响对原有类的使用。
可见,面向对象的软件开发技术所实现的可重用性是自然和准确的。
4.易于开发大型软件产品
当开发大型软件时,组织开发人员的方法不恰当往往是出现问题的主要原因。
用面向对象范型开发软件时,可以把一个大型产品看作是一系列本质上相互独立的小产品来处理,这就不仅降低了开发的技术难度,而且也使得对开发工作的管理变的更容易。
这就好似为什么对于大型产品来说,面向对象范型优于结构化范型的原因之一。
许多软件开发公司的经验都表明,当把面向对象技术用于大型软件开发时,软件成本明显地降低了,软件的整体质量提高了。
5.可维护性好
用传统的方法开发和面向过程的方法开发出来的软件很难维护,是长期困扰人们的一个严重问题,是软件危机的突出表现。
由于下述因素的存在,使得面向对象的方法开发的软件可维护性好。
(1)用面向对象的方法开发的软件稳定性比较好。
如前所述,当对软件的功能或性能的要求发生变化时,通常不会引起软件的整体变化,往往只需对局部做一些修改。
由于软件的改动较小且限于局部,自然比较容易实现。
(2)用面向对象的方法开发的软件比较容易修改。
在面向对象方法中,核心是类(对象),它具有理想的模块机制,独立性好,修改一个类通常很少会牵扯到其他类。
如果仅修改一个类的内部实现部分(私有数据成员或成员函数算法),而不修改该类的对外接口,则可以完全不影响软件的其他部分。
面向对象技术特有的继承机制,使得对所开发的软件的修改和扩充比较容易实现,通常只需从已有类派生出一些新类,无需修改软件原有成分。
面向对象技术的多态机制,使得当扩充软件功能时对原有代码的修改进一步减少,需要增加新代码也比较少。
(3)用面向对象的方法开发的软件比较容易理解。
在维护已有软件的时候,首先需要对原有软件与此次修改有关的部分有深入理解,才能正确完成维护工作。
传统软件之所以难于维护,在很大程度上是因为修改所涉及的部分分散在软件的各个地方,需要了解的面很广,内容很多,而且传统软件的解空间与问题空间的结构很不一致,更增加了理解原有软件的难度和工作量。
面向对象的技术符合人们习惯的思维方式,用这种方法所建立的软件系统的结构与问题空间的结构基本一致。
因此,面向对象的软件系统比较容易理解。
对面向对象软件系统进行修改和扩充,通常是通过在原有类的基础上派生出一些新类来实现。
由于对象类有很强的独立性,当派生新类的时候通常不需要详细了解基类中操作的实现算法。
因此,了解原有系统的工作量可以大幅度降低。
(4)易于测试和调试
为了保证软件的质量,对软件进行维护之后必须进行必要的测试,以确保要求修改或扩充的功能已正确的实现了,而且没有影响到软件未修改的部分。
如果测试过程中发现了错误,还必须通过调试改正过来。
显然,软件是否易于测试和调试,是影响软件可维护性的一个重要因素。
对用面向对象的方法开发的软件进行维护,往往是通过从已有类派生出一些新类来实现。
因此,维护后的测试和调试工作也主要围绕这些新派生出来的类进行。
类是独立性很强的模块,向类的实例发消息后即可运行它,观察它是否能正确地完成相应的工作,因此对类的测试通常比较容易实现。
2.3.2面向对象方法的基本概念
关于面向对象方法,对其概念有许多不同的看法和定义,但是都涵盖对象及对象属性与方法、类、继承、多态性几个基本要素。
下面分别介绍面向对象方法中这几个重要的基本概念,这些概念是理解和使用面向对象方法的关键和基础。
1.对象(object)
对象是面向对象方法中最基本的概念。
对象可以用来表示客观世界中的任何实体,也就是说,应用领域中有意义的、与所要解决的问题有关系的任何事物都可以作为对象,它既可以是具体的物理实体的抽象,也可以是认为的概念,或者是任何有明确边界和意义的东西。
例如,一个人、一家公司、一个窗口、贷款和借款等,都可以作为一个对象。
总之,对象是对问题域中某个实体的抽象,设立某个对象就反映了软件系统保存有关它的信息并具有与它进行交互的能力。
面向对象的程序设计方法中涉及的对象是系统中用来描述客观事物的一个实体,是构成系统的一个基本单位,它由一组表示静态特征的属性和它可执行的一组操作组成。
例如,一辆汽车是一个对象,它包含了汽车的属性(如颜色、型号、载重量等)及其操作(如启动、刹车等)。
一个窗口是一个对象,它包含了窗口的属性(如大小、颜色、位置等)及其操作(如打开、关闭等)。
客观世界中的实体通常都既有静态的属性,有具有动态的行为,因此,面向对象方法学中的对象是由描述该对象属性的数据以及可以对这些数据施加的所以操作封装在一起构成的统一体。
对象可以做的操作表示它的动态行为,在面向对象分析和面向对象设计中,通常把对象的操作也称为方法或服务。
属性即对象所包含的信息,它在设计对象时确定,一般只能通过执行对象的操作来改变。
如对象Person的属性有姓名、年龄、体重等。
不同对象的同一属性可以具有相同或不同的属性值。
如张三的年龄为19,李四的年龄为20。
张三、李四是两个不同的对象,他们共同的属性“年龄”的值不同。
要注意的是,属性值应该指的是纯粹的数据值,而不能指对象。
操作描述了对象执行的功能,若通过消息传递,还可以为其他对象使用。
操作的过程对外是封闭的,即用户只能看到这一操作实施后的结果。
这相当于实现已经设计好的各种过程,只需要调用就可以了,用户不必关心这一过程是如何编写的。
事实上,这个过程已经封装在对象中,用户也看不到,即是对象的封装性。
对象有如下一些基本特点:
• 表示惟一性。
指对象是可区分的,并且由对象的内在本质来区分,而不是通过描述来区分。
• 分类性:
指可以将具有相同属性和操作的对象抽象成类。
• 多态性:
指同一个操作可以是不同对象的行为。
• 封装性:
从外面看只能看到对象的外部特征,即只需知道数据的取值范围和可以对该数据施加的操作,根本无需知道数据的具体结构以及实现操作的算法。
对象的内部,即处理能力的实行和内部状态,对外是不可见的。
从外面不能直接使用对象的处理能力,也不能直接修改其内部状态,对象的内部状态只能由其自身改变。
• 模块独立性较好。
对象是面向对象的软件的基本模块,它是由数据及可以对这些数据施加的操作所组成的统一体,而且对象是以数据为中心的,操作围绕对其数据所需做的数据来处理设置,没有无关的操作。
从模块的独立性考虑,对象内部各种元素彼此结合得很紧密,内聚性很强。
2.类(Class)和实例(Instance)
将属性、操作相似的对象归为类,也就是说,类是具有共同属性、共同方法的对象的集合。
所以,类是对象的抽象,它描述了属于该对象类型所有对象的性质,而一个对象则是其对应类的一个实例。
要注意的是,当使用“对象”这个术语时,既可以指一个具体的对象,也可以泛指一般的对象,但是,当使用“实例”这个术语时,必然指的是一个具体的对象。
例如:
Integer是一个整型类,它描述了所以整数的性质。
因此任何整数都是整数类的对象,而一个具体的整数“123”是类Integer的一个实例。
由类的定义可知,类是关于对象性质的描述,它同对象一样,包括一组数据属性和数据上的一组合法操作。
例如,一个面向对象的图形程序在屏幕左下角显示一个半径3cm的红颜色的圆,在屏幕中部显示一个半径4cm的绿颜色的圆,在屏幕右上角显示一个半径1cm的黄颜色的圆。
这三个圆心位置、半径大小和颜色均不相同的圆,是三个不同的对象。
但是,它们都有相同的属性(圆心坐标、半径、颜色)和相同的操作(显示自己、放大缩小半径、在屏幕上移动位置,等等)。
因此,他们是同一类事物,可以用“Circle类”来定义。
3.消息(Message)
面向对象的世界是通过对象与对象间彼此的相互合作来推动的,对象间的这种相互合作需要一个机制协助进行,这样的机制称为“消息”。
消息是一个实例与另一个实