Event Driven Programming

In general: programming where the primary activity is reaction to receipt of semantically significant signals (aka 'events'). The signals can be from any source, most commonly including sensors, human input (e.g. clicking on a button), timers, observation upon shared state, or produced during computation as a result of reacting to other signals. It should be noted that CommunicatingSequentialProcesses and ActorModel are pretty much founded in this form of computation (though they approach it from varying perspectives). It is relevant to note that there exists a potential for infinite recursive reactive events (at least in the general case) - thus, to implement EventDrivenProgramming in the general case, it is necessary to provide a message queue (or queues). Such a queue doesn't prevent the infinite recursion, but it does allow a guarantee that every event will be handled after some finite count of steps even if such loops exist. It is only this limitation that prevents most ObjectOriented systems from being readily transformed into EventDrivenProgramming systems.

Contrast with ProceduralProgramming (which merely acts, rather than reacts) and GoalBasedProgramming (StrongArtificialIntelligence or ControlTheory?, wherein the primary activity is planning and actuation towards a goal, and signals are only considered as sensory feedback to aide in future decisions). These (in conjunction with EventDrivenProgramming) constitute the three best-understood approaches towards describing behavior in any system. EventDrivenProgramming is quite useful when dealing with GUIs, HCI, and other object systems where one expects response to action as the primary activity. It is inappropriate for systems that must do one thing well and finish without intervention (like compilers... this sort of thing implies ProceduralProgramming). It is also inappropriate for systems that must react intelligently based upon total observed context of any sort (which implies GoalBasedProgramming and possibly a KalmanFilter or HiddenMarkovModel) - e.g. it's difficult to make EventDrivenProgramming work when there is no clear distinction between events, or when signals are temporally ambiguous (where a signal might mean one of many things based on what happens next or what happened previously). EventDrivenProgramming is for dumb reaction to obvious stimuli... not much more behavioral 'intelligence' than a Jellyfish.

EventDrivenProgramming may or may not be ObjectOriented or possess an ObjectModel or ObserverPattern. EventDrivenProgramming, for example, need not imply that the events are ever dispatched to method calls upon different objects after receipt, except insofar as they are dispatched somehow to the process that receives them in the first place. However, it is most common in ObjectOriented systems to see EventDrivenProgramming constructed as hooking directly into method calls upon particular objects, possibly with observers.

In an EverythingIsRelative viewpoint, EventDrivenProgramming can be viewed as the case where you as a developer cannot control or change the "caller", and thus have to focus on the callee routine(s) and related infrastructure and conventions.

See "Event-Driven Programming: Introduction, Tutorial, History" at http://eventdrivenpgm.sourceforge.net.

Notable examples:


EventDrivenProgramming can be implemented with so-called "procedural languages", so perhaps we need to be careful about making it appear as if they are mutually-exclusive. I suspect there is a better word for what you are trying to describe.

Language-wise, they really can't be mutually exclusive. You need to do something after receiving the event, and that something will invariably be procedural/imperative (even if said procedure just involves performing a few calculations then sending more messages or modifying some state). Trivially, a language that supported only EventDrivenProgramming could perform procedural programming by accepting exactly one event, that being: (main_event with (args)). Nonetheless, in practice, whether a particular program architecture can really be considered 'EventDrivenProgramming' doesn't often overlap with architectures that can reasonably be called 'ProceduralProgramming'... i.e. they do tend to be rather exclusive. This is true even when the programming language happens to be capable of both.

It's important to note that not all 'procedural languages' are capable of supporting EventDrivenProgramming. The ability to receive real events (as opposed to emulated events) is not implied even for a language that is TuringComplete. (TuringComplete only implies ability to perform any computable closed calculation, and says nothing of communication). EventDrivenProgramming fundamentally requires the ability to detect signals and trigger 'events' upon receiving them - e.g. via interrupts on a CPU, or continuous polling in a forever-loop. ProceduralProgramming does not require or imply the ability to react to events (even via queuing and polling for them). It is this distinction that most clearly denotes the 'conceptual' divide between EventDrivenProgramming and ProceduralProgramming.

EventDrivenProgramming does not imply concurrent programming. On the other hand, a single-threaded framework can simulate cooperative multitasking within an application, by putting anything that blocks execution on its own handler and requiring handlers to return control to the message loop regularly (as opposed to yielding control to another thread in multi-threaded programming).


please reconsider/refactor/redact from here down to use less negatives & prevarication.

