Reasons to use Adapters, not Listeners

C

Chris Berg

In a recent posting thread, I went into a discussion about using event
adapters as opposed to simply implementing the event listener
interface directly. A lot of pro and con can be said about this, but
one argument made me consider an aspect that I have never thought
about.

Generally, I don't like to subclass adapters, because the event
handler method usually requires access to a components fields, which
makes things messy if the listener is a separate class. It is much
easier to let a component implement the listener(s) of choice, leaving
the unused handler methods empty.

Anyway, it was pointed out that a reason to use adapters is that you
are more safe when the listener changes, that is, if another method is
added to the listener in a later version of the VM. Then the
corresponding adapter would of course have the method added, securing
that your application can still run under the new VM.

On first view, this seems to be a good argument, but after thinking a
bit about it, I wonder if that is really a risk? Has Sun actually ever
done that? I mean, putting new methods in an already published
interface seems to be risky, not only if Sun does it, but also if it
happens in a developer team. I would prefer to make a new interface,
which extends the old one and adds new methods.

Comments?

Chris
 
R

Raymond DeCampo

Chris said:
In a recent posting thread, I went into a discussion about using event
adapters as opposed to simply implementing the event listener
interface directly. A lot of pro and con can be said about this, but
one argument made me consider an aspect that I have never thought
about.

Generally, I don't like to subclass adapters, because the event
handler method usually requires access to a components fields, which
makes things messy if the listener is a separate class. It is much
easier to let a component implement the listener(s) of choice, leaving
the unused handler methods empty.

You'll probably draw some flames from OO purists on this one. :)

What I do not like about that is that you litter your components with a
bunch of publicly available listener methods that do nothing and/or
should not be invoked by clients.

The typical solution to this is to use an inner class (anonymous or not)
to implement the listener. The inner class has access to members of the
containing class. Now you are free to have the inner class extend the
adapter or not, as you wish.

These are all just style issues, although having extra public methods in
the class potentially goes beyond that and may be the source of future bugs.
Anyway, it was pointed out that a reason to use adapters is that you
are more safe when the listener changes, that is, if another method is
added to the listener in a later version of the VM. Then the
corresponding adapter would of course have the method added, securing
that your application can still run under the new VM.

On first view, this seems to be a good argument, but after thinking a
bit about it, I wonder if that is really a risk? Has Sun actually ever
done that? I mean, putting new methods in an already published
interface seems to be risky, not only if Sun does it, but also if it
happens in a developer team. I would prefer to make a new interface,
which extends the old one and adds new methods.

I don't have an example involving GUI listeners, but Sun has added
methods to the JDBC interfaces on a regular basis. Interestingly, there
are no adapter classes for these interfaces.

HTH,
Ray
 
P

Patricia Shanahan

Chris said:
Generally, I don't like to subclass adapters, because the event
handler method usually requires access to a components fields, which
makes things messy if the listener is a separate class. It is much
easier to let a component implement the listener(s) of choice, leaving
the unused handler methods empty.

Why not make the Listener extend the adapter and be an inner class of
the Component?

Extending the adapter avoids cluttering the component code with
implementations of methods that are not needed, because the adapter
tidily supplies empty bodies for them. On the other hand, an inner class
object has access to all the fields and methods of its surrounding
object. The Listener methods the component does need are nested in the
Component class' body.

This seems to me to be the best of both worlds.

Patricia
 
C

Chris Uppal

Raymond said:
I don't have an example involving GUI listeners, but Sun has added
methods to the JDBC interfaces on a regular basis. Interestingly, there
are no adapter classes for these interfaces.

There's a big difference between interfaces that client code is expected to
/implement/ and interfaces that client code is expected to /use/.

Changing the former is a nuisance (at minimum) for everyone, and is therefore
unacceptable. Changing the latter is a nuisance only for providers of the
service in question, and is not even all that big a nuisance for them (since
they'd be updating the code anyway, whether they were "forced" to do so by the
change to the interface definition or not).

In a similar vein there is no (or very, very, little) point in providing blank
"adaptors" for interfaces defining services that will be provided /to/ client
code. But there's a hell of a lot of point in doing so for interfaces that
must be implemented /by/ client code.

It's perfectly OK to change (extend) a contract that defines the service that
you will provide to someone else. It is never OK (unless all parties have
agreed in advance) to change (extend) the definition of what you require from
them. (If you replace "extend" by "reduce" in the previous sentence then the
OK-ness reverses also.)

-- chris
 
R

Raymond DeCampo

