Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

should the Observer Pattern include some infinite loop detection?

Quickly going through the GoF and the Head First Design Patterns book, it seems like there is no mentioning of infinite loop detection and handling for the Observer pattern?

I think if it is between 2 classes, we can be more careful about the infinite loop problem, but what if there are 5 classes or 12 classes, and the observers go multi-directions. In this case, won't an infinite loop be possible and some detection should be added to this pattern?

like image 681
nonopolarity Avatar asked Dec 03 '22 08:12

nonopolarity


2 Answers

Infinite loops can only happen if (a) Observers are also Observable, (b) changes they observe can lead to changes in themselves, (c) the graph of observation is cyclic and (d) there is a kind of change which can end up triggering a change of the same kind. The ideal solution would be to design out the risk of infinite loops by ensuring one of those requirements is absent. If your current design makes all four true, see if you can change it to make one of them false.

The traditional uses for Observer-Observable are in layered architectures - for instance, where view-controllers observe model objects, or where event handlers observe GUI components - and here, the graph will not be cyclic, so there's no risk of infinite loop.

I should probably explain about point (d), about different kinds of changes. What i mean is that if you have a situation where, say, a UserInputEvent can trigger a ModelStateChangedEvent, and a ModelStateChangedEvent can trigger a WidgetUpdateEvent, which can't itself trigger anything, then even if the Observers form a cyclic graph, you can never get infinite loops, because there's only a finite number of stages in the sequence of events. Effectively, the events form an acyclic graph, even if the Observers don't. If, however, a ModelStateChangedEvent can trigger another ModelStateChangedEvent, then you have the risk of cycles.

If you really can't avoid the risk of cycles, then you can steal an idea from Jon Postel, and make every event notification carry an integer time-to-live counter. When an Observable broadcasts an 'original' event, meaning something that comes in from outside the network of Observers and kicks off a cascade of events inside it, it sets the counter to some suitable initial TTL value. When an Observable responds to an event by broadcasting another event, it would use a TTL one less than that of the triggering event. When an Observer gets a notification with a TTL of zero, it ignores it. This would prevent infinite loops, but would also prevent an Observer responding 'correctly' to some events, so it's an idea to be used with caution. I would strongly suggest that an event cascade hitting the TTL limit should be considered the result of a programming error, and should be logged and reported in the same way as you'd handle something like a NullPointerException or an assertion failure.

like image 178
Tom Anderson Avatar answered Dec 24 '22 20:12

Tom Anderson


Infinite loop handling could be part of the actual implementation of the pattern, but the description of the pattern itself should be general and not be concerned with these details.

like image 40
eljenso Avatar answered Dec 24 '22 22:12

eljenso