天天看點

前端控制器是邪惡的麼?

更新:鑒于我最初的行文方式有讓人誤解之嫌,是以我對措辭做了适當的删減,使之更簡明扼要。

所謂前端控制器(FrontController),是指一個請求運作的公共起點,并且在這裡決定下一步執行什麼。

多數PHP架構裡都實作了它。統一進行權限限制,會話管理等等公共操作,并且進而通過一個類似路由的裝置,把請求委派給一個具體的指令對象來執行。實作方 式上,前端控制器通常是以一個名為index.php的檔案為載體,通過重寫規則把請求都轉發到這個檔案上,如CakePHP在Apache上的設定:

<IfModule mod_rewrite.c>

    RewriteEngine On

    RewriteCond %{REQUEST_FILENAME} !-d

    RewriteCond %{REQUEST_FILENAME} !-f

    RewriteRule ^(.*)$ index.php?url=$1 [QSA,L]

</IfModule>

不過老話說,物極必反,随着前端控制器使用的泛濫,越來越多的人開始質疑PHP開發是否有必要使用前端控制器。這裡以PHP之父Rasmus Lerdorf的影響最大,早些時候,他在Simple is Hard裡陳述了如果想開發出有擴充性的Web應用,必須保證架構是Share-nothing Architecture:

Share-nothing Architecture

    * Like HTTP, each request is distinct

    * Shared data is pushed down to the data-store layer

    * Avoid front controllers

在Rasmus Lerdorf看來,想要讓一個網站具有良好的擴充性其實是非常簡單的,隻需将網站應用分成若幹個獨立小程式,前端透過API提供服務,後端是應用程式引 擎,這樣做自然會有擴充性。因為應用的每一個部分,都有不同等級的使用方式,需要有不同的擴充程度,需要不同的機制來處理。以開發雅虎電子郵件而言,是要 開發一個位址服務程式、一個讀信服務、一個送信服務,而送信程式完全和讀信程式無關。以雅虎的規模而言,需要讓這些工作完全分離,才有擴充性。這裡的關鍵 是你必須建立分離、子產品化的獨立端點,而不是全部放在同一個大籃子裡。大多數現今開發架構,都使用了前端控制器,每一次浏覽器送出請求時,就會調用這個前 端控制器,再由前端控制器來分辨,使用者想要執行哪一支程式。這樣做,一點意義都沒有。在浏覽器層次,程式完全能知道使用者想要做什麼事情,例如使用者隻是 要讀信,程式就不用再把需求送到伺服器,讓伺服器判斷使用者要讀信還是送信。将這類決策工作拉出浏覽器,由伺服器處理,就會浪費大量伺服器資源,來處理那 些對使用者沒有實際功用的工作。

前端控制器是邪惡的麼?

總結:

首先,前端控制器裡存在一個路由轉發的過程,這個過程是在服務端完成的,不管是什麼請求都要經由前端控制再完成路由轉發,這個過程很可能會引起性能問題。 如果抛棄了前端控制器的做法,轉而使用頁面控制器的實作方式,那麼服務端就不必再存在路由轉發的過程,因為在把頁面渲染到浏覽器上的時候,自然而然就完成 了路由的設定,不同的動作對應着不同的URL。功能實作則完全由頁面控制器來實作。如果某個動作引起了性能的瓶頸,那麼我們隻要針對這個動作對應的URL 增加更多的伺服器就可以完成擴充。

另外,傳統的MVC理論裡,強調代碼邏輯上的分離,但并未就實體分離做出描述,Rasmus Lerdorf在這方面做出了有益的補充,按Rasmus Lerdorf的引申想法,M和V是分别位于不同伺服器的,V通過WebService調用M上的資料。

請牢記Rasmus Lerdorf的教誨。

參考連結: Rasmus 校園講座台大場:Simple is Hard

繼續閱讀