Neither here nor there

Ovid on 2003-03-11T17:33:12

This morning, I moved two more screens from our application from the "in progress" to the "for testing" queue. This made me pretty happy as it means we're probably about halfway to completion, but I got stuck on a thorny problem that I'm still trying to decompose: auditing.

I have "handlers" that handle the application logic for a given screen. For my immediate problem, I'm dealing with a "product" screen. I have a "product" object built with Class::DBI. If someone uses the product screen to change the price of a product, an entry is made in our audit system, but where does the auditing go? On one hand, every time a change is made to a monetary value of a product, it must be audited so, in theory, this functionality belongs in the product object.

The problem: much of the information to be audited is irrelevant to the product object and is actually part of a given application. The product object shouldn't be collecting information about which application is using it or who is making the changes (should it?). Instead, this is in the application layer. However, if I push it in the application layer, a programmer might forget to audit something.

I've considered having objects self-aware about what should properties require auditing and throwing exceptions if I don't send an "audit_completed" message to them. It's not the most elegant solution, but it guarantees that I can't forget to the object.

Now to check how Class::DBI can inform me, the programmer, about what has changed without me having to dig into the internals of an object. (Update: duh. It's the "is_changed" method)


how tidy

wickline on 2003-03-11T20:15:23

Does your auditing need to be concise?

Maybe you could just follow caller() until it returns undef (or up to some appropriate max if that's a worry)... or follow caller() until it's tracked back to some srcript?

Or maybe it's time for Yet Another Level of Indirection, so that auditable things all go through an API which requires the appropriate audit log data.
    app -> YALI -> Class::DBI
               `-> auditing (as needed)
you wrote:

The product object shouldn't be collecting information about which application is using it or who is making the changes (should it?).


I've had objects (not with Class::DBI) which tried to determine who was modifying them. This wasn't a critical audit thing, but just for purposes of advisory record-change collision notices ("Bob just saved that record 2min ago and you'll want make changes from that more recent version"). In that case, each record had this metadata, and so it made sense (to me) for the object to gather that info. If I needed auditing, I would have stuck it in the object in that case.

I dunno... five hours of sleep in three days leaves my mind tending to wander a bit, but I don't think it's a universal evil for the object to care about who does what to it.

-matt