0% found this document useful (0 votes)
162 views40 pages

12 Event Driven Programming

Event-driven programming is a programming paradigm where the flow is determined by events such as user input or messages. There is usually a main event loop that listens for events and triggers callback functions when events are detected. Many applications use this paradigm, including GUIs, JavaScript apps, and games. In games, the main loop is called the game loop and typically involves updating the game state based on elapsed time, then drawing the new frame. User input can also trigger updates to the game state. The observer pattern, commonly used in event-driven programs, involves objects called subjects notifying observer objects of any state changes by calling their methods.

Uploaded by

yilvas
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
Download as pdf or txt
0% found this document useful (0 votes)
162 views40 pages

12 Event Driven Programming

Event-driven programming is a programming paradigm where the flow is determined by events such as user input or messages. There is usually a main event loop that listens for events and triggers callback functions when events are detected. Many applications use this paradigm, including GUIs, JavaScript apps, and games. In games, the main loop is called the game loop and typically involves updating the game state based on elapsed time, then drawing the new frame. User input can also trigger updates to the game state. The observer pattern, commonly used in event-driven programs, involves objects called subjects notifying observer objects of any state changes by calling their methods.

Uploaded by

yilvas
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
Download as pdf or txt
Download as pdf or txt
You are on page 1/ 40

Event-driven programming

Event-driven programming

Paul Alexander Bilokon, PhD

Thalesians Ltd
Level39, One Canada Square, Canary Wharf, London E14 5AB

2022.06.23
Event-driven programming

Event-driven programming

I Event-driven programming is a programming paradigm in which the flow of the


program is determined by events such as user actions (mouse clicks, key presses),
sensor outputs, or messages from other programs or threads.
I Event-driven programming is the dominant paradigm in graphical user
interfaces (GUIs) and other applications (e.g., JavaScript web applications) that are
centred on performing certain actions in response to user input. This is also true of
programming for device drivers.
I In an event-driven application, there is usually a main loop (event loop) that listens
for events and then triggers a callback function when one of those events is detected.
Event-driven programming

Dummy BitMEX feedhandler (i)

import logging
import sys
import websocket

try:
import thread
except ImportError :
import _thread as thread

def on_message (ws , message ):


print ( message )

def on_error (ws , error):


print (error)
sys.exit (1)

def on_open (ws):


print (’Opened WebSocket connection ’)

def on_close (ws):


print (’Closed WebSocket connection ’)
Event-driven programming

Dummy BitMEX feedhandler (ii)

if __name__ == " __main__ ":


print (’Opening WebSocket connection ’)
websocket . enableTrace (True)
ws = websocket . WebSocketApp ("wss :// www. bitmex .com/ realtime ? subscribe =instrument ,
,→ orderBook10 :XBTUSD ,trade: XBTUSD ",
on_message = on_message ,
on_error = on_error ,
on_close = on_close )
ws. on_open = on_open
ws. run_forever ()
Event-driven programming

Game loop
I Many other examples of event-driven programming occur in games.
I There is an interesting tutorial by Mark Brown, peer reviewed by Andrew Ray and
Sebastian Seitz, Quick Tip: How to Make a Game Loop in JavaScript (2016.08.03).
I In this context the main loop is called the game loop and usually takes the following
form:

function update ( progress ) {


// Update the state of the world for the elapsed time since last render
}

function draw () {
// Draw the state of the world
}

function loop( timestamp ) {


var progress = timestamp - lastRender

update ( progress )
draw ()

lastRender = timestamp
window . requestAnimationFrame (loop)
}

var lastRender = 0
window . requestAnimationFrame (loop)
Event-driven programming

Analysis

I The requestAnimationFrame method requests that the browser call a specified


function as soon as it can before the next repaint occurs.
I It’s an API specifically for rendering animations.
I You can also use setTimeout with a short timeout for a similar result.
I The requestAnimationFrame callback is passed a timestamp of when the callback
started firing, it contains the number of milliseconds since the window loaded and is
equal to performance.now().
I The progress value, or time between renders is crucial for creating smooth
animations. By using it to adjust the object positions in our update function, we ensure
that our animations move at a consistent speed.
Event-driven programming

A specific example

I Our first animation will be simple: a red square that moves to the right until it reaches
the edge of the canvas and loops back around to the start.
I We’ll need to store the square’s position and increment the x position in our update
function. When we hit a boundary we can subtract the canvas width to loop back
around.

var width = 800


var height = 200

var state = {
x: width / 2,
y: height / 2
}

function update ( progress ) {


state.x += progress

if (state.x > width) {


state.x -= width
}
}
Event-driven programming

Drawing the new frame

