tags:

views:

155

answers:

4

Hi, I read "Effective Java" by Joshua Bloch and removed the 'Constant Interface anti-pattern' from our application. The trick is to use Non-instantiable util class whose constructor is private, and define all the constants as 'public static final'

I have to extend the this constant util class. I can only do this when I change the constructor to protected.

Could somebody suggest a better way.

public class Constants {
    private Constants () {} // Prevent instantiation
    public static final String MyString = "MyString";
}

public class MyConstants extends Constants {
    private MyConstants () {} // Compiler error : Implicit super constructor Constants() is not visible.
    public static final String MySecondString = "MySecondString";
}
+1  A: 

I don't see anything wrong with changing the constructor to protected.

I also don't see anything wrong with using interfaces to hold constants.

Carl Smotricz
"When a class implements an interface, it becomes part of the class's public API. Implementation details should not leak into public APIs." http://java.sun.com/j2se/1.5.0/docs/guide/language/static-import.html. see Effective Java Item 17 for more details :)
Pascal Thivent
I can understand the sentiment, but I believe a lot of people are tying themselves into knots trying to find the best possible compromise for possibly conflicting requirements, while others go ahead and get things done. The Java language culture has managed to get itself mired into a confusing network of patterns, conventions and restrictions which I'm not sure contribute to greater productivity in the end. But this is of course just a personal opinion of mine.
Carl Smotricz
What I think is less controversial is that "rules" such as those from *Effective Java* are much more relevant to public-use libraries and toolkits than for single-use, in-house projects. It's very important for Sun, Apache and other highly visible projects to put the bar high. My sentiment is that different contexts may justify easing up a bit.
Carl Smotricz
My answer admittedly doesn't contribute much and I'd delete it, but Pascal's comment is useful and relevant, so I'll leave it up for the possible edification of future readers.
Carl Smotricz
Jonik
@Jonik: Yes, personally I sometimes do this. After a bit of reflection (in my head, not in the JVM) but after no agonizing. In about 13 years of Java programming, I have yet to be bitten by a problem resulting from this, so my personal conclusion is that it's more of an academic issue.
Carl Smotricz
@Carl - I have to agree with you on this, as a pragmatic solution. The purist in me understands the technical issues - the pragmatist says it's low down on my list of issues :-)
Brian Agnew
+1  A: 

Is there a problem with using the protected keyword ? It looks like a pragmatic solution to me.

I have to say (in addition) that I don't have a particular problem with using an interface to hold constants. Use static import to make them available in your client classes. I wouldn't advocate implementing it, though.

Brian Agnew
I wouldn't necessarily *implement* it, though...
Brian Agnew
"In order to get around this, people sometimes put static members into an interface and inherit from that interface. This is a bad idea. In fact, it's such a bad idea that there's a name for it: the Constant Interface Antipattern (see Effective Java Item 17). The problem is that a class's use of the static members of another class is a mere implementation detail. When a class implements an interface, it becomes part of the class's public API. Implementation details should not leak into public APIs." http://java.sun.com/j2se/1.5.0/docs/guide/language/static-import.html
Pascal Thivent
@Brian You can't prevent it, that's the problem. And you can't blame someone for not using your API properly (the API is faulty, not the user of the API).
Pascal Thivent
I wasn't aware I was blaming anyone, I confess
Brian Agnew
I didn't mean that you are blaming anyone. I should maybe have used "one" instead of "you". Sorry for the confusion. But I wonder if you get my point now.
Pascal Thivent
@Pascal - I was being slightly flippant (probably didn't come across well). But I don't necessarily see what the issue is, if I don't implement this interface in a public API. Those constants would be available most everywhere without implementation, simply via the fact they're in an interface file and importable. That may be appropriate (the value of PI isn't a secret). That may *not* be appropriate in some cases. As usual, different requirements result in different solutions (I would normally use Enums rather than constants, but that's another issue)
Brian Agnew
@Brian Yes, if you don't implement it, it's ok. But someone will which is the problem IMHO (if something is possible, it will happen). That's why I think an API shouldn't give that possibility and avoid using an interface for constants. And I agree about Enums.
Pascal Thivent
Ok. That makes more sense. I definitely concur that if something *can* be done, likely it *will* be done :-)
Brian Agnew
@Pascal: I hope I don't annoy anyone by adding to a topic already flogged nearly to death. But I disagree with "someone will". It's time to realize that code reuse has turned out to be a fairy tale. Most application (as opposed to library) code is written and used exactly once, and usually any pondering of possible use scenarios of one's code is moot. Worse, dangers of misuse of one's code arise much more often from mindless copy-and-pasting than from incorrect subclassing. Disclaimer: Circumstances may vary in some environments.
Carl Smotricz
@Carl My experience is that "someone will" does happen in corporate projects/apps too, especially with big projects and distributed teams with developers unequally skilled (I've seen things I would never have thought about). So, no, I won't let a door open if I can close it. But it's of course your right to disagree.
Pascal Thivent
+4  A: 

You are not typically supposed to extend these constant classes. Could you provide us with a more concrete example of what you're trying to do?

Typically you'd want to group constants together when they are related, e.g., maths constants or configuration parameter names for a particular functional component.

If the constants are really related, is there anyway you could just add them to the original class? Alternatively, is there any reason you can't create a separate class for your constants?

Jack Leow
Yeah, my thoughts exactly, +1
Jonik
Exactly. Even I think we don't need to extend Constants classes. The code is legacy and I'd fix this. Thanks a lot.
Nayn
+1  A: 

If the classes are in the same package and you want to forbid inheritance for non-package classes, consider using default access:

public class Constants {
    Constants () {} // Prevent instantiation
    public static final String MyString = "MyString";
}
McDowell