Design Questions about static factory classes

R

Rhino

I think you are too ambitious.
Probably :)
Not everything need to be internationalized.

Some forms of output are not even possible to internationalize
(especially languages outside of the western countries can
be difficult).

You should focus on the output that is rich (looks good, has
advanced capabilities).

GUI's (both fat client and web) plus print intended for
advanced printers (not line printers).

Drop it for console IO, log files, print for line printers etc..

Some guidelines on when internationalization is appropriate are just what
I need. I appreciate your advice.
I prefer #2 with the note that you set Locale on the factory
not on the objects created by the factory.
Sorry? I'm not clear on the distinction you're making in your note.

Are you envisioning that the invoking class do:

LocalizationUtils localizationUtils = LocalizationUtils.getInstance(new
Locale("FR", "fr));
Map<String, Locale> myLocales = localizationUtils.getLocales();

-OR-

LocalizationUtils localizationUtils = LocalizationUtils.getInstance();
localizationUtils.setLocale(new Locale("FR", "fr");
Map<String, Locale> myLocales = localizationUtils.getLocales();

Or did you mean something else altogether?
 
R

Rhino

I would expect developers, testers and operators to understand
English too, but unfortunately it is not uncommon for customers
to require internationalization for operations. In Europe
both Germany and France often require that. Scandinavia
not so often.


The argument for a common language is still valid, but you may have
a problem if the language chosen was french.


For the text then resource bundles should be the solution, but there
are a lot more to internationalization than just text.
Agreed. I only mentioned text specifically but I have written code that
uses List, Text and Message bundles. I know how to use them all. I'm
still struggling a bit with the "big picture" stuff though so that's what
I'm asking about here.
 
R

Rhino

Which can be a bit problematic when having a global team
that needs to fix bugs related to a GUI in German or
French.
I can imagine! I have a probably oversimplistic view that virtually all of
the developers out there have at least a working knowledge of English and
frequently much much better command of the language but that may be a
little overoptimistic :) I can easily imagine a developer that has only a
fairly weak grasp of English and no knowledge whatever of French or German
- maybe an Asian for example - struggling to uncover the meaning of a
message that is probably cryptic even to a native English speaker! I know
I've seen a number of messages over the years that were (apparently)
written by native English speakers that were almost incomprehensible. I can
only imagine how hard these were for people whose English is less fluent
than mine.....
 
E

Eric Sosman

Lew said:
[...]
Why do you want to provide factory classes at all?
(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?

He probably isn't. Factory methods are quite common; factory
*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.)
Agreed. That's exactly what I meant; I just phrased it crudely in an
attempt to be brief.

Brevity is the soul of wit. Crudity is the soul of halfwit.
(And crudités are the life of the party, but I digest. Er, digress.)
 
L

Lew

Eric said:
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.
 
T

Tom Anderson

Sorry for the off-topic digression but I just can't help but admit to
some surprise that some eastern Europeans still know German.

Hey, don't look at me. I got the list of locales handed to me from someone
else, and he got it from someone else, and i assume that someone who knew
what they were doing drew it up. Or at least, i hope so; all i can assume
is that someone who had the authority to do it did it.
What codebase changes concern you? If you do ResourceBundles correctly,
there really aren't any code changes. You simply throw ResourceBundles
for the appropriate languages into the jar and you should be good to go,
right?

And then deploy the JAR and reboot. Not so hot if you're hoping to run a
global ecommerce site.
Do your classes have constructors (or getInstance() methods that
establish a Locale? Do you have setLocale() methods in your classes? If
you don't use either approach, how do you set the Locale and how do you
change it if it needs to be changed?

The system is a web application. We attach a locale to each user session.
We have a component near the top of the servlet container's request
processing chain that looks at the incoming request, and the existing user
object if there is one, and sets the locale accordingly. When a class
needs to know the current locale, it gets hold of the user object for the
current request (via some sort of thread-local variable or some such) and
asks it. So, no class inside the system has any concept of its own locale
- they always use the 'current locale', where that's something that can be
different in different threads that are running at the same time.

tom
 
A

Arne Vajhøj

Lew said:
Arne said:
And my guess is that Tom [sic] meant US English.

Tom said:
Certainly not! en_GB is the canonical form, and en_US is merely a
popular but subordinate deviation.

It has ever amazed me how well the Brits speak English. Awesome!

Yeah, you'd think they invented the language or something ;-)

English is a mix of the languages of the invaders from
Germany, Scandinavia and France.

Arne
 
A

Arne Vajhøj

It certainly is. I'm trying to write code that will be easily usable by
non-English speakers. But my code isn't actually being written for a
specific customer at this time, other than me. At the moment, I'm trying
to put together a sort of code portfolio. I'm hoping it will show
prospective employers or clients that I am culturally sensitive enough to
write code that will work in multiple languages and knowledgeable on how
to do it. In other words, I don't just want to claim that I am culturally
sensitive but then have no code to back that up. When they challenge me
to prove that I can write code that works for customers in various
locales, I want to be able to point them to some decent examples where I
have done that. I'm just trying to figure out the best way to do that
right now.....

Do you just want to support western languages?

Or do you also want to solve the difficult problems?
Really? I find that a surprising thing to say. Maybe we're not talking
about the same thing.

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.

Arne
 
A

Arne Vajhøj

Sorry for the off-topic digression but I just can't help but admit to
some surprise that some eastern Europeans still know German. Stalin and
his eastern European brothers were pretty ruthless about exiling or
killing their German residents in the immediate aftermath of WW II. I had
thought the German language was pretty much non-existent in the former
Warsaw Pact area by this point.... Based on what you're saying, it
appears that I was premature in assuming an absence of German in those
countries.

There may be few ethnic Germans left in those countries.

But there are a lot of people that wants to do business
with German companies.

Arne
 
A

Arne Vajhøj

For instance, i'm currently on a project which will roll out to 23
countries in the first wave. They're all European and North Amererican,
and in a slightly weird twist, to begin with we're only supporting
english, french, and german as languages. So, if you're a native of the
UK, the US, Canada, France, Switzerland, Luxembourg or a few other
places, you have your own language, but if you live in Hungary or the
Netherlands, you'll have to be able to read english, or in some cases in
eastern Europe, german. In the second wave, Korea will be added, and for
that, there will be korean. I assume that in later waves, there will be
proper localisation into national languages, but i haven't heard about
that. By that point, such localisation would not require programmer
input (or at least only a tiny bit) - the client's content management
team will be able to add new locales and their corresponding
translations to the system themselves. We're keeping translations in a
database rather than resource bundle files, so they can do this to a
running system without having to modify the codebase.

There are increasing levels of difficulties of internationalization:
1) different language
2) different alphabet
3) different writing directions

If #3 does not require code changes, then somebody will have had
to planned very well.

Arne
 
A

Arne Vajhøj

I can imagine! I have a probably oversimplistic view that virtually all of
the developers out there have at least a working knowledge of English and
frequently much much better command of the language but that may be a
little overoptimistic :) I can easily imagine a developer that has only a
fairly weak grasp of English and no knowledge whatever of French or German
- maybe an Asian for example - struggling to uncover the meaning of a
message that is probably cryptic even to a native English speaker! I know
I've seen a number of messages over the years that were (apparently)
written by native English speakers that were almost incomprehensible. I can
only imagine how hard these were for people whose English is less fluent
than mine.....

True.

But the problem I describe is not that problem.

I am describing the problem of:
- developers being good at English
- operators being good at English
- for political reasons the GUI's are not in English but the
local language
- something is not working and the developers get some screen
shots and they can only say WTF

Arne
 
A

Arne Vajhøj

Probably :)


Some guidelines on when internationalization is appropriate are just what
I need. I appreciate your advice.

Sorry? I'm not clear on the distinction you're making in your note.

Are you envisioning that the invoking class do:

LocalizationUtils localizationUtils = LocalizationUtils.getInstance(new
Locale("FR", "fr));
Map<String, Locale> myLocales = localizationUtils.getLocales();

-OR-

LocalizationUtils localizationUtils = LocalizationUtils.getInstance();
localizationUtils.setLocale(new Locale("FR", "fr");
Map<String, Locale> myLocales = localizationUtils.getLocales();

Or did you mean something else altogether?

Something else.

LocalizationFactory lf = new LocalizationFactory();
lf.setLocale(new Locale("FR", "fr"));
X x = lf.getX();
Y y = lf.getY();
Z z = lf.getZ();

Arne
 
L

Lew

Arne said:
English is a mix of the languages of the invaders from
Germany, Scandinavia and France.

Of course, borrowing from any other language is far from taboo. It's enough
to drive you meshugge. Maybe some sleazy gigolo tycoon will fund an opera
about a funky zombie vampire who lives in an igloo, wearing a parka and
smoking cigars, then runs amok because people won't kowtow to him.

"English doesn't borrow from other languages. English follows other languages
down dark alleys, knocks them over, and goes through their pockets for loose
grammar."
- Paraphrased from James D. Nicoll
 
T

Tom Anderson

There are increasing levels of difficulties of internationalization:
1) different language
2) different alphabet
3) different writing directions

If #3 does not require code changes, then somebody will have had
to planned very well.

True. Everyone involved would, i think, be prepared to accept a redeploy
when we add RTL languages, or even ideographics. We'll also need to push
new versions whenever we roll out to countries which require more
significant structural changes - adding new country-specific behaviour to
the checkout flow for example (eg ISTR that in some middle eastern
countries the law requires that customers must give their national ID
number when buying anything online).

But it's nice to be able to push out new locales to existing countries (eg
adding danish to Denmark, which currently only has english) without a
redeploy, and it's absolutely essential to be able to push changed content
to an existing locale without taking down the system.

tom
 
T

Tom Anderson

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
 
A

Arne Vajhøj

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
 
L

Lew

Tom said:
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.
 
R

Rhino

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.
 
R

Rhino

Lew said:
He saw my amendment that I meant factory methods, not classes.


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....
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,774
Messages
2,569,598
Members
45,161
Latest member
GertrudeMa
Top