干净架构中缓存位于何处

问题描述 投票:0回答:1

对于我的一个微服务项目,我决定将代码构建为控制器、服务和存储库。 API 调用路由到控制器,控制器然后调用服务,服务再调用存储库。每一层都通过接口与下一层交互,以保持事物的解耦。

一切都很好,直到我需要缓存。

想象一下,我已经有一个具有

findById(int id)
方法的 CustomerRepository 接口,并且有一个与数据库交互的实现 (
DbCustomerRepositoryImpl
)。现在由于某种原因我需要缓存这些信息。因此,我创建了一个与缓存交互的 CustomerRepository 实现 (
CacheCustomerRepositoryImpl
),
findById(int id)
执行一个简单的
cache.get()
并返回响应。但是我在哪里处理缓存未命中呢?

  1. 我可以在服务层处理缓存未命中,并在发生缓存未命中时与 CustomerRepository 的
    DbCustomerRepositoryImpl
    进行交互(并且可能写入缓存)。但这导致了服务和存储库的耦合。如果最终我决定只使用
    DbCustomerRepositoryImpl
    ,那么我将有不需要的代码来处理服务中的缓存缺失,或者在最坏的情况下,需要在服务中进行一些代码更改。
  2. 我可以在存储库层处理缓存未命中 -
    CacheCustomerRepositoryImpl
    将首先检查缓存,在缓存未命中的情况下,与
    DbCustomerRepositoryImpl
    交互并将结果返回给服务。这看起来很好,因为根据我的说法,存储库层应该只获取数据,无论来自哪里,对服务层来说都无关紧要。但这有一个陷阱。如果我需要缓存业务逻辑的响应,我该怎么办?服务层会调用
    CacheCustomerRepositoryImpl
    然后调用服务层吗?这种在应用程序中添加了我试图避免的循环依赖。

我可以想到这两种情况,每种情况都有自己的优点和缺点。但我需要一些帮助来找出哪种情况可能更好,或者是否有更好的方法在干净的架构中进行缓存。

caching repository-pattern clean-architecture hexagonal-architecture
1个回答
0
投票

对于大多数应用程序来说,缓存是一个技术细节,在清洁架构中,应该位于接口适配器层。

为了缓存来自存储库的数据,我将应用装饰器模式。您的 CachingRepository 实现与实际存储库相同的接口,将缓存实现和真实存储库作为构造函数依赖项,然后始终首先在读取时检查缓存,并在缓存未命中的情况下回退到真实存储库。它会在写入 API 调用时更新缓存。 另请参阅:https://youtu.be/e_-bf93vx10?si=LxN8jbHKmhu5PgRe

如果您还需要缓存业务逻辑响应,我会在控制器级别添加单独的缓存。在 Asp.Net 中,这可以通过自定义中间件轻松完成。

© www.soinside.com 2019 - 2024. All rights reserved.