洋葱架构

详解“洋葱架构”_架构_Ritesh Kapoor_InfoQ精选文章

为什么要用洋葱架构

领域实体是核心和中心部分。洋葱架构是建立在一个领域模型上的,其中各层是通过接口连接的。其背后的思想是,再领域实体和业务规则架构的核心部分,尽可能将外部依赖保持在外。

  • 它提供了灵活、可持续和可移植的架构。
  • 各层之间没有紧密的耦合,并且有关注点的分离。
  • 由于所有的代码都依赖于更深的层或者中心,所以提供了更好的可维护性。
  • 提高了整体代码的可测试性,因为单元测试可以为单独的层创建,而不会影响到其他的模块。
  • 框架/技术可以很容易地改变而不影响核心领域。例如,RabbitMQ 可以被 ActiveMQ 取代,SQL 可以被 MongoDB 取代。

原则

洋葱架构是由多个同心圆组成,它们相互连接,并代表领域的核心。它是基于控制反转的(IOC)原则。该架构并不关注底层技术或框架,而是关注实际的领域模型,它是基于以下原则:

依赖性

圆圈代表不同的职责层。一般来说,我们潜入得越深,就越接近领域和业务规则。外圈代表机制,内圈代表核心领域逻辑。外层依赖于内层,而内层对外圈一无所知。通常情况下,属于外圈的类、方法、变量和源代码依赖于内圈,但是反过来也一样。

数据格式/结构可能因层而异。外层数据格式不应该被内层使用。例如,API中使用的数据格式可以鱼DB中用于持久化的数据格式不同。数据流可以使用数据传输对象。每当数据跨越层、跨界时,它应该以方便该层的形式出现。例如,API可以有DTO,DB层可以有Entity Objects,这取决于存储在数据库中的对象与领域模型的不同。

数据封装

每个层、圈封装或隐藏内部的实现细节,并向外层公开接口。所有的层也需要提供便于内层消费的信息。其目的是最小化层与层之间的耦合,最大话跨垂直切面内的耦合。我们在较深层定义抽象接口,并在外层提供其具体实现。这样可以确保我们专注于领域模型,而不必过多地担心实现细节。我们可以使用依赖性注入框架,比如Spring,在运行时将接口与实现连接起来。例如,领域中使用的存储库和应用服务中使用的外部服务在基础设施层实现。

关注点的分离

应用被分为若干层,每一层都有一组职责,并解决不同的关注点。每一层都作为应用中的模块、包、命名空间。

耦合性

低耦合性,可以使一个模块与另一个模块交互,而不需要关注另一个模块的内部。所有的内部层都不需要关注外部层的内部实现。

洋葱架构层

让我们通过一个创建订单的用例来了解架构的不同层和它们的职责。当收到一个创建订单的请求时,我们会对这个订单进行验证,将这个订单保存在数据库中,更新所有订单项目的库存,借记订单金额,最后向客户发送订单完成的通知。

说明各层之间的依赖关系的包图

领域模型、实体

领域实体是领域驱动设计的基本构件,它们在被用来在代码中为通用语言的概念建模。实体是在问题中具有唯一身份的领域概念。领域实体封装了属性和实体行为。它应该是独立于数据库或网络API等特定技术的,例如,再订单领域中,订单是一个实体,并具有像 OrderId、Address、UserInfo、OrderItems、PricingInfo 这样的属性以及像 AddOrderItems、GetPricingInfo、ValidateOrder 这样的行为。

领域服务

领域服务负责保持领域逻辑和业务规则。所有的业务逻辑应该作为领域服务的一部分来实现。领域服务由应用服务协调,以服务于业务用例。他们不是典型的CRUD服务,通常是独立的服务。领域服务负责法则的业务规则,再处理订单时计算价格和税收信息,保存更新订单的订单库接口,更新购买物品信息的库存接口等。

它包含了对其目标非常关键的算法,并且将用例作为应用的核心来实现。

应用服务

应用服务也被称为用例,只是负责协调请求步骤的服务,不应该有任何的业务逻辑。应用服务与其他服务交互,以满足客户的请求。让我们考虑一下用例,用一个物品清单创建一个订单。我们首先需要计算价格,包括税收计算/折扣等,保存订单项目并向客户发送订单确认通知。定价计算应该是领域服务的一部分,但涉及定价计算、检查可用性、保存订单和通知用户的协调工作应该是应用服务的一部分。应用服务只能由基础设施服务调用。

基础设施服务

基础设施服务也被称为基础设施适配器,是洋葱架构的最外层。这些服务负责与外部世界交互,不解决任何领域的问题。这些服务只是与外部资源通信,没有任何逻辑。例如:外部通知服务、GRPC 服务器端点、Kafka 事件流适配器、数据库适配器。

可观测性服务

可观测性服务负责健康应用。这些服务有助于执行一下任务

  • 数据收集(指标、日志、痕迹):主要使用库/侧线来收集代码执行期间的各种数据。
  • 数据存储:使用能够集中存储所收集的数据的工具(分类、索引等)。
  • 可视化:使用允许你对收集的数据进行可视化的工具。

一些例子包括 Splunk、ELK、Grafana、Graphite、Datadog。

我们需要每个层吗?

将我们的应用分层组织有助于实现关注点的分离。但我们需要所有的层吗?也许需要,也许不需要。这取决于用例和应用的复杂性。根据应用的需要,也可以创建更多的抽象层。例如,对于没有很多业务逻辑的小型应用,拥有领域服务可能没有意义。无论哪一层,依赖关系都应该是从外层到内层。

总结

洋葱架构在开始时可能似乎有些困难,但是在业界已经得到了普遍的认可。这是一种让软件易于演进的强有力架构。通过把应用划分为几层,可以使系统更加易于测试、维护和移植。它有助于在旧框架过时时轻松采用新框架/技术。与其他架构风格类似,如六边形、分层、简洁的架构等,它为常见问题提供了一个解决方案。

Last modification:February 1, 2024
如果觉得我的文章对你有用,请随意赞赏