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)