好得很程序员自学网

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

面向领域开发示例【转】

面向领域开发示例【转】

 最近面向领域的知识挺火,我也来插一腿。说说我平时做项目时候用到的开发方式,以下代码为伪代码,主要展示一下我现在的开发方式供大家讨论,系统中不考虑持久、 UI 、 AOP 和 IOC 等方面内容。

    说到 .NET 社区的“开发方式”就不得不提一下 Petshop 了,可以说 Petshop 真是影响了 .NET 的一代人。以至于三层成了 .NET 这边流行的标准的开发方式。但是要说一下 Petshop 是数据库驱动业务核心的过程式开发,也正是它也毒害了一批人。

   

下面我们以一个最常见也是大家比较熟的下定单来简单看一下。首先是系统的几个领域类:

   

我也就不解释了,发下几个类的代码里面有注解。大家看一下就明白了。这里我们要强调的是类关系,还有一个根的概念。每个业务流都会有一个根。而根不是整个系统唯一确定的是而是根据对象在哪个业务范围内而决定的。显然这里面是 Order 定单对象。

 

     ///   <summary>
     ///  商品
     ///   </summary>
     public   class  Product
    {
         ///   <summary>
         ///  键
         ///   </summary>
         public   int  SysNo {  get ;  set ; }
         ///   <summary>
         ///  商品名称
         ///   </summary>
         public   string  ProductName {  get ;  set ; }
         ///   <summary>
         ///  商品价格
         ///   </summary>
         public   decimal  ProductPrice {  get ;  set ; }
         private  Category _category;
         ///   <summary>
         ///  所属分类
         ///   </summary>
         public  Category Category
        {
             get  {  return  _category; }
             set  { _category  =  value; }
        }
    }

     ///   <summary>
     ///  定单
     ///   </summary>
     public   class  Order
    {
         #region  属性
         ///   <summary>
         ///  键
         ///   </summary>
         public   int  SysNo {  get ;  set ; }
         ///   <summary>
         ///  定单ID
         ///   </summary>
         public   string  OrderId {  get ;  set ; }
         ///   <summary>
         ///  定单金额
         ///   </summary>
         public   decimal  OrderAmount {  get ;  set ; }
         ///   <summary>
         ///  运费金额
         ///   </summary>
         public   decimal  ShipAmount {  get ;  set ; }
         ///   <summary>
         ///  支付金额
         ///   </summary>
         public   decimal  PayAmount {  get ;  set ; }
         ///   <summary>
         ///  定单状态
         ///   </summary>
         public   int  OrderStatus {  get ;  set ; }
         ///   <summary>
         ///  定单时间
         ///   </summary>
         public  DateTime OrderTime {  get ;  set ; }
         private  List < OrderItem >  _orderItems  =   new  List < OrderItem > ();
         ///   <summary>
         ///  定单明细
         ///   </summary>
         public  List < OrderItem >  OrderItems
        {
             get  {  return  _orderItems; }
             set  { _orderItems  =  value; }
        }
         #endregion

         #region  方法
         ///   <summary>
         ///  计算定单金额
         ///   </summary>
         ///   <returns></returns>
         public   decimal  GetOrderAmount()
        {
             decimal  amount  =   0 ;
             // 计算商品金额
             foreach  (var item  in  OrderItems)
            {
                amount  +=  item.GetAmount();
            }
             // 加上运费
            amount  +=  ShipAmount;
             return  amount;
        }
         #endregion

    }

  ///   <summary>
     ///  定单明细
     ///   </summary>
     public   class  OrderItem
    {
         #region  属性
         ///   <summary>
         ///  键
         ///   </summary>
         public   int  SysNo {  get ;  set ; }
         private  Product _product  =   new  Product();
         ///   <summary>
         ///  购买商品
         ///   </summary>
         public  Product Product
        {
             get  {  return  _product; }
             set  { _product  =  value; }
        }
         ///   <summary>
         ///  购买价格
         ///   </summary>
         public   decimal  ProductPrice {  get ;  set ; }
         ///   <summary>
         ///  购买数量
         ///   </summary>
         public   int  ProductQty {  get ;  set ; }
         #endregion

         #region  方法
         ///   <summary>
         ///  主算小计金额
         ///   </summary>
         ///   <returns></returns>
         public   decimal  GetAmount()
        {
             return   this .ProductPrice  *  Convert.ToDecimal( this .ProductQty);
        }
         #endregion
    }

