微服务架构:从事务脚本到领域模型

简介: 微服务架构:从事务脚本到领域模型

image.png


图1 Order Service具有六边形架构。它由业务逻辑和一个或多个与其他服务和外部应用程序连接的适配器组成


图1显示了一个典型的服务架构。业务逻辑是六边形架构的核心。业务逻辑的周围是入站和出站适配器。入站适配器处理来自客户端的请求并调用业务逻辑出站适配器被业务逻辑调用,然后它们再调用其他服务和外部应用程序。


此服务由业务逻辑和以下适配器组成。

  • REST API adapter:入站适配器,实现REST API,这些API会调用业务逻辑。
  • OrderCommandHandlers入站适配器,它接收来自消息通道的命令式消息,并调用业务逻辑。
  • Database Adapter由业务逻辑调用以访问数据库的出站适配器。
  • Domain Event Publishing Adapter将事件发布到消息代理的出站适配器。

业务逻辑通常是服务中最复杂的部分。在开发业务逻辑时,你应该以最适合应用程序的方式,精心地设计和组织业务逻辑。我确信大多数读者都经历过不得不维护别人的糟糕代码的挫败感。大多数企业应用程序都是用面向对象的语言编写的,例如Java,因此它们由类和方法组成。但是使用面向对象的语言并不能保证业务逻辑具有面向对象的设计。在开发业务逻辑时必须做出的关键决策是选用面向对象的方式,还是选用面向过程的方式。组织业务逻辑有两种主要模式:面向过程的事务脚本模式和面向对象的领域建模模式。


1 使用事务脚本模式设计业务逻辑


虽然我一直积极地倡导使用面向对象的方式,但在某些情况下使用面向对象的设计方法会有一种“杀鸡用牛刀”的感觉,例如在开发简单的业务逻辑时。在这种情况下,更好的方法是编写面向过程的代码,并使用Martin Fowler在《Patterns of EnterpriseApplication Architecture》一书中提到的事务脚本模式。你可以编写一个称为事务脚本的方法来处理来自表示层的每个请求,而不是进行任何面向对象的设计。如图2所示,这种方法的一个重要特征是实现行为的类与存储状态的类是分开的。


image.png


图2 将业务逻辑组织为事务脚本。在典型的基于事务脚本的设计中,一组类实现行为,另一组类负责存储状态。事务脚本通常被写成没有状态的类。脚本访问没有行为的数据类以完成持久化的任务

 

使用事务脚本模式时,脚本通常位于服务类中,在此示例中是OrderService类。每个服务类都有一个用于请求或系统操作的方法。这个方法实现该请求的业务逻辑。它使用数据访问对象(DAO)访问数据库,例如OrderDao数据对象(在此示例中为Order类)是纯数据,几乎没有行为。

 



image.png


这种设计风格是高度面向过程的,仅仅依赖于面向对象编程(OOP)语言的少量功能。就好比你使用C或其他非OOP语言编写应用所能实现的功能。然而,在适当的时候,你不应该羞于使用面向过程的设计。这种方法适用于简单的业务逻辑。但这往往不是实现复杂业务逻辑的好方法。



2 使用领域模型模式设计业务逻辑


面向过程方法的可以简单迅速地搞定项目,这非常诱人。你可以专注编写业务逻辑代码,而无须仔细考虑如何设计和组织各种类。但是问题在于,如果业务逻辑变得复杂,你最终可能会得到噩梦般难以维护的代码。实际上,就像单体应用程序不断增长的趋势一样,事务脚本也存在同样的问题。因此,除非是编写一个非常简单的应用程序,否则你应该抵制编写面向过程代码的诱惑,使用领域模型模式,并进行面向对象的设计。



在面向对象的设计中,业务逻辑由对象模型和相对较小的一些类的网络组成。这些类通常直接对应于问题域中的概念。在这样的设计中,有些类只有状态或行为,但很多类同时包含状态和行为,这样的类都是精心设计的。图3显示了领域模型模式的示例。


image.png


图3 将业务逻辑组织为领域模型。大多数业务逻辑由具有状态和行为的类组成


