基于DDD的.NET开发框架 - ABP分层设计
ABP是“ASP.NET Boilerplate Project (ASP.NET样板项目)”的简称。
ASP.NET Boilerplate是一个用最佳实践和流行技术开发现代WEB应用程序的新起点,它旨在成为一个通用的WEB应用程序框架和项目模板。
ABP的官方网站:http://www.aspnetboilerplate.com
ABP官方文档:http://www.aspnetboilerplate.com/Pages/Documents
Github上的开源项目:https://github.com/aspnetboilerplate
一、为什么要分层
分层架构是所有架构的鼻祖,分层的作用就是隔离,不过,我们有时候有个误解,就是把层和程序集对应起来,就比如简单三层架构中,在你的解决方案中,一般会有三个程序集项目:XXUI.dll、XXBLL.dll 和 XXDAL.dll,然后把这三个程序集看成一个层,这没什么不可以,但当项目复杂的时候,如果还按照这种方式的话,你的程序集中的文件夹会越来越多,程序集也会越来越大。当你的视野跳出这个程序集的概念后,你会发现,层不只是和程序集对应,也和解决方案文件夹,或者是整个解决方案对应,一个层甚至可以对应一个系统。
分层的目的即为了“高内聚低耦合”的思想。
二、微软经典的三层架构
任何一个.net都知道的微软的三层架构,三层架构就是把业务划分为界面层(User Interface layer)、业务逻辑层(Business Logic Layer)、数据访问层(Data access layer)。如下图
各层的作用:
界面层(UI):主要表示WEB方式,也可以表示成WINFORM方式;如果逻辑层相当强大和完善,无论表现层如何定义和更改,逻辑层都能完善地提供服务。主要对用户的请求接受,以及数据的返回。
业务逻辑层(BLL):主要是针对具体的问题的操作,也可以理解成对数据层的操作,对数据业务逻辑处理,如果说数据层是积木,那逻辑层就是对这些积木的搭建。
数据访问层(DAL):主要看数据层里面有没有包含逻辑处理,实际上它的各个函数主要完成各个对数据文件的操作。而不必管其他操作。
在开发人员眼里,一个业务系统的分层只是技术架构上的,所以会把日志纪录、权限管理、数据库持久化、消息服务等等,把一些能分离出来的尽量分离出来,然后再把这些东西组合起来,就成了系统帮助层,它们贯彻于整个业务系统。
三层架构是典型事务脚本逻辑结构,一个复杂的业务都在BBL方法体中从头到尾描述,处理高度复杂的业务显得无能为力!!!
估计所有的.NET 程序员都是从这个经典的三层的架构一步一步走过来的。
三、DDD经典分层
DDD:领域驱动设计
TDD:是测试驱动开发
POEAA:企业应用架构模式
DDD核心思想是由业务问题来控制解决方案的形式从以数据库为中心过渡到领域模型为中心
下面这个图是我在《领域驱动设计与模式实战》书中拍下来的,他完全诠释DDD的经典分层。
各层概念:
表现层(Presentation Layer):图中的用户界面层包括用户接口层,用户输入和数据展示。
应用层(Application Layer):应用层定义系统的业务功能,并指挥领域层中的领域对象实现这些功能。
领域层(Domain Layer):核心层,实现所有业务逻辑。
基础设施层(Infrastructure Layer):提供整个业务系统的基础服务。
各层在编译时的类依赖关系如下图(这是一个很矮矬穷的图):
高层模块不应该依赖于底层模块,两者都应该依赖于抽象
抽象不应该依赖于细节,细节应该依赖于抽象。
四、ABP分层
上节FirstABP的解决方案:
ABP详细分层:
我们从上到下看看都是什么意思:
表示层
Presentation:
View Models (Javascript):=
Views (HTML/CSS):=
Localization, Navigation, Notifications:多语言,菜单,通知
web:
Web API Controllers:webapi接口
MVC Controllers, OData:OData是oData是构建restful服务的标准。(懒得安分指出)
应用层(Application)
Application Services:应用服务
DTOs:数据传输对象
DTO Mappers:AutoMapper进行实体与DTO之间的映射
Authorization:参数验证
Session:
Audit Logging:审计日志
应用层提供一些应用服务(Application Services)方法供展现层调用。一个应用服务方法接收一个DTO(数据传输对象)作为输入参数,使用这个输入参数执行特定的领域层操作,并根据需要可返回另一个DTO。在展现层到领域层之间,不应该接收或返回实体(Entity)对象,应该进行DTO映射。一个应用服务方法通常被认为是一个工作单元(Unit of Work)。用户输入参数的验证工作也应该在应用层实现。ABP提供了一个基础架构让我们很容易地实现输入参数有效性验证。建议使用一种像AutoMapper这样的工具来进行实体与DTO之间的映射。
领域层(Domain(Core))
Entities:实体,领域对象,代表业务领域的数据和操作
value objects:实体模型
Repositories:仓储,用来操作数据库进行数据存取。仓储接口在领域层定义,而仓储的实现类应该写在基础设施层。
Domain Services:领域服务,当处理的业务规则跨越两个(及以上)实体时,应该写在领域服务方法里面。
Domain Event:领域事件,在领域层某些特定情况发生时可以触发领域事件,并且在相应地方捕获并处理它们。
Unit of Work:工作单元,一种设计模式,用于维护一个由已经被修改(如增加、删除和更新等)的业务对象组成的列表。它负责协调这些业务对象的持久化工作及并发问题。
基础设施(Infrastructure)
ORM (EntityFramework, NHibernate):ORM框架,ABP提供了EF和NHibernate支持
DB Migrations:EF Code First创建数据库用的
Background Jobs:作业调度和自动任务,(类似Quartz.NET)
补充(单页面应用和多页面应用)
在单页面应用中(SPA),所有的资源都会一次性加载到客户端(或者只加载核心资源,懒加载其他资源),所有的后续和服务器的交互都是通过Ajax调用。Html代码是使用从服务端接收到的数据在客户端生成的。整个页面不会刷新,视图只是在必要时换入换出。有许多的Javascript SPA框架,比如AngularJs,DurandalJs,BackboneJs和EmberJs。ABP可以使用它们中的任何一个,但是提供了使用 AngularJs和DurandalJs的样例。
在多页面(经典)应用中(MPA),客户端向服务端发送请求,服务端代码(ASP.NET MVC 控制器)从数据库中获取数据,然后Razor视图引擎生成html 代码。这些编译后的页面发回给客户端显示。每个新的页面都会导致完整页面的刷新。
SPA和MPA涉及了完全不同的架构。对于后台管理系统来说,SPA是最好的候选者,另一方面,博客更适合MPA模型,因为博客渴望被搜索引擎抓取数据。虽然有很多工具可以使SPA对于搜索引擎可见,但是目前的一般做法就是使用MPA。
最后
ABP平衡了一些最好的框架或者类库,除此之外,ABP自己的类和系统也提供了一个很好的用于N层架构Web应用构建的基础设施,也提供了很轻松地创建分层的解决方案的模板,用作应用的起点。
根据分层我们把项目的类库用解决方案的文件夹整理下: