創建應用程序框架,首先要考慮的問題是,你準備採用哪一種分層架構,而後根據應用程序框架的邏輯層次來肯定須要建立的VS解決方案和程序集。程序員
若是項目很小,需求很簡單,時間異常緊迫,且你手上沒有任何積累,那麼,單層架構將是首選,最簡單的單層架構以下圖所示(爲了集中你的注意力,我把不相關的文件都刪除了)。數據庫
單層架構的主要優點是代碼火力集中,幹活直截了當,不像多層架構那樣拐彎抹角,每一個操做都須要層層傳遞。對於上圖的User.aspx,全部相關代碼都直接寫到aspx頁面或後置代碼中,包括界面上的控件操做,業務操做和數據庫操做。編程
另外,單層架構比較符合初學者的習慣,初學者對編程語法和.Net 基本API尚且不熟,哪會過多考慮代碼結構上的問題。c#
使用單層架構,主要依賴於.Net強大的控件體系,拖控件,配屬性,寫事件處理函數,是單層架構下編程的真實寫照,這也是.Net程序員在外人眼裏一直保持的印象。架構
對於主要包含CRUD操做的小項目,單層架構能夠工做得很好,但若是項目有一些比較複雜的業務邏輯,好比訂單流程 ,會發現代碼很快會變成一團爛泥,失去方向。業務邏輯與表現層代碼混雜在一塊兒,其結果是界面上的任何修改均可能致使業務邏輯失敗。框架
爲了提高代碼複用能力,能夠把每一個頁面都須要處理的操做,好比權限檢查,日誌跟蹤,全局錯誤處理等,提取到一個PageBase的基類中,放到Base文件夾,另外能夠建立一個Helpers文件夾來放置公共操做類。函數
單層架構爲下一個相似項目所做出的積累微乎其微,業務上大部分代碼會被拋棄,有多是技術的變化,好比以前使用Web Form,如今須要使用Win Form, 因爲業務代碼和表現層代碼高度耦合,很明顯沒法再使用以前的代碼。哪怕技術沒有變化,要在以前開發的爛泥中新增和修改功能,將是舉步維艱。有些邏輯上看似很是簡單的需求,當你實際動手時,發現並非這麼簡單,修改一處會牽動更多地方,所謂牽一髮而動全身。學習
對於技術上的積累,主要經過複製文件的方式供下一個項目使用。一個更好的辦法是把技術積累單獨提取到一個.Net類庫中,以下圖所示。spa
這樣就實現了業務與技術的分離,當下一個項目到來時,只須要把Util.dll引入便可。設計
爲了挖掘單層架構的極限能力,須要開發一套強大的自定義控件,把數據庫操做、驗證操做、權限操做等內容所有封裝進去,在控件上設置數據庫列名,不須要通過DataTable或實體對象,直接生成Sql發送到數據庫。若是配上代碼生成器,開發簡單項目的速度驚人。
對於單層架構,不論你怎麼想盡辦法,它對複雜項目都無能爲力,使用單層架構來開發業務邏輯複雜的項目,最終獲得的就是一團亂麻。提高代碼質量能夠在必定程度上緩解這些問題,但要從根本上解決,還必須向多層架構靠攏。
從上面分析能夠看到,單層架構不能勝任複雜業務領域,並且複用能力十分有限。因爲應用程序框架的目標在於提高技術和業務兩方面的代碼複用,因此單層架構不是一個合適的選擇。
信息系統從根本上來講,是對數據庫的操做,而且須要提供一套操做界面。若是按相關職責劃分到不一樣的層中,會有助於項目的管理和代碼清晰度的提高。分層架構是SRP(單一職責原則)的一個應用,把高度相關的東西彙集在一塊兒,把各個層用接口鏈接起來,這樣就能獲得一個高內聚、低耦合的設計。
目前.Net程序員廣泛使用的分層架構是傳統三層架構,架構示意圖以下。
傳統三層架構的核心在業務邏輯層,表現層會把數據放到實體中,做爲參數傳遞給業務邏輯層,業務邏輯層會使用過程式的代碼來處理業務,若是須要訪問數據庫,則調用數據訪問層。
傳統三層架構把表現、業務和數據訪問分離到不一樣的層中,當切換表現層技術,或更換數據庫時,只須要替換相關的組件便可,不需所有重寫。
天下沒有白吃的午飯,在得到清晰度、重用性,擴展性等好處的同時,也帶來了一些問題,主要是直觀性下降,複雜度提高,工做量增大。在單層架構下實現一個功能,可能只須要一個方法就能徹底搞定,理解起來也比較容易,進入三層架構之後,每一個操做都被分離打散到不一樣的層裏,每一個層有一部分代碼,須要在幾個層裏來回跳動,才能窺其全貌,因此直觀性有所下降。另外,任何一個操做,須要在多個地方編寫,工做量倍增。
若是嚴格按照三層架構的要求來編寫代碼,表現層儘可能不要有業務操做,更不能有數據操做,業務層只管邏輯,這樣能夠得到比較高的可維護性。可是不少初學者對架構職責沒有認識,他們會隨便找個地方放置代碼,這個地方多半是表現層,這樣一來,不只代碼質量不好,架構還很複雜,就得不償失了。
傳統三層架構特別具備爭議的地方是Model實體層。這些實體從表面上看,好像是業務對象,好比客戶Customer,仔細觀察這個類,發現裏面全是屬性,沒有方法,它用來充當數據容器,在各層之間傳遞數據。
有些人一直認爲本身是在進行面向對象開發,畢竟c#是個面向對象的語言,又使用了三層架構,還建立了實體,不就是面向對象開發嗎?實際上傳統三層架構仍是面向過程的,只是披上了面向對象的外衣。還有些人對是否面向對象開發不屑一顧,「管它這些理論幹啥,咱只搞實際的」,沒錯,通常程序員確實能夠無論這些道理,但若是要追求更高的封裝性、複用性,可維護性,就必須向面向對象深刻。
面向對象的核心是根據概念建模,好比客戶,雖然傳統三層架構在Model層中確實建立了一個Customer類,可是Model層在三層架構中屬於輔助地位,是一個無關緊要的東西,若是把Customer類換成DataTable也同樣可行。
Model中的實體之因此用處不大,是由於違反了對象的特徵,真正的對象是數據與操做的集合。有人把單純的數據對象稱爲貧血模型,把具備數據和豐富操做的對象稱爲充血模型,意指只有屬性的數據對象先天不足,養分不良,智商低,只會吃飯(數據),不會幹活。
爲什麼對象必定要把數據和操做放到一塊兒,才能發揮威力?由於這些數據與數據上的操做老是息息相關,且同時變化。把數據和操做封裝到一塊兒,能夠爲操做提供惟一訪問點,主要好處是對操做集中管理,消除代碼冗餘。當數據發生變化時,相關操做多半須要同時修改,因爲代碼沒有冗餘副本,且在對象內部完成修改,對外界甚至不產生影響,可維護性大大提高。
把業務對象的數據和操做分離之後,第一個影響是業務邏輯散亂,難以管理。因爲操做沒有一個統一的位置,因此沒有人知道這些操做究竟位於何處?可能在業務層,也可能在表現層,還有可能在存儲過程裏。哪怕嚴格按照三層架構職責編寫代碼,全部業務邏輯都在業務層中,但可能不少個類都使用了這個實體,究竟某個操做在哪一個類裏?特別是在團隊做戰時,這個問題更加明顯,若是他不能很容易找到他要的方法,那麼他就會本身添加一個,從而致使冗餘。第二個影響就是致使明顯的代碼冗餘,而代碼冗餘是可維護性的天敵。每當數據發生變化或發現Bug,須要找到全部操做代碼的副本進行修改,若是有遺漏就會埋下地雷。
固然,CRUD簡單操做不在以上討論範圍,上面主要指業務邏輯受數據的影響程度。
能夠看到,三層架構相比單層架構來講,已經有至關進步,但它還有一些缺陷能夠改進,若是把Model實體層和BLL業務邏輯層合併,就能夠獲得面向對象模型,在《企業應用架構模式》中稱爲領域模型。不過Eric Evans在《領域驅動設計》中以更具體的方式指導如何使用面向對象進行開發。
應該採用充血模型(面向對象)、仍是貧血模型(面向過程)?要不要使用ORM,要不要使用DDD(領域驅動設計)?這些問題老是爭論不休。不過個人建議是,若是你還準備在.Net界多混幾年,不如提前進行,由於這是大勢所趨,就好像單層架構最終被三層架構所取代。另外,領域驅動設計若是用得很差,充其量也就和三層架構差很少,因此你不須要有任何顧忌。
本系列文章將採用Entity Framework和DDD分層架構演示應用程序框架的建設,因此本文暫不對DDD進行介紹。
本文對分層架構的演化過程進行了簡單介紹,爲你選擇適合本身的架構提供了一些參考,最後的結論是,不管你是否願意,因爲軟件行業的發展,特別是微軟技術的推進,你始終會走上面向對象之路,與其被動挨打,不如主動學習。
有些朋友發現這個實戰系列名不符實,全是廢話,一句代碼都沒有,還有些朋友喜歡四處蒐集源碼,坐等乾貨。我想說的是,這個實戰系列畢竟是介紹架構和框架的,若是你只拿到幾行代碼,沒有真正搞懂如何爲你的項目創建應用程序框架,代碼沒法造成一個體繫結構,仍是一團亂麻,那又有什麼用。另外,我所提供的代碼也是四處蒐集整理,沒有什麼特別,你若是須要源碼,直接百度就會多如牛毛,但我但願你能搞懂每一個細節, 這樣更有幫助。
.Net應用程序框架交流QQ羣: 386092459,歡迎有興趣的朋友加入討論。