一、编排业务逻辑的模式
1. 事务脚本模式TS(The Transaction Script pattern )

  • TS模式概述

    TS 鼓励你跳过任何的面向对象的设计,你直接到所需的用户操作的业务组件映射。专注于的业务用户可以通过表示层完成,并为每个请求编写方法。这个方法被称之为事务脚本,此处事务通常是指想要进行商业交易,脚本是指系统中的一系列关系用户操作的系统操作。

    TS历时多年仍然不过时的原因只有一个:它基于推行可视化的业务逻辑设计,而可视化正上用户体验的核心。

    在TS中,每个用户操作都在上下文的物理事务边界中完成。不同于数据访问层的数据执行脚本,TS的数据访问通常被封装在数据个组件中。按照设计,TS不包含使用面向对象设计。TS中的任务逻辑都是If,while,for等组成。

  • TS模式实际应用

    在实现中每个TS都是一个单独的,可能表现为一个类的静态方法,可以在每个类自己执行TS。当你这样做的时候,就已经完美演绎了命令模式。

    命令模式的主要设计思想是用一个对象来表示动作。命令对象封装一个动作和它所有的参数。典型的,命令对象公开的标准接口,以便调用方可以调用任何命令,而无需关注命令类的具体行为。如:

public interface IApplicationCommand

{

    int Run();

}

 

public class BookHotelRoom : IApplicationCommand

{

    Customer _guest;

    DateTime _checkIn, _checkOut;

    String _confirmationNumber;

    // other internal members 

 

    public BookHotelRoom(Customer guest, DateTime checkIn, DateTime checkOut)

    {

        _guest = guest;

        _checkIn = checkIn;

        _checkOut = checkOut;

    }

    public String ConfirmationNumber

    {

        get { return _confirmationNumber; }

    }

 

    public int Run()

    {

        // Start the transaction  

        // Check room availability for requested stay 

        // Check customer information?(already guest, payment method, preferences) 

        // Calculate room rate  

        // Add a new record to the Bookings database table 

        // Generate the confirmation number 

        // Commit the transaction???????  

        // E-mail the customer 

        // Store the confirmation number to the local member _confirmationNumber 

    } 

 

    ...  

}

TS模式不对任务数据设计权限,不也会对数据做任何转换。它只用用于接收和发送数据,所以通常的做法是使用数据类(Dto)来传递数据。

 

2. 域模型模式(The Domain Model pattern)

域模型(DM)通常在DDD设计中使用,但也不局限于它。DM也是一个常用的设计模式,它让架构师侧重于系统的预期行为和运行时的数据流。

  • DM模式概述

    域模型是不同于对象模型的一系列集合。域模型忠实于表示业务领域,特别是域内进程的数据流。

  • DM模式实际应用

    域模型是一系列表示业务领域的plain old classes。这些类是数据容器,可以表现为属性也可以是方法。The term POCO (Plain Old CLR Object)通常指这些域模型。

    实际使用我们不关注类本身,关注的是行为和事件。这些行为能帮助你理解在类上发生了什么。着眼于行为比着眼于类属性更有用,另一方面看来,这就是Tell-Don't-Ask原则的体现。

    有些时候域模型需要被持久化,而持久化不是域模型的职责,持久化将在基础结构层才能被实现。从应用程序看来域模型是业务逻辑数据库,不依赖任何接口,而持久化依赖接口,使用关系模型来持久化。域模型和关系模型通常要通过ORM工具来完成,如Microsoft's Entity Framework 和 NHibernate

 
 

3.反域模式ADM(The Anemic Domain Model (anti-)pattern)

 域模式的核心于对象关联的行为,"行为先行"是违背域模型设计原则的,所以产生了另外一种模式,反域模式(ADM)。

  • ADM概述

    ADM域模型中,所有对象仍然都遵循命名约定的真实世界域实体、 实体之间的关系仍存在,和模型的整体结构紧密匹配的真实域空间。没有行为,只有属性的实体。

    ADM模式建议不要在域对象里放任何逻辑。所有的逻辑都被放在逻辑领域的服务组件里。这此服务是域模型的消费者,并且有存储和持久化的功能。

  ■ Analysis leads to objects that closely model the domain space and are tailored to the real 

