From: Rhino on 28 May 2010 14:58 I'm trying to figure out some "best practices" for error handling. Our various recent discussions have convinced me that many error situations should probably not be handled via Exceptions, particularly things like input errors on GUIs. I know there is a school of thought that says exceptions are a reasonable approach to some input errors but that seems to be the minority opinion; most people prefer other ways. I'm trying to understand what the best approach is for a few different situations. 1. User input errors in a GUI. The user has a form or panel in front of him and is asked to enter his date of birth; despite help screens and labels advising him that the format is year-month-day separated by dashes, e.g. 2010-05-28, he enters this information incorrectly, e.g. 05/28/10. The code that validates the input on the form detects this error. How should the user be notified of this error? I'm picturing a utility class being invoked by the GUI to validate the date since this kind of validation is going to be very routine. Obviously, the utility method is going to format an error message that tells the user what is wrong (in the appropriate language) but then what? I've seen, written, or used programs where that message would be displayed back on the input panel, typically in a position that the builders of the system think is going to be the most readily seen, like just above the input panel or just below it. Often, you would flag the particular input field that is in error. This feels rather 'old school' at this point but the basic design is tried and true and it worked pretty well. I've seen, written, or used programs where an error message popped up on in its own window, advising the user what the error is. (Of course, this approach needs a bit of care since you want to make sure that the message isn't modal so that the user can see the message but also the input field so that he can grasp the error. And you want the error window to be movable so that it isn't frozen in one position and covering the input field that is in error.) Which of these do very experienced Java developers prefer? Or is there a different approach that is better than these? I'm mostly concerning with Java applications today, as opposed to applets or servlets, but I write all of those types so I'm interested in the best way of error handling for all types of Java programs. And what would the code in the method that detects the error look like? I'm picturing if statements that test the input and then format a message if an error is seen. But what actually gets returned to the calling class? Presumably, the method that edits the date was going to return a boolean indicating if the data is good or not but how does the error message get back to the caller? (At one point, I was writing edits like this to return an array of Objects; the array always started with the boolean that says if the data was good or not and, if the data was bad, the second Object would be an error message. If the data was good though, only the boolean was returned. Is that a good or bad design? It _felt_ wrong and forced the calling class to parse the array but it worked okay.) Also, am I correct in thinking that errors of the kind I am describing should not be logged, even at a very detailed level, since the log should only be for serious things that would involve a system administrator? (I'm tempted to argue that the log _could_ be a place where user errors get recorded so that people managing the users know which of their people are having a lot of errors so that remedial training might be provided but I suspect you will persuade me that that kind of requirement should be handled differently.) 2. Bad input errors from a process which doesn't use a GUI. One of my projects writes resumes to files for eventual placement on a website. The classes that write the resumes use various utility classes to write the resume files but there is no GUI involved. The classes make frequent use of various utility classes that help with issues like formatting. My project classes invoke the methods in the utility classes and sometimes I make mistakes in invoking the method in the utility class. Typically, it's because I've made a typo or forgotten the range of acceptable values for a parameter to the method. So, let's say I'm going to invoke a method that causes text to wrap on the page of a document and I've specified one of the parameters incorrectly, perhaps the width in characters of the available space. When I run my resume-generating class, that method invocation is going to fail because the wrapping method is going to detect that I've given it invalid input but there is not going to be a GUI on which to display the message for that error. So how should that be handled? Frankly, I feel a little odd in asking about this type of error because they are essentially programming errors, not runtime-type errors. Basically, the user of the class didn't understand the method that was being invoked well enough to avoid coding unreasonable parameters in the invocation. But these kinds of things do happen so maybe it's not ridiculous to mention them. Or should I just assume that test cases will find these errors so that they can be rectified during development and that it's not necessary to design for this kind of situation. Again, I'm assuming that errors like this shouldn't be logged. 3. Serious errors causes by programmer error. Consider this example. Let's say that I have a method which tries to obtain a resource bundle given input parameters like the "base name" of the resource bundle. This base name is simply a String typed by a programmer but the programmer recently made some coding changes and misspelled the base name during those changes. This is rather similar to the second type of error I just raised but this time, the consequences of the problem are a lot more severe. Without a correctly-spelled base name, much of the information needed by the classes won't be found and the classes are basically dead in the water. But it is still just a programmer error: somebody mistyped the base name. Should there be any specific error handling within the method that looks for the resource bundle or is it reasonable to code it as if it will inevitably work and then assume that unit testing will catch it if the base name is misspelled? Should this type of error be logged? If this error will prevent the rest of the classes' work from proceeding satisfactorily, do I just System.exit() with a message on the console or are there better things to do? 4. Really bad errors not caused by the programmer. A routine method in a class somewhere tries to find a file on a server somewhere and the file is inaccessible because someone messed with file permissions. Or a method tries to access information on a server and the server is down for some reason. Or any of umpteen other things beyond the control of the programmer takes place but makes it impossible for the class to carry on. I assume that ALL such situations should be logged. (Some of them will surely be so obvious that the logging is redundant - every resource you're trying to get from your server in Chile is unavailable and CNN just announced an earthquake close to the server's location - but many are likely to be more subtle and would not automatically be noticed by system administrators with a nudge from the logs.) What notifications should users receive in such cases? What notifications should batch programs make in those cases? Overall, I'm trying to figure out what situations need error messages, who should see those messages and where they should be written. (Also, what situations would call for me to write to the console? Who would normally see the console output from a production application?) Sorry for asking yet another "big" question but I need this kind of knowledge to make my code more acceptable than it is.... -- Rhino
From: Jeff Higgins on 28 May 2010 16:13 On 5/28/2010 2:58 PM, Rhino wrote: > I'm trying to figure out some "best practices" for error handling. > <http://books.google.com/books?id=Fz1kQgAACAAJ&dq=Robust+Java&cd=1>
From: Eric Sosman on 28 May 2010 16:35 On 5/28/2010 2:58 PM, Rhino wrote: > I'm trying to figure out some "best practices" for error handling. > > Our various recent discussions have convinced me that many error situations > should probably not be handled via Exceptions, particularly things like > input errors on GUIs. I know there is a school of thought that says > exceptions are a reasonable approach to some input errors but that seems to > be the minority opinion; most people prefer other ways. Don't conflate the program's mechanisms for detecting and handling errors with the way they are presented to a user. It doesn't matter to the user whether the original detection of the error reported it by throwing, or by returning null, or by some other means: The user just needs to know that the program couldn't do what was asked of it, plus whatever information might be helpful in figuring out what to do next. > 1. User input errors in a GUI. > [...] > And what would the code in the method that detects the error look like? I'm > picturing if statements that test the input and then format a message if an > error is seen. But what actually gets returned to the calling class? > Presumably, the method that edits the date was going to return a boolean > indicating if the data is good or not but how does the error message get > back to the caller? (At one point, I was writing edits like this to return > an array of Objects; the array always started with the boolean that says if > the data was good or not and, if the data was bad, the second Object would > be an error message. If the data was good though, only the boolean was > returned. Is that a good or bad design? It _felt_ wrong and forced the > calling class to parse the array but it worked okay.) An array of Object[] is unattractive, forcing the caller through ugly downcasts and so on. Even BigInteger.divideAndRemainder() is pretty hokey, IMHO. If you want to return multiple things, it's often better to write a simple "holder" class to contain them. Another approach is to pass a "status" object to the method, which the method can mutate to pass back information about how things went. See, for example, ParsePosition. One of the attractions of using exceptions is that they can carry information of types unrelated to what the code might otherwise compute. Combined strategies can also be used, along the lines of Value getValue(String input, Status status) { ... if (all_went_well) { status.setValid(true); return convertedValue; } else { status.setValid(false); status.setMessage("No comprendo"); return null; } } Value getValue(String input) throws BadValueException { Status status = new Status(); Value value = getValue(input, status); if (status.isValid()) return value; throw new BadValueException(status.getMessage()); } > Also, am I correct in thinking that errors of the kind I am describing > should not be logged, even at a very detailed level, since the log should > only be for serious things that would involve a system administrator? (I'm > tempted to argue that the log _could_ be a place where user errors get > recorded so that people managing the users know which of their people are > having a lot of errors so that remedial training might be provided but I > suspect you will persuade me that that kind of requirement should be handled > differently.) Most input errors aren't worth logging. Some are: For example, if the error message is "Invalid username and/or password", someone might be interested in the fact that seven thousand of them have been generated in the last two minutes, and might want to find out something about where they're coming from ... (Incidentally, when logging authentication failures you might want to omit the failed username/password combination. Someone might guess that a failed password is a simple typo for the real password, and find the latter with a very brief brute-force search. Also, people occasionally get "out of sync" and enter usernames and passwords in the wrong boxes, so logging just the username can also wind up logging some passwords. If you must log them for forensic reasons, at least encrypt those parts of the log against casual snooping.) -- Eric Sosman esosman(a)ieee-dot-org.invalid
From: Rhino on 28 May 2010 16:51 "Jeff Higgins" <oohiggins(a)yahoo.com> wrote in message news:htp86q$arf$1(a)news.eternal-september.org... > On 5/28/2010 2:58 PM, Rhino wrote: >> I'm trying to figure out some "best practices" for error handling. >> > <http://books.google.com/books?id=Fz1kQgAACAAJ&dq=Robust+Java&cd=1> Thank you. Money is tight right now so I won't be able to get that book right away but I'll look at buying it when I have a bit more disposable income.... -- Rhino
From: Rhino on 28 May 2010 17:01 "Eric Sosman" <esosman(a)ieee-dot-org.invalid> wrote in message news:htp9h6$h4u$1(a)news.eternal-september.org... > On 5/28/2010 2:58 PM, Rhino wrote: >> I'm trying to figure out some "best practices" for error handling. >> >> Our various recent discussions have convinced me that many error >> situations >> should probably not be handled via Exceptions, particularly things like >> input errors on GUIs. I know there is a school of thought that says >> exceptions are a reasonable approach to some input errors but that seems >> to >> be the minority opinion; most people prefer other ways. > > Don't conflate the program's mechanisms for detecting and > handling errors with the way they are presented to a user. It > doesn't matter to the user whether the original detection of the > error reported it by throwing, or by returning null, or by some > other means: The user just needs to know that the program couldn't > do what was asked of it, plus whatever information might be > helpful in figuring out what to do next. > Sure. Sorry if my remarks made it look like I didn't make any distinction between the two. >> 1. User input errors in a GUI. >> [...] >> And what would the code in the method that detects the error look like? >> I'm >> picturing if statements that test the input and then format a message if >> an >> error is seen. But what actually gets returned to the calling class? >> Presumably, the method that edits the date was going to return a boolean >> indicating if the data is good or not but how does the error message get >> back to the caller? (At one point, I was writing edits like this to >> return >> an array of Objects; the array always started with the boolean that says >> if >> the data was good or not and, if the data was bad, the second Object >> would >> be an error message. If the data was good though, only the boolean was >> returned. Is that a good or bad design? It _felt_ wrong and forced the >> calling class to parse the array but it worked okay.) > > An array of Object[] is unattractive, forcing the caller through > ugly downcasts and so on. Even BigInteger.divideAndRemainder() is > pretty hokey, IMHO. If you want to return multiple things, it's > often better to write a simple "holder" class to contain them. > Fair enough. The holder class could have two values in it, the boolean and the error message, just like Object array, but I'd use getters from the holder class to find out what value is in each. That would be a simple example of what you mean? > Another approach is to pass a "status" object to the method, which > the method can mutate to pass back information about how things went. > See, for example, ParsePosition. > ParsePosition itself looks simple enough, at least in the Javadoc, but I'll have to look at the source for several Java classes to see how it updates itself and how the final result gets passed back to the caller.... > One of the attractions of using exceptions is that they can carry > information of types unrelated to what the code might otherwise compute. > I'm not actually that ooposed to using exceptions but I'd like to know the other options too. It's hard to make an informed choice if you don't know the other options ;-) > Combined strategies can also be used, along the lines of > > Value getValue(String input, Status status) { > ... > if (all_went_well) { > status.setValid(true); > return convertedValue; > } > else { > status.setValid(false); > status.setMessage("No comprendo"); > return null; > } > } > > Value getValue(String input) throws BadValueException { > Status status = new Status(); > Value value = getValue(input, status); > if (status.isValid()) > return value; > throw new BadValueException(status.getMessage()); > } > >> Also, am I correct in thinking that errors of the kind I am describing >> should not be logged, even at a very detailed level, since the log should >> only be for serious things that would involve a system administrator? >> (I'm >> tempted to argue that the log _could_ be a place where user errors get >> recorded so that people managing the users know which of their people are >> having a lot of errors so that remedial training might be provided but I >> suspect you will persuade me that that kind of requirement should be >> handled >> differently.) > > Most input errors aren't worth logging. Some are: For example, > if the error message is "Invalid username and/or password", someone > might be interested in the fact that seven thousand of them have > been generated in the last two minutes, and might want to find out > something about where they're coming from ... > > (Incidentally, when logging authentication failures you might > want to omit the failed username/password combination. Someone > might guess that a failed password is a simple typo for the real > password, and find the latter with a very brief brute-force search. > Also, people occasionally get "out of sync" and enter usernames and > passwords in the wrong boxes, so logging just the username can also > wind up logging some passwords. If you must log them for forensic > reasons, at least encrypt those parts of the log against casual > snooping.) > Sound advice, as always. Thanks Eric! -- Rhino
|
Next
|
Last
Pages: 1 2 3 4 5 6 Prev: XWSSecurity and WebSphere Next: Open source licensing being questioned by anti-copyrighttypes |