How to define parallel states?


#1

Is it possible to define/manage parallel states inside the spec ?


#2

Not yet, though we’re considering it.

Would parallel states be useful to you even without transition guards and data?


#3

Yes it will be useful because when I want to model complex states inside my app parallel states will help me a lot


#4

I would also find this useful. I’ve been using sketch.system in conjunctions with xstate. At the moment I have to manage multiple sketches for parallel states, instead of having everything in one place.


#5

If I design states for a minimal app, I will have states like {paid, in stock, not sent} or {not paid, not in stock, not sent} and I can make these multiple events as one like ‘paid_in_stock_not_sent’ and ‘not_paid_not_in_stock_not_sent’ but I will multiply the number of states for nothing. That’s the difference between a toy system and a professional one.


#6

Hey Adrien—Not sure I understand exactly, do you have an example sketch we could take a look at?


#7

Hi Ryan,

you have two ways to model complex states. Let me take an example with a (simple) complex state made of a payment, fulfilment and delivery noted {payment, fulfilment, delivery}.

Option 1 (complicated to model and work with)
You model your complex state as a concatenated big piece

  • payment_not_done_fulfilment_not_done_delivery_not_done
  • payment_done_fulfilment_not_done_delivery_not_done
  • payment_done_fulfilment_done_delivery_not_done
  • payment_done_fulfilment_done_delivery_done

Now my question is “What happens if fulfilment needs to be done before payment?”, you need to add a bunch of new states and it will be super complex to read and your interface will have a multiplication of identical code for each part of the state.

  • payment_not_done_fulfilment_done_delivery_not_done
  • payment_not_done_fulfilment_done_delivery_done

Option 2 (Simpler to work with)
You model your complex state as a collection of individual states

  • payment: [not_done, done]
  • fulfilment: [not_done, done]
  • delivery: [not_done, done]

Now you have it all, each part of the interface is independent and you can model it simply. Here comes my question again “What happens if fulfilment needs to be done before payment?”, then you do
{not_done, done, whatever } and you are done. :grinning:

The implication is that the visualisation on the top right of Sketch needs to be accepting two or more blue parts to model for a complex state.

Is that a bit clearer?

Adrien


#8

Looks like I killed the conversation… :frowning:


#9

Hey Adrien—You didn’t. :slight_smile: Kevin’s kicking around an implementation of parallel states that may help your use case. He’ll announce it here on the forum when it’s ready, so stay tuned.


#10

Awesome! :yum: Will be testing it straight away.

Thanks


#11

@Adrien, @elijah-schow, and @jeremyfourna — I’m implementing parallel states and working through some of the tricker parts right now.

Before deploying, I’m curious to get ya’lls opinion on two things:

  1. Syntax for specifying parallel states. I have something in mind, but would like to hear about what ya’ll think first so we can have some discussion before committing to one. E.g., should it be a prefix/suffix in the name? Some annotation indented within the state? etc.

  2. Parallel states can lead to unclear semantics. For example:

ParallelParent
  C1
    foo -> A
  C2
    foo -> B
A
B

When C1 and C2 are simultaniously active and the “foo” event shows up, where does the statechart end up?
Or is this kind of configuration an error in the first place and should be disallowed?

There are lots of situations like this, and I’m curious to hear if ya’ll have any other examples or thoughts.

Thanks!


#12

To me C1 and C2 are independent.
If C1 is active and foo happens then A disregarding C2.
If C2 is active and foo happens then B disregarding C1.

That’s what I meant by “The implication is that the visualisation on the top right of Sketch needs to be accepting two or more blue parts to model for a complex state.”

Currently, I describe how to go from a state to another. All the rules for active states are active as well. So the syntax should not be different. If I take the boring shipment example again.

Payment
    Money_out*
    Banked
    Paid -> Banked
Fulfilment
    Undone*
    Wrapped
    Packed -> Wrapped
Delivery
    Stalled*
    Shipped
    Sent -> Shipped

Right now the * 2 and 3 are ignored so the state is {Money_out} when it should be {Money_out, Undone, Stalled}. It allows thinking of 3 parts of the interface independently without to make different sketches. Because, you can ship before you pay, or send before you packed (and that’s wrong) even if you didn’t think of it beforehand. It makes a more robust interface.

I have another use case, but that may be a bit more advanced and not everybody would need it, although it should not be massively different.

  A*
      Parallel_Action -> B
      Parallel_Action -> C
  B
  C

On Parallel_Action state goes from {A} to {B, C}

Here you got another too long post.


#13

The implicit root state of the statechart is a regular state, a disjunction where exactly 1 child is active.
If we discard this rule (i.e., follow both transitions from C1 and C2 to make both A and B to be active), then we would no longer be in the realm of statecharts as defined by Harel in his original paper.