I We use the <canvas> element for rendering the graphics:

<canvas id=" canvas " width ="1496" height ="488" />

I The draw function simply renders the current state of the world. On each frame we’ll
clear the canvas and then draw a 10px red square with its centre at the position stored
in our state object:

var canvas = document . getElementById (" canvas ")


var width = canvas .width
var height = canvas . height
var ctx = canvas . getContext ("2d")
ctx. fillStyle = "red"

function draw () {
ctx. clearRect (0, 0, width , height )

ctx. fillRect (state.x - 5, state.y - 5, 10, 10)


}
Event-driven programming

Responding to user input (i)

I Next we’ll get keyboard input to control the position of our object, state.pressedKeys
will keep track of which keys are pressed.

var state = {
x: (width / 2),
y: ( height / 2),
pressedKeys : {
left: false ,
right: false ,
up: false ,
down: false
}
}

I Let’s listen to all keydown and keyup events and update state.pressedKeys
accordingly.
I The keys we’ll be using are D for right, A for left, W for up, and S for down.
Event-driven programming

Responding to user input (ii)

var keyMap = {
68: ’right ’,
65: ’left ’,
87: ’up ’,
83: ’down ’
}
function keydown (event) {
var key = keyMap [event. keyCode ]
state . pressedKeys [key] = true
}
function keyup(event) {
var key = keyMap [event. keyCode ]
state . pressedKeys [key] = false
}

window . addEventListener (" keydown ", keydown , false)


window . addEventListener (" keyup", keyup , false)
Event-driven programming

Responding to user input (iii)


Then we just need to update the x and y values based on the pressed keys and ensure that
we keep our object within the boundaries:
function update ( progress ) {
if ( state. pressedKeys .left) {
state .x -= progress
}
if ( state. pressedKeys .right) {
state .x += progress
}
if ( state. pressedKeys .up) {
state .y -= progress
}
if ( state. pressedKeys .down) {
state .y += progress
}
if ( state.x > width) {
state .x -= width
}
else if (state.x < 0) {
state .x += width
}
if ( state.y > height ) {
state .y -= height
}
else if (state.y < 0) {
state .y += height
}
}
Event-driven programming

The observer pattern (i)

I The observer pattern (also known as listeners or callbacks) is a software design


pattern in which an object, named the subject, maintains a list of its dependents,
called observers, and notifies them automatically of any state changes, usually by
calling one of their methods.
I It is mainly used for implementing distributed event handling systems, in event-driven
software.
I In those systems, the subject is usually named a “stream of events” or “stream source
of events”, while the observers are called “sinks of events”.
I This pattern suits a process where data arrives from some input, isn’t available to the
CPU at startup, but can arrive “at random” (HTTP requests, GPIO data, user input
from keyboard/mouse/..., distributed databases, blockchains, etc.).
Event-driven programming

The observer pattern (ii)


Event-driven programming

The six plagues of listeners

According to [BJ16]:
I Unpredictable order—In a complex network of listeners, the order in which events are
received can depend on the order you registered the listeners in, which is not helpful.
I Missed first event—It can be difficult to guarantee that you have registered your
listeners before you send the first event.
I Messy state—Callbacks push your code into a traditional state machine style.
I Threading issues—Attempting to make listeners thread-safe can lead to deadlocks,
and it can be difficult to guarantee that no more callbacks will be received after
deregistering a listener.
I Leaking callbacks—If you forget to deregister your listener, your program will leak
memory. Listeners reverse the natural data dependency, but do not reverse the
keep-alive dependency, as we would like them to.
I Accidental recursion—The order in which you update local state and notify listeners
can be critical, and it’s easy to make mistakes.
Event-driven programming

Functional reactive programming (FRP)

Functional reactive programming (FRP) [EH97] can be viewed from different angles [BJ16]:
I It’s a replacement for the widely used observer pattern.
I It’s a composable, modular way to code event-driven logic.
I It’s a different way of thinking: the program is expressed as a reaction to its inputs, or
as a flow of data.
I It brings order to the management of program state.
I It’s normally implemented as a lightweight software library in a standard programming
language.
I It can be seen as a complete embedded language for stateful logic. It can be viewed
as a minimal complete domain-specific language (DSL) for stateful logic.
Event-driven programming

