评论系统设计
Posted
技术标签:
【中文标题】评论系统设计【英文标题】:Comment system design 【发布时间】:2011-08-06 09:30:54 【问题描述】:这是我目前的:
我正在为一个有很多领域、博客、教程、手册等的网站开发它。应该为每个(tblBlogComments
、tblTutorialComments
)等开发一个单独的评论表,我是尝试采用一种适合所有方法的结构。
这样,我可以将评论系统变成一个 web 控件,然后将它放到我想要 cmets 的任何页面上。这意味着我只有一套规则,一套代码文件要维护。
唯一的问题是,想出一种“好”的方法来确定(博客/教程/手册)属于哪个部分。
例如,一种解决方案是:
tblComment
-------------
Section (int)
SectionIdentifier (int)
其中 'Section
' 映射到网站每个部分的唯一值,例如:
Blog = 1
Articles = 2
Tutorials = 3
...
SectionIdentifier
是该页面的某种唯一 ID,例如:
ViewBlog.aspx?ID=5
这将是第 1 部分,标识符 5。所以现在,带有 Section = 1
、SectionIdentifier = 5
的评论意味着它是对博客条目号 5 的评论。
这很好用,但代价是可维护性和稳固的结构,因为SectionIdentifier
是匿名的,无法建立任何关系。
这个设计可以吗,还是有更好的解决方案(IE某种父表来评论?)
【问题讨论】:
IdentifierID 令人难以置信! @Martin,你是什么意思?我不太确定如何解决这个问题 :-( 部分标识符实际上可能更具语义,我会更新问题 开个玩笑... IdentifierIdentifier - 简直令人难以置信。 :-) @Martin 哦,好吧 :) 是的,这也是命名可能有点模棱两可的情况之一,这就是为什么我宁愿使用替代解决方案 【参考方案1】:好像是这样。您的评论系统包含多种评论(tblBlogComments、tblTutorialComments ......等)。我建议你采用策略设计模式。
让我们说。你有一个 IComment 接口。并且各种评论类都实现了IComment接口。
interface IComment
int ID get; set;
int Section get; set;
....
class BlogComment : IComment
....
class TutorialComment : IComment
....
还有一个只知道如何处理 IComment 的 WebControl
class WebControl
IComment _comment = null;
public WebControl(IComment comment)
_comment = comment;
当然,您需要一个 CommentCreater 来从数据库中加载评论数据并构建评论对象。
public static void main()
var creater = new CommentCreater();
IComment comment1 = creater.CreateBlogComment()
WebControl webcontrol = new WebControl(comment1);
......
IComment comment2 = creater.CreateTutorialComment()
webcontrol = new WebControl(comment2);
........
这样,您的 Web 控件就可以以相同的方式处理所有类型的评论。不管它究竟是什么样的评论。你也可以只维护 CommentCreater 来正确构建各种评论类。
【讨论】:
【参考方案2】:我会避免创建一个 id 列,该列根据同一个表中的另一列定义不同的关系。例如,在您的示例中,SectionIdentifier
可以表示任意数量的外键引用,具体取决于 Section
的值。这让我在一般原则上感到厌烦。它还保留了现代 RDBMS 平台的一些好处,因为它不受支持。
这些不同部分的总体架构是如何布局的?我使用过一些 CMS,它们要求您的每个部分共享一个公共基础实体,称其为“模块”或“插件”。然后,给定模块的每个实例都有自己的 id,用于映射到该特定实例所需的任何内容。
如果这对您来说是一个可行的架构方向,您还可以使用 ModuleInstanceID
作为 cmets 的外键。您只需要决定如何将给定类型的模块/插件注册为 cmets 的有效目标。
无论如何,您能否稍微说明一下您的部分是如何在引擎盖下组合在一起的?
【讨论】:
谢谢皮特,这都是定制的,大多数部分都是相似的结构,tblBlogEntry.ID,tblTutorial.ID 但是我们可能需要用户配置文件上的 cmets,所以 tblUser.ID 等。我可以'不要想到任何基本上不仅仅是一个 ID 字段的实例,所有部分都在不同的表中,但它们不会相互继承任何东西。 目标受众是谁?用户会定期创建自己的博客/教程/等吗?这个系统将如何使用? 用户最终会生成很多内容,是的,当然是教程,也可能是博客。系统将非常开放并被所有人使用。 除了教程/博客/文章之外还有其他的吗? 是的,新版块会在以后添加,IE,手册,可能是单独的用户博客表,街机游戏等。这将是一个相当大的网站(当前已经有一个很多游客,但很基本)。【参考方案3】:在 Codd 为关系模型设计的原始设计中,一个外键可以引用不同表中的多个主键,并且如果任何一个表包含该值,则引用完整性是有效的。
不幸的是,SQL 只是原始愿景的苍白反映,因为正如您所指出的,它不提供这种能力。
一种标准的解决方法是创建一个新关系,该关系拥有所有其他关系的密钥。但在这种情况下,这不是一个很好的解决方案,因为如果同时发生大量插入,它会产生争用点。
我处理这个问题的方法是创建一个值——我们称它为 Comment-Anchor——你可以将它放入每个有 cmets 的表中。此值(与精心设计的数据库中的所有其他键不同)应该是 GUID。然后每条评论都可以有一个评论锚,指示它所引用的值。
通过将其设为 GUID,您始终可以在博客或教程或其他内容中插入唯一值,而不会发生争用。您不必在任何地方维护评论锚的主列表,并且没有任何部分与任何其他部分竞争或被任何其他部分阻止。
这对于查找单个博客条目的所有 cmets 的正常用例非常有效,例如。反过来,从评论到被评论的事物,您可以在评论表中放置一个标志来标识正在引用哪个表,但我不会这样做。我会搜索所有的表格,也许有一个视图或其他东西。反向查询很少见,我认为维护它的基础设施没有多大意义,而且标志将是冗余数据,这是 RDBMS 的祸根。
这个系统的另一个好处是它易于扩展。如果您创建新类型的数据,或决定将 cmets 添加到现有类型的数据中,则只需将 Comment-Anchor 列添加到表中。不必在数据库端做任何额外的工作。甚至处理 cmets 的中间件部分也不需要以任何方式进行修改,因为它不知道 cmets 需要什么样的东西。
【讨论】:
这将是我建议的内容和随意未定义的外键引用之间的一个很好的折衷方案。如果您不想/不能/doesnt-make-sense 为您的部分创建一个可扩展的框架,这将是一个合理的 hack。这有点做作,但可能是可供选择的最佳可行技巧。 这看起来是个不错的解决方案,感谢您的建议!以这种方式锚定它们看起来绝对是最好的解决方案。【参考方案4】:对于表格设计,我会尽可能地模拟这种情况下的类结构。从你所说的来看,这就是它的样子(大致):
Section <- Post <- Comment
所以,你有:
-
Section 表(例如博客、文章、教程等)
一个帖子表(用于每个部分中的各个帖子)
评论表(用于每个帖子的 cmets)
每条帖子都会引用它所在的部分,每条评论都会引用它的帖子。数据库可以将引用作为漂亮、干净的外键,并且类可以根据您的应用需要在关系的一侧或两侧具有列表。
对我来说,这似乎是一个不错、简单、灵活的结构,它不会使事情复杂化,而且仍然允许您在其中挂起额外的部分,例如编辑和投票。
【讨论】:
同意——评论适用的代码部分可以来自“拥有”帖子。将Section
添加到表中将添加冗余数据,如果您经常去评论表处理来自给定部分(而不是单个帖子)的 cmets 数据,这可能是一个有用的非规范化步骤。
@Philip Kelley - 通过将部分 id 拉入表中进行非规范化的好处将非常小,除了最大规模的规模之外,完整性和维护问题的成本远远高于性能优势这种非规范化。也就是说,您是正确的,因为它可以完成:)
好的,那么你会说有一个表tblBlogComment
和字段Comment ID, Blog Entry ID
是一个更好的解决方案吗?你的意思是这样的吗?每个部分都有一个将其连接到 cmets 的表?以上是关于评论系统设计的主要内容,如果未能解决你的问题,请参考以下文章