Pure UI Control

  • Teams improved at building complex UIs by changing the way they represented and communicated about them.
  • Unexpected behavior arises because teams struggle to represent an interface’s desired behavior.
  • By adopting the idea of control state, teams can gain a powerful way to represent a UI’s interactions and prevent unexpected behavior.

Understanding display states with Pure UI

In his wonderful essay Pure UI, Guillermo Rauch described how the React programming model changed his collaboration with designers. The major change is a focus on explicitly describing display states. The designer creates an artboard with side-by-side designs of each of the widget’s states. The React code similarly branches on those same states. There is a close correspondence between between each design on the artboard and the code in the render method. More importantly, the shared language of states means that when the developer discovers a new possible case, it has a natural place on the design artboard and requires only one new bit of thought from both design and development.

  • Different states of the application can be viewed only one at a time, and require careful manipulation to reach.
  • There is no explicit list of possible states.
  • There’s no easy way to see all the states at once, so it’s difficult to hold the interface as a whole in your head.
  • Without an explicit list of states, it’s easy to incorrectly judge progress if the default state looks finished.
  • When developers discover a new state, it doesn’t have a natural place in the design document, so often isn’t designed at all.
  • Adding a new design element to the interface becomes progressively harder because every transition method needs to consider whether it should show, hide, or make changes to every element.
  • Look for a missing idea not explicitly reflected in the problem’s current representation.
  • Find a new representation that makes that idea explicit and helps us represent what we know and what we still need to think through.
  • Then, only at the end, worry about the technology and process to use to bring this representation to life.

The problem of unexpected behavior

For as long as I’ve built interfaces, regardless of the technology or testing plan, we’ve found unexpected behavior in production. Nothing obvious, certainly nothing that anyone would have written a user story about.

  • The credit card validation widget stops working if you enter half of a card number, switch to another screen in the application, do something there, and then switch back to the payment screen.
  • If you’re in the middle of editing one object, click a button to load data about another, and if the timing of the response is just right, your edits may be saved to the wrong one. Or lost forever.
  • First they implement an action for the digits. A simple implementation just multiplies the existing value by 10 and adds the new digit.
  • Next they implement the decimal action. This doesn’t immediately change the numerical value but does need to show up on the display. So perhaps they add a new decimalPressed flag to the state. It’s set to true when decimal is pressed, and it causes the decimal point to show on the display even if the current value is integral. After this, the sequence of actions 2 0 . correctly shows 20. on the display.
  • Ah, but now a problem. When the decimalPressed flag is set to true, the existing handler for typing a digit is wrong. So any action that changes the number needs to check the flag. Oh, and any action that means we’re starting to type a new number needs to remember to set it back to false. Well, unless we pressed decimal right before the digit, then it should stay true. …
  • Adding new actions becomes progressively harder because they may need to react to arbitrary previous actions or influence arbitrary future ones. It’s not clear which combinations you need to consider, or when you’re done.
  • The nested conditions in the code don’t clearly match to any other representation, so code itself becomes the definition of correctness. It becomes difficult for designers, or anyone else, to have opinions about what should happen in any particular case.
  • There’s no way to know if you’re done. Unit tests can cover cases you think about. But there are infinite possible orderings of events, so can they cover everything?

Data state & control state

I think the idea we’re missing is an application’s control states. Previously we enumerated all of an interface’s display states as all the meaningfully different ways it should display. A control state is all the possible states of the interface that have different sets of allowed interactions. Sometimes the two layers of states align, as in a loading state that displays a spinner and ignores all user input. In other cases, an interface’s display state can remain the same even while it’s control state changes.

The high-level statechart for the calculator application. © Addison Wessley. From Ian Horrocks’ “Constructing the User Interface with Statecharts”, p215.

Summary

Over the past few years, web teams have adopted new state-centric representations for their design work. These representations made it easier to think about what an interface should look like depending on data and user context.

Any questions?

The calculator is a simple example: does this approach scale to larger interfaces? With simple state machines, things quickly grow too complicated. But a more powerful formalism, statecharts, can model more complex systems by allowing them to be decomposed into hierarchies (just like components, hmm…) and to represent several charts that can proceed concurrently with one another. Statecharts are a common method for modeling complex embedded software that has many more inputs, and less room for error, than our interfaces.

Notes

  • I am very thankful to Kevin Lynagh, who started bugging me about the idea of using statecharts in UI development almost three years ago. Despite my slow uptake, he kept raising the topic until I saw its value.
  • The calculator example and the statechart for its behavior come from Ian Horrocks’ book Constructing the User Interface with Statecharts. The book was written in 1999, but his complaints about the poor technical design and confusing behavior of most UIs read like a complaint about web development in 2017. I hope we can improve before another 18 years pass.
  • The idea of focusing on how teams communicate and represent their work came from a happy coincidence. I reread “Pure UI”, for which I am very grateful to Guillermo, at the same time that I was reading Edwin Hutchins’ Cognition in the Wild. Hutchins’ book is a critique of traditional cognitive science, arguing that humans mostly don’t use their critical thinking skills to solve problems. Instead, we adopt tools and representations that allow groups of people to solve what would be very complex cognitive problems with fairly minimal use of abstract reasoning. That critique could easily be pointed to normal discussion of programming. We praise the individual who by sheer force of thought arrives at a full understanding of a topic. But often all that effort would be avoidable with a good architecture diagram. I saw that the effect of Pure UI was to replace what had been a large amount of abstract thought with a more convenient representation. This led naturally to the question: what representation would help us understand behavior?

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Adam Solove

Adam Solove

Building the web. Everything should be faster.