This post originated from an RSS feed registered with .NET Buzz
by Udi Dahan.
Original Post: Exceptionally speaking, that is
Feed Title: Udi Dahan - The Software Simplist
Feed URL: http://feeds.feedburner.com/UdiDahan-TheSoftwareSimplist
Feed Description: I am a software simplist. I make this beast of architecting, analysing, designing, developing, testing, managing, deploying software systems simple.
This blog is about how I do it.
After a much needed ( and more than slightly protracted ) break - from blogging as well as work - I return to flog the dead horse back to life.
Exceptions, what are they, and how to deal with them.
The topic flares up now and again, and I thought I'd rekindle the flames after a recent epiphany. The epiphany came, of all times, in the middle of my recent talk on SOA at the Israel .Net Software Architects group. Attendance was high, as were some tempers, as I told the group of by-definition-smartest-people that layered architectures (LA) were "bad" and that SOA was "better". And then came the question about how SOA handles exceptions, and if it was any different than how LA does. I started with my regular spiel about structured exception handling in .Net, moving into the uses of strongly typed exceptions, and ( at the time thinking of ) wrapping up with the discussion of exceptions for exceptional cases etcetera.
All of a sudden it hit me. Strongly typed exceptions aren't meant to be caught ! I think that this trounces the linchpin argument of those who argue against using exceptions except in exceptional cases.
I'll expound a bit on the above statement. Strongly typed exceptions like "StringTooLongException" and "UserDoesntExistException" are there so that the author of a library can communicate to his users ( the developers using the library ) how they must work with it. I guess that this question has been plaguing library developers ever since we started pulling code apart into libraries - how do we force other developers to use our code properly. "Force" might be to harsh a word, but the general idea is to prevent the "garbage-in-garbage-out" cycle.
As it turns out, strongly typed exceptions aren't meant to occur at run time. The cycle changes. What is now seen is this:
Developer who uses library ( Dev ): "I'll pass these parameters to this call"
Library ( Lib ): StringTooLongException - first parameter
Dev: "OK, fix that up, and try again"
Lib: UserDoesntExistException
Dev: "Hmm..., well, how can I make sure that the use passed in exists ?"
( Dev is now forced to look at documentation and finds a preceding call that should be made )
Dev: "OK, let first call Lib.DoesUserExist(myUser), and only if it returns true, go on to the next call."
( Dev changes code to something like:
If ( Lib.DoesUserExist(myUser) ) Lib.DoSomethingWithUser(myString, myUser);
which won't ever cause a UserDoesntExistException )
Dev ( very pleased with himself ): "Lets move on to the next bit of functionality."
*
Well, I think that the library developer can give himself ( or herself ) a pat on the back. The users of their library find out quickly, at development time, the proper way to use the library, and, at run time, no exceptions need to be thrown, thus not adversely impacting performance.
In essence, these strongly typed exceptions are a way to communicate, and, it turns out, quite effectively. I've seen this work time and time again, always resulting in the same optimized outcome. The library creator and user need not ever meet, and yet, the library is used exactly as it was intended, without a performance hit at run time.
Flaws in this scheme ? Well, I haven't found any yet, but if you have - don't hesitate to let me know. I'm always looking for ways to better the development process. :)