Re: Observer pattern limitations
- From: "David Barrett-Lennard" <davidbl@xxxxxxxxxxxx>
- Date: 10 Jul 2006 07:24:12 -0700
Dmitry A. Kazakov wrote:
On 10 Jul 2006 02:31:26 -0700, David Barrett-Lennard wrote:
PROBLEM 1: Infinite recursion in notifications.
Use asynchronous notification services. Design notifications as independent
types (objects), you might wish to split "data change" and "visual
appearance change" events. Notifications need not to be hard callbacks. It
is the simplest possible mechanism, but it is not the only one.
[ The problem is known in middleware systems. You cannot mix notification
upon each change by each subscriber with an ability to make changes upon a
notification. The result is either deadlock or loss of a notification. ]
Yes, agreed. I have used this approach myself.
A simpler approach (which is also asynchronous) is for notification
handlers to simply mark their caches as dirty. The cache is
automatically recalculated when it is next requested.
PROBLEM 2: Dirty reads.
Use protected objects. Behavior should be encapsulated in a protected
action on it. Note that "read" is not yet a behavior, it is a low-level
operation. Low-level tend to be dirty.
No amount of encapsulation will help. If an object privately caches a
value and doesn't know that it is dirty then it will supply clients
with incorrect results in its public API.
As it turns out there is an easy way to avoid dirty reads: simply
recalculate caches asynchronously. However, the downside is the
dirtiness has to propagate eagerly through the dependency graph, even
though an output of a calculation may not have changed despite changes
to the inputs.
PROBLEM 3: Observer attaches or detaches during a notification
It is racing condition, when allowed to happen asynchronously.
No I'm talking about a single thread that is in the process of
iterating through the observers of a subject in order to notify them,
and an observer decides that it wants to synchronously detach (say).
The problem doesn't exist if the detach is performed asynchronously.
The problem is that while a subject is notifying one of the observers,
an observer decides to attach or detach to/from the subject. This may
cause a crash depending on the data structure used by the subject to
store the observers.
This is not a problem, it is a bug. List and its iterators are objects. So
it is legal to modify the list while iterating it.
Double linked lists (std::list) will work, std::vector or std::deque
will not.
The very idea to change the list of observers while notifying them is
horrible to me. For example, does it matter whether the new observers
being attached also receive the notification?
One hack I've seen to solve this problem is to use a "one shot
observer". Another is to make a copy of the list of observers before
issuing the notifications.
There are many solutions. For example, observers can be limited to wait for
exactly one event at a time.
All are horrible hacks in my opinion :)
PROBLEM 4: Memory management problems
There seems to only be one general solution (that I can think of). A
subject needs to hold strong references on its observers.
Well, usually it is a weak reference observer->subject. Clearly each weak
reference is a strong one in the backward direction. But implementations
don't care about it, because finalization of an observer finalizes the
reference with it. So there is nothing to care about.
Your typical C++ implementation of the observer pattern won't be able
to solve the memory management problem in the example I gave.
It's not much good if a third party toolkit makes it nearly impossible
to avoid memory leaks.
PROBLEM 5: Nested contract attachments
Huh, a container of observers is itself an observer. Or dually, a set of
events is an event.
I have no idea how that relates to the problem.
SO WHAT'S THE SOLUTION? : I have only found one general solution
to these problems. Basically it is to throw away the observer pattern
(unless you're doing a trivial problem that (provably) doesn't
suffer from these issues), and instead use a more general
graph-theoretic approach, such as the theory of one way or multi way
constraints, or the spread *** algorithm etc.
... and it solves all problems? ...
I highly recommend you to publish *the* solution in a renown scientific
magazine, rather than wasting your time in an Internet newsgroup.
I don't have a solution that is fit for publishing - at least not yet.
A newsgroup is a good place to quickly get some opinions.
The existing literature on lazy evaluation, one-way constraints etc,
seem to more directly solve the problem of cache recalculation. The
observer pattern appears rather flawed for a general solution.
Cheers,
David Barrett-Lennard
.
- Follow-Ups:
- Re: Observer pattern limitations
- From: Dmitry A. Kazakov
- Re: Observer pattern limitations
- From: Leslie Sanford
- Re: Observer pattern limitations
- References:
- Observer pattern limitations
- From: David Barrett-Lennard
- Re: Observer pattern limitations
- From: Dmitry A. Kazakov
- Observer pattern limitations
- Prev by Date: Re: Writing programs with GUI
- Next by Date: CfP: OMG's Software Based Communications Workshop 2007
- Previous by thread: Re: Observer pattern limitations
- Next by thread: Re: Observer pattern limitations
- Index(es):