与事务脚本模式一样,OrderService类具有针对每个请求或系统操作的方法。但是在使用领域模型模式时,服务方法通常很简单。因为服务方法几乎总是调用持久化领域对象,这些对象中包含大量的业务逻辑。例如,服务方法可以从数据库加载领域对象并调用其中一个方法。在这个例子中,Order类具有状态和行为。此外,它的状态是私有的,只能通过它的方法间接访问。

使用面向对象设计有许多好处。首先,这样的设计易于理解和维护。它不是由一个完成所有事情的大类组成,而是由许多小类组成,每个小类都有少量职责。此外,诸如Account、BankingTransaction和OverdraftPolicy这些类都密切地反映了现实世界,这使得它们在设计中的角色更容易理解。其次,我们的面向对象设计更容易测试:每个类都可以并且应该能够被独立测试。最后,面向对象的设计更容易扩展,因为它可以使用众所周知的设计模式,例如策略模式(Strategy pattern)和模板方法模式(Template methodpattern),这些设计模式定义了在不修改代码的情况下扩展组件的方法。


领域建模模式看似完美,但这种方法同样也存在许多问题,尤其是在微服务架构中。要解决这些问题,你需要使用称为领域驱动设计的思路来优化面向对象设计。


3 关于领域驱动设计


领域驱动设计Domain-Driven Design,DDD)的概念产生于Eric Evans写的《Domain Driven Design》一书,DDD是对面向对象设计的改进,是开发复杂业务逻辑的一种方法。我在第2章介绍过DDD,领域驱动设计的子域概念有助于把应用程序分解为服务。使用DDD时,每个服务都有自己的领域模型,这就避免了在单个应用程序全局范围内的领域模型问题。子域和相关联的限界上下文的相关概念是两种战略性DDD模式。


DDD还有一些战术性模式,它们是领域模型的基本元素(building block)。每个模式都是一个类在领域模型中扮演的角色,并定义了类的特征。开发人员广泛采用的基本元素包括以下几种。

  • 实体(entity):具有持久化ID的对象。具有相同属性值的两个实体仍然是不同的对象。在Java EE应用程序中,使用JPA @Entity进行持久化的类通常是DDD实体。
  • 值对象(value object):作为值集合的对象。具有相同属性值的两个值对象可以互换使用。值对象的一个例子是Money类,它由币种和金额组成。
  • 工厂(factory):负责实现对象创建逻辑的对象或方法,该逻辑过于复杂,无法由类的构造函数直接完成。它还可以隐藏被实例化的具体类。工厂方法一般可实现为类的静态方法。
  • 存储库(repository):用来访问持久化实体的对象,存储库也封装了访问数据库的底层机制。
  • 服务(service):实现不属于实体或值对象的业务逻辑的对象。

许多开发人员都使用这些基本元素,有些基本元素是通过JPASpring框架等实现的。除了DDD纯粹主义者之外,还有一个被众人(包括我在内)忽略的基本元素:聚合。事实证明,在开发微服务时,聚合是一个非常有用的概念。在下一部分,我们来看一看,聚合如何解决经典面向对象设计的一些微妙问题。





