当前位置: 首页 > news >正文

【微服务实战】01-工程结构概览

文章目录

  • 工程结构概览:定义应用分层及依赖关系
    • 1.应用分层
    • 2.定义Entity
    • 3.仓储层
      • 3.1 工作单元:事务管理
      • 3.2 仓储层
    • 4.领域事件
    • 5.APIController最佳实践

工程结构概览:定义应用分层及依赖关系

1.应用分层

  • 领域模型层
  • 基础设施层 ⇒ 仓储
  • 应用层 ⇒ Api、后台任务Job
  • 共享层

总结

  • 领域模型专注业务的设计,不依赖仓储等基础设施层
  • 基础设施的仓储层仅负责领域模型的取出和存储
  • 使用CQRS模式设计应用层
  • Web Api是面向前端的交互的接口,避免依赖领域模型
  • 将共享代码设计为共享包,使用私有Nuget仓库分发管理

2.定义Entity

要点总结

  • 将领域模型字段的修改设置为私有
  • 使用构造函数表示对象的创建
  • 使用具有业务含义的动作来操作模型字段
  • 领域模型负责对自己数据的处理
  • 领域服务或命令处理者负责调用领域模型业务动作

3.仓储层

3.1 工作单元:事务管理

仓储层最重要的就是事务的管理,这里通过工作单元模式实现事务管理

工作单元特性

  • 使用同一上下文
  • 跟踪实体的状态
  • 保障事务一致性

3.2 仓储层

仓储层接口TEntity必须继承Entity,并且必须实现聚合根,也就是仓储中储存的对象是一个聚合根对象,

public interface IRepository<TEntity>  where TEntity : Entity,IAggregateRoot
{IUnitOfWork UnitOfWork {get;}TEntity Add(TEntity entity);TEntity Update(TEntity entity);
}public interface IRepository<TEntity,TKey>:IRepository<TEntity> where TEntity : Entity<TKey>,IAggregateRoot
{bool Delete(TKey id);TEntity Get(TKey id);
}

4.领域事件

  • 领域事件的构造和添加都应该在领域模型的方法内完成,不应该被外界的代码调用创建,因为这些事件都是领域模型内部发生的
  • 接受领域事件的处理应该定义在应用层
  • 创建完领域模型并保存之后,领域事件的处理程序才触发

总结

1.由领域模型内部创建事件
2.由专有的领域事件处理类处理领域事件
3.根据实际情况来决定是否在同一事务中处理(如一致性、性能等因素)

5.APIController最佳实践

// 伪代码[HttpGet]
public Task<long> CreateOrder([FromBody]CreateOrderViewModel viewModel)
{var model = viewModel.ToModel();// 模型转换return await orderService.CreateOrder(model);// 业务代码调用
}// 服务中代码
class OrderService : IOrderService
{public long CreateOrder(CreateOrderMode model){var address = new Address("测试路","测试市区","123");var order = new Order("订单名称","客户名称",999,address);_orderRepository.Add(order);await _orderRepository.UnitOfWork.SaveEntitiesAsync(cancellationToken);return order.Id;}
}

上述代码,随着业务逻辑的复杂化,Controller就会越来越膨胀。而DD领域设计的理念中,更新倾向于把应用程序的每一层明确区分,层与层之间的界限应该是明确的,同时在实现上应该也是隔离的。因此控制器不应该负责处理领域模型,处理仓储这些动作,Controller应该负责与前端交互,主要责任应该是定义输入和输出,实现身份认证、授权等功能。因此上述代码不建议使用

推荐使用中间者模式,演示代码如下

// 这里不建议使用属性服务进行服务注册,因为当使用属性注入的时候,需要把属性设置为public,并且开放set,get方法,可能出现意外情况,这可能导致代码的维护不可控
IMediator _mediator;
public OrderController(IMediator mediator)
{_mediator = mediator;
}// 这里尽可能的定义异步的action,可以帮助提高应用程序的吞吐量
[HttpPost]
public async Task<long> CreateOrder([FromBody] CreateOrderCommans cmd)
{return await _mediator.Send(cmd,HttpContext.RequestAborted);
}

总结

  • 负责用户的输入输出定义
  • 负责身份认证和授权
  • 与领域服务职责区分开,不承载业务逻辑
http://www.lryc.cn/news/133778.html

相关文章:

  • 论文导读|European Journal of Operational Research近期文章精选:旅行商问题专题
  • playwright迭代元素
  • 65 | 增长模型案例
  • Django视图-HttpRequest请求对象和HttpResponse响应对象
  • 原来Lambda表达式是这样写的
  • smartsofthelp 5.0 最专业的数据库优化工具,数据库配置优化,数据库高并发优化,SQL 语句优化...
  • 智影 R100:首款三维Mesh建模的SLAM激光扫描仪
  • Next.js - Loading UI and Streaming
  • 快速解决Ubuntu 中 wine 程序 中文显示为方块/显示错误/无法显示中文(2023)
  • 漏洞指北-VulFocus靶场专栏-中级02
  • 【开源三方库】bignumber.js:一个大数数学库
  • 【C++】iota函数 + sort函数实现基于一个数组的多数组对应下标绑定排序
  • C# window forms 进度条实现
  • ListNode相关
  • docker的资源控制及docker数据管理
  • 通过请求头传数据向后端发请求
  • 产品流程图是什么?怎么做?
  • 面试之快速学习STL-map
  • ES的索引结构与算法解析
  • 32.Netty源码之服务端如何处理客户端新建连接
  • 代码随想录day11
  • RabbitMQ实习面试题
  • Electron入门,项目运行,只需四步轻松搞定。
  • 【C++】visualstudio环境安装
  • 使用MySQL:5.6和owncloud镜像搭建个人网盘
  • php中创建对象时传递的参数是构造方法
  • C++并发及互斥保护示例
  • 新手常犯的错误,anzo capital昂首资本一招避免少走弯路
  • Java Vue (el-date-picker组件) 前后端 关于时间格式数据的处理方法
  • Python爬虫——scrapy_多条管道下载