Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Object Construction/Initialization Methods

1 view
Skip to first unread message

Jürgen Lind

unread,
Jul 31, 2002, 5:39:38 AM7/31/02
to
Hi,

recently, we had a debate about the preferred way to construct a new object from
the data of another object. For example, in a client-server environment, it is
often the case that you would like to insulate the data model used on the client
side from that used on the server side. Thus, you have to translate the
server-side objects to client-side objects. The question is, how to do this.

Basically, we could see three possibilities:

* the client-side objects have a constructor that accepts a server-side object
as parameter, thuis would yield the following code

ServerSideObject sso = server.get(...);
ClientSideObject cso = new ClientSideObject(sso);

* the client-side object has a constructor that accepts explicit server-side
object fields:

ServerSideObject sso = server.get(...);
ClientSideObject cso = new ClientSideObject(sso.getData1(), sso.getData2());

* the client-side object provides only setter methods for particular data
fields:

ServerSideObject sso = server.get(...);
ClientSideObject cso = new ClientSideObject();
cso.setData1(sso.getData1());
cso.setData2(sso.getData2());

Now, which of these methods should be preferred over the others? For what
reasons (performance, coupling, extensibility)?

Any opinons on this issue?


Jürgen

--
Dr. Jürgen Lind
iteratec GmbH Fon: +49 (0)89 614551-44
Inselkammerstrasse 4 Fax: +49 (0)89 614551-10
82008 Unterhaching Web: www.iteratec.de

Jim Sculley

unread,
Jul 31, 2002, 8:48:23 AM7/31/02
to

Why not provide a clone() method? A similar situation exists when you
have an application with 'preferences'. If the user wants to change the
preferences, you typically display a dialog in which those preferences
can be changed. There are usually 'OK' and 'Cancel' buttons. If 'OK'
is clicked, you want the changes to be made. If 'Cancel' is clicked,
you want to revert to the old preferences. Rather than jump through
hoops to keep track of things, you can clone an object encapsulating the
current settings. Any changes made happen to the clone. If 'OK' is
clicked, a setter method of the application can be called, passing in
the cloned settings. If 'Cancel' is clicked, you don't have to do
anything, because the original preferences are still in place.

The clone() method allows you to have reasonably good control over what
state is shared, and what stated is unique between instances. It also
promotes encapsulation, since the object itself is responsible for
making its own copies. If the clone() method is properly implemented,
external code can safely assume that modifying a clone won't cause
problems with other instances.

Jim S.

Davor Cengija

unread,
Jul 31, 2002, 9:31:32 AM7/31/02
to

"Jürgen Lind" <Juerge...@iteratec.de> wrote in message
news:3D47B05C...@iteratec.de...

> Hi,
>
> recently, we had a debate about the preferred way to construct a new
object from
> the data of another object.

> * the client-side objects have a constructor that accepts a server-side


object
> as parameter, thuis would yield the following code
>
> ServerSideObject sso = server.get(...);
> ClientSideObject cso = new ClientSideObject(sso);
>
> * the client-side object has a constructor that accepts explicit
server-side
> object fields:
>
> ServerSideObject sso = server.get(...);
> ClientSideObject cso = new ClientSideObject(sso.getData1(),
sso.getData2());
>
> * the client-side object provides only setter methods for particular data
> fields:
>
> ServerSideObject sso = server.get(...);
> ClientSideObject cso = new ClientSideObject();
> cso.setData1(sso.getData1());
> cso.setData2(sso.getData2());

Or you can use Factory. That way you have decoupled cso and sso (ie cso
doesn't need to know about sso's format).

ClientSideObject cso = ClientSideObjectFactory.create(fromThisSso);

Different implementations with a similar approach are also possible, of
course.


Jean-Baptiste Nizet

unread,
Jul 31, 2002, 10:53:16 AM7/31/02
to
See inline...

Jürgen Lind wrote:
> Hi,
>
> recently, we had a debate about the preferred way to construct a new
> object from
> the data of another object. For example, in a client-server environment,
> it is
> often the case that you would like to insulate the data model used on
> the client
> side from that used on the server side. Thus, you have to translate the
> server-side objects to client-side objects. The question is, how to do
> this.
>

