小议传统分层与新式分层,抑或与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. public bool Add(_05_Entity.OrderEntity order)
  4. {
  5. IDbConnection conn = new sqlConnection();
  6. conn.open();
  7. IDbCommand comm = conn.CreateCommand();
  8. IDbDataParameter param = comm.CreateParameter();
  9. param.Direction = ParameterDirection.Input;
  10. param.DbType = DbType.String;
  11. param.ParameterName = "OrderSeqNo";
  12. if (comm.ExecuteNonQuery() &gt; 0)
  13. return true;
  14. else
  15. return false;
  16. }
  17. }
显示行号 复制代码 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. namespace Common
  9. {
  10. public static class ServiceLocator
  11. {
  12. // private static readonly InterfaceInterceptor injector = new InterfaceInterceptor ();
  13. private static readonly TransparentProxyInterceptor injector = new TransparentProxyInterceptor();
  14. public static IUnityContainer Container
  15. {
  16. get;
  17. private set;
  18. }
  19. static ServiceLocator()
  20. {
  21. Container = new UnityContainer();
  22. UnityConfigurationSection unitySection = ConfigurationManager.GetSection("unity") as UnityConfigurationSection;
  23. if (unitySection == null)
  24. {
  25. throw new ConfigurationErrorsException(string.Format(CultureInfo.CurrentCulture,"missing unity configuration section"));
  26. }
  27. Container.AddNewExtension<Interception>();
  28. unitySection.Configure(Container,"Container");
  29. }
  30. /// <summary>
  31. /// 没?有D为a映3射?指?定¨别e名?
  32. /// name属?性?没?有D赋3值μ
  33. /// </summary>
  34. /// <typeparam name="T"></typeparam>
  35. /// <returns></returns>
  36. public static T LoadService<T>()
  37. {
  38. Container.Configure<Interception>().SetDefaultInterceptorFor<T>(injector);
  39. return Container.Resolve<T>();
  40. }
  41. /// <summary>
  42. /// 为a映3射?指?定¨别e名?
  43. /// name属?性?赋3值μ
  44. /// </summary>
  45. /// <typeparam name="T"></typeparam>
  46. /// <param name="serviceName"></param>
  47. /// <returns></returns>
  48. public static T LoadService<T>(string serviceName)
  49. {
  50. Container.Configure<Interception>().SetDefaultInterceptorFor<T>(injector);
  51. return Container.Resolve<T>(serviceName);
  52. }
  53. }
  54. }

上层在调用下层的时候,不是调用自己需要的,而是从下层提供的服务中筛选一些可以用的,凑合用一下。如果发现没有自己可以用的,就在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的分层可以解决这个问题,会提高开发的效率,少走一些弯路。

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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


