    <rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:admin="http://webns.net/mvcb/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:content="http://purl.org/rss/1.0/modules/content/">
     <channel>
        <title>ACCU  :: An Eventful Story</title>
        <link>https://members.accu.org/index.php/journals/543</link>
        <description>Professionalism in Programming</description>
        <dc:language>en-us</dc:language> 
        <dc:creator>Administrator</dc:creator> 
        <admin:generatorAgent rdf:resource="http://www.xaraya.org" /> 
        <admin:errorReportsTo rdf:resource="mailto:webeditor@accu.org" />
       <sy:updatePeriod>hourly</sy:updatePeriod>
       <sy:updateFrequency>1</sy:updateFrequency>
       <docs>http://backend.userland.com/rss</docs>


        <h2>Journal Articles</h2>


<div class="xar-mod-head"><span class="xar-mod-title">Overload Journal #30 - Feb 1999 + Programming Topics</span></div>

<table border="0" cellpadding="1" cellspacing="0">
    <tbody>
    <tr>
        <td valign="top">
            Browse in :
       </td>
       <td valign="top">

                                            <a href="https://members.accu.org/index.php/journals/">All</a>

                     &gt;                         <a href="https://members.accu.org/index.php/journals/c76/">Journals</a>

                     &gt;                         <a href="https://members.accu.org/index.php/journals/c78/">Overload</a>

                     &gt;                         <a href="https://members.accu.org/index.php/journals/c174/">30</a>
                    (11)
<br />

                                            <a href="https://members.accu.org/index.php/journals/">All</a>

                     &gt;                         <a href="https://members.accu.org/index.php/journals/c13/">Topics</a>

                     &gt;                         <a href="https://members.accu.org/index.php/journals/c65/">Programming</a>
                    (877)
<br />

                                            <a href="https://members.accu.org/index.php/journals/c174-65/">Any of these categories</a>

                    -                        <a href="https://members.accu.org/index.php/journals/c174+65/">All of these categories</a>
<br />
</td>
   </tr>
   </tbody>
</table>




<div class="xar-error">
   <p>
 <strong>Note:</strong> when you create a new publication type,
the articles module will automatically use the templates
<em>user-display-[publicationtype].xt</em>
and <em>user-summary-[publicationtype].xt</em>.
If those templates do not exist when you try to preview or display a new article,
you'll get this warning :-)  Please place your own templates in themes/<em>yourtheme</em>/modules/articles . The templates will get the extension .xt there. </p>
</div>
<div class="xar-norm xar-standard-box-padding">
   <h1><strong>Title:</strong>&nbsp;An Eventful Story</h1>
