Upgrade to Pro — share decks privately, control downloads, hide ads and more …

State Machines and Asynchronous Programming

richardms
October 27, 2011

State Machines and Asynchronous Programming

As delivered at London Node User Group Oct. 11

richardms

October 27, 2011
Tweet

Other Decks in Programming

Transcript

  1. 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
  2. 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
  3. 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
  4. 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
  5.  Behaviour is drawn as a graph  A bit

    like a flowchart – but no decisions, just events  States are:  ‘Steady’  ‘Waiting’  Triggers/Events are key
  6. 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
  7. 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) { ... }) ;
  8. 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
  9. 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
  10. 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
  11. 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“ } } } } ; }
  12. 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
  13. 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’