• 文章内容全部来自张逸《领域驱动设计实践(战略+战术)》

上文 领域驱动实践

演进后的分层架构代码模型

需求:创建订单,发送邮件通知,异步消息通知仓储系统。

image.jpeg

controller是北向网关,承担与用户界面的交互,同理,如果是dubbo,那么dubbo的api也可以视作是北向网关。

南向网关是系统访问外面资源用于支撑业务系统的适配。

  • 领域层:包含 PlaceOrderService、Order、Notification、OrderConfirmed 与抽象的 OrderRepository,封装了纯粹的业务逻辑,不掺杂任何与业务无关的技术实现。
  • 应用层:包含 OrderAppService 以及抽象的 EventBus 与 NotificationService,提供对外体现业务价值的统一接口,同时还包含了基础设施功能的抽象接口。
  • 基础设施层:包含 OrderMapper、RabbitEventBus 与 EmailSender,为业务实现提供对应的技术功能支撑,但真正的基础设施访问则委派给系统边界之外的外部框架或驱动器。

限界上下文与架构

认识限界上下文

限界上下文体现的是一个垂直的架构边界,主要针对后端架构层次的垂直切分。对基础设施,框架的技术选型属于架构设计的考量范围,但不属于限界上下文的代码模型,但这些基础设施,框架的选择仍要考虑他们与限界上下文代码模型的集成、构建与部署。

限界上下文之间应该严格谨守边界,防腐层(ACL)是抵御外部限界上下文变化的最佳场所。

image.png

外部资源访问的两种架构风格:

1:数据库共享架构

避免不同限界上下文关联表之间的外键约束。

应该根据领域逻辑知识去识别限界上下文,避免从数据库层面建模。

2:零共享架构

将两个限界上下文共享的外部资源彻底分离。

需要考虑通信的健壮性。

需要保证数据的一致性。

运维和监控的复杂度也会上升。

代码结构

image.png

看上面这个图,applicationService是可以不经过domainService直接访问repositories,这就说明了domainService这一层更多的职责应该是领域对象的业务编排,如果一个业务只是简单的持久化一个对象,可以不用经过domainService,这样代码更简洁,避免经过无谓的代码层次,降低可读性。

ordercontext  
    - gateways 
    - controllers                  北向网关 
        - OrderController 
        - messages                 dto 
            - CreateOrderRequest 
    - persistence                  南向网关(持久化实现) 
        - OrderMapper 
    - client                       南向网关(其他微服务/外部服务) 
        - NotificationClient 
    - mq                           mq实现 
        - RabbitEventBus 
    - application                      业务service 
        - OrderAppService 
    - interfaces                       基础设施,南向网关的抽象 
    - client 
        - NotificationService 
        - SendNotificationRequest 
    - mq 
        - EventBus 
    - domain                          领域服务 
        - PlaceOrderService 
        - Order 
        - OrderConfirmed 
        - Notification 
        - NotificationComposer 
    - repositories                    持久化的抽象(持久化也是南向网关的一种,但比较特殊,所以独立出来) 
        - OrderRepository

不同的上下文之间的通信需要进行隔离

image.png

架构风格分析

微服务架构风格

将限界上下文视为微服务。包括用户和外部系统在内的客户端需要通过api Gateway实现微服务的调用。

一个限界上下文未必一定要部署为一个微服务,如果是提供整个系统的公共基础功能,应该定义为公共组件。

微服务架构风格可以保证技术选择,发布节奏的自由,但也会有分布式系统的复杂度,数据一致性和运维部署的挑战。

事件驱动架构风格

将上下文协作模式抽象为发布/订阅事件。系统与外部系统之间需要引入消息中间件,以便于事件消息的传递

CQRS架构风格

在限界上下文层面将查询与命令分为两种不同的实现模式。系统暴露的 API 接口需要分解为命令接口和查询接口,接口类型不同,处理模式和执行方式都不相同。可以为 command 和 query 分别建立 module(领域驱动设计中的设计要素),使得它们的代码模型可以独自演化,毕竟命令和查询的领域模型是完全不同的。甚至可以为同一个领域的 command 和 query 各自建立专有的限界上下文。

BFF

Backends For Frontends,为前端提供的后端。可以看作是业务的聚合,用于承接ui和后端代码。

案例分析

前提:不要以一个码农的视角来看待DDD,不要以一个码农的视角来看项目。

如何主导一个项目的开发

1:清楚项目背景

2:先启阶段:确定系统范围,明确开发目标,预见开发风险,统一技术架构,制定迭代计划。

确定系统范围:包括哪些做,哪些不做;有哪些利益相关方参与。

明确开发目标:包括业务目标,系统性能目标等。

预见开发风险:包括人力资源风险,第三方支持风险,外部政策变化风险等。

统一技术架构:主要指技术架构选型,技术方案制定等。

制定迭代计划:需要有一个明确可执行的迭代计划。

先启阶段最好能有一个mvp计划,明确第一个正式提交版本内容。否则容易迷失在细枝末节的功能需求中。

识别问题域:核心子领域,通用子领域,支撑子领域

统一语言

编写有效用例:分为概要目标,用户目标和子功能image.png

识别参与者,参与者可能是人,也可能是系统、服务或模块。

通过参与者识别用例

使用事件风暴识别限界上下文,避免限界上下文边界过大(2PTs原则)

识别上下文映射(结合用例),避免循坏依赖,如果出现循坏依赖,可能是遗漏了限界上下文,或者上下文之间职责不清

下游调用上游

代码组织架构

image.png

1111.png


toby1024
15 声望2 粉丝

奔波~儿爸


引用和评论

0 条评论