From: Rhino on
In the course of developing test cases for some of my classes,
particularly the classes that are static factories, I've developed some
confusion about localization. Basically, I'm trying to figure out when I
want to have separate constructor and getInstance() methods

First, I hope we can all agree that, in an ideal world, every class which
can produce text output - even if no text is produced per se, most
classed would be capable of producing error messages for Exceptions -
should be written so that it can produce that output in the languages of
the users of those classes. So, if your utility classes are used in
French-speaking countries, text output and/or error messages will be in
French and so forth for other languages. Now, I know that many developers
will not worry about that - after all, the whole IT field seems to be
fairly English-centric - but I aspire to make all of _my_ classes locale-
sensitive.

Now, with the preamble out of the way, let's get down to brass tacks.

Let's say that I want to make a static factory class locale-sensitive but
I don't want to force the user to choose an explicit locale every time
they try to use the class. That suggests to me that I go one of two ways:

1. Provide two private constructors - one that takes a specified locale
and one that uses the default locale - and two corresponding public
getInstance() methods, one of which takes a specified locale and one that
uses the default locale. Then, if the user is comfortable with the
default locale, they use the constructor that doesn't have a locale
parameter, otherwise, they use the constructor that has a locale
parameter and specify the locale of their choice.

2. Provide a single private constructor that has no locale parameter and
a corresponding public getInstance() method. Also provide getLocale() and
setLocale() methods so that a user can instantiate with the single
getInstance() method and then use setLocale() to alter that locale if it
is not to his liking.

I thought I'd have a look at the Java API and see what happens there. I
got something of a mixed bag. A handful of classes have getInstance()
methods that take a Locale parameter, suggesting that they favour
Approach 1. A handful of classes have setLocale() methods, suggesting
that they favour Approach 2. However, the vast, vast majority of the
classes have neither suggesting that they are NOT locale-sensitive and
have no capability for changing the Locale at all.

So I thought I'd ask the learned people on this group for their thoughts
on which approach they'd take when building classes that are meant to be
locale-sensitive. I'm sure there are variations on the two approaches
I've enumerated so I'm open to "none of the above" answers :-)

Personally, I'm leaning towards Approach 2. Approach 1 requires doubling
up of constructors and getInstance() methods and makes you reinstantiate
the class if you want to change Locales. Approach 2 avoids those extra
constructors and getInstance() methods and lets you change Locale by
simply doing setLocale(). There may be negative aspects to that which
aren't occuring to me though so I hope you will point those out if you
see them.

--
Rhino
From: Tom Anderson on
On Fri, 21 May 2010, Rhino wrote:

> First, I hope we can all agree that, in an ideal world, every class
> which can produce text output - even if no text is produced per se, most
> classed would be capable of producing error messages for Exceptions -
> should be written so that it can produce that output in the languages of
> the users of those classes.

I strongly disagree. Text for the consumption of end-users should be
localised; text for the consumption of programmers and sysops should not
be. I think the advantages of having a common language for these things
outweight the disadvantages of most people not having them in their first
language. It's like air traffic control - it's vital for clear
communication that i can say "i'm getting the NoMoreJam error", and not
draw a complete blank with French acquaintances who've only ever seen
NYAPlusDeConfiture and Americans familiar with NoMoreJelly. Having a
single language makes googling with error messages and so on a lot more
productive, too - and that's a benefit to the speakers of minor languages,
who have access to squillions of English search results.

Of course, being a native english speaker, i would say that, wouldn't it?

> Let's say that I want to make a static factory class locale-sensitive
> but I don't want to force the user to choose an explicit locale every
> time they try to use the class. That suggests to me that I go one of two
> ways:

Look up 'resource bundles'. They're the standard way of producing
localised messages, and are absolutely what you should use here if you
really want to do this. They use the current locale, so they leave the
onus of setting that correctly on your developers - but they only need to
set it once for the whole VM, and then messages everywhere come out in the
right language. And those who see the world my way and don't want
localised messages can set it to the canonical standard locale - en_GB.

tom

--
If goods don't cross borders, troops will. -- Fr
From: Rhino on
Tom Anderson <twic(a)urchin.earth.li> wrote in
news:alpine.DEB.1.10.1005212118590.16922(a)urchin.earth.li:

> On Fri, 21 May 2010, Rhino wrote:
>
>> First, I hope we can all agree that, in an ideal world, every class
>> which can produce text output - even if no text is produced per se,
>> most classed would be capable of producing error messages for
>> Exceptions - should be written so that it can produce that output in
>> the languages of the users of those classes.
>
> I strongly disagree. Text for the consumption of end-users should be
> localised; text for the consumption of programmers and sysops should
> not be. I think the advantages of having a common language for these
> things outweight the disadvantages of most people not having them in
> their first language. It's like air traffic control - it's vital for
> clear communication that i can say "i'm getting the NoMoreJam error",
> and not draw a complete blank with French acquaintances who've only
> ever seen NYAPlusDeConfiture and Americans familiar with NoMoreJelly.
> Having a single language makes googling with error messages and so on
> a lot more productive, too - and that's a benefit to the speakers of
> minor languages, who have access to squillions of English search
> results.
>
You raise VERY good points which I totally failed to consider. That is a
great example of how this newsgroup serves as a valuable sanity check on
my thinking.

