簡介
“真正的天才具有正确評價不确定的,有風險的和沖突的資訊的能力。--邱吉爾”
使用許多程式設計語言時,你通常隻能使用面向對象或面向過程二者之一的程式設計方式。而在PHP中,你可以自由選擇或混用。目前絕大多數PHP程式員使用面向過程的方式,因為解析WEB頁面本身就非常“過程化”(從一個标簽到另一個标簽)。在HTML中嵌入過程處理代碼是很直接自然的作法,是以PHP程式員通常使用這種方式。
如果你是剛接觸PHP,用面向過程的風格來書寫代碼很可能是你唯一的選擇。但是如果你經常上PHP論壇和新聞討論區的話,你應該會看到有關“對象”的文章。你也可能看到過如何書寫面向對象的PHP代碼的教程。或者你也可能下載下傳過一些現成的類庫,并嘗試着去執行個體化其中的對象和使用類方法--盡管你可能沒有真正了解這些類為什麼可以工作,或者為什麼需要使用面向對象的方法來實作功能。
應該使用“面向對象”的風格還是“面向過程”的風格?雙方各有支援者。像“對象是低效的”或“對象非常棒”這樣的議論也時有耳聞。本文不嘗試輕易判定兩種方法的哪種具有絕對的優勢,而是要找出每種方法的優缺點。
以下是面向過程風格的代碼示例:
<?php
print "Hello, world.";
?>
以下是面向對象風格的代碼示例:
class helloWorld {
function myPrint() {
}
$myHelloWorld = new helloWorld();
$myHelloWorld->myPrint();
如果你想了解一些“面向對象”的基本知識,請使用Google搜尋,網絡上有非常多精彩的文章。
誰像這樣寫代碼?
為了了解為什麼這個論題成為論壇上口水戰的導火線,我們看一些每個陣營的比較極端的例子。我們看看“過程狂熱”和“對象狂熱”。看看他們的觀點聽起來是不是有點熟悉。
過程狂熱
過程狂熱曾在上課時被計算機教師批評,因為這種方法沒有使用更加抽象的實作方式。而支援面向過程者的觀點“它可以工作!”并不能提高其程式設計水準和檔次。畢業後他們可能找到一個工作,寫驅動程式,檔案系統或其它的偏向底層的程式設計,他們的注意力集中于速度和代碼的精煉。
“過程狂熱”極端的例子是抵制對象,抵制抽象化。他們總在想着如何讓程式運作起來更快,而不在乎别人是否能讀懂他們的代碼。他們常常把程式設計當成競賽而不是團隊活動。除了PHP外,他們最喜愛的程式設計語言是C和彙編。在PHP世界中他們可能會開發PECL子產品,貢獻出高效率的代碼。
對象狂熱
對象狂熱者熱衷于在任何時候使用面向對象的風格來書寫代碼。他們沒有真正考慮過用這種方式是否會影響程式的執行效率。有時候讓人覺得他們更享受抽象的設計概念而不是現實的代碼。他們通常很可能是項目管理者或文檔書寫者。
對象狂熱者指出,如果沒有抽象的設計方法我們仍然在使用0和1進行程式設計。他們喜歡用僞碼來描述問題。極端的例子是對象狂熱者即使知道有時候會犧牲效率仍然使用對象。 除了PHP,他們最喜歡的語言是Java和Smalltalk。在PHP世界中,他們可能會開發PEAR子產品,貢獻文檔化非常好,易于維護的代碼。
不要偏激和諷刺
你知道為什麼論壇上總是充斥着各種偏見嗎?你的經驗閱曆,你對新事物的态度都可能是原因。作為程式員,我們需要時常注意這些偏見并以開放的心态去學習新事物。
你的編碼傾向?
考慮一下當你書寫PHP代碼時有什麼偏好或傾向。通常這些偏好是比較隐晦的。有時候你可能在每個項目中有着同樣的偏好。我個人傾向于“優雅”,但我不想在此定義如何才是“優雅”的代碼,那應當出現在另一篇文章裡。但是,理論化的偏好不一定适合于實際項目?相反地,他們常常是一種偏見。
理論化的傾向
• 用最少行數的代碼提供一個完整的解決方案
• 在問題層次上考慮問題
這聽起來似乎很不錯。但“代碼行數最少”如何來衡量呢?要把代碼注釋算在内嗎? 我們是否要把每一行都串起來而隻用分号來區分呢?大括号呢? 很明顯這種想法是錯誤的。
再解釋一下什麼是“問題層次”。這是否意味着在我們的方案中的每個概念都需要建立一個類?或者需要在每個獨立的檔案裡保持問題的每個部分,并建立一個複雜的檔案樹來與現實中的問題相對應?就是這樣的想法--為每個想法準備一個檔案或類!
很明顯這些概括極端化後變得可笑。但現實中存在更微妙的證明。是否常常會有程式員在團隊合作時插入一行複雜的,強大的但沒有注釋的代碼?這對于接手維護這些代碼的人來說無疑是非常令人沮喪的事。 相反地,是否你的官僚的自以為是的上一級程式員常常“橫沖直撞”般地,建立接口和類? 而那些接口和類不僅僅限制了負責實作的程式員,也限制了效率和靈活性,導緻客戶要求擴充程式時手足無措。 這些都是以上各種傾向的微妙的證明。
實際傾向
一個項目開始的時候,首先要尋求實際的編碼目的和方向。這個項目的實作目标是什麼?下面是可能是答案。
• 開發快,釋出快
• 盡可能快地運作
• 易于維護,改進和擴充
• 釋出一個API
第一、二個方向傾向于使用過程化的風格,而最後兩個傾向于使用面向對象的風格。
什麼時候某種方式更有效?
現在讓我們試着評價每種方式在現實中的優勢。
面向過程案例
有關PHP的面向過程化程式設計優勢的一個基礎性的論據是:PHP是一個解釋性的語言--這意味着,不像其它的語言一樣,它不會被編譯成一個可執行的包,而是被解釋并馬上執行。它是一種腳本語言并存儲于文本檔案中(例外的,如果使用了Zend編譯工具)。
另一個反對在PHP4及更低版本中使用面向對象方式進行編碼的理由是:在PHP的早期版本中對象的功能并沒有經過良好設計。就像Rasmus曾說過的:“那是事後才想起要增加的功能”。這意味着在PHP4及更早的版本中,對象的效率是個問題。但PHP5出來後,這種情形會有改觀。
以下兩個最流行的PHP程式--OsCommerce 和PhpMyAdmin.主要使用面向過程的編碼方式。它們建構起來很快,運作起來也很快。兩者都很自然地采用嵌入HTML的方法。
OsCommerce
OsCommerce實際上使用了很多對象,但絕大部分功能是通過“過程”來實作的。我曾經hack過OsCommerce,為其增添一些對于客戶非常實用的自定義功能。這個過程是挺麻煩的,因為OsCommerce中的很多過程代碼,沒有使用模闆化的系統,并且設計成多語言版,是以需要花一定的時間才能上手。但是它可以工作,事實上它已經很好地運作在數目衆多的電子商務站點上了。OsCommerce同時提供了一個論壇和一個開發架構用來開發子產品和插件。是以,現在已經有了很多其它開發者提供的實用的功能子產品。
PhpMyAdmin
PhpMyAdmin直接使用的類隻有一個:Mimer SQL Validator類,依賴于PEAR包中的Mail_Mime, Net_DIME 和 SOAP。這可能是考慮到開發的友善:利用現成的可以實作目的的代碼。除此之外,一切都是面向過程的,HTML和PHP代碼也是混雜在一起。
PhpMyAdmin是我幾乎每天都要用到的一個工具,用來對少量的資料表進行不太複雜的處理。有時我甚至鼓勵我的客戶将它當作後端的管理工具來使用(當然我會限制他們的權限)。PhpMyAdmin的表現非常棒,也很快。有時我想在一些項目中擴充PhpMyAdmin作為後端的管理工具,利用它的一些新功能如資料查詢語句書簽可以很友善地展示給我的客戶和編輯。随着每個新版本的推出,PhpMyAdmin越來越實用,功能越來越強大。
面向過程小結
以上兩個使用面向過程風格的程式都有非常好的文檔和代碼注釋。OsCommerce提供的開發架構可以增加維護性和擴充性。但是兩者都沒有提供API,不能擴充程式到另外的體系中。
如果你想把OsCommerce整合到一個帳單程式中,需要花費大量的時間和精力,就像擴充PhpMyAdmin成一個供客戶使用的後端管理工具。不過從它們設計的目的來看,确實在各自的領域中都表現地很出色。
面向對象案例
支援面向對象風格者的觀點都集中于擴充性和封裝。僅僅用面向對象的方式來寫代碼不會為你的代碼産生文檔,但它可以鼓勵你為之添加文檔。并且,為了易于擴充,你可能會寫一個API。 PHP5許諾讓面向對象程式設計更加愉快。我開玩笑地将它稱為PHP中的”Java 2”版本,因為它整合了Java中的許多特性,像接口,面向對象模型,try-catch語句等。但即使在對面向對象支援不力的PHP4中,仍然出現了許多出色的面向對象應用程式。
Smarty
Smarty用來建構帶有複雜表單并基于模闆的站點。最近,我寫了一個可以完全換“皮膚”的線上考試系統?可以不用改變任何底層的代碼和功能就可以将整個站點的外觀界面和風格完全改變。為了讓設計師可以易于設計新的界面,我設計了一個自定義的标簽庫作為Smarty标簽庫的擴充。可以像這樣簡單地插入:
[navigation horizontal separated by " | "]
由于Smarty封裝成一個類,并且它的方法都有很詳盡的文檔,使得使用模闆的過程變得令人難以置信地易于擴充。同時,通過強制性地隻能顯式地傳遞你要使用的變量給Smarty模闆的方法,Smarty也為PHP的環境變量提供了一個保護層。這種方法有助于在Smarty模闆設計師和程式員間建立安全、可靠的工作關系。
FPDF
FPDF是一個非常優秀的工具。如果你被改來改去的pdflib的API所困惑,或者不願為商業化的解決方案而交錢;或者由于共享主機的限制,無法使用擴充子產品?請考慮使用這個免費的,純PHP建構的PDF生成工具。
這個類有很好的文檔,包括許多很好的例子來闡述如何在PDF中布局文本和圖檔。在上面提到的同一個線上學習站點我使用FPDF來動态生成PDF檔案,使用true type字型和300dpi精度的圖像。在PHP中執行個體化FPDF類并進行PDF操作并不會花費太多額外的時間,因為PDF本身就可能需要花費幾分鐘來下載下傳。事實上,動态生成并傳送一個PDF所花的時間不比當使用一個慢速的網絡連接配接來傳送靜态PDF檔案所花的時間多。這都是相對而言的。并且,由于FPDF是基于類的,他可以被擴充。事實上,有些類方法雖然存在但還沒有完全實作,僅作為一個架構,這可以為你在子類中建立你自己的内容(如自定義的頭尾元素)提供向導。
面向對象小結
Smarty和FPDF都提供了帶有良好文檔的API來擴充主類。這說明了在類的内部組織方法和資料的必要性--有時同樣的功能可以用函數和全局變量來完成,但這樣不易于擴充。并且,使用對象對跟蹤和保持PDF或HTML文檔的風格非常有幫助,你可以将同樣的資料用不同的格式來釋出。Smarty和FPDF都是使用對象來建立靈活實用的類庫的極好的例子。
為什麼兩種方式都是必需的?
回到我們充滿熱情的程式員身上,我們開始贊美他們:
• 我們欣賞Smarty和FPDF的實用性和擴充性
• 我們欣賞osCommerce和phpMyAdmin的運作速度和良好表現
這種欣賞還包括對PHP的一些基礎開發。PECL和PEAR都收到了很多贊揚和批評。我想這兩個項目為闡明面向過程和面向對象程式設計的差別提供了很好的例子。
PECl提供了PHP的擴充庫,用C和面向過程的方式開發,注重速度和簡潔精煉。通常,這些都是從已經存在的LGPL軟體中移植而來,其中許多有趣的特性已經加入PHP。畢竟,PHP是用C寫的。
PEAR則貢獻了很多有趣的類如建立Excel表或改變DNS記錄等。使用PEAR類庫可以為你節約大量時間,甚至可以讓你在不怎麼熟悉PHP的情況進行開發?“我不了解但它能用!”。
總結
希望本文能加深你對兩種程式設計方式的了解,并且更重要地?鼓勵你在更具體的細節上進行探索。我希望你會有自己的想法,并在實際開發中檢驗你的項目開發傾向,總結出更多實際的案例,并不啬寫些針對本文的評論。
總之,每種方式都有其優勢的一面,糾纏于争論不如離開去寫些實際的代碼!
本文轉自
朱志兵 51CTO部落格,原文連結:http://blog.51cto.com/richardzhu/196752 ,如需轉載請自行聯系原作者