jQuery in Action, 2nd edition*
The moose likes Java in General and the fly likes enum toString override Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of Spring in Action this week in the Spring forum!
JavaRanch » Java Forums » Java » Java in General
Bookmark "enum toString override" Watch "enum toString override" New topic
Author

enum toString override

Santhosh Kalisamy
Ranch Hand

Joined: Apr 15, 2008
Posts: 59
Friends,

In properties file, we do have properties like

db.username = xxx
db.password = xxxx
db.servername = yyyy

I do have a enum as below.



Where ever we use PROPx.toString(), I would like property keys (like "db.username", "db.password"....etc) to be returned.

I found, We have to override the toString() method for each enum (PROPx). Is there any common way to do that? without override?

like



Please share your ideas.
dennis deems
Ranch Hand

Joined: Mar 12, 2011
Posts: 808
Receiving a meaningful value from the toString method always requires overriding it. Btw, may I ask how are you planning to use PROP constants in your code? If your app is anything like the one I'm working on, this enum will very rapidly grow to contain hundreds of constants -- an unmanageable size IMO.
Anayonkar Shivalkar
Bartender

Joined: Dec 08, 2010
Posts: 1509
    
    5

I believe using java.util.Properties would be quite neater.


Regards,
Anayonkar Shivalkar (SCJP, SCWCD, OCMJD, OCEEJBD)
Santhosh Kalisamy
Ranch Hand

Joined: Apr 15, 2008
Posts: 59
@ Dennis Deems

We do read properties on entire application and it is maintained by many developers.

When we change properties name, we are forced to check entire application. I have introduced a Constants class to hold all properties. But, still few try to use the "" on getProperty method.

My implementation is like this:

PropertyConstants class to hold all Properties file keys


And In propertyManager class to give the value of the key,


Now, returns like "PROP1", "PROP2"...etc

I would like this to return like "db.username", "db.password"...etc

But, I don't know to add that value on enum.

------------------------------------------------------
@ Anayonkar Shivalkar

Yes. I am using java.util.properties only. The restriction on using key in entire application, I would like to introduce with enum.
John Jai
Bartender

Joined: May 31, 2011
Posts: 1776
Instead of toString() override, you can declare an abstract class and override it in each of the enum constants. Or declare the constants with a value and override the toString() to return the value for each constant.



Do take Dennis advice on not using an Enum. For ease of code, I might look the property key value in the Property file and would query it directly. A constant file holding all the keys as String is enough I think. It will be hard for users to match enum constant with key name. If you are still stubborn, then at least name it the enum constants meaningful (not as PROP1, PROP2, etc.)
Santhosh Kalisamy
Ranch Hand

Joined: Apr 15, 2008
Posts: 59
@ John Jai:

Thanks John. Yes, I am not planning to use PROP1...etc. It's just for example to show here.

I do have meaningful names on constant file (Around 100) now.

our properities file is growing faster and its hard, when people use them directly on methods. That's why, I wanted to restrict. Your code looks good with me. Thanks.
Junilu Lacar
Bartender

Joined: Feb 26, 2001
Posts: 4742
    
    7

My thoughts on this:

1. The less coding you have to do, the better. Using enums looks like it will involve a lot more coding that I'd be willing to invest in for this problem.

2. Defining constants is about abstraction and removing duplication. You will already have duplication between the constants and the actual keys used in the properties file but that's unavoidable. You want to limit the duplication to only that though. Using enums to map to keys in a properties file seems like overkill to me because the benefit of type-safety with enums is not needed here. Abstraction comes into play also because you want to isolate the use of the constants from the fact that you're using a properties files or database table or XML or some other format to hold the key-value mapping.

3. Defining a constants-only interface is not good form. Interfaces are contracts for behavior. If an interface is not intended to be implemented, then it should not exist. I prefer to use a final class with a private constructor to hold constants.

4. I also prefer naming the constants as close to the actual key values as possible, just so it's easier to establish the relationships. For example, DB_URL constant corresponds to the db.url key in the properties file. It also makes it easier to implement my next point below.

5. I find that the best way to keep track of synchronization between the Java constants and the keys defined in the properties file is to use JUnit tests. I have at least two tests: one to check that all required keys in the properties file have corresponding constants and another to check that all Java constants have corresponding keys defined in the properties files. These tests will involve using reflection but you should only have to write the tests once. Other tests can be written to check for optional parameters and constants as well. If a new constant is added without a corresponding key being added in the properties file, a test will fail. If a key is added without a corresponding Java constant, a test will fail.

6. There's no rule that says you have to use one properties file and one constants class. When a properties file gets too big or when one section of a properties file gets too big, I usually separate it out to another properties file. When I have multiple properties files, my JUnit tests for properties/constants that uses reflection gets refactored into a parent test and I have subclasses of it check for specific things in their corresponding properties files.


