Wow: 基于 DDD、EventSourcing 的现代响应式 CQRS 架构微服务开发框架

Wow: 基于 DDD、EventSourcing 的现代响应式 CQRS 架构微服务开发框架
Wow: 基于 DDD、EventSourcing 的现代响应式 CQRS 架构微服务开发框架
Wow: 基于 DDD、EventSourcing 的现代响应式 CQRS 架构微服务开发框架
Wow: 基于 DDD、EventSourcing 的现代响应式 CQRS 架构微服务开发框架
Wow: 基于 DDD、EventSourcing 的现代响应式 CQRS 架构微服务开发框架
Wow: 基于 DDD、EventSourcing 的现代响应式 CQRS 架构微服务开发框架
Wow: 基于 DDD、EventSourcing 的现代响应式 CQRS 架构微服务开发框架

领域驱动 | 事件驱动 | 测试驱动 | 声明式设计 | 响应式编程 | 命令查询职责分离 | 事件溯源

架构图

Wow: 基于 DDD、EventSourcing 的现代响应式 CQRS 架构微服务开发框架

事件源

Wow: 基于 DDD、EventSourcing 的现代响应式 CQRS 架构微服务开发框架

可观测性

Wow: 基于 DDD、EventSourcing 的现代响应式 CQRS 架构微服务开发框架

OpenAPI (Spring WebFlux 集成)

自动注册 命令 路由处理函数(HandlerFunction) ,开发人员仅需编写领域模型,即可完成服务开发。

Wow: 基于 DDD、EventSourcing 的现代响应式 CQRS 架构微服务开发框架

测试套件:80%+ 的测试覆盖率轻而易举

Given -> When -> Expect .

Wow: 基于 DDD、EventSourcing 的现代响应式 CQRS 架构微服务开发框架

前置条件

  • 理解 领域驱动设计:《实现领域驱动设计》、《领域驱动设计:软件核心复杂性应对之道》
  • 理解 命令查询职责分离(CQRS)
  • 理解 事件源架构
  • 理解 响应式编程

特性

    • EventStore
    • Snapshot

Example

Example

单元测试套件

80%+ 的测试覆盖率轻而易举。

Wow: 基于 DDD、EventSourcing 的现代响应式 CQRS 架构微服务开发框架

Given -> When -> Expect .

Aggregate Unit Test (AggregateVerifier)

Aggregate Test

