Giter Club home page Giter Club logo

simple-finite-state-machine's Introduction

SFSM - Simple Finite State Machine

build License Maven Central Version Coverage Status

This library allows Kotlin & Java developers to use a simplified (as the name suggests) State Machine model.
This project was inspired by Spring State Machine and is still under development!

You can find this useful if:

  • You are writing a state-based application with a simple Trigger -> Transition logic
  • You can describe the problem you are solving using a basic State Machine diagram.
  • You do not require any advanced Statemachine features like composite states or sub-machines / sub regions.

Defining a State Machine

TL;DR - see examples in statemachine-examples module.

Example:

// Extend StateMachineDefiner
// Pre define all possible State Machine states
override fun defineStates(definer: StatesDefiner<LoginState, LoginTrigger>) {
    definer.apply {
        setInitial(INITIAL_STATE)
        simple(EMAIL_INPUT)
        choice(PASSWORD_INPUT)
        terminal(LOGIN_COMPLETE)
        terminal(LOGIN_FAILED)
    }
}

// Pre define all possible State Machine transitions, including transition Guards and Actions
override fun defineTransitions(definer: TransitionsDefiner<LoginState, LoginTrigger>) {
    definer.apply {
        add(sourceId = INITIAL_STATE, targetId = EMAIL_INPUT, triggerId = BEGIN_LOGIN_FLOW, guard = Guard.ofPredicate { true })
        add(sourceId = EMAIL_INPUT, targetId = PASSWORD_INPUT, triggerId = SEND_EMAIL, guard = emailValidatorGuard)
        add(sourceId = PASSWORD_INPUT, targetId = LOGIN_COMPLETE, triggerId = SEND_PASSWORD, guard = passwordValidatorGuard)
        add(sourceId = PASSWORD_INPUT, targetId = LOGIN_FAILED, triggerId = SEND_PASSWORD, guard = passwordAttemptsExceededGuard)
    }
}

Key Components

The State Machine is made up of a few key components:

  • States
  • Transitions that specify possible transitions between States and are made up of:
    • Source and target state IDs.
    • Triggers - sent to the state machine to possibly transition to the target state, specified by Trigger ID.
    • Guards - in charge of allowing (or preventing) transitioning between states.
    • Actions - which are run before, during or after transitioning between states.
  • S generic type, specifies the ID of a State
  • T generic type, specifies the ID of a Trigger

Each component can be customized to your specific needs.

Create a custom state machine

First, extend the StateMachineDefiner<S, T> class, where S and T specify the ID types of your custom States and Transitions, respectively.

States

Add your own state definitions by overriding the defineStates() method and invoking StatesDefiner methods.

Example:

override fun defineStates(statesDefiner: StatesDefiner<S, T>) {
    statesDefiner.apply {
        setInitial(INITIAL_STATE)
        simple(STATE_A)
        simple(STATE_B)
        setTerminal(SUCCESS_STATE)
        setTerminal(FAILURE_STATE)
    }
}

(Note you must define at least one initial state and one terminal state)

Add your own transitions to the definition by overriding the defineTransitions() method and invoking TransitionsDefiner methods

override fun defineTransitions(definer: TransitionsDefiner<S, T>) {
    definer.apply {
        add(S.INITIAL, S.STATE_A, T.MOVE_TO_A, positiveGuard, SomeActionToPerformOnTransition)
        add(S.STATE_A, S.STATE_B, T.MOVE_TO_B, positiveGuard)
    }
}

Guards

Extends or simply create your own Guards
Example:

class EmailValidatorGuard : Guard<LoginState, LoginTrigger> {
    override fun allow(transitionContext: TransitionContext<LoginState, LoginTrigger>): Boolean {
        val email = (transitionContext.trigger as EmailInputTrigger).email
        return email.matches("^[A-Za-z0-9+_.-]+@[A-Za-z0-9.-]+\$".toRegex()) && mockExistingEmails.contains(email)
    }
}

You can also define a simple guard inline, example:

Guard.ofPredicate { someFunctionThatEvaluatestToTrueOrFalse }

Actions

You have 2 types of actions:

  • TransitionAction runs when transitioning between states, should be attached to a Transition when defining transitions
  • StateAction - entry or exit actions, run when entering or exiting a state

Example:

TransitionAction.create { log.info("A transition has happened") }

How to run a state-machine

val definer = CustomStateMachineDefiner()
val definition = definer.getDefinition()
val factory = DefaultStateMachineFactory()
val sm = factory.createStarted(<state machine id>, definition)
// The State Machine is now running and can be triggered

UML - State Machine Visualization

A Gradle Plugin is available to generate UML visualzations for your defined State machine.

See statemachine-uml-plugin

simple-finite-state-machine's People

Contributors

yonigev avatar

Stargazers

ismemonday avatar  avatar Moriel Veksler avatar

Watchers

 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.