Adept Software Development

Adept: (A)pplication (D)evelopment (E)nterprise to (P)ersonal (T)ransition. It is a system I am developing to leverage Enterprise developer skills to produce stand-alone software for other market segments. This is a general software development blog discussing issues about project, architecture, design and development. The emphasis will be in Java, but many of the issues will be more general. Almost all will be technical.

http://marringtons.com

Monday, April 11, 2005

Transferring Data Between Tiers

Tiers and slices are simply mechanisms for visualising the age-old principle of divide and conquer. For the ultimate in maintainability and reuse, it is best to keep the divisions as clear as possible.

A software object emulates objects in the real world by being a combination of information and functionality. To keep code regions separate and independant, however, it's best if they don't know anything about the internal functionality of their neighbours. You may ask an object to do a job or provide a result, but separation means you should not know about or rely on the methods the object uses to achieve that. You should know that you can use your calculator to add up, but you shouldn't be weighing up the variable resistance methods within the microchip that are used to represent binary data. The key to tiered design is to be creatively stupid.

So, when calling a service in another tier we should provide and receive pure information without attached functionality. When the said information is larger that a single primative it's often called a data transfer object or DTO.

There's another good reason for a DTO. If your application is J2EE EJB or otherwise designed so that it can be distributed, information will be passed by value rather than reference.

For the separation to occur it is important that the DTO be clean. It should contain mostly primative, other DTOs or well known classes that do not cause too much interdependence. Where possible, the latter should be immutable. There's nothing worse than receiving a DTO by RMI from a remote server that includes the whole session or security structure as a field. Not only is it massive to transfer over the wire, but you rebuild it locally without almost all the remote code existing locally in an up-to-date format. On the other hand a Map of String is quite acceptable since both sides will be using a common library.

I prefer DTOs to be very specific. I intensely dislike DTOs floating around with partially filled fields depending on what was asked for. It's also bad to have DTOs with information extraneous to requirements. Not only is it confusing when maintenance is required, but it also means you are retrieving information that is not required - often at considerable expense in resources. This can happen if you attempt to pass a DTO through more than one tier.

The persistence tier, for example, will probably have DTOs that match the database tables. There's a temptation when providing a service at the service layer to create a DTO that has persistence tier DTOs as fields. Resist. Firstly you are exposing too much of your database structure, secondly your service is presenting a complex graph to its client in a form not logical for that view and thirdly it's not common for data to require different formatting from different viewpoints. In an extreme case, the persistence layer may be using sql.date while the service layer uses Calendar and the GUI tiers deal with a string including a formatted date.

The bigest valid complaint against using DTOs in a clean compartmentalised manner is the need to be continually copying the contents at each tier interface - in both directions. I have seen tier interface services that are just masses of copy statements. Updating a DTO without changing all the copy code is a common source of subtle bugs.

The Adept library object package has a lot of support for DTOs. Specifically there is a DTO helper class with static methods for transfering data between DTOs and POJOs, both in bulk and given a list of required fields. It is a deep copy operation. There are also classes to convert DTOs to/from XML streams for data transfer and to/from name-value pairs for screen or form population and retrieval.

Using deep copy methods such as this allow you to remove the interface layers in each side of each tier since the copy can become a single line part of the logic layer of the tier.

0 Comments:

Post a Comment

<< Home