A stricter definition
Conal Elliot stated in a StackOverflow post, Specification for a Functional Reactive
Programming Language1 :
I’m glad you’re starting by asking about a specification rather than implementation
first. There are a lot of ideas floating around about what FRP is. For me it’s always
been two things: (a) denotative and (b) temporally continuous. Many folks drop
both of these properties and identify FRP with various implementation notions, all
of which are beside the point in my perspective. To reduce confusion, I would like
to see the term “functional reactive programming” replaced by the more accurate
& descriptive “denotative, continuous-time programming” (DCTP), as suggested
by Jake McArthur in a conversation last year.
By “denotative”, I mean founded on a precise, simple, implementation-
independent, compositional semantics that exactly specifies the meaning of each
type and building block. The compositional nature of the semantics then deter-
mines the meaning of all type-correct combinations of the building blocks. For me,
denotative is the heart & essence of functional programming, and is what enables
precise & tractable reasoning and thus a foundation for correctness, derivation,
and optimization. Peter Landin recommended “denotative” as a substantive re-
placement to the fuzzier term “functional” and a way to distinguish deeply/gen-
uinely functional programming from merely functional-looking notations.

1 https://stackoverflow.com/questions/5875929/
specification-for-a-functional-reactive-programming-language
Event-driven programming

More definitions

I Denotational semantics is a mathematical expression of the formal meaning of a


programming language. For an FRP system, it provides both a formal specification of
the system and a proof that the important property of compositionality holds for all
building blocks in all cases.
I Compositionality is a mathematically strong form of the concept of composability that
is often recommended in software design.
I Functional programming (FP) is a style of programming based on functions, in the
mathematical sense of the word. It deliberately avoids shared mutable state, so it
implies the use of immutable data structures and it emphasizes compositionality.
I Reactive programming2 is a broad term meaning that a program is (1) event-based,
(2) acts in response to input, and (3) is viewed as a flow of data instead of the
traditional flow of control. It doesn’t dictate any specific method of achieving these
aims. Reactive programming gives looser coupling between program components, so
the code is more modular.
I Functional reactive programming (FRP) is a specific method of reactive
programming that enforces the rules of functional programming, particularly the
property of compositionality.

2 A definition from [Lel19]: Reactive programming is a programming paradigm oriented toward data flows and the
propagation of change: programming with asynchronous data streams.
Event-driven programming

Functional programming (FP)

I Functional programming (FP) is the process of building software by


I composing pure functions;
I avoiding shared state;
I avoiding mutable data;
I avoiding side effects.
I Functional programming is declarative rather than imperative, and application state
flows through pure functions.
I It can be contrasted to object oriented programming (OOP), where application state
is usually shared and colocated with methods in objects.
I Functional programming is a programming paradigm, meaning that it is a way of
thinking about software construction based on some fundamental, defining principles.
Other examples of programming paradigms include OOP and procedural
programming.
I Functional code tends to be more concise, more predictable, and easier to test than
imperative or object oriented code.
I If you are unfamiliar with it and the common patterns associated with it, functional
code can also seem a lot more dense, and the related literature can be difficult for
newcomers.
Event-driven programming

Pure functions

I A pure function is a function which:


I given the same inputs, always returns the same output, and
I has no side effects.
I Pure functions have properties that are important in functional programming, including
referential transparency (you can replace a function call with its resulting value
without changing the meaning of the program).
I A giveaway that a function is impure is if it makes sense to call it without using its
return value.
I A function is only pure if, given the same input, it will always produce the same output.
Event-driven programming

Function composition

I Function composition is the process of combining two or more functions in order to


produce a new function or perform some computation.
I The composition f .g (the dot means “composed with”) is equivalent to f (g (x )).
I Composing functions together is like snapping together a series of pipes for our data
to flow through.
Event-driven programming

Shared state

I Shared state is any variable, object, or memory space that exists in a shared scope,
or as the property of an object being passed between scopes.
I A shared scope can include global scope or closure scopes.
I In object oriented programming, objects are shared between scopes by adding
properties to other objects.
I The problem with shared state is that in order to understand the effects of a function,
you have to know the entire history of every shared variable that the function uses or
affects.
Event-driven programming

Race condition

I Imagine you have a user object which needs saving.


I Your saveUser() function makes a request to an API on the server.
I While that’s happening, the user changes their profile picture with updateAvatarg()
and triggers another saveUser() request.
I On save, the server sends back a canonical user object that should replace whatever
is in memory in order to sync up with changes that happen on the server or in
response to other API calls.
I Unfortunately, the second response gets received before the first resoponse, so when
the first (now outdated) response gets returned, the new profile pic gets wiped out in
memory and replaced with the old one.
I This is an example of a race condition—a very common bug associated with shared
state.
Event-driven programming

Timing dependency

// With shared state , the order in which function calls are made
// changes the result of the function calls.
const x = {
val: 2
};
const x1 = () => x.val += 1;
const x2 = () => x.val *= 2;
x1 ()
x2 ();
console .log(x.val); // 6

