In this post, we're going to take a look at a technique for developers and designers to collaborate, called state diagrams. State diagrams are initially a mathematical concept, but it can also be a handy tool when working within software design and development. But before we dig into how we're interpreting and using this technique, let's have a quick look at our motivation.
Motivation for state diagrams
When developers and designers work together, the most common process is that the designers produce sketches that are delivered to the developers. The developers, in turn (more or less), implement these sketches and produce an application. The sketches show static images of how the UI looks at specific times, given some sequence of events leading up to those screens. The screens can be delivered to a developer in very many different ways, but often they are in a sequence or arranged on a horizontal line so that it reads like a story. But what these sketches usually don't show is how one screen leads to the next.
Most of the time the developer can infer what makes the app go from one screen to the next from what is going on in each screen. However, it’s not always very obvious how everything is supposed to look and work. In the screens above, for instance, there is no loading state. The sample application that we’re using for this post is a simple application for searching images on pixabay. This means that the search will be a network request and that it’s natural to expect some loading time in between the user hitting the search button and the results showing up. Another thing not specified in these screens, and a very common thing to be missing from design sketches, is a possible error screen. We know that something can go wrong here since we’re dealing with data from the internet. This means that we should have some type of screen for when there’s a network error, like a server that’s down, the user not having cell coverage.
Now that we have more complete design sketches we can start implementing, right? We can start implementing this as is, but there are still some uncertainties. For example when we’re in the error state/screen, and the user wants to try again, how would that work? Or if we’re in the search results state and want to search for something else? Does the keyboard appear over the current context when we tap the search field, or do we go back to the list of recent searches? Keeping a mental model of these interactions and transitions can become increasingly complex when the flow of the application starts to become non-linear. These actions and transitions are not specified in the sketches, and it’s often up to the developer to guess what the designer meant.
So can we do better? Is there something we can do to help give more information about how this is supposed to work? Yes, there is! This technique has many different names and can be practised in many ways. Some call it state diagrams, state machines, statecharts, or click diagrams. In this post, we’re using the term state diagram. The main idea is the following: A screen in the application represents a state of the UI. When we are in a given state there are usually one or more actions the user can perform to modify the screen, and possibly transition into another state.
We’ll use a state diagram to visualise our application flow. A circle with text inside represents a state, and a state corresponds to a screen. We draw arrows between states to represent transitions, and some text next to the arrow to tell us which action can trigger this transition. These actions are usually inputted from the user, such as clicks.
Our sample application has the following states: start, searching, loading, search results, and error, each of which corresponds to the screens shown above. We also have a set of possible actions:
Start the search: the user taps the search field.
Cancel: the user taps the cancel button that appears when the search field is active.
Search: the user taps the search button on the keyboard.
Success: the search for images has completed successfully.
Failure: the search for images has failed.
If we dig a little deeper into this diagram we can start to reason about how it all fits together. We’re starting in the start state. Clicking the search field will trigger the start search action, which transitions us into the searching state. From there we have the keyboard visible, which lets the user type. When the user taps the search button on the keyboard we’ll trigger the search action which triggers the transition into the loading state. Entering the loading state fires the network request to pixabay. If the request fails for some reason it fires the failure action and we transition to the error state. If the request is successful it fires the success action, which leads us to the search results screen.
Take a minute to look at the demo above, how the UI transitions from one state to another, and how this corresponds to the states and transitions defined in our state diagram.
Designers and developers are often very task-oriented when they work, and it’s easy to forget to take a step back and look at the bigger picture. Using state diagrams can help ut take that step back, and it’s also a great way for developers and designers to collaborate and speak the same language. It can help us identify points in our application where people have different perceptions about how something is supposed to work and to make sure everybody is on the same page. I strongly believe that the best results come when designers and developers work closely together and enable each other.
It’s worth mentioning is that the visual representation of our states doesn’t necessarily have to look like the notation we used here. Some people prefer using the actual screen designs and drawing the transition arrows from the element that caused the transition. Another alternative is to use wireframes. Two advantages of using our notation is that it’s compact and easy to draw by hand. In the end, it’s up to you to decide how you prefer to work.
One thing that we’ve noticed while working on this app is that it cannot cancel an ongoing search. Say that the loading state is taking a long time, or the user wants to try to search for something else. There’s no way to go back to the searching state from the loading state right now. This begs the question, should this be possible? I think that this illustrates how state diagrams can become very valuable when developers and designers are working together. By using the state diagram when discussing a change like this we can immediately see what consequences it will have in our application. In this case, it means that we should add a transition back to the searching state if the user taps the search field while being in the loading state. Developers can also see that this means that we can cancel the ongoing network request, and probably save the user some data usage. When the number of transitions and state changes increases we see an exponential increase in complexity in an application like this. State diagrams can really help us structure that complexity back into an understandable format.
We’ve seen how state diagrams can help us communicate, structure and validate our applications. We started with a design that looked pretty simple at first, but as we started to dig a little bit into the specifics we could see that there was a lot of hidden complexity and uncertainty in how this was supposed to work.
One thing to note here is that state diagrams will never be a 100% complete representation of how our application works, but I think that it is a big step in the right direction. One of the biggest advantages of using state diagrams is that it gives us a structured way to think about our applications. State diagrams mostly represent the UX side of the application, and that is something that is often overlooked in other visualisation techniques.
By using a state diagram to describe our application we could build a deeper understanding of how the user can influence the UI. We could also see how we had forgotten about a state transition, between loading and searching. Transitions like these are pretty easy to miss, but with the help of our state diagram, we could easily add it and see how it affected our application as a whole. It’s not always the case that adding transitions like these are the right choice, and a state diagram can also be helpful in this regard. When drawing the state diagram we can often find illogical assumptions or ambiguous transitions, since the state diagram forces us to represent our logic visually.
Let's talk to Tech Lead
+47 920 81 737