Odd. I remember a topic on this somewhere. Anybody seen it? A search for "EventDriven" turned up nothing.

maybe you remember reading HollywoodPrinciple. As far as I can tell, they are the same.

{No, that does not sound like it. Plus, it implies that OOP is better at EventDrivenProgramming, which I disagree with, given the right languages and tools.}

BatchMode?: Originally, people had some big mathematical problem to solve, so they loaded the entire program into the ("mainframe") computer, let it chug for hours without any interaction. After the computer printed out "the answer", then the next "job" was run.

EventDrivenProgramming: In contrast, most people today use software that is far more interactive. They click on a button, or select something from a menu, or push a key (generating an "event"), then some little subroutine attached to that button or menu item or key gets called. Most of the time, the machine is in an IdleLoop? (OptimizingTheIdleLoop) waiting for the next event. In some languages like VisualBasic, there appears to be no "main" subroutine that calls all the other ones; all that appears in the code are subroutines attached to specific menu items or other events. When these subroutines "return", it's a mystery where the processor returns "to".

It returns to a hidden WinMain() function inside the VB runtime, doesn't it?

I think the biggest difference between EventDrivenProgramming and the "old way" is that a framework is in primary control of flow instead of your own program. Or at least you develop with that assumption. I don't know if having access to the "main loop" takes one out of the definition by itself. I see EventDrivenProgramming as a design technique/approach more than an access limitation. A "main" routine is perhaps one way to implement it, but not a defining characteristic, for the framework should mostly hide such issues.


Inter-event Communication

Obviously events should be able to read state and transform state. The form of this state can vary widely, however. Different approaches include global variables (shunned by many), "form" variables, a database, and special structures/objects created just for events. Sometimes returning "True" or "False" at the end of an event can indicate something to the framework, such as whether the event was successful. For example, an "onValidate" event may return True if validation was successful, or False if it was not. Another approach is to return an error message string. If the string is blank, then the framework assumes that validation was successful, otherwise display the string to notify user of errors and not proceed to the next step.

Most 'purists' would shun the use of return values from event processing. There is no clear semantic meaning for any such return value... nor a clear semantic as to whom you're returning the value. Purists would suggest you communicate a failure by creating another event carrying all the necessary information.

That kind of approach tends to create bloated interfaces in my experience. A return value or structure attribute may handle about 90% of error handling using a simple convention. The other 10% can still use a more "pure" approach just fine.

In my own experience, it seems 'bloated' only until you find out how much removing explicit 'simple convention' error handling (e.g. 'return 0 on success, -1 on failure') both simplifies the code AND removes hidden communications and synchronization costs (thus freeing the system for more distributed or concurrent operation). However, I also think it fair that we've had different experiences. Now, be honest with yourself: have you actually tried the 'purist' approach, or are you making a generalization based upon an assumption of the consequences?

The suggestion did not limit it to a single 1 or zero integer. In fact, that would be too limiting in my experience. If you have some specific "go bad" scenario you want to demonstrate, be my guest.

I also did not suggest that it be limited to a single boolean integer. "e.g." or exemplia gratia means exactly that - "good example", not "limit". I will suggest that having more complicated return values means needing more complicated (and 'bloated') error handling, potentially along with more expensive hidden communications costs (if the return value is considerably larger than an integer). Now, I said it's fair that we've had different experiences; I'm supposing your rather defensive response here was because you weren't being honest with yourself about having actually had said experience. However, since you asked so nicely, if you want a "'go bad' scenario" involving return-values in EventDrivenProgramming: try doing it on a distributed system overlaying DisruptionTolerantNetworks.

A return value from the event handler to the framework seems useful in a GUI framework. For the implementors of a framework, especially one implemented on an asynchronous system (concurrent/multi-threaded, networked, or systems with non-trivial communication costs), each event handler that returns a value requires additional programming effort.


I've seen EventDrivenDesign?. Basically, you enumerate all the events that could come into your system, and then what the responses to these events should be. Keep breaking the event-response pieces down (you might generate internal "events", to communicate between the pieces), until you know how to implement each piece.


Typical features of events in event-driven programming

Typical Inputs and Outputs of Events, using a GUI system as an example:

Typical Event Attributes (usually set during design time)


....As opposed to state-driven programming. Once described this way (CeeBias?):

"A state-driven program has an outer switch(on state), with inner switches(on event). An event-driven program has an outer switch(on event), with inner switches(on state)."

