.项目分析

  在上篇中介绍了什么是"干净架构",DDD符合了这种干净架构的特点,重点描述了DDD架构遵循的依赖倒置原则,使软件达到了低藕合。eShopOnWeb项目是学习DDD领域模型架构的一个很好案例,本篇继续分析该项目各层的职责功能,主要掌握ApplicationCore领域层内部的术语、成员职责。

  1. web层介绍

    eShopOnWeb项目与Equinox项目,双方在表现层方面对比,没有太大区别。都是遵循了DDD表现层的功能职责。有一点差异的是eShopOnWeb把表现层和应用服务层集中在了项目web层下,这并不影响DDD风格架构。

    项目web表现层引用了ApplicationCore领域层和Infrastructure基础设施层,这种引用依赖是正常的。引用Infrastructure层是为了添加EF上下文以及Identity用户管理。 引用ApplicationCore层是为了应用程序服务 调用 领域服务处理领域业务。

    在DDD架构下依赖关系重点强调的是领域层的独立,领域层是同心圆中最核心的层,所以在eShopOnWeb项目中,ApplicationCore层并没有依赖引用项目其它层。再回头看Equinox项目,领域层也不需要依赖引用项目其它层。

    下面web混合了MVC和Razor,结构目录如下所示:

    (1) Health checks 

      Health checks是ASP.NET Core的特性,用于可视化web应用程序的状态,以便开发人员可以确定应用程序是否健康。运行状况检查端点/health。

         //添加服务           services.AddHealthChecks()                .AddCheck<HomePageHealthCheck>("home_page_health_check")                .AddCheck<ApiHealthCheck>("api_health_check");         //添加中间件          app.UseHealthChecks("/health");

       下图检查了web首页和api接口的健康状态,如下图所示

    (2) Extensions

      向现有对象添加辅助方法。该Extensions文件夹有两个类,包含用于电子邮件发送和URL生成的扩展方法。

    (3) 缓存

      对于Web层获取数据库的数据,如果数据不会经常更改,可以使用缓存,避免每次请求页面时,都去读取数据库数据。这里用的是本机内存缓存。

   //缓存接口类private readonly IMemoryCache _cache;// 添加服务,缓存类实现  services.AddScoped<ICatalogViewModelService, CachedCatalogViewModelService>();  //添加服务,非缓存的实现  //services.AddScoped<ICatalogViewModelService, CatalogViewModelService>();
  2. ApplicationCore

    ApplicationCore是领域层,是项目中最重要最复杂的一层。ApplicationCore层包含应用程序的业务逻辑,此业务逻辑包含在领域模型中。领域层知识在Equinox项目中并没有讲清楚,这里在重点解析领域层内部成员,并结合项目来说清楚。

    下面讲解领域层内部的成员职责描述定义,参考了“Microsoft.NET企业级应用架构设计 第二版”。

    领域层内部包括:领域模型和领域服务二大块。涉及到的术语:

  领域模型(模型)

             1)模块

        2)领域实体(也叫"实体")

        3)值对象

        4)聚合

    领域服务(也叫"服务")

    仓储

    下面是领域层主要的成员:

    下面是聚合与领域模型的关系。最终领域模型包含了:聚合、单个实体、值对象的结合。

    (1) 领域模型

      领域模型是提供业务领域的概念视图,它由实体和值对象构成。在下图中Entities文件夹是领域模型,可以看到包含了聚合、实体、值对象。

      1.1 模块

   模块是用来组织领域模型,在.net中领域模型通过命令空间组织,模块也就是命名空间,用来组织类库项目里的类。比如:

namespace Microsoft.eShopWeb.ApplicationCore.Entities.BasketAggregatenamespace Microsoft.eShopWeb.ApplicationCore.Entities.BuyerAggregate

      1.2 实体

  实体通常由数据和行为构成。如果要在整个生命周期的上下文里唯一跟踪它,这个对象就需要一个身份标识(ID主键),并看成实体。 如下所示是一个实体: 

    /// <summary>/// 领域实体都有唯一标识,这里用ID做唯一标识/// </summary>public class BaseEntity    {public int Id { get; set; }    }

/// <summary>/// 领域实体,该实体行为由Basket聚合根来操作/// </summary>public class BasketItem : BaseEntity    {public decimal UnitPrice { get; set; }public int Quantity { get; set; }public int CatalogItemId { get; set; } }

  1.3 值对象

  值对象和实体都由.net 类构成。值对象是包含数据的类,没有行为,可能有方法本质上是辅助方法。值对象不需要身份标识,因为它们不会改变状态。如下所示是一个值对象

  