This is basically the "Data Object" or "Value Object" pattern,
well-knows by anyone who makes EJBs. I suggest reading from
theserverside.com and from the J2EE design patterns at Sun about this.
See more details inline...

> Basically, we could see three possibilities:
>
> * the client-side objects have a constructor that accepts a server-side
> object
> as parameter, thuis would yield the following code
>
> ServerSideObject sso = server.get(...);
> ClientSideObject cso = new ClientSideObject(sso);
>

This is not acceptable, since it makes the client-side object dependent
on your server-side object. You want to isolate the client from the
server implementation, so don't do that.

> * the client-side object has a constructor that accepts explicit
> server-side
> object fields:
>
> ServerSideObject sso = server.get(...);
> ClientSideObject cso = new ClientSideObject(sso.getData1(),
> sso.getData2());
>

That's my preferred solution. It makes it possible to use immutable
client-side objects, which can be very important (for example, if the
primary key of your object is stored in your client-side object, you
want to make it read-only, and impolement your hashCode() and equals()
methods based on this primary key).

> * the client-side object provides only setter methods for particular data
> fields:
>
> ServerSideObject sso = server.get(...);
> ClientSideObject cso = new ClientSideObject();
> cso.setData1(sso.getData1());
> cso.setData2(sso.getData2());

You could do that, but it makes your object mutable. That's not always a
good thing.

JB.

Ryan Breidenbach

unread,
Jul 31, 2002, 11:12:51 AM7/31/02
to
Jürgen Lind <Juerge...@iteratec.de> wrote in message news:<3D47B05C...@iteratec.de>...


There is another solution to this. You can create a
ClientSideObjectFactory that is responsible for creating the
ClientSideObject from the ServerSideObject. This decouples the
ServerSideObject from the ClientSideObject.

Ryan

Jean-Baptiste Nizet

unread,
Jul 31, 2002, 11:27:51 AM7/31/02
to
Ryan Breidenbach wrote:
> Jürgen Lind <Juerge...@iteratec.de> wrote in message news:<3D47B05C...@iteratec.de>...
>
>>Hi,
>>
>>recently, we had a debate about the preferred way to construct a new object from
>>the data of another object. For example, in a client-server environment, it is
>>often the case that you would like to insulate the data model used on the client
>>side from that used on the server side. Thus, you have to translate the
>>server-side objects to client-side objects. The question is, how to do this.
>>


<snipped>


> There is another solution to this. You can create a
> ClientSideObjectFactory that is responsible for creating the
> ClientSideObject from the ServerSideObject. This decouples the
> ServerSideObject from the ClientSideObject.
>
> Ryan

This doesn't solve the problem: the factory will still have to create
the client-side objects. Will it use another factory?

JB.

Jean-Baptiste Nizet

unread,
Jul 31, 2002, 11:28:47 AM7/31/02
to
Davor Cengija wrote:

<snipped>

>
> Or you can use Factory. That way you have decoupled cso and sso (ie cso
> doesn't need to know about sso's format).
>
> ClientSideObject cso = ClientSideObjectFactory.create(fromThisSso);
>
> Different implementations with a similar approach are also possible, of
> course.
>
>

This doesn't solve the problem: the factory will still have to create

Jean-Baptiste Nizet

unread,
Jul 31, 2002, 11:34:36 AM7/31/02
to
Jim Sculley wrote:
> Jürgen Lind wrote:
>
>> Hi,
>>
>> recently, we had a debate about the preferred way to construct a new
>> object from
>> the data of another object. For example, in a client-server
>> environment, it is
>> often the case that you would like to insulate the data model used on
>> the client
>> side from that used on the server side. Thus, you have to translate the
>> server-side objects to client-side objects. The question is, how to do
>> this.
>>

<snipped>

>
>
> Why not provide a clone() method?

Because in a client-server approach, server-side objects are often
unusable at client-side. These server-side objects could be EJBs, that
rely on a container to handle them. They could be persistent objects,
that come from an OODBMS, etc. Usually, these kinds of server-side
objects are only meant to be used inside of a persistence framework, and
are not Serializable.

