2.4.1 Qualified Notification

Motivation

The most basic form of Model notification is unqualified: Views are just informed that a change occurred in the Model state. In response, Views retrieve the new Model state and repaint themselves accordingly. This approach is simple but coarse. Consider these scenarios:

  • A specific View is only interested in a subset of the Model. The Model changes, but not in the data relevant to the View. The View is forced to repaint even if none of the data it displays actually changed

  • A View has additional state which is destroyed by a full repaint. For example, a TreeView representing files in a directory keeps state for the opened/closed sub-branches. If a new file is added and the View is forced to rescan and repaint, the open/closed state is discarded. Knowing the nature of the change would help in handling this case.

  • A View takes a very long time to perform a repaint from the full Model’s content, but it can run faster if it can operate by knowing only the change.

A Qualified Notification addresses the above cases by enhancing the notification system with a more fine-grained protocol carrying information about what has changed in the Model.

Design

Qualified Notification can be implemented by passing arguments to the Views’ notify() method. When the Model changes and calls this method on the subscribed Views, it passes information about

  • The subject of the change (e.g., which Model property has changed)
  • The nature of the change (e.g., the previous and new values)

The following example implementation trivially satisfies the above design

class View(object):
    def notify(self, name, old_value, new_value):
        # ...

Unfortunately, this solution does not allow to notify about more than one property change at a time. Additionally, it does not support multiple Models notifying the same View, as the View would not be able to differentiate which Model is reporting the change.

A more flexible approach is given by the following implementation

class View(object):
    def notify(self, change_info):
        # ...

where change_info is a dictionary or other data object describing the change in enhanced detail. Models are responsible for creating and populating this data object so that is meaningful to the receiving View.