As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 10 years ago.
In writing the code that throws the exception I asked about here, I came to the end of my message, and paused at the punctuation. I realized that nearly every exception message I've ever thrown probably has a ! somewhere.
throw new InvalidOperationException("I'm not configured correctly!");
throw new ArgumentNullException("You passed a null!");
throw new StupidUserException("You can't divide by 0! What the hell were you THINKING??? DUMMY!!!!!");
What tone do you take when writing exception messages? When going through logs, do you find any certain style of message actually helps more than another?
A conversational tone in system messages makes the software look unprofessional and sloppy. Exclamation points, insults, and slang don't really have a place in polished exception messages.
Also, I tend to use different styles in Java for runtime exceptions and checked exceptions, since runtime exceptions are addressed to the programmer that made the mistake. Since runtime exceptions might be displayed to end users, I still "keep it clean," but they can be a little more terse and cryptic. Checked exception messages should be more helpful, since it may be that the user can fix the problem if you describe it (e.g., file not found, disk full, no route to host, etc.).
One thing that is helpful, in the absence of a specific field on the exception for the information, is the offending data:
throw new IndexOutOfBoundsException("offset < 0: " + off);
Just be matter of fact. Include all the information you're likely to need when debugging, but no more than that.
The only time I'd include an exclamation mark in an exception message is if it indicates that something really, really bizarre has happened. Most errors aren't really bizarre, just the product of an incorrect environment, user error, or a simple programming mistake.
I try to mirror the tone, grammar and punctuation style of the framework against which I'm coding. You never know when one of these messages might actually make it out in front of a client or user, so I keep everything professional, non-judgmental and specific enough for troubleshooting -- without being so specific as to give away any security issues in the code.
I avoid exclamation marks in all strings (UI and exception) like the plague, except (ocasionally) in my unit tests.
Taking responsibility, even when it really was the user's fault, is the best option I've seen.
Things along the lines of "I can't find the file you wanted, would you check to see I have it correctly?" or "Something went wrong. Dunno what, but the only way I can get fixed is by stopping. Please restart me."
Concise, detailed and little redundant information (i.e. ArgumentNullException obviously involved a null).
But here's the best i've read for a while, first answer to this.
I wouldn't use exclamation marks too much. They express too much, think about the fact that "No disk in drive!" can be read as "No disk in drive you crazy user." ;)
I think that it's wise to throw exceptions that contain internationalized text. You never know who will use your code, catch your exception and display the text to the user.
So that would be:
throw new MagicalException(getText("magical.exception.text"));
I also recommend wrapping the underlying exception (if you have one) when throwing it. It really helps debugging.
Don't think that runtime exceptions won't be seen by the user. If you are logging to a file appender some curious user might just open the log and peek into your dirty secrets.
I find the most helpful messages provide:
A consistent format that makes it easy to understand what they're telling you.
A time stamp, so you can get a feel for the dynamics of your program.
A terse summary of the error. If you provide tech support, add an error code for quick identification.
An explanation of what went wrong, differentiating between an invalid user input and a coding error.
Detailed information, including the line of code or values involved.
And most important:
They tell the user how to fix the problem.
Example: Error 203 (Timeout) in commit.c line 42:
Unable to save salary data for user 'Linus' to database at '10.10.1.21'
after 1500ms. Verify database address and login credentials.
One of the hardest lessons to learn is that your users are far less interested in the internals of your code than they are in getting their jobs done. Make it as easy as possible for them to do their jobs, and you've added tremendous value to your software.
I tend to work my exception messages into the exception themselves. E.g. a file_not_found should say "file not found". Specific data should only be included if the user can't figure it out; in this case, the user knows the filename, so I don't add that data. Formatting can be done by whatever outputs the information if necessary, so I try to make them as friendly to reformatting as possible.
Polite, terse, simple, specific. Often, including state values in message is helpful.
Related
I need to make a short premise: I am a software architect with more than 20 years of experience, not a junior asking directions. This is not to say "I know it all" (quite the contrary in fact) but just to give context and state that I have come across a legitimate doubt about something I thought was common knowledge and best practice and have done so for all this time.
I am working on different projects for different clients. I always check method's parameters for not being null and for other non valid states. A common precondition check you can find in my code is:
if (param == null) { throw new ArgumentNullException(nameof(param)); }
or
this.myField = myParam ?? throw new ArgumentNullException(nameof(myParam));
Also bear in mind that I use exceptions sparingly, I do not do user input validation with exceptions, I just use them to check and/or signal invalid states in the code, thus programming errors. It's extremely rare to find a try/catch block in my code at all.
One of my clients just asked me, without much margin to debate, to replace any similar occurrence with the use of custom exceptions. Meaning I am to define a CustomerNameArgumentNullException, CustomerNameFileNotFoundException, etc. and use those wherever I would use a standard exception.
Now I will comply, I have no right to debate the client request, but their lead programmer was pretty strong about this point on how this is the right way to go, that using default exceptions makes code less readable and also that custom exceptions make more easy to see what-is-what in Azure Application Insights. I tried to point out that he has the fully qualified name of the method that raised the exception so he can know which program, in which assembly and namespace and such but again, there was not much room to debate and it was not my place to do so.
So I've been wondering if he's actually right and I've been doing exceptions wrong all this time. If anyone has some more insight and/or some material I can read about that supports this theory.
Thanks.
While normally I'd suggest that a question like this should be closed as opinion-based, in this case there's really clear guidance from Microsoft:
Use the predefined .NET exception types
Introduce a new exception class only when a predefined one doesn't apply. For example:
Throw an InvalidOperationException exception if a property set or method call is not appropriate given the object's current state.
Throw an ArgumentException exception or one of the predefined classes that derive from ArgumentException if invalid parameters are passed.
In other words, your customer is asking you to go against guidance from the platform authors.
You may not be able to change the customer's mind to follow the guidance, but you can be confident that your approach is the recommended one, and their approach goes against that.
Following conventions like this is particularly important in Open Source projects - it's one thing to decide that you'll have your own conventions when only your team will work with the code, but if an application uses 10 different Open Source libraries, each of which has decided to create its own conventions, that's a nightmare.
There are two sides of the coin. Sure MS recommends this
Using custom exceptions gives you some advantages and disadvantages.
Advantages:
Abstraction
You can log telemetry data before you raise an exception. If not for custom exceptions, you'd have to catch an exception, log data and re-throw.
Customizing exception and error handling as needed by the app/services, etc
Disadvantages:
Telemetry data will have no stack trace if you are throwing custom exceptions.
Code maintenance and rigorous testing
There are various other things that come into picture, but catching an exception, logging metrics and then re-throwing (to preserve stack trace) the same exception is expensive.
Just my thoughts.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 5 years ago.
Improve this question
For the software we're developing at the company that I work for, we use a third-party library which is developed by a guy that we're constantly in contact with. His code is written in C++, and we use C# in the project.
Normally, his library functions return error codes. I decided to have different exception classes to cover different ranges of error codes. For example, one exception class for parameter handling errors, one exception class for main operation errors, one exception class for input value errors and so on.
He thinks it's not a good idea, and suggests using one exception class for the library that catches all the errors, and then fetches the error code from an XML file and outputs the problem to the user. He thinks, it's pointless to write more than one exception class. And also he says that he can't promise that the error codes will be the same in different versions of the library.
I think it's a good idea to have more than one exception class because:
There may be different situations that we need to handle the problem differently. Maybe when there's a parameter exception, do other stuff than just outputting an error. But he thinks his library is handling everything, and we should just stop the operation and output an error. I also can't think of many concrete examples of cases we need to handle differently, other than showing an error message. But I feel we may need it, and I'm afraid that I'm just violating the YAGNI principle.
I think if he turns out wrong, and we need to handle things differently in different cases, I'll have to introduce conditional code (if error was A then do this, if B then do that). And it will be difficult to handle.
I think it's a better idea to develop the program in a way that we can handle different types of exceptions differently. But then the guy has much more experience than me, plus he has much more credibility in the company (I'm a new intern) and I'm pretty new to software development and I feel like maybe he's right and I'm just trying to add extra code because it looks pretty, and violating the YAGNI principle.
Do you think we should go with one class or more? And if you think we should use more than one exception class, what are your reasons?
If the error codes can change from version to version, then no amount of work (or lack of it) is going to save you trouble of having to remap these somehow at some point. If you have exceptions for codes (or code ranges) then it's hardly going to be much more work than if you didn't have, when error codes do change (you're going to be rearranging what exceptions are thrown, just as you would have to be jiggling the messages around for one exception if you didn't have dedicated classes).
Besides, in general practice, by .NET convention, you should create a dedicated exception class for specific exceptions that aren't aptly covered by BCL-provided exceptions (excluding use of the some in there that are meant for abstraction only).
For some Microsoft input, consider this:
Applications and libraries should not use return codes to communicate errors.
And this:
Consider throwing existing exceptions residing in the System
namespaces instead of creating custom exception types.
But, following the Exception Design Guidelines,
[will] help ensure that you use the existing
exceptions, where appropriate, and create new exceptions where they
add value to your library.
Stick to your guns.
You're right. It's better to use several exception classes for different types of errors (for different error codes). Exceptions are somewhat successors of error codes, so it's better to use exception. And the approach that guy is offering is again using error codes, wrapped by one exception class.
SqlException with his Number comes on my mind. It's a hell to catch different types of errors by checking error code.
You should definitely use more than one exception class. Note though that there are a ton of built in classes already made in the System namespace such as ArgumentNull and friends.
If you want to see a case where multiple exceptions aren't used, take a look at COM interop. It's a dark place with generic exceptions thrown and their reasoning being justified by a single integer HRESULT. Trust me, you don't want to recreate that.
One really specific use case though is for instance whenever you just want to catch a certain exception. i.e.
try
{
lib.OpenFile(mypath);
}catch(FileNotFoundException e)
{
//handle gracefully and possibly "ignore" this error
}
Here, you want to do some other action if the file isn't found. However, if OpenFile throws an exception because mypath is null, you probably want this exception to bubble up and throw an error. (at least so you can log it or something). With a single exception class, this becomes more painful
catch(MyException e)
{
if(e.Reason=10)
{
}else{
throw; //rethrow exception(which makes debugging more difficult)
}
}
Consider a C# GUI application which uses a FileStream to read a file, chosen by the user through an "Open File" dialog.
In case the read fails with one of the exceptions, what is the correct way to report the failure to the user, in an user-friendly manner?
Should I invent my own message for each of those exceptions, or is there a way of obtaining a localized, user-friendly message that I could present verbatim to the user?
Edit
I'm asking whether .NET itself is able to provide me with a descriptive string that I can present (and which would be consistent with other .NET programs). I know that I can roll up my own, but I'd like to avoid that if there's a standard alternative.
You can have a set of localizable user exceptions with one of them being say FileUploadError. You can put a localized general information there. Throwing a few technical details might be a bit challenging, as it can be quite hard to get the right balance between technical details and a simple step that a user needs to take to fix an error.
My suggestion would be:
Have one user level FileUploadErrorException
Have a details property in it
Depending on the actual exception, suggest a user to try a few things
If you are catching an exception thrown by one of the .Net framework's File classes, then it is likely that the contents of the exception's .Message property will already be localized. The .Message property is supposed to contain localized, human readable text. How 'friendly' it is depends, I guess, but it might contain something you can embed within a more general and friendly paragraph.
Assuming you might write some method AlertUserWithMessage() to display the error to the user, this might be useful:
try
{
fileStream.Read(...); // or some other operation
}
catch(Exception e)
{
AlertUserWithMessage(e.Message);
}
If you want to include additional information that might be helpful to a support person diagnosing the problem, then you can also get the stack trace as a string from the exception.
try
{
fileStream.Read(...); // or some other operation
}
catch(Exception e)
{
AlertUserWithMessageAndStackTrace(e.Message, e.StackTrace);
}
Exception messages are by nature technical and describe what went wrong (at implementation level), as opposed to how to solve an end user's problem. On the other hand the intent of an error message presented to the user is to explain what failed and what action to take to remedy the problem. Exceptions messages and end-user error messages don't have the same purpose and aren't written for the same audience.
So for decent user experience, it is much better to map these exceptions to localized user-friendly advice on how to get around the problem. Sure, for technical users it could be nice to have some diagnostic feature that could give details of the exception (in which case having exception messages in English doesn't matter that much--English is really the world's technical language), or just point them to a log with all the details. But just throwing an exception message, even localized, at an end user is likely to baffle them.
For this reason I don't think localizing exception messages is much use. It's true that the .NET framework has localized exception messages for major languages, but I think that's more because there are developers who use these languages as their base language and do not necessarily have a good command of English. So the audience of these localized exception messages is still developers, not end users of a software product built in .NET.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 6 years ago.
Improve this question
I currently support an application at work that was originally written by a team of four but has now reduced to just me. We recently got a contractor in to look at some performance issues while I'm occupied with other things.
While the contractor has appeared to do a good job with the performance, they have also gone through large amounts of the code replacing the pre-existing style with their personal preference.
Unfortunately we don't have a coding standards doc, just a general rule to adhere to c# general rules.
As an example of what they've done, it includes:
removing nearly all the uses of the 'var' keyword
Anywhere with an if statement and a single line, they've added curly braces
Removing most of the lambdas and replacing it with more verbose code
Changing method signatures so every parameter is on a separate line rather than one line
We also operate a TDD policy but the test coverage, especially on the performance specific parts, is very low leaving very little documentation on what they've changed and making it even harder as their checkin comments aren't particularly helpful and the actual functional changes are lost amongst the swathe of 'tweaks'.
How do I talk to the contractor about this? Obviously there's not much impetus on them to change it given they have no responsibility to support the project and they don't seem particularly receptive to change.
Or should I just put up with it for the short duration of the contract then change everything back to the code formatting we used before?
Made community-wiki 'cos there's probably not one right answer here.
Anywhere with an if statement and a single line, they've added curly braces
This one and the only one may be beneficial.
removing nearly all the uses of the 'var' keyword
Removing most of the lambdas and replacing it with more verbose code
Changing method signatures so every parameter is on a separate line rather than one line
These ones make little sense to change.
Tell him he's not authorized to restyle code. You won't be paying for the time wasted for these activities and they'll have to use their own time to put things back. That should provide a refreshment.
These things should be discussed in advance. You should state clearly what activities are allowed and what not. Not a long ago there was another similar question here about a contractor who would put his initials all over the code including database entities. It was some perverse kind of self-promotion for which there is no place in someone else's code.
P.S. There may also be a possibility that by doing all these things your contractor is artificially creating extra workload to bill you more hours.
I'm a contractor (sometimes) and if I did this I would expect to be shown the door with great speed and no payment. Seriously, this person is hired by you and should be doing exactly what he is told to do, no more and no less. And don't worry about being "nice" - contractors don't expect that from permies.
How do I talk to the contractor about this?
Politely: explain why you want to minimize changes to the source code.
ALternatively, have a code inspection of the changes before check-in: and don't allow check-in of changes that you don't understand/don't want/haven't been tested.
Implement FxCop - this should be your first line of defense. Also if you use source control (if you don't then implement one ASAP), make sure to use dev labelling (only build on file that have been labelled for the build), and don't give him rights to move labels on the files. This way you can scrutinize his changes, and refuse to dev label his code until it meets your standards. Whatever he codes won't make it into QA until you move the dev label to the revision in question, so he's pretty much at your mercy there. Note that some shops don't use a single label for their sandbox builds, they like to apply new labels even to the sandbox, so you may be inclined to do that as well.
The problem has happened now, and as the other said it's an unjustifiable waste of your money and it's outright impolite (as correct as the curly braces thing may be).
Certainly to help prevent future problems, and maybe helpful to resolve this, I'd advise you set up a stylecop implementation - at the very least they can't fail to be unaware of when they are breaking your rules.
I think we all know the temptation of seeing coded we think is "not the way I'd do it". But we resist it.
I would have a chat about it with your boss first to get their take on it. But the first thing that springs to mind is that unless you specifically asked the contractor to do the work, he was not doing what he was hired to do, regardless of any benefit he thinks he may have been adding. So there needs to be a discussion about that.
The next thing that sprung to mind is that regardless of how good they may be or well intentioned, people who make bulk changes without discussing it with the owners of the code are bad news. They will piss people off, or worse introduce bugs and unforeseen behavior that you will have to clean up. He needs to be set straight that doing this sort of thing without permission on other peoples code is not acceptable.
When I see things I don't like in others code which are serious enough to warrant attention, I check with the owners of the code first. Even if there are obvious bugs, it
s their code and their decision about cleaning it up, not mine.
As others have said, these changes are simply for coding style. If he is there to improve performance, he is wasting time with these changes. If he can't cite how these changes will improve performance, then his OCD is just running up the bill.
I would say, "I appreciate your changes to the coding style, but lets focus on non-style changes to areas of the code that are causing the slowdown."
If a contractor did wholesale reformatting of code without authorization, I'd give him one and only one change to put things back the way they were -- and on his own time.
In addition to the valid points others make, consider the version-control nightmare this causes. Instead of the clean progression of a few lines added here, a few lines changed here, you now have this "rift" in your source control database, so that any comparisons between versions before and after this contractor's "improvements" will be meaningless.
Have the contractor back out all of his changes. Today. And on his own time.
This is quite common my experience, that people can't resist making 'improvements' and suddenly you find you're billed for stuff you didn't want. Sometimes I'm sure it's done deliberately to get more paying work, but mostly I think it's a developer getting side-tracked and unable to deal with leaving 'wrong' code.
It might require a bit of a battle, but you basically have to keep reiterating "don't change anything you're not asked to work on". Depending on his personality, you might just have to ask once nicely, or get someone higher to force him.
First, as others have said. You are paying the bill. He is not an employee. His job is to do what you ask him to do, and only what you ask him to do, otherwise you can show him the door. Always remember this. You are driving the boat, not him. You can try to not pay him, but that will be hard to do if you have a legal contract and there is nothing in it about leaving code as-is. But, you can simply let him go at any time.
Second, if you can't get him to stop and revert, and you can't get rid of him, you can tell him that if he plans to do style changes, then he should do all style changes in one check-in with absolutely NO code changes. This allows you to move forward from a base set of code that can be diffed to see code changes.
Third, make him explain the justification for the changes he's made. Removing var has no performance benefit.
Fourth, and this may suck a great deal, but youc an always use ReSharper to put the code back to your accepted style after the fact. It's more work, and you still have borked diffs, but oh well. The lambdas are harder, and that's the one you should really get on his case about.
Fifth, to drive home your point, force him to back out every change he's made and re-implement only the code changes, and not the style changes. That should open his eyes as to the mess he's created when he can't figure it out himself.
Finally, you may just have the bite the bullet and PAY him to revet back. Yes, it sucks, but since you made the mistake of not policing him, not specifying up front what you wanted, and what he's not allowed to do... You will pay the ultimate price. You can either pay him to do it, pay someone else to do it, pay you to do it, or live with it (and pay the price of the borked diffs). Any way you cut it, it will cost you money.
Well, smells like a solution wide code reformatting to me, that could be automated/enforced by settings in a tool like Resharper. I would think it very impolite and would ask him to refrain from pressing the "Reformat all code according to my personal taste" button.
To avoid the situation happening in the first place, introduce code review, particularly for any new developers joining who may not know your standards.
I'm a big fan of using git, feature branches and a service that supports pull requests (github or bitbucket). TFS isn't really up to the job, but thankfully Visual Studio supports git now. Doing code review before merging to master ensures it doesn't get forgotton. If you're paranoid you don't even need to give contractors write access to your primary repository.
Alternate point of view:
Your make two statements: "While the contractor has appeared to do a good job with the performance" and "they have also gone through large amounts of the code replacing the pre-existing style with their personal preference."
This raises many questions such as: Whenever you can "drop in" a contractor for a short period of time and gain performance enhancements. This indicates that there must have been very major flaws in the application in the first place. Anytime you need to bring in a contractor to "fix performance" this is a sign of very poorly written code or a very complex problem that requires high end expertise.
Next: When you complain that they have changed the code style even though you did not have any stated code style are you just making a pointless argument about your mojo being better than someone else's mojo. Maybe you should ask the person why they made changes which appear syntactical such that you have a complete picture.
I'm looking at the long list of one sided answers on this post and wondering what happened to the other side. Folks take the emotion out of it and look at it objectively. It's often amazing how many people will look past a beautiful algorithm solution to a complex problem just to notice that the variable naming convention has been altered from camel case to pascal case. I generally put this type of reaction down to justification of self worth by finding immaterial flaws.
Key question I have to ask is: Does the newly formatted code make the application any less readable. If you had budget constraints why did you not make it explicit that you wanted very specific fixes and nothing else. If you wanted to maintain a specific coding style then why not have that explicitly stated?
I'm working on a project and I'm just starting to do all the work necessary to globalize the application. One thing that comes up quite often is whether to globalize the exception messages, but ensuring that string.Format uses CultureInfo.CurrentCulture instead of CultureInfo.InvariantCulture. Additionally this would mean that exception messages would be stored in resource files that can be marked as culture-specific.
So the question is, should exception messages be globalized or should be be left in either the InvariantCulture or the author's country; in my case en-US.
Exception messages should rarely be displayed directly to the user. You need to think of the consumer for each string. Obviously pieces of text in the user interface need internationalizing, but if an exception message is only going to be seen by support (or is going to be visible to the user and then emailed to support when they click a button) then where's the benefit of translating it?
If you go too far, you could not only waste time and effort (and i18n can take a lot of effort) but you'll also make your support life harder as well. You really don't want to have to read log files written in a foreign language and translate them back to your native tongue.
It makes sense for Microsoft to internationalize their exception messages, because they will be read by developers from all over the world - but unless you're multinational with developers in multiple countries who don't share a common language, I wouldn't translate message which are really meant for dev/support.
typically, I don't.
Globalize strings that may be seen by a user, and you don't let your exception messages percolate up to the UI, right?
Right? :)
If you are going to be the one to deal with the exceptions, then either leave them in a language you can understand, or give them codes so you can look them up in your native language.
I assume by globalize, you mean i18n compliant which is usually called internationalize. Yes, internationalize all visible parts of the GUI, including diagnostic messages. The log file, which is where developers should go to get the real information such as the stack trace, should not be internationalized.