虽然每天的工作都是CURD、还是使用着传统的三层架构、使用着.net Framework,但是这并不能影响我学习DDD和.net core。

总是希望软件在应对复杂多变的场景时能够游刃有余,在解决问题时能够多一种选择。

很早就有关注大神dax.netNLayerApp系列博文https://www.cnblogs.com/daxnet/category/304141.html

近期入坑.net core,看了进击的辣条的文章Asp.Net Core微服务初体验,很有收获,感谢感谢。

抽时间读了下NLayerAppV3项目的源码,Github地址:https://github.com/cesarcastrocuba/nlayerappv3

分享下体会,希望相互交流学习,谢谢!

1、项目简介

NLayerAppV3是一个使用.net 2.1实现的经典DDD的分层架构的项目。

NLayerAppV3是在NLayerAppV2的基础上,使用.net core2.1进行重新构建的;它包含了开发人员和架构师都可以重用的DDD层;以银行和博客上下文示例。

2、项目结构

放一张DDD风格架构l图。主要分为四层:表现层、应用层、领域层和基础结构层。

详细的各层的含义可以查看dax.net的文章https://www.cnblogs.com/daxnet/archive/2011/05/10/2042095.html

1.1-Presentation(表现层)

系统和用户的交互层。UI展示给终端用户、收集用户的反馈信息。

1.2-Distributed Services(分布式服务层)

为应用程序提供远程访问;如果是http协议,一般设计为WebApi。

1.2.1-Seedwork --DistributedServices.Seedwork

分布式服务的Controller、Filter等

1.2.2-MainBoundedContext

--DistributedServices.MainBoundedContext

以银行的业务示例,构建上下文、对外提供WebApi服务,结合Swagger UI

--DistributedServices.MainBoundedContext.Tests

DistributedServices.MainBoundedContext的测试项目

1.2.3-BlogContext

--DistributedServices.BlogBoundedContext

以博客业务示例,构建上下文,对外提供WebApi服务,结合Swagger UI

--DistributedServices.BlogBoundedContext.Tests

DistributedServices.BlogBoundedContext项目的测试项目

1.3-Application(应用层)

协调领域模型与其它应用、包括事务调度、UOW、数据转换等。

主要作用:通过仓储来访问持久层;对不同领域的数据组织整理;协调领域对象之间、领域对象与基础层的协作关系;应用服务等

1.3.1-Seedwork --Application.Seedwork

应用层共用接口、实现的封装

1.3.2-MainBoundedContext

--Application.MainBoundedContext

业务模块的应用层服务接口和实现

--Application.MainBoundedContext.DTO

应用层业务模块的数据转换等

--Application.MainBoundedContext.Tests

Application.MainBoundedContext的测试项目

1.3.3-BlogBoundedContext

同1.3.2,不同的是业务换为博客业务

1.4-Domain(领域层)

展现业务/领域逻辑、业务处理状态,以及实现业务规则,它同时也包含了领域对象的状态信息。

1.4.1-Seedwork

--Domain.Seedwork

领域层实体基类、仓储接口、UOW接口、值对象基类、规约等

--Domain.Seedwork.Tests

Domain.Seedwork的测试项目

1.4.2-MainBoundedContext

--Domain.MainBoundedContext

实体、值对象、领域服务、聚合根、聚合及工厂

--Domain.MainBoundedContext.Tests

Domain.MainBoundedContext的测试项目

1.4.3-BlogBoundedContext

同1.4.2 业务逻辑换成了博客

1.5-Infrastructure(基础设施层)

1.5.1-Data  

为应用程序的数据存取提供服务,它可以是应用程序本身的持久化机制,也可以是外部系统提供的数据访问的Web Service等

--Infrastructure.Data.Seedwork

UOW的实现基类、仓储的实现基类

--Infrastructure.Data.MainBoundedContext

UOW的实现、仓储的实现

--Infrastructure.Data.MainBoundedContext.Tests

Infrastructure.Data.MainBoundedContext的测试项目

1.5.2-CrossCutting 

该层提供了能被其它各层访问的通用技术框架,比如异常捕获与处理、日志、认证、授权、验证、跟踪、监视、缓存等等。

--Infrastructure.Crosscutting

适配器、国际化、验证等接口的封装

--Infrastructure.Crosscutting.NetFramework

适配器、国际化、验证等实现、国际化依赖的资源

--Infrastructure.Crosscutting.Tests

Infrastructure.Crosscutting的测试项目

3、示例

