好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

DDD的模型选择

DDD的模型选择

关于DDD的模型选择,应该是在05年的时候,从充血模型转换到贫血模型,那时候的资料太少,自己是通过项目体会出来的,架构经过这些年的升级改进,从模型方面这一块基本应该是不再有大的变化了。至少这些年的这么多项目,用起来非常顺手,从分析、设计、编码一路映射下来,现在又加个工作流、静态图,也只是对框架的完善。

我说说自己的理解。

//---------------------------------------

说DDD,先上标准的图和解释:

      1. 用户界面/展现层 
  负责向用户展现信息以及解释用户命令。更细的方面来讲就是: 
  a) 请求应用层以获取用户所需要展现的数据; 
  b) 发送命令给应用层要求其执行某个用户命令。
 
  2. 应用层 
  很薄的一层,定义软件要完成的所有任务。对外为展现层提供各种应用功能(包括查询或命令),对内调用领域层(领域对象或领域服务)完成各种业务逻辑,应用层不包含业务逻辑。
 
  3. 领域层 
  负责表达业务概念,业务状态信息以及业务规则,领域模型处于这一层,是业务软件的核心。
 
  4. 基础设施层 
  本层为其他层提供通用的技术能力;提供了层间的通信;为领域层实现持久化机制;总之,基础设施层可以通过架构和框架来支持其他层的技术需求。

//--------------------------------------

1、界面层:就是获取显示数据,把数据发送到服务端,并告诉服务端这些数据干什么用。

2、应用层?我有些不理解:作用是什么呢?存在价值是什么?如果用的是充血模型,如果对客户端通信的话,可以在此解耦,以值类型实现远程通信,包括SOA的支持等。如果想走SOA,充血模型应该是行不通的,特别是如果用的ORM后,可能有的是动态类,序列化与反序列化,都是一个大问题。如果是贫血模型,这一层好像是多余的,或者也有是为了SOA或者其他之类的服务,或者技术难题,这是可以理解的。如果是作为流程编排层,那么与应用层的定义就有差异了。在我的框架里面,就不存在应用层,但是存在流程编排层,但不是作为独立的层次存在,从有篇随笔上已经有表现了。

3、领域层:我想可以理解为业务逻辑层。如果说一定要纯粹的OO,一个类一定要有属性、方法才是完整意义上的OO,那好像有些太本本主义了。重要是要好用,能够方便的实现问题的解决。   如果以Service对外公开服务也未偿不可,或者说方法,方法分几4种,1是public对客户端公开的粗粒度的服务,相当于SOA用到的服务;2是internal对DLL公开的内部可以访问的服务,对模型内有效;3是protected 对继承的对象有效;4是private只对内部有效。组合起来,应该能够实现领域层的要求,不足就是本来一个对象一个类可以实现的东东,硬生生把人分家。有人提到公开了增删改的操作,没有必要公开,多余了,其实不就是4个操作嘛,也差不多哪里去了。没有十全十美的方法,有缺点,也有优点,可以直接对客户端提供服务,统一模型。

4、基础设施层:可能更多的是ORM,持久化之类的吧。当然会有一些通用服务等等。

还是一句话,没有十全十美的。不同的理解会造就不同的模型,产生可能相当大的差异。

上一段代码,看看我的理解:

1、实体对象。  这是一个主从结构 ,从下面的代码上面已经能够明细看的出来了     

 Order

 namespace   eWMS.Data
{
      using   System;
      using   System.Collections.Generic;
      using   EES.Common;
      using   EES.Common.Data;
      using   EES.Common.Model;
      using   System.ComponentModel;

    
    
    [EESData(  "  移库单  "  )]
    [Contract()]
      public   class   MOVHeader : EESObject
    {
        
          #region  字段属性
         private   String id;
        
          private   String corpCode;
        
          private   String code;
        
          private   String moc;
        
          private   String orderStatus;
        
            
          #endregion 
        