internal class OrderTest {      private fun mockCreateOrder(): VerifiedStage<OrderState> {         val tenantId = GlobalIdGenerator.generateAsString()         val customerId = GlobalIdGenerator.generateAsString()          val orderItem = OrderItem(             GlobalIdGenerator.generateAsString(),             GlobalIdGenerator.generateAsString(),             BigDecimal.valueOf(10),             10,         )         val orderItems = listOf(orderItem)         val inventoryService = object : InventoryService {             override fun getInventory(productId: String): Mono<Int> {                 return orderItems.filter { it.productId == productId }.map { it.quantity }.first().toMono()             }         }         val pricingService = object : PricingService {             override fun getProductPrice(productId: String): Mono<BigDecimal> {                 return orderItems.filter { it.productId == productId }.map { it.price }.first().toMono()             }         }         return aggregateVerifier<Order, OrderState>(tenantId = tenantId)             .inject(DefaultCreateOrderSpec(inventoryService, pricingService))             .given()             .`when`(CreateOrder(customerId, orderItems, SHIPPING_ADDRESS, false))             .expectEventCount(1)             .expectEventType(OrderCreated::class.java)             .expectStateAggregate {                 assertThat(it.aggregateId.tenantId, equalTo(tenantId))             }             .expectState {                 assertThat(it.id, notNullValue())                 assertThat(it.customerId, equalTo(customerId))                 assertThat(it.address, equalTo(SHIPPING_ADDRESS))                 assertThat(it.items, equalTo(orderItems))                 assertThat(it.status, equalTo(OrderStatus.CREATED))             }             .verify()     }      /**      * 创建订单      */     @Test     fun createOrder() {         mockCreateOrder()     }      @Test     fun createOrderGivenEmptyItems() {         val customerId = GlobalIdGenerator.generateAsString()         aggregateVerifier<Order, OrderState>()             .inject(mockk<CreateOrderSpec>(), "createOrderSpec")             .given()             .`when`(CreateOrder(customerId, listOf(), SHIPPING_ADDRESS, false))             .expectErrorType(IllegalArgumentException::class.java)             .expectStateAggregate {                 /*                  * 该聚合对象处于未初始化状态,即该聚合未创建成功.                  */                 assertThat(it.initialized, equalTo(false))             }.verify()     }      /**      * 创建订单-库存不足      */     @Test     fun createOrderWhenInventoryShortage() {         val customerId = GlobalIdGenerator.generateAsString()         val orderItem = OrderItem(             GlobalIdGenerator.generateAsString(),             GlobalIdGenerator.generateAsString(),             BigDecimal.valueOf(10),             10,         )         val orderItems = listOf(orderItem)         val inventoryService = object : InventoryService {             override fun getInventory(productId: String): Mono<Int> {                 return orderItems.filter { it.productId == productId }                     /*                      * 模拟库存不足                      */                     .map { it.quantity - 1 }.first().toMono()             }         }         val pricingService = object : PricingService {             override fun getProductPrice(productId: String): Mono<BigDecimal> {                 return orderItems.filter { it.productId == productId }.map { it.price }.first().toMono()             }         }          aggregateVerifier<Order, OrderState>()             .inject(DefaultCreateOrderSpec(inventoryService, pricingService))             .given()             .`when`(CreateOrder(customerId, orderItems, SHIPPING_ADDRESS, false))             /*              * 期望:库存不足异常.              */             .expectErrorType(InventoryShortageException::class.java)             .expectStateAggregate {                 /*                  * 该聚合对象处于未初始化状态,即该聚合未创建成功.                  */                 assertThat(it.initialized, equalTo(false))             }.verify()     }      /**      * 创建订单-下单价格与当前价格不一致      */     @Test     fun createOrderWhenPriceInconsistency() {         val customerId = GlobalIdGenerator.generateAsString()         val orderItem = OrderItem(             GlobalIdGenerator.generateAsString(),             GlobalIdGenerator.generateAsString(),             BigDecimal.valueOf(10),             10,         )         val orderItems = listOf(orderItem)         val inventoryService = object : InventoryService {             override fun getInventory(productId: String): Mono<Int> {                 return orderItems.filter { it.productId == productId }.map { it.quantity }.first().toMono()             }         }         val pricingService = object : PricingService {             override fun getProductPrice(productId: String): Mono<BigDecimal> {                 return orderItems.filter { it.productId == productId }                     /*                      * 模拟下单价格、商品定价不一致                      */                     .map { it.price.plus(BigDecimal.valueOf(1)) }.first().toMono()             }         }         aggregateVerifier<Order, OrderState>()             .inject(DefaultCreateOrderSpec(inventoryService, pricingService))             .given()             .`when`(CreateOrder(customerId, orderItems, SHIPPING_ADDRESS, false))             /*              * 期望:价格不一致异常.              */             .expectErrorType(PriceInconsistencyException::class.java).verify()     } } 

Saga Unit Test (SagaVerifier)

Saga Test

class CartSagaTest {      @Test     fun onOrderCreated() {         val orderItem = OrderItem(             GlobalIdGenerator.generateAsString(),             GlobalIdGenerator.generateAsString(),             BigDecimal.valueOf(10),             10,         )         sagaVerifier<CartSaga>()             .`when`(                 mockk<OrderCreated> {                     every {                         customerId                     } returns "customerId"                     every {                         items                     } returns listOf(orderItem)                     every {                         fromCart                     } returns true                 },             )             .expectCommandBody<RemoveCartItem> {                 assertThat(it.id, equalTo("customerId"))                 assertThat(it.productIds, hasSize(1))                 assertThat(it.productIds.first(), equalTo(orderItem.productId))             }             .verify()     } } 

设计

聚合建模

Single Class Inheritance Pattern Aggregation Pattern
Wow: 基于 DDD、EventSourcing 的现代响应式 CQRS 架构微服务开发框架 Wow: 基于 DDD、EventSourcing 的现代响应式 CQRS 架构微服务开发框架 Wow: 基于 DDD、EventSourcing 的现代响应式 CQRS 架构微服务开发框架

加载聚合

Wow: 基于 DDD、EventSourcing 的现代响应式 CQRS 架构微服务开发框架

聚合状态流

Wow: 基于 DDD、EventSourcing 的现代响应式 CQRS 架构微服务开发框架

发送命令

Wow: 基于 DDD、EventSourcing 的现代响应式 CQRS 架构微服务开发框架

命令与事件流

Wow: 基于 DDD、EventSourcing 的现代响应式 CQRS 架构微服务开发框架

Saga - OrderProcessManager (Demo)

Wow: 基于 DDD、EventSourcing 的现代响应式 CQRS 架构微服务开发框架

发表评论

评论已关闭。

相关文章