Delphi - Database persistence, consistency and change resilience.

Delphi - Database persistence, consistency and change resilience.

We are looking at creating a unified audit trail log system, and in that respect, we have a challenge.

We want to log ObjectTypeId, ObjectInstanceId, Context, Verb (+time/user/app/comment/etc)

Here is the challenge.  How to ensure that the ObjectTypeId is the same in all databases, remains the same over time (as types come and go), is source code name change resilient, and has a minimum of in-code-maintenance overhead.

- Can't hash the class name, as it may change.
- Can't use only a factory, as the number of, and order of items may change.

Current two options...

1. A virtual abstract function in the base class, and overrides for each class - which still also requires a constant, but a certain risk for forgetting to change the value, and we have a LOT of classes

2. RegisterObjectTypeID(const_SomeTypeId: Cardinal; TSomeType: TClassOfBaseType);
But - this also requires creating a new constant every time, and ensuring that you actually call RegisterObjectTypeID for each type.

Currently leaning towards one - and only override for classes that will be using the audit system.

Are there other patterns that may apply to this?

Comments

  1. With 1, if you forget to override, you'll end up with a garbage log rather than an audit log ;)

    The problematic aspect of your spec is that you start from a technical name (the classname) and want it resilient, which is impossible, f.i. what if you have a single TFoo which at a later time becomes TFooParent + TFooChild? 
    There is also the case of the same classname present in multiple units, or when TFoo is deleted from Unit1 and another (unrelated) TFoo is added to Unit2.
    Thus the name resilience is not just fragile, it's also more likely to result in garbage than audit :)

    A safe audit log would be thus be to log a type id that is derived from unitname + classname + version, ie. log only hard, cold, truth, and then unify these in an external db for human auditing purposes.

    This makes your log foolproof, which is the #1 property an audit log should have.

    You can then use your db to coalesce the log into business, user or domain audits, doing straight matching on the unitnames/classnames most of the time, and manual matching to handle the name changes and other edge cases.
    The db would also assist you in finding all those edge cases, and wouldn't require the developer to write perfect code.

    ReplyDelete
  2. Good observations and food for thought, Eric Grange.

    ReplyDelete
  3. maybe use attribute on class type? in this way, you can avoid renaming issues

    ReplyDelete
  4. Not very different from the maintenance required for a virtual method, IMO.

    ReplyDelete

Post a Comment