         #region  映射属性
         ///   <summary> 
         ///   Id
          ///   </summary> 
         public   virtual   String Id
        {
              get  
            {
                  return   id;
            }
              set  
            {
                  if  ((id !=  value))
                {
                      this .OnPropertyChanging( "  Id  "  );
                    id  =  value;
                      this .OnPropertyChanged( "  Id  "  );
                }
            }
        }
        
          ///   <summary> 
         ///   企业编码
          ///   </summary> 
         public   virtual   String CorpCode
        {
              get  
            {
                  return   corpCode;
            }
              set  
            {
                  if  ((corpCode !=  value))
                {
                      this .OnPropertyChanging( "  CorpCode  "  );
                    corpCode  =  value;
                      this .OnPropertyChanged( "  CorpCode  "  );
                }
            }
        }
        
          ///   <summary> 
         ///   单号
          ///   </summary> 
         [Key()]
          public   virtual   String Code
        {
              get  
            {
                  return   code;
            }
              set  
            {
                  if  ((code !=  value))
                {
                      this .OnPropertyChanging( "  Code  "  );
                    code  =  value;
                      this .OnPropertyChanged( "  Code  "  );
                }
            }
        }
        
          ///   <summary> 
         ///   纸面单据号
          ///   </summary> 
         public   virtual   String Moc
        {
              get  
            {
                  return   moc;
            }
              set  
            {
                  if  ((moc !=  value))
                {
                      this .OnPropertyChanging( "  Moc  "  );
                    moc  =  value;
                      this .OnPropertyChanged( "  Moc  "  );
                }
            }
        }
        
          ///   <summary> 
         ///   单据状态
          ///   </summary> 
         public   virtual   String OrderStatus
        {
              get  
            {
                  return   orderStatus;
            }
              set  
            {
                  if  ((orderStatus !=  value))
                {
                      this .OnPropertyChanging( "  OrderStatus  "  );
                    orderStatus  =  value;
                      this .OnPropertyChanged( "  OrderStatus  "  );
                }
            }
        }
      
          #endregion 

         private  DataCollection<MOVDetail>  detailCollection;
          public   virtual  DataCollection<MOVDetail>  DetailCollection
        {
              get  {  return   detailCollection; }
              set  { detailCollection =  value; }
        }

          private  DataCollection<MOVData>  movDataCollection;
          public   virtual  DataCollection<MOVData>  MOVDataCollection
        {
              get  {  return   movDataCollection; }
              set  { movDataCollection =  value; }
        }
    }
} 

