<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Nicholas Blumhardt : Stateless</title><link>http://blogs.msdn.com/nblumhardt/archive/tags/Stateless/default.aspx</link><description>Tags: Stateless</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>Parameterised Triggers and Re-Entrant States in Stateless v2</title><link>http://blogs.msdn.com/nblumhardt/archive/2009/08/30/parameterised-triggers-and-re-entrant-states-in-stateless-v2.aspx</link><pubDate>Sun, 30 Aug 2009 04:34:51 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9889032</guid><dc:creator>niblumha</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/nblumhardt/comments/9889032.aspx</comments><wfw:commentRss>http://blogs.msdn.com/nblumhardt/commentrss.aspx?PostID=9889032</wfw:commentRss><description>&lt;p&gt;Since working on a &lt;em&gt;clinical outcomes review system&lt;/em&gt; a couple of years ago, I’ve been aware of the gap between simple hand-coded workflows and the full-blown workflow tools.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://stateless.googlecode.com"&gt;Stateless&lt;/a&gt; embodies the idea that a state machine can use closures to &lt;strong&gt;implement workflow without taking on persistence responsibilities&lt;/strong&gt;. So long as all of the data used to drive the state machine is external to it, a regular ORM or other persistence mechanism can deal with identity, persistence and transactional issues. This substantially reduces the technical complexity of the framework.&lt;/p&gt;  &lt;p&gt;As a ‘fun’ project, I haven’t done much other than maintain the site since the first version was finished. The second version extends the paradigm just a little, but in doing so makes a wider range of scenarios cleanly approachable.&lt;/p&gt;  &lt;p&gt;To illustrate the new features I’ll draw on &lt;a href="http://www.odetocode.com/Articles/460.aspx"&gt;Scott Allen’s nifty bug tracker example&lt;/a&gt; for Windows Workflow.&lt;/p&gt;  &lt;h2&gt;Parameterised Triggers&lt;/h2&gt;  &lt;p&gt;The triggers that drive transitions in a state machine are approximately analogous to events or commands. Like events and commands, triggers can be associated with parameters.&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;When a bug is &lt;em&gt;assigned&lt;/em&gt;, the parameter may be the &lt;em&gt;assignee&lt;/em&gt;; &lt;/li&gt;    &lt;li&gt;When an order is &lt;em&gt;cancelled&lt;/em&gt;, the parameter may be the &lt;em&gt;reason&lt;/em&gt;; &lt;/li&gt;    &lt;li&gt;etc. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Modelling these details in Stateless, I adopted the some design goals and constraints:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Retain the existing simple syntax for non-parameterised triggers; &lt;/li&gt;    &lt;li&gt;Execute parameter-driven logic &lt;em&gt;during&lt;/em&gt; the transition, i.e. &lt;em&gt;after&lt;/em&gt; the exit events for the last state have fired; &lt;/li&gt;    &lt;li&gt;Make it clear to the user exactly when parameter-driven logic will execute; &lt;/li&gt;    &lt;li&gt;Control interference between parameter-driven logic and guard conditions; &lt;/li&gt;    &lt;li&gt;Ensure parameter type-safety at compile time. &lt;/li&gt; &lt;/ol&gt;  &lt;h3&gt;New APIs&lt;/h3&gt;  &lt;p&gt;To associate parameters with a trigger, &lt;em&gt;StateMachine &lt;/em&gt;provides the &lt;em&gt;SetTriggerParameters()&lt;/em&gt; generic methods:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/ParameterisedTriggersandReentrantStatesi_9950/image_6.png"&gt;&lt;img title="image" style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" height="67" alt="image" src="http://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/ParameterisedTriggersandReentrantStatesi_9950/image_thumb_2.png" width="569" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;&lt;em&gt;SetTriggerParameters() &lt;/em&gt;accepts one generic parameter for each of the trigger’s parameters, so in this case the &lt;em&gt;Assign&lt;/em&gt; trigger is being associated with a single parameter of type &lt;em&gt;string&lt;/em&gt;.&lt;/p&gt;  &lt;p&gt;This method is called once, when the state machine is being configured.&lt;/p&gt;  &lt;p&gt;The return value in this case is a &lt;em&gt;TriggerWithParameters&amp;lt;string&amp;gt;&lt;/em&gt; object that lets us invoke the &lt;em&gt;Fire() &lt;/em&gt;method in a strongly-typed way:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/ParameterisedTriggersandReentrantStatesi_9950/image_4.png"&gt;&lt;img title="image" style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" height="28" alt="image" src="http://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/ParameterisedTriggersandReentrantStatesi_9950/image_thumb_1.png" width="388" border="0" /&gt;&lt;/a&gt;The C# compiler will use inference to determine that the parameter to the trigger is of type &lt;em&gt;string&lt;/em&gt;. Attempting to fire &lt;em&gt;assignTrigger&lt;/em&gt; with any other parameters will be rejected at compile-time.&lt;/p&gt;  &lt;p&gt;Now, all of this would be fairly pointless if &lt;em&gt;Fire()&lt;/em&gt; was the only place that the parameters needed checking. However, the firing of the trigger is only half of the story.&lt;/p&gt;  &lt;p&gt;When the machine transitions into the new state, logic based on the trigger parameters will need to run:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/ParameterisedTriggersandReentrantStatesi_9950/image_8.png"&gt;&lt;img title="image" style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" height="62" alt="image" src="http://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/ParameterisedTriggersandReentrantStatesi_9950/image_thumb_3.png" width="544" border="0" /&gt;&lt;/a&gt;Because &lt;em&gt;assignTrigger&lt;/em&gt; is provided to the &lt;em&gt;OnEntryFrom()&lt;/em&gt; method, the compiler knows that the provided entry action accepts a single parameter of type &lt;em&gt;string&lt;/em&gt;.&lt;/p&gt;  &lt;p&gt;Putting everything together behind the facade of a domain object leads to a natural, understandable design:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/ParameterisedTriggersandReentrantStatesi_9950/image_10.png"&gt;&lt;img title="image" style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" height="73" alt="image" src="http://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/ParameterisedTriggersandReentrantStatesi_9950/image_thumb_4.png" width="353" border="0" /&gt;&lt;/a&gt; A more complete example is in the &lt;a href="http://code.google.com/p/stateless/source/browse/#hg/BugTrackerExample"&gt;Stateless Mercurial repository&lt;/a&gt;.&lt;/p&gt;  &lt;h3&gt;Alternatives&lt;/h3&gt;  &lt;p&gt;One alternative I considered but later discarded was to parameterise the &lt;em&gt;states&lt;/em&gt; rather than the triggers, something that seems to be more established in traditional state machine models. After a good deal of unsuccessful experimentation I concluded that state parameterisation isn’t as useful as the trigger-based version.&lt;/p&gt;  &lt;h2&gt;Re-Entrant States&lt;/h2&gt;  &lt;p&gt;Stateless encourages you to attach program logic to &lt;em&gt;entry &lt;/em&gt;and &lt;em&gt;exit &lt;/em&gt;events for the states in your state machine.&lt;/p&gt;  &lt;p&gt;One of the edge cases that the bug tracker example reveals is re-initialisation of an already active state. When the bug is assigned, an email might be sent to the assignee. If &lt;em&gt;Assign() &lt;/em&gt;is called again, to reassign the bug to someone else, it makes sense to re-initialise the &lt;em&gt;Assigned&lt;/em&gt; state by executing the exit actions then executing the entry actions again.&lt;/p&gt;  &lt;p&gt;To enable this behaviour for a state, the &lt;em&gt;PermitReentry() &lt;/em&gt;method is supplied:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/ParameterisedTriggersandReentrantStatesi_9950/image_12.png"&gt;&lt;img title="image" style="border-right: 0px; border-top: 0px; display: block; float: none; margin-left: auto; border-left: 0px; margin-right: auto; border-bottom: 0px" height="82" alt="image" src="http://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/ParameterisedTriggersandReentrantStatesi_9950/image_thumb.png" width="536" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;The previous version of Stateless considered a self-transition to be the same as an ignored trigger. Version 2 requires that self-transitions are either explicitly ignored, or configured as re-entrant.&lt;/p&gt;  &lt;h2&gt;Next?&lt;/h2&gt;  &lt;p&gt;These small additions were actually quite a challenge, but Stateless is still a very small library. One idea I’m toyed with is to use it as a ‘kernel’ for higher-level state machine functionality, e.g. an XML or DSL-driven framework. If you have ideas or requests, feel free to visit the &lt;a href="http://stateless.uservoice.com"&gt;UserVoice forum&lt;/a&gt;!&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9889032" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/nblumhardt/archive/tags/Stateless/default.aspx">Stateless</category></item><item><title>State Machines in Domain Models</title><link>http://blogs.msdn.com/nblumhardt/archive/2009/04/16/state-machines-in-domain-models.aspx</link><pubDate>Thu, 16 Apr 2009 09:52:37 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9552345</guid><dc:creator>niblumha</dc:creator><slash:comments>10</slash:comments><comments>http://blogs.msdn.com/nblumhardt/comments/9552345.aspx</comments><wfw:commentRss>http://blogs.msdn.com/nblumhardt/commentrss.aspx?PostID=9552345</wfw:commentRss><description>&lt;p&gt;I was reminded today of &lt;a href="http://stateless.googlecode.com"&gt;Stateless&lt;/a&gt;, a little project that I’m quite fond of.&lt;/p&gt;  &lt;p&gt;Stateless is a &lt;em&gt;hierarchical state machine framework&lt;/em&gt; based on &lt;a href="http://codeplex.com/simplestatemachine"&gt;Simple State Machine&lt;/a&gt; for &lt;a href="http://boo.codehaus.org"&gt;Boo&lt;/a&gt;, but configured using C# 3.0.&lt;/p&gt;  &lt;p&gt;When I &lt;a href="http://ubik.com.au/article/named/stateless"&gt;announced Stateless last year&lt;/a&gt;, I hardly even explained its purpose, let alone its tongue-in-cheek name. I think I owe it a better start in life!&lt;/p&gt;  &lt;p&gt;If you’re doing heavy duty state-machine based programming (writing parsers, radiotherapy machines or flight control systems) then Stateless is probably not what you’re looking for.&lt;/p&gt;  &lt;p&gt;If you’re doing domain-driven design, and anxious about the ugly nested ‘if’ and ‘switch’ statements building up around _state variables, Stateless can help.&lt;/p&gt;  &lt;p&gt;State-based behaviour is awkward because despite careful programming, it is difficult to see how the states relate to each other. Adding and removing states is error-prone, repetition creeps in, and refactoring gets tricky.&lt;/p&gt;  &lt;p&gt;There’s more than one way out. The &lt;a href="http://en.wikipedia.org/wiki/State_pattern"&gt;State&lt;/a&gt; &lt;a href="http://codebetter.com/blogs/jeremy.miller/archive/2006/04/30/143733.aspx"&gt;pattern&lt;/a&gt; can be one very elegant solution. &lt;/p&gt;  &lt;p&gt;Another solution that works nicely is to create a declarative model of the states, transitions and associated actions, and have a state machine framework ‘run’ it for you. This is the approach enabled by Stateless.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/StateMachinesinDDD_12E24/image_2.png"&gt;&lt;img title="image" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="551" alt="image" src="http://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/StateMachinesinDDD_12E24/image_thumb.png" width="337" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;The Telephone Call state chart is broken down into the following states and triggers:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/StateMachinesinDDD_12E24/image_4.png"&gt;&lt;img title="image" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="351" alt="image" src="http://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/StateMachinesinDDD_12E24/image_thumb_1.png" width="238" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;You can use any types to represent states and triggers, but enumerations are convenient.&lt;/p&gt;  &lt;p&gt;After creating an instance of &lt;em&gt;StateMachine&lt;/em&gt;, each state is configured independently. Configuration for a state revolves around the triggers that the state can accept, the transitions that these triggers will cause (to new states) and the actions that will be performed when entering or leaving a state.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/StateMachinesinDDD_12E24/image_6.png"&gt;&lt;img title="image" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="385" alt="image" src="http://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/StateMachinesinDDD_12E24/image_thumb_2.png" width="546" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Once the state machine has been configured, the triggers can be ‘fired’. The side-effects from firing triggers drive the program.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/StateMachinesinDDD_12E24/image_8.png"&gt;&lt;img title="image" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="46" alt="image" src="http://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/StateMachinesinDDD_12E24/image_thumb_3.png" width="300" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;You might wonder how this fits into a domain model. &lt;em&gt;StateMachine&lt;/em&gt; certainly doesn’t belong on the public surface area of your domain model classes. It’s an implementation detail – like, for example, &lt;em&gt;StringBuilder &lt;/em&gt;or &lt;em&gt;Regex.&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/StateMachinesinDDD_12E24/image_10.png"&gt;&lt;img title="image" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="281" alt="image" src="http://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/StateMachinesinDDD_12E24/image_thumb_4.png" width="438" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Users of the class interact with the state machine indirectly, by calling public methods on the domain object.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/StateMachinesinDDD_12E24/image_12.png"&gt;&lt;img title="image" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="178" alt="image" src="http://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/StateMachinesinDDD_12E24/image_thumb_5.png" width="349" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;The state machine is configured to call two methods when entering and leaving the Connected state (see the configuration above.)&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/StateMachinesinDDD_12E24/image_14.png"&gt;&lt;img title="image" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="197" alt="image" src="http://blogs.msdn.com/blogfiles/nblumhardt/WindowsLiveWriter/StateMachinesinDDD_12E24/image_thumb_6.png" width="452" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Stateless does all of the heavy lifting. For example, the state machine understands that because &lt;em&gt;OnHold&lt;/em&gt; is a sub-state of &lt;em&gt;Connected&lt;/em&gt;, the &lt;em&gt;Connected &lt;/em&gt;entry/exit actions aren’t called when moving &lt;em&gt;between&lt;/em&gt; these two states.&lt;/p&gt;  &lt;p&gt;Now for a justification of the silly name…&lt;/p&gt;  &lt;p&gt;Notice the way that the &lt;em&gt;_state&lt;/em&gt; field belongs to the &lt;em&gt;PhoneCall &lt;/em&gt;object, rather than the state machine? This allows the field to be easily mapped to a database column by NHibernate or your ORM of choice. The state machine reads and writes the &lt;em&gt;_state&lt;/em&gt; value using the pair of lambdas provided to its constructor. In that sense you can &lt;em&gt;almost &lt;/em&gt;say that the state machine itself is ‘stateless’. Almost.&lt;/p&gt;  &lt;p&gt;There’s some more basic documentation and a source download &lt;a href="http://code.google.com/p/stateless/"&gt;at the site&lt;/a&gt;. I hope you’ll try Stateless and be pleasantly surprised by how expressive it can make your code. Search your domain model for “State” or “Status” and see what Stateless can do!&lt;/p&gt;  &lt;p&gt;&lt;em&gt;This post also comes with a challenge: Stateless is fairly simple and very hackable - if you’re a fluent-interface aficionado and think you can improve the configuration API, join the project!&lt;/em&gt;&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9552345" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/nblumhardt/archive/tags/DDD/default.aspx">DDD</category><category domain="http://blogs.msdn.com/nblumhardt/archive/tags/Stateless/default.aspx">Stateless</category></item></channel></rss>