aspose file tools*
The moose likes Java in General and the fly likes Composition - instantiation versus parameter passed to Constructor Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Java » Java in General
Bookmark "Composition - instantiation versus parameter passed to Constructor" Watch "Composition - instantiation versus parameter passed to Constructor" New topic
Author

Composition - instantiation versus parameter passed to Constructor

John Ryan
Ranch Hand

Joined: Mar 14, 2001
Posts: 124
Hi all,
I have a theoretical OO design question which I was hoping someone could help me with. I have a particular Class MessageProcessor whose responsibility is to process a message by extracting some data and then sending that message to an external partner. I have another class CommunicationHandler whose responsibility it is to send the new message to the external partner.
The MessageProcessor will use the behaviour of CommunicationHandler through composition. What Im wondering is whether an instance of CommunicationHandler should be created within the MessageProcessor when its needed or should I pass the CommunicationHandler to the MessageProcessor constructor.
At the moment Im creating the MessageHandler using a factory so Im creating the CommunicationHandler within the factory's create method and passing it the MessageProcessors constructor. However I could just have easily have created the CommunicationHandler within the MessageProcessors constructor (which is bugging me a bit as I should surely be able to justofy somthing like this).
So I suppose what I am looking for are a few guidelines/design rules that would point me in the right direction.
Cheers John
Stan James
(instanceof Sidekick)
Ranch Hand

Joined: Jan 29, 2003
Posts: 8791
It's often useful to configure an object by telling it what its parts are. Say CommHandler is an interface, and you configure MessageHandler like this:
messageHandler.setCommHandler(someCommHandler)
Now messageHandler could be talking to any of a variety of CommHandlers, maybe one that does sockets, another that does SOAP and another that is a mock handler just for unit testing. Actually that last case may be enough reason to do it. Are you familiar with mock objects? If not, start a new thread. They are cool.
This is probably the opposite of reality, but say messageHandler is very stable and will never change, while CommHandler must frequently adapt to new networks, protocols, addresses, etc. You want the less stable package to have compile time dependencies to the more stable package. MessageHandler's package could define the CommHandler interface so that any unstable packages that implement CommHandler will depend on the stable MessageHandler package. MessageHandler will never know the actual classes that implement CommHandler, so it would have a hard time creating a CommHandler in its constructor.
Any of that help? Hope it wasn't too far off the deep end. OO Theory is great fun!


A good question is never answered. It is not a bolt to be tightened into place but a seed to be planted and to bear more seed toward the hope of greening the landscape of the idea. John Ciardi
John Ryan
Ranch Hand

Joined: Mar 14, 2001
Posts: 124
Hi Stan.
Thanks for your comments. Much appreciated.
Originally posted by Stan James:
It's often useful to configure an object by telling it what its parts are. Say CommHandler is an interface, and you configure MessageHandler like this:
messageHandler.setCommHandler(someCommHandler)
Now messageHandler could be talking to any of a variety of CommHandlers, maybe one that does sockets, another that does SOAP and another that is a mock handler just for unit testing. Actually that last case may be enough reason to do it. Are you familiar with mock objects? If not, start a new thread. They are cool.

Actually I am using a CommunicationHandler interface. I should have specified that it is a CommunicationHandler interface that I am passing to the MessageHandler constructor. So I suppose there is no difference between using the constructor or the set method to configure the CommunicationHandler interface so I am on the right tracks.


This is probably the opposite of reality, but say messageHandler is very stable and will never change, while CommHandler must frequently adapt to new networks, protocols, addresses, etc. You want the less stable package to have compile time dependencies to the more stable package. MessageHandler's package could define the CommHandler interface so that any unstable packages that implement CommHandler will depend on the stable MessageHandler package. MessageHandler will never know the actual classes that implement CommHandler, so it would have a hard time creating a CommHandler in its constructor.
Any of that help? Hope it wasn't too far off the deep end. OO Theory is great fun!

