• 小议传统分层与新式分层,抑或与DDD分层 Virus


    引言

    本文提到的分层只是软件架构上的分层。文中的传统分层指的是传统的三层结构:UI(界面表现层),BLL(业务逻辑层),DAL(数据访问层)。文中提出的观点也都是个人的一点认识,与任何组织没有关系,如有异议,还请各位踊跃拍砖。

    当然了,出现的这些问题,也可能只是我个人的问题,不代表每个人都存在。无则加勉,有则改正吧。如果是个人的问题,那就当是个人总结吧,大家看看就算了。

    这里说到的传统分层,也有可能是我对于分层的错误理解造成的,但是我看见的不只是我的项目是这么的结构,很多的项目也都是这样的结构。里面的代码, 都和我理解的一样,至少可以说明,还是有一部分人犯了和我一样的错误。

    传统分层

    传统分层最大的问题就在于割裂了上层与下层之间的联系,把他们之间的关系变成了简单的接口调用,变成了完全的接口形式主义。同时,忽略了下层是为上层提供服务的,不是单独存在的,下层提供的服务应该受到上层的规约。当然,也不是说不可以提供更多的服务,但是至少应该提供上层需要的,然后再考虑提供一些“边角料”。

    我们先看一个传统分层的解决方案结构。

    image

    相互之间的引用关系是:UI引用BLL、Entity、Common;BLL引用IDAL、Entity、Common;IDAL引用Entity;DAL引用IDAL、Entity、Common。

    显示行号 复制代码 UI  Code
    1. private void button1_Click(object sender, EventArgs e)
      
    2.        {
      
    3.            _02_BLL.OrderBll orderBll = Common.ServiceLocator.LoadService<_02_BLL.OrderBll>();
      
    4.            orderBll.SubmitOrder(new _05_Entity.OrderEntity()
      
    5.            {
      
    6.                OrderSeqNo = "123",
      
    7.                OrderAmount = 1000
      
    8.            }); 
      
    9.        }
      
    显示行号 复制代码 BLL Code
    1. public class OrderBll
      
    2.    {
      
    3.        IOrderDal _orderDal;
      
    4.        public OrderBll()
      
    5.        {
      
    6.            _orderDal = Common.ServiceLocator.LoadService<_03_IDAL.IOrderDal>();
      
    7.        }
      
    8.        public bool SubmitOrder(OrderEntity order)
      
    9.        {
      
    10.            return _orderDal.Add(order);
      
    11.        }
      
    12.    }
      
    显示行号 复制代码 IDAL Code
    1. public interface IOrderDal
      
    2.     {
      
    3.         bool Add(OrderEntity order);
      
    4.     }
      
    显示行号 复制代码 DAL Code
    1. public class OrderDal:_03_IDAL.IOrderDal 
      
    2.    {
      
    3. 
      
    4.        public bool Add(_05_Entity.OrderEntity order)
      
    5.        {
      
    6.            IDbConnection conn = new SqlConnection();
      
    7.            conn.Open();
      
    8.            IDbCommand comm = conn.CreateCommand();
      
    9.            IDbDataParameter param = comm.CreateParameter();
      
    10.            param.Direction = ParameterDirection.Input;
      
    11.            param.DbType = DbType.String;
      
    12.            param.ParameterName = "OrderSeqNo";
      
    13. 
      
    14.            if (comm.ExecuteNonQuery() > 0)
      
    15.                return true;
      
    16.            else
      
    17.                return false;
      
    18.        }
      
    19.    }
      
    显示行号 复制代码 Unity Container Locator
    1. using System.Configuration;
      
    2. using System.Globalization;
      
    3. using Microsoft.Practices.Unity;
      
    4. using Microsoft.Practices.Unity.Configuration;
      
    5. using Microsoft.Practices.Unity.InterceptionExtension;
      
    6. using System.Web;
      
    7. using System;
      
    8. 
      
    9. namespace Common
      
    10. {
      
    11.     public static class ServiceLocator
      
    12.     {
      
    13.         // private static readonly InterfaceInterceptor  injector = new InterfaceInterceptor ();
      
    14. 
      
    15.         private static readonly TransparentProxyInterceptor injector = new TransparentProxyInterceptor();
      
    16. 
      
    17.         public static IUnityContainer Container
      
    18.         {
      
    19.             get;
      
    20.             private set;
      
    21.         }
      
    22.         static ServiceLocator()
      
    23.         {
      
    24.             Container = new UnityContainer();
      
    25.             UnityConfigurationSection unitySection = ConfigurationManager.GetSection("unity") as UnityConfigurationSection;
      
    26.             if (unitySection == null)
      
    27.             {
      
    28.                 throw new ConfigurationErrorsException(string.Format(CultureInfo.CurrentCulture, "missing unity configuration section"));
      
    29.             }
      
    30.             Container.AddNewExtension<Interception>();
      
    31. 
      
    32.             unitySection.Configure(Container, "Container");
      
    33. 
      
    34.         }
      
    35.         /// <summary>
      
    36.         /// 没?有D为a映3射?指?定¨别e名?
      
    37.         /// name属?性?没?有D赋3值μ
      
    38.         /// </summary>
      
    39.         /// <typeparam name="T"></typeparam>
      
    40.         /// <returns></returns>
      
    41.         public static T LoadService<T>()
      
    42.         {
      
    43.             Container.Configure<Interception>().SetDefaultInterceptorFor<T>(injector);
      
    44.             return Container.Resolve<T>();
      
    45.         }
      
    46.         /// <summary>
      
    47.         /// 为a映3射?指?定¨别e名?
      
    48.         /// name属?性?赋3值μ
      
    49.         /// </summary>
      
    50.         /// <typeparam name="T"></typeparam>
      
    51.         /// <param name="serviceName"></param>
      
    52.         /// <returns></returns>
      
    53.         public static T LoadService<T>(string serviceName)
      
    54.         {
      
    55.             Container.Configure<Interception>().SetDefaultInterceptorFor<T>(injector);
      
    56.             return Container.Resolve<T>(serviceName);
      
    57.         }
      
    58.     }
      
    59. }
      
    60. 
      

    上层在调用下层的时候,不是调用自己需要的,而是从下层提供的服务中筛选一些可以用的,凑合用一下。如果发现没有自己可以用的,就在IDAL文件中添加一个,然后在DAL文件中实现以下,这下好了,BLL可以用了。这样也会造成在开发DAL层的时候,没有充分考虑BLL的需要,自己盲目实现一些,然后BLL用的时候,才发现很多还要重新写。造成大量的浪费,代码、人力、时间、精力都浪费一部分了。也会影响到开发的进度。

    新式分层,抑或叫做DDD分层

    说是新式分层,其实也是我随便叫的。就是这段时间看了博客园的一些DDD文章,还有就是codeplex上的两个项目NLayerApp和SmartCA的源码。看了这些之后,有的一点理解。不管是神似还是形似吧,反正觉得比以前传统分层有一点道理,就分享出来了,也挣点人气,骗点点击量,哈哈。

    先来一张图吧。

    image

    DDD中的分层主要是四层:Presentation(表现层),Application(应用层),Domain(领域层),Infrastructure(基础层)。

    Presentation相当于以前的UI层。Application是一个任务的调度层,没有实际的业务逻辑,也不推荐放入业务逻辑,实际中可以用Wcf来代替,或者使用普通的类库就可以。其实就是根据UI的业务调用,然后映射到具体的领域对象身上去。也可以通过Application来暴露粗粒度的业务处理,因为领域层的业务处理是细粒度的。没有了以前的DAL,把它的部分放入了Infrastructure层。

    以前的IDAL被放入了Domain,在图上,是Domain.Core项目,这个项目会被Infrastructure引用。因为Domain.Core中的IDAL相当于是领域对象对于持久化提出的要求,也就是说必须要实现这些功能,这些都是领域对象需要的。具体的如何实现,具体如何持久化,是持久化到关系数据库还是文件系统,还是内存数据库,都由具体的实现来定义。也就是图中的Infrastructure.Data.Core和Infrastructure.Data.MainModule项目。这两个项目中的实现,实现的都是领域对象持久化所需要的,不会实现一大丢不必要的方法。不知道这算不算是改进呢?

    结论

    传统分层,或者说是我理解的传统分层,存在的问题就是割裂层之间的联系,形式化了层之间的联系。没有表达出上层对于下层的需要,下层是为上层服务的,这些联系。DDD的分层可以解决这个问题,会提高开发的效率,少走一些弯路。

    不知道大家是如何认识的呢????????期待大家的回复,拍砖。

  • 相关阅读:
    正则表达式
    iOS获取设备型号、设备类型等信息
    Dubbo-Zookeeper安装
    CentOS-常用安装
    多线程-线程通信
    JVM-高效并发
    静态代理与JDK动态代理
    JVM-类加载机制
    RPC原理及实现
    JVM-自动内存管理机制
  • 原文地址:https://www.cnblogs.com/virusswb/p/1931964.html
Copyright © 2020-2023  润新知