David Khourshid - Infinitely Better UIs with Finite Automata

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments

2 years ago when I started working with react/redux a senior backend software developer always went on about how state machines are bad, to be honest I never really read the theory on state machines & why they might be bad. learned a lot from this and subsequent reading

👍︎︎ 13 👤︎︎ u/cynicalreason 📅︎︎ Oct 20 2017 🗫︎ replies

Interesting talk. What about, say, text inputs? Must you then define an infinite number of possible transitions? It's a pretty fundamental use case, but it never came up.

👍︎︎ 1 👤︎︎ u/SoInsightful 📅︎︎ Oct 20 2017 🗫︎ replies

This is really cool!

👍︎︎ 1 👤︎︎ u/gonorthjohnny 📅︎︎ Oct 21 2017 🗫︎ replies
Captions
thank you so show of hands how many of you think that developing user interfaces is actually easy alright so no one's hands got up maybe one or two but the truth is we all know that developing user interfaces is not easy in fact it's pretty difficult and you know working at Microsoft I completely understand this developing user interfaces is a lot more complex than we give it credit for especially as a you know if you talk to back in engineers they might think of the front end as just something that oh we'll just you know throw some CSS on there which you know makes problems worse but developing user interfaces comes with a lot of problems on their own and these could usually be traced down to the behavior of app state and app actions even for simple apps where you have two states downloading or paused and of course you know it doesn't exactly work and sometimes we just assume that the user is going to follow our direct needs exactly so it's sort of a two sided problem first we trust the user and the user trusts us right we think that the user is going to take the easiest way and the most happy pathway through our path or through our app but that's usually never the case and so today I want to talk to you about an idea that's an extremely important idea because it's been around for a long time it's not an original idea and it's used in so many different applications such as software embedded hardware electronics things that keep you alive even and it's called deterministic finite automata or finite state machines so I really pull a while ago and I asked how many people are actually familiar with finite state machines or use them in design and developments most of you said no some of you are familiar with it and a very small percentage of you actually use it in code which is pretty awesome because many years ago we actually are not week as I was dead well I was not born yet but uh we software developers use state machines in order to develop applications and this concept can be extended to user interfaces as well so I want to explain in very easy terms what a finite state machine is and so if you go on Wikipedia you're going to see this definition of the mathematical model of a deterministic finite state machine my favorite part is this it explains that a finite state machine is a quintuple and alright if you're trying to teach someone something never start with it's a quintuple you know we're gonna be completely lost have no idea what you're talking about so finite state machines fall into the automata theory category which is related to combinatorial logic and also has relations to category theory this could make the concept seems really really foreign to a lot of people and also extremely difficult now the beauty of react since this is a reacts conference is it makes us rethink we rethink about best practices we rethink about just the way we think about developing software where everything's componentized everything's hierarchical data flows in a single direction and it makes it easier to reason about data so I want to do a little thought experiment with you let's say that we wanted to create a really really simple app let's say that we wanted to create a button that's just you know fetch of goats it fetches an image of a goats right it calls Flickr or something and eventually you get an image of a goat right that's all your app does you're probably thinking right now like yeah that's actually pretty simple to implement you know I could think immediately how I want to do this first we're using component state because we're not gonna get fancy and use Redux quite yet we're also you know gonna have an events handler that fetches the goat so once we get the goat we put it in state and then our render function just gonna show the goat pretty simple right here's a problem what if a number of things happen what if the goat search fails right well if we get an error from the server what if the user decides that he or she really wants a goat and clicks the button repeatedly like just give me the goat and so what's gonna end up happening is you're gonna have the photo of the goat and then another goat loaded in another goat because you know it's a race condition so what you can do is disable the button but then that's a problem too because the user could just say oh I'll just undo siebel the button you know it's really easy to get around apps that way also what if we want a custom loading message or a custom error message we have a little bit of work to do now so now in our state let's uh and this is a typical way we think right let's add some boolean flags right let's say well we'll keep track if there's an error and we'll keep track if we're in the middle of searching for our goats also in our events handler let's make sure that if we're searching for a goat let's not try to get another goats right and let's also indicate if the search fails that there's a goat error and display an error message accordingly so on that button we'll say hey the goat failed to load so do you want to retry our code now got a lot bigger so before it was like this don't try to read it by the way I'm just showing the size and now we have this yeah well it's odd you can't really see this check because it's on a black background but this is called the bottom-up approach to software development and this is what most of us have either done or are still doing today and there's a reason for it it's because it's simple and it works but there's problems with this in a bottom-up approach our events handlers so for example when we click a button and we try to you know fetch the goat we have so many possible things that could happen in that event because of the business logic involved so now our business logic logic is decentralized present in so many different events handlers units all over our code this makes it really difficult to understand exactly what's happening to our code and this means our codes can contain bugs and adding features is going to be an absolute nightmare have you ever tried to add a feature to a legacy app or an existing app that you worked on where you know if it's a week old it is a legacy app doing that makes it just extremely difficult because you have to remember which parts of the code that you know that you have to touch and that whatever state you're modifying is touching and this also makes it really difficult to test as well water break now with react react has a very simple and a very performant data flow model where since components are nested from their parents we have props and we have set state this sort of and you know I mean though criticism to react but this sort of exacerbates our problem with how we develop applications and the reason for this is because as soon as we need to go to you know a different state that our sorry at different components that's not part of the tree now we have just a flurry of different options that we have to choose from and so this thing this makes things a lot more complicated and I know some of you are going to go to me and say well well actually David you could you could probably you know just use props and set state for this to maybe use a callback prop like I know I could do this I could also drive from Florida to Utah but I decided to take a flight because it was a lot simpler it's more direct you know we like going from point A to point B in the shortest path possible so the main takeaway from that is this it's that user interfaces are graphs they're you know they're not strictly trees they're graphs which means that things can connect to other things in a non hierarchical fashion and I know some of you might also come to me and say well actually my my application is a tree and flows perfectly down I'm still right because trees are grafts - so don't at me so keep that in mind as we go through what deterministic finite automata really is and we're going to be using probably the simplest example which is a traffic light to explain what this is so let's break down all of these three confusing words first of all finite refers to the number of possible States we have in our application in a traffic light we have three green yellow red right then we have at Amida which is just a fancy word for a predetermined sequence something that's built in something that mechanically will always happen in a single way for example green will always go to yellow yellow will always go to red and red will always go to green because you know if green goes directly to red people die so we want to make sure that doesn't happen and deterministic finite automata are also deterministic and what this means is that given the current state in action you will know what the next date is going to be all the time so when the timer goes off it will go from green to yellow and then yellow to red and then red to green and we could predict this to happen every single time in Utah these timers are like 20 minutes each smoothing so we could also consider this a finite state machine these two things are the same thing so if if you've heard finite state machines this is exactly what we're talking about just to make things a little less confusing all right so now let's talk about designing state machines and fair warning there's a little bit of graph theory in here and yeah so let's take pac-man for example in pac-man we have the ghost which could only exist in one of three states first as a normal ghost that's chasing pac-man or mrs. pac-man then as a ghost that you know once pac-man eats a cherry it runs away and then if the ghost is eaten then you know the ghost becomes dead or what ghosts are already dead I don't know it becomes eyeballs okay so in a graph remembering you know you're like weather graph is we have three nodes or States these are the finite number of states but that we represent in the finite state machine we always have an initial state which in this case is just a normal ghost we have the edges between the notes which are the transitions between the states now these have arrows which makes this a directed graph why because we're going from one direction to another and then we have actions that cause these transitions just like I talked about once pac-man gets a pill did I say cherry I'm sorry I meant pill then it becomes you know a scared ghost you eat revived or the ghost could go back to a normal goat or yeah the scare goes could go back to a normal ghost once the timer goes off so let's go back to our original example before we do anything else we could use two powerful tools that require no code it's just pencil and paper I say pencil instead pen because you will make mistakes I make mistakes and with pencil and paper you could draw this out as a state transition diagram so considering our original example first we're in an idle state right we're waiting for something to happen from the user and the only thing the user could do is click once that happens we go into a loading state and then this fetch could either resolve or reject and so when that happens we go to one of the two states either goat or arrow state and then once we do a click action again we go back to loading alright when you well when I was reading about these state transition diagrams they're commonly referred to as STDs but honestly just call it state transition diagrams now you might find this sort of notation vaguely familiar and that's because designers inherently work with state machines all the time it's sort of a natural way of thinking they might call it like user flowcharts or something like that where a user can go from one state to another of the app and they would design each state of the app so this is a powerful application of state machines because they provide a common language for both designers and developers alike and I don't need to tell you how powerful that is so now that we've designed our state machine let's talk about how we develop them if you were to look you know as computer science books or whatever and read up on how do you declare that Li represents a graph then you're going to see an adjacency list which is just a mapping of States to states that they're connected to unfortunately this doesn't give us all the information that we need because you know we need to know what actions have occurred so what I propose is this it's a a machine can be represented as a mapping of states such as I alone encode or error and then each one of those states could be represented as a mapping of actions to the next dates and so if you thought that these finite state machines were difficult to implement here's a transition function it's just a lookup function where we look up the current state and then we look up the action that has been performed upon that state and so if you wanted this magical finite state machine library here you go 24 bytes you know I don't even need to put it on the npm or anything you could just memorize it if you gzip it it becomes 44 bytes so don't gzip it all right so now let's talk about how we could put this back in our application let's refactor it a lil so now in our set in our state our component state we're gonna represent the state as two things we have the finite state and then we have whatever data we get and then we're going to have this thing called commands and these commands you could think of as side effects and I borrowed this from Elm because Elms architecture has a very powerful way of abstracting these side effects in a declarative pure way and that's when you update instead of just saying here's the next components I'm going to render you say here's the next component and here's the command that I also want to run once you render that component so our transition method in our state is going to do the exact same thing that that transition function that we showed did it's also going to grab the next command and then you know if you were at the last talk you could see that you could pass a callback to set state and this is a very powerful way to to execute side effects right from the comfort of set state and so I know you could use Redux for this you could use mob X rxjs whatever but there's there's this natural beauty of just using set state especially in react and I'm sure Ryan Florence would approve which is why I named this pattern Ryan Florence in the state machine [Applause] now in our event handler it becomes extremely simple why because when we get a goat we just send off a resolve action and when we when we get an error we just send off a reject action the beautiful part of this compared to our last thing is that no matter how many other states we use no matter how complex our application gets this is never going to change it's never going to grow and that's the important part and because of that we could actually grab that state instead of random boolean flags and we could declaratively render our view and I'm just using a you know a map or a object whatever you want to call it I know that sometimes you use switch but honestly I like representing things as you know just objects so now let's talk about testing and visualizing our state machines because this is another powerful application of it and shoot oh wow it's resolving host right there we go come on you know what I prepared it here so because we could represent our state machine as a JSON object instead of switch statements or if statements or boolean flags or anything like that I could do some really cool things like like representing it as a a visual graph so you know I could change this and well I guess it doesn't change but anyway I promise you it works I just have a few bugs to fix this is something called cytoscape and I tried to use d3 but d3 doesn't really handle the nested grass and things like that but the idea is that by having a declarative representation of your finite state machine there's a lot of applications that you could do there it is that you could do from it and also testing is more powerful too because of this why because you know when you're using storybook are using just snapshots you want to do two things first you want to get all of your states all that is is object out keys right on your you know on your object and then you know finding all of the transitions that's just higher rating through each of the states and then you could go crazy and use Dijkstra or breadth-first search or any of those other crazy algorithms that you've only used for interview questions and you could actually use that to find the shortest path between the initial state and every other state and that way you could automate unit testing and integration testing now it would it would not be right for me to to talk about all the benefits of finite state machines without talking about some of their trade-offs to one of the most obvious trade-offs is that let's go back to our traffic light example let's say that we have a know simple traffic light that goes from green to yellow to red and now let's say our boss comes in and says hey you know how we live in Florida we have hurricanes we have power outages because of thunderstorms you know sometimes Florida man crawls on the power poles and takes it down so we need this flashing red state whenever the power goes out all I did was add one state and you see what happened now we have three more transitions so imagine if we had even more states we have to add even more transitions and this is what's known as state explosion I I was creating the slide at the airport that was not a good idea anyway there's this thing called state charts that solves this and what state charts are our hierarchical finite state machines and they were invented by a guy named David Harrell so they're also known as harel statecharts and again this was in 1987 so it's a very very old concept that's definitely useful today there's three main benefits of state charts the first one is that you could represent your finite state machines as hierarchical States so now instead of saying you know we have all these dates interconnected let's imagine this as two states both the normal operation of the traffic light and the flashing red thing and so now we could just say when normal has a power outage go to the flashing red and so there's two rules with hierarchical States the first one is when you enter a state you also enter all the initial sub states so when you enter normal you're actually in normal green and then things progresses normal normal green normal yellow normal red and then when the inner machine cannot handle in the action such as a power outage it sends it up to the parents and asks for help sort of like like talking a god or something and then it would take that normal and normal would say hey I know how to handle this and then it was just transition to flashing red so this simplifies things a lot because we could put as many states as we want inside normal and the number of transitions out going to flashing red will never change there's also the concept of concurrent States which is that a state machine could be in more than one state at the same time the most obvious example of this is a text editor where you could have bold underline italics right each of these could be on and off and each of these could you know have basically their own state machine right and I know what you're thinking like you know I thought we were being deterministic I thought we could only be in one state at a time what is this is it's like you know Schrodinger a state machine where we don't know if our apps alive or dead but the reason this works is because each of the state machines are orthogonal which is just a fancy word that means they don't touch and one of my favorite features is history states to imagine you have a payment flow where the users entering a payment method to buy their a card or a check and then the user goes to a review page and then goes back we want to remember if the user chose card or check and that's what his three states are good for so I actually wrote a library for this called X date because all the other steep names were taken so I just put an X in front but it actually makes sense because X stands for a transition or between states or something and so this tiny library handles transitioning from both hierarchical States and concurrent States in ways that you would expect so just like that same machine before if we are in bold off and we toggle bold we're gonna be in four states at the same time bold on italics off underline off and list bullets and the best part is it's represented also as a JSON object we just have to extend our original syntax a little bit so that we could have both states which are the nested States and on which is the mapping of actions to other states now there's a lot of advantages to using state charts such as having precise semantics which allows you to make them declarative having a rich expressive notation for describing these state charts and many other things where you could describe complex user interfaces in a completely declarative way now the my main inspiration for this and where I got the most information is from this book called constructing the user interface with state charts it was written in 1997 by ian horrocks and i really want to recommend it to you but if you go on Amazon it's like six hundred seventy five dollars so maybe hold off or put it as a business expense I don't know thankfully there's other resources for this including the original paper and two excellent articles by Guillaume Arash and Adam salope which don't necessarily talk about state charts exactly but they definitely points in that direction and as I was walking I saw the sign so I thought it was extremely appropriate that even though it's covered in bird it's a very important message and that's that we wants to stop maintaining state in in an unpredictable way and so I I really encourage you whether you're using it just for design just for testing or if you're going the extra mile and you're using state machines for actual development that that you find state machines and thinking of your data as a transition between two different states connected with an action that you know you start to represent your data in a way that's robust testable maintainable and easier to reason about so with that said thank you react rally you could find me everywhere at David Kay piano
Info
Channel: ReactRally
Views: 43,209
Rating: undefined out of 5
Keywords:
Id: VU1NKX6Qkxc
Channel Id: undefined
Length: 25min 33sec (1533 seconds)
Published: Thu Aug 31 2017
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.