2022年7月13日 星期三

Delphi 是否還應該保留對Goto/Label, With 的支援?

 Pascal 時代的遺產

熟悉或者使用了 Delphi 一小段時間的開發人員,都知道 Delphi 的語言是 Object Pascal,而 Object Pascal 是從傳統的 Pascal 演進而來的,這個歷史可能得回溯到 1993-1995 之間,Turbo Pascal 6, Turbo Pascal 7, 以及 Delphi 誕生的那個時代,提到那個年代,就不可避免的必須提到 Anders Hejlsberg 這位大神的貢獻,在 Borland,他改進了 Turbo Pascal 6.0 到 Delphi 7 之間的所有記憶體管理功能,之後轉戰微軟創造了 C# 程式語言與 .NET 平台,最近這幾年又創造了 TypeScript,如果過去三十年當中必須選擇一位我最崇拜的技術人員,非 Anders Hejlsberg 莫屬。

嘮叨了一下簡單的歷史,在 Pascal 時代延續到 Delphi 的 Object Pascal 語法,到目前的 Dephi 11 Alexandria,即使 Delphi 已經加入對於 Windows/macOS/iOS/Android/Linux 各種平台的支援,也加入了 Parallel (平行處理)  的功能,讓多核心的系統能真正發揮最大效能,但 Pascal 時代的遺產還是一直存在。

雖然對於傳統 Pascal 的語法支援可以讓大多數熟悉傳統 Pascal 的開發人員更快上手 Delphi,但是這些語法在新支援的功能中還是有些風險的。讓我們一起來看一下當中的問題。

絕對不要使用的語法:GOTO/LABEL

從 1998 年開始,筆者在攻讀博士的時候,也開始在學校兼課,在所有的程式開發課程中,只要開始講到 LOOP, Branch, Function, 都不免會講到這個最古老的語法:GOTO + LABEL,但筆者也一定會跟課堂的所有學生說『這個語法,禁用!在我課堂上的所有作業中,出現GOTO語法,一律 0 分』

GOTO語法在筆者唸高中剛學 BASIC 語言的時候,是不得不使用的功能,畢竟當時的作業系統是單工的DOS,也沒有多核心、多線程、網路或其他週邊可能來干擾,用 GOTO 讓程式碼得到迴圈的功能無可厚非。

但一旦引入了副程式的概念之後,不管是在 BASIC 裡面的 sub, 還是 Pascal 裡面的 procedure/function 或者 C 的 function, 更可怕的是在 OOP 當中的 Method,都有維護、管理變數、屬性生命週期的議題需要注意,即使不用 GOTO 這個惡魔語法,一個不慎都可能讓整個程式 crash,如果有傻傻搞不清楚的開發人員或者開發學員,在 function A 裡面設定了個 LABEL,在另一個 function B 裡面直接 GOTO 到該 LABEL,下場就是程式直接巴比Q了。

現在還有更嚴重的情況,就是在 Class A 的 Method 當中寫了 Label,但從 Class B 的某個 Event Handler 用了 Goto 跳過去,如果這時候 Class A 根本不曾被建立出來,整個程式也是直接 GG..... 或者是在匿名函式當中做了 Label, 從其他 Method 中 Goto, 執行中的程式也是直接 Bye 了.

如果是簡單的工具程式,幫大家做做簡單的計算機或者文字編輯就算了,但如果是排版、圖片處理的應用程式,在輸入了很多資料,還沒存檔之前,突然直接 crash,絕對會讓使用者直接問候開發人員或者提供應用程式的人家裡的祖宗十八代。

所以,修過筆者開課的所有同學都會牢牢的記住『不可以用GOTO,不然一律0分』這個鐵律,也請大家絕對不要用它。只有組合語言是個例外,因為不用 jumper,就沒得玩了!

不建議使用的語法: With

在傳統 Pascal 當中,Record 跟 Packed Record 常被用來作為自訂型別的結構,由於當中可以把多種型別組合成一個新的型別,在還沒有OOP的那個年代,這個做法已經接近現代OOP的屬性概念(當然當時還沒演進到資料封裝的能力、也還不能包含Method的程式碼在 record 裡面,這些功能都在 Delphi 10.4, 11 的這幾個版本當中被加入了)。

為了方便程式碼的撰寫,傳統 Pascal 提供了 With 這個語法,透過 With,開發人員可以不用把完整的變數名稱每次都 key 出來,省下了不少的打字時間。但是有一長就有一短,在With 當中可以一次標明多個變數,如果這幾個變數當中,出現了同名的屬性,在編譯的時候可能會有語焉不詳(ambigution)的情況發生,而在後續的維護中,也可能讓接手的ㄎ發人員弄錯該程式碼的原意,這是很糟糕的情況。

結論

綜合以上的說明,筆者的想法是『GOTO/LABEL』應該要從Delphi 的 Object Pascal 語法中移除,連出現都不該出現。而 With 語法則是建議編譯時出現提示警告,再過一兩個版本就不支援。希望 Embarcadero 能盡早為了 Delphi 的產出程式更穩定而做出這個修改。

您也有想要建議 Embarcadero 移除掉的傳統 Pascal 語法嗎? 歡迎在底下留言,筆者在參加 Embarcadero MVP 會議的時候會幫大家提出的。

2 則留言:

  1. 我自己是不用with, 但是在大量的維護程式碼中,處處都可以看到with, 是真的可以少key in 很多字, 但是要閱讀很多遍才弄得清楚什麼是什麼, 看來with是很難取捨的兩難寫法

    回覆刪除
    回覆
    1. 的確, 但多層的 with 發生的時候, 如果當時兩三個 object 有相同的屬性, 就會有混淆不明的情形, 所以在7月份 EMBT 發出了幾個舊語法, 發起全球開發人員投票, 看看大家最希望拿掉哪個語法.

      我想這個語法未來也可能用舊版專案轉換的工具把它轉成新版語法就是了.

      刪除