Академический Документы
Профессиональный Документы
Культура Документы
MARTIN FOWLER
http://martinfowler.com
JMock expectations
2
Opening the door resets the system and locks the panel
1 start
State name ! action ! Command
source
1 target
! Transition
! ! trigger Event
reset events !
doorClosed = new Event("doorClosed", "D1CL"); drawOpened = new Event("drawOpened", "D2OP"); lightOn = new Event("lightOn", "L1ON"); doorOpened = new Event("doorOpened", "D1OP"); panelClosed = new Event("panelClosed", "PNCL"); unlockPanelCmd = new Command("unlockPanel", "PNUL"); lockPanelCmd = new Command("lockPanel", "PNLK"); lockDoorCmd = new Command("lockDoor", "D1LK"); unlockDoorCmd = new Command("unlockDoor", "D1UL");
machine.addResetEvents(doorOpened); State State State State State idle = new State("idle"); activeState = new State("active"); waitingForLightState = new State("waitingForLight"); waitingForDrawState = new State("waitingForDraw"); unlockedPanelState = new State("unlockedPanel");
StateMachine machine = new StateMachine(idle); idle.addTransition(doorClosed, activeState); idle.addAction(unlockDoorCmd); idle.addAction(lockPanelCmd); activeState.addTransition(drawOpened, waitingForLightState); activeState.addTransition(lightOn, waitingForDrawState); waitingForLightState.addTransition(lightOn, unlockedPanelState); waitingForDrawState.addTransition(drawOpened, unlockedPanelState); unlockedPanelState.addAction(unlockPanelCmd); unlockedPanelState.addAction(lockDoorCmd); unlockedPanelState.addTransition(panelClosed, idle);
<stateMachine start = "idle"> <event name="doorClosed" code="D1CL"/> <event name="drawOpened" code="D2OP"/> <event name="lightOn" code="L1ON"/> <event name="doorOpened" code="D1OP"/> <event name="panelClosed" code="PNCL"/> <command <command <command <command name="unlockPanel" code="PNUL"/> name="lockPanel" code="PNLK"/> name="lockDoor" code="D1LK"/> name="unlockDoor" code="D1UL"/>
<state name="idle"> <transition event="doorClosed" target="active"/> <action command="unlockDoor"/> <action command="lockPanel"/> </state> <state name="active"> <transition event="drawOpened" target="waitingForLight"/> <transition event="lightOn" target="waitingForDraw"/> </state> <state name="waitingForLight"> <transition event="lightOn" target="unlockedPanel"/> </state> <state name="waitingForDraw"> <transition event="drawOpened" target="unlockedPanel"/> </state> <state name="unlockedPanel"> <action command="unlockPanel"/> <action command="lockDoor"/> <transition event="panelClosed" target="idle"/> </state> </stateMachine>
events doorClosed drawOpened lightOn doorOpened panelClosed end resetEvents doorOpened end commands unlockPanel lockPanel lockDoor unlockDoor end
state idle actions {unlockDoor lockPanel} doorClosed => active end state active drawOpened => waitingForLight lightOn => waitingForDraw end state waitingForLight lightOn => unlockedPanel end
state waitingForDraw drawOpened => unlockedPanel end state unlockedPanel actions {unlockPanel lockDoor} panelClosed => idle end
:doorClosed, "D1CL" :drawOpened, "D2OP" :lightOn, "L1ON" :doorOpened, "D1OP" :panelClosed, "PNCL" :unlockPanel, :lockPanel, :lockDoor, :unlockDoor, "PNUL" "PNLK" "D1LK" "D1UL"
state :idle do actions :unlockDoor, :lockPanel transitions :doorClosed => :active end state :active do transitions :drawOpened => :waitingForLight, :lightOn => :waitingForDraw end state :waitingForLight do transitions :lightOn => :unlockedPanel end state :waitingForDraw do transitions :drawOpened => :unlockedPanel end state :unlockedPanel do actions :unlockPanel, :lockDoor transitions :panelClosed => :idle end
resetEvents :doorOpened
10
External DSL
Internal DSL
(aka Embedded DSL)
state :idle do actions :unlockDoor, :lockPanel transitions :doorClosed => :active end
<state name="idle"> <transition event="doorClosed" target="active"/> <action command="unlockDoor"/> <action command="lockPanel"/> </state>
doorClosed = new Event("doorClosed", "D1CL"); drawOpened = new Event("drawOpened", "D2OP"); lightOn = new Event("lightOn", "L1ON"); doorOpened = new Event("doorOpened", "D1OP"); panelClosed = new Event("panelClosed", "PNCL");
Is this a DSL?
unlockPanelCmd = new Command("unlockPanel", "PNUL"); lockPanelCmd = new Command("lockPanel", "PNLK"); lockDoorCmd = new Command("lockDoor", "D1LK"); unlockDoorCmd = new Command("unlockDoor", "D1UL");
machine.addResetEvents(doorOpened); State State State State State idle = new State("idle"); activeState = new State("active"); waitingForLightState = new State("waitingForLight"); waitingForDrawState = new State("waitingForDraw"); unlockedPanelState = new State("unlockedPanel");
StateMachine machine = new StateMachine(idle); idle.addTransition(doorClosed, activeState); idle.addAction(unlockDoorCmd); idle.addAction(lockPanelCmd); activeState.addTransition(drawOpened, waitingForLightState); activeState.addTransition(lightOn, waitingForDrawState); waitingForLightState.addTransition(lightOn, unlockedPanelState); waitingForDrawState.addTransition(drawOpened, unlockedPanelState); unlockedPanelState.addAction(unlockPanelCmd); unlockedPanelState.addAction(lockDoorCmd); unlockedPanelState.addTransition(panelClosed, idle);
12
public class BasicStateMachine extends StateMachineBuilder { Events doorClosed, drawOpened, lightOn, panelClosed; Commands unlockPanel, lockPanel, lockDoor, unlockDoor; States idle, active, waitingForLight, waitingForDraw, unlockedPanel; ResetEvents doorOpened; protected void defineStateMachine() { doorClosed. code("D1CL"); drawOpened. code("D2OP"); lightOn. code("L1ON"); panelClosed.code("PNCL"); doorOpened. code("D1OP"); unlockPanel.code("PNUL"); lockPanel. code("PNLK"); lockDoor. code("D1LK"); unlockDoor. code("D1UL"); idle .actions(unlockDoor, lockPanel) .transition(doorClosed).to(active) ; active .transition(drawOpened).to(waitingForLight) .transition(lightOn). to(waitingForDraw) ; waitingForLight .transition(lightOn).to(unlockedPanel) ; waitingForDraw .transition(drawOpened).to(unlockedPanel) ; unlockedPanel .actions(unlockPanel, lockDoor) .transition(panelClosed).to(idle) ; } }
Tuesday, April 7, 2009 13
Command-Query API
State idle = new State("idle"); State activeState = new State("active"); idle.addTransition(doorClosed, activeState); idle.addAction(unlockDoorCmd); idle.addAction(lockPanelCmd); activeState.addTransition(drawOpened, waitingForLightState); activeState.addTransition(lightOn, waitingForDrawState);
Fluent API
14
Domain Specic Language (noun) a computer programming language of limited expressiveness focused on a particular domain
Execute
DSL Script
optional
Parse
Generate
Semantic Model
Code
16
Language Workbenches
open source eclipse mature made IntelliJ and ReSharper
Tuesday, April 7, 2009
DSL Tools
17
Source Editing
string sentence = I am completely operational, and all + my circuits are functioning perfectly; voice.speak (sentence);
javac hal.java
18
Projectional Editing
Model Repository
projections
generate
19
Source
Projectional
Structured Text
Oslo
Diagrams
DSL Tools
Tuesday, April 7, 2009 20
input =~ /\d{3}-\d{3}-\d{4}/
21
22
write read
Tuesday, April 7, 2009 23
MARTIN FOWLER
http://martinfowler.com
24