const y = {
val: 2
};
const y1 = () => y.val += 1;
const y2 = () => y.val *= 2;
y2 ();
y1 ();
console .log(y.val); // 5
Event-driven programming

Resolving the timing dependency (i)

I When you avoid shared state, the timing and order of function calls don’t change the
result of calling the function.
I With pure functions, given the same input, you’ll always get the same output.
I This makes function calls completely independent of other function calls, which can
radically simplify changes and refactoring.
I A change in one function, or the timing of a function call won’t ripple out and break
other parts of the program.
Event-driven programming

Resolving the timing dependency (ii)

// With shared state , the order in which function calls are made
// changes the result of the function calls.
const x = {
val: 2
};
const x1 = x => Object . assign ({}, x, {val: x.val + 1});
const x2 = x => Object . assign ({}, x, {val: x.val * 2};
console .log(x1(x2(x)).val); // 5

const y = {
val: 2
};

// Since there are no dependencies on outside variables ,


// we don ’t need different functions to operate on different
// variables .

// Because the functions don ’t mutate , you can call these


// functions as many times as you want , in any order ,
// without changing the result of other function calls.
x2(y);
x1(y);
console .log(x1(x2(y)).val); // 5
Event-driven programming

Order matters

I Of course, if you change the order of the composition, the output will change.
I Order of operations still matters.
I f(g(x)) is not always equal to g(f(x)), but what doesn’t matter anymore is what
happens to variables outside the function—and that’s a big deal.
I With impure functions, it’s possible to fully understand what a function does unless you
know the entire history of every variable that the function uses or affects.
I Remove function call timing dependency, and you eliminate an entire class of potential
bugs.
Event-driven programming

Immutability

I An immutable object is an object that cannot be modified after it has been created.
I Conversely, a mutable object is an object that can be modified after it has been
created.
I Immutability is a central concept of functional programming because without it the data
flow in your program is lossy. State history is abandoned and strange bugs can creep
into your software.
I Don’t confuse constness with immutability. Immutable objects can’t be changed at all.
Event-driven programming

Side effects

I A side effect is any application state change that is observable outside the called
function other than its return value.
I Side effects include:
I Modifying any external variable or object property (e.g. a global variable or a variable in the
parent function scope chain);
I Logging to the console;
I Writing to the screen;
I Writing to a file;
I Writing to the network;
I Triggering any external process;
I Calling any other functions with side effects.
I Side effects are mostly avoided in functional programming, which makes the effects of
a program much easier to understand and much easier to test.
I Haskell and other functional languages frequently isolate and encapsulate side effects
from pure functions using monads.
I In functional programming side-effect actions need to be isolated from the rest of your
software.
I If you keep side effects separate from the rest of your program logic, your software will
be easier to extend, refactor, debug, test, and maintain.
Event-driven programming

Higher order function

I A higher order function is any function which takes a function as an argument,


returns a function, or both.
I Higher order functions are often used to:
I Abstract or isolate actions, effects, or asynchronous flow control using callback functions,
promises, monads, etc...
I Create utilities which can act on a wide variety of data types.
I Partially apply a function to its arguments or create a curried function for the purpose of
reuse or function composition.
I Take a list of functions and return some composition of those input functions.
Event-driven programming

Stream

I The stream (event stream, observable) is a sequence of events ordered in time.


I A stream can emit:
I a value;
I an “error” signal;
I a “completed” signal.
I The stream can be represented by a marble diagram:

I You can think of streams as “arrays” with an added dimension of time.


Event-driven programming

Operations on streams

I Creating: create, just, from...


I Transforming: map, flatMap, scan, buffer...
I Filtering: filter, debounce, skip, distinct...
I Combining: join, merge, combineLatest...
I Conditional/boolean: takeUntil, contains...
I ...
Event-driven programming

Example: click stream to multiple clicks stream


Event-driven programming

Example: counting ages ≥ 21

# include <iostream >


# include <vector >

# include " rxcpp/rx.hpp"

int main ()
{
std :: vector <int > ages{ 9, 20, 13, 4, 5, 6, 10, 28, 19, 15, 60, 23, 47, 12, 19, 99
,→ };

auto values = rxcpp :: observable <>:: iterate (ages)


. filter ([]( int age) { return age >= 21; })
. count ()
. subscribe (
[]( int count) { std :: cout << " Number over 21 = " << count << std :: endl;
,→ },
[]() { std :: cout << " OnCompleted " << std :: endl; }
);

return 0;
}
Event-driven programming

Fluent interface

I A fluent interface is an object-oriented API whose design relies extensively on


method chaining (each method returns an object, allowing the calls to be chained
together in a single statement without requiring variables to store the intermediate
results).
I Its goal is to increase code legibility by creating a domain-specific language (DSL).
I The term was coined in 2005 by Eric Evans and Martin Fowler:
https://www.martinfowler.com/bliki/FluentInterface.html
I A fluent interface is normally implemented by using method chaining to implement
method cascading (a syntax which allows multiple methods to be called on the same
object), concretely by having each method return the object to which it is attached,
often referred to as this or self.
I A fluent interface means more than just method cascading via chaining; it entrails
designing an interface that reads like a domain-specific language (DSL).
Event-driven programming

FRP libraries

I ReactiveX ecosystem:
I RxJS
I RxJava
I Rx.NET
I RxCpp
I Bacon.js
I Kefir.js
I Cycle.js
I Reactive Streams and java.util.concurrent.Flow
I Sodium (C++, C#, F#, Java, Kotlin, Scala, Typescript/Javascript, Embedded-C, Rust)
I Reactive Banana (Haskell)
Event-driven programming

Videos on functional reactive programming (i)

I Conal Elliott. The essence and origins of FRP or How you could have invented
Functional Reactive Programming. LambdaJam, 2015.10.18,
https://www.youtube.com/watch?v=j3Q32brCUAI
I Andre Staltz. Cycle.js and functional reactive user interfaces. ReactiveConf,
2015.11.28, https://www.youtube.com/watch?v=uNZnftSksYg
I Colby CheeZe. Functional Programming for Beginners. 2016.03.09,
https://www.youtube.com/watch?v=vLmaZxegahk
I Adam M. Intrator. FRP, Observables, and React. Fullstack Academy, 2017.01.29,
https://www.youtube.com/watch?v=IfFfvfCl4A8
I Stephen Blackheath. FRP in Java using Sodium. FP Auckland Meetup, 2017.10.14,
https://www.youtube.com/watch?v=xHaoPVSgtiM
Event-driven programming

Videos on functional reactive programming (ii)

I Hannah Howard. Reactive Programming: A Better Way To Write Frontend


Applications. Strange Loop, 2018.10.11,
https://www.youtube.com/watch?v=NkVfvxaKVVY
I Troy Miles. RxCpp library. Introducing Functional Programming in C++, 2018.11.12,
https://www.linkedin.com/learning/
introducing-functional-programming-in-c-plus-plus/rxcpp-library
I Venkat Subramaniam. From Functional to Reactive Programming. RigaDevDays,
2019.07.01, https://www.youtube.com/watch?v=eaJVeVV6Ky0
I Tikhon Jelvis. What is Functional Reactive Programming? FunctionalTV, 2019.11.19,
https://www.youtube.com/watch?v=ePgWU3KZvfQ
Event-driven programming

Tutorials on functional reactive programming

I Andre Staltz. The introduction to Reactive Programming you’ve been missing.


2014.06.23, https://gist.github.com/staltz/868e7e9bc2a7b8c1f754
I Eric Elliott. Master the JavaScript Interview: What is Functional Programming?
Medium, 2017.01.04, https://medium.com/javascript-scene/
master-the-javascript-interview-what-is-functional-programming-7f218c68b3a0
I Dan Lew. An Introduction to Functional Reactive Programming. 2017.07.27,
https://blog.danlew.net/2017/07/27/
an-introduction-to-functional-reactive-programming/
I Eric Rey. Functional Reactive Programming explained in a simple way, in JavaScript...
yes, in a simple way. 2018.06.20, https://itnext.io/
functional-reactive-programming-explained-in-a-simple-way-in-javascript-yes
Event-driven programming

Books on functional reactive programming

I Stephen Blackheath and Anthony Jones. Functional Reactive Programming.


Manning, 2016 [BJ16].
I Tomasz Nurkiewicz and Ben Christensen. Reactive programming with RxJava:
Creating Asynchronous, Event-Based Applications. O’Reilly, 2016 [NC16].
I Tamir Dresher. Rx.NET in action. Manning, 2017 [Dre17].
Event-driven programming
Bibliography

Stephen Blackheath and Anthony Jones.


Functional Reactive Programming.
Manning, 2016.
Tamir Dresher.
Reactive Extensions in .NET: With examples in C#.
Manning, 2017.
Conal Elliott and Paul Hudak.
Functional reactive animation.
In International Conference on Functional Programming, 1997.
Tomasz Lelek.
Hands-on Reactive Programming with Java 12.
Packt Publishing, 2019.
Tomasz Nurkiewicz and Ben Christensen.
Reactive Programming with RxJava: Creating Asynchronous Event-based
Applications.
O’Reilly, 2016.

You might also like