I don't really know the best way to handle exception in an multi-language application.
Where should I handle the translation of the error message (Exception.Message)?
Shall I translate the message in the ctor as soon as I throw the exception?
throw new MyException("Error message", Resource.MyException_TranslatedMessage);
Or do I throw the exception and I use a home made helper that will find the error message using the type of the exception in the logic of the View?
try
{
//...
}
catch(Exception ex)
{
myLabel.Text = new ExceptionTranslator(ex).Translate();
}
Or, does Microsoft offer a tool or a mechanism to do that?
In a word: what are the good practices to handle exception messages translation?
Most exceptions are there for technical purposes, unless your operations and maintenance crew are also located in different countries, those exceptions should simply have messages in the language of the people who write and maintain the application.
The .NET framework contains localized exception messages. For me as a developer, that's very annoying, since the exception messages in my local language (Dutch) don't mean as much as the original English exception messages. However, it seems reasonable for Microsoft to localize those framework exception messages, since their target audience can be located anywhere.
Some types of exceptions however, are explicitly thrown to be displayed to the user. These are your ValidationException or BusinessLayerException. Their clear contract is to be displayed to the user. Of course you should localize those exception messages, but instead of translating them, it's often much better and easier to pull the exception message from a localized resource when throwing the exception:
throw new ValidationException(Resources.InvalidUserName);
Much better to only translate it when it needs to be displayed, IMHO.
This applies to any localisable string, not just error messages.
Ideally, the logic of the code shouldn't care about the content - or language - of the message, it's only interested in the type of the exception. It's only the presentation layer that (might) need to display it in the local language.
The external code should not translate messages
throw new MyException("Error message", Resource.MyException_TranslatedMessage);
This is best solution in my mind
Related
I am working on re-writing a business layer for one of the apps in company. For now, the business layer will interface directly with the web client. But in the future, it will be encapsulated with service interfaces and will be consumed by the same web client.
My question is that when a validation exception or other exceptions occur in the business layer, is it okay to throw custom exceptions or would it be better to use custom objects that represent errors ... like ValidationError, etc? Is it more expensive to throw an exception vs returning an object?
The most popular thought on this today is to throw the errors towards the application layer. I guess the idea is so that the interpretation of what went wrong and telling the user is more clear there than way down in the guts of the applications.
Some people catch errors everywhere and then throw them as they go, this leaves a trail of traceable documentation for the developer.
One other interesting point, if the developer makes all the error messages contain unique identifiers, then they are easily able to debug because they can pinpoint the code just by looking for that number.
Throwing an exception is way more expensive than returning an object. Exceptions should be used only for unexpected situations. Errors in validation of user input is not unexpected and should not result in an exception being thrown.
When defining exceptions should you have separate exceptions for every type of error that can occur or a more general exception that can be used for multiple error conditions.
For example lets say that I have a class that processes strings and I want to throw exceptions if a string is not the correct format.
Would I create separate exceptions such as:
StringTooLongException, StringContainsIllegalCharactersException, StringTerminationException
or just create a single exception such as
StringFormatException
and indicate the more specific exception with an error code within the exception?
That depends. Can the receiver of the exception take any useful action depending on the type? Then yes, it would be nice to have different types. If all he can do is show the error message to the user, then different .NET types are not useful and if something has no use, it should not be done.
There are lots of existing "generic" exception types in the .Net framework, e.g., System.IO.IOException covers lots of possible IO errors, and System.Data.SqlClient.SqlException is used for reporting lots of differents types of Sql error, so I would say it is OK to use a more generic exception type, preferably one that already exists (don't reinvent the wheel).
In our app, we use components developed by other teams. The question was how can I define a nicely way of exception handling than this
try
{
someComponent.DoStuff();
}
catch (Exception ex)
{
textLabel= ex.Message;
}
The component has no custom exception type, maybe a nicely way to do it would be to define a component specific Exception type and wrap this somehow?
I know the question is very basic, but I am interested more in the let's say how it is good to do it. If you call another component with no custom defined exception types, how do you handle any potential exceptions in an elegant way?
Ideally you would have the component development team do this for you - how else do they expect their clients to recognize and handle errors from their component? Scoping the exceptions that a component can raise is a fundamental part of good C# design.
If that's not an option, then implementing your own wrapper on top of the component to taxonomize its failure cases sounds like a good second best, and very noble of you into the bargain.
If the third-party library is poorly documented (they don't specify the exceptions that can be thrown by each method), there are tools available that can Reflect into the code and determine the possible Exceptions that may be thrown. This can get a bit daunting (there are a surprising number of exceptions that can be thrown for any given call), but it's better in principle than catching the general Exception type. Here is one commercial product that performs this type of analysis.
When you catch an error you are able to repackage it and then throw another error, at the most basic level you may just be adding more data - but, from what you've suggested, you could also replace the generic error with a custom error that, whilst it won't overcome the limitations of the response you've got from the component, would give the code further up the call stack the opportunity to respond more appropriately.
So in terms of just adding information in the most basic manner - by throwing a new exception with some additional text whilst still passing the original exception:
catch (Exception ex)
{
throw new Exception("This is more about where the exception occurred", ex);
}
Now, if you want to define your own custom component exception you change the new Exception to new ComponentSpecificException adding data as necessary to the constructor but never forgetting to set the inner exception. Exceptions also have a data collection of key, value pairs into which you can insert more information (by creating the exception, adding the data and then doing the throw).
That's all fairly generic - working forward from there, where you can't necessarily anticipate all the exceptions you have to handle you don't try - you set up logging so that you know when you've got a generic exception i.e. one that hits the final catch - and then over time add exception specific catches above the generic to provide more appropriate responses or, at the very least, package up the error into less general custom exceptions.
Not sure I've explained that very well - but the notion is that as its difficult to anticipate every possible error you want to have a strategy to develop your application in a systematic fashion as you discover new exceptions.
Assuming you want to catch every type of exception, this solution looks fine to me.
Either from your knowledge of using the component, or by using something like Reflector to analyze the compiled component, what possible exceptions can this component throw? Would providing exception handlers for these allow you to provide better feedback to you users?
The only reasonable (much less "elegant") way to handle exceptions is to log them if you can't recover from them.
Then notify the user there was a problem and offer them the chance to try again (if it's an interactive program).
If your application is exclusively for .NET developers, go ahead and show them the exception message (though Exception.ToString is better, since it includes a stack trace). Otherwise, don't display exception messages in your user interface - that's a security hole and will only confuse your users.
I have an application which tries to load some expected registry settings within its constructor.
What is the most appropriate .NET Exception from the BCL to throw if these (essential, non-defaultable) registry settings cannot be loaded?
For example:
RegistryKey registryKey = Registry.LocalMachine.OpenSubkey("HKLM\Foo\Bar\Baz");
// registryKey might be null!
if (registryKey == null)
{
// What exception to throw?
throw new ???Exception("Could not load settings from HKLM\foo\bar\baz.");
}
Why not create your custom exception?
public class KeyNotFoundException : RegistryException
{
public KeyNotFoundException(string message)
: base(message) { }
}
public class RegistryException : Exception
{
public RegistryException(string message)
: base(message) { }
}
....
if (registryKey == null)
{
throw new KeyNotFoundException("Could not load settings from HKLM\foo\bar\baz.");
}
Also, instead of inheriting from Exception you could inherit from ApplicationException. This depends on the kind of failure you want your application to have in this situation.
actually, I wouldn't throw an exception here. I would have a default value, and then create the key using that default value.
If you MUST have a user-defined value, I'd use the ArgumentException (as that's fundamentally what you're missing, an argument for your constructor--where you store it is irrelevant to the type of exception you're trying to generate).
I'd go with ArgumentException or ArgumentOutOfRangeException..
throw new ArgumentException("Could not find registry key: " + theKey);
Quoting MSDN:
The exception that is thrown when one
of the arguments provided to a method
is not valid.
...
IMO writing a proper exception message is more important.
It depends on why it failed. If it's a permissions issue, the I'd go with System.UnauthorizedAccess exception:
The exception that is thrown when the operating system denies access because of an I/O error or a specific type of security error.
I don't know if it matches the "specific type", but it is a security error, and access wasn't authorized.
On the other hand, if the item just doesn't exist then I'd thrown a FileNotFound exception. Of course, a registry key isn't a file, but FileNotFound is pretty well understood.
Since this entry is as you put it an essential value, what is the impacts to your application if this value cannot be obtained? Do you need to hault operations or do you simply need to notify the application.
Also, there are a number of reasons that the value could be null
User doesn't have permission to read the key
The key doesn't exist
Does this impact the action you take when working with the application?
I think that these types of scenarios play into what exception to throw. Personally I would never throw just Exception, as it really is a "no-no" from a standard design practice.
If it is due to a user not having permissions, AND then not having this permission might cause future problems I would vote for an UnauthroizedAccess exception.
If the issue is not a critical issue, but you really need to know that the key isn't there I would strongly recommend the "KeyNotFoundException" implementation mentioned elsehwere.
When throwing an exception you want to make sure that the exception being thrown is descriptive and provides all needed information, thus why I think it depends on the root cause as well as the overall impacts to the application.
To quote MSDN's "Design Guidelines for Developing Class Libraries"
ApplicationException
If you are designing an application
that needs to create its own
exceptions, you are advised to derive
custom exceptions from the Exception
class. It was originally thought that
custom exceptions should derive from
the ApplicationException class;
however in practice this has not been
found to add significant value. For
more information, see Best Practices
for Handling Exceptions.
I think that the best approach is to take a step back. If there is not a clear cut exception that describes what is happening, it takes only minutes to define one. Try to avoid repurposing exceptions because it "is close enough".
My recommendation is that you should create a base exception class which inherits from either Exception or ApplicationException. This will allow for you to easily identify, from your stack trace, whether the exception is a custom exception that you defined or whether it originated somewhere else. All of your custom exceptions should inherit from the base exception that you create.
Note: I am not going to recommend the use of either Exception or ApplicationException. There is enough debate in the community vs. Microsoft's documentation over which should be used and for what purpose. On a personal level, I choose Exception as my base exception.
If there is not a clearly predefined exception that matches your intent, going forward, derive a custom exception from your base exception. It definitely helps in tracing down the origin of a problem, makes them easier to handle (imagine that an existing framework exception was thrown in the block of code, but by the framework or another method), and just plain makes sense.
Keep in mind, you can have multiple exception hierarchies to group like exceptions together. For example, I can have MyBaseException which inherits either ApplicationException or Exception. I then can have a more generalized MyRegsitryException which inherits from MyBaseException. Then I can have specific exceptions, such as MyRegistryKeyNotFoundException or MyRegistryKeyPermissionException.
This allows you to catch a grouped exception on a higher level and reduce the number of catches that you might have that contain redundant handling mechanism. Combine this with isolating the scope of the exceptions to specific namespaces that would use them, and you have the start of a very clean exception handling scheme.
I would probably throw an ApplicationException since this is specifically related to your application. Alternatively, you could throw a ConfigurationErrorsException, though this is usually associated with an error parsing an application configuration file, not reading the configuration from the registry.
The other potential exceptions that come to mind are ArgumentException or ArgumentNullException, but these have a connotation of being related to parameters that are passed into the method and are not, therefore, appropriate to my mind. It could easily lead someone using/modifying your code astray when trying to determine why it is not working.
In any case, a good, descriptive error message is probably the most effective way of communicating what the problem is.
EDIT: Note that throwing an exception on a null value doesn't mask any exceptions that would occur when attempting to read the registry value. I believe that any SecurityException that gets thrown when you attempt to read the value without sufficient privileges will still occur as long as you don't wrap it in a try/catch block.
I think just Exception itself could do the job. If your message is descriptive enough, then it's all good. If you really want to be precise about it, then I'd agree with petr k. Just roll your own.
Since I can't use Microsoft as an example for best practice since their exception messages are stored in resource files out of necessity, I am forced to ask where should exception messages be stored.
I figure it's probably one of common locations I thought of
Default resource file
Local constant
Class constant
Global exception message class
Inline as string literals
I may get shot (well, downvoted) for this, but why not "where you create the exception"?
throw new InvalidDataException("A wurble can't follow a flurble");
Unless you're going to internationalize the exception messages (which I suggest you don't) do you particularly need them to be constants etc? Where's the benefit?
If your exceptions are strongly typed, you don't need to worry about messages. Messages are for presenting errors to users, and exceptions are for controlling flow in exceptional cases.
throw new InvalidOperationException("The Nacho Ordering system is not responding.");
could become
throw new SystemNotRespondingException("Nacho Ordering");
In the latter case, there's nothing to translate, and therefore no need to worry about localization.
Out of necessity? It's to ease localization. To localize error messages in your applications, it's a great way.
If you are not going to show the exception messages to the user, then you need to keep them separate from the resource strings you do need to translate.
Either use string literals like Jon suggests or create a utility class to hold them if you have a lot of duplicate strings.