Chris said:
Raymond DeCampo wrote:




There's a big difference between interfaces that client code is expected to
/implement/ and interfaces that client code is expected to /use/.

Just because you never implement a particular interface in your code
doesn't mean that nobody does. Your so-called client code cannot /use/
the interfaces unless somebody /implements/ them.

Changing the former is a nuisance (at minimum) for everyone, and is therefore
unacceptable. Changing the latter is a nuisance only for providers of the
service in question, and is not even all that big a nuisance for them (since
they'd be updating the code anyway, whether they were "forced" to do so by the
change to the interface definition or not).

Why would a JDBC driver supplier be forced to update their code when a
new Java version comes out if there are no changes to the interface?
That is not a valid assumption.
In a similar vein there is no (or very, very, little) point in providing blank
"adaptors" for interfaces defining services that will be provided /to/ client
code. But there's a hell of a lot of point in doing so for interfaces that
must be implemented /by/ client code.

Again, I do not know what you mean by "client code".
It's perfectly OK to change (extend) a contract that defines the service that
you will provide to someone else. It is never OK (unless all parties have
agreed in advance) to change (extend) the definition of what you require from
them. (If you replace "extend" by "reduce" in the previous sentence then the
OK-ness reverses also.)

Perhaps you are under the illusion that Sun writes every JDBC driver in
the universe? When Sun adds to the JDBC interfaces, that forces third
party JDBC suppliers to change their code or it will be broken.

FWIW, I have implementations of the JDBC interfaces in my company's
repository that we use as a wrapper around vendor-supplied JDBC
interfaces. These are not a library that we provide to anybody, but an
intervening layer that we have found convenient to have. (E.g., we have
a number of work-arounds for various JDBC drivers implemented so that
the main code can operate without knowledge of specific drivers.) When
we moved from 1.3 to 1.4, we had to fix these implementations because
they would not compile.

The OP asked for an example of interfaces being expanded by Sun, and I
have supplied one. I have not made a value judgment as to the amount of
risk involved in not using the adapter classes typically provided for
the GUI listeners. If you choose not to use them, there is nothing
wrong with that. You are accepting the risk that the interface will be
expanded in the future. The risk is not high and the cost of being
wrong is not high, so it is not worth getting worked up about.

Ray
 
M

Monique Y. Mudama

Anyway, it was pointed out that a reason to use adapters is that you
are more safe when the listener changes, that is, if another method
is added to the listener in a later version of the VM. Then the
corresponding adapter would of course have the method added,
securing that your application can still run under the new VM.

On first view, this seems to be a good argument, but after thinking
a bit about it, I wonder if that is really a risk? Has Sun actually
ever done that? I mean, putting new methods in an already published
interface seems to be risky, not only if Sun does it, but also if it
happens in a developer team. I would prefer to make a new interface,
which extends the old one and adds new methods.

I don't know, but my concern would be that, if my code doesn't break
with a new API, I might not notice and test for the changes, which
could lead to highly undesirable results. Depending on the ease of
deployment, your security concerns, the criticality of your app, and
maybe the phase of the moon, it might be better for the app to break
noisly when the API changes than to silently change/add behavior.
 
C

Chris Berg

Why not make the Listener extend the adapter and be an inner class of
the Component?

True. I have a hidden agenda, though: Frequently, we are writing
Applets for use in web pages, and there is an incentive to make the
code as small as possible to save on download time. Every extra class
(including inner ones) adds extra kBytes to the jar file. Making the
Component implement the listener saves on the total number of classes.
But I know this is a very special case, that cannot (and should not)
be used in the general argumentation about this subject.

But I have another situation: We submit a large java application,
where our customers must glue it to a database by writing a few
classes themselves. In previous versions, we published the
superclasses that these classes should subclass, but we have switched
to publishing some interfaces instead. The user now must write a bit
more code as no code comes with the interfaces, but we also publish a
static class with some static helper methods that ease the task. The
benefit is, of course, that we don't reveal anything about HOW the app
does things, only WHAT it does. Interestingly, during the class - to -
interface transition we recognised some weaknesses in our design that
was related to inconsistent design, anw which had tro be fixed in
order to make the interfaces work, so our oo design became much
cleaner. The inconsistencies were actually related to the fact that we
used 'Extreme Programming' during the development, which we have
otherwise found beneficial because it has reduced the development
time. But that is a whole different issue. (sorry for bringing it up).

Chris
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,767
Messages
2,569,572
Members
45,045
Latest member
DRCM

Latest Threads

Top