缓存是存储库、域还是应用程序的问题?
我试图找出哪一层应该负责域驱动设计项目中的缓存(插入/删除)工作。目标是通过缓存从存储库检索的任何实体来提高 Web 应用程序的性能。
我的解决方案是分开如下:
MyApp.Infrastracture
MyApp.Repositories
MyApp.Domain
MyApp.WebApplication
我觉得既然只有Web应用程序使用缓存,那么缓存逻辑应该在这一层?然而,这感觉不正确,因为我想让网络应用程序保持轻量级并专注于提供网页。
此外,缓存不是一流的域概念,因此在域层中并不自然。
该怎么办?
I am trying to figure out which layer should be responsible for the caching (insert/remove) work in a Domain Driven Design project. The goal is to improve performance of the Web Application by caching any entities that is retrieved from the repository.
My solution is separated as follows:
MyApp.Infrastracture
MyApp.Repositories
MyApp.Domain
MyApp.WebApplication
I feel that since it's only the Web Application that utilises the cache then it should be this layer that the caching logic should go? However this does not feel correct as i want to keep the web app lightweight and focused on serving web pages.
Also caching is not a first class domain concept so does not have a natural fit in the Domain layer.
What to do?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
这是以上所有方面都关心的问题。
缓存是每层需要单独处理并且应用程序需要编排的交叉问题之一。
It is a concern of all of the above.
Caching is one of those cross cutting concerns that each layer needs to handle individually and the application needs to orchestrate.
你注意到
所以我认为你应该在你的存储库中透明地实现它。存储库旨在向域隐藏持久性的详细信息,如果您想缓存大型对象以提高性能,那么域应该不那么明智。您的存储库必须变得更加智能,当并行线程请求对象并同时改变它们时,可能会跟踪同一对象的多个副本。或者——如果可能的话——序列化对各个聚合根的访问,因为它们代表事务边界。
正如 @Oded 指出的那样,缓存确实可以在任何地方发生,如果性能存在问题,您可能会发现自己在很多地方实现它,并且每个地方的做法可能有所不同。例如,您可以缓存域中某些查询的结果,或者可以缓存整个 HTML 响应。
跨层协调的出现是因为缓存可能是一个非常容易泄漏的抽象。如果您的域对象被缓存,那么什么时候应该取消缓存它们?如果一个线程正在使用缓存对象而另一个线程没有使用怎么办?如果您正在缓存查询结果,但基础对象已发生更改,该怎么办?无论从基础设施角度还是从业务角度来看,何时失效以及如何失效都是难题。过时的查询并不总是坏事。
You noted
So I think you should implement it transparently in your repository. The repository is meant to hide the details of persistence from the domain, and if you want to cache large objects for performance, then the domain should be none the wiser. Your repository will have to get quite a bit smarter, potentially tracking multiple copies of the same object as parallel threads request objects and simultaneously mutate them. Or -- if possible -- serialize access to individual aggregate roots as they represent transaction boundaries.
As @Oded pointed out, caching can really happen anywhere, and you'll likely find yourself implementing it in lots of places if performance is a problem, and each spot might do it differently. For instance, you might cache the result of certain queries in your domain, or you might cache entire HTML responses.
The cross-layer coordination comes in because caches can be quite a leaky abstraction. If your domain objects are cached, when should they be uncached? What if one thread is using a cached object and the other is not? What if you are caching query results, but the underlying objects have since changed? When to invalidate and how to invalidate are difficult questions, both from the infrastructure perspective and the business perspective. Stale queries aren't always bad.
我完全同意 Oded 这是一个横切关注点,但它也应该对缓存项目的客户端透明。
例如,存储库的用户不应该关心项目是否被缓存。
我认为,如果缓存是解决方案的一个重要方面,那么它应该在域中明确说明,但是,您可能会发现它实际上最终成为基础设施的一部分,并通过您使用的任何 IoC 容器(静默)交付。使用。
I totally agree with Oded that it's a cross cutting concern, but it should also be transparent to the client of the cached items.
For example, users of your repository shouldn't care whether an item is cached or not.
I would argue that if caching is an important aspect of your solution then it should made clear in the Domain, however, you'll probably find that it actually ends up as part of the infrastructure and is delivered (silently) via whichever IoC container you use.
缓存可以分布在各层之间,如果您使用像 Nhibernate 这样支持多级缓存的 ORM,有时可以在域层自动实现缓存。在上层可以根据需求,例如加载用户时系统加载允许用户执行的功能,然后可以将其缓存在应用程序级别。所以这一切都取决于应用程序。
The caching could be distributed among layers, sometimes caching can be automatically achieved in the domain layer if you are using a ORM like Nhibernate which supports caches of multiple levels. In upper layers it could be based on requirement, for example when loading the user the system loads what are the functions user is allowed to do, then it can be cached in the Application level. So it all depends on the application.