Junilu - [How to Ask Questions] [How to Answer Questions]
dennis deems
Ranch Hand

Joined: Mar 12, 2011
Posts: 808
Junilu Lacar wrote:My thoughts on this:

I'd give this 100 thumbs up if I could.
Santhosh Kalisamy
Ranch Hand

Joined: Apr 15, 2008
Posts: 59
Dennis Deems wrote:
Junilu Lacar wrote:My thoughts on this:

I'd give this 100 thumbs up if I could.


Yes, I would agree with Dennis.... Excellent reply... Thanks a lot guys...

I have been refactoring all Junilu mentioned facts. Except, Using Interface(s) for Constants. Will change possible ones to final class.
Winston Gutkowski
Bartender

Joined: Mar 17, 2011
Posts: 8008
    
  22

Junilu Lacar wrote:My thoughts on this:

I agree with the others, except for your point 5; and specifically:
"I find that the best way to keep track of synchronization between the Java constants and the keys defined in the properties file is to use..."

Not quite sure what you mean here. Either a constant is what it says it says, or it ain't; and if it is, there is no "synchronization" involved. (oops, see below)

If you want to load constants (or indeed enum values) with contents of a properties file, that's fine; but don't change them after the fact.

@Santhosh: Think of an enum as a class with values that have public static final tacked onto them. The problem is: it's a class, so implementations can abuse it however they want.

My advice: DON'T.

Winston

[Edit] Apologies Junilar, I now understand your point. I'm still not sure I agree with it though.


Isn't it funny how there's always time and money enough to do it WRONG?
Articles by Winston can be found here
Santhosh Kalisamy
Ranch Hand

Joined: Apr 15, 2008
Posts: 59
@ Winston :

What alternative are you suggesting?

All I want is to control the parameters for getProperties method.
Winston Gutkowski
Bartender

Joined: Mar 17, 2011
Posts: 8008
    
  22

Santhosh Kalisamy wrote:@ Winston : What alternative are you suggesting?
All I want is to control the parameters for getProperties method.

Simplest: ignore "new" properties. If you really want every invocation to take them all on board, throw an Exception until they're all recognized.

There really is no way around this. Java is statically typed, and enums are simply a type that has "values". If you truly want a system based on supplied properties as constants, then a constant Properties object would seem to your simplest option (note the emphasis on 'constant').

Winston
Junilu Lacar
Bartender

Joined: Feb 26, 2001
Posts: 4742
    
    7

Winston Gutkowski wrote:[Edit] Apologies Junilar, I now understand your point. I'm still not sure I agree with it though.

It's "Junilu" ;)

Writing those tests is not necessary in all cases. Sometimes though, especially with large legacy systems, you'll get duplication even with constants and properties. That is, when you have multiple developers over time, they might not take the time to familiarize themselves with the system very well. Worse, they may not even have the luxury of taking the time to familiarize themselves. This can often lead to multiple constants defined to refer to the same value. You can also end up with multiple properties files with duplicate keys and values. I find that when we have tests, it makes it clear which constants should be used and what their corresponding properties files are. From there, we can start systematically deprecating any duplicate constants and properties files. Moreover, if you decide to not use properties files but some other mechanism instead, e.g. DB or XML, then you can easily adjust the tests to check those instead. These aren't really unit tests though; they are integration tests.

Edit: I suppose this just comes from my strong conviction that Test-Driven Development should be the way you develop.

You need a constant? Where's the test that says you need that constant? You need to get it from a properties file? the DB? and XML file? Where's the test? There's a bug? Where's the test that broke? You don't have a broken test? Well, write a test and see it fail to show that you need to fix something. Then fix it. Fixed? Do all your tests pass now? Great, you're done! Deploy it!
dennis deems
Ranch Hand

Joined: Mar 12, 2011
Posts: 808
I think it's okay to have constants whose text is identical if they have different functions. Maybe one is a table header, and the other is a label for an input field or something like that. If there were only the one key for these, then you find your table has a zillion columns and you decide to abbreviate your headers, now all your field labels are also abbreviated.
Winston Gutkowski
Bartender

Joined: Mar 17, 2011
Posts: 8008
    
  22

Junilu Lacar wrote:
Winston Gutkowski wrote:[Edit] Apologies Junilar, I now understand your point. I'm still not sure I agree with it though.

It's "Junilu" ;)

My apologies, mate.

Phew. Quite a lot to answer; I'll do my best, but I hope you don't mind if I pick and choose.

Writing those tests is not necessary in all cases...

I thought tests were written for "users", not programmers, but I may be out of date.

Sometimes though, especially with large legacy systems, you'll get duplication even with constants and properties...

Yes, but surely that's when "bounds" are most useful. Either a constant is or it isn't. Start mucking about with that and I suspect you'll have a lot more issues than what we're talking about. To my mind, everything else is a "translation" task.

But feel free to correct me.

Winston
Junilu Lacar
Bartender