DTL 

 1   namespace   eWMS.Data
    2   {
    3       using   System;
    4       using   System.Collections.Generic;
    5       using   EES.Common;
    6       using   EES.Common.Data;
    7       using   EES.Common.Model;
    8       using   System.ComponentModel;
    9      
  10      
  11      [EESData( "  单明细  "  )]
   12       [Contract()]
   13       public   class   MOVDetail : EESObject
   14       {
   15          
  16           #region  字段属性
  17           private   String id;
   18          
  19           private   String corpCode;
   20          
  21           private   String ordCode;
   22          
  23           private   Int32 rowNo;
   24          
  25           private   String rowStatus;
   26          
  27         
  28           #endregion 
  29          
  30           #region  映射属性
  31           ///   <summary> 
  32           ///   Id
   33           ///   </summary> 
  34           [Key()]
   35           public   virtual   String Id
   36           {
   37               get 
  38               {
   39                   return   id;
   40               }
   41               set 
  42               {
   43                   if  ((id !=  value))
   44                   {
   45                       this .OnPropertyChanging( "  Id  "  );
   46                      id =  value;
   47                       this .OnPropertyChanged( "  Id  "  );
   48                   }
   49               }
   50           }
   51          
  52           ///   <summary> 
  53           ///   公司编码
   54           ///   </summary> 
  55           public   virtual   String CorpCode
   56           {
   57               get 
  58               {
   59                   return   corpCode;
   60               }
   61               set 
  62               {
   63                   if  ((corpCode !=  value))
   64                   {
   65                       this .OnPropertyChanging( "  CorpCode  "  );
   66                      corpCode =  value;
   67                       this .OnPropertyChanged( "  CorpCode  "  );
   68                   }
   69               }
   70           }
   71          
  72           ///   <summary> 
  73           ///   到货单号
   74           ///   </summary> 
  75           public   virtual   String OrdCode
   76           {
   77               get 
  78               {
   79                   return   ordCode;
   80               }
   81               set 
  82               {
   83                   if  ((ordCode !=  value))
   84                   {
   85                       this .OnPropertyChanging( "  OrdCode  "  );
   86                      ordCode =  value;
   87                       this .OnPropertyChanged( "  OrdCode  "  );
   88                   }
   89               }
   90           }
   91          
  92           ///   <summary> 
  93           ///   行号
   94           ///   </summary> 
  95           public   virtual   Int32 RowNo
   96           {
   97               get 
  98               {
   99                   return   rowNo;
  100               }
  101               set 
 102               {
  103                   if  ((rowNo !=  value))
  104                   {
  105                       this .OnPropertyChanging( "  RowNo  "  );
  106                      rowNo =  value;
  107                       this .OnPropertyChanged( "  RowNo  "  );
  108                   }
  109               }
  110           }
  111          
 112           ///   <summary> 
 113           ///   行状态
  114           ///   </summary> 
 115           public   virtual   String RowStatus
  116           {
  117               get 
 118               {
  119                   return   rowStatus;
  120               }
  121               set 
 122               {
  123                   if  ((rowStatus !=  value))
  124                   {
  125                       this .OnPropertyChanging( "  RowStatus  "  );
  126                      rowStatus =  value;
  127                       this .OnPropertyChanged( "  RowStatus  "  );
  128                   }
  129               }
  130           }
  131          
 132        
 133           #endregion 
 134       }
  135  }

DATA

 namespace   eWMS.Data
{
      using   System;
      using   System.Collections.Generic;
      using   EES.Common;
      using   EES.Common.Data;
      using   EES.Common.Model;
      using   System.ComponentModel;
    
    
    [EESData(  "  编码  "  )]
    [Contract()]
      public   class   MOVData : EESObject
    {
        
          #region  字段属性
         private   String id;
        
          private   String ordCode;
        
          private   String detailId;
        
          private   String productCode;
        
          private   String productSKU;
        
          private   String code;
        
       
          #endregion 
        
         #region  映射属性
         ///   <summary> 
         ///   Id
          ///   </summary> 
         [Key()]
          public   virtual   String Id
        {
              get  
            {
                  return   id;
            }
              set  
            {
                  if  ((id !=  value))
                {
                      this .OnPropertyChanging( "  Id  "  );
                    id  =  value;
                      this .OnPropertyChanged( "  Id  "  );
                }
            }
        }
        
          ///   <summary> 
         ///   单号
          ///   </summary> 
         public   virtual   String OrdCode
        {
              get  
            {
                  return   ordCode;
            }
              set  
            {
                  if  ((ordCode !=  value))
                {
                      this .OnPropertyChanging( "  OrdCode  "  );
                    ordCode  =  value;
                      this .OnPropertyChanged( "  OrdCode  "  );
                }
            }
        }
        
          ///   <summary> 
         ///   明细Id
          ///   </summary> 
         public   virtual   String DetailId
        {
              get  
            {
                  return   detailId;
            }
              set  
            {
                  if  ((detailId !=  value))
                {
                      this .OnPropertyChanging( "  DetailId  "  );
                    detailId  =  value;
                      this .OnPropertyChanged( "  DetailId  "  );
                }
            }
        }
        