1.4 聚合

  在开发中单个实体总是互相引用,聚合的作用是把相关逻辑的实体组合当作一个整体对待。聚合是一致性(事务性)的边界,对领域模型进行分组和隔离。聚合是关联的对象(实体)群,放在一个聚合容器中,用于数据更改的目的。每个聚合通常被限制于2~3个对象。聚合根在整个领域模型都可见,而且可以直接引用。   

    在该项目中领域模型与“Microsoft.NET企业级应用架构设计第二版”书中描述的职责有不一样地方,来看一下:

   (1) 领域服务有直接引用聚合中的实体(如:BasketItem)。书中描述是聚合中实体不能从聚合之处直接引用,应用把聚合看成一个整体。

   (2) 领域实体几乎都是贫血模型。书中描述是领域实体应该包括行为和数据。

  (2) 领域服务

   领域服务类方法实现领域逻辑,不属于特定聚合中(聚合是属于领域模型的),很可能跨多个实体。当一块业务逻辑无法融入任何现有聚合,而聚合又无法通过重新设计适应操作时,就需要考虑使用领域服务。下图是领域服务文件夹:

      在该项目与“Microsoft.NET企业级应用架构设计第二版”书中描述的领域服务职责不完全一样,来看一下:

      (1) 项目中,领域服务只是用来执行领域业务逻辑,包括了订单服务OrderService和购物车服务BasketService。书中描述是可能跨多个实体。当一块业务逻辑无法融入任何现有聚合。

     总的来说,eShopOnWeb项目虽然没有完全遵循领域层中,成员职责描述,但可以理解是在代码上简化了领域层的复杂性。

    (3) 仓储

      仓储是协调领域模型和数据映射层的组件。仓储是领域服务中最常见类型,它负责持久化。仓储接口的实现属于基础设施层。仓储通常基于一个IRepository接口。 下面看下项目定义的仓储接口。

    /// <summary>/// T是领域实体,是BaseEntity类型的实体/// </summary>/// <typeparam name="T"></typeparam>public interface IAsyncRepository<T> where T : BaseEntity    {        Task<T> GetByIdAsync(int id);        Task<IReadOnlyList<T>> ListAllAsync();//使用领域规则查询        Task<IReadOnlyList<T>> ListAsync(ISpecification<T> spec);        Task<T> AddAsync(T entity);        Task UpdateAsync(T entity);        Task DeleteAsync(T entity);//使用领域规则查询        Task<int> CountAsync(ISpecification<T> spec);    }

    (4) 领域规则

      在仓储设计查询接口时,可能还会用到领域规则。 在仓储中一般都是定义固定的查询接口,如上面仓储的IAsyncRepository所示。而复杂的查询条件可能需要用到领域规则。在本项目中通过强大Linq 表达式树Expression 来实现动态查询。

    最后Interfaces文件夹中定义的接口,都由基础设施层来实现。如:

     IAppLogger日志接口

     IEmailSender邮件接口

      IAsyncRepository仓储接口

  3.Infrastructure层

    基础设施层Infrastructure依赖于ApplicationCore,这遵循依赖倒置原则(DIP),Infrastructure中代码实现了ApplicationCore中定义的接口(Interfaces文件夹)。该层没有太多要讲的,功能主要包括:使用EF Core进行数据访问、Identity、日志、邮件发送。与Equinox项目的基础设施层差不多,区别多了领域规则。

           领域规则SpecificationEvaluator.cs类用来构建查询表达式(Linq expression),该类返回IQueryable<T>类型。IQueryable接口并不负责查询的实际执行,它所做的只是描述要执行的查询。

 参考资料

    Microsoft.NET企业级应用架构设计 第二版

原文地址:https://www.cnblogs.com/MrHSR/p/10869911.html

.NET社区新闻,深度好文,欢迎访问公众号文章汇总 http://www.csharpkit.com 

