RE: Exception Handling Opinion 2004-12-13 - By J. Ambrose Little
I disagree that you should handle exceptions on every layer. If you can't handle an exception meaningfully, you should let it bubble. Whether this is by not handling or by wrapping it in another exception using, e.g., the InnerException property, depends on whether or not you can add any value. If you can't add value, let it bubble.
Saying that validating inventory should be a business layer function is not, IMO, to the point. If the data store is keeping track of inventory, you have to go to the data store to validate inventory. So at some point, the data tier is involved in the business rule. Clearly, if he's throwing an exception when inventory is unavailalbe, this is happening in code and the distinction between the data tier and the business tier at that level is at best blurry.
I'd only suggest that maybe checking inventory in a separate operation to avoid exceptions might be a better approach, depending on the architectural topology, i.e., whether or not it is prohibitively expensive to do so.
--Ambrose
On Mon, 13 Dec 2004 17:17:57 -0600, Robert Hanson <rhanson@(protected)> wrote: > > > I'd argue that ensuring that they "have enough inventory on hand" is a > business layer function, not a DB level function. Sure, you ought to have > constraints in the DB that won't let you create a negative inventory, but > you should never let your application try to store a record that would > cause a business rule violation > > (I won't get into the case where physical inventory and "book" inventory > get out of whack - like the time when I went to look up a price for an > item, and the computer said we had none on hand, even though I actually had > one in my hand at the time.... If that one was sold, then the inventory > would have gone negative) > > You certainly can pass information from a lower layer to the next higher > layer; but at that next higher layer, there should be code that traps > those exceptions and deals with them. One way of dealing with them is to > send a new message upwards again; but you should not be passing a message > from the DB straight up the chain to the UI. Let each layer handle the > message and decide what to do with it. > > One cleaner method is to pass a "messages" object down one layer (that is, > when you make a call from your business layer to your DAL layer) pass along > a "messages" object to that layer. I'd make the "messages" object > impliment a simple interface, where perhaps you can only "addMessage" or > "addException". This make the interface pretty clean and lightweight. > When the call returns from the lower layer, the current layer can examine > the messages object and take appropriate action. > > I appreciate your thoughts about "return values" and HResult. But by using > an intelligent object instead of a return value, you can capture a lot more > information about the exception, and pass that info back up into the > previous layer. This gives you a lot more possibilities than a single > return value, or a single exception. For example, the messages object > could impliment some logic that determines the severity of the exception, > and whether to abort the current method being executed, or just to log the > exception and continue. (And since it is the previous layer that > instanciates the messages object and passes it down, the previous layer has > control over the logic that is contained within the messages object.) > > Just hoping to trigger a few thoughts about alternatives. > > Tim Weaver <icodemarine@(protected)> on 12/13/2004 03:37:50 PM > > Please respond to aspnet-architecture@(protected) > > To: aspnet-architecture@(protected) > cc: > > > > Subject: [aspnet-architecture] RE: Exception Handling Opinion > > J. makes a great point about using exceptions to handle > non-exceptional data. The problem we faced was that at the DB layer > validations was done against the customs account to ensure they had > enough inventory available. If they didn't then some sort of message > had to go back to the UI to tell the user. > > You can certainly argue that this isn't exceptional (in fact I did > when approached about this). However, you still have the problem of > how to get the information back to the caller. You could force the > caller to wait for a return value and then build a message based upon > what was sent down the stack, but that is a lot of work spread out all > over the UI. > > If you use return values all the way up the stack then you are > basically building HResults because any given call is going to have > different data to return. We needed to have contextually aware > information returned and exceptions allowed us to do it in a concise > way. I'm still on the fence about the whole approach, but its hard to > argue that using exceptions didn't produce much cleaner/simpler code. > > We attempt to tackle all our problems with an agile approach. One of > the tenants that we adhere to (or try) is to keep things as simple as > possible. Sometimes simple is better than elegant even if it costs you > a few cycles... > > Tim > > On Mon, 13 Dec 2004 15:42:43 -0500, J. Ambrose Little > <ambrogio@(protected)> wrote: > > Eh? It can't fall (bubble) anywhere farther (higher) than the > > application level of the UI tier. And I use a plain HTML error page, > > so no errors can occur on it. > > > > In any case, IMO, using exceptions is okay as long as you only throw > > them when you cannot meaningfully handle them. Obviously, (in my eyes > > anyways), you shouldn't use them to just pass non-exceptional > > information around. But there's a reason we have exceptions and a > > framework that can catch and throw them. It can make error handling, > > particularly when developing APIs, much more robust. > > > > > > > > --Ambrose > > > > On Mon, 13 Dec 2004 22:20:33 +0200, Justin Lovell <justin@(protected)> > wrote: > > > I would not like to use exceptions. It is generally bad that the > exception > > > could possibly fall through and on top of that, is kinda expensive to > throw > > > and catch. > > > > > > Have you considered using delegates (not events)? > > > > > > > > > > > > -----Original Message----- > > > From: J. Ambrose Little [mailto:ambrogio@(protected)] > > > Sent: 13 December 2004 08:40 PM > > > To: aspnet-architecture@(protected) > > > Subject: [aspnet-architecture] RE: Exception Handling Opinion > > > > > > Well, I don't think bubbling exceptions to the user is generally a > > > good idea. If an exception occurs (bubbles to the UI tier), and the > > > UI tier can't handle it gracefully, I let it bubble to the application > > > level, which has the on error handler that logs/publishes the error to > > > the appropriate place and redirects the user to an HTML error page > > > that, obviously, just has a general error on it. You definitely do > > > not want your users to see the exception details because that provides > > > attackers with an insight into your app that you don't want them to > > > have. > > > > > > If your UI tier can gracefully handle the exception, then I think it > > > will be very context sensitive and not something that you can really > > > standardarize on with a vanilla error page using message substitution. > > > But if you want to do that, you can just use, e.g., a resources file > > > and have a static function that you pass the exception to like > > > GetDisplayMessage(Exception ex) that, based on the exception details > > > (like type name), will pull an appropriate message from your resource > > > file. > > > > > > --Ambrose > > > > > > On Mon, 13 Dec 2004 13:15:23 -0500, Tim Weaver <icodemarine@(protected)> > > > wrote: > > > > I've been going over something very similar. We already have an > > > > infrastructure that allows customized messaging so the question for > us > > > > what is the best way to get that message to the UI. The problem with > > > > exceptions is that we were seeing developers use: > > > > catch(Exception ex) > > > > { > > > > string error = ex.Message; > > > > } > > > > and then add the error string to the page. This is a really dangerous > > > > way to go (IMO). There is no guarantee that the information returned > > > > from the message property should be shown to the user. It is a big > > > > security risk to just blindly reflect error messages. > > > > > > > > The solution we ended up with is that we created custom exception(s). > > > > The base custom exception overrides the Message property and returns > > > > the "messagized" text. This way the developers can do > > > > catch(SafeException ex) > > > > { > > > > string error = ex.Message; > > > > > > > > } > > > > and always know that they will be given back text to show to the end > > > > user. They don't catch anything except the base exception and those > > > > derived from it. All other exceptions go to a generic error page that > > > > logs the issue and tells the user we had a problem. > > > > > > > > On Mon, 13 Dec 2004 11:39:41 -0500, Jason Gaylord > > > > > > > > > > > > <jgaylord@(protected)> wrote: > > > > > I am creating a new web application where I want to allow some end > users > > > to customize messages for specific business rules. For instance, if a > user > > > attempts to login, I want to kick off an exception. Then, the user > would be > > > shown a customized message. > > > > > > > > > > > > > I figure I need an HttpHandler to effectively handle the message > > > portion. However, I can't think of a good solution to raise an error or > > > throw an exception. I have other exceptions such as a 404. > > > > > > > > > > Any suggestions? > > > > > > > > > > Best Regards, > > > > > Jason N. Gaylord > > > > > Microsoft MVP, ASPInsider > > > > > http://www.jasongaylord.com > > > > > jgaylord@(protected) > > > > > --- > > > > > [This E-mail scanned for viruses by Declude Virus] > > > > > > > > > > Need SQL Advice? http://sqladvice.com > > > > > Need RegEx Advice? http://regexadvice.com > > > > > Need XML Advice? http://xmladvice.com > > > > > > > > > > > > > Need SQL Advice? http://sqladvice.com > > > > Need RegEx Advice? http://regexadvice.com > > > > Need XML Advice? http://xmladvice.com > > > > > > > > > > -- > > > J. Ambrose Little > > > Microsoft ASP.NET MVP, ASPInsider > > > http://dotNetTemplar.net > > > > > > Need SQL Advice? http://sqladvice.com > > > Need RegEx Advice? http://regexadvice.com > > > Need XML Advice? http://xmladvice.com > > > --- > > > > > > > > > [This E-mail scanned for viruses by Declude Virus] > > > > > > Need SQL Advice? http://sqladvice.com > > > Need RegEx Advice? http://regexadvice.com > > > Need XML Advice? http://xmladvice.com > > > > > > > -- > > J. Ambrose Little > > Microsoft ASP.NET MVP, ASPInsider > > http://dotNetTemplar.net > > > > Need SQL Advice? http://sqladvice.com > > Need RegEx Advice? http://regexadvice.com > > Need XML Advice? http://xmladvice.com > > > > Need SQL Advice? http://sqladvice.com > Need RegEx Advice? http://regexadvice.com > Need XML Advice? http://xmladvice.com > > Need SQL Advice? http://sqladvice.com > Need RegEx Advice? http://regexadvice.com > Need XML Advice? http://xmladvice.com >
-- J. Ambrose Little Microsoft ASP.NET MVP, ASPInsider http://dotNetTemplar.net
Need SQL Advice? http://sqladvice.com Need RegEx Advice? http://regexadvice.com Need XML Advice? http://xmladvice.com
|
|