相关文章
|
8月前
|
Cloud Native Serverless API
微服务架构实战指南:从单体应用到云原生的蜕变之路
🌟蒋星熠Jaxonic,代码为舟的星际旅人。深耕微服务架构,擅以DDD拆分服务、构建高可用通信与治理体系。分享从单体到云原生的实战经验,探索技术演进的无限可能。
微服务架构实战指南:从单体应用到云原生的蜕变之路
|
Java 关系型数据库 数据库
微服务——SpringBoot使用归纳——Spring Boot事务配置管理——常见问题总结
本文总结了Spring Boot中使用事务的常见问题,虽然通过`@Transactional`注解可以轻松实现事务管理,但在实际项目中仍有许多潜在坑点。文章详细分析了三个典型问题:1) 异常未被捕获导致事务未回滚,需明确指定`rollbackFor`属性;2) 异常被try-catch“吃掉”,应避免在事务方法中直接处理异常;3) 事务范围与锁范围不一致引发并发问题,建议调整锁策略以覆盖事务范围。这些问题看似简单,但一旦发生,排查难度较大,因此开发时需格外留意。最后,文章提供了课程源代码下载地址,供读者实践参考。
436 0
|
Java 关系型数据库 数据库
微服务——SpringBoot使用归纳——Spring Boot事务配置管理——Spring Boot 事务配置
本文介绍了 Spring Boot 中的事务配置与使用方法。首先需要导入 MySQL 依赖,Spring Boot 会自动注入 `DataSourceTransactionManager`,无需额外配置即可通过 `@Transactional` 注解实现事务管理。接着通过创建一个用户插入功能的示例,展示了如何在 Service 层手动抛出异常以测试事务回滚机制。测试结果表明,数据库中未新增记录,证明事务已成功回滚。此过程简单高效,适合日常开发需求。
1896 0
|
Java 数据库 微服务
微服务——SpringBoot使用归纳——Spring Boot事务配置管理——事务相关
本文介绍Spring Boot事务配置管理,阐述事务在企业应用开发中的重要性。事务确保数据操作可靠,任一异常均可回滚至初始状态,如转账、购票等场景需全流程执行成功才算完成。同时,事务管理在Spring Boot的service层广泛应用,但根据实际需求也可能存在无需事务的情况,例如独立数据插入操作。
355 0
|
11月前
|
缓存 Cloud Native Java
Java 面试微服务架构与云原生技术实操内容及核心考点梳理 Java 面试
本内容涵盖Java面试核心技术实操,包括微服务架构(Spring Cloud Alibaba)、响应式编程(WebFlux)、容器化(Docker+K8s)、函数式编程、多级缓存、分库分表、链路追踪(Skywalking)等大厂高频考点,助你系统提升面试能力。
1457 0
|
Cloud Native Serverless 流计算
云原生时代的应用架构演进:从微服务到 Serverless 的阿里云实践
云原生技术正重塑企业数字化转型路径。阿里云作为亚太领先云服务商,提供完整云原生产品矩阵:容器服务ACK优化启动速度与镜像分发效率;MSE微服务引擎保障高可用性;ASM服务网格降低资源消耗;函数计算FC突破冷启动瓶颈;SAE重新定义PaaS边界;PolarDB数据库实现存储计算分离;DataWorks简化数据湖构建;Flink实时计算助力风控系统。这些技术已在多行业落地,推动效率提升与商业模式创新,助力企业在数字化浪潮中占据先机。
766 12
|
运维 监控 持续交付
微服务架构解析:跨越传统架构的技术革命
微服务架构(Microservices Architecture)是一种软件架构风格,它将一个大型的单体应用拆分为多个小而独立的服务,每个服务都可以独立开发、部署和扩展。
3823 37
微服务架构解析:跨越传统架构的技术革命
|
传感器 监控 安全
智慧工地云平台的技术架构解析:微服务+Spring Cloud如何支撑海量数据?
慧工地解决方案依托AI、物联网和BIM技术,实现对施工现场的全方位、立体化管理。通过规范施工、减少安全隐患、节省人力、降低运营成本,提升工地管理的安全性、效率和精益度。该方案适用于大型建筑、基础设施、房地产开发等场景,具备微服务架构、大数据与AI分析、物联网设备联网、多端协同等创新点,推动建筑行业向数字化、智能化转型。未来将融合5G、区块链等技术,助力智慧城市建设。
815 1
|
存储 JSON NoSQL
微服务——MongoDB的数据模型
MongoDB采用文档(document)作为最小存储单位,类似关系型数据库中的行,使用BSON(Binary-JSON)格式存储数据。BSON是JSON的二进制扩展,支持内嵌文档和数组,新增了如Date、BinData等特殊数据类型,具有轻量、高效、可遍历的特点,适合非结构化与结构化数据存储。其灵活性高,但空间利用率略低。BSON数据类型包括string、integer、boolean等基本类型及date、object id等扩展类型。
385 0