结构化程式设计(英语:Structured programming),一种编程典範。它採用子程式、程式码区块(英语:block structures)、for循环以及while循环等结构,来取代传统的 goto。希望藉此来改善电脑程式的明晰性、品质以及开发时间,并且避免写出麵条式代码。
基本介绍
- 中文名:结构化编程
- 外文名:Structured programming
- 类型:一种编程典範
- 採用:子程式、程式码区块
主要内容
结构化程式设计在1960年代开始发展,科拉多·伯姆(Corrado Böhm)及朱塞佩·贾可皮尼(Giuseppe Jacopini)伯姆于1966年5月在《Communications of the ACM》期刊发表论文,说明任何一个有goto指令的程式,可以改为完全不使用goto指令的程式,后来艾兹赫尔·戴克斯特拉在1968年也提出着名的论文《GOTO陈述有害论》(Go To Statement Considered Harmful),因此结构化程式设计开始盛行,此概念理论上可以由结构化程式理论所证明,而在实务上,当时也有像ALGOL一样,有丰富控制结构的程式语言来实现结构化程式设计。
原则
结构化程式设计提出的原则可以归纳为32个字:自顶向下,逐步细化;清晰第一,效率第二;书写规範,缩进格式;基本结构,组合而成。
底层的结构化程式设计
结构化的程式是以一些简单、有层次的程式流程架构所组成,可分为顺序(sequence)、选择(selection)及循环(repetition)。
● 顺序是指程式正常的执行方式,执行完一个指令后,执行后面的指令。
● 选择结构顾名思义,当程式到了一定的处理过程时,遇到了很多分支,无法按直线走下去,它需要根据某一特定选择结构表示程式的处理步骤出现了分支,它需要根据某一特定的条件选择其中的一个分支执行,选择结构有单选择、双选择和多选弹三种形式。
● 不断的重複,被称作循环,所以这里的循环结构通常就是用来表示反覆执行一个程式或某些操作的过程,直到某条件为假(或为真)时才可终止循环。在循环结构中最主要的是:什幺时候可以执行循环?出现哪些操作需要循环执行?循环结构的基本形式有两种。当型循环和直到型循环。
● 重用测试过代码,如果重用别的程式中的部分越多,您自身的工作也越简单。在面向对象中,重用的过程更为容易一些,因为代码本身的可复用性更高。如果项目的任务不重,程式设计师之间的协作也更容易。
面向对象的类库中的类和框架能够帮助减轻编程任务。例如,如果您使用了苹果公司提供的软体框架,您就可以和苹果公司的程式设计师合作。这些框架通常构成了您的程式中比较基础的部分,而您可以把精力放在您最擅长的方面,其它的事情让类库的开发人员去做。因此,您的项目可以更快的做出原型系统,更快的完成,协作方面的问题也更少。
若一个程式语言的语法允许用成对的关键字包围一段程式,形成一个结构,这种程式语言称为有“区块结构”(block-structured),这类的结构包括用ALGOL 68的if..fi包围的程式,或是在PL/I中用BEGIN..END包围的一段程式,或是在C语言中用大括弧{...}包围的一段程式。
结构化程式语言
用任何语言都可以进行结构化程式设计,不过一般较常使用程式式的程式语言。早期的结构化程式语言包括ALGOL、 Pascal、PL/I及Ada,不过后来大部份的程式式程式语言都鼓励使用结构化程式设计,有时也会特意的省去一些特性(例如不支援goto指令)使得非结构化的程式设计更加困难。
历史
理论基础
结构化程式理论可做为结构化编程的理论基础,结构化程式理论中提到利用顺序、选择及重複这三种组合程式的方式,可以表示所有可计算函式。上述的三种结构已足以表示CPU中的指令周期,也可以表示图灵机的运作,以此观点来看,处理器所执行的指令可视为是某种“结构化程式”,虽然整个程式可能不是一个结构化程式。一般都认为结构化程式理论是归功于伯姆和贾可皮尼于1966年发表的论文,其中一个原因可能是戴克斯特拉引用过此论文。结构化程式理论未提及如何撰写结构化程式,也没有提到结构化程式的分析,后来1960至1970年代时,戴克斯特拉、罗伯特·弗洛伊德、东尼·霍尔等计算机科学家在此领域有许多的贡献。
争议
结构化编程中一项重要的原则是减少甚至禁止goto指令的使用,不过不是所有计算机科学家都赞成禁止使用goto指令。高德纳赞成程式设计时需考虑可读性,但他不赞成禁用goto指令。在其1974年发表的论文《使用goto指令的结构化编程》(Structured Programming with Goto Statements)中,他提出了一些程式,使用goto指令可以使得程式更清楚而有效率,也不会犠牲程式的可读性。高德纳提出了一个较松的结构限制要求:将程式以流程图表示,前进的分支在流程图的左侧,倒退的分支在流程图的右侧,所有分支均不得交叉。
结构化编程在1970年有很大的进展,IBM的研究员哈伦·米尔斯(英语:Harlan Mills)将结构化编程套用在纽约时报研究档案索引系统的开发,此计画相当成功,因此许多公司开始使用结构化编程,不过戴克斯特拉评论米尔斯使用的方式和一些已发表论文中的方式不同。
到1987年时在计算机科学领域仍有针对结构化编程的争论,弗兰克·鲁宾发表了一篇论文《“goto有害论”是有害的》(GOTO considered harmful' considered harmful),引发许多的反对,戴克斯特拉本人也批评鲁宾及其追随者的论点。
影响
在二十世纪末时绝大多数的计算机科学学者均已同意使用结构化程式设计的好处,原来缺乏程式结构的高阶程式语言(如FORTRAN、COBOL及BASIC)也都已加入此特性。
例外情形
异常处理
子程式很少会有一个以上的进入点,相对的,有时子程式会有一个以上的结束点,表示剩下的程式不需执行,或因为一些原因,造成无法执行后续的程式。
以下是是一个由档案中读取资料并处理的程式範例:
open file;
while (reading not finished) {
read some data;
if (error) {
stop the subprogram and inform rest of the program about the error;
}
}
process read data;
finish the subprogram;
其中“stop and inform”的步骤可以利用多种方式达成,包括产生一个异常(exception)、利用return指令回到上一层的程式、使用配合标记的break指令,或是使用goto。当子程式有二个结束点时,就违背了戴克斯特拉的结构化编程原则。但此情形下若强制要撰写只有一个结束点的子程式又相当麻烦,而且若有几个不同的错误处理,错误产生后有不同的清除方式,单一结束点的程式会相当难以阅读及理解,甚至比未结构化使用goto的程式相当。
许多程式语言就提供了在结构化编程中产生多个结束点的方式。C语言允许使用continue、break及return指令来产生结构的多个结束点,C++还可以用throw产生异常,在结构外再用catch进行异常的处理,有些语言则有配合标记的break指令(类似一般的break指令,但可以跳出不只一层的结构)。
状态机
有些程式(例如语法分析器或是处理通讯协定的程式)有许多的状态(英语:state (computer science)),因此程式进行的过程会在各状态中切换,此架构不容易简化成基本的控制结构。可以将此架构各状态下的程式分别独立为子程式,再用一个变数表示当前的状态,(可参考trampoline(英语:trampoline (computers))),另一种作法是用goto的方式切换到新状态对应的程式。