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

State Machines Are Everywhere - Why don't you u...

State Machines Are Everywhere - Why don't you use them?

Ruby developers don't tend to use state machines. State machines are a great tool build a mental model of the dynamic behaviour of objects and systems. They help to write code that is so simple that there are no obvious deficiencies. Why don't you use them?

Avatar for Klaas Jan Wierenga

Klaas Jan Wierenga

May 12, 2014
Tweet

Other Decks in Programming

Transcript

  1. KLAAS-JAN WIERENGA "KLASS" / KJ CHURCH CATCHUP SERVICE RUBY /

    RAILS SINCE 1.0 (2007) AMAZON AWS / CHEF @kjw github.com/kjwierenga
  2. QUANTUM PHYSICS ▸ quantum objects ▸ quantum states ▸ quantum

    leaps (transitions) ▸ interaction via intermediate artifacts (bosons)
  3. EVERY WEBSITE IS A STATE MACHINE Every URL is an

    application state. Hyperlinks are the transitions between states.
  4. WHAT IS A STATE MACHINE? "Sequence of states in response

    to events and the responses to those events"
  5. WHAT IS STATE? Situation where an object (or matter) ▸

    satisfies some condition ▸ performs some activity ▸ waits for some event
  6. WHAT IS AN EVENT? ▸ message ▸ timeout ▸ condition

    occuring that can trigger a state transition
  7. WHAT IS A TRANSITION "Change of current state in reaction

    to an event, given that certain conditions are satisfied."
  8. UML DIAGRAMS? I find that Rubyists don't draw too many

    UML diagrams. So this may look like higher glyphics to you, I'm not sure. - JIM WEIRICH
  9. I conclude that there are two ways of constructing a

    software design: One way is to make it so simple that there are obviously no deficiencies and the other way is to make it so complicated that there are no obvious deficiencies. The first method is far more difficult. C.A.R. (TONY) HOARE
  10. FSM # Initial state On Hook phone = MicroMachine.new(:on_hook) #

    On Hook phone.when(:digit, :on_hook => :dialing) phone.when(:incoming_call, :on_hook => :ringing) # Dialing phone.when(:digit, :dialing => :dialing) phone.when(:off_hook, :dialing => :alerting) phone.when(:on_hook, :dialing => :on_hook) # Alerting phone.when(:connected, :alerting => :connected) phone.when(:busy, :alerting => :busy) phone.when(:on_hook, :alerting => :on_hook) # Connected phone.when(:on_hook, :connected => :on_hook) # Ringing phone.when(:off_hook, :ringing => :connected) phone.when(:on_hook, :ringing => :on_hook)
  11. BEHAVIOUR i, number = 0, [9,1,1] digits = [] phone.on(:dialing)

    { digits << number[i]; i += 1 } phone.on(:alerting) { puts "Dial number #{digits.join}" } phone.on(:connected) { puts "Say: Happy mothersday!" }
  12. OUTPUT $ ruby examples/micromachine/phone.rb digit [ On_hook -> Dialing ]

    digit [ Dialing -> Dialing ] digit [ Dialing -> Dialing ] off_hook [ Dialing -> Alerting ] Dial number 911 connected [ Alerting -> Connected ] Say: Happy Mothersday! on_hook [ Connected -> On_hook ]
  13. ORM Integration class Event < ActiveRecord::Base def confirm!; confirmation.trigger(:confirm);end def

    cancel!; confirmation.trigger(:cancel); end def reset!; confirmation.trigger(:reset); end def confirmation @confirmation ||= begin fsm = MicroMachine.new(confirmation_state || "pending") fsm.when(:confirm, :pending => :confirmed) fsm.when(:cancel, :confirmed => :cancelled) fsm.when(:reset, :confirmed => :pending, :cancelled => :pending) fsm.on(:any) { self.confirmation_state = confirmation.state } fsm end end end
  14. SIMPLE 50 LINES IMPLEMENTATION class MicroMachine InvalidEvent = Class.new(NoMethodError) attr

    :transitions_for attr :state def initialize initial_state @state = initial_state @transitions_for = Hash.new { |hash, key| hash[key] = {} } @callbacks = Hash.new { |hash, key| hash[key] = [] } end def on key, &block @callbacks[key] << block end def when(event, transitions) transitions_for[event].merge!(transitions) end def trigger event if trigger?(event) from, @state = @state, transitions_for[event][@state] callbacks = @callbacks[@state] + @callbacks[:any] callbacks.each { |callback| callback.call(event, from) } true else false end end def trigger?(event) raise InvalidEvent unless transitions_for.has_key?(event) transitions_for[event][state] ? true : false end def events transitions_for.keys end def states events.map { |e| transitions_for[e].to_a }.flatten.uniq end def ==(some_state) state == some_state end end
  15. DON'T LET YOUR PROGRAMS TURN INTO RANDOM SEGMENTS OF CODE

    THAT GROUP TOGETHER TO FORM UNEXPECTED PROTOCOLS
  16. ?

  17. REFERENCES Booch, Jacobsen, Rumbauch, The Unified Modelling Language User Guide

    (Addison Wesley Longman, Inc., 1999). Prof. James W. Fowler. Stages of Faith. Retrieved from http://en.wikipedia.org/wiki/Fowler's_stages_of_faith_development Martin Fowler. CircuitBreaker. Retrieved from http://martinfowler.com/bliki/CircuitBreaker.html Peter Gordon, The Incredible Rate of Diminishing Returns of Fixing Software Bugs. Retrieved from http://superwebdeveloper.com/2009/11/25/the-incredible-rate-of-diminishing-returns-of-fixing-software-bugs/ Hacker News, Why Developers Never Use State Machines. Retrieved from https://news.ycombinator.com/item?id=2949543 Miro Samek, Ph.D. Practical statecharts in C/C++ (CMP Books, 2002). Alan Skorkin, Why Developers Never Use State Machines. Retrieved from http://www.skorks.com/2011/09/why-developers-never-use-state-machines/ Dale Schumacher, Debugging Actor Systems. Retrieved from http://www.dalnefre.com/wp/2012/07/debugging-actor-systems/ Tom Stuart, Understanding Computation (O'Reilly, 2013).
  18. IMAGES https://nl.gravatar.com/userimage/8655/782e975c930e6ed42b6231084f64bf96.png?size=200 http://ahintofgarlic.files.wordpress.com/2011/10/glenmorangie-10-yo.jpg http://riverofhopehutchinson.org/wp-content/uploads/2014/01/World.jpg http://possiblyhelpfuladvice.com/wp-content/uploads/2011/10/denial-edit3.jpg http://uowresearch.files.wordpress.com/2011/10/cern2.jpg http://blog.sciencemuseum.org.uk/insight/files/2013/07/CMS.-Credit-CERN.jpg http://photos.pcpro.co.uk/blogs/wp-content/uploads/2011/02/clouds.jpg http://upload.wikimedia.org/wikipedia/commons/thumb/0/0b/Phase_change_-_en.svg/340px-Phase_change_-_en.svg.png http://www.tcpipguide.com/free/diagrams/tcpfsm.png

    http://assets1.bigthink.com/system/idea_thumbnails/44250/headline/religion SS.jpg http://farm2.static.flickr.com/1344/1454826321_f97fd090c7.jpg http://www.gliffy.com/go/publish/image/5693931/L.png http://www.wearyourbeer.com/images/Humor_Whats_In_It_For_Me_Navy_Shirt2.jpg http://www.gliffy.com/go/publish/image/5712330/l.png http://aturingmachine.com/turingFull560.jpg http://computationbook.com/images/cover https://lh6.googleusercontent.com/-dF4YA8UayMU/Tr0xl7AxDZI/AAAAAAAAAYU/YfQ4t8IhwNY/s400/rest-00.jpg http://www.gliffy.com/go/publish/image/5718828/L.png?8 http://upload.wikimedia.org/wikipedia/commons/e/e4/Reitter-1908_table75_life_cycle.png http://thedude.com/wp/wp-content/uploads/2009/01/bugs_6.jpg http://upload.wikimedia.org/wikipedia/commons/2/2c/Sir_Tony_Hoare_IMG_5125.jpg http://phenomena.nationalgeographic.com/files/2013/04/brain-990x622.png http://possiblyhelpfuladvice.com/wp-content/uploads/2011/10/denial-edit3.jpg http://archive.linuxgizmos.com/ldfiles/misc/ericsson-screenphone.jpg http://www.gliffy.com/go/publish/image/5701653/L.png?8 http://www.gliffy.com/go/publish/image/5701653/L.png?8 http://www.gliffy.com/go/publish/image/5717746/L.png http://www.gliffy.com/go/publish/image/5717759/L.png http://www.gliffy.com/go/publish/image/5701653/L.png?7 http://upload.wikimedia.org/math/6/a/e/6ae270f6bf32afdd113c866546fe0a1b.png http://www.gliffy.com/go/publish/image/5729145/L.png?2 https://dl.dropboxusercontent.com/u/483070/fsmtalk-images/fsm-comparison.png http://blog.travis-ci.com/images/Travdroid.png http://martinfowler.com/bliki/images/circuitBreaker/state.png http://gcoinc.files.wordpress.com/2011/06/where_am_i.png http://static.wixstatic.com/media/4ad061_87913765cb4c43d6b778e188af0ad6e6.jpg_srz_2448_3264_85_22_0.50_1.20_0.00_jpg_srz http://richardlfloyd.files.wordpress.com/2012/01/confused-face.jpg http://riablog.com/wp-content/uploads/2011/10/whatnext1.jpg http://www.billboard.com/files/styles/promo_650/public/stylus/502061-tron-daft-punk-617-409.jpg http://img.dxcdn.com/productimages/sku_156802_1.jpg http://www.gliffy.com/go/publish/image/5693845/L.png http://www.mathertel.de/Arduino/OneButtonFSM.png http://inwallspeakers1.com/wp-content/uploads/2014/03/apple-keyboard.jpg https://dv95pc38vkxqb.cloudfront.net/production/previews/248/1354501098/original.png?1354501098 http://ulam2.cs.luc.edu/ebook/html/_images/tcp_ladder_states.png http://www.newstalk650.com/sites/default/files/news-image/IMG_3959.JPG http://www.gliffy.com/go/publish/image/5726819/L.png http://www.gliffy.com/go/publish/image/5718715/L.png http://www.gliffy.com/go/publish/image/5719123/L.png https://dl.dropboxusercontent.com/u/483070/fsmtalk-images/abstract_model_of_computation.png http://www.gliffy.com/go/publish/image/5729154/L.png