State Machine DSL revamp

I min forrige blogpost gikk jeg gjennom hvordan jeg laget en enkel tilstandsmaskin i Ruby. Jeg har tenkt litt mer på den, og her kommer en liten forbedring..

Orginalt la jeg til rette for to ulike måter å konfigurere tilstandsmaskinen på. Først lagde jeg en enkel add_transition metode som jeg kunne kalle slik som dette:

   9         @state_machine.add_transition(:locked, :coin, :unlocked) { @unlock_called = true }

Ulempen med denne er at den ikke kommuniserer så godt – god kode skrevet for mennesker bør kommunisere mer enn det der. Jeg lagde derfor et flytende grensesnitt, ala det jeg tidligere hadde laget i C#.

   72         @state_machine.configure do |sm|

   73             sm.given(:locked).when(:coin).then_set_state(:unlocked).and_run { @unlock_called = true }

   74             sm.given(:locked).when(:pass).then_set_state(:locked).and_run { @alarm_called = true }

   75             sm.given(:unlocked).when(:coin).then_set_state(:unlocked).and_run { @thank_you_called = true }

   76             sm.given(:unlocked).when(:pass).then_set_state(:locked).and_run { @lock_action_called = true }

   77         end

Etter å ha tenkt meg litt om har jeg kommet opp med et grensesnitt jeg liker bedre. Det ligner mer på andre ting jeg har sett i Ruby, og er på en form som Rubyister gjerne refererer til som DSL-metoder. Ved å bruke en Hash (dotnet’ere kan kalle dette Dictionary) som parameter kommuniserer koden enda bedre. Det blir litt mer tekst å skrive, men på den andre siden er det også mere fleksibelt (om man f.eks. vil legge til flere parametre). Det nye grensesnittet brukes på denne måten:

   137         @state_machine.transition :if_state_is => :locked,  

   138             :when_event => :coin, :then_set_state => :unlocked do

   139             @unlock_called = true

   140         end

   141         @state_machine.transition :if_state_is => :locked,  

   142             :when_event => :pass, :then_set_state => :locked do

   143             @alarm_called = true

   144         end

   145         @state_machine.transition :if_state_is => :unlocked,  

   146             :when_event => :coin, :then_set_state => :unlocked do

   147             @thank_you_called = true

   148         end

   149         @state_machine.transition :if_state_is => :unlocked,  

   150             :when_event => :pass, :then_set_state => :locked do

   151             @lock_action_called = true

   152         end

Mellom ‘do’ og ‘end’ putter man selvsagt all koden som skal trigges av tilstandsendringen – på samme måte som man kunne gjøre mellom { og } i de foregående eksemplene (dette er to ulike måter å gjøre det samme på i Ruby, hvor klammene normalt brukes når kodeblokken er på samme linje som metodekallet, og bare inneholder én statement.

Selve transition-metoden er enkel å implementere. Den plukker ut verdiene fra Hash’en og sender dem til den tidligere definerte add_transition-metoden.

   185 class GenericStateMachine #open class definition to add another dsl method

   186     def transition args, &and_run

   187         add_transition args[:if_state_is], args[:when_event], args[:then_set_state], &and_run

   188     end

   189 end

Kategorier: Ruby.
RSS feed for kommentarene. Tilbaketråkk.

Skriv en kommentar

Tillatte tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>


Torbjørn: La oss anta to ulike definisjoner av Template Method pattern - de to ytterpunkte...

Lars-Petter: Hei igjen. Siden du inviterer til å ta diskusjonen i bloggen, og har tatt deg t...

Torbjørn: Lars-Petter: Det er én måte å se det på. Det er absolutt fortsatt Template M...

Lars-Petter: Hei. Har du ikke i prinsippet her gått over fra Template Method (arv) til Strat...

Christian Abildsø: I alle fall i C#, så føles dette som kode som blir mer fleksibel men vanskelig...

Torbjørn: Hei Henrik, og takk for tilbudet. Ble oppmerksom på Rasberry Pi for under en uk...

Henrik Sandaker Palm: Ang. større hobby prosjekt. Du er som er en slik rakker på programmering har j...

Øivind Nilsen: Slutt å bruke mobilnummeret mitt som eksempel !...

Bjørn Einar Bjartnes: Jeg har også latt meg fascinere av Clojure, uten at jeg har kommet så veldig l...

Bjørn Einar Bjartnes: Sweet :) Jeg tror egentlig jeg liker det som det er, med musikk. Litt av utford...

Mulig relaterte linker

 Hold deg oppdatert

Søk i bloggen

Ferske innlegg

  • Template Method del 4: Multippel arv
  • Template Method Intermesso
  • Template Method del 3: Bare funksjoner
  • Template Method del 2: På vei mot funksjonell programmering
  • Kategorier

  • .net ninja (37)
  • Bøker (17)
  • Diverse prosjekter (35)
  • DSL (10)
  • Erlang (10)
  • F# (5)
  • Hardware (1)
  • Jobb (77)
  • Julekalender (51)
  • kjempekjekt.com (23)
  • LISP/Clojure (33)
  • NNUG / community (60)
  • O/RM & databaser (10)
  • Off topic (116)
  • OO-design/clean code (30)
  • Podcasts (14)
  • Polyglot (77)
  • Ruby (27)
  • Silverlight / RIA (3)
  • Software/verktøy (20)
  • Softwareutvikling (20)
  • Testing / TDD (30)
  • the contiki strip (13)
  • User experience (3)
  • WCF (3)
  • Webutvikling (32)
  • WPF (9)
  • WTF (12)
  • Last ned Wallpaper

    Programmeringsbloggens tøffe skrivebordsbakgrunn med snippets fra ulike språk laster du ned her!

    Abonner via epost

    Om du vil kan du få alle nye blogposter tilsendt til din epost. Abonner nå, det er kjempeenkelt!

    Meta