用于处理撤消和通知的架构

发布于 2024-10-11 13:04:10 字数 520 浏览 6 评论 0原文

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

通过撤消,我的意思是用户可以创建/修改/删除一个项目,然后决定取消他所做的事情(因此删除创建的项目,恢复已修改项目的先前状态,或恢复)已删除的项目)。他可以在执行该操作后短暂地执行此操作(超时时间为2分钟,因为系统相当复杂,用户可能需要一段时间才能注意到修改不正确)。

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

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

让它们一起工作会产生很多额外的复杂性,因为通知必须保持静止状态,直到无法撤消为止,而且我对此事没有足够的后见之明,无法以理智的方式设计它。

构建这样的系统时需要避免哪些模式、最佳实践或陷阱?

I'm currently designing a complex website that needs to support Undo and Notifications for CRUD operations.

By Undo, I mean that the user may create/modify/delete an item and then decide to cancel what he did (therefore removing the created item, restoring the previous state of the modified item, or bringing back the deleted item). He can do so for a short while after doing that operation (the timeout is 2 minutes, because the system is fairly complex and it may take some time for the user to notice that the modification was incorrect).

By Notifications, I mean that when an item is created/modified/deleted, other users that are interested in that item will receive an on-site notification (the next time they load a new page) and will also receive an e-mail or SMS notification if they asked for it.

Getting either feature done is simple: Undo involves keeping undo information around (old version of modified or deleted items, mostly) while Notifications are as simple as pushing a notification object into the appropriate tables and sending an e-mail/SMS on the fly.

Getting them both to work together creates a lot of additional complexity because Notifications must remain in stasis until the Undo becomes impossible, and I don't have enough hindsight on the matter to design it in a sane way.

What would be patterns, best practices or pitfalls to avoid when building such a system?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

把梦留给海 2024-10-18 13:04:10

I'd consider using the Command Pattern for Undo (possibly not persisting until the timeout expired) and the Observer Pattern for Notifications.

EDIT1: Rethinking that, I'd probably persist immediately. Otherwise you have the issue of the user's session ending before the timeout expires.

EDIT2: Another option would be to use Windows Workflow Foundation 4 (WF4) and Compensation. Set up a long-running, persistent workflow as a WCF service. The workflow could just be a WCF Receive activity to start it, a Delay activity, and a custom activity to send notifications; you might not even need a CompensableActivity (if the delay hasn't expired and the notification hasn't been sent, there's nothing to undo). Each notification request makes a WCF call to start a new workflow instance. If the user cancels, abort the instance. (It might be easier to do a Pick activity with a Delay and another WCF Receive activity that cancels the notification if called.) Caveat: I haven't implemented a system like this.

浅唱ヾ落雨殇 2024-10-18 13:04:10

基于思想和代码上的一些实验,我成功地提取了一系列原则。

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

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

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

这样,操作总是通过基本操作集,从而触发通知,而这些通知是由于取消较早的操作还是手动运行其逆操作而引起的 - 系统通过将它们分组在一起来巧妙地处理有关同一对象的多个通知并让它们互相抵消。

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

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

Based on a bit of experimenting both in thought and in code, I managed to extract a series of principles.

  • The user may cancel the operation by clicking the cancel button, or by performing the reverse operation (such as deleting his comment). From a notification standpoint, there's no reason to treat these two situations differently.
  • Notifications for the same object that happen at about the same time should, as much as possible, be grouped together: there's no point in displaying "A commented on your post" ... "Z commented on your post" instead of "A, B ... and Z commented on your post". As such, creation and deletion notifications should be grouped together according to grouping rules: if they're sufficiently close together, they cancel each other.
  • Because of the possibility of cancellation, never send notification e-mails straight away. Wait for two minutes instead. If the operation is canceled, the creation-and-deletion group rules will delete the unsent notification while it's still pending. Of course, if the user is currently connected, you may display notifications in real-time because unlike e-mail, real-time notifications can be "taken back".

Based on these principles, I decided to architecture two distinct layers on top of the data access layer:

  • A set of semantically significant operations such as "post a new comment" or "delete a comment" which are then wired to send out notifications.
  • A definition of undo-enabled operation pairs : the "undo" aspect of "post a new comment" is "delete a comment".

This way, operations always pass through the basic set of operations and thus trigger notifications that are agnostic of whether they are caused by canceling an earlier operation or running its inverse operation manually — the system cleverly handles multiple notifications about the same object by grouping them together and letting them cancel each other out.

Conversely, the "undo" facilities merely call the code from the semantic layer, without requiring any knowledge about the notifications being sent out.

Obviously, there will still be a little amount of coupling, because it sometimes is necessary to add a semantic operation only because it's the "undo" inverse of an existing operation. For instance, one can cancel the creation of a discussion, but cannot delete the message once it is sent (because there might be replies on it). So, a cancelDiscussion function might exist where a deleteDiscussion is unavailable. I suspect such situations are rare enough to safely accept.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文