什麼是代碼結構的組織?
asp.net MVC 5 默認建立出的幾個目錄的標準含義分別以下:html
- Controllers目錄存放MVC模式中的Controler
- Models目錄存放MVC模式中的Model
- Views目錄存放MVC模式中的View
除此外還有Content(存放資源文件,如CSS、圖片)、Scripts(JS腳本文件)等目錄是有標準含義的,有標準含義也就是說有非標準含義,你能夠遵循這些標準含義也能夠定義本身的非標準含義,好比:前端
- asp.net MVC 5 中的Controller無非是繼承system.web.mvc.controller的類而已,你能夠把這個class放在其餘目錄甚至另一個Project中。
- asp.net MVC 5 的Model,常見作法是將它獨立在一個Class Lib類型的Project中
- asp.net MVC 5 的View默認爲Razor引擎,在默認的規則中用Views目錄存放全部的視圖,你能夠經過修改規則來將視圖放在其餘目錄中,或者你用其餘的視圖引擎甚至自定義視圖引擎
這就是我所謂的代碼結構的組織,本質上其實就是MVC模式(在看MVC各類理論的時候注意一個心態:MVC模式自己也是發展變化的,每一個具體的MVC模式的實現(好比asp.net mvc)或多或少都在理論的基礎上作了修改,和理論不能徹底吻合上很正常,我在學習之初太過死板,在這方面糾結了好久時間)在asp.net MVC中的實現,固然遠沒有上面所述的僅僅是幾個目錄的分類這麼簡單,好比Model,若是僅僅是把它獨立在一個Class Lib中的話,仔細想一想,咱們之前不都是這麼作的嗎?web
有個PHP平臺的框架YII所遵循的一些MVC實踐原則我以爲是總結的比較實用的(如下內容是這些實踐內容的核心,部分爲我本身對原文的理解加變化):數據庫
模型(Model)用於表示底層數據結構,常常在整個應用的不一樣部分共享,有些模型在先後臺、API中都會用到,因此一個Model應該遵循的指導原則有:後端
- 包含屬性用於描述特定的數據
- 應該包含業務邏輯,以確保數據可以知足表現的須要
- 應該包含數據操做的代碼,好比數據存儲、檢索
- 確保在不一樣的環境中都可實用,好比B/S環境、控制檯應用或者做爲單純的API
- 不該該出現HTML代碼,負責表現的代碼應該放到view文件中(這點是WebForm時代爲了實現動態響應而常常這麼處理的,而如今咱們有Javascript框架能夠選擇,如JQuery)
在上述指導原則下,可能會寫出很是龐大的Model類(過多數據操做,業務邏輯代碼包含其中)。這種狀況下,建議進一步抽象,提煉出一個基類,包含最通用的功能,而後前端、後端和API在用到時候,將各個子應用才相關的邏輯放到基類繼承出來的子類裏面。微信
視圖(View)主要就用於前端表現的代碼:數據結構
- 包含HTML,以及全部負責表現的代碼,能夠出現.net語法,可是隻用於遍歷數據、格式化數據(在asp.net mvc + JQuery環境中,用JQuery語法來遍歷、格式化、構造Html呈現數據而不用.net語法)
- 不該該包含DB請求
- 僅關於表現,佈局等和頁面呈現有關的業務出如今View中,用戶的請求數據應該由Controller和Model負責處理
- 若是必要,能夠訪問Model和Controller的屬性,不過這是爲了知足表現的須要(asp.net mvc 5 默認建立的view就是直接訪問Model的屬性來呈現數據的,老實說這讓我很Confuse<困惑、糊塗>:MVC模式自己不是爲了解耦的嗎?且不少說法都是視圖都是經過Controller來與Model關聯而不是直接與Model關聯。在asp.net mvc + JQuery環境中,全部視圖經過JQuery訪問Controller來得到返回數據以呈現,也經過JQuery訪問Controller來修改數據)
可使用諸如佈局、部分視圖等框架特性來最大程度重用View的代碼。mvc
控制器(Controller)是將模型、視圖和其餘組件組裝在一塊兒造成一個應用的粘合劑。控制器直接負責處理終端用戶的請求。框架
- 處理終端用戶發出的GET或POST請求,GET用來獲取數據,POST用於修改數據
- 建立模型,並決定一個模型對象的生命週期
- 不該該出現SQL語句,數據庫請求應該放到Model中(在WebForm的實踐作法中,咱們建立了一堆的API、方法、函數,不少也沒有出現SQL語句,在考慮重構時這很讓我抓狂:什麼樣的代碼應該放在Controller中,什麼樣的代碼應該放在Model中,即使有了這個原則以後也是)
- 不該該出現HTML代碼,而應該將其放入到View中
在一個設計良好的MVC應用中,控制器是很是輕量級的,常常只有幾十行代碼的樣子;而Model老是很是複雜並且龐大,包含了全部的用於表現的數據及其操做方法。這是由於由數據結構和業務邏輯組成的模型對每一個應用來講,都是獨特的,須要大量的定製化工做來知足應用的需求;控制器的邏輯常常遵循一個特定的套路,在各個應用中都差很少,所以能夠被框架底層代碼極大程度地簡化(也就是說不是控制器代碼少,而是Web開發框架已經都抽象出來而且都幫你作好了,這也 就是框架的價值和可以實現快速開發的緣由)。asp.net
遵循以上代碼結構組織實踐,能夠有一個基於asp.net mvc 5構建的Web Application,這個project主要處理Controller和View,關於Controller的實踐原則以上四條是遠遠不夠的,Controller的做用是經過調度來達到控制輸出(視圖或數據)的目的(當咱們說這句話時,實際上指的是Controller的Action的實踐原則。另注意:這裏說起的調度和控制兩個詞不是技術術語,就是通俗語言的說法而已),舉例來講:
- MVCStore示例將身份驗證做爲一個AuthenticationController,此控制器內不一樣的方法(Action)可實現不一樣的身份登陸(想象一下:AD登陸、Form登陸,這是企業內部應用常見的兩種身份驗證方式,我最近參與的一個對公網的系統還涉及到與微信登陸的集成),代振軍有篇博文對MVCStore的這種作法作了不錯的分析,由此我總結的一個Controller開發原則(出發目的是用來應對讓我抓狂的"到底哪些代碼放入Controller,哪些代碼放入Model"的困惑):業務流程放入Controller中,而業務流程中的具體業務規則放入Model中(這是符合SOA構的思想的---好大的帽子吧,能夠閱讀上面提到的代振軍的那篇博文)。基於這個原則,不論是哪個登陸方法,其調度控制的業務流程都應該是這樣:
-
- 接收客戶端發出的身份信息(經過調度實現):Oxite示例的作法是經過調度,而MVCStore是直接在Action中Request.Form獲取,缺點在於會讓Action中的代碼增加過快
- 判斷此身份是否合法(經過調度實現):MVCStore中體現的很明顯,在Model中建立有對應AuthenticationController的AuthenticationService,經過對此Service的調用來完成此業務流程步驟,而具體的業務規則就放在了Model中(根據此原則可將Model劃分爲兩部分:一是數據模型實體部分,二是業務邏輯部分,以下圖所示)
- 若是身份合法則承認(這是控制):"若是合法"是業務流程,而"承認"的具體內容(主要指的是對登陸身份的保持)則是業務規則,承認後固然就是控制輸出視圖了(這部分代碼我也把它併入到業務流程中)
- 若是不合法則不承認(這也是控制):"若是不合法"是業務流程,而"不承認"通常不包含什麼業務規則,直接開始控制視圖輸出
對於Controller在實際項目中須要當心時刻留心要始終保持Controller與View的輕快,當心隨着業務複雜度提升而產生的困惑:有不少代碼你不知道把它放哪,就只好把它放到控制層,最後發如今控制層中塞了太多的代碼。有個叫Irwin的人提出了MOVE模式(這裏有個簡單的翻譯版本)做爲MVC模式的改進,其出發點也基於此,在這個MOVE模式中MOV從概念定義能夠判斷出就是對應了MVC(Operations對應着Controller),增長的一個Events彷佛是用來使視圖和模型直接關聯,我猜測做者多是在開發Controller時不少的Action須要根據複雜業務邏輯對視圖產生影響,於是寫了不少此類的代碼在Controller中,當心的對Controller和View進行結構化組織,就可在很大程度上避免這種狀況。
接下來針對我手上的系統的重構作些實際的思考來應用以上這些原則。