Git Product home page Git Product logo

fsm.net's Introduction

FSM.NET

A simple "stateless" finite-state machine library for .NET, written in F#.

Now available through NuGet!

Quick start

C# example

(See also the Samples folder)

// Example does not include error handling.

// using TrueWill.Fsm;

// Could load text from database, configuration, etc.
string transitionTableText =
    @"
    # Turnstile

    Locked   | coin | Unlocked
    Unlocked | coin | Unlocked
    Unlocked | pass | Locked";

var transitions = TransitionTableParser.Parse(transitionTableText);

var fsm = new StateMachine(transitions);

string currentState = fsm.InitialState;
Console.WriteLine("Initial state: " + currentState);

IEnumerable<string> availableEvents =
    fsm.GetAvailableEvents(currentState);

// Typically a user would make a selection.
string selectedEvent = availableEvents.First();

Console.WriteLine("Selected event: " + selectedEvent);

currentState = fsm.GetNewState(currentState, selectedEvent);

Console.WriteLine("New state: " + currentState);
// Repeat.

// fsm.States is also available.

F# example

// Example does not include error handling.

open TrueWill.Fsm

// Could load text from database, configuration, etc.
let transitionTableText =
    """
    # Turnstile

    Locked   | coin | Unlocked
    Unlocked | coin | Unlocked
    Unlocked | pass | Locked
    """

let transitions = Parser.parse transitionTableText

Validator.validate transitions

let currentState = Fsm.getInitialState transitions

printfn "Initial state: %s" currentState

// Partially apply these functions to store the transitions.
let getAvailableEvents = Fsm.getAvailableEvents transitions
let getNewState = Fsm.getNewState transitions

let availableEvents = getAvailableEvents currentState

// Typically a user would make a selection.
let selectedEvent = Seq.head availableEvents

printfn "Selected event: %s" selectedEvent

let newState = getNewState currentState selectedEvent

printfn "New state: %s" newState
// Repeat.

// Fsm.getStates is also available.

Origin/Credits

I was reading Agile Principles, Patterns, and Practices in C# by Robert C. Martin and Micah Martin, and fixated on Uncle Bob's State Machine Compiler (SMC). That reads a state transition table and generates C++ code.

I wanted to write a functional library that would do the same - read a textual DSL (domain-specific language) that defined a state transition table, and create a Semantic Model (Fowler).

I borrowed parsing techniques from Fowler's book (see above link).

This project also is helping me to learn F#. :)

Keith Dahlby provided help and encouragement.

Build

Visual Studio 2012, targeting .NET 4.0 under Windows. It doesn't need 4.5 features, and I don't want to restrict its use to Windows 7+.

The assembly should be CLS-compliant, and it should be natural to call from C# (to give it the widest possible audience). There are unit tests in both F# and C# to insure this.

I would prefer to avoid adding dependencies on other libraries to the core library. (The tests depend on xUnit.net, FsUnit, etc.)

Thread Safety

All public types, methods, and functions should be thread safe.

I make no warranties.

If you find anything that is not thread safe, please open an issue.

State Transition Tables

Format

CurrentState|triggeringEvent|NewState

One per line.
The first state of the first line is the initial state.

Anything following a '#' is ignored (a comment). Blank lines are ignored.

Whitespace surrounding states and events is ignored, so you can line up delimiters if you prefer.

States and events are composed of letters, digits, and underscores, and may contain embedded spaces. They must start and end with a letter, digit, or underscore.

States may not differ only by case; neither may events.

By default, FSM will raise an exception if an event is received that isn't defined on the current state. If you want to ignore the event instead, define a transition for the event where the current state and the new state are the same.

Example

Locked|coin|Unlocked
Unlocked|coin|Unlocked
Unlocked|pass|Locked

Philosophy

This is a solution in search of a problem. That's not a good thing. Dogfooding will almost certainly improve the design.

The idea is that a web service would reference FSM. The state transition tables could be provided by callers, loaded from a data store, stored in configuration - it doesn't matter. The callers would be responsible for storing their current state, and would pass it to the service.

Say I have a simple workflow, defined in a state machine.

  1. Ask the service for the initial state
  2. Ask the service for the available events
  3. Display the available events to the user
  4. User makes selection
  5. Ask the service for the new state, given the old state and the event
  6. Repeat from #2

You'd want to combine this with a data store and security.

(See the Samples folder for an example of this.)

FSM machines are designed to be deserialized from text. This constraint makes it difficult to support actions or guards (behavior/code). While there are options (such as Roslyn), these would provide limited benefit without associating data with the state machine and supporting calling custom assemblies. It's a slippery slope that can lead to reinventing Windows Workflow Foundation. What's more, there are other libraries that already provide some of these features as internal DSLs (fluent interfaces, etc.).

I do not want to make FSM complicated. If you want to fork the project and add the ability to run custom code on transitions, feel free, but I probably won't accept that pull request. In particular, I want the DSL to be self-contained, without requiring binary references. (I'm willing to listen to ideas, though!)

Notes

The validate function may evaluate the transitions sequence multiple times. Since the parse function and the StateMachine constructor both do toList internally, this is not an issue in typical use.

Release notes

  • 1.0.0 Initial stable release
  • 2.0.0 Breaking change for F# clients - moved transitions to first parameter on several methods for partial application. This allows F# clients to store the transitions along with the function. Moved validation from parser to validator. F# clients will want to call the validator manually; C# clients will not be affected, except that some exceptions formerly thrown by the parser will now be thrown by the constructor of the state machine.
  • 2.0.1 Supports embedded spaces in states and events; improved validation.

To Do

  • Improved documentation (XML comments, exception thrown, etc.)
  • Psake build script?

Finally, I'm very new to Git and GitHub, so please be patient with me.

Thanks,
Bill

fsm.net's People

Contributors

truewill avatar

Watchers

Keith Dahlby avatar James Cloos avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.