PHP Design Patterns

自從拙文「為甚麼 PHP 沒被大企業採用」登出以後,不少人問「是否你不愛 了? 在你心目中是不是沒有價值啦?」當然不是! 是強大的語言,開發中小型系統最好不過,但是由於 平台對分散系統的先天支援不足,所以通常那些跨洋越洲的系統大多選上 J2EE 或 .NET 作開發平台(對了,還有很多系統還用上 C/C++,Perl,etc)。

此外,文末提到,PHP 很亂,而且有 “encourage dirty coding” 的成份。為甚麼啊?就是 PHP 太容易上手,太方便,編程的時候會左改右改,最後除錯的時候原碼會亂得令人非常頭痛。此外,不諳編程者面對著 PHP 這類結構鬆散的語言,往往會走歪路,喜歡不斷重用程式碼,例如該用 foreach 卻用 for loop,物件該用繼承卻自己重寫另一個物件,又或為物件加進太多不相關的方法,降低源碼可讀性之餘,還會令系統執行效率變差。(所以我經常說,編程初學者不要學 PHP!)

所以開始要在 PHP 開發上套用 Design Pattern。總括而言,Design 是「讓你知道在甚麼地方該做甚麼」的一套原則。Design Pattern 可以說是大型系統開發的 guideline,使計劃更容易分工(各組員可只負責其中的一部份),也使維護更方便。

ordinary
大部份 PHP 系統模型
經常看見的開源 PHP 系統比如 phpBB,PHPNuke,etc… 也是用上三層模組的 pattern,就是 Template,Code,Library。Template 負責作 Presentation 及 Presentation Logic,而 code 通常則對應著 presentation,執行 business/programatic logic 並將結果填進 template 裏。Library 則提供 Code Layer 常用的函式及類別。WordPress 則是用 2 層:沒有的是中間的 code,在 template 中直接呼叫 Library,Library 則有時會負責 presentation logic,例如顯示連結,列表等等。

但是流程分配上就是有點問題。大家會發現,Code 跟 Library 也許會有相同類型的程式碼,有些地方可能 Library 由 database 拿到資料便把球踢到 Code 去,有些時候則待 Library 把資料整理好,再進行一輪處理才傳球給 Code。很多時候也就是因為這樣,程式碼便不能有效地重用,以致影響系統效能。

MVC
傳統的 MVC 模型
我們也許可以在 PHP 上實行 MVC (Model-View-Controller) 這種模式。Model 是資料儲存的格式定義,View 是處理 Presentation Logic 的部份,Controller 則負責一切資料處理及顯示工作(而 Library 則當是已存在,而內裏也沒有任何相關系統的程式碼)。就拿 CRUD 作例子,Controller 先在 View 接到 Request,接著會從資料庫取得資料(或執行指令),把資料儲存到 Model 中 (Model 大概要像 C struct 吧)。最後另一個 View 則從 Model 裏提取資料。

這其實是 Java 裏常用的 Design Pattern,但是我總覺得有些在 Controller 的程序會在不同的模組會產生重覆,顯得較多餘,也沒有實際得益。所以我就在想,是不是會有一種 MVC/3-Tier 的混種呢?

MVC2
我在 PHP 上的 MVC 模型
這是我的 MVC 模型。Model 現在會負責透過基本的 framework 從資料庫提取資料,在內部整理成 Controller 可以直接提取的物件。拿我以往在 group project 的例子(醫院管理系統),「病人」類別會接受 Controller 的指令,從資料庫提取病人的病歷資料,而 Controller 會透過類別的各種方法處理資料。最後 Controller 會透過 View 顯示給用家看。View 可以是 Template Engine,也可以是 XSL Transformation。

這個模型的好處是 Controller 會全心負責處理得來的資料,更合適於 PHP 的架構。而 View 也可以和資料有更佳的整合,不用再從外部對其設定資料,使用上也會較方便。

6 thoughts on “PHP Design Patterns

  1. 是不是會有一種 MVC/3-Tier 的混種呢?

    這個問題我這幾天剛好也在思考,也把MS的User Interface Process觀念放在一起
    我想了2種情況,
    一種跟版主相似,model 本身是bussiness logic layer,並再包括了DataAcessLayer

    另一種則把bussinessLogicLayer和DataAcessLayer獨立出來,直接由View進行操作
    Controller和Model則負責系統流程控制與狀態儲存

    不知您有什麼看法呢?

  2. 第二種你是指像一些著名的 framework,例如 WASP 使用 MVC 嗎?我覺得如果應用程式規模夠大,物件資料鬆散,這樣做較便利於開發。

    我覺得 view 本身負責的人應該只負責外觀,外來指令他應該一句不理直接傳到後台(即 controller 和 model),分工適當有助團助開發。

  3. 其實我本身沒有接觸過PHP,是在找MVC的資料才發現這裡的^^

    MS的User Interface Process(UIP)也是依MVC架構去做,但它的Model是用於儲存狀態
    因為UIP主要是為了有效處理”執行流程”的架構.一般3-Tier則是處理”邏輯切割”的架構
    例如一個完整會員註冊的功能,依User操作不同,
    而會有幾種階段或畫面的變化,像註冊失敗,授權同意,基本資料填寫,進階資料填寫…
    該怎麼去定義並控制執行它所該跑的各種畫面,則是它要做的

    這對Web程式來說是相當適用的一種做法.所以又看了所謂的3-Tier的概念,
    讓我在思考如何適切的去整合UIP這類MVC架構,再配合著3-Tier
    同上的例子,在註冊的過程中,或者會有些bussiness Logic 像user ID不能重複
    這部分的layer應該安排至Model或Controller?

    要放在UIP裡的model,讓model變得較為複雜,不但負責Process的狀態,也負責呼叫
    bussinessLogicLayer 和 DataAcessLayer class(類似圖二你所用的PHP模型)

    還是model單純負責process的狀態,讓Controller也直接呼叫bussinessLogicLayer和DataAcessLayer的class(類似圖一 傳統的 MVC 模型)

    我本身對這些概念也還沒有很正確的認知,所以希望能藉由討論,得到些新的觀點

  4. 另外也有個小疑惑,那就是若View用XML+XSL來輸出,也為此動作建立了library
    像這種通用的Library,是否也該放到Controller或Model裡?
    還是就在View的地方,直接去呼叫引用?

  5. 如果你說 user ID 不應重覆,這應該在資料儲存(我假設你在用資料庫吧)就該好好定義了,在註冊的 business logic 那部份也只需定義遇到這種情況(以及其他資料庫回傳的問題)該怎麼辦。

    有不少人嚮往微軟 ASP.NET 那種一次過的整合方法,但也有用家批評它把很多重要資訊都收起來,令介面設計員沒彈性(比如說,在元件外沒法存取元件的資訊)。我想還是依你的喜好及工作的性質吧。

    至於view 的那個問題,大部份都可以用現成的程式庫,在 controller 的尾端(或,有些厲害的 framework 甚至內置轉譯器,不用設計員費心)將整套東西變成 view。如果可以大膽一點,你甚至可以在 XML 裏直接加上 XSL 的參考連結,指示用戶端的瀏覽器自行轉譯。

  6. 您的文章有一段時間了,不過還是耐人尋味。確實直到現在您所提出的php上MVC模型也正好就是目前幾乎所有framework都達成的事。

    實感佩服!

Leave a Reply

Your email address will not be published. Required fields are marked *