Slide 1

Slide 1 text

State Machines & Asynchronous Programming ignitejs.com: Richard Miller-Smith David Hammond

Slide 2

Slide 2 text

To discuss: ‘In asynchronous programming state machines are as important as object-oriented design’  Agenda:  (Finite) State Machines  How to use in node.js  ignite.js

Slide 3

Slide 3 text

(Finite) State Machines

Slide 4

Slide 4 text

Background  A tried and tested technique:  Protocols  Embedded devices (phones, video players)  Games  Lots of history and theory  Taught, but in a very theoretical way

Slide 5

Slide 5 text

Definition A finite-state machine (FSM) or finite-state automaton (plural: automata), or simply a state machine, is a behavioral model used to design computer programs. It is composed of a finite number of states associated to transitions. A transition is a set of actions that starts from one state and ends in another (or the same) state. A transition is started by a trigger, and a trigger can be an event or a condition. Finite-state machines can model a large number of problems, among which are electronic design automation, communication protocol design, parsing and other engineering applications.... [1] [1] http://en.wikipedia.org/wiki/Finite-state_machine

Slide 6

Slide 6 text

My Evening Chat Listen Drink Beer Do Talk Describe Slide Intro Answer Questions Arrive Talks start Introduced Finished All talks finished Go to sleep Kebab

Slide 7

Slide 7 text

 Behaviour is drawn as a graph  A bit like a flowchart – but no decisions, just events  States are:  ‘Steady’  ‘Waiting’  Triggers/Events are key

Slide 8

Slide 8 text

UML2 State Machines [2]  Making state machines usable:  Beyond your CS course  Merging OO and state machines  Useful additions and patterns: ▪ Extended states ▪ Guard conditions ▪ Hierarchical ▪ Entry and exit actions ▪ Internal transitions ▪ Event deferral [2] http://en.wikipedia.org/wiki/UML_state_machine

Slide 9

Slide 9 text

State Machines & node.js Be gone evil callbacks... doSomething(param, function (err, data) { if (err) {...} doSomethingElse(data, anotherParam, function (err2, info) { if (err2) {...} if (info.isComplex) { furtherCall(data, info, function (err3, furtherInfo) { ... }) ; } else { furtherCall2(info, function (err3, furtherInfo) { ... }) ;

Slide 10

Slide 10 text

A good match?  Asynchronous = asking and then waiting  Javascript & node.js offer a ‘run to completion’ environment  node.js has three common event sources:  Callback ▪ Usually function (err, ...) ▪ 2 events – error or success  EventEmitters ▪ Lots of possible events (unfortunately unknown)  Timers (one off and interval)  Code gets complex quickly:  Multiple callbacks, EventEmitters, timeouts etc  Needs a design metaphor to make manageable

Slide 11

Slide 11 text

ignite.js http://ignitejs.com/

Slide 12

Slide 12 text

ignite.js  Design Goals:  Bring UML2-like hierarchical state machines to JavaScript/node.js  Explore best ways to define FSMs in JS  Provide tools to help design and implementation process  Small core, but make extensible  Environment first, speed later  More than just another async framework: ● Designed for node.js and its standard patterns ● Built from ground-up to support hierarchical state machines ● Small, simple core with plug-ins and add-ons to extend capabilities ● Draw your code as State Machine Diagrams ● Linting: Check your code makes sense

Slide 13

Slide 13 text

Anatomy of a state  From incoming transition:  [Guard function: make sure the state is legal]  [Entry function: ‘start’ the state]  Wait   New event:  [Action function: decide how to deal with event: ▪ Stay in state ▪ Re-enter state ▪ Go to another state]  [Exit function: tidy-up] Guard A state Entry Exit Action

Slide 14

Slide 14 text

Example (1) function lnugExample (fire, name) { return { startState: "HelloWorld", states: { "HelloWorld": { entry: function () { fire.process.stdout.write("Hello World\n".green) ; }, actions: { "process.stdout.write.done": "HelloName", "process.stdout.write.err": "@error“ } }, "HelloName": { guard: function () { if (!name || typeof name !== "string") return "@exit" ; }, entry: function () { var str = "Hello "+name+", pleased to meet you.\n" ; fire.process.stdout.write(str.red) ; }, actions: { ".write.done": "@exit", ".write.err": "@error“ } } } } ; }

Slide 15

Slide 15 text

Example (2)

Slide 16

Slide 16 text

The 12 Best Things about SMs/ignite.js  Design: 1. Natural: you can draw them on a whiteboard and discuss 2. Layer complexity by using hierarchical machines 3. Re-use standard design patterns 4. As formal as you want to be  Debugging: 5. States and events have names 6. Single SM: ‘stack’ of recent state/event history 7. Multi SM: can view recent interactions with states and events 8. (Unexpected) errors are attached to the machine  Implementation: 9. Flatten embedded callbacks 10. Share states, actions and machines across multiple SMs 11. Lots of plugins to ease async pain (whilst providing parallel operations) 12. Multi-process

Slide 17

Slide 17 text

Discussion ‘In asynchronous programming state machines are as important as object-oriented design’ ‘In asynchronous programming behavioural design is as important as structural design’ ‘In asynchronous programming state machines are as important as classes and objects’

Slide 18

Slide 18 text

Questions?  Further info at: ignitejs.com  Contacts: ● Twitter: @detillen ● Github: ignitejs or richardms