DDD实战 - Repository模式的妙用

大家好,我是飘渺 。今天我们继续更新DDD(领域驱动设计) & 微服务系列 。
在之前的文章中,我们探讨了如何在DDD中结构化应用程序 。我们了解到,在DDD中通常将应用程序分为四个层次,分别为用户接口层(Interface Layer),应用层(Application Layer),领域层(DomAIn Layer),和基础设施层(Infrastructure Layer) 。此外,在用户注册的主题中,我们简要地提及了资源库模式 。然而,那时我们并没有深入探讨 。今天,我将为大家详细介绍资源库模式,这在DDD中是一个非常重要的概念 。
1. 传统开发流程分析首先,让我们回顾一下传统的以数据库为中心的开发流程 。
在这种开发流程中,开发者通常会创建Data Access Object(DAO)来封装对数据库的操作 。DAO的主要优势在于它能够简化构建SQL查询、管理数据库连接和事务等底层任务 。这使得开发者能够将更多的精力放在业务逻辑的编写上 。然而,DAO虽然简化了操作,但仍然直接处理数据库和数据模型 。
值得注意的是,Uncle Bob在《代码整洁之道》一书中,通过一些术语生动地描述了这个问题 。他将系统元素分为三类:
硬件(Hardware): 指那些一旦创建就不可(或难以)更改的元素 。在开发背景下,数据库被视为“硬件”,因为一旦选择了一种数据库,例如MySQL,转向另一种数据库,如MongoDB,通常会带来巨大的成本和挑战 。
软件(Software): 指那些创建后可以随时修改的元素 。开发者应该致力于使业务代码作为“软件”,因为业务需求和规则总是在不断变化,因此代码也应该具有相应的灵活性和可调整性 。
固件(Firmware): 是那些与硬件紧密耦合,但具有一定的软性特点的软件 。例如,路由器的固件或Android固件 。它们为硬件提供抽象,但通常只适用于特定类型的硬件 。
通过理解这些术语,我们可以认识到数据库应视为“硬件”,而DAO在本质上属于“固件” 。然而,我们的目标是使我们的代码保持像“软件”那样的灵活性 。但是,当业务代码过于依赖于“固件”时,它会受到限制,变得难以更改 。
让我们通过一个具体的例子来进一步理解这个概念 。下面是一个简单的代码片段,展示了一个对象如何依赖于DAO(也就是依赖于数据库):
private OrderDAO orderDAO;public Long addOrder(RequestDTO request) {// 此处省略很多拼装逻辑OrderDO orderDO = new OrderDO();orderDAO.insertOrder(orderDO);return orderDO.getId();}public void updateOrder(OrderDO orderDO, RequestDTO updateRequest) {orderDO.setXXX(XXX); // 省略很多orderDAO.updateOrder(orderDO);}public void doSomeBusiness(Long id) {OrderDO orderDO = orderDAO.getOrderById(id);// 此处省略很多业务逻辑}上面的代码片段看似无可厚非,但假设在未来我们需要加入缓存逻辑,代码则需要改为如下:
private OrderDAO orderDAO;private Cache cache;public Long addOrder(RequestDTO request) {// 此处省略很多拼装逻辑OrderDO orderDO = new OrderDO();orderDAO.insertOrder(orderDO);cache.put(orderDO.getId(), orderDO);return orderDO.getId();}public void updateOrder(OrderDO orderDO, RequestDTO updateRequest) {orderDO.setXXX(XXX); // 省略很多orderDAO.updateOrder(orderDO);cache.put(orderDO.getId(), orderDO);}public void doSomeBusiness(Long id) {OrderDO orderDO = cache.get(id);if (orderDO == null) {orderDO = orderDAO.getOrderById(id);}// 此处省略很多业务逻辑}可以看到,插入缓存逻辑后,原本简单的代码变得复杂 。原本一行代码现在至少需要三行 。随着代码量的增加,如果你在某处忘记查看缓存或忘记更新缓存,可能会导致轻微的性能下降或者更糟糕的是,缓存和数据库的数据不一致,从而导致bug 。这种问题随着代码量和复杂度的增长会变得更加严重,这就是软件被“固化”的后果 。
因此,我们需要一个设计模式来隔离我们的软件(业务逻辑)与固件/硬件(DAO、数据库),以提高代码的健壮性和可维护性 。这个模式就是DDD中的资源库模式(Repository Pattern) 。
2. 深入理解资源库模式在DDD(领域驱动设计)中,资源库起着至关重要的作用 。资源库的核心任务是为应用程序提供统一的数据访问入口 。它允许我们以一种与底层数据存储无关的方式,来存储和检索领域对象 。这对于将业务逻辑与数据访问代码解耦是非常有价值的 。
2.1 资源库模式在架构中的位置资源库是一种广泛应用的架构模式 。事实上,当你使用诸如Hibernate、MyBatis这样的ORM框架时,你已经在间接地使用资源库模式了 。资源库扮演着对象的提供者的角色,并且处理对象的持久化 。让我们看一下持久化:持久化意味着将数据保存在一个持久媒介,比如关系型数据库或NoSQL数据库,这样即使应用程序终止,数据也不会丢失 。这些持久化媒介具有不同的特性和优点,因此,资源库的实现会依据所使用的媒介有所不同 。


推荐阅读