领域驱动设计概念(Domain-driven Design), Flower(响应式微服务框架)

摘要:
领域服务领域设计中,有些重要的操作不适合归类到Entity或ValueObject的,可以设计到Service中,本质上是一些活动或者行为动作。
DDD

领域驱动设计优势

  • 领域专家和开发人员共同工作,这样软件可以准确表达业务规则,就像是领域专家开发出来的一样
  • 帮助业务人员自我提高
  • 知识集中,确保软件知识并不只是掌握在少数人手中
  • 领域专家、开发者和软件间不需要“翻译”,彼此使用通用语言交流
  • 设计就是代码,代码就是设计
  • DDD同时提供战略设计和战术设计。战略设计帮助理解必要的投入、团队人员构成;战术设计帮助创建DDD中的各个组件。

通用语言(Ubiquitous Language)

领域模型和软件设计是紧密联系在一起的,软件系统的各个方面的设计都要忠实的反映领域模型,以便明确二者的对应关系。而且需要经常反复检查修改模型,以便更优雅的实现模型。
那么,领域专家、设计人员和开发人员就要有一套交流的专业术语,可以称之为Ubiquitous Language

通用语言

领域驱动设计概念

  • 实体(Entity/Reference Object)
  • 值对象(Value object)
  • 聚合(Aggregate)和聚合根(Aggregate Root)
  • 领域服务(Domain Service)
  • 领域事件(Domain Event)
  • 仓储(Repository)

实体(Entity/Reference Object)

领域中具有生命周期的对象,通常会经历创建、更新和销毁的过程。它的显著特点是拥有一个全局唯一标识符,而且唯一标识符是区分两个实体是否相等的唯一条件。

值对象(Value object)

领域中当只关心领域模型的属性时,应把它归类为值对象。 而且值对象应该是不可变的,和实体对比来看,值对象不需要分配唯一标识符。两个对象只要内部属性都相等,就可以认为是同一个对象。

聚合聚合根(Aggregate)和聚合根(Aggregate Root)

  • 聚合定义了一组具有内聚关系的相关对象的集合,是一个修改数据的单元,通过聚合定义出对象间的关系和边界。
  • 如果一个聚合只包含一个实体,那么这个实体可以认为是一个聚合根。

领域服务(Domain Service)

  • 领域设计中,有些重要的操作不适合归类到Entity或Value Object的,可以设计到Service中,本质上是一些活动或者行为动作。
  • 软件设计中,Service可以划分为三种类型:应用层服务、领域层服务和基础设施服务

领域事件(Domain Event)

聚合对象接收命令(Command)请求和查询(Query)请求时,可能需要生成领域事件对象给领域对象。在CQRS模式的应用中,领域事件通常是由命令请求产生的。

仓储(Repository)

实体对象需要存储,可以存储在内存(In Memory)或者磁盘(Database)上,在需要实体对象时再从仓储中重构出实体对象。在实践中,数据库存储是仓储的一种实现方式。

领域驱动模式

  • 分层架构(Layers Architecture)
  • 六边形理论(Hexagonal Architecture)
  • 洋葱架构/简洁架构(Onion Architecture/The clean Architecture)
  • 命令查询职责分离(Command-Query Responsibility Segregation)
  • 事件溯源(Event Source)

分层架构(Layers Architecture)

分层架构

六边形架构/端口适配器架构(Hexagonal Architecture)

六边形架构/端口适配器架构

洋葱架构/简洁架构(Onion Architecture/The clean Architecture)

洋葱架构/简洁架构

命令查询职责分离(Command-Query Responsibility Segregation)

命令查询职责分离

事件溯源(Event Source)

事件溯源是一种数据存储的模式,区别于传统仓储存储实体对象的当前状态,事件溯源则存储了影响实体对象变化的所有事件,通过事件历史回溯实体的当前状态。

事件溯源

Flower Domain Driven Design

Flower DDD的设计思路

  • Flower基于akka,是一个反应式微服务框架,原生支持消息驱动模式。
  • Actor模型是消息驱动、非阻塞的,优雅解决多线程难题,提高系统吞吐量
  • 定义CommandHandler和EventHandler,处理Command和Query
  • 编排CommandGateway流程和QueryGateway流程,代理Command和Query的操作入口
  • 基于Flower异步特性,异步响应

Flower CQRS架构图

命令查询职责分离

Command

  • CommandGateway
  • CommandHandler
  • EventHandler

CommandGateway

@Autowired
CommandGateway commandGateway;