以DistributedServices.MainBoundedContext项目的BankAccounts的转账api示例,说明下我的理解

  1. [HttpPut]
  2. public void PerformTransfer([FromBody]BankAccountDTO from, [FromBody]BankAccountDTO to, [FromBody]decimal amount)
  3. {
  4. _bankAppService.PerformBankTransfer(from, to, amount);
  5. }

_bankAppService通过构造函数注入。

  1. readonly IBankAppService _bankAppService;
  2.  
  3. public BankAccounts(IBankAppService bankAppService)
  4. {
  5. _bankAppService = bankAppService;
  6. }

IBankAppService是应用层的服务接口

对应的应用层有接口的实现BankAppService

  1. public BankAppService(IBankAccountRepository bankAccountRepository, // the bank account repository dependency
  2. ICustomerRepository customerRepository, // the customer repository dependency
  3. IBankTransferService transferService,
  4. ILogger<BankAppService> logger)
  5. {
  6. //check preconditions
  7. if (bankAccountRepository == null)
  8. throw new ArgumentNullException("bankAccountRepository");
  9.  
  10. if (customerRepository == null)
  11. throw new ArgumentNullException("customerRepository");
  12.  
  13. if (transferService == null)
  14. throw new ArgumentNullException("trasferService");
  15.  
  16. _bankAccountRepository = bankAccountRepository;
  17. _customerRepository = customerRepository;
  18. _transferService = transferService;
  19.  
  20. _logger = logger;
  21. _resources = LocalizationFactory.CreateLocalResources();
  22.  
  23. }

BankAppService通过构造函数注入了领域层的银行账号仓储IBankAccountRepository和客户仓储ICustomerRepository、转账服务等,全部依赖于接口。

  1. public void PerformBankTransfer(BankAccountDTO fromAccount, BankAccountDTO toAccount, decimal amount)
  2. {
  3. //Application-Logic Process:
  4. // 1º Get Accounts objects from Repositories
  5. // 2º Start Transaction
  6. // 3º Call PerformTransfer method in Domain Service
  7. // 4º If no exceptions, commit the unit of work and complete transaction
  8.  
  9. if (BankAccountHasIdentity(fromAccount)
  10. &&
  11. BankAccountHasIdentity(toAccount))
  12. {
  13. var source = _bankAccountRepository.Get(fromAccount.Id);
  14. var target = _bankAccountRepository.Get(toAccount.Id);
  15.  
  16. if (source != null & target != null) // if all accounts exist
  17. {
  18. using (TransactionScope scope = new TransactionScope())
  19. {
  20. //perform transfer
  21. _transferService.PerformTransfer(amount, source, target);
  22.  
  23. //comit unit of work
  24. _bankAccountRepository.UnitOfWork.Commit();
  25.  
  26. //complete transaction
  27. scope.Complete();
  28. }
  29. }
  30. else
  31. _logger.LogError(_resources.GetStringResource(LocalizationKeys.Application.error_CannotPerformTransferInvalidAccounts));
  32. }
  33. else
  34. _logger.LogError(_resources.GetStringResource(LocalizationKeys.Application.error_CannotPerformTransferInvalidAccounts));
  35.  
  36. }

实现转账的功能,输入参数都是Dto对象,通过AutoMapper或者其它映射工具完成数据转换;通过仓储访问聚合,获取源和目标账号信息、开启事务,UOW提交转账操作。

DistributedServices.MainBoundedContext的StartUp中注册IOC

仓储、领域服务、应用层服务、适配器、国际化、验证、Swagger UI等。

运行项目

在DistributedServices.MainBoundedContext目录下打开cmd命令,输入dotnet restore,完成之后,输入dotnet run

运行结果:

4、想法和计划

跟.net core microservice结合

使用ocelot搭建服务网关、结合identityserver4实现授权认证;polly服务熔断;限流;consul服务发现;Appolo配置中心;Skywalking追踪结果。

