There are three things that are certain with any software development project:
  1. A complete and consistent set of requirements will not be captured before the design and coding starts.
  2. The requirements will change during the lifetime of the project.
  3. The user interface is more likely to change than any other part of the system.

ember-statecharts has been created to address many of the difficulties of client-side application development. Even with an ambitious framework like Ember.js, client-side application development can get very complex and there are several reasons for this being the case:

  • client-side apps are stateful - client-side apps are a system that allows users to request data from someplace and manipulate it entirely on the user's client device. Application developers' job is to manage the UI-state created by the user interacting with the requested data in their applications and make sure to always display the correct representation of that state to their users.

  • We are building complex reactive systems because the representation of client-side state has to react continuously to internal and external events:

    • Internal events - events triggered by the user like clicks, text input etc.
    • External events - events triggered by the outside like server responses, web-socket push-events or timers firing.
  • Modeling this behavior is very complex if not done explicitly. The usual way to develop client-side applications though is implicit. Developers usually develop code in an ad-hoc fashion by setting properties based on actions on components and other objects that can hold state. This implicit modeling breaks down fast even for medium-level complexity. Components that implement their behavior implicitly are hard to reason about, hard to maintain, and hard to extend. [Horrocks 99]

  • Discussing behavior is very difficult with other stakeholders. There's no shared language between developers, designers, and other stakeholders like product owners. Thus a lot of requirements are left unidentified in the requirements phase of a development iteration - loading-states are often forgotten and nobody on the team really can answer questions about how the application should behave when certain events have happened in the application lifecycle - "What happens when the user loses the server connection during upload?" and similar are questions that come up during development but not before. This leads to frustration on teams and missed deadlines because so much of the implicit requirements have not been accounted for during the planning phase.

Statecharts to the rescue

A way to deal with the difficulties of client-side application development is to use statecharts to model your application's behaviors explicitly:

  • The literature has been conclusive in that dynamic complex behavior is best modeled as a set of states that react to events - statecharts are a way of modeling behavior explicitly in a scalable way even for the most complex behaviors. [Harel 87]
The behavior of a reactive system is really the set of allowed sequences of input and output events, conditions, and actions, perhaps with some additional information such as timing constraints.
  • Statecharts can be modeled explicitly and are executable. Instead of relying on implicit state management, you model behavior as an executable statechart configuration that makes it impossible for your application to behave in unexpected ways.

  • With Statecharts it is easy to understand and change existing behavior. Statecharts are easy to reason about, refine and maintain because states in statecharts can be extended and nested.

  • In addition to explicitly modeling behavior statecharts can be used to visualize modeled behavior and can thus be used to close a gap in client-side application development today where it is hard to discuss application behavior with other stakeholders. Statecharts can be used as an easy-to-understand shared language between stakeholders - designers, product owners, and developers.

  • Statecharts can be used as a modeling tool in the requirements phase, as an implementation tool in the coding phase, and as a debugging and documentation tool in the production phase of your application.

Documenting behavior

Modeling your application behavior explicitly via ember-statecharts will give you documentation of your application behavior for free. Statecharts can be visualized via the XState-visualizer and you will have an easier time understanding components and user-flows by looking at them.

An example of a statechart modeling button behavior in the visualizer

Visualizing statecharts also allows you to communicate about behavior with other stakeholders - designers, product owners, and fellow developers. Because you are modeling behavior explicitly with an executable statechart in your code there is now always up-to-date documentation of how components and other parts of your app behave.

You can step through your behavior with the XState-visualizer and have discussions about how your application behaves based on a visual language that everyone understands.

Powered by XState

ember-statecharts provides a small Ember.js-specific wrapper around the fabulous and widely-used XState-library. All of the powerful features of XState are supported. The purpose of ember-statecharts is to make it easy to use XState in an Ember.js application without having to write the same boilerplate code over and over again.

ember-statecharts vs. ember-concurrency

ember-statecharts is not a contender to ember-concurrency. Both addons can be used in combination. ember-concurrency gives you a clean API to handle async interactions in your code and will handle cleanup when components are destroyed. After modeling the states in your components explicitly for some time you might even come to the conclusion that the reason why ember-concurrency is so great is that it models async interactions explicitly. But async interactions with APIs are not the only complex reactive behavior you will want to model in your applications explicitly. If you want to model a complex sign-up flow for example it might include async interaction with your backend API but you will still want to model the rest of the sign-up flow explicitly and ember-statecharts will help you with that.

Generally speaking ember-statecharts can do all the things ember-concurrency can do, but not the other way around. If you so desire, you can continue using ember-concurrency in combination with ember-statecharts, but you will be surprised how far XState's invoking promises feature will get you.

References

[Harel 87] D. Harel, Statecharts: a visual formalism for complex systems, Science of Computer Programming, Volume 8, Issue 3, June 1987, Pages 231-274

[Horrocks 99] I. Horrocks, Constructing the User Interface with Statecharts, Addison-Wesley, 1999