<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12
        

      C#進階系列——DDD領域驅動設計初探(一):聚合

      前言:又有差不多半個月沒寫點什么了,感覺這樣很對不起自己似的。今天看到一篇博文里面寫道:越是忙人越有時間寫博客。呵呵,似乎有點道理,博主為了證明自己也是忙人,這不就來學習下DDD這么一個聽上去高大上的東西。前面介紹了下MEF和AOP的相關知識,后面打算分享Automapper、倉儲模式、WCF等東西的,可是每次準備動手寫點什么的時候,就被要寫的Demo難住了,比如倉儲模式,使用過它的朋友應該知道,如果你的項目不是按照DDD的架構而引入倉儲的設計,那么會讓它變得很“雞肋”,用不好就會十分痛苦,之前看過這篇 博客園的大牛們,被你們害慘了,Entity Framework從來都不需要去寫Repository設計模式 文章的朋友應該還記得,不止是該文章的作者,很多園友在評論里面也提到了使用它的不爽。博主的項目中也遇到類似的問題,雖然引入了倉儲模式,但是由于沒有架構好,把倉儲的接口和實現統一放在了數據訪問層,導致到后面代碼越寫越難維護,完全感覺不到倉儲帶來的好處。所以博主覺得單純分享倉儲模式很容易使讀者陷入“為了模式而模式”的誤區,再加上最近一段時間在看《領域驅動設計:軟件核心復雜性應對之道.Eric.Eva》這本書和博客園大牛dax.net的DDD系列文章,所以打算分享一個Demo來說明倉儲模式、Automapper、WCF等知識點。

      DDD領域驅動設計初探系列文章:

      一、領域驅動設計基本概念

      根據《領域驅動設計:軟件核心復雜性應對之道.Eric.Eva》書中的觀點,領域模型是軟件項目的公共語言的核心,是領域專家和開發人員共同遵守的通用語言規則,那么在DDD里面,建模的重要性不用多說,所以要想更好理解領域驅動設計,理解領域模型的劃分和建立就變得相當必要。首先來看看DDD里面幾個比較重要的概念:

      1、領域模型:領域模型與數據模型不同,它表述的是領域中各個類及其之間的關系。從領域驅動設計的角度看,數據庫只不過是存儲實體的一個外部機制,是屬于技術層面的東西。數據模型主要用于描述領域模型對象的持久化方式,應該是先有領域模型,才有數據模型,領域模型需要通過某種映射而產生相應的數據模型,從這點來說,最新的EF的Code First就是一個很好的體現。領域模型對象分為實體、值對象和服務。

      2、實體:在領域驅動設計里面,實體是模型中需要區分個體的對象。這里的實體和EntityFramework里面的實體不是一個概念,EF的實體為數據實體,不包含對象的行為。就博主的理解,DDD概念里面的實體就是包括實體數據(EF的Model)和行為的結合體

      3、值對象:通過對象屬性值來識別的對象,它將多個相關屬性組合為一個概念整體。相比實體而言,值對象僅僅是比實體少了一個標識。值對象的設計比較存在爭議,我們暫且記住值對象和實體的區別:(1)實體擁有唯一標識,而值對象沒有;(2)實體允許變化,而值對象不允許變化;(3)判斷兩個實體相等的方法是判斷實體的標識相等,而判斷兩個值對象相等的標準是值對象內部所有屬性值相等;

      4、聚合(以及聚合根):聚合表示一組領域對象(包括實體和值對象),用來表述一個完整的領域概念。而每個聚合都有一個根實體,這個根實體又叫做聚合根。舉個簡單的例子,一個電腦包含硬盤、CPU、內存條等,這一個組合就是一個聚合,而電腦就是這個組合的聚合根。博主覺得關于聚合的劃分學問還是挺大的,需要在實踐中慢慢積累。同一個實體,在不同的聚合中,它可能是聚合根,也可能不是,需要根據實際的業務決定。聚合根是聚合所表述的領域概念的主體,外部對象需要訪問聚合內的實體時,只能通過聚合根進行訪問,而不能直接訪問

      5、領域服務:博主的理解,領域模型主張富領域模式,也就是說把領域邏輯盡量寫在領域實體里面,也就是常說的“充血模式”,而對于業務邏輯,最好是以服務的形式提供。至于領域邏輯和業務邏輯的界定,這個要根據實際情況來定。總之,領域服務是用來處理那些領域模型里面不好定義或者某些可變邏輯的的時候才會用到。待驗證!

      6、工廠、倉儲等概念留在Demo里面說明。

       

      二、領域驅動設計開始之旅

      1、項目分層

      領域驅動設計將軟件系統分為四層:基礎結構層、領域層、應用層和表現層。來看看書中的分層:

      其實在dax.net的系列中這張圖更能說明這種架構

       

      2、項目架構

      博主打算用權限系統的案例說明的領域驅動設計的項目架構。項目嚴格按照表現層、應用層、領域層、基礎設施層來劃分。

      表現層:MVC的Web項目,負責UI呈現。

      應用層:WCF服務,負責協調領域層的調用,向UI層提供需要的接口。

      領域層:定義領域實體和領域邏輯。

      基礎設施層:一些通用的技術,比如AOP、MEF注入、通用的工具類、DTO模型層,這里為什么要有一個DTO模型層,DTO是用于UI展現用的純數據Model,它不包含實體行為,是一種貧血的模型。

      整個項目的調用方式嚴格按照DDD設計來進行,UI層通過WCF服務調用應用層的WCF接口,WCF服務通過倉儲調用領域層里面的接口,基礎設施層貫穿其他各層,在需要的項目中都可以引用基礎設施層里面的內庫。

       

      3、代碼示例

      接下來,博主就根據自己的理解,從零開始使用這種架構寫一個簡單的權限管理系統。由于是領域驅動設計,所以,文章的重點會放在領域層,項目使用了EF的Model First來進行,先設計實體,后生成數據庫。

      3.1 首先來看看表結構

       

      根據博友要求,這里說明一下表之間的映射關系:

      1表示TB_DEPARTMENT表的主鍵DEPARTMENT_ID作為TB_USERS表的外鍵;

      2表示TB_USERS表的主鍵USER_ID作為TB_USERROLE表的外鍵;

      3表示TB_ROLE表的主鍵ROLE_ID作為TB_USERROLE表的外鍵;

      4表示TB_ROLE表的主鍵ROLE_ID作為TB_MENUROLE表的外鍵

      5表示TB_MENU表的主鍵MENU_ID作為TB_MENUROLE表的外鍵

      首先建好對應的表實體,然后根據模型生成數據庫

      將生成的sql語句執行后就可以得到對應的表結構。

       

      3.2 聚合的劃分

      在領域層里面我們新建一個BaseModel,里面有三個類

      這三個類IEntity、IAggregateRoot、AggregateRoot分別定義了實體的接口、聚合根的接口、聚合根的抽象實現類。

          //用作泛型約束,表示繼承自該接口的為領域實體
          public interface IEntity
          {
      
          }
          /// <summary>
          /// 聚合根接口,用作泛型約束,約束領域實體為聚合根,表示實現了該接口的為聚合根實例,由于聚合根也是領域實體的一種,所以也要實現IEntity接口
          /// </summary>
          public interface IAggregateRoot:IEntity
          {
      
          }
         /// <summary>
          /// 聚合根的抽象實現類,定義聚合根的公共屬性和行為
          /// </summary>
          public abstract class AggregateRoot:IAggregateRoot
          {
              
          }

      這里定義接口的作用是定義實體和聚合根的泛型約束,抽象類用來定義聚合根的公共行為,目前為止,這些接口和類里面都是空的,后面會根據項目的需求一步一步往里面加入邏輯。

      在EF里面由edmx文件會生成實體的屬性,前面說到領域模型主張充血模式,所以要在EF的實體model里面加入實體的行為,為了不改變EF生成實體的代碼,我們使用partial類來定義實體的行為。我們來看Model文件夾下面的代碼

          public partial class TB_DEPARTMENT: AggregateRoot
          {
              public override string ToString()
              {
                  return base.ToString();
              }
          }
          public partial class TB_MENU : AggregateRoot
          {
      
          }
          /// <summary>
          /// 由于不會直接操作此表,所以TB_MENUROLE實體不必作為聚合根,只是作為領域實體即可
          /// </summary>
          public partial class TB_MENUROLE:IEntity
          {
          }
          public partial class TB_ROLE:AggregateRoot
          {
          }
          public partial class TB_USERROLE:IEntity
          {
          }
          public partial class TB_USERS:AggregateRoot
          {
          }

      我們看到,這些實體,只有TB_MENUROLE和TB_USERROLE不是聚合根,其他實體都是聚合根。我這里大概劃分為4個聚合:

      聚合1:TB_DEPARTMENT實體

      聚合2:TB_MENU、TB_MENUROLE、TB_ROLE這3個為一個聚合,聚合根是TB_MENU。

      聚合3:TB_USERS、TB_USERROLE、TB_DEPARTMENT、TB_ROLE這4個為一個聚合,聚合根是TB_USERS。

      聚合4:TB_ROLE、TB_USERS、TB_USERROLE、TB_MENUROLE、TB_MENU這5個表為一個聚合,聚合根是TB_ROLE。

      可能這樣分會有一定的問題,后續出現再慢慢糾正。

      到這里,聚合的劃分基本完了,至于為什么要做這么一些約束和設計,因為倉儲只能對聚合根做操作,下篇講倉儲的時候會詳細說明。

      DDD博大精深,文中很多觀點為博主個人理解,可能不太成熟或者有誤,歡迎拍磚~~

       

      posted @ 2015-09-21 09:02  懶得安分  閱讀(68173)  評論(24)    收藏  舉報
      主站蜘蛛池模板: 久久精品亚洲精品国产区| 白嫩日本少妇做爰| 精品一卡2卡三卡4卡乱码精品视频| 亚洲av无码片在线播放| 久久精品国产99国产精品严洲| 国产日韩一区二区三区在线观看| 国产av丝袜旗袍无码网站| 九九热视频在线观看视频| 娇妻玩4p被三个男人伺候| 亚洲精品美女久久久久9999| 国内免费视频成人精品| 强开小雪的嫩苞又嫩又紧| 亚洲欧洲日韩国内精品| 人妻精品无码一区二区三区| 国产福利深夜在线播放| 天堂www在线中文| 免费人成在线观看网站| 国产人成精品一区二区三| 亚洲女人天堂| 邛崃市| 国产精品亚洲一区二区三区| 国产成人一区二区不卡| 看免费真人视频网站| 视频一区二区 国产视频| 国产高清在线男人的天堂| 天堂中文在线资源| 热久久这里只有精品国产| 肥臀浪妇太爽了快点再快点| 202丰满熟女妇大| 国产乱码精品一区二三区| 亚洲精品国产一区二区三| 久久精品丝袜高跟鞋| 亚洲国产码专区在线观看| 国产亚洲情侣一区二区无| 国产精品毛片久久久久久久 | 国产国亚洲洲人成人人专区| 亚洲国产中文字幕在线视频综合| 亚洲欧美日韩高清一区二区三区| 亚洲天堂男人天堂女人天堂| 中文字幕日本一区二区在线观看| 日本韩国一区二区精品|