          ///   <summary> 
         ///   产品编码
          ///   </summary> 
         public   virtual   String ProductCode
        {
              get  
            {
                  return   productCode;
            }
              set  
            {
                  if  ((productCode !=  value))
                {
                      this .OnPropertyChanging( "  ProductCode  "  );
                    productCode  =  value;
                      this .OnPropertyChanged( "  ProductCode  "  );
                }
            }
        }
        
          ///   <summary> 
         ///   产品SKU
          ///   </summary> 
         public   virtual   String ProductSKU
        {
              get  
            {
                  return   productSKU;
            }
              set  
            {
                  if  ((productSKU !=  value))
                {
                      this .OnPropertyChanging( "  ProductSKU  "  );
                    productSKU  =  value;
                      this .OnPropertyChanged( "  ProductSKU  "  );
                }
            }
        }
        
          ///   <summary> 
         ///   追踪码
          ///   </summary> 
         public   virtual   String Code
        {
              get  
            {
                  return   code;
            }
              set  
            {
                  if  ((code !=  value))
                {
                      this .OnPropertyChanging( "  Code  "  );
                    code  =  value;
                      this .OnPropertyChanged( "  Code  "  );
                }
            }
        }
      
          #endregion  
    }
} 

2、服务:或者说方法。

服务/方法

 namespace   eWMS.Service
{
      using   System;
      using   System.Collections.Generic;
      using   EES.Common;
      using   EES.Common.Data;
      using   EES.Common.Model;
      using   EES.Common.Query;
      using   EES.Common.Injectors.Handlers;
      using   eWMS.Data;
      using   T.BC.Service;
    
    
    [EESBO(  "  移库单服务  "  )]
      public   class  MOVHeaderService : MOVHeaderImp<MOVHeader> 
    {
        
        [Operation(ScopeOption.Required)]
      public   virtual   void   WriteTrans(MOVHeader h)
        {
            trans.Id  =  GUID.NewGuid();
            trans.OrderCode  =  h.Code;
            trans.OrderType  =  typeof  (MOVHeader).ToString();
            trans.ProductCode  =  detail.ProductCode;
            trans.ProductSKU  =  detail.ProductSKU;
            trans.BatchCode  =  detail.BatchCode;
            trans.StoreCode  =  detail.StoreCode;
            trans.StoreZone  =  detail.StoreZone;
            trans.Qty  =  0  ;
            trans.UOM  =  detail.UOM;
            trans.RowNo  =  detail.RowNo;
            trans.PackCode  =  detail.PackCode;
            getProxyTrans().Save(trans);
        }


          protected   override   void   OnSaved(MOVHeader t)
        {
            getProxyMovDetail().SaveAll(t.DetailCollection);
            getProxyMovData().SaveAll(t.MOVDataCollection);
              base  .OnSaved(t);
        }


          private   MOVDetailService proxyMovDetail;
          private   MOVDetailService getProxyMovDetail()
        {
              if  (proxyMovDetail ==  null  )
                proxyMovDetail  = Factory.getProxy<MOVDetailService> ();
              return   proxyMovDetail;
        }
          private   MOVDataService proxyMovData;
          private   MOVDataService getProxyMovData()
        {
              if  (proxyMovData ==  null  )
                proxyMovData  = Factory.getProxy<MOVDataService> ();
              return   proxyMovData;
        }
          private   OrderTransactionService proxyTrans;
          private   OrderTransactionService getProxyTrans()
        {
              if  (proxyTrans ==  null  )
                proxyTrans  = Factory.getProxy<OrderTransactionService> ();
              return   proxyTrans;
        }

    }
} 

为什么叫方法或者服务呢,结合框架这些方法可以直接公开出来,可以远程访问的,不需要加额外的编码,另外流程引擎也可以直接调用这些服务的,然后流程引擎会组合成新的服务对客户端公开。对于事务的处理,有[Operation(ScopeOption.Required)]这一句就可以了,也可以通过配置文件加上去。异常可以通过服务直接抛到客户端,如果在事务内则整个参与事务的所有服务的事务全部回滚,可能会涉及到多个服务的嵌套调用以及递归调用,全部会回滚,所涉及到的数据库连接会自动释放掉,缓存清理掉。
3、客户端调用:已经到了界面显示层。对于Web客户端与Form客户端的调用一样,已经到了界面显示层了。

