I work for a good friend of mine on a side project and we are currently in the development stages of version 2.0. The biggest modification being a complete architecture over haul. One of the issues that I have come across involves propagating logical error messages for non-exceptional circumstances (what?) through the different application layers. Here's what I mean...
An exception occurs when the database you anticipate being available is unavailable. An error occurs when you attempt to insert a new record in the database and a duplicate entry is found. You should not throw an exception in this instance because of the over head involved in terms of performance (perf).
In a standard Enterprise application you typically have 3 logical layers - Presentation, Business Logic and Data Access. The layer separation allows a developer to keep dependencies to a minimum so that maintenance is easier. We have decided to use objects as our business components instead of DataSets (this is a .NET project) because this allows for more complicated business logic (read Martin Fowler's Patterns of Enterprise Application Architecture for more information). We are then using what's called a Gateway to map data to these objects and then return the intialized objects to the presentation layer.
Okay, now you have the background, back to the example.
Say you are trying to insert a new person's information into a database; for simplicity's sake we are just going to insert a last name and an e-mail address. Your business rules tell you that both the last name and e-mail address have to be unique (not reality I know, but it's simple). Your method call ends up looking like the following.
Person person = Person.Create( lastName, email );
The Create method might look something like this.
public static Person Create( string lastName, string email )
Person person = null;
if ( Person.FindByLastName( lastName, email ) == null )
person = PersonGateway.Create( lastName, email );
Now, if the person object being returned is null, then we can assume a duplication was found in either the last name or the email address, but how do we communicate to the user which one was the problem? Do we just say a duplicate was found and hope he/she guesses correctly or wait for the annoying tech support call?
Making two separate calls to check the last name and then the email address is a logical solution but that means going to the database twice before we even attempting to create the new record (a third trip to the database). Another suggestion would be to let the SQL handle the business logic (a no-no because that's supposed to happen in the Business Logic layer), but again how do we communicate which field was the problem.
Can anyone out there offer a suggestion?