Event-Driven Programming: Dispatcher and Handlers Pattern, Slides of Programming Languages

The concept of event-driven programming using the Dispatcher and Handlers pattern. It discusses how a transaction begins, the role of a dispatcher, and the handling of events. The document also covers the Headless Handlers Pattern and its implementation in Python. Additionally, it touches upon GUI programming and the challenges of handling events in this context.

Typology: Slides

2017/2018

Uploaded on 06/19/2022

rd-chhanel
rd-chhanel 🇳🇵

3.5

(6)

24 documents

1 / 59

Toggle sidebar

This page cannot be seen from the preview

Don't miss anything!

bg1
1
Event-Driven Programming:
Introduction, Tutorial, History
http://Tutorial_EventDrivenProgramming.sourceforge.net
Stephen Ferg ([email protected])
Version 0.2 – 2006-02-08
This work is licensed under a Creative Commons Attribution License
http://creativecommons.org/licenses/by/2.5/
The Creative Commons Attribution License gives you permission to do virtually anything you
want with this work, including copying it, distributing it, and making derived works (including
translations) based on it – as long as you give credit to the original author (Stephen Ferg).
In particular, I encourage teachers to make copies of all or parts of this document for their
students, and translators to translate this document into other languages. It is not necessary to
ask for permission.
-- Steve Ferg
pf3
pf4
pf5
pf8
pf9
pfa
pfd
pfe
pff
pf12
pf13
pf14
pf15
pf16
pf17
pf18
pf19
pf1a
pf1b
pf1c
pf1d
pf1e
pf1f
pf20
pf21
pf22
pf23
pf24
pf25
pf26
pf27
pf28
pf29
pf2a
pf2b
pf2c
pf2d
pf2e
pf2f
pf30
pf31
pf32
pf33
pf34
pf35
pf36
pf37
pf38
pf39
pf3a
pf3b

Partial preview of the text

Download Event-Driven Programming: Dispatcher and Handlers Pattern and more Slides Programming Languages in PDF only on Docsity!

Event-Driven Programming:

Introduction, Tutorial, History

http://Tutorial_EventDrivenProgramming.sourceforge.net

Stephen Ferg ([email protected])

Version 0.2 – 2006-02-

This work is licensed under a Creative Commons Attribution License http://creativecommons.org/licenses/by/2.5/

The Creative Commons Attribution License gives you permission to do virtually anything you want with this work, including copying it, distributing it, and making derived works (including translations) based on it – as long as you give credit to the original author (Stephen Ferg).

In particular, I encourage teachers to make copies of all or parts of this document for their students, and translators to translate this document into other languages. It is not necessary to ask for permission.

-- Steve Ferg

Revision History

(most recent first)

? version 1.0 released

? version 0.3 – Modified beta version

2006-02-08 version 0.2 – modified draft version

2006-01-10 version 0.1 – First draft

Acknowledgments

Thanks to my co-worker Jeff Davis, for scanning several of the diagrams.

Thanks to my co-worker Gary Ault, who reported a mistake in one of the state transition diagrams.

Introduction

It's not easy to learn event-driven programming. If you're trying to program your first GUI application, or trying to learn how to parse XML with a SAX parser, you've experienced the difficulties first-hand.

Most, if not all, GUI systems and toolkits are designed to be event driven, meaning that the main flow of your program is not sequential from beginning to end. If you've never done GUI programming, this is one of the trickiest paradigm shifts. — Robin Dunn, speaking on GUI programming at OSCON

Hollywood Principle: "Don't call us; we'll call you." ... You implement the interfaces, you get registered. You get called when the time is right. This requires a distinctly different way of thinking to that which is taught in introductory programming where the student dictates the flow of control. — Dafydd Rees, http://c2.com/cgi/wiki?HollywoodPrinciple

The problem isn't that the concepts are complicated or difficult – the basic ideas are really quite simple. The problem is that – as of January 2005 – no reasonably complete explanation of these concepts is available on the Web.

This paper is my attempt to change that. Like so many authors, I've written the paper that I wish I could have found when I needed it. I hope it will help you in your attempt to learn event-driven programming.

