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

引言

本文提到的分层只是软件架构上的分层。文中的传统分层指的是传统的三层结构: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的分层可以解决这个问题,会提高开发的效率,少走一些弯路。

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

转载于:https://www.cnblogs.com/virusswb/archive/2011/01/10/1931964.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/422954.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

WCF 第八章 安全 客户端认证

一个服务的客户端认证是通过向服务提供一系列信赖的声明。声明可以是任何形式&#xff0c;只要客户端和服务端理解这个格式并信赖它的来源就可以。 如果客户端和服务端共享一个秘密信息&#xff0c;比如一个用户名和密码&#xff0c;只要客户端通过一个合法认证发送数据&#x…

前端学习(205):animation动画库

动画库 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><meta http-equiv"X-UA-Compatible" conte…

【剑指offer - C++/Java】7、斐波那契数列

在线题目链接&#xff1a;斐波那契数列 文章目录1、题目描述2、题目分析3、代码3.1 递归方法3.11 Java代码3.12 C代码3.2 动态规划3.21 Java代码3.22 C代码3.3 循环方法3.31 Java代码3.32 C代码4、总结1、题目描述 大家都知道斐波那契数列&#xff0c;现在要求输入一个整数n&a…

【剑指offer - C++/Java】8、跳台阶

在线题目链接&#xff1a;跳台阶 文章目录1、题目描述2、题目分析3、代码3.1 递归方法3.11 Java代码3.12 C代码3.2 动态规划3.21 Java代码3.22 C代码3.3 循环方法3.31 Java代码3.32 C代码4、总结1、题目描述 一只青蛙一次可以跳上1级台阶&#xff0c;也可以跳上2级。求该青蛙跳…

【剑指offer - C++/Java】10、矩形覆盖

在线题目链接&#xff1a;矩形覆盖 文章目录1 题目描述2 题目分析3 代码3.1 递归方法3.11 Java代码3.12 C代码3.2 动态规划算法3.2 动态规划3.21 Java代码3.22 C代码3.3 循环方法3.31 Java代码3.32 C代码4、总结1 题目描述 我们可以用2*1的小矩形横着或者竖着去覆盖更大的矩形…

【剑指offer - C++/Java】12、数值的整数次方

在线题目链接&#xff1a;数值的整数次方 文章目录1 题目描述2 题目分析2.1 方法1 循环2.11 Java代码2.12 C代码2.2 方法2 递归2.21 Java代码2.22 C代码3 总结1 题目描述 给定一个double类型的浮点数base和int类型的整数exponent。求base的exponent次方。 2 题目分析 2.1 方…

【剑指offer - C++/Java】14、链表中倒数第k的节点

在线题目链接&#xff1a;链表中倒数第k的节点 文章目录1 题目描述2 题目分析2.1 Java代码2.2 C代码3 总结1 题目描述 输入一个链表&#xff0c;输出该链表中倒数第k个结点。 2 题目分析 这道题比较简单。常规做法是先求出链表的总的节点个数n&#xff0c;然后再从头开始找第n-…

beta:scrum5

今天的工作 周一的工作 困难 王佳磊 收集数据&#xff0c;build了online的数据库, 38934 38939&#xff0c;收集更多数据&#xff0c;在新的API环境下&#xff0c;逐步发现并fix掉以前姓名到ID映射的bug. API的改动&#xff0c;ID的合并 肖巍&#xff0c;兰翠玲 等待测…

【软件开发底层知识修炼】十三 链接器-如何写出不依赖C库函数的代码

本文将综合以下4篇文章&#xff0c;学习如何写出不依赖libc库的程序&#xff1a; 【软件开发底层知识修炼】九 链接器-可重定位文件与可执行文件【软件开发底层知识修炼】十 链接器-main函数不是第一个被执行的函数【软件开发底层知识修炼】十一 链接器-链接脚本【软件开发底层…

前端学习(218):属性选择器

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/ html4/strict.dtd"> <html><head><meta http-equiv"content-type" content"text/html; charsetutf-8"><title>属性选择器&…

【软件开发底层知识修炼】十四 快速学习GDB调试一 入门使用

前面几篇文章学习了链接器相关的内容。现在开始来学习GDB调试。我们的目的是通过这几篇文章将GDB调试完全学会。 文章目录1 为什么需要GDB2 GDB 的常规应用3 GDB调试程序实例4 总结1 为什么需要GDB 什么是GDB&#xff1f; GNU项目中的调试器&#xff08;gnu debuger&#xff0…

前端学习(219):css伪类选择器

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/ html4/strict.dtd"> <html><head><meta http-equiv"content-type" content"text/html; charsetutf-8"><title>CSS伪类<…

【软件开发底层知识修炼】十五 快速学习GDB调试二 使用GDB进行断点调试

上一篇文章我们学习了使用GDB的最基本方法&#xff1a;【软件开发底层知识修炼】十四 快速学习GDB调试一 入门使用 本篇文章将学习GDB的断点调试。断点调试是一种非常重要的调试方法。 文章目录1 断点类型2 GDB软件断点调试相关操作2.1 通过函数名设置断点2.2 通过文件名行号…

Informix IDS 11体系操持(918测验)认证指南,第 4 部门: 机能调优(1)

对 IBM Informix Dynamic Server (IDS) 和它的分比如子体系举行调优&#xff0c;以失掉最佳机能。在一个冗长的概述之后&#xff0c;本教程给出了一些关于怎样检查数据库做事器及其子体系的例子。本文是这个分 8 部门的 系列教程 的第 4 部门&#xff0c;这个教程可以帮手您筹办…

前端学习(220):伪元素选择器

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/ html4/strict.dtd"> <html><head><meta http-equiv"content-type" content"text/html; charsetutf-8"><title>CSS伪元素&l…

【软件开发底层知识修炼】十六 快速学习GDB调试三 使用GDB的数据断点监测变量是否改变

上一篇文章我们学习了如何使用GDB进行软件断点调试和硬件断点调试&#xff1a;【软件开发底层知识修炼】十五 快速学习GDB调试二 使用GDB进行断点调试本篇文章继续上一篇文章的学习&#xff0c;如何使用GDB的数据断点监测内存中的变量是否被改变 文章目录1 GDB的数据断点1.1 利…

AllTray-将办法最小化到琐细托盘

Toy Posted in AppsAllTray 是一个很有效的小办法&#xff0c;操纵它你可以将办法的窗口最小化到琐细托盘&#xff0c;从而腾出桌面空间以作它用。此办法主要为那些没有原生供给最小化到琐细托盘成效的办法而预备的。今朝&#xff0c;AllTray 可以在 GNOME、KDE、Xfce、Fluxbox…

【软件开发底层知识修炼】十七 快速学习GDB调试四 使用GDB进行函数调用栈的查看

上一篇文章学习了如何使用GDB数据断点进行内存监测&#xff1a;【软件开发底层知识修炼】十五 快速学习GDB调试三 使用GDB的数据断点监测变量是否改变本篇文章继续上一篇文章的学习&#xff1a;如何使用GDB进行函数调用栈的查看 文章目录1 backtrace和frame2 使用GDB进行函数调…

前端学习(221):字体属性

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/ html4/strict.dtd"> <html><head><meta http-equiv"content-type" content"text/html; charsetutf-8"><title>CSS字体属性…

前端学习(222):文本属性

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/ html4/strict.dtd"> <html><head><meta http-equiv"content-type" content"text/html; charsetutf-8"><title>CSS文本属性…