.NET应用架构设计—面向查询的领域驱动设计实践(调整传统三层架构,外加维护型的业务开关)
阅读目录:
- 1.背景介绍
- 2.在业务层中加入核心领域模型(引入DomainModel,让逻辑、数据有家可归,变成一个完整的业务对象)
- 3.统一协调层Application Layer(加入协调层来转换DomianModel)
- 4.从数据扁平结构转换成OO体系结构(使用OO丰富代码结构)
- 5.DomainModel中的内容(带开关的Specification、SOA化的Specification)
- 6.模式、重构、单元测试在领域模型中的运用
1.背景介绍
由于时间关系废话不多扯了,直奔主题,对领域驱动设计不是太了解的朋友请先熟悉相关主题或参考本人以下两篇文章:
.NET领域驱动设计—初尝(疑问、模式、原则、工具、过程、框架、实践),这篇文章对领域驱动设计的基本精神详细分析;
.NET领域驱动设计—实践(穿过迷雾走向光明) ,这篇文章对领域驱动设计的一个基本实践,记录下了实践过程、建模的技巧等内容;
DomainModel是由很多细粒度的Object组成,按照以往的教训(将Object行为、数据肢解,得到一个残缺的Object),现在我们将逻辑行为和数据绑定在一起,形成了一个丰富的领域模型,这也是面向对象设计原则之一;想了解更多关于实现面向对象的技巧请参考【《实现模式》作者:Kent Beck】一书;
但是这样又带来了由于充血型DDD模型会给面向大规模查询的业务模块带来一定的性能开销,试想一个OrderManager对象,如果我们需要获取在某个条件范围类的所有Order会给OrderManager带来很多性能、逻辑上的复杂度;根据DDD.CQRS架构,得知将DomainModel中的查询逻辑单独剥离出去,让Command端很干净的处理聚合的写逻辑,在Query端也很直接的处理查询逻辑;
这样设计之后会有一个很尴尬的情况,在Query端的DomainModel不被关注了,因为Query的逻辑有简单有复杂,大型站点会有很多复杂的查询逻辑还会有很多的业务开关,做过维护的朋友应该知道新功能上线需要有switch的控制,这是为了安全起见吧;但是简单的业务逻辑就会被我们下意识的认为不需要使用完整的DomainModel结构,还是使用传统的分层架构上层依赖下层,Business Layer直接依赖DataAccess Layer,其实这个时候Business Object已经不在是遵循“单一职责”原则了,这样时间一长又慢慢的回到了以前肢解Object的困境;
这篇文章是讲解如何在Query端实践DDD,如何运用DDD的强项来解决复杂业务逻辑的实现,尤其是复杂的业务逻辑需要开关控制的时候其实更需要DomainModel来完成;
2.在业务层中加入核心领域模型(引入DomainModel,让逻辑、数据有家可归,变成一个完整的业务对象)
由于我们缺乏领域模型,所以导致我们的业务逻辑、规则随波逐流,无家可归,时间久了就搞不清到底这块业务逻辑是哪里的;我们现有的Domain Model是一个数据映射对象用来传递数据用的,严格意义是一个DTO对象,大部分的项目都将DTO命名为DomainModel但是其实里面没有任何的行为、方法,只是一个纯粹的数据传输用的容器,所以称不上DomainModel;
所以我们首先要做的就是加入DomainModel,然后逐渐将逻辑搬移到DomainModel中来,在进行逐步的重构、单元测试,让其成为一个可以测试的具有一定核心价值的可重用的DomainModel;
3.统一协调层Application Layer(加入协调层来转换DomainModel)
我们的Service没有Application Layer 也称协调层,专门用来组装业务处理环节的统一调度中心,它并非只是一个简单的静态类;传统三层中没有应用层的概念或者说应用层的概念没扭曲了,或者并没有发挥其的核心作用;我们需要加入应用层来协调DomainModel的工作;
4.从数据扁平结构转换成OO体系结构(使用OO丰富代码结构)
当我们使用DTO对象成功将数据从数据源获取之后,就需要一个对象化的过程,将扁平化的数据实体转换成丰满的领域模型,这个时候所有的领域规则将起作用;
5.DomainModel中的内容(带开关的Specification、SOA化的Specification)
1.实体:
简单理解为OO对象,可以独立存在也可以聚合在某个领域实体下,如果聚合在某个实体下那么只能通过父级实体进行一系列的访问;
2.工厂:
对实体进行有相关约定的创建,这其中包括各种验证、约束、开关等等前提条件。注意:创建实体不像创建数据DTO那么简单;
3.规约、规约工厂:
对业务规则进行对象化,将原本淹没在杂乱无章代码中的核心业务规则提取出来统一管理;这可以很好的像规则配置化(专业称:规则外挂);注意:这可以和我们的业务开关进行合并;最值得惊喜的是可以通过规约工厂来实现面向SOA的规约;
4.领域事件(扩展):
监控、观察等等非侵入式的获取实体在业务处理当中的状态数据,如:发送一封邮件、记录一条LOG,但是这种代码严禁写入业务逻辑层包括分层架构中的任何一个层面,它必须是在一个无关紧要的宿主中进行,类似管道模型的Module;
5.面向特定业务开关:
由于我们每次添加或修改业务逻辑都会加入相应的开关控制,如果这个开关是和业务逻辑相关的那么就可以很巧妙的和规约合并设计;
6.模式、重构、单元测试在领域模型中的运用
设计模式的运用:通过运用DDD就可以方便的对Domain Model进行设计模式的强粒度运用;
重构的运用:对领域模型进行重构就不需要考虑业务逻辑会影响到其他层面;
单元测试的运用:可以独立对领域模型进行测试,包括细粒度的接口抽取都会很方便;
总结:由于时间关系文中都是精简的介绍,具体的理解可以参考我上传的代码示例:http://files.cnblogs.com/wangiqngpei557/3WDDDDemo.zip
.NET应用架构设计—面向查询的领域驱动设计实践(调整传统三层架构,外加维护型的业务开关)的更多相关文章
- 【DDD】领域驱动设计实践 —— 架构风格及架构实例
概述 DDD为复杂软件的设计提供了指导思想,其将易发生变化的业务核心域放置在限定上下文中,在确保核心域一致性和内聚性的基础上,DDD可以被多种语言和多种技术框架实现,具体的框架实现需要根据实际的业务场 ...
- 如何使用ABP进行软件开发(2) 领域驱动设计和三层架构的对比
简述 上一篇简述了ABP框架中的一些基础理论,包括ABP前后端项目的分层结构,以及后端项目中涉及到的知识点,例如DTO,应用服务层,整洁架构,领域对象(如实体,聚合,值对象)等. 笔者也曾经提到,AB ...
- 领域驱动设计(Domain Driven Design)参考架构详解
摘要 本文将介绍领域驱动设计(Domain Driven Design)的官方参考架构,该架构分成了Interfaces.Applications和Domain三层以及包含各类基础设施的Infrast ...
- [转载]领域驱动设计(Domain Driven Design)参考架构详解
摘要 本文将介绍领域驱动设计(Domain Driven Design)的官方参考架构,该架构分成了Interfaces.Applications和Domain三层以及包含各类基础设施的Infrast ...
- 一缕阳光:DDD(领域驱动设计)应对具体业务场景,如何聚焦 Domain Model(领域模型)?
写在前面 阅读目录: 问题根源是什么? <领域驱动设计-软件核心复杂性应对之道>分层概念 Repository(仓储)职责所在? Domain Model(领域模型)重新设计 Domain ...
- (转)EntityFramework之领域驱动设计实践
EntityFramework之领域驱动设计实践 - 前言 EntityFramework之领域驱动设计实践 (一):从DataTable到EntityObject EntityFramework之领 ...
- DDD(领域驱动设计)应对具体业务场景,如何聚焦 Domain Model(领域模型)?
DDD(领域驱动设计)应对具体业务场景,如何聚焦 Domain Model(领域模型)? 阅读目录: 问题根源是什么? <领域驱动设计-软件核心复杂性应对之道>分层概念 Repositor ...
- EntityFramework之领域驱动设计实践
EntityFramework之领域驱动设计实践 - 前言 EntityFramework之领域驱动设计实践 (一):从DataTable到EntityObject EntityFramework之领 ...
- 如何领域驱动设计?-实践感悟&总结分享
主要是在开发过程中,个人对于领域驱动设计的实践感悟和总结:也是对新进开发人员的培训资料:希望对关注DDD的童鞋有所帮助. 概述 领域驱动不是纯粹的技术问题,领域建模(建立数据表只是一部分)是领域专家( ...
随机推荐
- 附录A 编译安装Hadoop
A.1 编译Hadoop A.1.1 搭建环境 第一步安装并设置maven 1. 下载maven安装包 建议安装3.0以上版本(由于Spark2.0编译要求Maven3.3.9及以上版本),本次 ...
- 1Z0-053 争议题目解析330
1Z0-053 争议题目解析330 考试科目:1Z0-053 题库版本:V13.02 题库中原题为: 330.What will be the end result of this set of RM ...
- iOS_UIImage的方向(imageOrientation)
Demo下载地址 一.重现问题: 拍照获得的图片,由于尺寸不对,需要拆切.但是有的图片拆切出来,方向就乱了.查找了一些质量才知道.图片还有个方向属性! imageOrientation. 二.一个图片 ...
- Node.js连接Mysql,并把连接集成进Express中间件中
引言 在node.js连接mysql的过程,我们通常有两种连接方法,普通连接和连接池. 这两种方法较为常见,当我们使用express框架时还会选择使用中间express-myconnection,可以 ...
- Html标签列表【转】
Html标签 Html标签按功能类别排列 基础 标签 描述 <!DOCTYPE> 定义文档类型. <html> 定义 HTML 文档. <title> 定义文档的标 ...
- 深入剖析tomcat之一个简单的web服务器
这个简单的web服务器包含三个类 HttpServer Request Response 在应用程序的入口点,也就是静态main函数中,创建一个HttpServer实例,然后调用其await()方法. ...
- Objective-C 对象(内容根据iOS编程编写)
开发iOS程序需要使用 Objective-C 语言和Cocoa Touch框架.Objective-C 源于 C 语言,是 C 语言的扩展. Cocoa Touch框架是一个Objective-C类 ...
- FPGA的引脚VCCINT 、VCCIO VCCA
首先是看到FPGA在配置的时候有三种不同的电VCCINT .VCCIO VCCA,于是就查了下有什么不同: FPGA一般会有许多引脚,那它们都有什么用呢? VCCINT为施加于 FPGA 内核逻辑的电 ...
- mysql数据库权限及编码
CREATE DATABASE IF NOT EXISTS yourdbname DEFAULT CHARSET utf8 COLLATE utf8_general_ci; 在tigase中,发送消息 ...
- java for循环冒泡排序
int[]a =new int[]{7,19,66,21,88,40}; for(int i=1;i<=a.length-1;i++){ //比总长度减1趟就排好序了.因为每一趟出一个值. fo ...