结合eShopOnWeb全面认识领域模型架构相关推荐

  1. 领域模型架构 eShopOnWeb项目分析 上

    一.概述 本篇继续探讨web应用架构,讲基于DDD风格下最初的领域模型架构,不同于DDD风格下CQRS架构,二者架构主要区别是领域层的变化. 架构的演变是从领域模型到CQRS,  一开始DDD是用领域 ...

  2. ABP VNext学习日记5

    1.ABP后台模块 解析: [1]Volo.Abp.Threading:提供了一些常用的线程组件,其中AbpTimer就是在里面实现的. [2]Volo.Abp.BackgroundWorkers:后 ...

  3. 项目架构之传统三层架构和领域模型三层架构

    一.架构之传统三层架构 传统三层架构是一种软件架构,是一种典型的.基于贫血模型的.面向过程的JavaWeb分层方式.该架构分为以下三个层次: 数据访问层(DAL - Data Access Layer ...

  4. mysql 三层架构开发_从三层架构迈向领域驱动设计(转载)

    三层架构 严格分层架构模式的特点是上层只能访问相邻的下层,其他层次间的调用都不允许.三层架构就是一种严格分层模式,它把职责划分为界面展示.业务逻辑.数据访问三层,还有一个业务实体,前面三层都要依赖它, ...

  5. CQRS架构下Equinox开源项目分析

    一.DDD分层架构介绍 本篇分析CQRS架构下的Equinox开源项目.该项目在github上star占有2.4k.便决定分析Equinox项目来学习下CQRS架构.再讲CQRS架构时,先简述下DDD ...

  6. 企业信息系统架构要点

    企业信息系统架构要点 前言 前几天我和一个人聊天,我说我做了多年管理软件,那他就问我有什么心得,呵呵,当时我说了一些但感觉没有说好,所以今天我总结一下.这个总结既不是曾经项目的总结,也不会是将来某个项 ...

  7. 用Transformer定义所有ML模型,特斯拉AI总监Karpathy发推感叹AI融合趋势

    来源:机器之心 本文约1700字,建议阅读5分钟 特斯拉 AI 总监 Andrej Karpathy 连发多条推文表示,AI 不同领域(视觉.语音.自然语言等)正在打通,融合速度令人惊叹. 近日,特斯 ...

  8. 用Transformer定义所有AI模型!特斯拉AI总监Karpathy发推感叹AI融合趋势

    点击上方"AI遇见机器学习",选择"星标"公众号 重磅干货,第一时间送达 来源 | CVer 特斯拉 AI 总监 Andrej Karpathy 连发多条推文表 ...

  9. 软件架构最佳实践和案例分析

    软件架构是软件业的一个重要研究领域,正受到越来越多的关注,其地位也日益明显地体现出来.而架构设计师--也就成为软件系统的最高设计者.此课程就是为有志成为卓越架构师的人准备的培训课程.作为架构设计师,需 ...

最新文章

  1. 百度的卡尔曼滤波的解释
  2. centos环境变量设置
  3. SpringMVC、Spring和Struts的区别
  4. PyCharm修改镜像源无用?
  5. sql 执行顺序_10个简单步骤,完全理解SQL
  6. DLL动态链接库的工作原理
  7. Android adb.exe程序启动不起来,如何处理
  8. nb-iot链路层加密_Google为低端Android手机和IoT设备创建了更快的加密
  9. (转) RabbitMQ学习之spring整合发送异步消息
  10. Protobuf3详细介绍
  11. matlab在遥感数字图像处理方面的应用
  12. 《深入分析Java Web技术内幕》读书笔记
  13. SQL注入攻击与防御
  14. 【备忘】mysql优化工具
  15. 现代控制理论(机器人方向)习题与实践补充资料和复习说明(2019版)
  16. Amigo学习(一)解决使用中遇到的问题
  17. 正方教务系统连接服务器失败,模拟登陆正方教务系统,重定向一直解决不了〉...
  18. C#实现调用打印机(打印字符串、打印绘图、打印图片),还差打印水晶报表
  19. 颠覆IoT行业的开发神器!涂鸦智能重磅推出TuyaOS操作系统【程序员必备】
  20. 联想计算机管理员权限设置,管理员身份运行,详细教您如何设置以管理员身份运行程序...

热门文章

  1. 如何在Windows上设置BitLocker加密
  2. 如何在Windows 8中将旧控制面板添加到Metro Start屏幕
  3. yii---where or该如何使用
  4. 16-djongo中间件学习
  5. 016-Spring Boot JDBC
  6. nginx php 配置
  7. ubuntu下mysql-python模块的安装
  8. .NET 6新特性试用 | ArgumentNullException卫语句
  9. 如何用 Linq 进行多重 Orderby ?
  10. 前端老弟第一次写后端,崩了!