I’m not saying that statecharts are the best way to model every system, but for the purposes of sketch.systems I think it’d be best to stay with that well studied notation rather than inventing our own semantics — there are several books about statecharts, a good SCXML reference spec for implementors, visual modeling tools, etc.

Do you have suggestions about the parallel state situation I brought up that work within the existing statechart semantics?

One option could be to transition to “A” because that transition occurs first in the textual order (the approach SCXML takes)?
Another option would be to reject the spec for being ambiguous.


#14

I’ll be honest, I won’t take the time to read the hundreds of pages you referenced, my job is elsewhere.

Let me just say this: “SQL” is a well known semantic, but every single vendor have its own “dialect” of it with extensions for unique functionalities that the standardisation body didn’t think of. The semantic you have doesn’t allow any 1 to many (state or transition) so no, this semantic doesn’t work unless you build crazy “option 1” states like described in an earlier post.

I understand you want to follow strictly the standard because it is easier. Fine with me, no hard feeling, I’ll continue with my own tools in order to build systems that can have complex states. They are not as rich but they are easy to work with. I guess I’ll need to work on a visualisation.
I’ll check this space every now and then to see how you guys progress.

Have a nice time.


#15

I would also find this feature incredibly useful.

Here’s a simplified use case of a Control Panel, where I’d like to represent in parallel what is ‘Sorted by’ and how much is ‘Zoomed’. In this case I’d like to be able to identify Sort and Zoom as ‘parallel states’, so that their child states can be active side by side.

I could imagine representing this by prefixing the parallel states with a special character, for example:

Control Panel
  &Sort
    Sorted by Date
      sort by title -> Sorted by Title
    Sorted by Title
      sort by date -> Sorted by Date
  &Zoom
    Zoomed In
      zoom out -> Zoomed Out
    Zoomed Out
     zoom in -> Zoomed In

This particular use case doesn’t directly clarify your 2nd point @kevin, but if I imagine that defining transitions by the same event foo in multiple parallel states just shouldn’t be allowed. In my eyes the following should throw a spec error:

Control Panel
  &Sort
    foo -> A
    Sorted by Date
      sort by title -> Sorted by Title
    Sorted by Title
      sort by date -> Sorted by Date
  &Zoom
    foo -> B
    Zoomed In
      zoom out -> Zoomed Out
    Zoomed Out
     zoom in -> Zoomed In
  A
  B

#16

Thanks for the feedback!

If I’m reading your idea correctly, it looks like you are annotating the parallel children (rather than the parent).

I.e.,

Control Panel
  &Sort
  &Zoom

both sort and zoom are active at the same time.
What happens when there’s a third sibling that doesn’t have the prefix?

Control Panel
  &Sort
  &Zoom
  Other

?


#17

Yes, by annotating &Sort and &Zoom I indicate that they are a group of sibling states which can be active in parallel.

This group ‘tagged’ by & (let’s say &Group) would behave similar to a ‘regular’ state (like Other), in a way that only one of &Group and Other can be active at a time.

I could also imagine a situation where you have multiple parallel groups like such (using && to indicate a separate parallel group):

Control Panel
  &Sort
  &Zoom
  Other
  &&Video Playback
  &&Language Selection

This spec would mean that at one moment Control Panel can be in 1 of 3 (mutually exclusive) states:

  • &Group
  • Other
  • &&Group

When in &Group, both &Sort and &Zoom can be active.
When in &&Group, both &&Video Playback and &&Language Selection can be active.

(perhaps a further specification I might like to be able to add is whether &Sort and &Zoom NEED to be both active, but perhaps I’m getting ahead of myself and it can just be written out as the behaviour of this system without it becoming a specified constraint supported by syntax)

Would this break down anywhere?


#18

So the number of ampersands in the prefix implicitly defines a grouping.

Given that the spec already uses indentation for grouping, why not make those groups explicit:

Control Panel
  &Group
    Sort
    Zoom
  Other
  &Other Group
    Video Playback
    Language Selection

The tradeoff of this is that there’s a bit more typing, of course, but it seems clearer and easier to teach. (Children are indented below parents; only one child of a parent can be active, unless the parent has an ampersand, in which case all of its children are active in parallel)


#19

Update on this topic: we’ve just added in provisional support for parallel states!

To get started:

Thanks for all the feedback on parallel states so far. Give it a dry run and let us know what you think.


#20

This is a great feature, I’m finding this to be an incredibly useful tool and I’m learning a lot by reading the notes and material around it.
One thing I wondered, would it be possible to implement a way of making a transition cause multiple parallel state changes (…something like “Click Menu Button A -> Section_A + Menu_Hide”), or is this inadvisable or better represented in another way?