JB.

<snipped>

Chris

unread,
Aug 1, 2002, 4:16:25 AM8/1/02
to
The 'Value Object' pattern is frequently used in the situation you
describe, and particularly when using EJBs.

Check out:
http://www.precisejava.com/javaperf/j2ee/Patterns.htm
for a nice overview.

- sarge

willy gates

unread,
Aug 1, 2002, 5:18:42 AM8/1/02
to
I would appreciate comments/criticism on my recent solution to this
problem.

I have server that talk to a database and a client that displays a GUI
(wo-hoo).

The main thing that I need to display is a Customer which has about 40
fields, and has associated Address and Policy objects.

I implemented the Customer, Address and Policy objects so they just
held the fields required and then made these available for both the
client and server to use. (in a ipcshare.jar file). The idea is that
these basic objects are useful to both the client and the server
(these are ValueObjects I suppose) but the client or server can
specialise them to make them more useful for their own needs without
needing to clone or construct from them.

e.g.

class Customer
{

protected String name;
protected Address abode;
protected Address work;
...

protected Customer ();
}

My server side customer needed to be much more complicated i.e. it
needed to construct itself from a ResultSet (a database reply) so I
extended Customer to ServerSideCustomer. The ServerSideCustomer will
then be able to upcast to a Customer before returning it to the
client.


class ServerSideCustomer extends Customer
{
ServerSideCustomer( ResultSet rs )
{
//set all the protected super class members
name = rs.getString("name");

//abode is an Address object therefore it needs to be constructed.
int aboderef = rs.getInt("abode");

//Turn it into an object
ResultSet rs_for_address = some_database_lookup();
abode = (Address) new ServerSideAddress(
databaselookuptogetaResultSet );

//etc...
}
}

Then the server can provide an RMI method such as getCustomer( int
custID) as follows:

Customer getCustomer( int custID )
{
ResultSet rs = theDatabase.lookupCustomer( custID );
return (Customer) new ServerCustomer( rs );
}

comments....

Jean-Baptiste Nizet

unread,
Aug 1, 2002, 8:17:31 AM8/1/02
to

This is all fine if you realize that :
- casting the ServerCustomer to Customer doesn't transform the object at
all: it's still a ServerCustomer, and the client will have to have this
class on its classpath to be able to deserialize the object
- since your ServerSideCustomer class relies on ResultSet, this class
must also be in the client classpath, even if it's never used there.
ResultSet is in the JRE, but if you relied on another persistence
framework that would use, for example, FooSets instead of ResultSets,
FooSet would also have to be in the client classpath, which is not
normal, since the client normally doesn't have to deal with persistence.

I would use a completely dumb Customer object, shared by the client and
the server, and use a factory at server-side to create the Customer from
the ResultSet.

JB.

Ryan Breidenbach

unread,
Aug 1, 2002, 3:00:48 PM8/1/02
to
> > There is another solution to this. You can create a
> > ClientSideObjectFactory that is responsible for creating the
> > ClientSideObject from the ServerSideObject. This decouples the
> > ServerSideObject from the ClientSideObject.
> >
> > Ryan
>
> This doesn't solve the problem: the factory will still have to create
> the client-side objects. Will it use another factory?
>
> JB.

I didn't realize there was a problem to solve. The original question
was how to create a ClientSideObject from a ServerSideObject. This is
one way to do this. The original post was so vague, I didn't want to
assume EJBs, DAOs, or anything else.

Will it use another factory? I'm sure what this means. All I was
saying that if you delegate the responsibility of creating a
ClientSideObject from a ServerSideOject to another class (the
Factory), then the Client and Server classes have no dependecies on
each other. There are completely decoupled.

There is a lot of fine grained details you can introduce to this
discussion, especially when you bring in factors like immutability of
the ClientSideObject, EJBs, DAOs, Serialization, etc. I just tried to
keep it as simple as possible, seeing how the example was pretty
simple.

Ryan

0 new messages