You do have many options and, you are right, it can be confusing which direction to take.
It sounds like you are already on the right track understanding that your auditor should be a separate entity from your other business objects. The question then becomes how to communicate audit information between your business objects and your auditor.
If you are dealing with a pretty fixed application, you could code calls to the auditor in your business objects just as you would include Trace statements. This becomes tedious if the project is pretty active and you have many developers working on it - trying to make sure everyone puts the necessary instrumentation in the code is always difficult. There are ways through base classes and delegation that much of this can be abstracted, however. In any event, going this route will require you to put calls into your business objects whenever you want an audit record created.
The Observer pattern frees you from having to do anything within your business objects to support auditing. You would instead have to code your auditor so that it "listens to" or "observes" your business objects and writes audit information as appropriate. You do this by wiring up event handlers in your auditor that responds to events from your business objects. So, for instance, if you want to write an audit record when your BO is saved, the auditor should wire-up to the Saved event on the BO. This works great but can be cumbersome if your object model is dynamic. You'll have to be very diligent about wiring and unwiring objects every time one is created or removed.
Aspect-Oriented Programming (AOP) is another route. There are some existing AOP logging-type solutions out there that use an attribute and configuration-based approach to extending your business objects with auditing capabilities. I'm not a huge fan of AOP in .NET, but that's just my opinion and I've seen plenty of instances where it has been used successfully on projects.
Hope that helps.
Fintanv:We do auditing at the database table level. Each table has an equiv. <table>_audit. We then use triggers to capture the change (insert, update, delete), who made the change, what the original data was, and what it was changed to. No business objects involved.
We just have “last changed by” column in table you
need to audit. As you are setting this column, you can use its value in
auditing table. Alternatively you can pass in user into to each SP.
Sergey Barskiy
Principal Consultant
office: 678.405.0687 |
mobile: 404.388.1899
Microsoft Worldwide Partner of the Year | Custom
Development Solutions, Technical Innovation
From: bpb2221
[mailto:cslanet@lhotka.net]
Sent: Friday, January 09, 2009 2:44 PM
To: Sergey Barskiy
Subject: Re: [CSLA .NET] How do you audit your business objects?
Fintanv:
We do auditing at the database table level. Each table has an equiv. <table>_audit. We then use triggers to capture the change (insert, update, delete), who made the change, what the original data was, and what it was changed to. No business objects involved.
How do you determine who made the change from SQL?
sergeyb:We just have “last changed by” column in table you need to audit. As you are setting this column, you can use its value in auditing table. Alternatively you can pass in user into to each SP.
The short answer is that auditing is not usually part of the use case that created the need for the business object. Auditing is usually a system-level concern. Thus, you could argue that adding the auditing functionality to the BO breaks the Single Responsibility Principle.
Stepping away from OO theory, separating the auditing function from your BO's makes the BO's easier to maintain. It also allows the auditing functionality to be centralized, making it easier to manage as well. Lastly, it allows the auditing system to more easily change over time. It's not uncommon for systems that use BO's to audit to later switch to a database-based system, or vice-versa.
HTH
- Scott
Keep in mind though, that not all databases or data access technologies support the same features. Triggers are a good example. If you know for a certainty that you will only ever be developing for a single database, then absolutely make the most of what that platform offers. For some of us, we have to support multiple platforms (not to mention the never ending argument about how much logic should be in sprocs) so we have to design for data-agnosticity and have to develop to the lowest common feature set. This is where AOP and other approaches have given us great solutions with complete flexibility at the back-end.
Scott, SOP.
Thanks for that, particularly as you answered on a Saturday.
I haven't myself implemented auditing todate. But it seems to me that it is the required functionality of the auditing that will determine how it will be implemented in a CSLA environment.
As I getnerate my BOs from an Applicaion definition I will gernerate support for the BOs to be audited, Then providing an Audit service that can be configured on a per implementatation basis to suit the customers' specific audit requirements should provide the most flexible and portable approach.
You guys have been most helpful, thanks again.
Regards
Simon
Copyright (c) Marimer LLC