用 PHP 開發健壯的代碼 系列文章是關於解決大中型應用程式中的實際問題的。這一系列文章主要側重於 PHP 4 中可用的新功能,重點介紹了大量使開發工作更容易的技巧和竅門。在這一系列文章中,您將發現許多要學習的樣本和技術,還附帶了大量樣本代碼。在這第一篇文章中,PHP 高手 Amol Hatwar 從更高的角度介紹了如何為中到大型 Web 應用程式設計和編寫無錯誤、可維護的代碼。
如果您是一名構建 Web 應用程式的開發人員並且需要速度、功能和平台獨立性(platform-independence),那麼 PHP 將適合您。而且 PHP 是免費的,易於學習和部署。這些是使 PHP 如此受歡迎的最大優點。但這些優點也可以變成缺點。由於 PHP 便於使用,所以開發人員在本應規劃和設計的時候,他們經常先把代碼硬塞到編輯器中。而且,在 PHP 中,解決問題的方法不止一種,比較容易犯那種慘痛的錯誤,這種錯誤過後難以訂正。
在這一系列文章中,您將學會如何避免許多錯誤。如果您一步不落地堅持到底,您會發現自己嘗試一兩次就能編寫無錯誤的代碼了,對此不要感到奇怪。我還會指出 PHP 4 中可用的新功能,它們使開發工作更容易。我要介紹的大多數樣本都是用來處理諸如指令碼配置和安裝、檔案處理以及資料庫使用之類的實際問題。即使您對這一切都不熟悉,您也會發現理解起來很容易。不過,我假設您對 PHP 有初步的瞭解。如果您需要重新溫習,您會發現本文結尾處所列出的參考資料會對您有所協助。(請參閱參考資料。)
奠定健壯的基礎
用 PHP 編寫代碼與用類似 C 的語言編寫代碼非常相似。由於它們句法上類似,所以還會導致類似的代碼維護問題。當必須開發大型應用程式時,您可能要編寫大量代碼。隨著時間的流逝,這些代碼可能變得難以管理,錯誤很快就會乘虛而入。無論您從哪裡聽到這種說法,都不要相信 — 至少不能全信。但是,更重要的事實是如果您發現自己維護代碼過於頻繁,那麼首先您的應用程式的設計可能是很糟糕的。
正確地設計代碼
您最初做出的選擇會影響您以後編寫代碼時的自由度。這使得正確的設計成為一個重要的先決條件。雖然當您解決一個微不足道的問題時設計會成為一個額外的儀式,但是您至少必須知道就是應該這樣做的。許多人把設計和規劃看作額外的開銷。但是以糟糕的設計開始,或者根本就沒有設計,結果總是會造成草率的代碼。請記住,再巧妙的編碼也不能彌補糟糕的設計。雖然如何設計應用程式超出了這個系列文章的範疇,但我還是會提示一些設計 Web 應用程式時應該牢記的問題。
分割和征服
通過一個個較小的鬆散耦合的組件來設計和編寫大型應用程式總是更可取的。這樣,每個組件都是可維護的。例如,一個內容管理系統(Content Management System,CMS)可能分布在許多諸如使用者認證、顯示、內容解析和查看統計資訊等較小的模組上。而且,如果您的模組足夠通用的話,您可以在您開發的其它應用程式中重用代碼。程式員經常這麼做,但他們仍然抱怨。至於編碼的技巧就是讓每個模組具有它絕對需要的功能並且到此為止。賦予一個模組的功能要不多不少,恰到好處。
絕對不要在頁面中考慮
如果您對用 PHP 將您的 HTML 頁面變得更動態些感興趣,這部分將適合您。當您想在每個頁面上顯示日期和時間以使其看上去是最新的時候,通常是這個習慣開始的時候。每個 HTML 頁面都變成一個只有有限幾行的小 PHP 指令碼,日期函數隱藏在某個地方。如果這是您想要的,您必須認可這是使該作業實現的最簡單的方式。但是,想象一下您必須做些什麼變動才能改變頁面上呈現的日期格式。您將不得不更改每個頁面內的代碼。
顯然,有更好的方式來達到這個目的。我最喜歡的方式是使用設定檔並在設定檔中定義一個常量,這個常量保留 date()
函數的格式字串。然後,您就可以在需要的地方使用 date()
函數了。每個頁面仍以指令碼結束,但是您要徹底地把那些您必須對單行代碼作更改的地方降到最少。
如所示,您在所有頁面上都能看到日期格式的更改。這裡的想法就是要避免複製代碼以及寫入程式碼。在編寫大型應用程式時,請牢記這一點。當您避免了複製代碼時,調試和維護就變得更加容易了。
減少客戶機端要求
Web 頁面和應用程式的類型已經向多方向發展了。首先是映像和影像地圖,然後是實現很酷的動畫的 Java applet 和客戶機端指令碼。現在是 Flash。有影響是好事情,但是您必須記住 Web 背後的整體思想是使任何需要資訊的人都能隨時訪問這些資訊。如果您使用並非所有瀏覽器和平台都支援的技術,就會拒絕人們訪問您的資訊。您永遠不知道不能訪問您 Web 網站的人是否本來可以成為您的下一個客戶!
您的應用程式設計應該儘可能地將網路流量降到最低。我們經常看到許多網站訪問量過多並且只給瀏覽器一類僅能使其啟動並執行 cookie。篡改大量 cookie 不僅消耗頻寬,而且還使得許多方面難以管理。根據經驗,如果您的應用程式發送超過 40 KB 的資料或者如果您的頁面需要多於 5 秒的時間來裝入,那就該從頭設計應用程式了。各處的小調整不會持續太久。如果您到處看看,就會發現最受歡迎的、訪問人數最多的網站都是非常簡單的。
您還應該考慮下一波行動裝置以及它們訪問您的應用程式所用的串連。最好的做法就是,您的應用程式必鬚根據請求內容的客戶機對內容進行調整。Leon Atkinson 在他的 Core PHPProgramming 一書的第 720 頁中說到,“我們可以設法將 HTML 文檔的大小控製得較小,並且我們可以設法避免諸如巢狀表格(nested table)這樣的複雜的 HTML,但是我們不能對每個人的 28.8 數據機都進行升級。”
把代碼、內容和顯示分開
HTML 是顯示內容的標記語言,PHP 是嵌入 HTML 的指令碼語言。這確實使簡單的任務變得容易 — 例如,以日期為例。不過,當您要實現複雜的要求時,將 PHP 嵌入 HTML 使代碼的簡單性盡失。儘可能地把代碼、內容和顯示分開,這很好。考慮一下您正在閱讀的這個文檔。這個文檔開始被建立為一個 XML 檔案。HTML 和 PDF 版本是用樣式表自動產生的。代碼(向您顯示該頁面的應用程式)、內容(XML 文檔)和顯示(樣式表(style sheet))是不同的。
正象將核心功能封裝在模組中以及避免代碼複製很重要一樣,用單獨的內容來源代碼以及按照要求的方式顯示內容也很重要。您根據客戶機和連線速度定製頁面的靈活性也增加了。同時使程式員、設計師和作者彼此獨立工作 — 如果您正在處理一個大型項目,這是一件好事。
不要害怕拋棄設計
無論別人告訴您什麼,實踐才是學習應用程式設計的最佳方式。如果您剛剛起步,可能會犯許多錯誤 — 這就是學習方法。糟糕的設計應該被拋棄。這就是您必須保持代碼、內容和顯示鬆散耦合的原因 — 拋棄糟糕的設計成為減輕痛苦的手段。當您丟棄陳舊的代碼,以更好的代碼取而代之的時候,您可以保留內容和顯示。
現在,回到我所承諾的問題上,使您的代碼健壯起來。您必須一直記住您的代碼將為其他人的內容和顯示提供力量。如果您的代碼不能勝任的話,其他部門再多驚人的努力也不能彌補這個缺陷。
編寫健壯的代碼
假定您的代碼要求不變,您將不會明顯地發現更改代碼的需要。除了偶爾需要最佳化和改進之外,您的代碼應該像加了潤滑油的機器一樣運行。
聽上去很困難?事實並非如此。坦白地說,編寫健壯的代碼並不需要天才。您只需要在拿不準的時候問自己一些適當的問題,這樣就不會偏離正軌:
- 它安全嗎?
- 它簡單且易於理解嗎?
- 它是平台獨立的嗎?
- 它足夠快嗎?
保護您的代碼
任何使大量使用者滿意的系統都必須是安全的。儘管 PHP 本身不易受到黑帽(black-hat)駭客的攻擊,但是您不要太肯定。在版本 4.2.2 之前的 PHP 4 有嚴重的安全性缺陷。要一直確保在有適當加密的網路上儲存或傳送敏感性資料。這對於處理業務、儲存資訊(如信用卡號碼)以及傳輸機密資料的應用程式來說更重要。
現在,很難信任使用者提交的資料。要確保對資料進行了驗證並確保資料在使用前是清白的。請牢記,將您的 Web 應用程式放到網際網路上就是向巨大的網路公布了您的系統、軟體、資料以及業務。
確保您的代碼一直安全地運行。
保持代碼簡單
您的代碼應該是易於理解、可讀性好且文檔良好的。為了減少您熟悉自己或其他人的代碼所需的時間,請在工程內一直使用公用命名和編碼約定。請投入時間以確保在需要維護代碼時這些方面會有所回報。
您最好在編程時為代碼建立文檔。能為您解析所有的指令碼並建立看起來整潔的 HTML 格式的文檔的工具並不存在。如果您改變了代碼的行為,就要相應地改變文檔。如果代碼的文檔並沒有實際記錄什麼東西,那麼擁有這樣的文檔是沒用的。
確保您的代碼是備有文檔的、簡單的並且易於理解的。從長遠來看這樣會有所協助。
使代碼是平台獨立的
您必須解決的另一個問題是平台獨立性。當然,為 Windows 上的 PHP 編寫的指令碼將對任何其它平台上的 PHP 起作用:PHP 就是這樣設計的。不過,您仍然需要小心比較小的不一致。例如,換行字元在 Windows 和 UNIX 中就以不同的方式表示。
您在訪問資源(如位於 PHP 外部的資料庫)時還必須使用抽取。比方說您的應用程式用 MySQL 作為資料庫伺服器來削減成本。如果您決定以後擁有一個功能更豐富的資料庫,您必須更改應用程式中的代碼。對代碼進行重大更改總是一個苦差事而且是一個易出錯的過程。請使用抽取來隔離對易於更改的部分的改變。您不必重新編寫整個應用程式。
確保您編寫的是平台獨立的代碼。這使您的應用程式具有更好的適應性和延展性。
為速度構建
最後一個值得處理的因素是速度。當您的指令碼從資料庫中拖拖拉拉地選擇大約 300 個條目並顯示一個頁面時,沒有人願意一直等下去。將 20 個結果放在 15 個不同的頁面(這些頁面在使用者的瀏覽器上快速移動和裝入)上通常是一個較好的主意。使用者把更快的回應時間理解為速度。另一個易犯的錯誤是每次使用者訪問頁面時都動態建立頁面。這的確能確保您的網站總是最新,但是當使用者數量增加時,PHP 就不能容許這樣做了。您應該快取那些使用頻繁的頁面。快取使您的應用程式速度更快並且減少了伺服器上的負載。
確保您的代碼快速運行。沒人喜歡等待。
總結
在這個系列的開篇文章中,您瞭解了編寫健壯的代碼要實際做些什麼事。如果您認真學習的話,用 PHP 開發大型應用程式一點兒都不難。事實上,許多用 PHP 編寫的應用程式已經輕鬆開發出來了。同時,意識到您容易掉入陷阱中是很重要的。只要您進行了規劃、把事情分解成許多小一些的任務並且正確實現它們 — 幾乎沒有別的什麼會阻礙您了。
在下一篇文章中,您將學會如何高效率地使用變數和函數。我將額外向您展示如何用 PHP 中的變數和函數變一些戲法。我們在這篇文章中規划了我們要討論的主要內容。在下一篇文章之後,我們將逐個討論這些內容 — 可能甚至會跳躍著講述。到時再見。
參考資料
- 請訪問 phpbuilder.com 以擷取大量初級到中級的教程和參考資料。
- 通過 Zend(開發 PHP 的公司)的討論群組、文章以及許多其它的技巧進一步提高您的技巧。
- 學習 Developer Shed 教程並學慣用 PHP 編寫自編寫文檔(self-documenting)的代碼。
- 試著使用 PHP 編寫的 PHPDocumentor 工具從您的檔案中抽取文檔。
- 探究 Weberdev.com 上的許多初學者指南,以獲得實際使用 PHP 的信。
- 現在就開始 PHP?請閱讀“Introduction to PHP”,一篇開始學習 PHP 的好文章(developerWorks,2002 年 12 月)。
- 請閱讀“Script Web databases quickly with PHP scripting language”以擷取關於讓 PHP 和資料庫一起工作的優秀的介紹(developerWorks,1999 年 9 月)。
- 通過文章“Creating dynamic Web sites with PHP and MySQL”(developerWorks,2001 年 5 月)學慣用 PHP 和 MySQL 編碼的出色的方面。
- 通過“Personalized Web sites in a jiffy”(developerWorks,2000 年 9 月)找到更多現實中應用您的新 PHP 技巧的地方。
- 請閱讀 Kent Beck 的 eXtreme Programming Explained 以獲得關於 XP 的優秀介紹。
- 請查閱 Leon Atkinson 的 Core PHP Programming,一個面向 Web 開發人員的實用的 PHP 4 指南。