Joined: Feb 26, 2001
Posts: 4742
    
    7

Winston Gutkowski wrote:I thought tests were written for "users", not programmers, but I may be out of date.

When you do TDD, most of the developer tests become, or are part of, the detailed design documentation. That is, the tests give examples of how APIs are used, exceptions you can expect under certain conditions, etc. That's totally for other programmers. Tests that involve the constants would ideally show other developers how those constants should be used.

Yes, but surely that's when "bounds" are most useful. Either a constant is or it isn't. Start mucking about with that and I suspect you'll have a lot more issues than what we're talking about. To my mind, everything else is a "translation" task.

Not quite sure what you mean here by "bounds" but let me give you an example of what I'm talking about:

1. Version 1.0 of an application was developed by an initial team. Application constants were created but the design wasn't clear (no tests). Say a constant, APP_DB_URL, was included in there.

2. Version 2.0 was developed by part of the initial team + new team members. Everyone was busy and communication and collaboration between team members is not great. New developers have not been made aware of the Application constants, much less APP_DB_URL. Because of inexperience, they just hard-code the values, same as the value represented by APP_DB_URL. That's now a problem that can become a bug (technical debt).

3. Version 3.0 was developed by a new team. They see code changes in Version 2.0 with hard-code values. New team member is under pressure to deliver but wants to refactor the hard-code values to constants. He refactors by "Extract Constant" but the constant is created in the same class as the hard-coded values were in. Still under time pressure, developer does not take the time to find the Application constants created in Version 1.0. Now you have duplicate constants defined in Application constants and in the refactored class. They refer to the same value and they are for the same purpose. Despite the refactoring, you still have technical debt because somebody could change one constant but not the other.

Multiply all this N number of times for different constants and different developers then you can quickly have a mess on your hands.

Granted, having tests won't necessarily eliminate this problem either but at least they will help me find bugs a lot quicker, at least that's my experience. But that's just me and my TDD. YMMV.
Junilu Lacar
Bartender

Joined: Feb 26, 2001
Posts: 4742
    
    7

I think we also need to clarify something in this discussion. The "constants" we've been talking about are really the keys used to access configurable application settings, not the values themselves. So, in my previous example, the APP_DB_URL would have a value like "app.db.url" or something like that. Just to add to the confusion of my previous example, say the developers of Version 2.0 hard-coded the value instead of the key. Then the Version 3.0 developers decided to name the refactored constant APP_DB_URL also. So now you have duplicate constants defined in the application but one APP_DB_URL represents the key while the other one represents the value. This is something that I can easily see happening on large projects that have a high churn of developers on the project team. Imagine how much more difficult it will be to find bugs if you don't have tests in this situation.
Winston Gutkowski
Bartender

Joined: Mar 17, 2011
Posts: 8008
    
  22

Junilu Lacar wrote:Just to add to the confusion of my previous example, say the developers of Version 2.0 hard-coded the value instead of the key. Then the Version 3.0 developers decided to name the refactored constant APP_DB_URL also. So now you have duplicate constants defined in the application but one APP_DB_URL represents the key while the other one represents the value.

All this surely boils down to two basic design issues:
1. The same value (and since we're talking about constants, I presume we can refer to it as a value) is known by more than one name.
2. The same NAME refers to different values, depending on context.

#1, I suggest, is more likely to lend itself to a coded solution if refactoring is out of the question; but both need analysis as to intent. Fairly obviously, there's no point in "guessing" at what a constant like "weekday" means; particularly if the sources are from different countries - and the penalties for getting it wrong could be severe, and subtle.

Winston
Junilu Lacar
Bartender

Joined: Feb 26, 2001
Posts: 4742
    
    7

Winston Gutkowski wrote:All this surely boils down to two basic design issues:

Right, which is why I submit that tests written as a result of TDD will help address the issues since TDD is really as much, if not more, about design as it is about testing per se. I'm not sure I understand where you're going with the rest of that with regard to the relative merits of having tests that involve these types of constants and keys though.
Junilu Lacar
Bartender

Joined: Feb 26, 2001
Posts: 4742
    
    7

One more try at clarifying how tests like those that I describe would likely come to existence.

Initially, there probably won't be any tests specifically for constants that represent keys for configurable application settings, if that's how the design turns out. The more likely scenario is that software entropy will result in duplication in the form that I've already described before. The technical debt from the duplication eventually results in a bug, say someone changes one constant value but misses changing its duplicates. Developers who do TDD to fix the bug will first write tests to show that the bug is in fact present. They would refactor to eliminate the duplication and make the test(s) pass.

After a while, perhaps after having to deal with the same type of issue/bug a number of times, someone will say something like "You know what, this is getting really old. Let's just write a JUnit test that shows our design intent for using and maintaining the constants for keys that need to be used to access the application configuration settings." And so the tests that I described in point #5 of my first reply are born.
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: enum toString override