One effective way to explain a complex idea is to tell the story of its life. This kind of story begins with the initial appearance of a young, simple idea. As the story unfolds we watch the progress of the idea as it responds and adapts to changing circumstances, slowly growing in complexity. This kind of story is called a genetic explanation and it is what I try to do in the first part of this paper.

This story of the evolution of event-driven programming is told from the perspective of a business applications programmer who started programming in the late 1970's, worked mostly on IBM and Microsoft platforms, and most recently began working with Java and Python on Unix platforms. A professor of computer science – or someone who worked on IBM's CICS transaction processing monitor, or on the Mesa programming environment, or on the Andrew windowing system – would undoubtedly tell a different story, or at least tell it differently. So this is not the only way the story could be told; it is simply the story as I am able to tell it.

The code examples are mostly in pseudo-code and Python, with the occasional bit of Java. Python is such a straightforward language (it's been called "executable pseudocode") that you should be able to understand the Python examples even if you've never seen a line of Python before. For more information about Python, two good places to start are http://www.python.org/ and http://pythonology.org.

In The Beginning – Transaction Analysis

My tale begins in the late 1970's. In those days, the typical computer system was a batch processing system. Input data was typically a sequential file on tape. A program read data from the input file, processed it, and wrote the results out to another sequential file. That file, in turn, was processed by another program and written out to another file, which in turn was processed by another program, and so on. The standard model of a computer system was an assembly line. Raw materials come in one door; they are processed, processed, processed; and at the end of the processing, a finished product is pushed out another door.

This mental model underlay the "structured" systems development methods in the 1970's. The human father of the structured methods was Larry L. Constantine. Their corporate father was IBM's Systems Research Institute. The most successful advocate of structured methods was Edward Yourdon – so much so that the expressions "Yourdon" and "structured analysis and design method" became almost synonymous.

The origin of the term "structured" was a paper called "Structured Design" by Glenford J. Myers, Wayne P. Stevens, and Larry Constantine, that appeared in the IBM Systems Journal in 1974. In 1975, Glen Myers, one of Larry Constantine's students at IBM SRI, published Reliable Software Through Composite Design. Then in 1977 and 1978, almost simultaneously, several important books on the structured methods appeared – Structured Design by Ed Yourdon and Larry Constantine, Structured Analysis and System Specification Tom De Marco, Structured Systems Analysis by Chris Gane and Trish Sarson, and Structured Systems Development by Ken Orr. Perhaps the most influential of these books was Tom De Marco's Structured Analysis and System Specification, published through the Yourdon press.

Dataflow Diagrams

Structured analysis used dataflow diagrams (DFDs) to show the logical structure of a computer system. On a DFD, a record in a sequential file was conceptualized as a packet of data moving through a pipeline, or along a conveyor belt, called a dataflow. Packets passed through a sequence of workstations called processes where they were filtered, used, enhanced, or transformed, and then passed on to the next workstation. Here's an example of a dataflow diagram from page 316 of De Marco's Structured Analysis and System Specification.

Describing a system in this way was called transform analysis.

De Marco also briefly described a second kind of analysis called transaction analysis and provided this diagram.

He explained the differences between transform and transaction analysis this way [p. 315]:

Transform analysis applies to applications that are transforms — that is, applications that have clearly identified input streams, central processing, and output streams. A transform is represented in Data Flow Diagram terms by a linear network.

Transaction analysis applies to transaction centers, parts of the application characterized by sudden parallelism of data flow.

De Marco actually spent very little time discussing transaction analysis. But the topic received more attention in Ed Yourdon and Larry Constantine's book Structured Design. In Chapter 11, Yourdon and Constantine give credit for the first description of transaction analysis to one P. Vincent, in a paper called "The System Structure Design Method" published in the limited-edition Proceedings of the 1968 National Symposium on Modular Programming. Apparently Mr. Vincent and others at Bell Telephone of Canada had developed a methodology called SAPTAD; Yourdon and Constantine described transaction analysis as "a more flexible, more sophisticated updating of the SAPTAD technique."

Structure Charts

A dataflow diagram shows the logical functions that a system must perform, but it doesn't say anything about the design of the program that will perform those functions. In structured analysis and design, a different diagram called a structure chart was used to show program design. On structure charts, boxes represent modules (functions, or subroutines). The boxes are arranged hierarchically, with calling modules at the top and called modules beneath them.

Converting a transaction-processing dataflow diagram to a structure chart produced a structure diagram like this one (from Structured Design, p. 205).

In this diagram, the dotted arrow coming in from the top represents flow of control being passed to the transaction center. Transactions are obtained by the GETTRAN function. Once obtained, a transaction is analyzed to determine its type (its transaction code) and then passed up to the transaction center. From there, it is passed to the DISPATCH module which sends it to the module that handles transactions of that type.

The Handlers Design Pattern

If Yourdon and Constantine were writing today, they might very well call their notion of transaction analysis a design pattern. I will call it the Handlers pattern.

Here's a diagram of the Handlers pattern. The diagram follows the structure of Figure 11.1 – Yourdon and Constantine's original dataflow diagram for transaction analysis.

Handlers pattern

On the diagram you can see:

  • a stream of data items called events (Yourdon and Constantine's "transactions")
  • a dispatcher (Yourdon and Constantine's "transaction center")
  • a set of handlers.

The job of the dispatcher is to take each event that comes to it, analyze the event to determine its event type, and then send each event to a handler that can handle events of that type.

The dispatcher must process a stream of input events, so its logic must include an event loop so that it can get an event, dispatch it, and then loop back to obtain and process the next event in the input stream.

Some applications (for example, applications that control hardware) may treat the event stream as effectively infinite. But for most event-handling applications the event stream is finite, with an end indicated by some special event — an end-of-file marker, or a press of the ESCAPE key, or a left-click on a CLOSE button in a GUI. In those applications, the dispatcher logic must include a quit capability to break out of the event loop when the end-of-event-stream event is detected.

In some situations, the dispatcher may determine that it has no appropriate handler for the event. In those situations, it can either discard the event or raise (throw) an exception. GUI applications are typically interested in certain kinds of events (e.g. mouse button clicks) but uninterested in others (e.g. mouse movement events). So in GUI applications, events without handlers are typically discarded. For most other kinds of applications, an unrecognized event constitutes an error in the input stream and the appropriate action is to raise an exception.

The Extended Handlers Pattern

Another variant is the Extended Handlers pattern. In this variant, the pattern includes an events generator component that generates the stream of events that the dispatcher processes.

The Event Queue

In some cases, the dispatcher and its handlers may not be able to handle events as quickly as they arrive. In such cases, the solution is to buffer the input stream of events by introducing an event queue into the events stream, between the events generator and the dispatcher. Events are added to the end of the queue as fast as they arrive, and the dispatcher takes them off the front of the queue as fast as it is able.

GUI applications typically include an event queue. Significant events such as mouse clicks may require some time to be handled. While that is happening, other events such as mouse-movement events may accumulate in the buffer. When the dispatcher becomes free again, it can rapidly discard the ignorable mouse-movement events and quickly empty the event queue.

Some Examples of the Handlers Pattern

Now that I've described the Handlers pattern, I'd like to show you some examples of the pattern. These methods and technologies are probably familiar, but you may never have thought of them as examples of event-driven programming.

Objects

In the 1990's, object-oriented (OO) technology and methods gradually eclipsed the structured methods of the 1970s and 1980s. Software methodologists began experimenting with new diagramming notations to express object-oriented concepts. At that time, one of the popular diagramming notations (invented by Grady Booch?) was object diagrams. Here is an example of an object diagram.

Object diagram of a STACK object

In this object diagram, Stack is an object type (or class). Push, pop, and peek are its methods. To use the Stack class, you would create a stack object, and then use its methods to do things to it.

create a stack object by instantiating the Stack class

myStack = new Stack()

myStack.push("abc") myStack.push("xyz")

print myStack.pop() # prints "xyz" print myStack.peek() # prints "abc"

I like object diagrams because they clearly show objects as examples of the Headless Handlers pattern. An object diagram is basically the same as the Headless Handlers diagram, except that events arrive from the left rather than the top of the diagram. The Stack class, for example, is clearly a collection of event handlers (called methods in OO jargon) for handling push, pop, and peek events.

The lesson here is that if you're an object-oriented programmer you already know event-driven programming. When you write object methods, you are — quite literally — writing event handlers.

Stack push

p o p

peek

internal data

This diagram (from page 55 of Essential Systems Analysis) shows the essential parts of a computer system, as they were conceptualized in ESA.

Basically, ESA views a computer system as a single, huge OO-style object. The system's essential activities are its methods, and its essential memory is its internal data. And just as an object is an example of the Headless Handlers pattern, with the methods playing the role of handlers, so here an entire computer system is an example of the Headless Handlers pattern, with the essential activities playing the role of handlers.

The most fully worked-out conceptualization of a system on the Handlers pattern was JSD (Jackson System Development), described in Michael Jackson's book System Development (1983). JSD was a brilliant method, and arguably the first true object-oriented analysis and design method.

The design of a JSD system is shown in an SID (system implementation diagram). Here is a typical SID, from p. 293 of System Development.

At the top of this diagram, we see the dispatcher — in JSD it is called the scheduler. A stream of events arrives from outside the system; it is labeled SCIN ("scheduler input"). Events are dispatched to CUST-1 or ENQ, the event handlers. The system's internal data is stored in database tables called "state vector" files (labeled SVFILE). EREPLIES is a stream of replies produced in response to operator enquiry events.

CUST-1 and ENQ are not functions; they are full-fledged OO-style objects. This means that JSD uses the Handlers pattern on two levels. On the upper level, the entire system is conceived on the full Handlers pattern, with the scheduler as the dispatcher and objects as event handlers. On the secondary level are OO-style objects, whose methods function as event handlers for events arriving from the scheduler or from other objects.

ESA and JSD mark a huge shift in thinking from the earlier structured methods. The cause of the shift was the rapid advances that were being made in database technology. In the early days of structured analysis, database management systems (DBMSs) were essentially non-existent. But by the time ESA and JSD appeared, computerized data processing was quickly moving away from batch systems processing sequential files to online systems processing databases. At first there were linked-list DBMSs (e.g. IBM's IMS, Cullinane's Cullinet, and Cincom's Total). These were quickly followed by inverted-list DBMSs (Adabas, Model204), then by relational DBMSs (DB2,

Here is the situation, described in terms of the Handlers pattern.

Each bank customer represents a service request (event, transaction) sent by a client. The customers queue up and wait for service. The tireless teller is a good analogy for a server which, because of its collection of event handlers, can handle different kinds of service requests. And the bank teller's "infinite loop" is of course the dispatcher's event loop.

Messaging Systems

Messaging systems represent an extreme version of the Handlers pattern. The purpose of a messaging system is to get events (messages) from event generators (senders) to handlers (receivers) in situations where the senders and receivers are in different physical locations or running on different platforms.

In messaging systems, messages are typically addressed to specific receivers, so the dispatching function (which determines which receiver should receive the message) is trivially simple. A familiar example of a messaging system is the post office. A sender gives a message (a letter or a parcel) to the post-office (the messaging system). The post office reads the receiver's address on the message and transports the message to the receiver.

server

events

dispatcher

handler 1 handler 2 handlern

client

client client

"event queue" containing service requests

Messaging System receiver

receiver

receiver

sender

sender

sender

dispatcher

E-mail messaging systems perform essentially the same function as the post office; the only difference is that the messages are encoded electronically rather than physically.

Perhaps the most sophisticated kinds of messaging systems are enterprise messaging systems, which use message-oriented middleware or MOM. In MOM systems, the senders and receivers are computer applications, rather than human beings. MOM systems enable computerized applications that are physically separated, or running on different hardware/software platforms, to communicate with each other. For example, a big company may have offices and servers that are geographically dispersed. MOM software could allow an order placed with the company's order-entry system in LA to be electronically sent to an order-fulfillment application hosted on a server in Chicago, and to a management-reporting application hosted on a server in New York, all without human intervention.

In addition to this point-to-point model of communications, MOM products also support a publish/subscribe model. In a publish/subscribe model, receivers become subscribers by subscribing to topics, and senders may send messages to topics (rather than to individual subscribers). When a topic receives a message, the topic forwards the message to all receivers who have subscribed to the topic.

Messaging System subscriber

subscriber

subscriber

sender

sender

sender

topic

topic

dispatcher

In MOM systems, telecommunications issues (and queuing issues, and implementation issues of the publish/subscribe model) dwarf the Handlers aspect of the system. Nevertheless, for some purposes it may be helpful to think of MOM systems as simply extreme, specialized examples of the Handlers pattern.