【问题标题】:Architecture for handling both Undo and Notifications处理撤消和通知的架构
【发布时间】:2011-06-08 13:51:43
【问题描述】:

我目前正在设计一个复杂的网站,该网站需要支持 CRUD 操作的撤消和通知。

撤消,我的意思是用户可以创建/修改/删除一个项目,然后决定取消他所做的(因此删除创建的项目,恢复修改项目的先前状态,或带回已删除的项目)。做完那个操作后他可以做一小会儿(超时时间是2分钟,因为系统相当复杂,用户可能需要一段时间才能注意到修改不正确)。

通知是指当一个项目被创建/修改/删除时,其他对该项目感兴趣的用户将收到现场通知(下次他们加载新页面时) ) 并且如果他们要求,也会收到电子邮件或短信通知。

完成任一功能都很简单:撤消涉及保留撤消信息(主要是修改或删除项目的旧版本),而通知就像将通知对象推入适当的表并发送电子邮件/短信一样简单苍蝇。

让它们一起工作会带来很多额外的复杂性,因为通知必须保持静止,直到撤消变得不可能,而且我没有足够的事后诸葛亮以理智的方式设计它。

在构建此类系统时应避免哪些模式、最佳实践或陷阱?

【问题讨论】:

    标签: architecture notifications undo


    【解决方案1】:

    我会考虑将Command Pattern 用于撤消(可能不会持续到超时到期)Observer Pattern 用于通知。

    EDIT1:重新考虑这一点,我可能会立即坚持。否则,您会遇到用户会话在超时到期之前结束的问题。

    EDIT2:另一种选择是使用 Windows Workflow Foundation 4 (WF4) 和 Compensation。将长期运行的持久工作流设置为 WCF 服务。工作流可能只是一个启动它的 WCF 接收活动、一个延迟活动和一个发送通知的自定义活动;您甚至可能不需要 CompensableActivity(如果延迟尚未过期且通知尚未发送,则无需撤消)。每个通知请求都会调用 WCF 来启动一个新的工作流实例。如果用户取消,则中止实例。 (使用 Delay 和另一个 WCF Receive 活动来执行 Pick 活动可能会更容易,如果调用它会取消通知。)警告:我还没有实现这样的系统。

    【讨论】:

    • 这确实是我独立处理事情的方式。我正在寻找一种特定的模式,可以让我同时做这两件事。
    • @Victor - 如何在不违反 SRP 的情况下? en.wikipedia.org/wiki/Single_responsibility_principle
    • 根据用户要求,通知必须是撤消感知的,反之亦然。虽然保持 SRP 是一件好事,但我宁愿牺牲 SRP 而不是牺牲用户体验。我想我是在寻求一种通过尽可能少地损坏 SRP 来做到这一点的方法。
    【解决方案2】:

    基于思想和代码的一些实验,我设法提取了一系列原则。

    • 用户可以通过点击取消按钮取消操作,或者执行相反的操作(例如删除他的评论)。从通知的角度来看,没有理由区别对待这两种情况。
    • 应尽可能将几乎同时发生的同一对象的通知组合在一起:显示“A 评论了您的帖子”...“Z 评论了您的帖子”而不是“A、B ... 和 Z 对您的帖子发表了评论”。因此,创建和删除通知应该根据分组规则组合在一起:如果它们足够接近,它们就会相互取消。
    • 由于可能取消,切勿立即发送通知电子邮件。而是等待两分钟。如果操作被取消,创建和删除组规则将在未发送通知仍处于挂起状态时将其删除。当然,如果用户当前已连接,您可以实时显示通知,因为与电子邮件不同,实时通知可以“收回”。

    基于这些原则,我决定在数据访问层之上构建两个不同的层:

    • 一组语义上重要的操作,例如“发布新评论”或“删除评论”,然后连接以发送通知。
    • 启用撤消操作对的定义:“发表新评论”的“撤消”方面是“删除评论”。

    这样,操作总是通过基本操作集,从而触发通知,这些通知是由取消先前的操作或手动运行其反向操作引起的——系统巧妙地通过以下方式处理关于同一对象的多个通知将它们组合在一起并让它们相互抵消。

    相反,“撤消”工具只是从语义层调用代码,不需要任何关于发送通知的知识。

    显然,仍然会有少量耦合,因为有时需要添加语义操作只是因为它是现有操作的“撤消”逆操作。例如,可以取消讨论的创建,但一旦发送消息就不能删除消息(因为可能会有回复)。因此,cancelDiscussion 函数可能存在于 deleteDiscussion 不可用的位置。我怀疑这种情况很少见,可以安全地接受。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-28
      • 2010-09-30
      相关资源
      最近更新 更多