needs 

  ■ The strong domain perspective of things reduces the risk of misunderstandings between the 

domain experts and the development team 

  ■ Code is likely to become more readable and easily understandable 

  ■ The fnal result has more chances to really be close to expectations.

 

二、将关注点从数据转移到任务

1. Asp.net Mvc中的任务

    用户行为最终被实现为controller类中的一个方法调用。controller应该是被用来组织任务的首选。抽象的说,Contrller与WebForm中的postback事件没有区别。在这两个方法中,聪明的开发人员都会为了避免web form中的完整的事件执行而选择使用Controller。

  • Controller是一个协调者

    Responsibility-Driven Design (RDD)职责驱动设计由Rebecca Wirfs-Brock 和Alan McKean提出:Roles, Responsibilities, and Collaborations。RDD的本质是将系统分解成一系统可执行的Action动作,然后每个action被映射到一个组件类。执行action被设计成组件类的职责。组件的解决依赖于它设定的职责。

    Asp.net mvc 的controller是RDD模式的一个生动的实现,RDD协调者建议将action分组到一系统application services中,由controller 调用services来执行action返回view model

public ActionResult PlaceOrder(OrderInputModel orderInfo) 

    // Input data already mapped thanks to the model binding  

    // infrastructure of ASP.NET MVC 

 

    // Perform the task invoking a application service and 

    // get a view model back from application layer 

    var service = new OrderService(); 

    var model = service.PlaceOrder(); 

 

    // Invoke next view 

    return View(model); 

}

 

controller负责展现层和应用层的协调调用,这种情况下如果需要不同的展现层,可以用以下代码轻松实现:

var service = new OrderService(); 

var model = service.PlaceOrder(); 

 

// Adapt to the new view model 

var newFrontendModel = someAdapter.NewViewModel(response);  

 

  • 连接应用层和展现层 Connecting the application and presentation layers

    应用层和展现层的连接点是controller,使用依赖倒置模式Ioc容器如microsoft unity来重写asp.net mvc的controller factory:

var factory = new UnityControllerFactory(); 

ControllerBuilder.Current.SetControllerFactory(factory);

 

UnityControllerFactory实现如下:

public class UnityControllerFactory : DefaultControllerFactory 

   public static IUnityContainer Container { get; private set; } 

   public UnityControllerFactory() 

   { 

      Container = new UnityContainer();   // Initialize the IoC 

      Container.LoadConfiguration();      // Configure it reading details from web.config 

   } 

   protected override IController GetControllerInstance(RequestContext context, Type type) 

   { 

       if (type == null)  return null; 

       return Container.Resolve(type) as IController; 

   } 

}

然后每个controller类的默认构造函数要改成如下:

public class HomeController 

    private IHomeService _service; 

    public HomeController(IHomeService service) 

    { 

       _service = service; 

    } 

    ... 

}

    You can use the Unity Mvc library available as a NuGet package  For more  information,  see http://github com/feedbackhound/Unity Mvc5 

    
 

 

  • 连接应用层和数据访问层 Connecting the application and data-access layers

    同样的问题存在于数应用层和基础架构层的数据访问。使用相同的方法——依赖注入。在域模型场景中的数据访问逻辑容器通常被命名为repository

public class HomeService 

    private ISomeEntityRepository _someEntityRepo; 

    public HomeService(ISomeEntityRepository repo) 

    { 

       _someEntityRepo = repo; 

    } 

    ... 

}

有意思的是,你不需要在代码中修改初始化controller来设置factory,你只要确保仓储类型和接口都映射到Ioc容器里就可以。所有Ioc容器都提供配置和api两方式来映射类型。所以不需要再通过代码来配置,现在的IoC容器都提供了这种透明的方式来解决依赖关系。如果你通知IoC容器获取一个Controller类型,这个controller类型依赖一些Application Services类型,反过来,Services类型又依赖一个或多个仓储类型,所有这些代码都在一行代码里解决。

    层与层之间的连接通信建议使用依赖注入实现,但它不是唯一的解决方案。如果你有多个层在同一个进程空间内,比较简单的方法是直接并且本地实例化对象,不论他们在application layers、servces layers或是respositories layers. 缺点就是他们会在层之间产生高偶合。

