 If you have been programming for less than two years, me too, how about less than five years, less than ten years, more than ten years, damn, okay, I'm just gonna, it's fine, we'll just go with more than ten years, just for my sake, okay, so obviously a huge range of experience levels in this room, how many of you, at some point or another in your programming careers, have felt like this, right? Like I don't, I don't really know what's going on in this GIF or like most of the time when I'm sitting in front of a computer I have no idea what I'm doing and it's not like I'm completely new, but most of the time I have no idea what I'm doing and I think that's okay. So, hi, my name is Vaidehi, you can find me most places on the internet at Vaidehi Joshi and I have no idea what I'm doing most of the time and I've come to realize that whether you've been programming for six weeks or six years or sixteen or twenty, most of the time there are times when you're just not going to know what you're doing and you're over your head, in over your head and I think that's totally acceptable and I think it's totally normal because what we do every single day for a living, we solve really tough problems and a lot of what we do is trying to mirror things in the real world in software in ways that are not simple and are deeply, deeply complex and part of the complexity comes with the fact that things are never what they seem. Things never start out, things never end up the way that you plan for them to and specs change and you realize what you started off wanting to build, it's very different than the direction that you're going. So, that kind of ties back into a lot of the talks that we've been hearing yesterday and today which is that we always have this stream of endless learning. We're in over our heads a lot of the times because we're doing something we've never done before and it's hard to know where to start and how to navigate that path. So, I hope by the end of this talk I'll be able to tell you about one of the things that I learned and it was one of the scariest things that I ever learned and how I came to overcome my fear of it. Now, I really hope on the next slide no one's going to like run away out of this room because then this talk is going to be over, it's going to be really sad. So, at my very first dev job one of the things that I had to struggle with learning was this daunting, daunting thing called state and I had no idea how to manage it. And I think application state and state with an object is very, very difficult to wrap your head around and it's a concept that's hard to grapple with when you're very, very new to software and if you come from not having a CS background like I do. I've only been programming for about two years and before I got into software I was a sixth grade teacher and a freelance writer. So, you can imagine my surprise when people would throw around terms, CS terms like, well, you'll see some of the terms in a minute and I had no idea what they were talking about and it was a really, really hard thing for me to understand. But I think part of being able to learn something new is being compassionate towards yourself and being able to accept that really, really big scary things that seem daunting and impossible to learn actually aren't that scary if you can just take the time and be patient enough with yourself to break them down into simpler pieces. Because at the end of the day everything is just a simpler piece of something that's larger and can tend to be more intimidating. So, state machines was one of the ways that I learned about state. But here's the thing. Someone told me about this thing called state machines and I looked at it in our source code but I didn't know what that was. So, I did what most of you probably would have done in my position. I asked the Internet. The Internet wasn't super helpful because the Internet told me, oh, what you're actually looking for is something called finite state machines, which, what's that? That doesn't help. That's not even a definition for anything. Okay. So, Internet, what is a finite state machine? Actually, no. The Internet told me you're looking for something called a directed graph, which I don't know what that is either. So, I did something that I really don't encourage most of you to do because it was a little bit terrifying. I went on Google Images and I searched for directed graphs. Like, what? I don't, I don't know what that is. What is happening over there? None of it makes sense. So, I did some reading. I did some research and I talked to people and instead of being completely frustrated by that image on the slide before that we're not going to look at again because it still kind of scares me to this day, instead what I did was I tried to break down the concept of just state machines and I ended up learning how cool they are and how awesome they can be for solving really tough problems when it comes to handling mutable state. So, state machines I've learned are just flowcharts and flowcharts aren't scary. They're not daunting, right? They're simple to understand because they're everywhere. They're all around us, all around us all the time. And when you start thinking about something complex as it's simple parts, it becomes less scary. So, if a state machine is just a flowchart, okay, that's a little bit easier to work with. Let's break down the parts of the flowchart. Let's break down our state machine into the different parts. State machines and flowcharts just control how things happen. So, how do they do that? Well, I think that there's four basic parts of any state machine and no matter how complex or how simple, you can find these four pieces in any kind of state machine. So, what are those four pieces? Well, when you're trying to handle state, you usually have some things that need to get done, which in programmatic terms you can call as functions. But, of course, you also need to have reasons to call those functions. They don't just get called magically by themselves, right? Well, those are our events. And you need some sort of data to keep track of these functions and how and when they're called. These are our states. And, of course, you probably need to do some sort of complex logic, some sort of work that needs to happen between changing states or between events. And this is just going to be the code that's going to be in our functions. So, does anybody feel like that's an awful lot of work and a lot of things that are happening? And why would you ever need to do all of those things? Okay, cool. It's not just me. Well, you're right. Sometimes it is an awful lot of work. And sometimes it's not the right tool for the job. And it can seem like an awful lot of setup for something that you may or may not need. But sometimes there are a couple warning signs and red flags of when you might want to consider using a state machine. So, what might some of those be? Well, for one, if you have any kind of column in your database called state or status, you might want to just maybe consider using a state machine. Because this kind of thing is going to get pretty complex and kind of crazy really fast. It's probably not going to be great for you down the road. If you have instance methods that return Boolean values, well, that's also going to be quite a lot of work and hard to keep track of. And your code is just going to start to grow in a way that you're going to lose track of it. So, maybe it's a good time to consider using a state machine. If you have timestamps that have a null value, also a good time to use a state machine. And, of course, if you have records that are valid by a certain period of time, for example, if you have a start date or end date on one of your models, you might want to consider using a state machine. So, if you have any kind of code that looks something like this, this is the kind of stuff that would look really good refactored into a state machine. Or, hopefully, before you go down that track, you'll kind of realize that that's the time to look into using state machines for your code. So, all of those instances, probably not a great idea for yourself in the long run. But how do you start writing a state machine? Well, I think before you even start writing any piece of code, it's a good idea to wrap your head around what it is that you're trying to do. And, for me, the technique that works really well is actually sketching out what it is that I want to build. So, let's say we have an e-commerce application and we want to represent a piece of state on an order object. Well, how can you do that? You can sketch out and draw out the different life cycles of your order object. Most orders start off unplaced and then they're submitted and then they go into a processing state. From there, they could possibly be shipped and then delivered to a customer or they could be deleted. So, we know what it looks like. How do you find those four pieces of our state machine in the one we just drew out? We're going to have some functions. For example, our user inputting a credit card number in order to transition from an unplaced state to a submitted state. But we also need some events, which we actually kind of drew out as well. When our user successfully submits the form to update the database, our submit event could be called and our order would actually be submitted and wherever that information needs to go, it will end up in the right place. And, of course, we have states, the data that's going to keep track of where our order actually is in its life. So, an order that's in its processing state would encapsulate all of the different parts of the system. And, of course, we're going to have to write some code in our functions to make sure that nothing happens unless it's supposed to. So, for example, you'd want to check if an order's products are in stock before actually allowing someone to place an order. We'd want to guard against changing a state unless we are sure that that state changes. So, we look again at what our state machine might look like. We'll notice that it's kind of only going in one direction. It's kind of got this unidirectional flow. But, of course, in the real world, things are never that simple, and they're never what they seem. In the real world, you might have a completed order, and then it might go to processing, and then it realizes that they ordered the wrong size shoe, and then they want to return their order, and then it needs to go back into processing, and things start to get really complex, really fast. Thankfully, we can make our state machine as complex as we want it to be as well. We can make our state machine self-referential, and we'll get into this a little bit when we start actually coding. But, if we make our state machine self-referential, instead of being a directed graph, it'll be a directed cyclic graph, which I'm still not completely sure what those are. That's okay. I'm not going to Google image it at all. So, cool. We know a little bit about the theory of state machines. What might it actually look like when we write code? Well, there are a few different gems that I think are really, really great for implementing state machines. My favorite is Axis state machine, which is often referred to as AASM, and it's very, very easy to implement. First, you just need to include it into the model that you want to track the state of, and then you need an initial state. If you remember from our diagram, all state machines are going to start off with some sort of initial state, and then you just need a state that you want to transition to. And honestly, that's really the basics of a state machine. It's not anything more complex than that. So, this is what our most simplest form of a state machine might look like. We have an order that has an initial state of being unplaced, and it can transition to a submitted state. And it is with the submit event that this transition between one state to another actually happens. But, of course, nothing is ever that simple, and we need to, of course, make it more complicated, obviously. So, we'll add a couple more states. We'll add a processing state and a ship state, and we'll add events that trigger one state transition to another. And if you remember, users might be able to return orders, so we can add that state as well. And now, our state machine has actually become self-referential. Let's take a closer look at what that actually means. Now, we can transition between two states to a third, which is actually pretty cool, because what's happening here is that our event is looking back upon states in the state machine, and it's reflecting back upon itself in order to decide whether it can transition between one state to another, which when you start thinking about how powerful this is, you can build some amazingly complex forms of state machines through this kind of thing. And you can do some pretty cool stuff, like you can ask whether your order is unplaced or whether you can submit it, or you can trigger a submit event, or you can raise a transition. But we didn't write any of those methods. Where did they come from? We got them for free. Actually, that's not entirely true. We got them for free, but someone else wrote them. AASM is pretty cool, because it actually dynamically defines all of these methods for you based on the states that you define in your state machine, which means that you get all of these methods that you can use in order to guard and transition between states for free without ever having to write the logic in order to implement this, which is pretty rad. So, okay, that's what our code looks like with a state machine. What if we didn't have one? Well, how would we implement this without using access state machine or any other gem for that matter? Well, let's just look at one state. What would we have had to do? In order to create an unplaced state, we would have first had to write a migration that would have added a string that's like state or status for our order object, and then we would have had to give that column some sort of initial state, some sort of initial value, and then we would have had to add an instance method called unplaced with a Boolean return value, and then we would have had to add another instance method called submit that would have changed our object state, not to mention all the logic that would have had to live inside of that method, and all the things that it could possibly break. And then we would have had to add another instance method called submitted, and then also step six, cry, because, oh, my God, you have to do that every single time for every single one of your states, and that just seems really bad. Let's just not do that. So, in our case, maybe state machines sound like the perfect tool for the job, but what else can you do with it? Well, it turns out you can do a lot of really awesome things. You can pass a block to an event, and what's really cool about this is that you're only if your transition succeeds will the code inside of that block be executed. So, in this example, we have a send order shipped email, which is only going to ever execute if we transition to the ship state, which is nice because you can just let your state machine handle all of the logic of knowing whether it should fire that code or not. You can also use callbacks, which is really rad because you can hook into different parts of the life cycle of a state. So, when you enter a state or when you're leaving a state and transitioning between states, you can make sure that certain pieces of code are executed. So, in this case, before we're entering the ship state, we're calling this print return label method, and after we enter the delete event, we're calling our send delete confirmation method. You can also implement guards, and I think this is probably my favorite thing about state machines because it allows you to abstract a lot of the logic that you would have had to write and just stick it in your state machine and make sure that it's responsible for knowing what to do. And what's really cool about this is that it only will execute code given a transition. So, in this case, if the guard payment successfully processed returns a truthy value, will we be able to transition between unplaced and submitted? And if you're not a big fan of raising exceptions, you can also return Boolean values. Just wrap your state machine inside of whiny transitions, and then if you don't want exceptions, that problem is solved for you. So, I think that it's really, really easy to get daunted by things like state machines and really, really tough computer science and theoretical concepts that you might not have ever known before. And I think all of this is to say that learning new things can be scary, whether you've been doing this for two years or for 20. And at some point or another, we're all going to have to learn new things. Hopefully, we're all learning new things every single day. But it can be very, very intimidating. And honestly, sometimes it can seem impossible. It can seem like there's no way that I'm ever going to be able to wrap my head around this really, really tough concept. But I like to think that if we can just give ourselves a little bit of compassion and patience and be a little bit empathetic towards ourselves when we're trying to learn something new, we can actually break it down into something that's far more simple and then it doesn't become scary or frustrating. It actually means that it can be pretty fun. And you start to realize that you can learn new things and you're just going to slug it out and enjoy it. Because that's honestly part of what makes our job as developers and lifelong learners one of the coolest jobs there is. Thank you. That's all I have.