WebObjects/Web 应用程序/开发/审计跟踪
这在很多地方都会被讨论,因此有很多例子。例如,这是我在谷歌上找到的其他人实现的:http://web.archive.org/20050215013412/homepage.mac.com/i_love_my/code.html
然而,除非你疯了,需要记录对每个对象的每个更改,否则在许多情况下,“审计跟踪”的概念最终会成为应用程序特定的。如果可以简化需求,请务必这样做。例如,在 www.marketocracy.com 上,我们从未“删除”基金,我们只是将其标记为已删除。类似地,在论坛中,我们不会“删除”我们不想显示的论坛帖子,我们只是将其“隐藏”。
我们不能删除基金,因为它们与太多对象交叉链接,但我故意设置了论坛帖子,使其不可删除,因为我知道总有一天会有人“Oops”(他们确实做到了)。因此,这些表有一个标志,并且关系被定义为忽略“已删除”对象。
为了在 www.marketocracy.com 上进行“预测和回忆”,我们已经记录了每一笔交易,因此在业务逻辑中添加方法以使您可以“时间旅行”到任何时间点非常容易。也就是说,交易会为您的账户添加股票,同时从您的现金中扣除(反之亦然)。因此,在任何时间点的任何头寸上的股票都是 sum(trade.shares where date < desired time)。因此,我们能够避免对审计跟踪的需求,因为我们已经有了一个“会计模型”,其中每次操作都被记录为交易。事实上,如果我必须重新做 Marketocracy,我可能会将其实现为一个双重记账系统。
如果我要记录对每个对象的每个更改,一些典型的提示是,如果您子类化 EOEditingContext,那么在任何 saveChanges() 操作之前,您可以获得已插入/删除/更改的对象列表(您必须先调用 processRecentChanges())。如果我要设计这个,我会让我的所有 EOF 对象都有一个共同的超类/接口,它实现了类似于
auditTrailChanged() auditTrailInsert() auditTrailDelete()
然后,我可以逐个类地决定该怎么做。这可能包括插入额外的对象等。例如,一个对象可以将其自己与快照进行比较,如果它已更改,它可以将旧值和新值记录到一个通用对象中,该对象存储 AuditTrail(类名,对象的 主键,用户名,时间戳,属性,旧值(字符串),新值(字符串)。
在伪代码中
override saveChanges() self.processRecentChanges() foreach obj (self.changedObjects) obj.auditTrailChanged() foreach obj (self.insertedObjects) obj.auditTrailChanged() foreach obj (self.deletedObjects) obj.auditTrailChanged() super.saveChanges()