Another approach to event-driven programming, the classic state-transition table: for each state, a table indexed by event, containing next-state for each event.


For example, contrast to a polling loop that looks for keyboard or mouse input, decides which function to call.

An event model would simply "arrive" at the appropriate function (okay, method if you insist), and the receiving routine would do its bit in relative ignorance of other contexts.

The "polling" model has a definite, traceable flow, while the event model magically teleports to any random target code without benefit of a decision tree.

But this just reflects the unpredictable nature of human interaction.

Predictably, code that uses EventDrivenProgramming can be sticky to debug.

good. EDP makes ProgrammerTests easy, because the tests need only spoof messages and collect replies. This makes EventDrivenProgramming less likely to catch a bug, so its ability to submit to a BugEnhancer is irrelevant.

I think GUIs are sometimes sticky to debug because the framework often does not provide enough tracing tools or tracing access. It would be nice to have a log something like:

  13:42:17.35 - Mouse click at x437,y972
  ---- Events Triggered:
  --------- WindowFoo_onClick, priority 4
  --------- ButtonBar_onClick, priority 8
  ---- Events Executed:
  --------- ButtonBar_onClick, 13:42:18, return status: 1
  --------- WindowFoo_onClick, 13:42:22, return status: 1
  13:43:12.08 - Keypress, keycode: 37 "B"
  13:43:12.64 - Keypress, keycode: 52 "U"
     ....
(Dashes added to prevent TabMunging)


Magically arrives at the appropriate function? Doesn't event driven code have an infinite loop buried in it somewhere, say, down in the bowels of a foundation class, receiving system events and deciding what functions to call, what objects to send the events to?

Well, yes. In fact, all appearances to the contrary, all "event driven" environments are ultimately polled - even down to the hardware level - the CPU only "interrupts" after it's polled the interrupt request channels to see if someone wants its attention. Hiding this fact from the programmer creates an environment where the coder can say "magically do this when that happens" without worrying about how.

[Not so. At the software level, synchronous IO is most frequently used to wait on an event, in this day and age, and your description of the "hardware" is a misunderstanding of how the kernel, interrupt routines, and digital electronics function: there typically is no polling involved. An interrupt really, really, really is an interrupt in most designs today. There are exceptions, naturally, but not ones that prove your rule.]

[Perhaps you are thinking of how low-end systems functioned back in the bad old days. -- DougMerritt]

I don't see why it matters if the application developer does not need to know or care. That is more or less an implementation detail or decision. Whether it is polling plus NO-OPs, or interrupts should not change how it behaves. BTW, here is a typical polling wait loop:

  while (e = eventQueueCheck()) {
     if (e.hasEvent) {
       processEvent(e)
     } else {
       idleProcess()  // garbage collection, etc. or perhaps sleep(0.01) 
                      // or noop() or the like, depending on environment.
     }
  }


Example "Linda", demonstrating dual use (input and output) of array/structure.

 event click_button_foo(info[]) {
   if (info[x_rel_cordinate] > 55) {
     info['error_msg'] = 'You clicked the very edge of the button';
   } else {
     process_button...
   }
   return(info);  // perhaps unneeded if passed by reference
 }

// OO-style syntax event click_button_foo(info) { if (info.x_rel_cordinate > 55) { info.error_msg = 'You clicked the very edge of the button'; } else { process_button... } return(info); // perhaps unneeded if passed by reference }
Note that "rel_cordinate" stands for "relative coordinate", which is the coordinate relative to the target widget (button in this case). That way if the screen is rearranged, we less likely have to change the value. (Using coordinates is perhaps a risky approach anyhow because we may resize the button, but this is just an illustrative example, and sometimes there are no alternatives.)


I have tentatively decided that the best way to standardize the event interface is to pass in two by-reference associative arrays (or objects for OO fans):

  event foo_activity(eventStruct[], contextStruct[]) {
    ...
    if (someError) {
       eventStruct.errorMessage = "you can't click here after midnight."
    }
    ...
  }
The "event" structure parameter has standardized info for all events, while the "context" structure may be widget-specific or context specific. For example, it may contain column values if validating a record about to be submitted (when individual field validation is not sufficient, such as having at least one of two phone numbers, day and evening, required).

-- top

Your meaning here is quite unclear. What is 'standardized info' for even one event, much less all events? As far as finding the 'best way to standardize the event interface', I'd suggest looking towards the languages developed in conjunction with ActorModel and CSP.