NLayerAppV3--.net Core2实现的DDD分层架构的更多相关文章

  1. 应用程序框架实战十八:DDD分层架构之聚合

    前面已经介绍了DDD分层架构的实体和值对象,本文将介绍聚合以及与其高度相关的并发主题. 我在之前已经说过,初学者第一步需要将业务逻辑尽量放到实体或值对象中,给实体“充血”,这样可以让业务逻辑高度内聚, ...

  2. 应用程序框架实战十七:DDD分层架构之值对象(层超类型篇)

    上一篇介绍了值对象的基本概念,得到了一些朋友的支持,另外也有一些朋友提出了不同意见.这其实是很自然的事情,设计本来就充满了各种可能性,没有绝对正确的做法,只有更好的实践.但是设计与实践的好与坏,对于不 ...

  3. 应用程序框架实战十六:DDD分层架构之值对象(介绍篇)

    前面介绍了DDD分层架构的实体,并完成了实体层超类型的开发,同时提供了验证方面的支持.本篇将介绍另一个重要的构造块——值对象,它是聚合中的主要成分. 如果说你已经在使用DDD分层架构,但你却从来没有使 ...

  4. 应用程序框架实战十五:DDD分层架构之领域实体(验证篇)

    在应用程序框架实战十四:DDD分层架构之领域实体(基础篇)一文中,我介绍了领域实体的基础,包括标识.相等性比较.输出实体状态等.本文将介绍领域实体的一个核心内容——验证,它是应用程序健壮性的基石.为了 ...

  5. 应用程序框架实战十四:DDD分层架构之领域实体(基础篇)

    上一篇,我介绍了自己在DDD分层架构方面的一些感想,本文开始介绍领域层的实体,代码主要参考自<领域驱动设计C#2008实现>,另外参考了网上找到的一些示例代码. 什么是实体 由标识来区分的 ...

  6. 应用程序框架实战十三:DDD分层架构之我见

    前面介绍了应用程序框架的一个重要组成部分——公共操作类,并提供了一个数据类型转换公共操作类作为示例进行演示.下面准备介绍应用程序框架的另一个重要组成部分,即体系架构支持.你不一定要使用DDD这样的架构 ...

  7. 应用程序框架实战十三:DDD分层架构之我见(转)

    前面介绍了应用程序框架的一个重要组成部分——公共操作类,并提供了一个数据类型转换公共操作类作为示例进行演示.下面准备介绍应用程序框架的另一个重要组成部分,即体系架构支持.你不一定要使用DDD这样的架构 ...

  8. DDD分层架构的进化

    .NET逻辑分层架构演示:DDD分层架构的进化 概述:   架构是高层的设计,如果设计和理解有误,必将在实现时带来各种问题.架构又是最稳定的,不会因为各种具体技术的依赖,如各种UI框架.ORM框架.I ...

  9. DDD分层架构之仓储

    DDD分层架构之仓储(层超类型基础篇) 前一篇介绍了仓储的基本概念,并谈了我对仓储的一些认识,本文将实现仓储的基本功能. 仓储代表聚合在内存中的集合,所以仓储的接口需要模拟得像一个集合.仓储中有很多操 ...

随机推荐

  1. 联想笔记本Win10 F1-F12失效的解决方法

    最近换了笔记本,用的是win10,发现F1到F12不生效. 比如玩游戏时,按F1没有切换到自己角色上,编程运行代码时的shift+F10也不行. 后来发现,这是因为某些笔记本的Fn功能键默认的不是传统 ...

  2. hdoj1010 奇偶剪枝+DFS

    Tempter of the Bone Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Othe ...

  3. C++强制转换

    static_cast,dynamic_cast, const_cast, reinterpret_cast dynamic_cast比static_cast多了安全检测,判断源和目标有无继承被继承关 ...

  4. 动态加载JS,并执行回调函数

    有些时候我们需要动态的加载一些JS,并在JS加载完成后执行一些回调函数. var loadscript = { $$: function (id) { return document.getEleme ...

  5. oracle使用 merge 更新或插入数据

    OracleCC++C#  总结下.使用merge比传统的先判断再选择插入或更新快很多. 1)主要功能 提供有条件地更新和插入数据到数据库表中 如果该行存在,执行一个UPDATE操作,如果是一个新行, ...

  6. ssh的无密码登录

    实现步骤如下: 1 生成一对公钥和私钥 $ ssh-keygen #以上命令等价于 ssh-keygen -t rsa #-t:指定密钥的类型,默认为SSH-2 的rsa类型; 运行上面的命令后,系统 ...

  7. HDU_1022

    题目: As the new term comes, the Ignatius Train Station is very busy nowadays. A lot of student want t ...

  8. 值得一看!2018年最优秀的9个Android Material Design Apps!

    今年4月,谷歌Gmail推出了全新的设计外观,全新的配色方案,更多的空白区域和精致的图标.也带来了Material Design 的一些改变 – Material Theming (材料主题),旨在自 ...

  9. Monte carlo

    转载 http://blog.sciencenet.cn/blog-324394-292355.html 蒙特卡罗(Monte Carlo)方法,也称为计算机随机模拟方法,是一种基于"随机数 ...

  10. jQuery获得元素位置offset()和position()的区别

    jQuery获得元素位置offset()和position()的区别 jQuery 中有两个获取元素位置的方法offset()和position(),这两个方法之间有什么异同 offset(): 获取 ...