From: Tom Anderson on
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
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
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
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
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