///   <summary>
     ///  商品库存
     ///   </summary>
     public   class  Inventory
    {
         #region  属性
         ///   <summary>
         ///  键
         ///   </summary>
         public   int  SysNo {  get ;  set ; }
         ///   <summary>
         ///  更新键,用来保证更新的数据之前没有别人更新过。对应表的ModKey列,每更新一次更新Guid值
         ///   </summary>
         public  Guid ModKey {  get ;  set ; }
         private  Product _product  =   new  Product();
         ///   <summary>
         ///  商品
         ///   </summary>
         public  Product Product
        {
             get  {  return  _product; }
             set  { _product  =  value; }
        }
         ///   <summary>
         ///  库存数量
         ///   </summary>
         public   int  Qty {  get ;  set ; }
         #endregion

         #region  方法
         ///   <summary>
         ///  验证库存是否有库存
         ///   </summary>
         ///   <returns></returns>
         public   bool  ValidInventory()
        {
             if  ( this .Qty  >   0 )
                 return   true ;
             else
                 return   false ;
        }
         ///   <summary>
         ///  减库存
         ///   </summary>
         ///   <param name="qty"></param>
         public   void  MinusInventory( int  qty)
        {
             if  ( this .Qty  <  qty)
                 throw   new  Exception( " 库存不足! " );
             this .Qty  -=  qty;
        }
         #endregion
    }

接下来看看我这个伪代码的项目结构。做的很简单,简单明快的架构就是好的架构,不要把架构搞的很复杂。

 

 

Domain :领域层,里面放的是领域对象。这个层对其它层没有依赖

Repository :持久层,对领域对象进行持久。里面可以有级存和 DB 等。这个层依赖 Domain

Services :应用程序服务,这个名字喜好着起吧。我们可以把它理解为业务逻辑层,当然这个业务逻辑是对一个功能更粗粒度的 API 。里面会调用依赖的领域对象进行业务组合达到业务需求。当然对对象的持久也是这里来做的。这个层依赖 Domain 和 Repository

Web : UI 层,调用 Services 进行业务处理,需要 ViewModel(VO) 我们可以加,我个人比较喜欢按需要创建 ViewModel 对象,不需要的没必要增加工作量。

基本流程就是

UI 调用 Serivices 创建定单

Services 调用 Domain 对象进行业务组合处理

最后 Services 调用 Repository 进行对象的持久

 

我们从上到下,首先是UI的控制器里面开始。生成定单

  public  ActionResult About()
        {
             // 创建定单,生成定单必要数据收货信息,购物车信息等
            Order order  =   new  Order();
            OrderService service  =   new  OrderService();
            service.OrderBuy(order); // 定单提交


             return  View();
        }

 然后是Services里面的方法

  ///   <summary>
         ///  定单提交
         ///   </summary>
         ///   <param name="order"></param>
         public   void  OrderBuy(Order order)
        {
             // 事务开始
            order.OrderAmount  =  order.GetOrderAmount(); // 计算订单金额
             // 更新库存
             foreach  (var item  in  order.OrderItems)
            {
                Inventory inventory  =  InventoryRepository.LoadInventory(item.Product); // 取得一个库存对象
                inventory.MinusInventory(item.ProductQty); // 调用库存调用方法
                InventoryRepository.SaveInventory(inventory); // 持久更新完的库存
            }
            OrderRepository.SaveOrder(order); // 持久化定单
             // 事务结束
        }

Repository里面的是伪代码,就不发了。

工作呢,写的很粗略。最后说一点,其实面向领域开发通过这些代码是看不出本质的。我在这总结一下。

把你的开发关注点提到类(对象)上来,不要把关注点放到数据库(表)上。

作者: Leo_wl

    

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

    

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

版权信息

查看更多关于面向领域开发示例【转】的详细内容...

  阅读:35次