最近負責一個項目,用了 Yii Framework 的 MVC 框架,剛開始自以為結構很穩健。
但是隨著對業務邏輯理解的深入,才開始意識到問題的嚴重性。
我錯誤地理解了 MVC 中的 Controller,想當然地根據以往的經驗,把所有的業務邏輯都放在 Controller 的 action 中去實現。
於是,每個 Controller 的程式碼都上千行,越來越臃腫。
最後,我下定決心重構程式碼,起源是一個對外開放 API 介面的需求。
依照現在的架構,程式碼基本上無法重複使用,我需要把很多功能再重複寫一遍,這實在是無法接受。
物件導向程式不只是課本上的名詞啊!
真正開始實踐才發現,要有物件導向意識,有全局觀,是多麼難得的一件事情。
MVC設計原則
#1、到底什麼是MVC
##模型-視圖-控制器(MVC)是一種設計框架(設計模式)。 MVC 的目標是將業務邏輯從使用者介面的考量中分開。 這樣,開發者就可以更容易地改變每一部分而不會影響其他。 在 MVC 中,Model 代表資料和業務規則;View 包含了使用者介面元素,例如文本,表單等;Controller 則管理模型和視圖中的通訊。 MVC 在各種程式語言中都有實現,例如J2EE 應用開發中,View 可能由jsp 實作;Controller 是servlet,現在一般用Struts 實作;Model 則是由一個實體Bean 來實作。2、我遇到了什麼問題
Yii Framework 是一個流行的 PHP 框架,它藉鑒了 Ruby on Rails 的 ActiveRecord(AR) 概念。 資料庫中的每一個 table 都可以用 AR 類別來方便地進行增刪改查操作。 它把 AR 當做 Model,並推薦放在一個名為 models 的目錄下面。 於是,我在自動產生表對應的 AR 之後,便望文生義想當然地認為已經擁有了 Model 層。 其實,AR只不過是 DAO (資料存取層),並不是 Model 層。 我們的業務幾乎全放在了Controller 裡:對使用者提交上來的表單進行各種邏輯判斷,進行計算,實例化AR 對資料進行儲存…#因為一個Controller中會有多個action,每個action 都有這樣的業務處理。 最後,我發現我的 Controller 程式碼已經超過了 1000 行。 突然有一天,leader 說,我們這個系統要開放 API 給現有的舊系統調用,要給第三方介面。 第三方只是要給定一個參數,本系統給出個結果值而已,這其中的業務處理它是不關心的。 壞就壞在這裡,Controller 已經實現了那些業務,但它是接受表單提交的,怎麼能夠也接受 SOAP 的 xml 文件呢? Controller 和套套一樣,應該越薄越好。 它的職責應該只是接受使用者的輸入,然後立刻轉發給別的類別來處理。 這樣 Controller 只負責提供不同的接口,我們才能算是將業務邏輯分離出去,而分離出去的業務也很容易進行重用。 分離出來的這部分業務由誰來處理呢?答案應該是 Model。3、View的職責
View部分比較明確,就是負責顯示。 一切與顯示介面無關的東西,都不應該出現在view裡面。 因此,View 中一般不應該出現複雜的判斷語句,以及複雜的運算過程。 可以有簡單的迴圈語句、格式化語句。例如,部落格首頁的文字清單就是一種循環。 對於PHP的Web應用而言,HTML是View中的主要內容。 View應該從不呼叫Model的寫入方法。 也就是說,View只從Model讀取數據,但不改寫Model。 所以我們說,View和Model是老死不相往來的。 而且,View不直接存取$_GET和$_POST,應該由Controller傳遞給View。 此外,View一般沒有任何準備資料處理的內容,如查詢資料庫等。 這些一般是放在Controller裡面,並以變數的形式傳給視圖。 也就是說,視圖裡面要用到的數據,就是一個變數。4、Model的職責
對Model而言,最主要就是保存和輸出資訊。 例如,Post類別必然有一個用來保存部落格文章標題的title屬性,必然有一個刪除的操作,這都是Model的內容。 資料、行為、方法是Model的主要內容。 實際工作中,Model是MVC中程式碼量最大。 Model是邏輯最複雜的地方,因為所應用的業務邏輯也要在這裡表示。 注意將Model與Controller區分開。 Model是處理業務方面的邏輯,Controller只是簡單的協調Model和View之間的關係。只要是跟業務有關的,就該放在Model裡面。
資料校驗、public常數和變量,都應該放在model層,
也就是說,有可能被重複使用的屬性或方法,都應該放在model層,一次定義,到處使用。
Model不應該存取request、session以及其他環境數據,這些應該由Controller注入。
好的設計,應該是胖Model,瘦Controller。
5、Controller的職責
對於Controller,主要是回應使用者要求,決定使用什麼視圖,需要準備什麼資料用來顯示。
因此,對於request的存取程式碼,應該放在Controller裡面,例如$_GET、$_POST等。
Controller應該僅限於獲取用戶請求數據,不應該對數據有任何操作或預處理,這應該放在 Model 裡面。
對於資料的寫入操作,要呼叫Model類別的方法完成。
對於使用者請求的回應,要呼叫視圖渲染。
此外,一般不要有HTML程式碼等其他表現層的東西,這應該是屬於View的內容。
6、啟示
Yii Framework 的官方文件中有這麼一段:
In a well-designed MVC application, controllers are often very thin, containing probably only a few dozen lines of code; while models are very fat, containing most of the code responsible for representing and manipulating the data.
簡言之,Rich Model is Better。
以上是MVC架構的職責分割原則的詳細內容。更多資訊請關注PHP中文網其他相關文章!