State of the Art User Interfaces with State Machines
Watch on YouTube (CraftHub Events)
What is this talk about?
As the number of possible states in your app grows, developing UIs can become exponentially more complex. With the help of finite automata, or finite state machines (FSMs), you will be able to manage your app's states in a simple, robust way, and even visualize them! In this session, we will discover how FSMs and statecharts can take your UIs to the next level, with innovative techniques for imple (From the video description.)
“The answer, at least to me, is using finite state machines and statecharts.”
“Looking at our original example, we could model this whole search thing as a state machine instead.”
From the opening of the talk.
Key takeaways
- We need to model the fact that this pairing gives us a pairing of a next state and a declarative set of effects that happen whenever you transition from one state to the next. 5:00
- The answer, at least to me, is using finite state machines and statecharts. 11:00
- One of the things I love about state machines is that software bugs are made visually clear with them. 17:00
- The technique that we would use for this is you would first create an abstract model of your application using these state machines and statecharts. 28:00
- With regard to the actor model, so state machines and actor model go very well together. 35:00
Quoted from the transcript.
Full transcript
From YouTube auto-captions. Punctuation and capitals were restored automatically. Technical terms were normalized; some errors remain. 7,084 words.
0:00 Introduction
All right, hello everyone. I am so excited to be in Budapest. This is the second time I've been to Budapest, the first time was in 2015 for a different conference. But this is my first time at craft Calm and I am so excited to see so many people in a mostly back-end, architecture oriented conference, come to my talk, which is about user interfaces, its front end. But. But I promise you, the techniques and the skills that we're going to learn in this presentation applies to everything. Whether you're doing back-end, front-end programming, it's software modeling, so it's these are very important concepts in general. I was also very surprised to see how many, how many David's I've met so far. Can you raise your name if your name's David? By the way? I'm just okay, never mind me, there's not that many, but that's okay. So my name is David, you know, one of, I guess three, and I work at Microsoft, and at Microsoft we do a lot of things, like regarding user interfaces, back in services.
Just all these parts that connect together. And the more parts you have that communicate with each other, the more complexity you get in. This complexity can exhibit itself in many different ways. So one thing I want to talk about is an incident that happened, I think it was a few months ago. It's the Apple FaceTime bug, and so I don't have an iPhone, I have an Android phone, but this was a pretty serious bug. If you don't know what happened, because I, I didn't know what happened. Ions have an iPhone. What you could do is you could initiate a call with someone on your iPhone, and before they even picked up, you could swipe up. Select a day Participants all right, trains here, I guess you could, you could add yourself as a participant. And then you are able to listen to the other person on the other end through their microphone without them knowing.
And so this was a huge bug that was discovered at Apple, and so a lot of people were thinking, how do these types of bugs exhibit themselves, like, how do they even show up in production? You must believe that Apple might have, like a huge QA team, a big development team where they do so much. Automated testing and integrated testing, and all of that. And so how could serious bugs like this find their way into production? I mean, you could have the best developers, the best QA team in the world. And bugs like this are still able to find their way onto your iPhones, and so the problem is. However, this bug showed up. Like ions have access to the source code, and I don't know if any of you do. But what happened was something happened, which is the microphone turning on in a state that it was not supposed to happen.
And so regardless of how it happened. If we take a look at this from a software modeling perspective, then we could see that we should not be able to turn on the microphone.
3:00 Instead, we need to consider that, given our current state…
Unless we're in the states of we're making a call with that person and that person has already accepted the call. And so let's just look at this complexity in a different way. Let's bring it down to things that you might be used to in your everyday applications, for example, let's say that you wanted to fetch data so you have a button and this button when you click it. You know, you make an API request, in this case the users, and eventually this request comes back with some data. Now, this request might take some time and so you want to show to the user that this is going to take a little bit of time. So you might add some sort of loading indicator until the data is ready, so this works. This is a very common pattern for applications. But if you're like me, you get a little bit impatient. So you start clicking that button a few times and you all know what happens.
A lot of redundant API requests are made, which this is a toll on the server. This costs money when all your user wanted was one request. And so, you know, this happens all the time. One of the simplest solutions that we could do is we could just disable the button so that the user doesn't. You know, click the button. And then eventually you get your data back. But if you're also like me, you still get frustrated, you open the dev tools and you undisciplined, so then you just keep making the requests. So this is why I say that one of the most neglected variables in software development is time. We we tend to consider things in certain states, like what should be in this state, what should happen in this state, but we don't consider what happens between states. Now, if we talk about software like state management models, we typically see this pattern, which, of course you might know, is not really a sufficient pattern.
But whenever an events happens, you have some sort of next state. But we understand that's not entirely the full picture. We have to consider what the current state were in as well. So you have your current state, you have an events that acts on that current state, and then you have a next state. This is the way that we develop most applications, but this is also not sufficient. Instead, we need to consider that, given our current state, in an event that happens. We need to model the fact that this pairing gives us a pairing of a next state and a declarative set of effects that happen whenever you transition from one state to the next. And so this is a model that we're going to work with, and this model gives us a better understanding of how our application works over time and between states. So, that there's many different ways that we could, we could talk about time in our application, and this only adds to the complexity.
For example, we have callbacks, promises, async awaits, and my favorite observe a pulse. These are the many ways that we manage time and manage state changes that happen over time in the application. And typically, you will see applications in software have a mix of all of these. If not some other things, like, you know, you might be dealing with threads and concurrency, or you know, any other things. So let's take a look at this in code just to see how complex it could get. You can imagine this in any framework, in this case, I'm sort of using a React codebase, but you might think of it an Angular View or whatever application framework you're using. So let's say that we have that, that initial example that we had, where you click a button and you're fetching data so simple enough, you know, on. Search, we fetch the data and then we eventually show it. But as we seen before, we need to add a loading state, so typically we would add a loading flag, that loading true.
And then we have to make sure that once we have our data, loading is false. I've seen a few apps where the loading spinner still shows even though the data is there, and so we have to take care of that. But then what if an error happens, right? We have to go back. We have to make sure that we have some sort of error flag if there's an error. But this is also not sufficient. Because what if we want the user to try again, then we have to make sure that we turn the error flag false? Make sure the loading flag is true and just give them the ability to search again. But then also, what if we want to, you know, cancel the search, you know, then we have a lot more complexity if you can't see this all, zoom in for you. But we have just a lot of complexity in the code, and this is typically how our event handler look over time.
I hope that was correct. Hungarian I just so. This is what's known as a bottom-up approach in which we put all of our logic inside of the event handlers. And so I'm sure you could look in your codebase, look in your event handlers and you will see that. We have so much logic happening, and this is where the complexity lies in our applications is because the our application logic is spread throughout all of those event handlers. And so it makes it very difficult to get an idea of what's going on in your application. So this bottom-up code not only is it difficult to test because we don't know exactly where things are happening in the application. So we just have ad hoc code written in each of our event handlers. That writing tests for that becomes very difficult, where you no longer have a separation between the user interface and the application logic, so this also becomes very difficult to understand.
If anyone came up to you and asked, what are the features of the application or how does the application behave, you have to look at all of. These different and that handlers spread after your application, and this means that it's very hard for your code to not have bugs. Because all that complexity means there's infinitely, or not implement, exponentially more ways that the application can be used and exploited to, you know, to have bugs. This also makes applications difficult to enhance. Once you have all of that code within your event handlers, then adding a feature becomes exponentially more complex. Because you have to figure out. Not only am I adding this feature, but this feature might affect other features, but I don't exactly know how it's going to affect those other features. So that becomes a very hard thing to determine. And in fact, features do make it worse because it increases the surface area of complexity in your application.
And remember, this is all because we're using a bottom-up approach, just whenever we need to add a feature, we just go from the bottom up. Wherever we're typing, we put the event logic in there, and the application logic just wherever it lives. And so instead of having one centralized place for our logic, instead we have the logic spread out all over our application. So how can we better model the behavior of user interfaces? And so this is something I've been talking about for a couple years now, the idea of software modeling, and this doesn't just apply to the front-end world. Of course, if you've done game development, or, you know, even back in development, embedded electronics, things like that, then you're familiar with the ideas of software modeling already. It's just in the front ends, we're not really that familiar with that yet. So that's why I'm trying to talk about, you know, how we could better model these user interfaces.
And so the answer, at least to me, is using finite state machines and statecharts. And so how many of you are familiar with a, you know, finite state machines? Hopefully, that should be most of you, which is awesome, and probably fewer with statecharts. So in review, if you, if you don't remember what the finite state machine is, then it's just. It's a mathematical representation of, you know, the flow of states over time. And so we have one initial state, which in this case is I, though we have a finite number of. States in which our application can be in, and so this is just modeling a promise. We have a finite number of events that could either be initiated by the user or within the application, or via external services interacting with that application. Such as fetch, resolve and reject. We have a mapping of state transitions which are triggered by these events, so if we're in the idle state and the fetch event happens now, we're in the pending state.
And then we have a finite number of final states, which, in this case, would be either fulfilled or rejected. So, looking at our original example, we could model this whole search thing as a state machine instead. And so we could see that if our search events was tied to that but inferred, you know, making a fret fetch request. Then, once we're in the searching state, clicking search does nothing, because there's no outgoing transition from the searching state. And so that automatically means that we don't have to disable the button. I mean, we could, and we should, but we know that events will not have an effect once we're in the searching state. So they could click that button this many times as they want. Nothing's going to happen. And we also see we have this retry logic, and this is very clear to show anyone who's even non-technical. So you could show a designer, a stakeholder, your project manager, this diagram and they'll be able to understand the logic of your application.
So how do we do this in code? There's many different ways to do this in. The concepts are actually about the same. In whichever language you use, typically, you could state machines are implemented using switch case statements. But I honestly find that a little bit verbose. And I think that there's a better way to do it, using objects and using dictionaries. How everyone to call it, and mapping states to events to next state. So, for example, let's say we're in the searching state, in the searching state. We could just look up in this object on resolve, like, let's say we get the resolved events. Now we have the next state that we had, and of course, states that are unhandled just aren't on that, on object. And so what this means is that we create. A state machine without using a switch case statement and instead using this object.
And we have a very short, concise way determining what the next state is based on the current state and the events that just occurred. We just look up the current state, finds the event of mapping from that state, and if there is no transition from that events, we stay in the current state. This is an important part of state machines, where if the events unhandled, we stay on the same state.
15:00 Dragging again, doing the same action, drags the days…
So here's an example that I made. It was based on the dribble by Gal Shearer, and it's a fun example. It's called design your weekend, so what you could do is you could delete the weekdays and drag Sunday out. So when I saw this example, I really wanted to make it real, which I was able to do. But I noticed that there was a lot more complexity than I had thought. For example, when you drag over the screen, you'll see here, it starts with a blue rectangle, and that's a selection rectangle. Now, dragging again, doing the same action, drags the days, so it does something different, and then dragging for the third time does something different yet again, where it drags the days. And so trying to code this manually becomes a very complex process. But instead, using a state machine, I'm more able to easily determine what actions should be done, depending on which state I am. So let's say we're in the start state.
We started doing a mouse down and selecting, now we're in the selecting state. And then when our mouse goes up, we're in the selected states. And so from the selected state. If we were to start dragging again now, it's not going to do the selection and it's not going to do the selection. Because we've defined that dragging is supposed to do something different, and now we're in the state of dragging, and as were dragging, we keep transitioning to that same state. And then when we move the mouse up, then if we're over the trashcan, we dispose of those days, so now we're in the disposed state and then from the disposed state. Once we start grabbing one of those days, we could see that, you know, depending on whether we're grabbing or not grabbing.
17:00 States, which is either success or failure
We could stay in the Dispo, say, or just keep grabbing, and so we just go back and forth between those states. So this is a very visual representation of the logic of this application. And so you could imagine that you could use this for, you know, just for implementing the design, programming, yet testing it, and more so. One of the things I love about state machines is that software bugs are made visually clear with them. For example, let's say that we have our application as before, and we want to identify, are we missing any states, are we missing any transitions? In this case, we are in the loading state. They're like, what happens if there's an error? It's very visually clear from this diagram alone that we have no transition from the error state. And so we could add that. But then, either using static analysis or using our eyes, we could see that.
Once we're in the failure state, there's no way to go back. So a designer or a project manager might look at this and say, we need to find a way to go back from the failure state. Over there, this is a core piece of functionality that's missing, and I've actually experienced this in one of the apps I think was on taking a train in Europe. There was an app where you put your credit card information so that you could get a ticket for the train. But it said that my credit card wasn't valid. But then there was no other action, there was no back button, there was no retry button, it just stayed on the screen. So what was the only thing I could do? Close the app and restart it again, try a few more times. It kept rejecting my card. It was just a very frustrating experience, and that's because there was no outgoing transition, no built-in behavior that allowed me to retry.
So you could find these issues in the visual way a lot faster than if you were to do it in code, because in code you don't have these visual diagrams. So you don't have this clear way of looking at your data and your data flow in your application logic flow. So does this scale? State machines actually can become very complex, and there's a sink called state explosion. State and transition explosion, where the more sorry, the more states that you have in your application, the more transitions there are. And it becomes a very, very, very complex to, you know, to visualize all the different states of your application. Thankfully, this was solved a long time ago. Sorry, 1987 by a computer scientist named David Harel. He created a visual formalism for complex systems called statecharts, and statecharts are an extension on state machines. And so in 1987, he wrote this paper describing how statecharts work and possible extensions to the formalism. Since then, statecharts were adopted by UML if some of you are familiar with UML.
But L sort of shoehorn so many other things besides statecharts into there. So statecharts extend state machines, and they solve a lot of the problems that are inherent with state machines in terms of scalability. First of all, you could have actions, and so actions are the important things that actually make your app do things. So, for example, when you're in the idle states, if you enter, you might want to do some sort of action like logging or prefetching resources or telemetry. There's also on exit, where whenever you exit the states you would have an action to. You could also have actions on the transitions, so whenever you search, that might be an action like hitting the API. There's also guards, guards are conditional transitions so that they prevent you from taking a transition if the guard is not met. For example, we could model here that if the query is greater than zero, only then are we allowed to make a search.
There's also the idea of nested states now. In essence, seats are very important for refining the behavior of your application. Because you might say that you know you're in one state, then you go to another safe in another state. But one of those states could have its own set of sub states, for example, let's say that you were modeling yourself as a state machine and you want to wake up in the morning. So you might have be in the states of sleeping, waking up, eating breakfast, but that waking up might have sub states like snooze. The alarm three times like I usually do, roll out of bed, and then the eating. Breakfast might have some sub states - like grabbing the milk, grabbing the cereal, putting the milk in the cereal together. I don't know whether you put the milk first or the cereal first. But that's your own state machine.
I have my own state machine, my own preferences. There's also orthogonality, which is parallel states, which is states that represent that two things might be going on at the same time. And this doesn't introduce non determinism, but instead it's a better way of modeling on just complex states. And I'll show you an example of that soon. And there's also history, which is a very, very useful concept in statecharts, in which if we exit the states and we go to a different state, we could return and go to a remembered states or go to the previous state. That it was in, sort of like, when you're filling out a checkout form and you select card instead of check, but you want to go back to that form, you want to remember your choice, so that's. That's where history is important. So one example of where orthogonal states is good is, let's say that you are designing a text editor in which you could select bold, italic, underline, and all these dates are very distinct from each other.
They're orthogonal, like you could have both old and italic, or bold, italic and underline, or italic and underline. And you see, you have eight different states. If you were to add a different state, like strike through, whether strike through is on or off, then this would multiply to 16, and then 32, then 64. So you see how this becomes very unmanageable very quickly. So with statecharts, there's a different formalism, which is this idea of orthogonality. And so this diagram represents that you could be in a set of states for bold, for italic and for underline, all at the same time. And then this represents, in a nice, concise way, the Cartesian product of all of those different states. Now, unless it states are pretty similar to, instead, of, you know, in to Platini behavior, for example, for success and failure. We could make this more concise, and we could group them together like this.
We could say that we're in this overall search state, and the search state could have two sub. States, which is either success or failure. And so we see when searching is rejected, we go directly to the failure state, and whether we're in the success or failure state.
25:00 Just copy and paste into the visualizer and get a nice…
When we perform a search again, then it bubbles up to the search state, and then we see that we could go directly to searching again. So it's an easy way to group common behaviors now. I created a library awhile ago called XState, and this is for JavaScript or TypeScript. And X8 is a way to author these date charts and state machines either on the web or on Node.js if you're using Node. And it exhibits everything from state machines and statecharts as well, including things like an interpreter, timers, visualization tools, and so much more. And so the beauty about the API, at least I think so, is that this exact same object format that we had. It's exactly the same API as you would use for XState as well. And so the reason that I like having this instead of a big switch statement is because this can be visualized.
All you have to do is copy and paste this into a visualizer. And because it's an object, sorry, because it's an object you could enumerate through all of the possible states, and you could easily visualize all of them. So an example is over here, that's pretty tiny, but you could see that. We have our state machine definition right here, and then we could actually simulate the machine over here. So we could go here and then we could go through each of the states. And so this works with the code that you rights for XState. Just copy and paste into the visualizer and get a nice visual representation of the state machine. This is one of the biggest selling points at Leas for me to state machines, but I do want to talk about a couple other selling points as well.
27:00 You could represent all of the happy paths through these shortest…
I'm not trying to sell anything, but state machines are very useful for integration testing as well. And so the reason why is that we could trace the paths between states, such as, you know, going from. We could use simple paths, we could use shortest path algorithms such as Dijkstra or Bellman-ford. Depending on whether you have weights or not, and. You could represent all of the happy paths through these shortest paths, which are the paths that users are most likely to take through your application. And once you have all of these paths generated, then it becomes very easy to automate the generation of these tests and to write, you know, tests one by one. And so if you use a death per search, then you get what's called simple paths, which are paths without cycles, and you get a lot more paths. And so this is going to test every single edge case in your application, which is very useful but also can generate a lot of tests.
I don't think anyone's ever complained about we have too many tests, but there you go, if you want too many tests, then this is a great way to have too many tests. There's also many other ways of using state machines. So the same way that you use the state machine for your application, you could use it for adaptivity and for analytics. And so the technique that we would use for this is you would first create an abstract model of your application using these state machines and statecharts. You would, you would keep track of analytics through each of the transitions, and you could do this easily just through the you know, through. Whenever you transition from state to state, you record what happens from the user, you identify paths where you can make it easier for the user to go from one state to another. And adapted to their interests. And then you use this analysis that you've gathered in step two for automatically making your application adaptive to the user.
And so this is why when you represent your application, whether it's friend and their back-end, as a state machine. Now you have this idea that you could use weights on these transitions and be able to optimize. Or at least get a visual picture of how your users are using the application. So, for example, I worked on the visual Studio live share team last year. And I added a little state machine inside the you know, visual studio code, and we were able to visualize using the state machine. How many, how many users either join the session or share the session, how many errors were happening during the session sharing? And more. And so this was really useful analytics, you know, using Azure telemetry and Cousteau to to have that analysis. And so you could use analysis of transition to make better informed decisions about your about your application. So let's say we were creating a simple Instagram application. We might notice that users are more likely to go to the camera once they reach the gallery view.
And we could see that from there that going from logging to gallery to camera is a hot path. So instead, we could, we could change the state machine and make it so that they go directly from login to camera. And so this is using those weights and analytics to automatically provide a better user experience. Or, if you want to, you know, decide when to show ads, then you can have scoring based on you know if the user decides to skip ads. Or, you know, go through, you know, actually tap on the ad, then we could score, you know whether or not they tap on the ad, and we could better decide when to want to show the ads. And so with this, you could also use decision trees within your state machines and statecharts to better understand how to make decisions within the app. On, for example, when to show the ad. Because every user is different and we have all this information from our users, we could use that information to create automatic decision trees.
Which if you've done some reinforcement learning or some machine learning, you might be familiar with. And use that data to better, better adapt the application to the user. Or at least to you, because you're the one showing the ads and the users don't want to see the ads anyway, so anyway. So this limits the amount of code that you have to write for creating these transitions or for having these analytics to one spot. So in XState, there's this interpret function where you could interpret the machine and actually have it running, which just shows all of the application logic. And so in this, there's an on transition handler, which is just a way of listening whenever any state transition happens. So now telemetry is limited to just writing it in one single area. I don't know about you, but I've. Been used to having to write telemetry everywhere, like every single method in the class and every single place where I need to collect telemetry.
It's a lot better to write it just in one place. Where you provide the target, the source, which is which state you came from. The events which, of course, you should sanitize to remove any personally identifying user information in the time stamp which shows when the events occurred. And so all of this. These analytics are useful for determining which paths you should test and which paths are the most common paths in the application that your users would take. And so you could have a very visual representation of that. So that this brings just so many different possibilities to adapting state machines and statecharts in a way that's more than just a different way of coding. Now, because of analytics, and because of all these weights, we could even introduce reinforcement learning into our application, in which the environments are the agent learns the environment, which is the behaviors of our user. And so we could better predict how users are going to use the app, which means no more A/B tests.
We don't need to manually decide how's this user going to use this. Maybe they'll use it this way, maybe a little, use it the other way. Instead, we could just leave that to reinforcement learning and other machine learning techniques. And this is all because we have a very well structured set of data that we could work with because of these analytics, and so we could take these analytics. Feed it to Google analytics, MixPanel, Segment, IO, whatever you want to use. I should probably mention Microsoft because I worked there, but I don't know. Don't worry, it's not really the most common analytics platform. And then you could, you could feed these analytics back to the application. And, long story short, just make better applications and better user experiences for the users using your apps. So some examples of where XState was used a vault project. I, Oh, if you're familiar with that, by a hatchet Corp.
It. This is a very dynamic tutorial view, where as the user is going through the application and doing everything.
35:00 What you create an XState to SC XML and be able…
Then they could click on any one of these and have very personalized guided. Steps on how they would use certain features, and so this is using XState and statecharts. And it's done in a very declarative way. So that if the documentation or if any of the processes change, it's very easy to just update the state machine. Instead of having to go through the code and seeing what changed. There's many other examples of XState and youths especially. Service work ease, which is a fantastic game, and I recommend you play if you want to learn more about service workers. It was also mentioned to that Chrome Dev summit last year. With regard to the actor model, so state machines and actor model go very well together. And it's also in a couple other places like Gatsby, React training, many, many other places, which I'm not even allowed to talk about. But long story short, state machines and say charts are useful in a wide variety of applications.
Also, X8 works with the Dev tools as well, so whether you're using XState and View, React, Angular, whatever you could, you can visualize the state through these Dev tools as well. And this is because of the declarative nature of XState in the way that X8 works in a very similar way to Redux or NGR X, where you have a state in an event and then you get the next state and those declarative actions as well. So this might be as if I'm talking about the future of states, but we have to realize that this, these ideas are absolutely nothing new. So state machines date back from, I'm gonna say, the 1940s, 1950s, even so more than half a century old, and statecharts date back to 1987. And we're just using these ideas and bringing them to life. In today's applications. There's a standard called SC XML, which was drafted and released September 2015, so this has been around for a while and this is a standard for authoring these day charts.
And they're used in programs such as QT and YAK induced HR tools. And these work with other languages such as C++, Java, and even things like Python and TypeScript as well. And so this just provides a very universal way of authoring your statecharts. And X8 is also compatible with SC XML, so in the future you'll be able to convert. What you create an XState to SC XML and be able to use it in these tools, which have been used by many industries for many years.
38:00 With statecharts, even though it might not make sense for simple…
So there's many advantages of using statecharts, of course. One my favorite is from the auto from the Curiosity Rover, in which Mars sent this 2 billion dollar Mars rover over to Mars in. It landed successfully. Can you imagine how much testing had to go to do that? Can you imagine if you had one chance to deploy something? And if you messed up, it costs two billion dollars, you know, just imagine that. So, a lot of the advantages that they mentioned was visualize modeling these precise diagrams, where they knew exactly how states transition to other states. Code generation, which is a really interesting idea. You take these statecharts and you're able to generate code from them. Which is a way of saying that your developers don't need to develop directly. And, of course, it's an optional thing, a lot of test coverage, and you also have an accommodation of late-breaking requirement changes. So if things change, it's easy to go back in the diagram and actually see how things might potentially change.
If you were to add a new feature, remove a feature, change some requirements. Of course, there's disadvantages to. Statecharts are a big learning curve, state machines not so much, but statecharts definitely. There's a lot more to learn. Modeling does require planning ahead. So you have to get rid of this old notion of we're just going to start coding. And instead take a pencil, take paper, start drawing out your diagrams and start planning. And, of course, not everything can be modeled concisely in the statechart just yet, and that's why you wouldn't model. Sum up your things in, say, charts, like the overall abstract picture of your application, or maybe the individual parts, and just push everything else to the side, but have most of the things modeled as a statechart? There's also complexity trade-offs, too, with finite state machines. It's very simple to start, but it grows in complexity, as we've seen really quickly.
The bottom-up method that we're used to doing is just a linearly increasing complexity. But with statecharts, even though it might not make sense for simple applications, statecharts eventually. Pay off over time, the more complex your application gets. One of my favorite resources for statecharts, if you want to learn more, is the world of statecharts, which is at statecharts. Ajillo and so all of this to say is that I want to make your code do more than just managing states. More than just managing your application logic, but being able to visualize, analyze, simulates, tests and more with your applications. So thank you so much, crap to come for having me [Applause] and question that thing.
41:00 Redux and flux and all of that is half of the…
There says, we have four minutes to answer questions, are you good with that? Yeah, probably. Let's obey it. It's raining outside, door wants to go anywhere anyway. The first question we have up on here is from Artur. Is the framework able to detect issues with the model automatically, I.e. deadlocks? So that's coming soon. Right now, the model is for abstracting and actually like creating the model. But in the future, there's going to be tools for analytics. The great thing about C machines and say chars, it's. It's able to detect cycles, to detect like the halting problem, and to detect deadlocks as well. So these things are possible. They're just not in there yet. Fantastic, Anonymous says. Could you please describe how X take could improve existing applications using other state management efforts? WK is like Redux, yes, so XE works pretty much the same as Redux, and so it works in conjunction with either Redux or Mob X, or NGR X or NG XS.
Because at its core, XState is just a transition function. Where you give it the current state, you give it an event, and it gives you the next state. Plus a declarative set of actions. And so it improves this through many different ways. Have you seen test generation visualization and able to more clearly understand the overall model of your application? Yeah, Chakra, I think, says. What tools do you recommend use for designing state machines and possibly generate code? Sorry, if you go to statechart stock, GitHub I o /XState - Vis I know that's a long URL, just Google XState. And you'll see the visualizer over there, then that's one visualizer you could use. Funny enough. You could also use tools like plants, UML for designing these state. Machines and more, more tools are coming in the future. David, not me, says he's Redux, slash, flux. Not somehow exactly this state machine like handling about patience, state on steroids.
Oh okay. So this is a good question. Is it not somehow exactly like this damn machine handling? Okay, Redux and flux and all of that is half of the state machine, and here's what I mean by that Redux and flux. Allow you to. You have a state, you have an events, you get in next states, however, finite state machines, the key word is finite. We have very specific number of states that the application can be in, in very specific arrows or transitions between those states. Those are two important things that Redux and Flux patterns are missing. Because they just say, oh, you could go to any state from any state, and there's no way to predict which state you're going to go to. So if you were to ask, like, what are all the possible states in my application? Then that becomes very difficult with Redux? But very simple with something like a proper state machine pattern like XState cool.
And I think this will be our last one. Anonymous again very active on the slide. I would use any routine beside XState. Or you include routing as states are very good questions, so if you think about routes in the application, those are essentially state machines. So you have one state going to another state. And if you use XState just as a transition function, where it's just I'm given this date and the user clicks this link. Now, what's the next day that I go to? Or, like, what's the next in the wizard? Like a wizard form that I go to? Then? Then, yeah, you could definitely use XState with routing, and you could use it with routing libraries as well, it would just be XState. Would be the one to tell you what is the next route you have to go to? Wonderful, warm round of applause for David again, please. [Applause].
Related talks
-
XState: Making Application Logic Visually Collaborative
Norfolk Developers meetup, 2021. 44:05, 1.2K views -
State of the Art Web User Interfaces with State Machines
Codegram channel, 2018. 37:35 -
Simplifying Complex UIs with Finite Automata & Statecharts
JSConf Iceland 2018. 34:28, 20K views -
Making Application Logic Visually Collaborative (Infobip Shift)
Infobip Shift 2021. 27:18