One defect that I've been finding once and again in the past doing .NET projects is a bad exception handling strategy.
Too many times I've seen code that just places a generic try { ... } catch(Exception ex) { ... } code block to capture errors. And of course any code inside throwing generic exceptions (just with different messages).
The System.Exception class it is indeed the basis of any error that happens, but it is a bad habit to reuse it. Exception represents a fatal error, something critical unexpected.
.NET provides the System.ApplicationException class for a simple reason. To catch any exception from our applications.
It inherits from Exception, so a generic catch (Exception ex) would catch it anyway, but by using it, we differenciate between those exceptions generated by our application and those generated by external factors, like for example an OutOfMemoryException.
But if we just use ApplicationException instead of Exception we only have two layers of error levels... Why not going a step further and building a full hierarchy of exceptions?
- InvalidRuleSetException
- BLLException
- ApplicationException
- Exception
Look at that descending list... We can catch a lot of stuff from different layers:
- If something goes wrong in our BLL layer while loading a fictional RuleSet, we can just show a message to the user telling him to choose a correct one.
- If somehow the BLL components break, the presentation layer can catch it and present a "We're having technical problems, please try again later" message.
- If something goes really wrong in the setup of our web application (for example a wrongly configured IIS), we can silently keep users out of the website without showing them multiple nasty errors.
- And finally, if the server gets out of free space for the ASP.NET temporal files folder (which has happened to me too), we will avoid more ugly errors or generic IIS error descriptions...
The easy way is to stick to simple Exception throwings and catchings, but it doesn't helps your code readability. And probably, it won't help too much when the application fails and you just get a generic "Exception" in your log (it is amazing, but some people forget to at least log the full stack trace...).
And all of this can be applied to PHP too. PHP contains just two base exception classes, and a few typical derived ones.
So don't be lazy and create a hierarchy of exceptions. You, your colleages, and everyone who could use your code or the compiled components will not regret it, I promise.