麵條式代碼
麵條式代碼(Spaghetti code)是軟件工程中反面模式的一種[1],是指一個源代碼的控制流程複雜、混亂而難以理解[2],尤其是用了很多GOTO、例外、線程、或其他無組織的分支。其命名的原因是因為程式的流向就像一盤面一樣的扭曲糾結。麵條式代碼的產生有許多原因,例如沒有經驗的程序設計師,及已經過長期頻繁修改的複雜程序。結構化編程可避免麵條式代碼的出現。
距離[編輯]
以下是一段用BASIC寫的程序,是典型麵條式代碼的例子。程序在屏幕上顯示數字 1 到 10 及其對應的平方。由於有GOTO語句,此程序需要配合行號才能知道程序的流向,也無法利用縮排的方式使程序比較容易閱讀。而且因為跳轉指令的關係,要執行的程序會不可預測的由一個區域跳轉到另一個區域,不易調試。現實世界中的麵條式代碼往往更加複雜,會大幅增加維護成本。
10 i = 0
20 i = i + 1
30 PRINT i; " squared = "; i * i
40 IF i >= 10 THEN GOTO 60
50 GOTO 20
60 PRINT "Program Completed."
70 END
以下則是使用結構化的控制結構後的程序,由於沒有GOTO語句,程序可以用縮進的方式,增加程序的可讀性:
1 FOR i=1 TO 10
2 PRINT i;"squared=";i*i
3 NEXT i
4 PRINT "Program Completed."
5 END
程序中還是有由一個區域跳轉到另一個區域的情況,不過這種跳轉是可以預期的,也是標準的做法。使用FOR循環或子程序是處理程序控制流程的標準做法。若使用GOTO,也就表示允許程序任意的跳轉。上述示例的代碼很短,實際使用的程式其源代碼更長,若是麵條式代碼的話會相當難以維護。
匯編語言及腳本語言[編輯]
當使用各種匯編語言(及其底層的機器語言)時,編寫麵條式代碼會帶來更大的危險。其原因是由於這些低級語言很少有可以對應 FOR 循環或 WHILE 循環的機制。許多腳本語言也有類似的情況,例如 DOS 的批處理文件或者 OpenVMS 上的 DCL。
如果將結構化編程中的做法移植到匯編語言的程序,會對可靠性及可維護性有顯著的改善。例如限制 GOTO 的使用,只用 GOTO 來產生類似結構化程序設計中流程控制的效果、另外許多匯編語言都有提供子程序呼叫的機制,可以有類似過程式編程(Procedural programming)的效果。匯編語言一般都會有巨集,而且支持參數傳遞,以避免全局變量的使用,也可避免遠隔作用 (action at a distance)的反面模式。
使用高級語言編寫的程式可以利用一些標準流程控制的作法(如以上第2例的 For 循環),不過當編譯為匯編代碼或者機器代碼時,由於最後仍利用 GOTO 或 IF 之類的指令表示高級語言的標準流程控制,看起來會像是麵條式代碼。因為編譯器會忠實的將程序的結構轉換為匯編代碼,因此不會遇到其他結構性較弱的語言所遇到的程序流程難以辨識的問題。不過,如果程序做了過多的優化,可能在縮小程序大小的同時,也影響其程序的結構。若配合代碼級調試使用,有時會因此造成一些困難。
餛飩式代碼[編輯]
餛飩式代碼(Ravioli code)是指程序中是由許多小的、鬆散連接的部份所構成。餛飩式代碼可以和麵條式代碼作類比,後者用麵條來代表程序的結構,而前者用餛飩(Ravioli)來代表程序中的對象。這種代碼雖然滿足了低耦合性的要求,但是過度的分離與封裝導致過多的調用,使得堆棧容易變得臃腫,從而也增加了閱讀代碼的難度。
參見[編輯]
- 結構化編程:程序中不使用
GOTO,只使用像 Loop, For 及其他的流程控制指令。 - 國際C語言混亂代碼大賽:一個設法寫出讓人難以理解的 C 語言代碼的比賽。
- 組合子邏輯
- 柯里化
- λ演算
- 極小化求值
- 求值策略
參考文獻[編輯]
- ^ William J. Brown, Raphael C. Malveau, Hays W. "Skip" McCormick, Thomas J. Mowbray (1998). AntiPatterns: refactoring software, architectures, and projects in crisis.(1st ed.). Wiley. ISBN 0471197130.
- ^ J. Stanley Warford (2009). Computer Systems.(4th ed.). Jones & Bartlett Publishers. ISBN 0763771449.
本條目部分或全部內容出自以GFDL授權發佈的《自由線上電腦詞典》(FOLDOC)。