From: Tom Anderson on 23 May 2010 07:18 On Sat, 22 May 2010, Arne Vajh?j wrote: > On 22-05-2010 15:05, Rhino wrote: > >> I'm thinking of a situation like completing a form in a GUI. The >> customer has to enter his date of birth. Let's say that I can't use a >> JSpinner for some reason; it can't do everything I need it to do. The >> customer is given a simple JTextField for entering a date. Clearly, the >> customer would have many opportunities to enter bad data. He could type >> in 1985- 15-31 when he meant to type 1985-05-01; the first value is >> obviously a bad date since there are only 12 months in the year, not >> 15. My practice is to write edits that check for that kind of mistake >> and generate an exception, typically IllegalArgumentException, with a >> clear error message that reminds the user that there is no such month >> as '15'. Naturally, the customer might not be an English speaker so I >> put all such messages in ResourceBundles so that other bundles can >> easily be added for any languages that I support. >> >> How would you handle such a situation? > > Catch the exception but display something else that the exception text. > > Exceptions texts are for log files to be handed over to developers. > > For user input I don't even think that you should throw an exception. > Maybe just test and tell the user to correct. > > Bad user input is not really exceptional enough to justify an exception. I disagree. We've had arguments about the proper use of exceptions on this newsgroup before, so i recognise that this is a matter where opinions vary, but exceptions seem like a perfectly acceptable option for dealing with bad user input to me. They might not be the right solution in every situation, but they are an option that can be considered. Of course, i wouldn't show the exception's error message to the user. An approach i've seen is to do something like: public class ValidationException extends Exception { private final String validationKey; private final Object[] parameters; public ValidationException(String validationKey, Object.. parameters) { super(format(validationKey, Locale.getDefault())); this.validationKey = validationKey; this.parameters = parameters; } public String format(Locale locale) { return format(validationKey, locale); } private static String format(String validationKey, Locale locale) { ResourceBundle bundle = ResourceBundle.getBundle("ValidationMessages", locale); String pattern = bundle.getString(validationKey); MessageFormat fmt = new MessageFormat(pattern, locale); return fmt.format(parameters); } } ValidationExceptions have a message in the language of the default locale (or you could hardcode this to english if you wanted), which can be used in logging and so on, but can also supply their message in other languages, as needed. If you put on a getter for the fields, then code that handles them can also act on the key and parameters in other ways, as appropriate, if simply printing the messasge is not adequate. Although in this case, you should probably be using subclasses rather than switching on the contents of the key. If you do subclass, you can refine the above approach by pushing the parameters down into subclasses, accessed via an abstract getParameters method in the base class. That lets you construct the array on the fly from meaningful fields: public class AgeTooYoungException extends ValidationException { private final int actualAge; private final int requiredAge; // constructor protected Object[] getParameters() { return new Object[] {actualAge, requiredAge}; } // getters } Code which catches this and is interested in the ages can then discover them via proper getter calls, rather than having to scrub about in an untyped parameter array. Another refinement is to add a field which somehow indicates which bit of user input was wrong - a simple string key might be enough. The UI code can then attach the error message to the right bit of the UI simply by matching that up. tom -- One horse laugh is worth a thousand syllogisms. -- H. L. Mencken
From: Arne Vajhøj on 23 May 2010 10:07 On 23-05-2010 07:18, Tom Anderson wrote: > On Sat, 22 May 2010, Arne Vajh?j wrote: > >> On 22-05-2010 15:05, Rhino wrote: >> >>> I'm thinking of a situation like completing a form in a GUI. The >>> customer has to enter his date of birth. Let's say that I can't use a >>> JSpinner for some reason; it can't do everything I need it to do. The >>> customer is given a simple JTextField for entering a date. Clearly, >>> the customer would have many opportunities to enter bad data. He >>> could type in 1985- 15-31 when he meant to type 1985-05-01; the first >>> value is obviously a bad date since there are only 12 months in the >>> year, not 15. My practice is to write edits that check for that kind >>> of mistake and generate an exception, typically >>> IllegalArgumentException, with a clear error message that reminds the >>> user that there is no such month as '15'. Naturally, the customer >>> might not be an English speaker so I put all such messages in >>> ResourceBundles so that other bundles can easily be added for any >>> languages that I support. >>> >>> How would you handle such a situation? >> >> Catch the exception but display something else that the exception text. >> >> Exceptions texts are for log files to be handed over to developers. >> >> For user input I don't even think that you should throw an exception. >> Maybe just test and tell the user to correct. >> >> Bad user input is not really exceptional enough to justify an exception. > > I disagree. We've had arguments about the proper use of exceptions on > this newsgroup before, so i recognise that this is a matter where > opinions vary, but exceptions seem like a perfectly acceptable option > for dealing with bad user input to me. They might not be the right > solution in every situation, but they are an option that can be considered. > > Of course, i wouldn't show the exception's error message to the user. .... > Code which catches this and is interested in the ages can then discover > them via proper getter calls, rather than having to scrub about in an > untyped parameter array. > > Another refinement is to add a field which somehow indicates which bit > of user input was wrong - a simple string key might be enough. The UI > code can then attach the error message to the right bit of the UI simply > by matching that up. The advantage of an exception over returning not valid is if there is a deep call stack to skip. The trend today seems to put validation out in the presentation/control layer and then the need for exception does not really seems to be there. Arne
From: Lew on 23 May 2010 10:11 Arne Vajhøj wrote: >> Bad user input is not really exceptional enough to justify an exception. Tom Anderson wrote: > I disagree. We've had arguments about the proper use of exceptions on > this newsgroup before, so i [sic] recognise that this is a matter where > opinions vary, but exceptions seem like a perfectly acceptable option > for dealing with bad user input to me. They might not be the right > solution in every situation, but they are an option that can be considered. And usually rejected. Read /Effective Java/ (2nd ed.), "Item 57: Use exceptions only for exceptional conditions", and the rest of section 9. Part of the problem with exceptions is that they are expensive relative to conditionals. The other part in this case is that you expect bad inputs - they aren't exceptional conditions at all. Your style is your style, tom, and you are absolutely correct to suggest that one should consider all options. But the design purpose of exceptions is to deal with out-of-line conditions, and input validation is squarely in line. -- Lew
From: Rhino on 23 May 2010 17:04 Patricia Shanahan <pats(a)acm.org> wrote in news:8MOdnVeFX8O7qmXWnZ2dnUVZ_vWdnZ2d(a)earthlink.com: > Rhino wrote: > >> which is why I'm struggling with this. When there are several ways to >> do something, I'm not always clear on how to choose between them.... > > Have you done much background reading or studying on software > engineering ideas such as separation of concerns and design patterns? > Not enough, I'm afraid. I have spent a few hours a couple of times looking at a few of the standard 21 (?) design patterns and have a link (or several) to such discussions. But I don't THINK in patterns yet. > For research type projects, where the requirements can change very > frequently, I tend towards an approach of initially implementing > things as simply as possible for the current requirements, but being > very willing to refactor. > Absolutely! I think we should be very willing to be flexible, at least in the early days of building a system when big changes in requirements (or our understanding of them) come along regularly. -- Rhino
From: Rhino on 23 May 2010 17:14
Lew <noone(a)lewscanon.com> wrote in news:ht9e41$j0p$1(a)news.albasani.net: > Lew wrote: >>>> Why do you want to provide factory classes at all? > > Rhino wrote: >>> (I saw your amendment saying you meant factory METHODS in that >>> sentence.) >>> >>> Actually, you and/or Eric (and maybe some others) persuaded me to >>> use factories for my utility methods several weeks back when I was >>> asking about the best way to set up my StringUtils class. You're not >>> changing your mind and advising me against that now are you? > > Eric Sosman wrote: >> He probably isn't. Factory methods are quite common; factory > > He saw my amendment that I meant factory methods, not classes. > >> *classes* are relatively rare. (You'll learn more about what's >> what in a few years, when you've saved enough for "Effective Java," >> but until then you'll just have to take it on faith.) > > I did not "change my mind", nor do I recommend the use of factory > methds willy-nilly. > > But I did not make a recommendation in my question, I asked a > question. Why are you providing factory methods at all? > > There are reasons to provide a factory method. They do not always > apply. What are your reasons? Just answer the question. > Sorry, I heard you the wrong way. I thought you were - in effect - saying I was foolish to use them and should be doing something else. That was a little disorienting since I think you were part of the discussion that persuaded me to use static factory methods in the first place.... Well, on to your question as you intended it.... I have several utility classes, including StringUtils, DateTimeUtils, and LocalizationUtils, that provide methods (frequently convenience methods) to do such things as search a string for the number of occurrences of a specific character, or determine the current day name, or to grab a ResourceBundle. At a certain point, I was confused about whether these methods should be static or not and I was persuaded that a static factory method was the best way to go. Each user would do a getInstance() on the class, then use whichever methods they wanted. That's what I've done. If you are asking me to remember why this is a better way to go than the alternatives, I'm embarassed to admit that I don't recall. Sometimes, when I get persuaded to do something, I just do it and resolve to keep doing it (and even retrofit existing code to use the technique) but I don't necessarily remember why it is the best way. Maybe I should but I don't.... -- Rhino |