On 9 oct. 08, at 14:53, Asankha C. Perera wrote:
Andreas
Already some time ago I had the idea to refactor the existing
metrics collection code (used by the JMX support) in the transport
base package to use an observer pattern. More precisely the idea is
to allow to register any number of observers (or event listeners if
you prefer) with a transport listener or sender. These observers
would then be notified whenever something interesting happens in
the transport (message received, error, etc.). Basically the
refactoring would be achieved by extracting an interface from
MetricsCollector and change the 1:1 relationship between transport
and observer (metrics collector) into a 1:n relationship. The
existing MetricsCollector would then become one particular observer.
I'm primarily interested in this change because I'm facing a
particular problem in the transport unit tests: the test cases have
no way to detect a reception error in the transport, except for
waiting for the timeout. This could be solved using the observer
pattern described above. Probably this particular use case on its
own wouldn't justify the change, but there will probably be other
interesting use cases.
WDYT?
Although your suggestion seems to improve the existing code base at
first glance, I am not convinced that its a good thing to do for
something like metrics collection, which could literally get called
millions of times (e.g. counting the bytes sent/received etc).. and
going through a list of observers, when the list would contain one
element most of the time seems like its not worth it to me
The number of calls to the observers for a single message is O(1), so
the overhead seems to be quite negligible. What is of greater concern
is that if the pattern is not well implemented, it will clutter the
code with for loops. There is a design solution that addresses both
concerns: Keep the transport-observer relation 1:1 and provide a
particular observer implementation that dispatches to a list of
observers. As long as there is a single observer, it would be
registered directly with the transport, causing no overhead. Once a
second observer is added, a dispatcher would be created and registered
with the transport (and the original observer added to the
dispatcher). This also means that the code only ever calls a single
observer directly and that the uninteresting for loops are all
isolated in a single class.
Alternatively the scope could be reduced to error conditions: The
MetricsCollector would be unchanged and we would have a completely
separate concept of error listeners that can be registered with the
transport. Since they are only called when something goes wrong, we
don't care about a few microseconds lost in a for loop.
Andreas