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

Reply via email to