由於 PHP 正在成熟,因此是快速即編即用的腳本編制人員與了解 UML 的面向對象的開發人員「思想達成一致」的時候了。
很少有程式語言能夠像 PHP 一樣迅速地普及。現在廣泛宣傳的那個關於自己動手做 (DIY) 的腳本編制語言改變 IT 業的故事表明,成功不一定總是來自於系統計劃和市場研究。但是現在的實際問題是這種成功如何能夠被龐大的 IT 產業所接受。 Oracle 以及其他幾個大的參與者正在關注 PHP 錚錚事實表明,這種語言已經成熟。
直到現在,成功也只是剛剛「出現」。數量不斷增長的愛好者已經聚集在 PHP 周圍,就像聚集在一個天才神童身邊一樣。但是既然這個孩子正在長出鬍子,並開始以平等的地位與成年人交談,那麼早期的擁護者會適應這種變化嗎?
PHP 與大部分主要的開放原始碼專案一樣,是正在成為主流技術的過程中的一種基本現象。 PHP 會使那些使它獲得名譽的人失望嗎?它會達到龐大的 IT 產業的期望嗎?
兩種程式文化的故事
PHP 的成功吸引了不同背景人士的注意。早期的Rasmus 的擁護者(如果您能諒解那些在開放原始碼圈內不常出現的略以救世者自居的語氣)習慣於快速的即編即用的腳本編制方法,他們現在必須對付那些了解UML 、物件導向(OO) 程式設計的開發人員,這些開發人員決心使PHP 與其他現代開發工具並駕齊驅。雙方都很了解 Web 開發,都擁有強大的文化。忽略任何一方都是不明智的。
早期的 PHP 類型了解 Web 開發的哪些方面,它擅長做什麼,不擅長做什麼?它了解很多關於設計的問題。它的風格有時可能會有問題,但可以看出它擁有 HTML 和 CSS 功能,不必說更為流行的多資訊網路應用程式 (RIA) 技術了。它總是那麼年輕,卻經常出現在 PHP 論壇中。術語「面向對象」對於它可能具有負面的涵義。它的程式碼很扼要,注重表現而不注重可維護性。
由於採用類型鬆散的變數和為其 HTML 程式碼填入 語句,因此 UML 類型將更缺乏吸引力。它將要考慮應用程式體系結構、類別級程式碼重用、團隊合作以及原始碼管理。它知道,即使複雜度適中的網站首先也是一個應用程序,而設計不良的應用程式會導致工期延誤、惹惱客戶甚至丟掉工作。
乍一看來,後者似乎更適應於需求越來越多的環境,在這種環境中,Web 開發將會越來越多地受到行銷策略和經濟因素的驅動。但是我們是否應該把前者看成瀕臨滅絕的物種?或許不該這樣。如果我們承認Web 是與桌上型電腦系統差異很大的一種媒介— 更不要說大型主機了(還有人記得3270 嗎?),在大型主機環境中產生了佔統治地位的開發方法— 則我們可能會得出結論,畢竟可以從這種成功卻相對雜亂的方法中學到很好並且有效的東西。
讓我們來回顧實際的問題,以便在其可能發生之前加以克服,並回顧一些實際的工作方法。
彌補文化差距
現在 PHP5 即將把物件導向技術帶入 PHP 世界。 Zend 引擎修改 (ZE2) 正在將物件引入該語言的核心。不僅新的語言建構鼓勵物件程式設計風格,語言的實作也正在適應其他的物件導向環境。例如,不再以預設方式將物件進行來回的複製,而是透過引用來處理。引入了新的關鍵字(如 final 或 static),它們只與物件概念相關,是對 Java 風格的保留;其他特性(如委託)鼓勵使用物件設計模式。 (期待在幾個月的時間後能夠聽到大家談論「原有的 PHP4」。) 這種深刻的變化來自於向當前佔優勢的程式設計模型進行無情的革命性轉移。無論您喜不喜歡,物件方法都將會流行,因為它已證明自己在提供複雜應用程式方面最有效,無論它們是不是 Web 應用程式。這使得我們別無選擇,只能尋找富於想像力的方法來協調兩種文化,以便具有設計思想的人與了解體系結構的人能夠取長補短。
為此,必須開發(或從其他平台中變換出)各種方法,以便在將其包含在清晰的界限內的同時獲得語言的多功能性。這樣,程式設計創造力的「孤島」就可以存在於強健的體系結構中。
一個明顯的事實是,儘管 PHP CMS 或應用程式框架的數量呈現爆炸性增長,卻沒有關於它們的一致意見。經常出現的報怨是,無論您的專案是什麼,現有系統都不能完成任務。人們大都開始於對若干系統的評估,而最後經常從頭開始發展自己的框架。這是為什麼?
在桌上型電腦系統中,似乎已經由作業系統徹底解決了 GUI 設計問題,與此相反,Web 是個原始視覺設計舉足輕重的平台。 Web 網站承載商業公司的形象和個性,可能日益影響其收入。視覺創造力與品牌共同發揮作用,因此必須促進它們的發展。
同時,必須能夠將靈活的邏輯編入到應用程式中,以便盡可能改善使用者體驗,應牢記,使用者在 Web 上要比在桌上型電腦系統中可能表現的更「菜」。
當設計人員不斷對程式設計師所設計的系統感到失望時,這是個問題,而當開發人員必須將應用程式碼強行加入到不完備的入口網站框架中時,這同樣是個問題。最常見的結局就是無法令人滿意的折中 — 有些呆板的外觀、為了將應用的複雜性限制在某個可管理級別而犧牲了很多可用性。 (這種現象並不只限於 PHP 應用程式。)
為了徹底克服這些限制,設計人員和物件導向開發人員必須找到一種不阻礙對方工作的協作方法。最好的方法可能是從了解對方團隊如何工作開始。
從技巧到產業
此刻先不要考慮協作問題,讓我們觀察各自的實際操作。讓我們按照 PHP 的歷史順序開始,先造訪一個「增強 html」使用者的商店。
進行交易的工具非常類似於「純html」使用者的工具:某些html 編輯器,具有各種等級舒適特性和專案管理特性,並在某種程度上與PHP、ASP、JavaScript以及較次要工具整合。
讓我們花點時間仔細觀察程式碼。我們首先會注意到,使用這些不同種類的工具產生的網站非常漂亮。我們在這裡不僅指技術,也指天賦。由於擺脫了抽象程式設計因素的限制,Web 設計人員透過擺弄積極、微妙的情感效果(類似於機敏的裝飾人員在真實商店中所營造的效果)營造了令您網站的客戶感到安適的視覺環境。
當我們從經過訓練的物件導向程式設計者的角度來看這些程式碼時,事情卻突然變得很糟。程式碼看上去就像它本身一樣:它是一次性的、用完即忘的工作,沒有為將來的發展或為簡易的維護作出任何準備。常這樣,的確如此。
那麼,這有什麼不好嗎?它以後是否會成為一個難題,導致放棄部分或整個網站並從頭開始重建呢?或許不是。畢竟,真實商店的裝修經常定期拆除並重建。因此,就這些櫥窗式的網站而言,牛仔風格的 PHP 程式設計已經夠用了。這種語言富含各種有助於實現旨在吸引訪客注意的視覺效果的技巧。這裡顯然與物件方法無關。
一旦需要某些應用邏輯時,這種觀點就會發生顯著的變化。您是否需要若干表單來收集有關您網站的常客的少量的行銷資訊?如果您希望這種資訊能夠很中肯,則最好添加校驗代碼。如果您這樣做,您應該確保可以過濾惡意腳本或 SQL 指令侵入式攻擊。順便說一下,既然您正在閱讀 OTN 文章,因此您一定熟悉資料庫 (DB) 問題。您將要收集的這些資訊將會存放在某些資料庫表中,而您的 PHP 程式碼中的 SELECT 語句將反映這種資料庫結構。從現在開始,這個網站已經固定在您的業務基礎架構中 — 它正在成為成熟的應用程式。
我們暫時不要管其所有的硬編碼連結、危險的類型轉換以及安全漏洞,接著存取最新的 PHP 物件導向應用程式組裝線。對於我們那些具有藝術家風格的 Web 設計人員而言,這種地方可能並不熟悉,甚至可能並不友善。在這裡不太看重技巧。 Web 開發已經產業化了。要為這裡所接受,您必須熟悉類別、繼承、資料抽像以及大量的程式碼封裝工具。
團隊協作需要規則。必須遵循程式設計慣例;必須將原始檔案提交版本管理和原始程式碼管理。文件根據嚴格的模組化層次進行組織。摒棄了那些有危險的編碼技巧 — 尤其是那些耍小聰明的技巧。程式碼不僅必須易讀,而且必須有良好的註解。
這樣可能令人厭煩,但卻很有效。現在我們正在創建 Web 應用程式:內部網路、商業 Web 網站、電子市場、各種應用程序,其中有缺陷的設計可能會導致關閉。簡言之,我們正在克服複雜性。
PHP 物件導向組裝線的管理者並沒有選擇 PHP,因為他們熱愛這種語言。他們之所以這樣做,是因為它不但能像那些專有的其他語言一樣有效地完成工作,而且還是免費的,也沒有任何附加條件。
我們要走向何處?
那麼我們將如何利用那些經過 C 和 Java 培訓的人們所提供的行業級方法,以完成對早期使用者所使用的多功能語言的專業技術的潛在補充?
PHP5 將會動搖許多習慣,因此這個問題可能為時過早。有些人將被迫採用一定程度的物件導向方法,而有些人最終會了解物件導向的所有內容並成為它的信仰者。某些小環境可能會像過去那樣良好運作並繼續興盛發展。
讓我們來實踐一下
現在讓我們深入到基礎的技術級別,了解如何養成簡單的習慣,以及尋找簡單而有效的解決方案將會如何幫助我們準備好應對即將來臨的改變。大量非常簡單的慣例有助於促進編程,並使應用程式準備好進行擴展。
命名慣例(C 程式設計人員的習性)是最容易的方式。如果您已經大量使用了程式碼庫(例如 PEAR),則將其慣例作為自己的慣例可能是個好主意;否則應制定您自己的內部規則。簡化的匈牙利批註(根據其匈牙利發明者 Charles Symonyi 而命名)可在鬆散類型所允許的範圍內廣泛應用。您也可以使用下劃線作為類別成員的前綴。另一個有用的習慣是,向那些並不用於從類別外部進行呼叫的方法(屬於一個類別的函數)附加一個特殊的前綴(例如 impl_)。
無論您採用什麼命名慣例,都要盡可能使您的程式碼明確清楚。這樣,經過訓練的人員就可能在滿屏的 PHP 中發現程式錯誤,只因為它看起來就有問題,就像肖像上的一個污點。
命名慣例的另一個重要面向是避免名稱衝突,使得在大範圍中重複使用程式碼成為可能。經驗告訴我們,程式設計師在命名程式設計物件方面並不總是非常富有想像力。很有可能,存在很多的 Page 類,而且也不是沒有可能當您要重用兩個 Page 類時卻發現,它們只是名稱相同而用途卻迥異。真不夠走運的。從長遠看來,重新命名將會帶來維護問題。您最好一開始就避免這個問題。產生 GUID 將會矯枉過正、難看(例如 _16B280C5_EE70_11D1_9066_00C04FD9189D_Page!)並且有悖於 PHP 的精神。
一種簡單且可以防止衝突的方法是,透過將類別的幾個不同面向關聯到其名稱中(例如GalleryPage),確保內部類別的唯一性;而後,為了消除與您控制範圍以外的類別發生衝突的各種可能,您可以按Java 的方式將您擁有的網域的保留版本作為它的前綴(com_mydomain_GalleryPage)。
要養成的另一個習慣不需要您花費什麼,並且當某個應用程式範圍的意外變化不可避免時,它可以節省您的工作,這就是將最常用的基本語句封裝在一個單獨的管道中。例如,除了偵錯程式碼,在整個應用程式中只應該有一個「回應」語句,它應該在某個函數(或單獨的類別方法)中。如果在某個新環境中需要對輸出進行預處理或重定向,則您知道應該將所需的幾行程式碼寫在哪裡,而不必面對那種搜尋和編輯大量文件的令人沮喪的情況。
錯誤處理不必像 C 中那樣嚴格 — 在 C 中,一個懸空指針 (dangling pointer) 或者緩衝區溢位可能極具破壞性。當沒有危及資料完整性時,試著大方地放下架子告訴訪客,儘管某些功能不太完善,但她可以再試一次。一個經常被忽略的好幫手是標準的 set_error_handler() 函數。這是另一個 — 這次是基本事件 — 封裝到一個集中位置(其中所有程式碼都專門用於處理這些基本事件)的範例。如果您希望保留所有發生錯誤的事件日誌,以便找出重複發生的問題,則應該在這裡完成這項工作。
在我們結束低階程式討論之前,還有另一個救命招術。在 PHP5 中,預設情況下,分配或傳遞物件參考(引用是物件的句柄,而不是物件本身或物件的副本)。只要我們還需要使用 PHP4,就必須認真注意物件的傳遞方式。某些微妙之處可能使您心神不寧。例如,以下語句導致 $obj2 成為 $obj1 的副本;這並不奇怪。
$obj2=$obj1;
函數將使用副本並傳回副本,除非另有指定 — 我們只好接受這種情況。以下範例導致許多了難以追蹤的錯誤:
class ObjectKeeper {
var $_obj; // Whatever object is
function & get_objectthis()
>_obj;
}
}
//引用可以很好地回傳。現在陷阱出現了:
$keeper = new ObjectKeeper();
$obj1 = $keeper->get_object();
$obj1->modify();
$obj2 = $keeper- >get_object(); // Ask new reference to same object
if ($obj2->is_modified()) {
echo 'OK'; // 這永遠不會列印
}
正確的語句應該是:
$obj1=&$keeper->get_object(); // 注意,是「=&」而非「=」
如果沒有=&,則傳回的引用所指向的物件的副本被指派給$obj1,而無論您對您認為正確的參考進行什麼操作,也不會影響原始物件的狀態。換言之,您的更新將會遺失。
在協調 Web 設計人員與程式設計師的文化方面,模板可能會大有幫助。它們通常包括佈局中所配備的一切(主要是 HTML 程式碼),而在生成頁面時,模板引擎填入所有可變的內容。大部分的模板引擎帶有快取機制,確保相關的耗費資源處理只發生在資料來源更新要求進行這些處理的時候。
接下來的步驟
論壇:Oracle 上的PHP
開放原始碼開發人員中心
Oracle PHP 疑難解答指南
:隨心所欲的程式碼逐漸流行
Oracle PHP 使用入門
在Linux 上安裝Oracle、PHP 和Apache