aspose file tools*
The moose likes Java in General and the fly likes Implementation of Enumerated Types Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of EJB 3 in Action this week in the EJB and other Java EE Technologies forum!
JavaRanch » Java Forums » Java » Java in General
Bookmark "Implementation of Enumerated Types" Watch "Implementation of Enumerated Types" New topic
Author

Implementation of Enumerated Types

Jay Damon
Ranch Hand

Joined: Jul 31, 2001
Posts: 279
Our system architects have recently become enamored with the concept of Enumerated Types as outlined in Effective Java. I like the idea but we differ regarding how to use them. First, let me say that I am a developer working in our system data access layer. My issue is who should be responsible for converting the Integers and Strings retrieved from the database or, turning it around, converting the Strings retrieved from a request object into the corresponding enumerated type.
I hope you will review the following code and offer any comments. Thanks.
A system architect coded the following method on an Enumerated Type class named SourceSystem:

where idToType is a HashMap containing all the SourceSystem enumerated types. Additionally, the system architect coded the following setter method on the corresponding data transfer object:

I have several problems with this approach:
1. My data access object now has to "know" how to instantiate the enumerated type and invoke the appropriate method to perform the conversion. I think it should be the data transfer object's responsibility to "know" how perform any conversions required. Additionally, if defined more generically, the same setter method can be used to perform not only the conversion of an Integer value from a database table but also the conversion for a String parameter from the request object on the front-end. The amount of coding required by developers is minimized.
2. By not having to know about the enumerated type SourceSystem, that is one less import statement and one less dependency for my data access object. I fail to see the need to introduce a dependency where one is not required.
3. Because the system architect decided to handle invalid values by throwing an IllegalArgumentException rather than, say, returning a default value, I will have to code defensively (as will the developer of the corresponding JSP page) in order to handle a potential run-time exception. Again, I think it is the data transfer object's responsibility to decide how it wants to handle that possibility.
I proposed the following implementation for the setter method:

along with this corresponding new getter method on the enumerated type:

These two methods would allow me code the following line in the data access object to retrieve the source system from the database table:

instead of:

Personally, I think my solution is cleaner, is more flexible, reduces dependencies, isolates potential run-time exceptions, minimizes the code developers have to write, and results in more readable code. However, the system architect is not buying it.
Does my solution for using this enumerated type not seem preferable ?
David Harkness
Ranch Hand

Joined: Aug 07, 2003
Posts: 1646
My issue is who should be responsible for converting the Integers and Strings retrieved from the database or, turning it around, converting the Strings retrieved from a request object into the corresponding enumerated type.
For me it comes down to how you've defined your layer boundaries. For example, your domain objects know about SourceSystems but a web client does not. Thus your HTML presentation layer should be responsible for converting between SourceSystems and Strings. The same goes for the data access layer: the DB doesn't know about SourceSystems, and thus the data access layer must do the conversion.
Now, you mentioned that there are data transfer objects. At what points are they used in the system? Meaning, are they used *within* your data access layer to move data between the database and your domain objects? If so, then it really comes down to preference and ease of coding.
1. My data access object now has to "know" how to instantiate the enumerated type and invoke the appropriate method to perform the conversion. I think it should be the data transfer object's responsibility to "know" how perform any conversions required.
This depends on how much intelligence your DTOs have. For our system, I created a very simple DTO structure. They are, in effect, rows in the database. They have a state (new, loaded from db, marked for deletion), dirty flag, and a bunch of keyed values (TreeMap with Integer keys to be precise). I put all of the intelligence about what the fields contain outside the DTO class itself.
You, however, may have created DTOs that are typed (UserDTO) and have named accessors -- getFirstName() instead of get(Const.FIRST_NAME). In this case it would be quite reasonable to place the conversion logic in the DTO. In fact you could create multiple accessors: getSourceSystem(), getSourceSystemId(), getSourceSystemString().
2. By not having to know about the enumerated type SourceSystem, that is one less import statement and one less dependency for my data access object. I fail to see the need to introduce a dependency where one is not required.
I'm in full agreement here. But that means that your DTO class has one more import statement and one more dependency. If you've given your DTO a typed, named accessor already, this is moot as the dependency exists already.
3. Because the system architect decided to handle invalid values by throwing an IllegalArgumentException rather than, say, returning a default value, I will have to code defensively (as will the developer of the corresponding JSP page) in order to handle a potential run-time exception. Again, I think it is the data transfer object's responsibility to decide how it wants to handle that possibility.
For my lookup codes (your enumerations) I return null from codeToText() if the value isn't valid. This lets the caller decide how to handle it. In other similar cases I did choose to throw IAE. For me, it really comes down to another form of the 80/20 rule: if 80% of the callers will throw an IAE when
the given value is invalid, then have the method itself throw the exception.
Jay Damon
Ranch Hand

Joined: Jul 31, 2001
Posts: 279
Thanks for the your response. I'm pleased to hear I'm not going to have to totally re-examine my object-oriented development skills.
Allow me to answer your questions and comment further.
Now, you mentioned that there are data transfer objects. At what points are they used in the system? Meaning, are they used *within* your data access layer to move data between the database and your domain objects? If so, then it really comes down to preference and ease of coding.
Yes, primarily to move data between the database and domain objects. Ease of coding as well as readibility of the code are two of my primary concerns here.
This depends on how much intelligence your DTOs have. For our system, I created a very simple DTO structure. They are, in effect, rows in the database.
Unfortunately, our existing DTOs have more intelligence than I would like. But I am in complete agreement with you that DTOs should, in effect, be data structures that mirror the corresponding database table row. However, in this instance, I think makes sense for the DTO to know how to obtain a SourceSystem object given an Integer or String value.
I'm in full agreement here. But that means that your DTO class has one more import statement and one more dependency. If you've given your DTO a typed, named accessor already, this is moot as the dependency exists already
The point is moot. The system architects have designed the DTO such that it already has to "know" about the SourceSystem enumerated type. The corresponding getter method is:

I have no problem with this because it makes the corresponding id, code, and name attributes readily available.
For my lookup codes (your enumerations) I return null from codeToText() if the value isn't valid. This lets the caller decide how to handle it. In other similar cases I did choose to throw IAE. For me, it really comes down to another form of the 80/20 rule: if 80% of the callers will throw an IAE when
In an ideal world, an IAE would never occur in our application as there are referential constraints on our database. However, I do not like to blindly trust those constraints so I prefer to code for the possibility of an IAE. However, since it is unlike that one would occur, I would choose to delegate the responsibility for handling the IAE to the application object who, in turn, delegates the actual conversion to the SourceSystem enumerated type class.
I would not have a problem if the DTO class itself threw an exception. I would just add another catch statement to the existing try-catch block for my JDBC code. However, I really don't want to have to insert a nested try-catch block just to handle this conversion.
Alternately, if a null were returned, that would probably be okay with me but that would still create the dependency issue (point 2. above).
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Implementation of Enumerated Types
 
Similar Threads
Tiger objectives - take 2
my notes on JLS for any1 who needs them !!
Using DAO in struts
where we use enums
SCJP1.5