C# 设计问题:使缓存的实体可变是好是坏?
这里我需要缓存一些实体,例如,内容管理系统(CMS)中的页面树。该系统允许开发人员编写插件,在插件中他们可以访问缓存的页面树。使缓存的页面树可变是好还是坏(即,有树节点对象的setter,和/或我们在ChildPages集合中公开Add,Remove方法。这样客户端代码就可以设置页面树节点的属性,并自由添加/删除树节点) 以下是我的观点: (1) 如果页面树是不可变的,插件开发人员就无法修改树。这样我们可以避免一些微妙的错误 (2) 但有时我们需要更改页面的名称。如果页面树是不可变的,我们应该调用诸如“Refresh()”之类的方法来刷新缓存。这将导致数据库命中(因此总共两次数据库命中,但我们应该避免2次数据库命中中的1次)。在这种情况下,如果页面树是可变的,我们可以直接更改页面树中的名称,使其成为最新的(因此只需要一次数据库命中) 你觉得怎么样?如果遇到这种情况,你会怎么做 提前感谢!:) 更新:页面树类似于:C# 设计问题:使缓存的实体可变是好是坏?,c#,.net,design-patterns,caching,C#,.net,Design Patterns,Caching,这里我需要缓存一些实体,例如,内容管理系统(CMS)中的页面树。该系统允许开发人员编写插件,在插件中他们可以访问缓存的页面树。使缓存的页面树可变是好还是坏(即,有树节点对象的setter,和/或我们在ChildPages集合中公开Add,Remove方法。这样客户端代码就可以设置页面树节点的属性,并自由添加/删除树节点) 以下是我的观点: (1) 如果页面树是不可变的,插件开发人员就无法修改树。这样我们可以避免一些微妙的错误 (2) 但有时我们需要更改页面的名称。如果页面树是不可变的,我们应该调
public class PageCacheItem {
public string Name { get; set; }
public string PageTitle { get; set; }
public PageCacheItemCollection Children { get; private set; }
}
我这里的问题与hashcode无关,因为PageCacheItem不会作为键放在hashset或dictionary上
我的问题是:
如果PageCacheItem(树节点)是可变的,即属性有setter(例如,名称有setter,PageTitle属性有setter)。如果一些插件作者错误地更改了PageCacheItem的属性,系统将处于不正确的状态(缓存的数据与数据库中的数据不一致),并且这个错误很难调试,因为它是由一些插件引起的,而不是系统本身
但是如果PageCacheItem是只读的,那么可能很难实现高效的“缓存刷新”功能,因为没有属性设置器,我们不能简单地通过将属性设置为最新值来更新属性
更新2
谢谢各位。但我有一件事要注意,那就是,我不会开发一个通用的缓存框架,而是在现有缓存框架的基础上开发一些API。因此,我的API是底层缓存框架和插件作者之间的中间层。插件作者不需要知道任何关于底层缓存框架的信息。他只需要知道这个页面树是从缓存中检索到的。他得到了要使用的强类型PageCacheItem API,而不是从底层缓存框架检索到的弱类型“对象”
所以我的问题是关于为插件作者设计API的问题,也就是说,使API类PageCacheItem可变是好是坏(这里可变==属性可以在PageCacheItem类之外设置)?这样看,如果条目是可变的,然后,当对象发生变化时,哈希代码很可能会发生变化 根据缓存的字典实现,它可以:
- 迷路
- 在最坏的情况下,需要重新缓存整个缓存
只要删除并替换您希望“变异”的条目就会容易得多。这样看,如果条目是可变的,那么当对象发生变异时,哈希代码很可能会发生变化 根据缓存的字典实现,它可以:
- 迷路
- 在最坏的情况下,需要重新缓存整个缓存
删除和替换您希望“变异”的条目会容易得多。首先,我假设您的意思是缓存的值可能是可变的,也可能不是可变的,而不是它所标识的标识符。如果你也指标识符,那么我会非常强调在这方面是不可变的(强调到足以让我的帖子标记为淫秽语言) 至于可变值,这里没有一个正确的答案。您已经了解了主要的正反两种方法,并且在您描述的两个选项中都有多个变体。缓存失效通常是一个众所周知的难题(正如菲尔·卡尔顿(Phil Karlton)的名言“计算机科学中只有两个难题:缓存失效和命名问题”。*) 需要考虑的一些事项: