Converting constants-only interfaces to abstract classes

R

Robert Klemme

Rhino said:
Ahh, now we get to the heart of the issue....

In my case, I have several classes that are writing various formats of
resumes. (Yes, that same project we've been discussing for weeks
now.) The various resume writer classes share a variety of constants,
like the fonts to use in particular parts of the document, the color
palette to use, the name of the log file to use for reporting errors,
etc. I want all of the classes in _this_ project to use certain
values for those things but I don't want all of the classes in _all_
of my projects to use those same values.

It makes no sense to me to define LOG_FILE_NAME separately in each of
10 or 15 classes that use it, particularly if there is a chance that
I may want to change the value of that constant. If my log file is
current "Resume.log" and I decide to change it to "CV.log", I
_really_ don't want to have to change its value in 10 or 15 separate
classes; I just want to change it once and have each class see the
change.

Surely you're not suggesting that I should have 10 or 15 separate
definitions of LOG_FILE_NAME and then have to change each
individually? This seems like a very obvious case for storing these
definitions once - whether in an interface or a class - and then
sharing them amongst all of the classes that need them. Or does OO
propose a different way althogether of handling this very common
situation?

From what you write your constants seem to be rather some kind of
configuration information. In that case I'd consider using Properties
(although they do have some drawbacks as Roedy pointed out; you can of
course wrap them in some class that gives safer / better access to config
values).

Kind regards

robert
 
R

Rhino

Andrew McDonagh said:
before you would have done something like.....

public interface ResumeConstants {
public String HEADER = "Header";
}


public class ResumeWriter implements ResumeConstants {

public void writeResume() {
System.out.println(HEADER);
}

}



Which you now know is not a good use of interfaces - its even thought of
as a anti-pattern.

So what to do....convert the interface into a class (as you have done),
and make the constants 'static'.


public class ResumeConstants {
public static final String HEADER = "Header";
}


Now to make use of it...

public class ResumeWriter {

public void writeResume() {
System.out.println(ResumeConstants.HEADER);
}

}


By making the constants static, it saves you having to instantiate the
ResumeConstants class in order to use its constants....e.g.

public class ResumeWriter {

public void writeResume() {
ResumeConstants rc = new ResumeConstants();
System.out.println( rc.HEADER );
}

}

Now this business about making the constants class an abstract class....

If you try and use Inheritance you will always run into this type of
problem. This situation only ever calls for Delegation, not Inheritance.

In fact your designs will generally be much better if you 'favor
Delegation Over Inheritance' (nice and google-able term)

Even with Delegation, there's really only one valid reason for going the
Abstract class route, with these constants classes.... its to make it
difficult to instantiate the class like I just did above. However, making
it Abstract merely prevents some one 'newing' the class directly, it does
not stop them creating a derived class and newing that instead. A better
approach for be to make the default constructor 'private'.

As in...


public class ResumeConstants {
public static final String HEADER = "Header";

private ResumeConstants() {}
}


We sometimes do this if we think its a good thing to prevent this, but
there's always cases where we don't want to do this.

Going this route can actually leave you in as much trouble as having the
interface constants. For example, say your constants were just that,
constants, but then we have a new business requirement that says we need
two or more different sets of constants, depending upon the user's locale.
We'd be buggered if we used the approach above.

Instead, what we'd want to do it not directly access the constants values,
we want to get them via access methods (getters), but we'd want to
instantiate different ResumeUserLocaleConstants classes depending upon
locale, then use them in a polymorphic manner.

public interface UserLocaleDependantConstants {
public String getHeader();
public String getFooter();
...
}

public class UkUserConstants implements UserLocaleDependantConstants {
// ... load UK values for the user constants...
}

public class USAUserConstants implements UserLocaleDependantConstants {
// ... load USA values for the user constants...
}

public class FrenchUserConstants implements UserLocaleDependantConstants {
// ... load French values for the user constants...
}

...

so we still have constants, just a different set are created at
application start up, or read from a server, or file, or....

Thank you VERY much Andrew! Your explanation was very clear and
well-reasoned in all respects.
Once you explained that I shouldn't be implementing or extending the
classes, everything else fell into place.

I see why this is the recommended approach and have gone ahead and changed
my two constants interfaces into classes containing only public static final
constants along the lines you proposed. Naturally, I'll follow this approach
in future projects as well and will gradually retrofit this approach to
older projects as time permits.

I feel better knowing that I'm doing things the proper way. I just wish I'd
known that interfaces were a bad way to handle constants earlier; I feel
like I'm only just discovering something that the rest of the (Java) world
has known for years :)
 
E

Ed

Robert Klemme skrev:
From what you write your constants seem to be rather some kind of
configuration information. In that case I'd consider using Properties
(although they do have some drawbacks as Roedy pointed out; you can of
course wrap them in some class that gives safer / better access to config
values).

Kind regards

robert

Just what I was thinking.

And I do have a wrapper Option interface (other big beneft: no GUI
updates for each new configuration parameter); various packages
retrieve the specific option implementation they need by doing
something like:

Option option = options.getOption("parser type");

Except that that string is, of course, a final string declared in a
central location. Where? In the Options interface. Which brings us back
to your original point.

Option option = options.getOption(Options.PARSER_TYPE_TAG);

..ed
 
A

Andrea Desole

Rhino said:
Ahh, now we get to the heart of the issue....

In my case, I have several classes that are writing various formats of
resumes. (Yes, that same project we've been discussing for weeks now.) The
various resume writer classes share a variety of constants, like the fonts
to use in particular parts of the document, the color palette to use, the
name of the log file to use for reporting errors, etc. I want all of the
classes in _this_ project to use certain values for those things but I don't
want all of the classes in _all_ of my projects to use those same values.

It makes no sense to me to define LOG_FILE_NAME separately in each of 10 or
15 classes that use it, particularly if there is a chance that I may want to
change the value of that constant. If my log file is current "Resume.log"
and I decide to change it to "CV.log", I _really_ don't want to have to
change its value in 10 or 15 separate classes; I just want to change it once
and have each class see the change.

Surely you're not suggesting that I should have 10 or 15 separate
definitions of LOG_FILE_NAME and then have to change each individually? This
seems like a very obvious case for storing these definitions once - whether
in an interface or a class - and then sharing them amongst all of the
classes that need them. Or does OO propose a different way althogether of
handling this very common situation?

I don't really know how your code works, but what about a logger class?
There you can define your log operations and your static LOG_FILE_NAME,
which, by the way, doesn't even need to be public, since it's used only
by the logger.
 
R

Rhino

Andrea Desole said:
I don't really know how your code works, but what about a logger class?
There you can define your log operations and your static LOG_FILE_NAME,
which, by the way, doesn't even need to be public, since it's used only by
the logger.

That might be reasonable in the specific case of the log file but I was just
using that as an example of the bigger question of managing constants that
are used by several classes when I usually want all of those classes to
share the exact same values for the constants.

I don't think I want to create new classes for each and every constant that
is shared among multiple classes just to keep from using an interface
containing only constants; that would appear to make the cure worse than the
disease. Or am I not understanding your point correctly?
 
R

Rhino

Robert Klemme said:
From what you write your constants seem to be rather some kind of
configuration information. In that case I'd consider using Properties
(although they do have some drawbacks as Roedy pointed out; you can of
course wrap them in some class that gives safer / better access to config
values).
Yeah, I guess something like Properties or Roedy's variant on Properties
might be a better way to go.... But as Ed has pointed out in this thread,
that would appear to call for constants being defined somewhere as well,
probably in an interface.

If I'm going to end up with constants in an interface anyway, it makes me
wonder why I would complicate my life with Properties or Configure classes
_AND_ an interface when an interface alone is working just fine right now.
Doesn't some variant of Occam's Razor suggest that an interface alone is
better than an interface plus other classes to accomplish the same end?

If every solution ultimately ends with an interface of constants anyway, is
this just an exercise in coming up with the most sound reason for having an
interface of constants rather than convincing ourselves that an interface of
constants is a bad idea altogether? Maybe we're just proving that an
interface of constants needs to be in the solution regardless but are just
quibbling over WHY it needs to be there?
 
A

Andrea Desole

Rhino said:
That might be reasonable in the specific case of the log file but I was just
using that as an example of the bigger question of managing constants that
are used by several classes when I usually want all of those classes to
share the exact same values for the constants.

i know. The point is that it's difficult to tell more because I don't
know the code, so I wanted to use your example to tell how a constant is
declared in the class it refers to, without declaring an external
class/interface. This is, I guess, what also Chris meant
I don't think I want to create new classes for each and every constant that
is shared among multiple classes just to keep from using an interface
containing only constants; that would appear to make the cure worse than the
disease. Or am I not understanding your point correctly?

that's not really what I mean. The first thing I thought when I saw your
log example was "well, that constant refers to logging, as well as all
the log operations; that would fit nicely into a log class". Another
option is to think "the location/name of the log file is something that
should be configured, together with some other properties; this would
fit nicely into a configuration class". This is something that has
already been suggested, I guess.
So my point is that you usually use a constant that is related to
something, or is used by something, and that something is usually a
class. There you can declare your constant. Where and how (and also if,
since it may not be the case) depends on your code. For example, you
might have a class ResumeWriter which takes care of writing your text.
That class is subclassed by all the specific format writer. In that
class you can declare your constant font information as static
variables. Or you can add it to the already mentioned configuration
object; which, by the way, seems a better solution, since I would
personally like all this information to be configurable.
 
C

Chris Smith

zero said:
I completely disagree with the fact that abstract and final are mutually
exclusive.

The JLS doesn't, though. 8.1.1.2: "A compile-time error occurs if a
class is declared both final and abstract".

Your example shows a non-final abstract class, which can't be
subclassed. The concepts of "class that can't be instantiated" and
"abstract class" are related, but not identical. The latter is a subset
of the latter.

Put in a more interesting way, the keyword "abstract" carries certain
implications, beyond the mere inability to create an instance. It
implies that correct usage of that class involves overriding some class
behaviors. For that reason, it doesn't make sense to make a class
abstract if it shouldn't be subclassed. The lack of an accessible
constructor is good enough to express that idea.

--
www.designacourse.com
The Easiest Way To Train Anyone... Anywhere.

Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation
 
T

Tony Morris

Chris Uppal said:
Congrats !

Are you shunning the JLS ? Java ? Programming ? I'm just curious:
please ignore this question if you don't care for it.

-- chris

If I shunned the JLS, I'd also be implicitly shunning all the other
specifications that are written in a horribly ambiguous language called
English. I concede to the reality - we have a very suboptimal situation. I
have always disliked the notion of passive whinging - that is, whinging
about something and not taking any proactive measures to change it - I am
doing my best as time permits.

4 days to go!! :)
 
T

Tony Morris

zero said:
A final class may indeed be better for this purpose. Note that in my
original post about this, I said "Use a non-instantiable (for example
abstract) and preferably final class"

I completely disagree with the fact that abstract and final are mutually
exclusive.

When I said it, I mean, a class can be abstract, final, neither, but never
both.
A class with a private constructor is not final - and not even "effectively
final" - I'll leave it at that for anyone curious who wishes to investigate
the issue more thoroughly.
 
A

Andrew McDonagh

Chris said:
Andrew McDonagh wrote:

Sorry for the delay...been away on business all week...

Granting the (unlikely, IMO, but not impossible) hypothesis that a
constants-only class is required, I find myself asking:

a) Why would anyone want to instantiate it ?

I don't know, nor would I care personally. But as the OP was after a
best practise and how they relate to Abstracts, I gave what we typically
see.
b) If someone did, why would one want to prevent them from doing so ?

ditto above...
c) If this /is/ an issue, then what of Thomas Hawtin's point that an
interface will achieve exactly the same thing with less clutter and
semantic noise ?

It doesn't achieve the same thing though. A class making use of another
constants class via delegation encapsulates that usage.

If that class derives from a constants class or implements a constants
interface, then that class's own public interface now exposes those
constants - breaking encapsulation.

Going this route can actually leave you in as much trouble as having the
interface constants. For example, say your constants were just that,
constants, but then we have a new business requirement that says we need
two or more different sets of constants, depending upon the user's
locale. We'd be buggered if we used the approach above.


Agreed. I just wanted to point out that if there /isn't/ an [anticipated]
business requirement to do so, then this kind of messing around is
over-engineering. No criticism of your point intended, but I suspect that
Rhino's getting a bit confused with the range of "best-practise" that's being
recommended ;-)

-- chris


Sure, I was merely attempting to give a (granted overly complex) example
of what possible benefits of putting constants behind a class and using
getters to retrive them.

Andrew
 
A

Andrew McDonagh

Chris said:
Andrew McDonagh wrote:




Granting the (unlikely, IMO, but not impossible) hypothesis that a
constants-only class is required, I find myself asking:

a) Why would anyone want to instantiate it ?

b) If someone did, why would one want to prevent them from doing so ?

c) If this /is/ an issue, then what of Thomas Hawtin's point that an
interface will achieve exactly the same thing with less clutter and
semantic noise ?

oh... for those interested...

http://java.sun.com/j2se/1.5.0/docs/guide/language/static-import.html
 
T

Thomas Hawtin

Andrew said:
It doesn't achieve the same thing though. A class making use of another
constants class via delegation encapsulates that usage.

If that class derives from a constants class or implements a constants
interface, then that class's own public interface now exposes those
constants - breaking encapsulation.

My point was that if you declare constants (and only constants) in an
interface then you can ditch the "public static final" noise. From the
source or the JavaDocs it is easy to see an interface of this form for
what it is. I was not suggesting the interface should be implemented.

I do not think legislating against stupidity on the part of client code
is a high priority. The author of the client code has to set out to
implement the interface, and if they do that then it's their own fault.

Tom Hawtin
 

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

No members online now.

Forum statistics

Threads
473,997
Messages
2,570,239
Members
46,827
Latest member
DMUK_Beginner

Latest Threads

Top