Yes this makes some sense.By passing an interface to the MessageHandler Constructor I have minimized the coupling between the MessageHandler and CommunicationHandler and this ensures that the actual type of the CommunicationHandler can vary. I understand that MessageHandler will never know the actual classes that implement CommHandler, so it would have a hard time creating a CommHandler in its constructor.
However I am unclear as to your point regarding the compile time linking of the stable and unstable packages. What is the purpose of creating the CommunicationHandler within the MessageHandler package. Usually I would expect this to be defined within my Communication package? How does having the CommunicationHandler interface in the MessageHandler package change anything?. If the signature of one of the methods in the CommunicationHandler interface changes and this method is used by the MessageHandler then I would get a compile time error irrespective of the package the CommunicationHandler interface exists in.
John
[ November 10, 2003: Message edited by: John Ryan ]
Stan James
(instanceof Sidekick)
Ranch Hand

Joined: Jan 29, 2003
Posts: 8791
I just prepared a presentation on the Dependency Inversion Principle for my team; I regret I can't post the whole PPT somewhere for you to see. It does seem most intuitive to put the Interface in a package with the implementations. But that makes the general message handler dependent on the specific comm package, also described as making the policy (what we want to do) depend on the mechanism (how we do it). This is sub-optimal for long term system life.
Say we wanted to later integrate a 3rd party comm object. MsgHandler definitely doesn't know how to call it, so we need an adapter. The adapter must depend on the comm package to implement the interface. Now we have to deploy the comm package to use the 3rd party package. Hmmm.
Say we want to split the comm package into two and deploy one or the other to various customers. The one wihtout the interface depends on the one with the interface. Ooops, can't deploy that one alone.
By moving the interface definition into the msghandler package, we invert the dependency. Comm depends on MsgHandler. The mechanism depends on the policy. This is cool, because now we can add any number of new comm packages (not just classes!) including an adapter to a new 3rd party comm package without touching the MsgHandler. MsgHandler is now open for extension with new comm packages, but closed for modification. This yields all kinds of goodness in compiling, testing, deploying new comm packages etc.
Design is always compromise. Are you designing for comm to be reusable in other systems, maybe marketed as a binary-only jar? Then it needs to own its interface. Or are you designing for the stable part of your system to survive changes in the less stable parts? Then it needs to satisfy MsgHandler's requirements.
For more fun, think about how JDBC plays two roles. It must be reused by many applications. It must be stable over many drivers. Dependencies flow IN to JDBC from both directions. Writing an application you use one set of interfaces. Writing a driver you use another set of interfaces. But in both cases, JDBC owns the interface and does not depend on the app or the driver.
Any of that help?
John Ryan
Ranch Hand

Joined: Mar 14, 2001
Posts: 124
Originally posted by Stan James:

Design is always compromise. Are you designing for comm to be reusable in other systems, maybe marketed as a binary-only jar? Then it needs to own its interface. Or are you designing for the stable part of your system to survive changes in the less stable parts? Then it needs to satisfy MsgHandler's requirements.
For more fun, think about how JDBC plays two roles. It must be reused by many applications. It must be stable over many drivers. Dependencies flow IN to JDBC from both directions. Writing an application you use one set of interfaces. Writing a driver you use another set of interfaces. But in both cases, JDBC owns the interface and does not depend on the app or the driver.
Any of that help?

Yes I suppose I am definately designing for the stable part of my system to survive changes in the less stable parts.
Yes it does help. Thanks for your comments Stan. I hadnt heard of the Dependency Inversion Principle so Ive found some stuff on the web on it now.
Stan James
(instanceof Sidekick)
Ranch Hand

Joined: Jan 29, 2003
Posts: 8791
Glad that helped. DIP was a bit of a revelation to me, too, and explained why some things we did in PowerBuilder a few years ago went so badly. Course we had no interfaces there.
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Composition - instantiation versus parameter passed to Constructor