// Tight coupling between the class OrderService  

// and the class that contains this code 

var service = new OrderService(); 

var model = service.PlaceOrder();

 

2. 编排域内的任务

    通常、应用程序的逻辑层包含了任务编排、域逻辑和一些其它的东西。

  • 跨实体域逻辑

    域名服务通常包含业多个域实体操作的业务逻辑。大多情况下,域名服务是复杂、 多步的操作,都在域的边界内进行,并有可能是基础设施层(infrastructure)。典型的例子是OrderProcessor, BestPriceFinder, 或GoldCustomerEvaluator这样的域服务。服务的命名以功能命名,并且可以让领域专家和相关人员容易理解。

 

三、跨边界传递数据

    表示层物理边界跨界,无论是进程跨界还是物理计算机跨界都是一项很昂贵的操作。访问一个远程计算机的效率可能要比进程内通信慢100倍。

1.层架构间的数据流

    下图表示分层架构一个抽象的数据流。当执行一个命令执行时,数据流从用户接口以一个input model形势进入应用层。鉴于这个请求动作,应用程序层需要一系列用来做为input model的域模型实例。在一个领域分层系统中,持久性特指将转换成物理模型,妈实体关系模型(relational-data model),在返回结果时将data mode再转换为demain model。

 

 

理论上讲,一个分层的系统由上图的4种逻辑分离的model组成,但在有的情况下他们是一致的。data model通常与demain model在基础设施层是一致的。在Asp.net mvc应用程序中,input model与output model通常是同一个model。

  • 共享域模型实体(Sharing the Domain Model entities)

在遵循域模型配置设计的架构中,域实体与数据紧密相关,推荐将域模型向表示层冒泡,并且在必要的时候将他们序列化来传输。

 

  • 使用数据传输对象

在一个解决方案中很少能让一个实满足整个系统的需要,毕竟不同的层可能对数据要求不一样。有些情况下,为了便捷使在所有层中都使用了demain model,有些情况下需要使用Dto类,总之、跟据你的需要。

  •     Dto对象概述(data-transfer object)

    Dto被设计为用来做物理层之间的数据载体。Dto类只有属性,没有行为。Dto原生可以被序列化,在远程组件调用中通常这样做。

 

  • DTOs 与. domain entities区别

典型的DTO使用如:显示和处理一个自定义订单。在处理订单时需要大量的数据,显示数据时只需要简单少量数据。DTO增加了层次的复杂度,但是减少了容器的复杂度。

 

 

  • AutoMapper 和适配器

    Data model 与DTO之是可以通过AutoMapper适配器完成自动转换。

Mapper.CreateMap<YourSourceType, YourDtoType>();

Once a mapping is defned, you invoke it via the Map method:

var dto = Mapper.Map<YourDtoType>(sourceObject);

 

 

 

 