迭代器模式(Iterator)迭代器模式(Iterator)[Cursor]意图:提供一种方法顺序访问一个聚合对象中的每个元素,而又不想暴露该对象的内部表示。应用:STL标准库迭代器实现、Java集合类型迭代器等模式结构:心得:迭代器模式的目的是在不获知集合对象内部细节的同时能对集合元素进行遍历操作
高性能IO模型浅析服务器端编程经常需要构造高性能的IO模型,常见的IO模型有四种:(1)同步阻塞IO(BlockingIO):即传统的IO模型。(2)同步非阻塞IO(Non-blockingIO):默认创建的socket都是阻塞的,非阻塞IO要求socket被设置为NONBLOCK。注意这里所说的N
策略模式(Strategy)策略模式(Strategy)[Policy]意图:定义一系列算法,把他们封装起来,并且使他们可以相互替换,使算法可以独立于使用它的客户而变化。应用:排序的比较方法、封装针对类的不同的算法、消除条件判断、寄存器分配算法等。模式结构:心得:对对象(Context)的处理操作可
访问者模式(Visitor)访问者模式(Visitor)意图:表示一个作用于某对象结构中的各元素的操作,它使你在不改变各元素的类的前提下定义作用于这些元素的新操作。应用:作用于编译器语法树的语义分析算法。模式结构:心得:访问者模式是要解决对对象添加新的操作和功能时候,如何尽可能不修改对象的类的一种方
命令模式(Command)命令模式(Command)[Action/Transaction]意图:将一个请求封装为一个对象,从而可用不同的请求对客户参数化。对请求排队或记录请求日志,以及支持可撤消的操作。应用:用户操作日志、撤销恢复操作。模式结构:心得:命令对象的抽象接口(Command)提供的两个
生成器模式(Builder)生成器模式(Builder)意图:将一个对象的构建和它的表示分离,使得同样的构建过程可以创建不同的表示。 应用:编译器词法分析器指导生成抽象语法树、构造迷宫等。模式结构:心得:和工厂模式不同的是,Builder模式需要详细的指导产品的生产。指导者(Director)使用C
设计模式学习心得《设计模式:可复用面向对象软件的基础》一书以更贴近读者思维的角度描述了GOF的23个设计模式。按照书中介绍的每个设计模式的内容,结合网上搜集的资料,我将对设计模式的学习心得总结出来。网络上关于设计模式的资料和文章汗牛充栋,有些文章对设计模式介绍生动形象。但是我相信“一千个读者,一千个
工厂方法模式(Factory Method)工厂方法模式(Factory Method)[Virtual Constructor]意图:定义一个用于创建对象的接口,让子类决定实例化哪一个类,使一个类的实力化延迟到子类。应用:多文档应用管理不同类型的文档。模式结构:心得:面对同一继承体系(Produc
单例模式(Singleton)单例模式(Singleton)意图:保证一个类只有一个实例,并提供一个访问它的全局访问点。应用:Session或者控件的唯一示例等。模式结构:心得:单例模式应该是设计模式中最简单的结构了,它的目的很简单,就是保证自身的实例只有一份。实现这种目的的方式有很多,在Java中
装饰者模式(Decorator)装饰者模式(Decorator)[Wrapper]意图:动态的给一个对象添加一些额外的职责,就增加功能来说,比生成子类更为灵活。应用:给GUI组件添加功能等。模式结构:心得:装饰器(Decorator)和被装饰的对象(ConcreteComponent)拥有统一的接口
抽象工厂模式(Abstract Factory)抽象工厂模式(Abstract Factory)[Kit]意图:提供一个创建一系列相关或相互依赖对象的接口,而无须指定他们具体的类。应用:用户界面工具包。模式结构:心得:工厂方法把生产产品的方式封装起来了,但是一个工厂只能生产一类对象,当一个工厂需要生
桥接模式(Bridge)桥接模式(Bridge)[Handle/Body]意图:将抽象部分与它的实现部分分离,使他们都可以独立的变化。应用:不同系统平台的Windows界面。模式结构:心得:用户所见类体系结构(Window派生)提供了一系列用户的高层操作的接口,但是这些接口的实现是基于具体的底层实现
适配器模式(Adapter)适配器模式(Adapter)[Wrapper]意图:将类的一个接口转换成用户希望的另一个接口,使得原本由于接口不兼容而不能一起工作的类可以一起工作。应用:将图形类接口适配到用户界面组件类中。模式结构:心得:适配器模式一般应用在具有相似接口可复用的条件下。目标接口(Targ
组合模式(Composition)组合模式(Composition)意图:将对象组合成树形结构以表示“部分-整体”的层次结构,使得用户对单个对象和组合对象的使用具有一致性。应用:组合图形、文件目录、GUI容器等。模式结构:心得: 用户(Client)通过抽象类(Component)提供的公用接口统一
原型模式(Prototype)原型模式(Prototype)意图:用原型实例制定创建对象的种类,并且通过拷贝这些原型创建新的对象。应用:Java/C#中的Clonable和IClonable接口等。模式结构:心得:原型模式本质上就是对象的拷贝,使用对象拷贝代替对象创建的原因有很多。比如对象的初始化构
什么是设计模式一套被反复使用、多数人知晓的、经过分类编目的、代码 设计经验 的总结;使用设计模式是为了 可重用 代码、让代码 更容易 被他人理解、保证代码 可靠性;设计模式使代码编制  真正工程化;设计模式使软件工程的 基石脉络, 如同大厦的结构一样;并不直接用来完成代码的编写,而是 描述 在各种不同情况下,要怎么解决问题的一种方案;能使不稳定依赖于相对稳定、具体依赖于相对抽象,避免引
单一职责原则定义(Single Responsibility Principle,SRP)一个对象应该只包含 单一的职责,并且该职责被完整地封装在一个类中。Every  Object should have  a single responsibility, and that responsibility should be entirely encapsulated by t
动态代理和CGLib代理分不清吗,看看这篇文章,写的非常好,强烈推荐。原文截图*************************************************************************************************************************原文文本************
适配器模式将一个类的接口转换成客户期望的另一个接口,使得原本接口不兼容的类可以相互合作。
策略模式定义了一系列算法族,并封装在类中,它们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。