See "Typical Inputs and Outputs of Events" above. Also, this suggestion is meant to be language-neutral. I don't wish to assume any one language. The techniques of EventDrivenProgramming can work just fine in most of the common production languages, and thus I don't see any need to create a new language or syntax at this point.

There is no such thing as 'language-neutral'. However, my suggestion to looking at the languages isn't for adoption or syntax... it's simply a very good place to look in order to learn what sort of things should be included or excluded from any 'standardized event interface'.

By "language neutral", I meant not hard-wiring the event system to some specific application programming language, such as Java, Ada, etc. Of course, language-specific adapters may be needed for each app language, but if possible, we don't want to marry a standard to a specific application language, which has been a big problem with many GUI kits.


Since when does OO have a monopoly on EventDrivenProgramming? In a good event framework, the application developer does not even "see" the event driver, and things like ObserverPattern are a hidden implementation detail (if used). There are multiple approaches to event dispatching, and ObserverPattern is just one, and perhaps not sufficient in some cases to deal with multiple event dispatching and priorities. Maybe we can reword the above to avoid getting into a ParadigmPissingMatch by removing or lowering paradigm-specific references.

The above verbiage now satisfies whoever wrote the above complaint, so I'm moving it below and out of the way. Presumably, this complaint referred to an earlier generation of the work. -- SamuelFalvo?

Perhaps we need a section about internal implementation mechanisms and how they relate (or don't relate) to the application developer's interface to the event engine.


We also need a section about the ways of documenting an EventDrivenProgramming framework. For example, when clicking a GUI button results in multiple events being dispatched, it is not clear in which order the events are being processed unless it is documented. My guess is that a good documentation will resemble the source code that is in the framework.

I vote for a table-driven approach (surprise) to prioritize, catalog, study, and perhaps log events and/or event priorities for any non-trivial system. I find source code is difficult to read and sift except for things best expressed as nested expressions. Then again, I agree that some have FastEyes with regard to source code and thus don't need the power and organization abilities of tables. -- top

Okay, I suppose it's time to lay down my argument about the separation of architecture, design, and implementation again...right? The architecture defines basic unit duties and competencies. Design specifies how these units are ordered and how they interface to each other. Implementation is...well, implementation. Code falls into the latter category, but GUI event handling falls under design, does it not?

{I do not believe there are clean distinctions between architecture, design, implementation, and maintenance. Software Engineering makes some rough distinctions between them, but design, architectural, implementation, and maintenance issues intermingle in practice (assuming, perhaps optimistically, that they don't become ExtremelyInterstrangled). TopMind describes design considerations, such as the ability "to prioritize, catalog, study, and log events and/or event priorities", and suggests that tables be an explicit part of the architecture. KayLanguage is right up that same alley, proving it can be done well. If there are costs to a shared table approach, they are likely in terms of security (who is authorized to see which events?) and cleanup (are events ever deleted? if so, by whom?). The security issues would prevent only the highest ('Internet') levels of scalability. Distributed performance might suffer a bit, but could be mitigated.}


Please note that we need some real distinction here between "event driven" in terms of something like a user interface, where an "event" is a mouse click, and a system- or hardware-level event, such as a signal or processor interrupt. In the case of application-type events the system is doing a bunch of polling, conditioning, and setup long before the "event" is passed on to the application. In the case of a processor interrupt the hardware causes the current thread of execution to cease before it swaps in the interrupt handler.

Concurrent execution, reentrancy, semaphores, system resources, and many other considerations play into the design of system event programming. When a hardware signal or interrupt causes one thread to be suspended and allows another to run then there exists possibilities for all kinds of baddies to occur; deadly embrace, resource starving, memory leaks, yada yada yada.

We need to separate out the discussion of application events from system events and address these as two distinct topics. Eh?

I'm not convinced the topics are orthogonal, nor that events should be distinguished based on some arbitrary concept of 'domain'. But you could break this page down into useful patterns and cautions for using events.


Sarcastically, someone defined EventDrivenProgramming as "when somebody or someone else besides you gets to control when you can process stuff".


See: IdleUpdates, WhatIsWrongWithTheGeneralVisualBasicApproach, TheGuiThreadIsTheMainThread

SeptemberZeroSeven

CategoryEvents


EditText of this page (last edited November 4, 2014) or FindPage with title or text search