這篇是寫給新同事以及我自己備忘用的,也歡迎大家提出指正。

在撰寫網頁程式時,有些基本的東西要非常注意,這樣寫出來的程式才不容易出現問題,也才能夠交給客戶。以下就是我自己的開發心得,供大家參考。

利用明確的指定方式來取得頁面傳來的變數

不管是 GET 或 POST 的參數,我會希望明確地指定它的型態,例如 id 應該是整數, content 是文字等。而且我也常常發現有人把接到這些變數後,沒有事先做處理就直接串到程式中,這是非常危險的一件事情!

最明顯的例子就是 SQL Injection 了,我想這應該不用多說了。總而言之,不要過份相信用戶端傳來的資訊,把它轉換成你能掌握的型態再用吧。

資料庫的連結每個頁面只作一次

資料庫連結是網站頁面常做的事情,但是儘可能不要讓一個頁面產生太多的資料庫連結。我們可以利用 Singleton 模式來取得資料庫連結物件,這樣可以確保程式裡只會用到一個資料庫連結;當然需要連結不同資料庫的話就另當別論。

所以我們要確定資料庫會在頁面初始化時連結,頁面結束時關閉。這樣有單一的入口與出口,程式也就不容易出現奇怪的問題。

相同的邏輯不要寫兩遍以上

如果發現有兩支程式會用到相同的程式邏輯時,不要猶豫,把它抽出來變成類別或函式 (最好是類別,原因在下一則) 。因為如果哪一天需要更新程式的邏輯時,你只需要更改一支程式即可。對健忘的人來說,這點尤其重要。

我就遇過有人把產生選單的邏輯重複寫在十多支程式裡,結果有次客戶要求要修正其中一個地方,可憐的維護人員 (就是我啦) 就得一支一支地去翻出來改。

利用物件來管理錯誤

我這裡指的錯誤是任何預期中的狀況,也就是你不希望使用者操作的方式,例如編號不存在或是檔案大小超過限制等。

當錯誤發生時,不要立刻結束,應該利用錯誤上升機制來讓通知上一層的程式,最後再由頁面控制程式來決定要如何處理錯誤。我常常會遇到有人在函式裡利用 exit 離開程式,但是這時候頁面的資料庫或其他物件等等都還沒釋放掉;雖然程式平台可能會幫你做,但那總是很難預期。

所以我建議不要使用函式,而改為使用物件的方法,然後利用類似 PEAR::isError() 來判斷是否執行成功;如果失敗的話就把錯誤往上丟,直到頁面能夠控制為止。

該釋放的要記得釋放

不管是物件還是資料庫,都應該在頁面結束前將它們銷毀或關閉,而不要過於依賴程式執行平台。網頁程式是很多人會同時存取的,如果沒有正確地將資源即時釋放掉的話,久而久之就會造成系統效能上的不穩定。

而釋放的動作要什麼時候做呢?記住一句話:誰開的就誰負責關。例如上面頁面控制程式開啟資料庫連結,那就在頁面控制程式的最後把資料庫連結關閉。類別建構函式產生的物件,就在類別解構程式裡銷毀。函式開的頭,當然就在函式尾收掉;不過有個例外,那就是這個函式如果本身就是要回傳產生的物件時,那就不能把它給釋放囉,而是要改為呼叫這個函式的程式來釋放。

利用樣版技術

樣版是用來分離程式邏輯與視覺頁面的,也常常有人用 MVC 這個模式來稱呼它。然而兩者分離除了不相互干擾外,其實還有一個好處:那就是程式可以在錯誤發生後,決定要顯示的結果。就像上面提到的錯誤管理,當我們在頁面控制程式取得錯誤訊息時,我們就可以而用置換樣版來避免掉頁面的錯誤,或者是導向別的處理程式。

這點我覺得 PHP 的 Smarty 就考慮得很好,因為它是後期頁面綁定 (Binding) ,而不會像傳統樣版引擎在前期就把頁面拉進程式處理,導致錯誤發生時徒然浪費處理時間 (當然要看怎麼設計的) 。

徹底瞭解開發環境的性質

網頁程式和一般應用程式 (例如視窗應用程式) 在本質上是有差異的,這些差異不僅是在操作上,就連執行的過程都非常的不一樣。雖然現在有 AJAX 或其他技術可以縮小彼此的差距,但是它還是建構在 HTTP 這個無狀態協定之上。身為網站程式開發人員,其實應該要瞭解這些基礎,而不要只熟稔某些已經被包裝過的技術就顯得自得意滿。

最簡單的就是伺服端程式與用戶端程式之間的溝通,例如 PHP 和 JavaScript 。我常常在網路上看見有人問道:要如何讓 PHP 和 JavaScript 之間的變數互通?如果瞭解 HTTP 執行的過程,那麼你就會自己發現這些問題的答案。