我從1990年就開始編寫PL/SQL代碼。這意味著我已經編寫了幾萬行的軟體代碼,但我確信,其中的絕大多數代碼都非常拙劣,而且難以維護。
幸運地是,我發現找到並遵循編寫出更好代碼的新方法還為時不晚。就是在去年,My Code品質有了顯著改進;這些改進主要是由於制定了一些簡單的規則,並像紀律一樣加以遵守。
本文為PL/SQL新手及有經驗的開發人員提出了四條建議;遵守其中任何一條,你的代碼品質都會有提高。這四點建議都採納,你可能會驚奇地猛然發現:你竟然是一個非常好的程式員,要遠遠超乎你的想象。
所有工作都獨自完成
我們很少有人是孤立工作的;大多數PL/SQL開發工作是在相對較大的機構中進行的。但我們基本上還是在自己的小隔間裡用自己的裝置獨自工作。幾乎沒有PL/SQL開發小組進行正規的代碼複查或系統測試。
我不可能通過這篇文章改變你們開發小組的基本狀態。因此,我仔細地選取出以下幾點建議。實施其中任何一點並不需徵得管理員同意。不論你的小組是大是小,都不必讓其中的每個人都贊同這些編碼規則。你只需按以下建議來改變你的本人的編碼方式:
1. 嚴格遵循命名規範,好像它們就是你的生命支柱。
2. 戒除編寫SQL的嗜好:編寫的SQL越少越好。
3. 使執行部分短小:告別“意大利麵條式的代碼”。
4. 找一位夥伴:非常贊同找個人來監督你的工作。
1. 遵循命名規範
如果你建立並嚴格遵循一套命名規範,特別是對於應用程式組件的,你就可以節省很多時間。
當然,遵循命名規範的想法並沒有什麼新意,你可能已經聽煩了。所以我並不提出什麼宏偉的命名計劃,而是給出一些非常具體而明確的約定,然後證明這些約定會多麼有用。
前幾個月我一直在為PL/SQL開發人員設計、構建一種新工具。它名為Swyg(可以在www.swyg.com中找到),可以協助程式員完成代碼的產生、測試及重用的工作。它具有幾個獨特的組件。我為每個組件指定了一個由兩個字母組成的縮寫名稱,如下所示:
◆SF-Swyg的基礎組件
◆SM-Swyg的中繼資料
◆SG-Swyg的產生程式
◆SL-Swyg的程式碼程式庫
◆ST-Swyg的單元測試
於是,我便遵循表1中的命名規範,同時使用這些縮寫。遵循這些約定有什麼好處呢?一般來講,如果我要求一致的命名規則,我就可以更流暢更高效地編寫代碼。
明確地說,這些約定具有可預測性,意思是說我編寫的SQL程式能產生有用的指令碼。例如,通過使用表1中的約定,可以產生Swyg中所有基礎包的安裝指令碼。執行這些工作的SQL*Plus指令碼如清單1所示。這類指令碼非常有用,因為它意味著我不必手動維護安裝指令碼。當我向Swyg方案中增加另一個表,並產生一組相關包時,我只要運行我的指令碼,更新後的安裝指令碼便會跳出來。
2. 戒除編寫SQL的嗜好
編寫的SQL越少越好,這似乎與我們的直覺不太一致。對於PL/SQL開發人員來說,這是一個奇特的建議,因為PL/SQL的主要優點之一就是可以毫不費力地在代碼中編寫SQL語句。不過,這種簡易性也是這種語言的一個致命的弱點。
可以將純粹的SQL語句直接置於PL/SQL代碼中,而無需JDBC或ODBC之類的中介層。因此,無論何時何地,PL/SQL開發人員只要需要SQL語句,他們通常就會向其應用程式代碼中嵌入SQL語句。那麼這樣做有什麼問題嗎?
在PL/SQL代碼中到處使用SQL語句必然會導致以下後果:
儘管實際表現不同,但同一邏輯語句仍會出現重複,從而導致過多的文法分析,且難於最佳化應用程式的效能。
暴露商務規則和方案。這直接在SQL語句中包含了執行商務規則的邏輯。這些規則總在變化,所以應用程式的維護成本會急劇增加。
當然,你要編寫的每一個PL/SQL應用程式幾乎都是基於基礎資料表和視圖的。你需要執行SQL語句。問題不在於是否執行,而是何時執行、如何執行。
如果你對資料結構進行封裝,或者將它們隱藏於一個PL/SQL代碼層(通常是一個程式碼封裝)之後,那麼你的應用程式將會更健壯,而且你還會發現建立和維護變得更易多了。
我們來看一個簡單的例子。 假定我需要編寫一個處理某員工工作的程式。第一件事是擷取該員工的全名,定義為“姓名逗號(,)姓”;然後我可以進行詳細分析。清單2給出了這種情況下我很可能要編寫的這類代碼的一個樣本。
一切似乎都是這麼簡單和直接;這些代碼可能會有什麼錯誤呢?實際上真是非常糟糕。最主要的是我暴露了一個商務規則:全名的結構。我可能要花費數小時來對此代碼及其所基於的應用程式進行測試。但就在它剛剛投入使用時,我才知道客戶會不斷地打電話告訴我,實際上,他們的全名應該表示為“名空格姓”。
現在怎麼辦?搜尋所有位於引號內的單個逗號?
現實的解決方案是使用隱藏所有細節、只提供一組預定義、預測試及預最佳化並能完成所有任務的程式包。清單3為基於封裝代碼重新編寫的process_employee過程。hr_employee_tp包提供了用於定義儲存姓名的局部變數的類型;hr_employee_rp包含有基於一種商務規則而返回全名的函數。
將顯示PL/SQL語句灌入SQL代碼很容易,同樣,談論封裝這些語句是如何重要也不費勁。但另一方面,編寫執行封裝任務的代碼卻具有挑戰性;甚至是不現實的。產生這些包或許更有意義。
幾年前,我曾協助構建這樣一個產生程式。該程式段為PL/Generator,現在由Quest Software公司擁有,PL/SQL開發社區可以免費使用。你可以從我的網站www.StevenFeuerstein.com/puter/gencentral.htm下載。要知道,其封裝體繫結構與我在前面所概括的約定不同。PL/Generator建立了一個單獨的包,它包含了一個表的類型、查詢和變化邏輯的全部內容。
當你不再編寫太多的SQL,而是調用執行SQL的程式時,無論你是產生還是編寫自己的定製封裝,你的應用程式都會受益匪淺。