I was really thinking primarily of messages that end-users, not system
administrators, would see and was trying to accomodate the end-users. I
failed to allow for the system administrators.

So is there a middle ground that would accomodate both groups? Generating
a message in one language for the end-user and a different language for
the system administrator, perhaps in the logs? Hmmm, this needs some
thought....

> Of course, being a native english speaker, i would say that, wouldn't
> it?
>
Hey, we all have our biases and preferences; nothing wrong with that as
long as we are aware of them :-)

>> Let's say that I want to make a static factory class locale-sensitive
>> but I don't want to force the user to choose an explicit locale every
>> time they try to use the class. That suggests to me that I go one of
>> two ways:
>
> Look up 'resource bundles'. They're the standard way of producing
> localised messages, and are absolutely what you should use here if you
> really want to do this. They use the current locale, so they leave the
> onus of setting that correctly on your developers - but they only need
> to set it once for the whole VM, and then messages everywhere come out
> in the right language. And those who see the world my way and don't
> want localised messages can set it to the canonical standard locale -
> en_GB.
>
Sorry, I though it en_US was the canonical standard ;-) I say that as a
Canadian, just to show that I'm not trying to push my own variant of
English :-)

I'm very familiar with resource bundles at a detail; I use them quite
frequently. I'm not quite clear on the "big picture" though. I lack any
significant real-world experience with how "multilingual" systems are
written with Java. For instance, if I were a developer whose native
language was French would I typically install a French-language JVM, read
the Java API in French, and write my system so that it never chose or
changed Locales? Would my classes simply make use of the Resource
Bundles I had written in French and would I leave it up to foreign
purchasers of my system to simply translate the ResourceBundles for their
own languages?

Also, is there much need for systems in which the user can switch
languages on the fly? In other words, let's say I'm working in a system
that uses French language ResourceBundles but am finding that the French
is not to my liking - maybe it's Quebecois instead of Parisian - and I
realize that I will understand better in my second language, English,
which I learned by watching MTV. Would a system typically have the
capability of letting the user invoke a switch to another language via
setLocale()? Or would I install an English-language JVM and run my system
on that?

Hold on, that doesn't quite make sense. I don't recall any language
selection option any time I've installed Java. The language of the JVM
comes from a system property which I can presumably change. Hmm, I wonder
if I should take a minute and switch my language to see what kind of
output I get from core Java classes. Will the message that comes with my
Exception be in the newly-chosen language?.... I should answer this
question for myself with a bit of experimentation....

Thanks for helping me get back on the right track!
--
Rhino
From: Lew on
Rhino wrote:
> Let's say that I want to make a static factory class locale-sensitive but
> I don't want to force the user to choose an explicit locale every time
> they try to use the class. That suggests to me that I go one of two ways:
>
> 1. Provide two private constructors - one that takes a specified locale
> and one that uses the default locale - and two corresponding public
> getInstance() methods, one of which takes a specified locale and one that
> uses the default locale. Then, if the user is comfortable with the
> default locale, they use the constructor that doesn't have a locale
> parameter, otherwise, they use the constructor that has a locale
> parameter and specify the locale of their choice.

Why do you want to provide factory classes at all?

> 2. Provide a single private constructor that has no locale parameter and
> a corresponding public getInstance() method. Also provide getLocale() and
> setLocale() methods so that a user can instantiate with the single
> getInstance() method and then use setLocale() to alter that locale if it
> is not to his liking.

This can be a good solution but can exacerbate concurrency issues.

Generally, not always but generally one should prefer class instances to be
immutable - everything is fixed in the constructor and assigned to final
member variables, and guarded against changes in the internal state of
referenced objects.

Such objects are inherently thread safe.

Even in a single-threaded context, the object that takes a read-only Locale at
construction never risks being used with a different Locale than expected.

Once you make the Locale (or any other attribute) mutable, you have to add
complexity to guarantee that the attribute has a suitable value at any given
time, lest it change between accesses.

For example, collections class instances with an active iterator will throw a
'ConcurrentModificationException' if the collection state changes during the
iteration. This can happen in single-threaded or multi-threaded contexts. In
addition to the complexity in the collection class of checking for and
throwing the exception, there is complexity in the client code of preventing
and/or checking for the exception. Or failing to do so and having a sudden
program crash.

You have to weigh the advantages of having an object whose Locale (or any
other attribute) is fixed at construction for the lifetime of the object,
versus the advantages of permitting an object to alter its state, and perhaps
to live longer. There are also disadvantages to both approaches. (For
example, long-lived objects can put more strain on the garbage-collection
mechanism.)

As for letting "a user ... alter that locale", it's not the user who alters
the locale, it's the code in response to a user action. You could just as
easily instantiate a new object with a different locale in response to a user
action as mutate an existing object.

In your particular case, I'd lay dollars to doughnuts that an immutable Locale
attribute is the better solution.

--
Lew
From: Lew on
Lew wrote:
> Why do you want to provide factory classes at all?

Oops. I mean "factory methods".

--
Lew