.net架构设计读书笔记--第二章 第7节 神化般的业务层的更多相关文章

  1. .net架构设计读书笔记--第二章 设计体系结构

    第五节 探索领域架构 一.领域驱动设计的价值与意义 最初在java中使用,.net要晚些才引入.领域驱动设计出现之初的争议.一个向导,少走弯路   1. 我们真的需要DDD吗? DDD并不适用于每个软 ...

  2. .net架构设计读书笔记--第一章 基础

    第一章 基础 第一节 软件架构与软件架构师  简单的说软件架构即是为客户构建一个软件系统.架构师随便软件架构应运而生,架构师是一个角色. 2000年9月ANSI和IEEE发布了<密集性软件架构建 ...

  3. .net架构设计读书笔记--第三章 第8节 域模型简介(Introducing Domain Model)

    一.数据--行为转变     很长的时间,典型的分析方法或多或少是以下两种,第一,收集需求并做一些分析,找出有关实体 (例如,客户. 订单. 产品) 和进程来实现. 第二,手持这种理解你尝试推断一个物 ...

  4. STL源码分析读书笔记--第二章--空间配置器(allocator)

    声明:侯捷先生的STL源码剖析第二章个人感觉讲得蛮乱的,而且跟第三章有关,建议看完第三章再看第二章,网上有人上传了一篇读书笔记,觉得这个读书笔记的内容和编排还不错,我的这篇总结基本就延续了该读书笔记的 ...

  5. Spring 3.x 实践 第一个例子(Spring 3.x 企业应用开发实战读书笔记第二章)

    前言:工作之后一直在搞android,现在需要更多和后台的人员交涉,技术栈不一样,难免鸡同鸭讲,所以稍稍学习下. 这个例子取自于<Spring 3.x 企业应用开发实战>一书中的第二章,I ...

  6. Getting Started With Hazelcast 读书笔记(第二章、第三章)

    第二章 起步 本章就相当简单粗暴了,用一个个例子说明hazelcast怎么用. 1.map,set,list这些集合类都是开箱即用的,只要从Hazelcast的实例中获取一份就行. 2.增加了Mult ...

  7. Java Concurrency in Practice 读书笔记 第二章

    第二章的思维导图(代码迟点补上):

  8. javascript 数据结构和算法读书笔记 > 第二章 数组

    这章主要讲解了数组的工作原理和其适用场景. 定义: 一个存储元素的线性集合,元素可以通过索引来任意存取,索引通常是数字,用来计算元素之间存储位置的偏移量. javascript数组的特殊之处: jav ...

  9. 《C++ Primer》读书笔记—第二章 变量和基本类型

    声明: 文中内容收集整理自<C++ Primer 中文版 (第5版)>,版权归原书所有. 学习一门程序设计语言最好的方法就是练习编程. 1.8比特的char类型计算机表示的实际范围是-12 ...

随机推荐

  1. docker-containerd 启动流程分析

    一般在docker启动时,containerd的启动命令如下所示: root 2090 0.0 0.1 292780 11008 ? Ssl 10月22 0:12 docker-containerd ...

  2. POJ 2387 Til the Cows Come Home --最短路模板题

    Dijkstra模板题,也可以用Floyd算法. 关于Dijkstra算法有两种写法,只有一点细节不同,思想是一样的. 写法1: #include <iostream> #include ...

  3. 数据结构Java实现05----栈:顺序栈和链式堆栈

    一.堆栈的基本概念: 堆栈(也简称作栈)是一种特殊的线性表,堆栈的数据元素以及数据元素间的逻辑关系和线性表完全相同,其差别是线性表允许在任意位置进行插入和删除操作,而堆栈只允许在固定一端进行插入和删除 ...

  4. mac和centos下git安装

    mac下面的git安装,这篇文章写的很详细了http://www.cnblogs.com/ccdev/archive/2012/09/12/2682098.html 谈谈centos下的安装.我用的是 ...

  5. GitHub入门之二 参与一个项目编写

    接上文:大多数时候我们也需要把别人的代码进行整合和修改,而不是简单的修改,这时就需要对一个项目进行修改. 注意,本系列文章主要说明在github网站上的操作,更多高级操作请使用git控制台 一.for ...

  6. AFN框架基本使用

    0.AFN框架基本使用 0.1 AFN内部结构 AFN结构体 - NSURLConnection + AFURLConnectionOperation(已经被废弃) + AFHTTPRequestOp ...

  7. 19Spring_AOP编程(AspectJ)_使用@Pointcut注解来定义切点

    我们之前的方式是采用 @AfterReturning(value="execution(* com.guigu.shen.anotion.UserDaoImpl.*(..))",r ...

  8. ping提示小结

    1,Win7 ping 不存在的地址(请求超时) 因为路由器不理睬他. 2,R1-R2-R3 R1有默认路由,R1 ping不存在的地址(目标不可达) 3,R1-R2 R1ping本网段中不存在的地址 ...

  9. 图像相似度算法的C#实现及测评

    近日逛博客的时候偶然发现了一个有关图片相似度的Python算法实现.想着很有意思便搬到C#上来了,给大家看看. 闲言碎语 才疏学浅,只把计算图像相似度的一个基本算法的基本实现方式给罗列了出来,以至于在 ...

  10. 存储过程中执行动态Sql语句

    MSSQL为我们提供了两种动态执行SQL语句的命令,分别是EXEC和sp_executesql;通常,sp_executesql则更具有优势,它提供了输入输出接口,而EXEC没有.还有一个最大的好处就 ...