@RequestMapping("/create")
public void createFoodCart() {
      // ui create food cart
      // publish an commannd : CreateOrderCommand
      commandGateway.send(new CreateOrderCommand(index.incrementAndGet(), "foodcart"));
}

CommandHandler

@CommandHandler
public void command(CreateOrderCommand command, ServiceContext context) {
      logger.info("创建订单命令:{}", command);
      AggregateLifecycle.apply(new CreateOrderEvent(command.getId(), command.getName()));
}

EventHandler

@EventHandler
public void on(CreateOrderEvent event, ServiceContext context) throws IOException {
      logger.info("处理订单事件:{}", event);
      context.getWeb().printJSON(JSON.toJSONString(event));
      // dao
}

Query

QueryGateway

@Autowired
QueryGateway queryGateway;

@RequestMapping("{orderId}")
public void queryFoodcart(@PathVariable Long orderId) {
      queryGateway.query(new SelectOrderCommand(orderId));
}

QueryHandler

@CommandHandler
public void command(SelectOrderCommand command, ServiceContext context) {
      logger.info("选择订单命令:{}", command);
      AggregateLifecycle.apply(new SelectOrderEvent(command.getId()));
}

EventHandler

@EventHandler
public void on(SelectOrderEvent event, ServiceContext context) {
      logger.info("选择订单事件:{}", event);
      // do something
}

Flower请求响应

ServiceContext中持有请求上下文对象HttpServletRequest,通过ServiceContext可以对客户端响应数据。

@EventHandler
public void on(CreateOrderEvent event, ServiceContext context) throws IOException {
      logger.info("处理订单事件:{}", event);
      context.getWeb().printJSON(JSON.toJSONString(event));
      // dao
}

集成spring-boot

@SpringBootApplication
@FlowerComponentScan("com.ly.train.flower.ddd")
@EnableTransactionManagement
public class DDDApplication {
      public static void main(String[] args) {
            SpringApplication.run(DDDApplication.class, args);
      }
}

免责声明:文章转载自《领域驱动设计概念(Domain-driven Design), Flower(响应式微服务框架)》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Debug技巧[linux]如何更新Ubuntu的数据源下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Electron进程间通信

在说Electron进程通信的时候,先说一下Electron中的两种进程:主进程和渲染进程。 主进程通过创建 BrowserWindow 实例来创建网页。 每一个 BrowserWindow 实例在其渲染过程中运行网页,当一个BrowserWindow 实例被销毁时,对应的渲染过程也会被终止。简单来说,一个客户端就是一个主进程。 渲染进程只能管理相应的网页...

20211025-领域驱动设计的落地经验

一,从招聘请求看领域驱动设计的重要性 从boss直聘摘抄的部分要求: 如下做了细微摘抄:1、 负责供应链金融业务项目的业务架构设计,解决业务规划向信息化/数字化落地映射过程中整体性、结构性业务建模的问题;2、 深入理解供应链金融业务表征及其形态,归纳设计业务流程、场景,提炼业务过程、功能,并明确不同层次面临的问题域;3、 具备较高的业务抽象与建模能力、领...

火狐和IE的window.event对象详解

FF的FIREBUG,不仅能测试JS还能检查CSS错误,是一般常用的。但它主要检查FF方面的错误,对IE就无能为力了。要测试IE,就用ieTester,它可以测试IE几乎所有版本(1.0恐怕也用不到测试了),用法也很方便。   至于JS对不同浏览器的兼容注意事项,的确很多,下面给你的也只是部分,一般建议还是采用jquery,prototype等一些已经处理...

深入Android开发之--理解View#onTouchEvent

一:前言 View是Android中最基本的UI单元. 当一个View接收到了触碰事件时,会调用其onTouchEvent方法.方法声明如下: ? 1 2 3 4 5 6 7 /** * Implement this method to handle touch screen motion events. * * @param even...

div拖拽, onmousedown ,onmousemove, onmouseup

1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="UTF-8"> 5 <title></title> 6 <style type="text/css"> 7...

Opencv处理鼠标事件-OpenCV步步精深

在图片上双击过的位置绘制一个 圆圈 鼠标事件就是和鼠标有关的,比如左键按下,左键松开,右键按下,右键松开,双击右键等等。 我们可以通过鼠标事件获得与鼠标对应的图片上的坐标。我们通过以下函数来调用查看所有鼠标事件。 events=[i for i in dir(cv2) if 'EVENT'in i] print events 所有的鼠标事件 我们...