Dynamic Web Development with Seaside

12.7Component Coupling

Here is an interesting question that often comes up when writing components, and one which we faced when embedding our components: “How do the components communicate with each other in a way that doesn’t bind them together explicitly?” That is, how does a child component send a message to its parent component without explicitly knowing who the parent is? Designing a component to refer to its parent (as we did) is not always an ideal solution, since the interfaces of different parents may be different, and this would prevent the component from being reused in different contexts.

Another approach is to adopt a solution based on explicit dependencies, also called the change/update mechanism. Since the early days of Smalltalk, it has provided a built-in dependency mechanism based on a change/update protocol—this mechanism is the foundation of the MVC framework itself. A component registers its interest in some event and that event triggers a notification.

Announcements. Perhaps the most flexible and powerful approach is to use a more recent framework called Announcement. While the original dependency framework relied on symbols for the event registration and notification, Announcement promotes an object-oriented solution; i.e. events are standard objects. Originally developed by Vassili Bykov, this framework has been ported to several Smalltalk implementations, and is popular with Seaside developers.

The main idea behind the framework is to set up common announcers and to let clients register to send or receive notifications of events. An event is an object representing an occurrence of a specific event. It is the place to define all the information related to the event occurrence. An announcer is responsible for registering interested clients and announcing events. In the context of Seaside, we can define an announcer in a session. For more information on sessions see Chapter 18.

An Example. Here is an example taken from Ramon Leon’s very good Smalltalk blog (at http://onsmalltalk.com/). This example shows how we can use announcements to manage the communication between a parent component and its children as for example in the context of a menu and its menu items.

First we add a reference to a new Announcer to our session:

MySession>>announcer
^ announcer ifNil: [ announcer := Announcer new ]

Second a subclass of an Announcement is created for each event of interest, here child removal:

Announcement subclass: #RemoveChild
instanceVariableNames: 'child'
classVariableNames: ''
poolDictionaries: ''
category: 'iAddress'

Each subclass can have additional instance variables and accessors added to hold any extra information about the specific announcement such as a context, the objects involved etc. This is why announcement objects are both more powerful and simpler than using symbols.

RemoveChild class>>child: aChild
^ self new
child: aChild;
yourself
RemoveChild>>child: anChild
child := anChild
RemoveChild>>child
^ child

Any component interested in this announcement registers its interest by sending the announcer the message on: anAnnouncementClass do: aBlock or on: anAnnouncementClass send: aSelector to: anObject. You can also ask an announcer to unsubcribe: an object.

The messages on:do: and on:send:to: are strictly equivalent to the messages subscribe: anAnnouncementClass do: aValuable (an object understanding value) and subscribe: anAnnouncementClass send: aSelector to: anObject.

In the following example, when a parent component is created, it expresses interest in the RemoveChild event and specifies the action that it will perform when such an event happens.

Parent>>initialize
super initialize.
self session announcer on: RemoveChild do: [:it | self removeChild: it child]
Parent>>removeChild: aChild
self children remove: aChild

And any component that wants to fire this event simply announces it by sending in an instance of that custom announcement object:

Child>>removeMe
self session announcer announce: (RemoveChild child: self)

Note that depending on where you place the announcer, you can even have different sessions sending events to each other, or different applications.

Pros and cons. Announcements are not always the best way to establish communication between components and you have to decide the exact design you want. On one hand, announcements let you create loosely coupled components and thus maximize reusability. On the other hand, they introduce additional complexity when you may be able solve your communication problem with a simple message send.

Copyright © 19 March 2024 Stéphane Ducasse, Lukas Renggli, C. David Shaffer, Rick Zaccone
This book is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 license.

This book is published using Seaside, Magritte and the Pier book publishing engine.