<p><strong>Author:</strong>&nbsp;</p>
<p>
<strong>Date:</strong> 26 February 1999 16:50:51 +00:00 or Fri, 26 February 1999 16:50:51 +00:00</p>
<p><strong>Summary:</strong>&nbsp;</p>
<p><strong>Body:</strong>&nbsp;<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e18" id="d0e18"></a></h2>
</div>
<p>In my previous article, I talked about 'events'. These are an
intrinsic part of Delphi but the idea is equally valid in C++,
though not as widely used. I'd like to tell the story of one use
that I put this idea to in a project that I'm working on. The
problems are common to many projects and this is only one approach
from a choice of many.</p>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e22" id="d0e22"></a>Background</h2>
</div>
<p>The project is based around a number of medium sized databases
and consists of a main application plus a number of utilities. The
main application is a conventional MDI application, where the
documents don't actually correspond to files but instead are
queries stored in a separate database. The queries are of a number
of types, as are the data views. For reasons that I won't go into,
the queries, query editors and data views are managed by a
specially written singleton object that's independent of the user
interface. A lot of information about the available queries is also
cached in another cluster of objects that is independent of the
aforementioned manager class.</p>
<p>All of these objects work in conjunction with the main
application window that has the toolbars, menus etc.</p>
<div class="c2"><img src="/var/uploads/journals/resources/Fagg%20eventful%20story.png"
align="middle"></div>
<p>This is a simplified part of the application's architecture.
Associations drawn with a dashed line are application specific,
solid lines are more fundamental. However, the solid lines are
important only in one direction, e.g. a view must have a query but
a query doesn't need to know about views.</p>
<p>Perhaps surprisingly, co-ordination of these parts of the
application has taken a lot of time to get right, despite the
framework given by the VCL (Delphi's framework).</p>
<p>My problem is that I needed to eliminate the dependencies that
these objects had on each other. This was because I wanted to reuse
some objects in contexts other than the main application.
Specifically, I needed these objects in some of the utilities as
well as some as yet unspecified applications.</p>
<p>For example, when a view window is closed, both the query
manager and the main frame window need to be told. Likewise, when a
query name is changed, just about every object needs to be
told.</p>
<p>My original design allowed for these things to happen because
there were associations between these objects. If it weren't for
these co-ordination issues, these associations wouldn't have been
needed.</p>
<p>By the time that the first version was delivered, these
dependencies were beginning to become apparent. For the next
version, I wanted to open the door to alternative contexts and to
extend the degree of co-ordination between these and other
objects.</p>
<p>An additional change that was made related to a deficiency in
the early version of Delphi that was used originally. It wasn't
possible to use inheritance on the windows, so that for example, an
MDI child view couldn't have a common base class. This had led to
unnecessary code duplication, mostly the co-ordination code in
question! I only mention this as it meant that there was a good
incentive to rewrite these aspects on two fronts.</p>
<p>So let's look at some of the alternatives that offered
themselves.</p>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e46" id="d0e46"></a>Window
Messages</h2>
</div>
<p>This was an option that was already in use. When a query name
changed, a message was posted to all interested windows with a
pointer to the relevant object in the 'lparam'. The problem is to
decide what windows need to be told. The query manager having a
list of interested views and editors for each query object solved
this originally. It additionally needed to tell the main window,
which is a dependency that can be worked around by simply knowing
that the main window is a window. That is, it doesn't need to know
anything else about the main window. On the down side, I would
prefer it if the manager didn't need to know that there was a main
window, or that there was only one of them!</p>
<p>Unfortunately, not all objects involved are actually windows, so
this can't be used as a general solution.</p>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e53" id=
"d0e53"></a>Broadcasting</h2>
</div>
<p>An approach that we came up with was to make each object that
needed to tell other objects anything a 'broadcaster'. Objects that
needed to listen to the broadcaster registered themselves with it
and received notifications whenever anything happened. The
signature of the listening method called contained a message type
parameter and a pointer, something like a window message. A
listener would then get a look at each message and act according to
the message type.</p>
<p>I wasn't comfortable with this approach for two reasons.
Firstly, I didn't like the idea of having a switch statement in the
listener method. This was too much like SDK Windows
programming!</p>
<p>Secondly, each listener instance had to be connected to the
broadcaster instances. This implied either that there would be
knowledge of the broadcasters in the listener code or that this
knowledge would have to be held in application specific code. This
latter approach was feasible and could be invoked by firing an 'add
listener' event for example. However, I felt that this was a clumsy
way of making these associations. To make things even worse, these
associations tended to 'compound up' so that you would need to
connect many listeners to many broadcasters.</p>
<p>So, if I didn't like it, why bother at all? The above idea works
by maintaining a list of events (i.e. listener object plus method).
This is a useful thing in its own right but it does highlight a
problem that is general for events. It is important that an event
isn't called when the object that's handling the event no longer
exists! For components whose lifetimes are coincident with their
form, as is the most common case in Delphi, this problem doesn't
arise.</p>
<p>By virtue of the listener maintaining a list of broadcasters it
is simple for the listener to remove its handler from the
broadcaster's event list in its destructor. Symmetrically, if a
broadcaster is destroyed, it can let the remaining listener
instances know.</p>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e66" id="d0e66"></a>Event List</h2>
</div>
<p>From the broadcaster design, I took the guts of the event list
and generalised it for any type of event. That is to say, you can
safely cast these events in Delphi as they all have the same
storage. In C++, you would want to use a template. This gave me
storage for the events and methods to add and remove an instance's
hander from the list. I specialised for both plain (no parameters)
and notification (one 'sender' parameter, widely used in the VCL)
events. These have methods called NotifyAll with parameters
matching their event type. These classes are potentially useful in
their own right:</p>
<pre class="programlisting">
EventList = class
public
  constructor Create; virtual;
  destructor Destroy; override;

  procedure
  StopNotifying( instance : Pointer );
end;

NotifyEventList = class(EventList)
public
  procedure
  PleaseNotify( event : TNotifyEvent );
  procedure 
  NotifyAll(sender : TObject );
end;
</pre>
<p>I've omitted the 'plain' version for simplicity. Note that I've
declared 'instance' as a plain pointer (equivalent to void *)
because Delphi allows events both on an instance and a class
basis!</p>
<p>The implementation is simple. A union of the event and the two
pointers that make up the event is used to store each event. The
StopNotifying method simply scans the list for the 'instance' part
of the event and 'removes it if found. Naturally, a class
implementing an event handler would need to call StopNotifying in
its destructor, passing 'this' as the instance ('self' in Delphi).
So long as this is done in the same class that created the event in
the first place, the handler's instance pointer should match, even
with multiple inheritance.</p>
<p>A first rather feeble go at the event class:</p>
<pre class="programlisting">
class NotifyEvent
{
public:
  virtual void DoEvent(void *pSender)= 0;
  virtual bool InstanceMatches(void *pHandler) = 0;
};

template &lt;class HandlerClass&gt;
class NotifyEventHandler : public NotifyEvent
{
private:
  typedef void (HandlerClass::* FnNotifyEvent)
                (void *pSender);
  HandlerClass *m_pHandler;
  FnNotifyEvent m_OnNotifyEvent;
public:
  NotifyEventHandler
    (HandlerClass *pHandler, FnNotifyEvent ne)
    : m_pHandler(pHandler), 
      m_OnNotifyEvent(ne) {}
  
  void DoEvent(void *pSender)
  {
    (m_pHandler-&gt;*m_OnNotifyEvent)(pSender);
  }
  bool InstanceMatches(void *pHandler)
  {
    return m_pHandler == pHandler;
  }
};
</pre>
<p>There are some problems that the transition to C++ has
highlighted!</p>
<p>Firstly, the TNotifyEvent signature in Delphi has a sender of
type TObject. This is more comfortable than you might expect
because all classes are derived from TObject and they have RTTI
regardless!</p>
<p>This could perhaps be dealt with by using a template, an
exercise for the reader.</p>
<p>The other problem lies in the InstanceMatches method. Again,
I've hacked it with a void pointer, whether this can be made to
work correctly I don't know.</p>
<p>When implementing a C++ version of NotifyEventList, you will
need to work with pointers to NotifyEvent instances.</p>
<p>StopNotifying will require InstanceMatches and NotifyAll
requires DoEvent.</p>
<p>In use, PleaseNotify will require a new instance of
NotifyEventHandler for the handler class.</p>
<p>So, if you think that this is worth pursuing, I'm afraid that
you'll have to do all the hard work.</p>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e97" id="d0e97"></a>Event
Broker</h2>
</div>
<p>This was my final solution. I called it an 'event broker' but
don't read anything into the name.</p>
<div class="sidebar">
<p>Subsequent to my first version of this article, I found that a
design very much like this is described by William Crowe (CUJ June
1998) and called a switchboard. Then I also discovered that a
similar switchboard class is available in at least one C++
framework. The implementation is very like what I describe below
but solves the lifetime problem more effectively using a more
appropriate design in the C++ context. I leave my original text
below as it illustrates the reality of human frailty in this kind
of work!</p>
</div>
<p>The event list on its own is useful but in the broadcaster
design, it would be accessible via the broadcaster instance,
something that the listener would ideally not need to know about. A
more interesting approach is to make the event list available as a
central resource. The event broker fits this purpose. Here is my
Delphi declaration:</p>
<pre class="programlisting">
TEventBroker = class
private
  m_EventLists : TMapStringToObject;

public
  constructor Create;
  destructor Destroy; override;

  function AddOrGet( const name : string; eventListClass : TTEventListClass ) : TEventList;

  procedure StopNotifying( instance : TObject );
  
  // may return nil.
  function EventList( const name : string ) : TEventList;
  
  // will create if not already present...
  function NotifyEventList( const name : string ) : TNotifyEventList;
  function SimpleEventList( const name : string ) : TSimpleEventList;
  function StringEventList( const name : string ) : TStringEventList;

  class function Instance : TEventBroker;
end;
</pre>
<p>This is designed to be a singleton, though it really doesn't
have to be. What the event broker does is to maintain a collection
of event lists, mapped by a string key. The choice of key type was
based on convenience, other possibilities exist.</p>
<p>Creation of new event lists is done using a class reference,
hence the virtual constructor in the EventList class.</p>
<p>In use, it is straightforward. To listen to particular events
use something like:</p>
<pre class="programlisting">
with TEventBroker.Instance do begin
  NotifyEventList('QryVwClose').
                  PleaseNotify(QryViewClosed);
  NotifyEventList('QryVwActivate').
                PleaseNotify(QryViewActivate)
end
</pre>
<p>To notify do:</p>
<pre class="programlisting">
TEventBroker.Instance.
  NotifyEventList('QryVwClose').
  NotifyAll(self) 
</pre>
<p>To stop listening to any events:</p>
<pre class="programlisting">
TEventBroker.Instance.StopNotifying(self) 
</pre>
<p>Arranging for the last call to occur in a base class's
destructor is not a problem in Delphi. Unfortunately, it may well
be a problem in C++. This depends very much on being able to get
the InstanceMatches method above to work correctly.</p>
<p>Perhaps the single broker managing all the different types of
event list is a mistake, using templates, you could simply have it
work with the correct type.</p>
<p>I'm leaving all of the above as an 'exercise for the reader'
simply because I don't have the time to take it any further in C++.
It may well be that significant changes will be needed.</p>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e131" id=
"d0e131"></a>So&hellip;</h2>
</div>
<p>The above design has eliminated many dependencies from my
original application design. The remaining dependencies are those
that come with knowledge of the 'sender' parameter. For example,
the above listeners might need to know about the query view that's
closing or activating. Abstraction can be achieved by conventional
means where this is needed, e.g. by using abstract base classes for
the sender objects.</p>
<p>As a footnote, one way of implementing these classes as
described would be to use COM. The pointer conversion problems
could be overcome by using the IUnknown interface, which will
always be the same for a given instance.</p>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e138" id="d0e138"></a>Back to
now</h2>
</div>
<p>Now I'm back in the present, knowing of the switchboard class!
As can be seen above, I've dug a hole for myself by trying to give
responsibility to stopping notifications to the handler class.
William Crowe's switchboard solution simply makes the
NotifyEventHandler instance responsible in its destructor. My
problem was that in my Delphi implementation, the event objects are
owned by the event list, whereas if they are simply part of the
handler class, their lifetimes are just right for the job.</p>
<p>This is another good example of different language semantics
forcing different approaches. Delphi doesn't handle lifetimes in
the same way as C++ (except when using COM interface pointers),
consequently, the event object is better owned by the event list.
The switchboard class doesn't tackle the difficulties of emulating
the 'sender' parameter; they remain a problem for now. I also note
that the switchboard class is designed to work only as a singleton,
which may also be an improvement.</p>
<p>I would be very interested to hear from anyone else who has any
ideas in this area.</p>
</div>
</p>
<p><strong>Notes:</strong>&nbsp;</p>
<p><em>More fields may be available via dynamicdata ..</em></p>
</div>
</channel>
</rss>
