DDD在解决什么问题
当我们在谈论领域驱动设计的时候,我们到底在谈论什么?领域驱动设计是在解决什么问题?
领域本质是一种认知,是我们对业务问题域的认知,与其说我们是在用技术解决业务问题,更不如说,我们是在不断地提升对业务的认知,不断地优化业务领域模型,从而不断地接近业务问题的本质。代码坏味道的背后反映的是对业务问题不清晰的认知,最终落地了不优雅的代码实现。回归到生活中,工作中,我们会经常遇到各种问题,大多数时候不是我们没有习得解决问题的技能,而是我们对问题的认知不够。
在上一篇文章《真的,DDD太好玩了》中我们说,DDD是一种业务设计思想,用以将业务逻辑和技术实现分离,今天我们就是要讨论一下DDD三驾马车之中的架构设计(三架马车指的是架构设计,战略设计和战术设计),即如何将业务逻辑和技术实现分离。DDD中常见的架构设计有:MVC三层架构,传统四层架构,依赖倒置的四层架构,六边形架构(又称端口适配器架构,我更喜欢这个名字),洋葱架构,事件驱动架构(EDA,Event-Driven Architecture ),命令与查询分离(CQRS,Command Query Responsibility Segregation)。
四个分层
首先我要介绍一下四层架构的各个分层是做什么事情的,这对于理解后面各种架构设计是有帮助的,不管上述几种架构是如何命名的,是如何定义和认识业务逻辑和技术实现分离这个命题的,其内核都是一样的。四层架构的四层分别指的是用户接口层、应用层、领域层和基础设施层,其定义如下:
用户接口层(User Interface):主要负责处理用户请求,并将请求转发给应用层处理。
应用层(Application):主要负责协调上游的用户接口层以及下游的领域层,注意的是,该层逻辑要尽可能简单,否则会导致领域层的贫血。
领域层(Domain):主要包含了核心业务逻辑,包含实体,值对象,领域服务,领域事件等。
基础设施层(Infrastructure):主要提供各种技术中间件,数据库(MySQL,NoSql)和应用配置等技术实现方面的能力。
架构设计分析
在DDD架构设计中,核心的目标就是将业务逻辑和技术实现分离,这也正是MVC三层架构留下来的问题。
我们在MVC三层架构中将业务逻辑和技术实现一股脑写在了Service层,技术实现中参杂了业务逻辑,业务逻辑中也揉合了技术实现,从而将本来就复杂的业务逻辑变得更加复杂了。端口适配器架构则简化了这个问题,很直白地将架构设计成了两部分,即内部的业务逻辑和外部的基础设施和用户界面,当然这也是一种分层架构,即内部和外部两层。如果将内部业务逻辑对外部的依赖定义成接口,那么基础设施表示的技术实现部分,用户界面表示的是用户请求就都算是适配器实现。
这种实现业务逻辑和技术实现分离的架构真的是太优雅了,很符合奥卡姆剃刀原理(“如无必要,勿增实体”,即“简单有效原理”),简单就是美。但其实也会带来另一个问题,即如何去认识业务逻辑?难道业务逻辑就是一个大块头吗?该如何下手设计这个大块头呢?
洋葱架构既在端口适配器架构之上,提出了一种划分业务逻辑的方法,将业务逻辑划分为应用服务,领域服务和领域模型,并且依赖方向也是从外向内。这里其实也有了依赖倒置四层架构的味道了。
那么我们就顺理成章地介绍一下四层架构,在传统的四层架构中,我们可以发现,所有的依赖都指向了基础设施层,这带来了一个很大的问题,业务逻辑依赖了技术实现,技术实现的变动会导致业务逻辑发生变化,这不符合我们的认知。在理想的架构实现中,不管你技术如何变化,我的业务逻辑是不应该受到技术变化影响的。这时候依赖倒置原则就可以发挥作用了,将技术实现的契约或者规范定义在领域层,基础实施层只管实现就好了,从而实现了依赖方向的反转。这种架构设计维护了业务逻辑的稳定,也更近一步地将技术实现对业务逻辑的影响降到了最低,从而实现了业务逻辑和技术实现的解耦,也使得领域层处于架构模型中的核心地位。
在上面的分析中,我们可以发现,其实DDD的四层架构是一种相对而言更便于理解和落地的架构,它可以让我们更轻松地从MVC三层架构的认知中迁移至DDD四层架构。
至此,四层架构模型似乎已经解决了业务逻辑和技术实现分离的问题,事实上也确实如此。CQRS架构模型和EDA架构模型在我眼中更像是对四层架构的优化。其中CQRS模型类似于读写分离,其中命令是客户端让服务器做事情,是从客户端向服务器后端发出写入操作命令,通常会改变后端模型的状态;而查询是服务器后端向客户端返回结果。在前面几种架构模型中,查询和变更操作都是经过完整的四层处理,并且实现逻辑都耦合在一起了,即实现在相同的类中。其实对于查询操作来说,这是一种很轻量级的业务逻辑,核心就是获取数据并进行转化,最终展示给用户,将其与命令分离开使得读写逻辑可以独立建模,逻辑更清晰,也可以专门优化查询操作。
而EDA架构的核心目的是提供一个业务认知和业务解耦的方法,通过事件的流转来认识业务逻辑,并且也可以通过业务事件来解耦业务。因为不断是什么业务场景,其本质都是事件导致结果发生,每个结果也有可能是一个事件,从而通过事件来串联整个业务流程,但也会带来事务问题。
最后
上面分析了这么多架构模式,但仿佛是个屠龙之术,学了很多又似乎无用武之地。但回过头看,正是因为领域设计的目标,才有了形形色色的架构模式,每个架构架构模式都在提出自己对问题的认知和解决方案,即如何将业务逻辑和技术实现分离,从而使得领域设计回归本质,关注于业务认知,而不是技术实现。
注:本文图片均来源于网络。