最近看了 PHP 近幾年的使用者人數統計報表,發現使用得人數逐年下降(當然 Java 也是如此),PHP 的架構遇到大型的設計越來越難滿足需求。我承認 PHP 一開始在架構上確實沒有設計的很完善,但是隨這物件導向 (OOAD) 成為主流的設計模式,PHP 也開始慢慢跟進。在不同版本的 PHP 中,Class 的用法常常充斥著混亂與特異,真的說起來 PHP 的 OO 實在有點斷手斷腳,特別是 Interface 與弱型別的巧妙組合,當然我也不可否認 PHP 的 Magic Method 確實蠻好用的。這幾年 PHP 在物件導向的努力算是比較統一了,但是使用者開始有更大更多的物件導向需求。
PHP 奇妙的 Namespace 設計
PHP 5.3 新增了一個很大功能就是 Namespace,當我們在實作比較複雜的系統時,例如分散式或模組化系統都會遇到 Class 命名重複的問題。是的,Namespace 就是為了要解決這樣的問題而存在的一種機制,但是 Namespace 在 PHP 的實作上卻變得很奇怪,完全體會不出這樣的 Namespace 能解決本來應該解決的問題。先不談 PHP Namespace 使用了奇怪的 \ 符號作為命名空間的定義 (這大家都在罵),PHP Namespace 用起來就像是 PHP 系統內建了偽命名空間 (Simulating Namespaces) 的實作,然後我們可以在這個奇特 Namespace 中宣告不會互相干擾的全域變數與類別。為什麼失敗呢?第一、在檔案一開始就要宣告 Namespace 這樣的限制太大,想要動態掛載命名空間變得很困難;第二、在有階層關係的命名設計中,但卻未實作階層關係的類別載入機制;第三、在命名空間中僅剩可用的全域變數宣告,但"全域變數"在物件導向與或程式設計師手中,是被摒棄的設計麼模式。
話雖然這麼說,但是 PHP Namespace 還是讓不少 Framework 盡可能有效地使用,像是在 ORM (Object-relational mapping) 就相當需要這樣的機制。
聰明地 PHP 更需要老練的程式設計師
再來就是聰明的 PHP 所帶來的災害,話說 PHP 怎麼寫怎麼對,第一次寫 PHP 的時候真的感覺太有成就感了,開發速度超快。但程式碼常隱藏了很多的 Bug,除非遇到特定的 Case 才會出錯,因此在測試工作上需要花上更多的心力來補足。PHP 太多的錯誤在編譯時期 (Compile-time) 不會被驗證出來 (這裡編譯指的是語法檢查並非編譯為目的碼的那一件事),一定要到執行時期 (Run-time) 才會被呈現,如果遇到經驗不足的程式設計師,就容易設計出含有很多小問題的系統,使得系統整體的品質降低,專案風險提高。
而 PHP 的弱型別 (Weak Typing) 變數特性也是致命傷,變數不需要宣告即可使用,當然也沒有型態別。這樣的程式碼很難一眼看出設計的隱喻 (Metaphor),時間久了系統如果沒有足夠的文件作為輔助,在維護上會比較吃力。當然像 PHP 弱型別這樣的設計並不是沒有優點,至少它在動態性表現上會比較出色;但強型別依然可以透過其他方式強化動態特性,像是透過 Reflection (反射) 與 Annotation 等等機制來實現。
在 PHP 的程式碼中也很少程式設計師有設計變數宣告與釋放的動作(總想反正 Request 結束記憶體會自動釋放),我想這是一個概念性的問題,只是方便的 PHP 讓這樣的概念變得不重要了。但久了容易養成習慣,慢慢地就忘記要釋放記憶體這件事了(而通常在批次處理資料的 Request 碰到資料量大的時候)。
PHP 的未來!?
對於 PHP 這幾年的發展,看起來實在有些迷惘。為何 PHP 無法進入到企業領域?這絕不能怪罪於 Scripting Language 的限制,不論效能的影像,畢竟我承認直譯語言 (Interpreted Language) 在開發上既省時又省力。那 PHP 輸在哪裡?從架構面來看,目前普遍使用的 LAMP (Linux, Apache, MySql, PHP) 架構缺少了 Container 特性,少了這個特性使得做起事來綁手綁腳,為了效能很多設計模式變得不適合在這樣的架構中實作。常為了達到某種目的非得透過其他第三方元件來創造有點殘廢的偽容器 (Fake Container),指的就是用 Daemon Service 的方式將物件保存在記憶體中 (Persistence)。目的雖然是達到了,但我更希望 PHP 未來能有 Container 的設計,才不會旁門左道怪招一堆。希望 PHP 下個版本能有進步囉。