Use List/Map instead of DTO?
Since I'm manually creating my DAO and DTOs, and coding DTO seems to be a lot of work (with the constructors and accessor methods), what are the disadvantages of using generic containers like List and Map for my return values? These are the disadvantages I can think of:
1. All fields are of type Object which needs to be casted. The type must be specified separated in the comment/documentation rather than in code as is for DTO.
2. For List, elements can only be referenced using index number. For both List and Map, there needs to additional comment/documentation describing the return value of the fields. With DTO, the fields are apparent in code.
Aside from the fact that it's time consuming to create DTOs (which I can get around by writing some code generation function), it also spawns lots of classes in my package, making it quite a mess.I've tried two organizations: 1) putting all DTOs in a "dto" package 2) or, putting all DTO for an entity inside a package for that entity along with the DAO for that entity. Either way, I can't hide the clutter that all the DTOs create.
[1125 byte] By [
eyilin] at [2007-9-30 11:41:14]

This is probably not a good idea. You have provided the argument against using a List, Array, or Map. Of these the Map is probably the best choice, but you still need all those casts, and the name lookups are not very efficient.
If your DTO doesn't apply control on its data you can leave the member variables public and dispense with all those getters and setters.
I have seen quite a number of projects implementing DTO's through maps, and also using a wrapper.
The wrapper could contain for example for an int:
public int getInt(String key);
public int getInt(String key, int defaultValue);
The problem I've experienced with it that it's runtime checked, not compile time checked.
Anyway, it works, it's the "implement generic once, run as many times as you want"-principle, but i rather work with compile time checking.
> [creating] DTOs (which I can get around by writing some code generation function)
> spawns lots of classes in my package, making it quite a mess. I've tried two organizations:
> 1) putting all DTOs in a "dto" package
> 2) or, putting all DTO for an entity inside a package for that entity
I'd favor 1) (and you can refine your dto package into subpackages that match the entity packages).
DTOs tend to be client-oriented, and I dislike my entity package to depend on (be updated with) client code needs.
It's a good practice anyway to package together components that change together.
> along with the DAO for that entity. Either way, I can't hide the clutter that all the DTOs create.
All IDEs, and Javadoc too, present packages in a hierarchically organized view, and you don't need to expand what you don't want to see, so the cluttering is quite limited if you choose option 1.
And even otherwise, it's less troublesome than having to look for the documentation that specifies the actual data types (if you go for the HashMapDTO approach).
> what are the disadvantages of using generic containers like List and Map for my return values?
One more reason to avoid HashMapDTOs:
Since DTO change with client needs, you quickly have DTOs that encompass data from several entities. You can arrange that with hierarchical DTOs, or by collapsing these info into "flat" DTOs.
WIth the HashMapDTO approach, a hierarchy means a HashMap of HashMaps of HashMaps which quickly goes cumbersome to maintain (lots of if-then-else code, tests for null,...).
In this case you're very likley to choose a flat HashMap, which can really go ugly as well (ending up with keys such as "Customer_1/Order_3/Item_2/Price"...).
HashMapDTO has its fans though, and it's often used to speed up development when client code needs frequently change. In the long run, I don't think it pays...
I prefer 1, but then I always use code generation.For me there is really only one downside to using the hash map and that is that debugging them is nightmarish.
> One more reason to avoid HashMapDTOs:
>
> Since DTO change with client needs, you quickly have
> DTOs that encompass data from several entities. You
> can arrange that with hierarchical DTOs, or by
> collapsing these info into "flat" DTOs.
> WIth the HashMapDTO approach, a hierarchy means a
> HashMap of HashMaps of HashMaps which quickly goes
> cumbersome to maintain (lots of if-then-else code,
> tests for null,...).
> In this case you're very likley to choose a flat
> HashMap, which can really go ugly as well (ending up
> with keys such as
> "Customer_1/Order_3/Item_2/Price"...).
Good point. I've never thought about that.
> I prefer 1, but then I always use code generation.
You guys have convinced me to stick with DTO... now I need to know what code generation is all about. Do you mean creating a simple program that maybe takes in a file listing the member type and ID of the DTO and spits out a file filled in with all the variable declarations, constructors and accessors? Or do you mean something more sophisticated then that?
> > I prefer 1, but then I always use code generation.
>
> You guys have convinced me to stick with DTO... now I
> need to know what code generation is all about. Do
> you mean creating a simple program that maybe takes in
> a file listing the member type and ID of the DTO and
> spits out a file filled in with all the variable
> declarations, constructors and accessors? Or do you
> mean something more sophisticated then that?
I don't know how most people do this, but I'd be inclined to start from the metadata for the tables in the database I was working with. The generator would read the metadata and build DTO's that match the tables in the Schema. I'm sure there are tools available if you do a search.
> You guys have convinced me to stick with DTO... now I need to know what code generation is all about.
> Do you mean creating a simple program that maybe takes in a file listing the member type and ID
> of the DTO and spits out a file filled in with all the variable declarations, constructors and accessors?
You can define the data types and names in XML, then use XSLT to generate DTO source files.
Transforming your DB schema into DTO source will do only part of the job (as I wrote above, your DTOs may evolve more with the client code's needs, not necessarily with the DB schema). But if you have a tool that imports the DB metadat a into an XML representation, it may be a good start.
hello,
check XDoclet.. i m assuming u r using EJBs... with XDoclet u can generate DTOs automatically from the entity bean code.
for my 2 cents, i am writing a struts app that uses dynaactionform (sort of hashmap).
true that u have to do lot of casting, but in some cases utititles can help you (such as BeanUtils.copyProperties)..
that reduces the code that you have to write, (all hte casting) .....
regards
marco
>
> I don't know how most people do this, but I'd be
> inclined to start from the metadata for the tables in
> the database I was working with. The generator would
> read the metadata and build DTO's that match the
> tables in the Schema. I'm sure there are tools
> available if you do a search.
That is how I do it.
> >
> > I don't know how most people do this, but I'd be
> > inclined to start from the metadata for the tables
> in
> > the database I was working with. The generator
> would
> > read the metadata and build DTO's that match the
> > tables in the Schema. I'm sure there are tools
> > available if you do a search.
>
> That is how I do it.
But what if my DTOs don't match the DB schema half the time, but instead includes a subset of the schema fields or combination of fields from multiple schemas?
I'm not using EJB... it's for a simple 2-tiered application.
> > >
> > > I don't know how most people do this, but I'd be
> > > inclined to start from the metadata for the tables
> > in
> > > the database I was working with. The generator
> > would
> > > read the metadata and build DTO's that match the
> > > tables in the Schema. I'm sure there are tools
> > > available if you do a search.
> >
> > That is how I do it.
>
>
> But what if my DTOs don't match the DB schema half the
> time, but instead includes a subset of the schema
> fields or combination of fields from multiple schemas?
You'd need a more elaborate system. The use of an XML document to describe the DTO and an XSLT to turn the XML into a Java source has been suggested.
Shouldn't be too hard to code a small Java application that automates the generation. You need only a single XSLT file and a bunch of XML files. If you put all those in the same directory all you need to do is loop through it and process them all in sequence.
> > > >
> > > > I don't know how most people do this, but I'd be
> > > > inclined to start from the metadata for the
> tables
> > > in
> > > > the database I was working with. The generator
> > > would
> > > > read the metadata and build DTO's that match the
> > > > tables in the Schema. I'm sure there are tools
> > > > available if you do a search.
> > >
> > > That is how I do it.
> >
> >
> > But what if my DTOs don't match the DB schema half
> the
> > time, but instead includes a subset of the schema
> > fields or combination of fields from multiple
> schemas?
>
> You'd need a more elaborate system. The use of an XML
> document to describe the DTO and an XSLT to turn the
> XML into a Java source has been suggested.
> Shouldn't be too hard to code a small Java application
> that automates the generation. You need only a single
> XSLT file and a bunch of XML files. If you put all
> those in the same directory all you need to do is loop
> through it and process them all in sequence.
Sorry, but all this talk of XML and XSLT begs the question. How do the database fields get into the XML, you either get them from the existing metadata or your UML models, or your documentation, or you type them in again. The metadata is the most reliable source as its what the database itself uses.
I've not found XML to be any easier to edit than java.
> Sorry, but all this talk of XML and XSLT begs the
> question. How do the database fields get into the
> XML, you either get them from the existing metadata or
> your UML models, or your documentation, or you type
> them in again. The metadata is the most reliable
> source as its what the database itself uses.
>
> I've not found XML to be any easier to edit than java.
It all depends. If the metadata is not a good source to use (for example because the DTOs will need to be derived from stored procedures or complex composite queries instead of a simple 1-1 mapping between table fields and java fields, the metadat cannot be used.
The question here was how to generate DTO code. Maybe it is easier to just type in the Java (certainly with IDEs that generate getters and setters for you) but it's far from universal.
Taking an XML file containing the data to be turned into a DTO and parsing that through an XSLT document to generate all the Java code (including JavaDoc if you want) can save a lot of typing and if you tell the database boys what you want you might be able to trick them into declaring the XML files part of the database design and therefore their responsibility so you don't have to type anything >:-)
> I'd favor 1) (and you can refine your dto package into
> subpackages that match the entity packages).
> DTOs tend to be client-oriented, and I dislike my
> entity package to depend on (be updated with) client
> code needs.
> It's a good practice anyway to package together
> components that change together.
I disagree with this. It's highly useful to put the DTO's in the same package with the classes that populate them with data.
The DTOs can then provide package protected options to the DAOs that you don't want other things to have. It makes it easy to create these things in a way that nothing outside the package can. If you don't put them in the same package then you have to make things that only the DAO should be doing (setting an identity value for example) public.
One DTO pattern I've been playing around with is a package protected class that only defines fields. A structure, basically. Then you define public classes that wrap the DTO and present it in different ways depending on the use. For example, you would have a client wrapper and a server wrapper in a 3 tier system. As long as you don't make the DTO or the client wrapper depend on any of the server only classes, you can leave those out of the libraries used by the client.
> > >
> > > I don't know how most people do this, but I'd be
> > > inclined to start from the metadata for the tables in
> > > the database I was working with. The generator would
> > > read the metadata and build DTO's that match the
> > > tables in the Schema. I'm sure there are tools
> > > available if you do a search.
> >
> > That is how I do it.
>
>
> But what if my DTOs don't match the DB schema half the
> time, but instead includes a subset of the schema
> fields or combination of fields from multiple schemas?
The schema is just a source file for the generator.
You can provide other source files.
>
> I disagree with this. It's highly useful to put the
> DTO's in the same package with the classes that
> populate them with data.
>
I disagree with this.
The DTOs should be in their own package.
Doing that allows you to distribute the package without regard to the contents. Thus the client application jar includes that package and the server application jar does as well.
Additionally being in the same package confuses the point that the DTOs exist "between" sub-systems and do not really belong to any single sub-system.
> The DTOs can then provide package protected options to
> the DAOs that you don't want other things to have. It
> makes it easy to create these things in a way that
> nothing outside the package can. If you don't put
> them in the same package then you have to make things
> that only the DAO should be doing (setting an identity
> value for example) public.
>
I don't find that a problem for me.
But I am not overly protective when I design my classes either.
> One DTO pattern I've been playing around with is a
> package protected class that only defines fields. A
> structure, basically. Then you define public classes
> that wrap the DTO and present it in different ways
> depending on the use. For example, you would have a
> client wrapper and a server wrapper in a 3 tier
> system. As long as you don't make the DTO or the
> client wrapper depend on any of the server only
> classes, you can leave those out of the libraries used
> by the client.
That certainly makes sense if you want to protect all access. (Of course adding all of those classes makes the point of code generation so much more evident.)
> > Sorry, but all this talk of XML and XSLT begs the
> > question. How do the database fields get into the
> > XML, you either get them from the existing metadata or
> > your UML models, or your documentation, or you type
> > them in again. The metadata is the most reliable
> > source as its what the database itself uses.
> >
> > I've not found XML to be any easier to edit than java.
>
> It all depends. If the metadata is not a good source
> to use (for example because the DTOs will need to be
> derived from stored procedures or complex composite
> queries instead of a simple 1-1 mapping between table
> fields and java fields, the metadat cannot be used.
>
> The question here was how to generate DTO code.
I usually either start with the schema or I create a new file format and that drives not only the code creation but the schema creation as well.
> I disagree with this.
>
> The DTOs should be in their own package.
>
> Doing that allows you to distribute the package
> without regard to the contents. Thus the client
> application jar includes that package and the server
> application jar does as well.
I've done it that way and I think the other way is better. Packages should be grouped based on relationships between classes, not based on common functionality. Such packages only categorize things. This severly limits the usefulness of package-protected access.
> Additionally being in the same package confuses the
> point that the DTOs exist "between" sub-systems and do
> not really belong to any single sub-system.
The package shouldn't belong to one sub-system.
> I don't find that a problem for me.
>
> But I am not overly protective when I design my
> classes either.
Yes, you figure if things go wrong it's not your fault. Just like it's not my fault if you slip on the ice on my front step.
> That certainly makes sense if you want to protect all
> access. (Of course adding all of those classes makes
> the point of code generation so much more evident.)
I don't like to provide the oppourtunity to make mistakes. There's no sense in providing access to things that can only cause problems.
> > I disagree with this.
> >
> > The DTOs should be in their own package.
> >
> > Doing that allows you to distribute the package
> > without regard to the contents. Thus the client
> > application jar includes that package and the server
> > application jar does as well.
>
> I've done it that way and I think the other way is
> better. Packages should be grouped based on
> relationships between classes, not based on common
> functionality. Such packages only categorize things.
> This severly limits the usefulness of
> f package-protected access.
When you say
...DTO's in the same package with the classes that populate them with data.
You do mean your support classes that you described above. Rather than, for instance, putting them in the same package as the DAO layer right?
I don't believe that DTOs belong in the same package as the DAO layer (nor the GUI layer for that matter.) If you have support classes and/or wrappers then they belong in the same package.
>
> > Additionally being in the same package confuses the
> > point that the DTOs exist "between" sub-systems and do
> > not really belong to any single sub-system.
>
> The package shouldn't belong to one sub-system.
>
Which suggests that it won't be in the same package as the DAO layer.
> > I don't find that a problem for me.
> >
> > But I am not overly protective when I design my
> > classes either.
>
> Yes, you figure if things go wrong it's not your
> fault. Just like it's not my fault if you slip on the
> ice on my front step.
>
Actually I figure that the people that I work with are adults and are reasonably intelligent. And I treat them so.
> > That certainly makes sense if you want to protect all
> > access. (Of course adding all of those classes makes
> > the point of code generation so much more evident.)
>
> I don't like to provide the oppourtunity to make
> mistakes. There's no sense in providing access to
> things that can only cause problems.
But problems still occur. And simple problems, by their nature are simple. Complex problems are not.
My layers, without external protection mechanisms provide for validation for all the data coming in and sometimes for that that goes out. Those mechanisms are seldom needed and when used are almost (if not always) due to simple problems.
But extra wrappers require extra work when one is tracing a complex problem. Because of course one must follow the data through each of those extra layers.
And as I said the people I work with are reasonably intelligent so I don't feel that I need to provide extra work for the problems on which they are going to spend most of their time anyways.
As to in what package to put them, I prefer separate packages based on functionality and type of class.
But I've seen people who don't use any package at all. Effectively they take "put DTOs together with the objects that populate them" further and put every class in an application in the same package.
I've encountered sysadmins who insisted that all classes (including those of 3rd party code...) adhered to a predefined directory structure allowing only companyname.projectname as package without any subpackages (we shot them, or would have had had we weapons enough).
They of course didn't know anything about Java but that's what they'd always used with PL/I and Cobol so it was good enough for eternity.
> You do mean your support classes that you described
> above. Rather than, for instance, putting them in the
> same package as the DAO layer right?
No the DTOs, DAO and support classes all go in the same pacage. They are the only things in that package. The packages are divided up by if two DTOs are associated with each other they are in the same package.
> I don't believe that DTOs belong in the same package
> as the DAO layer (nor the GUI layer for that matter.)
> If you have support classes and/or wrappers then they
> belong in the same package.
Why not? What's the reasoning. I've done things that way. It's using the package mechanism as a filing cabinet. Package-protected access is so useful but you ca't take advantage of it if you put classes that are associated in different packages. I don't even think it makes sense in a filing cabinet way. You have to jump around from package to package and a naming scheme is required to make this organized in large applications.
> But extra wrappers require extra work when one is
> tracing a complex problem. Because of course one must
> follow the data through each of those extra layers.
the methodology I proposed doesn't require any more tracing than a method requires.
> And as I said the people I work with are reasonably
> intelligent so I don't feel that I need to provide
> extra work for the problems on which they are going to
> spend most of their time anyways.
When I worked with code designed the way you describe, I did spend a lot of time searching and debugging problems. I find that to be less the case with the methodolgy I have described. A lot of the old problems just don't occur.
> As to in what package to put them, I prefer separate
> packages based on functionality and type of class.
>
> But I've seen people who don't use any package at all.
> Effectively they take "put DTOs together with the
> objects that populate them" further and put every
> class in an application in the same package.
>
That would be a problem.
> I've encountered sysadmins who insisted that all
> classes (including those of 3rd party code...) adhered
> to a predefined directory structure allowing only
> companyname.projectname as package without any
> subpackages (we shot them, or would have had had we
> weapons enough).
A system administrator? Why was that even a concern for a sys admin? How did they even know what you were doing?
>
> No the DTOs, DAO and support classes all go in the
> same pacage. They are the only things in that
> package. The packages are divided up by if two DTOs
> are associated with each other they are in the same
> package.
>
> > I don't believe that DTOs belong in the same package
> > as the DAO layer (nor the GUI layer for that matter.)
> > If you have support classes and/or wrappers then they
> > belong in the same package.
>
> Why not?
For the same reason that the GUI doesn't belong in the same package.
> What's the reasoning. I've done things that
> way. It's using the package mechanism as a filing
> cabinet. Package-protected access is so useful but
> you ca't take advantage of it if you put classes that
> are associated in different packages.
If you feel that you need to use package access then of course you have to put it in the same package.
> I don't even
> think it makes sense in a filing cabinet way. You
> have to jump around from package to package and a
> naming scheme is required to make this organized in
> large applications.
I have no idea what you mean by "jump around from package to package."
>
> > But extra wrappers require extra work when one is
> > tracing a complex problem. Because of course one must
> > follow the data through each of those extra layers.
>
> the methodology I proposed doesn't require any more
> tracing than a method requires.
>
If the GUI is using a wrapper class which in turn actually accesses the actual DTO then you have an additional layer.
But perhaps I misunderstood your point about that.
> > And as I said the people I work with are reasonably
> > intelligent so I don't feel that I need to provide
> > extra work for the problems on which they are going to
> > spend most of their time anyways.
>
> When I worked with code designed the way you describe,
> I did spend a lot of time searching and debugging
> problems. I find that to be less the case with the
> methodolgy I have described. A lot of the old
> problems just don't occur.
Then perhaps your layers work differently than mine or you work with different people.
> For the same reason that the GUI doesn't belong in the
> same package.
What is that reason exactly and why does it apply here?
> If you feel that you need to use package access then
> of course you have to put it in the same package.
I don't have to use package protected access I just find it to be very effective.
> I have no idea what you mean by "jump around from
> package to package."
DTOs don't really interact with other DTOs. Generally when debugging or attempting to use a subsytem I work with a set of classes that interact with each other, not the classes that are similar to each other. So I find that I will have a class each from a set of packages. If you put all the classes that are coupled together in a single package I can go to that package and see the classes that I need to work with.
> If the GUI is using a wrapper class which in turn
> actually accesses the actual DTO then you have an
> additional layer.
It's the 'only' layer. Where's the additional one?
> Then perhaps your layers work differently than mine or
> you work with different people.
Yes, that's possible.
The other thing I dislike is when the packages are too specific. I've worked with code where a lot of packages have a single class in them.
> > For the same reason that the GUI doesn't belong in the
> > same package.
>
> What is that reason exactly and why does it apply
> here?
>
Packaging primarily should be used to group functionality.
> > If you feel that you need to use package access then
> > of course you have to put it in the same package.
>
> I don't have to use package protected access I just
> find it to be very effective.
>
> > I have no idea what you mean by "jump around from
> > package to package."
>
> DTOs don't really interact with other DTOs. Generally
> when debugging or attempting to use a subsytem I work
> with a set of classes that interact with each other,
> not the classes that are similar to each other. So I
> find that I will have a class each from a set of
> packages. If you put all the classes that are coupled
> together in a single package I can go to that package
> and see the classes that I need to work with.
>
So you do it because that way you can have them all in one directory?
Myself I have no problem seeing the DTOs in a seperate directory.
> > If the GUI is using a wrapper class which in turn
> > actually accesses the actual DTO then you have an
> > additional layer.
>
> It's the 'only' layer. Where's the additional one?
>
You have three classes....
1. GUI
2. Wrapper
3. DTO
If I have a problem in the GUI I am going to need to trace the data from the GUI to the wrapper to the DTO.
If the wrapper did not exist then there would be one less class to look at.
> Packaging primarily should be used to group
> functionality.
I disagree completely. Look at the JDK. There's not a package for all the factories and package for all the primitive wrappers. There's a package for sax and dom and util and text. My experience is that people use packages in order to categorize things like a biologist uses class, phyllum, genus, etc. But a package is much more effective as semi-autonomous unit.
For example if I want security functionality I grab the security package and it has everything I need for security instead of picking classes from many different packages based lexical relationships betrween the class names.
> So you do it because that way you can have them all in
> one directory?
Not just to have them in one directory. So that it's clear what goes with what and I can easily implement special access and associations between classes explcitly instead of relying on the knoweledge of myself or other developers to keep things straight.
> Myself I have no problem seeing the DTOs in a seperate
> directory.
Have you ever tried what I am suggesting? I've tried it your way.
> You have three classes....
>
> 1. GUI
> 2. Wrapper
> 3. DTO
>
> If I have a problem in the GUI I am going to need to
> trace the data from the GUI to the wrapper to the DTO.
The DTO doesn't have any methods or at least nothing non-trivial.
> If the wrapper did not exist then there would be one
> less class to look at.
That's really not significant.
> > Packaging primarily should be used to group
> > functionality.
>
> I disagree completely. Look at the JDK. There's not
> a package for all the factories and package for all
> the primitive wrappers. There's a package for sax and
> dom and util and text. My experience is that people
> use packages in order to categorize things like a
> biologist uses class, phyllum, genus, etc. But a
> package is much more effective as semi-autonomous
> unit.
>
> For example if I want security functionality I grab
> the security package and it has everything I need for
> security instead of picking classes from many
> different packages based lexical relationships
> betrween the class names.
Yes when one creates a library (as we have discussed before) then the layout is different then if one is creating an application.
I certainly have never created a library, much less more than one library, to provide access to a database.
I have created many applications however that use databases. And for those the functionality for the database layer will be in one sub-system and the GUI will be in another.
Within each sub-system there might be one or more functional groupings. And conceivably there could be a need to group different DTOs together under different functional groups (I have never needed to do that.)
But even so the DTOs encapsulate the data that moves between the different sub-systems. And thus do not belong to any of the sub-systems. (Although for no other reason than convenience I usually make a sub package in the database layer to contain them.)
>
> > So you do it because that way you can have them all in
> > one directory?
>
> Not just to have them in one directory. So that it's
> clear what goes with what and I can easily implement
> special access and associations between classes
> explcitly instead of relying on the knoweledge of
> myself or other developers to keep things straight.
>
Perhaps you deal with more complex issues than those that I have seen.
For the projects that I have worked on, including the one with 30 developers, a single DTO location is sufficent and no one was confused by that.
> > Myself I have no problem seeing the DTOs in a seperate
> > directory.
>
> Have you ever tried what I am suggesting? I've tried
> it your way.
>
I have tried a number of things which includes wrappers and putting all the DTOs in with other functionality. There was no gain that I saw and it made made it more complex (along with making distribution packaging that required manual maintainance.)
> > You have three classes....
> >
> > 1. GUI
> > 2. Wrapper
> > 3. DTO
> >
> > If I have a problem in the GUI I am going to need to
> > trace the data from the GUI to the wrapper to the DTO.
>
> The DTO doesn't have any methods or at least nothing
> non-trivial.
That does not matter. If you are tracing a complex data bug, then you need to look at where the data goes, how it is stored, etc.
>
> > If the wrapper did not exist then there would be one
> > less class to look at.
>
> That's really not significant.
As I said, tracing a complex data bug in your system means that there is one more layer to look at.
I don't believe I actually said that it was significant or not, but rather that there was another layer. However that means that conceptually more work is required. Whether that is measurably significant or not is a different matter.
> Yes when one creates a library (as we have discussed
> before) then the layout is different then if one is
> creating an application.
>
> I certainly have never created a library, much less
> more than one library, to provide access to a
> database.
I think it makes a lot of sense to treat classes shared between the server and client as a library. Especially when you have different teams of developers developing the client and server code.
> I have created many applications however that use
> databases. And for those the functionality for the
> database layer will be in one sub-system and the GUI
> will be in another.
I'm not suggesting putting GUI code with the DB code.
> But even so the DTOs encapsulate the data that moves
> between the different sub-systems. And thus do not
> belong to any of the sub-systems. (Although for no
> other reason than convenience I usually make a sub
> package in the database layer to contain them.)
That's it exactly. The DTOs are part of bridge between the client and server code. Therefore they go in a package that belongs to neither and both.
> For the projects that I have worked on, including the
> one with 30 developers, a single DTO location is
> sufficent and no one was confused by that.
It's not really confusing per se, it's just incovienient. This is really just a minor advantage. The main advantage is the ability to simplify the public contract of the DTO. Everything that 'normal' classes need to do with the DTO is public and nothing more.
> I have tried a number of things which includes
> wrappers and putting all the DTOs in with other
> functionality. There was no gain that I saw and it
> made made it more complex (along with making
> distribution packaging that required manual
> maintainance.)
Yes, you have to be careful not to put the server side classes in the GUI build and vice versa but it doesn't have to be manual. An Ant build can handle it.
> That does not matter. If you are tracing a complex
> data bug, then you need to look at where the data
> goes, how it is stored, etc.
This is true. If the developer doesn't understand the design they will probably have a more difficult time debugging problems. But my experience is that I get questions during developement like "Why can't I do X?" Instead of finding bugs and asking people "Why are you doing this?" at testing.
But it may be that you have worked in different environments.
>
> > But even so the DTOs encapsulate the data that moves
> > between the different sub-systems. And thus do not
> > belong to any of the sub-systems. (Although for no
> > other reason than convenience I usually make a sub
> > package in the database layer to contain them.)
>
> That's it exactly. The DTOs are part of bridge
> between the client and server code. Therefore they go
> in a package that belongs to neither and both.
>
You lost me there.
You made the following reply in a previous post....
> I don't believe that DTOs belong in the same package
> as the DAO layer (nor the GUI layer for that matter.)
> If you have support classes and/or wrappers then they
> belong in the same package.
Why not?
And now, my interpretation of what you just said, is that you are now agreeing with me (and thus contradicting what you said earlier.)
> > For the projects that I have worked on, including the
> > one with 30 developers, a single DTO location is
> > sufficent and no one was confused by that.
>
> It's not really confusing per se, it's just
> incovienient. This is really just a minor advantage.
> The main advantage is the ability to simplify the
> public contract of the DTO. Everything that 'normal'
> classes need to do with the DTO is public and nothing
> more.
>
Huh?
My DTOs don't have anything in them that 'normal' classes do not need to access.
Matter of fact the last couple of times nothing in them was private. And as far as I know everything was used in different layers.
> > I have tried a number of things which includes
> > wrappers and putting all the DTOs in with other
> > functionality. There was no gain that I saw and it
> > made made it more complex (along with making
> > distribution packaging that required manual
> > maintainance.)
>
> Yes, you have to be careful not to put the server side
> classes in the GUI build and vice versa but it doesn't
> have to be manual. An Ant build can handle it.
>
If you have mixed classes in one package that are not all distributed to every source then you will need to manually manage that. Modifying a ant file is still a manual process.
> > That does not matter. If you are tracing a complex
> > data bug, then you need to look at where the data
> > goes, how it is stored, etc.
>
> This is true. If the developer doesn't understand the
> design they will probably have a more difficult time
> debugging problems.
On complex data problems it doesn't matter if they understand the design or not. Such problems might encompass data not showing up, being mangled, etc. In a case like that the only solution is to completely trace the data to find the problem.
Now there are probably problems that wouldn't exist if they did understand the design. For example if they did not properly populate a query DTO to actually produce the result they expected. But that is not the class of problem that I am referring to.
> But my experience is that I get
> questions during developement like "Why can't I do X?"
> Instead of finding bugs and asking people "Why are
> you doing this?" at testing.
>
> But it may be that you have worked in different
> environments.
If I understand what you are saying then yes we are working in substantially different environments.
> And now, my interpretation of what you just said, is
> that you are now agreeing with me (and thus
> contradicting what you said earlier.)
Sorry. You are totally right. What I should say is that the DAO, the DTO, the wrappers, and classes that pass the DTOs are in the same package. The DAO in ths case is really just a DTO factory that happens to pull fom a DB.
> My DTOs don't have anything in them that 'normal'
> classes do not need to access.
The wrappers have no constructors. There's no way to set keys directly. Only things that that 'client' (where the client could be a server class) needs are available.
This becomes very important when managing dirty markers. Only classes in the package can mark the a ditry DTO as clean, for example. Clients cannot create instances of the DTO willy-nilly. That's important when woking wth a proxy pattern.
There are other solutions that we have tried but they ended up being too complicated and procedural. That lead to tough bugs.
> Matter of fact the last couple of times nothing in
> them was private. And as far as I know everything was
> used in different layers.
So with all public members, is there something a specific layer can do but shouldn't?
> If you have mixed classes in one package that are not
> all distributed to every source then you will need to
> manually manage that. Modifying a ant file is still a
> manual process.
So is writing code but i don't really think of that when someone says "manual process."
> On complex data problems it doesn't matter if they
> understand the design or not. Such problems might
> encompass data not showing up, being mangled, etc. In
> a case like that the only solution is to completely
> trace the data to find the problem.
I don't really see how using my design complicates debugging those kinds of problem. In a lot of ways I think it simplfies things as the DTO is so uncomplex and it is package-protected so there is a limited amount of code that can even interact with the Objects.
Hi, hope that you will read this.
How about implementing DTOs dynamically, i.e. make use of the dynamic proxy mechanism the Java APIs provide?
That means that you define a read-only or immutable interface to your entity objects representing the data that you would like to transfer. If you need to transfer these by network you must also provide some serialization mechanism of course, but as long as you are not, this should be really straight-forward:
public class DynamicDTOFactory
{
private class DTOInvocationHandler
extends java.lang.reflect.InvocationHandler
{
private Object entityObject;
public DTOInvocationHandler( Object entityObject )
{
this.entityObject = entityObject;
}
public Object invoke( Object proxy,
Method method,
Object[] args ) throws Throwable
{
return method.invoke( this.entityObject, args );
}
}
public DynamicDTOFactory()
{}
public Object createDTO( Object entityObject, Class[] ifaces )
{
// note that all ifaces must be implemented by the entityObject!
return java.lang.reflect.Proxy.newProxyInstance(
entityObject.getClass().getClassLoader(),
ifaces,
new DTOInvocationHandler( entityObject ) );
}
}
public interface ImmutableEntityObject
{
public String getName();
}
public interface MutableEntityObject extends ImmutableEntityObject
{
public void setName( String name );
}
public class EntityObject implements MutableEntityObject
{
private String name;
public EntityObject() {}
public void setName( String name ) { this.name = name; }
public String getName() { return this.name; }
}
this should do the trick, at least in theory, as I have not tested the above code.
The DynamicDTOFactory creates an Interface-Proxy from scratch for every entity object that you pass to it. However, you will have to decompose your interfaces into mutable and immutable interface, i.e. read-only and read-write interfaces. DTOs as far as I am concerned are always read-only, so that should not be much of a problem here. And, you will not have to copy the data that is inside your entity objects at all. And it is thread-safe as long as the entity object is not modified whilst reading the DTO. Yet, if you need to make it multi-thread-safe you will have to copy your entityObject on entry of the createDTO() method of the factory.
Hope this helps...
Carsten
One second word about lists, maps and arrays.
See for yourself the JavaServerFaces API, which in itself is not a bad thing, but the bad comes from the unspecified session management the JSF provides. Everything is passed out as an Array and, frankly, puts us in a state of unspecifiedness that is not easy to cope with. So I would say that passing data between the model and the view should be more sanctioned and the mechanism be specified than just being arrays and lists or maps of arbitrary objects.
Just my two cents.
Carsten
> Hi, hope that you will read this.
>
> How about implementing DTOs dynamically, i.e. make
> use of the dynamic proxy mechanism the Java APIs
> provide?
I already addressed that in the first few replies.
It is easy to program but very difficult to debug in particular because errors that would normally show up at compile time will only show up at runtime.
>
> That means that you define a read-only or immutable
> interface to your entity objects representing the
> data that you would like to transfer. If you need to
> transfer these by network you must also provide some
> serialization mechanism of course, but as long as you
> are not, this should be really straight-forward:
>
One must be careful with that train of thought.
A DTO can certainly be serializable (and/or implemented as a hash.) But one has to be careful about the functionality that the DTO has because once you start adding functionality then you might end up creating an object that is not a DTO.
(On the other hand if you are not discussing a DTO in the first place then this isn't the thread to address the issue.)
Thanks for pointing that one out, I must have overread it as there were no examples...Regards,Carsten
> I prefer 1, but then I always use code generation.
> For me there is really only one downside to using the hash map and that is that debugging them > is nightmarish.
Was that it? Well if it was, it would cause the original poster to struggle with it as it provides no hint whatsoever on dynamically creating his DTOs.
But, no harm done, I say, and no offense on behalv of mine.
I believe that even serialization can dynamically be done by extending the Proxy class provided adding the required protected read and write methods. Yet it requires that the receiver can dynamically construct a proxy from the data received to resemble the state of the server.
Yet, this would require much more code to be developed and delivered, I believe and I leave it up to the original posters imagination to come up with an appropriate solution.
Regards,
Carsten
dear sir Ple. tode me what is the function or use DTO in advance Java Program.Define me.thanksWith regerds rajib
Hi,
I am just working on a small project with Struts and the company I work for uses Maps for this small application instead of DTOs.
But I strongly advise you against using this kind of implementation.
The reason is that there are indeed a lot of casts and it gets pretty messy, far more than by creating your DTOs.
However, I don't know how big your project is, but if it has to be planned very good, or you intend to plan it very good, use your own DTOs. Once written the process of implementation will be way faster than using MAPs (just think of typing mistakes, renaming fields (just getting a gooseflesh)).
I can only recommend you to use DTOs (real DTOs).
I put the DTOs in seperate package from the DAO or other users of the DTOs. My DTOs have public access. I put everything in seperate packages. It helps my coding focus since all classes in the package should look resonable the same and have same general format.
My DAOs are also in their own package with public access. Again, they are only meaningful to classes that have the connection, so their publicness does not matter.
I used to use default access and have one class that was public and served as a factory to get at the package classes. But functionally this is no better than having them all public...So now they are all public and protection is mainly at runtime since you can't get any meaningful instance without the proper channels.
> I put the DTOs in seperate package from the DAO or
> other users of the DTOs. My DTOs have public access.
> I put everything in seperate packages. It helps my
> coding focus since all classes in the package should
> look resonable the same and have same general
> format.
That is what I do, but some people prefer to keep them together because it allows protected access for methods.
By the way this is a resurrected thread.
> That is what I do, but some people prefer to keep
> them together because it allows protected access for
> methods.
All my DTO methods are public so my DAOs get full access. However, the DTOs are only released through interfaces to the rest of the world, so they do not get access to methods no present on the interface.
I think its more expressive to manage interfaces than protected methods.But everything has its place.
>
> By the way this is a resurrected thread.
Heh, seem to be a lot of DAO DTO posts lately.