客户端调用

 namespace   eWMS.Forms
{
      using   System;
      using   System.Collections.Generic;
      using   System.Text;
      using   System.Drawing;
      using   System.Windows.Forms;
      using   EES.Common;
      using   EES.Common.Data;
      using   EES.Controls.Win;
      using   EES.Common.Query;
      using   EES.Common.MVC;
      using   eWMS.Data;
      using   eWMS.Service;
    
    
    [View(  "  移动类型管理  " , EntryType.入口,  "  移动类型  " ,  "  移动类型管理  "  )]
      public   sealed   partial   class   BillTypeLForm : EForm
    {
        
          private   BillTypeService proxy;
        
          public   BillTypeLForm()
        {
              this  .InitializeComponent();
              //   绑定数据错误不提示 
             this .gridView.DataError +=  GrivViewDataError;
              this .gridView.CellValidated +=  GrivViewCellValidated;
              //   数据源 
             this .gridView.DataSource =  this  .bindingSource;
              //  
             this .bindingSource.AddingNew +=  AddingNew;
              this .Input =  new  DataCollection<BillType> ();

            DataLoad();
        }
        
          private   BillTypeService getProxy()
        {
              if (proxy== null  )
                proxy =Factory.getProxy<BillTypeService> () ;
              return   proxy;
        }
        
          private   void  AddingNew( object   sender, System.ComponentModel.AddingNewEventArgs e)
        {
            BillType obj  = Factory.Create<BillType> ();
              //   更多初始化
              //  
            e.NewObject =  obj;
        }
        
          ///   <summary> 
         ///   刷新
          ///   </summary> 
        [Func( "  刷新  " , Ordinal= 10  )]
          public   void   DataLoad()
        {
              this .Input =  this  .getProxy().FindAll();
        }

        [Func(  "  删除  " ,Ordinal= 35  )]
          public   void   DataDelete()
        {
            BillType data  =  this .Current  as   BillType;
              if  (data ==  null  )
                  throw   new  EESException( "  请选择要删除的数据  "  );
              if  (MessageBox.Show( "  确定要删除数据吗?  " ,  "  删除数据  " , MessageBoxButtons.OKCancel, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button2) ==  System.Windows.Forms.DialogResult.OK)
            {
                  if  (data.DataState !=  DataState.Created)
                {
                      this  .getProxy().Delete(data);
                }
                data.DirectRemove();
                MessageBox.Show(  "  删除 成功  "  );
            }
        }
        
        [Func(  "  保存  " , Ordinal= 30  )]
          public   void   DataSave()
        {
              object  data =  this  .Input;
              if  (data  is  DataCollection<BillType> )
            {
                  this .Input =  this .getProxy().SaveAll(((DataCollection<BillType> )(data)));
                MessageBox.Show(  "  保存 成功  "  );
            }
        }

          ///   <summary> 
         ///   查询
          ///   </summary> 
        [Func( "  查询  " , Ordinal =  40  )]
          public   void   DataFind()
        {
            BillTypeFForm form  =  new   BillTypeFForm();
            form.OnOK  +=  delegate ( object  sender, TEventArgs<DataCollection<BillType>> e){ this .Input= e.Data;};
            form.ShowDialog();
        }

    }
} 


还没有说完,后面再继续吧

有不到之处,请大家批评指正……

谢谢!

 

 

 

标签:  .NET ,  C# ,  SOA ,  DDD ,  领域模型 ,  架构

作者: Leo_wl

    

出处: http://www.cnblogs.com/Leo_wl/

    

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

版权信息

查看更多关于DDD的模型选择的详细内容...

  阅读:42次