結構化編程

結構化編程

結構化程式設計(英語:Structured programming),一種編程典範。它採用子程序、程式碼區塊(英語:block structures)、for循環以及while循環等結構,來取代傳統的 goto。希望藉此來改善計算機程序的明晰性、品質以及開發時間,並且避免寫出麵條式代碼。

主要內容


結構化程式設計在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的方式切換到新狀態對應的程式。