 It was a time, it was a land, it was a world without selfie sticks. It was 2012. I lived it. I was there. I was actually busy writing applications using a technology called Backbone. And for those of you who are there at a time, this is going to be a little bit of a trip down memory lane. If you weren't, it might be a little bit involved, a little bit painful, but I really, really, really enjoyed working with Backbone because it allowed me to build these model-centric applications. And because the models were rich, the rendering could be this rote mechanical process whose outcome was just predetermined by the content of those models. And the way that Backbone did this was with property observation. You could add an observer to a model and be notified whenever a property changed on that model, and you could do any updates to anything that depended on that property. And this allowed entire trees of objects to be reactive. If a single property changed anywhere in the system, that change could ripple throughout the tree, and the DOM could be updated via that rote mechanical process that I was describing. And I was really quite happy with this approach, and I felt generally good about the apps that I could deliver with this style. That is until I didn't. As my applications became more complex, I started running into more and more friction that I just couldn't seem to eliminate. Backbone lets you observe a single property on a single object, but what if you needed to layer multiple dependencies? As the applications grew, and this distressing amount of code just started to grow that was dedicated to nothing but setting up and tearing down observers, and most of those observers were doing nothing but just copying one value from one place to another. And things got worse when you were trying to react to collections of objects, and Backbone never really did get a satisfying answer to this, and it was a constant source of pain for me. So now I know what you're thinking at this point. This is EmberConf. Why are we spending time on questions that were settled for us years ago? And the reason that I think that it's important to include it in this story is that because the pain I was feeling with my Backbone setup was acute enough that while I wasn't fully conscious of it, I was seriously open to a complete change in tools. So I went out and I was looking for alternative approaches. And this is, of course, where Ember enters the story. Specifically, EmberObject. This single class up there had everything that I was missing in Backbone, and then some. It had nested key value observations, so I didn't have to manually construct these huge chains of observers. It had array observations, so I finally got those reactive lists that I was after. It had these things called computed properties that blew my mind with their power, and it won me over almost immediately, and we started using it. So we had this strange hybrid phase where we ended up using EmberObject pretty much as a drop-in replacement for Backbone model. And with the turbocharged observers and computed properties, it turns out that Ember was actually better at doing Backbone than Backbone was. Not only did EmberObject have everything that I needed, it also came bundled with a whole lot more than I really had bargained for in the first place. It had this incredible router, it had this nice system for decorating model objects, and while it was still nascent at the time, it had this unbelievably warm and helpful community. And Backbone didn't really offer me anything that Ember didn't. And so we never really looked back. We threw in our lot with Ember, and honestly, it's been great, and we never thought of looking back. And because of that, I got to inherit nearly for free all of the wonderful things that came later, like Glimmer, Ember CLI, just to bring up a few. So that brings us up to 2015. It was around EmberConf one year ago, and exciting stuff was happening. You know, Glimmer had just been announced, dated down, actions up, was being codified as kind of the community best practice, and the hype machine was geared up, and it was in full swing. And overall, I was really quite happy with Ember, and I felt generally good about the apps that I could deliver with it. It wasn't until I didn't. As the problems that I was trying to solve became more complex, I started running into more and more friction that I just could not seem to eliminate. And ironically, it was related to Ember Object, which is the thing that had kind of stolen my heart to begin with. And the pain that I was feeling with my Ember setup was acute enough that while I wasn't fully conscious of it, I was actually open to a complete change in tools. So again, I went looking for alternative approaches, and I spent most of the time with two frameworks, one called OM and one called Omniscient. And these were React-based frameworks, but the fact that they used React was literally the least interesting thing to me. What really set them apart, and what intrigued me most, was their unique take on application state. They were able to solve many of the problems that I was having very, very neatly. And the things that were gumming up my Ember code just seemed to fall away as if they didn't exist. So this lifted me with a question. Do I change my tool set completely? Now, unlike when I made the transition from backbone to Ember, there was a lot that the alternatives didn't offer. I still had a world-class router, but since I adopted it in the first place, there was even more great stuff that it had originally, not least of which was the promise that the platform could upgrade and sometimes change radically in the course of a very short time, and that there would always be a path forward, and that the community would support you. So what do I do? Well, I am standing here, so if that's an answer to the question. I mean, I don't want to give up on all that great stuff. It's mine. It makes me productive. I want to keep it. It makes me happy. So I set about to see if you could have it both ways. If I could bring back this thought tool that I discovered when working with Ohm and Omniscient and use it with Ember, and it turns out that you can have your cake and eat it too. More than that, it turns out that it works really, really, really well with Ember right now today. And this thought tool is what I want to share with you. It's called immutability. And unlike what you might have heard in the past, it's very approachable. It sounds way more intimidating than it really is. My name is Charles Lowell. I'm Cowboy D on Twitter and GitHub. And I submitted this talk in the hope that you can walk away today with this same tool in your tool belt that has so dramatically improved the way that we write UI at the front side. And to be clear, I'm not talking about a piece of code or a library that you import and use in your Ember application. I'm talking about an organizing principle for thinking about your UI, a principle that will just, that made so many of these problems that I was facing just melt away. So anyway, it was early 2015. Glimmer had been announced, the add-on ecosystem was really starting to flourish and great big things were afoot. And at the time, I was heads down and I was working on a general purpose form library. And this wasn't any old form library. There's a lot of them out there. I tried all of them. And there's just a whole gaggle of problems that you always run into with user input. And I wanted to solve them in one place once and for all. And so the scope of this was pretty big. I've written a lot of forms and four. And there's just a long list of things that go into a truly sweet form experience. And as a result, it can be a lot of work to do every time. And instead of feeling like tired and exhausted, I wanted to feel excited every time that we were asked to build a complex form experience. And I knew that we would be excited if I could reduce the cost of making all these things happen. It's close to free as possible. And that's where the problem started. In order to juggle all of those things at once, the model had to be pretty gnarly. You have this massive tree of values, massive tree of input buffers, massive tree of validations, all of which have these intermingled dependencies and they have to be kept in sync and react to each other. And you know what? Even as a pretty experienced Ember developer and a pretty seasoned UI developer at the time, I just could not make it happen. I could get close. I could get really close. And I even got a couple of times where I achieved this false sense of security. But then always some little edge case or something would happen that would shake the wheels right off the whole endeavor. And I never got there. And after a while, I spent a good bit of time asking myself, why? Why was I so bedeviled by this particular problem in particular? Why was it difficult to come up with a general solution for something even as simple as this? Now, this is a really, really simple example. But it does have validation states and ready states that depend both on the client and the server. And this is where things got rough. Because it was highly asynchronous. It needed to handle updates from the keyboard. But there were server validations, the form submission itself. And they could fire in almost any order and they could return in almost any order. And keeping the entire form state intact was a real headache. And I was using one-way bindings. And I was using computed properties. But the values that were backing them could change mid-computation, which introduced this non-determinism into the system. And the problem is determining exactly when that bad value is introduced. Because as your system continues to change, the bad state begets more bad state. And when this happened, tracking it down was really, really difficult. The problem that I was having were with timing. And so to determine the sequence, I wanted to, for example, log things to the console, which is crucial. But have you ever tried actually logging a really complex data structure that's happening in real time to the console? If it's an ember object, you're going to see a lot of this. And it's pretty rough. And in fact, when your graph is constructed with computed properties, it's pretty well useless, because you can't read those computed properties from the console. But there was a deeper issue with the computed properties. And that's for the first time that I could recall, keeping the dependent keys in sync as I changed and kind of evolved the library became really onerous. In the form data structures, I wasn't just deriving a few extra fields to present to a template. I was actually computing, mapping entire trees to entire trees, and then computing your roll-ups of those trees. And figuring out the rights of the dependent keys was always possible, but it was just this endless source of paper cuts. And especially as I refactored and changed the data structures, it was like there was this shadow data structure that was chasing me of the hierarchy of the dependent keys. And if they didn't match the actual data structure precisely, it might appear to work, but then it would fail in really subtle ways. And when I did get a stack retrace related to bad dependent keys, a lot of times it would just be completely and totally buried inside, you know, the vendor JS. There was no reference, not a single line referencing my application code. And so none of these problems were really new to me. After all, I've been doing nothing but Ember for three years before this, and I'd encountered each one of these in isolation. But what was new was the way they came together in this kind of perfect storm that just seemed to block me at every turn. And so I was in the same place that I was at Backbone, and that's when I stood up from my desk and decided to start looking around. I heard good things about OM. It's a framework that uses closure script, and then there's a pure JavaScript that's cousin called omniscient. And so I spent some time with them. And what I found was that they had a very simple, very unique take on state management. And when I tried applying the same techniques that they used back in Ember, well, pretty neatly sidestepped all of the problems that I've just been describing to you. And so we'll get to that. But first, let's do a quick review of the way that I handled state and Ember back then. Ember was, and it remains today, an MBC framework. And without getting too bogged down in specifics and definitions, this is the essence of MBC to me. You have a model, and the content of that model guides the rendering process repeatedly. It's deterministic. If the model contains the same properties, then it's going to yield the same DOM every time. In other words, the view is a pure function of the model. This is true in Ember. It's true in Angular. It's true in React. It's even true in Backbone. That is just MBC done right. The difference is how we go about changing that value of M up there. What we're used to doing is updating the model. We change some portion of the model by erasing one of its properties and then replacing them with new values that we want. The view is observing this and it reacts accordingly. For a lot of use cases, this is a very workable approach. But that's not how these frameworks did it. When it came to updating the model, rather than editing the properties in place, they always generated a completely brand new, wholly formed state to replace the old one. No exceptions. By replacing that model each time, it ceases to become a single object, the model so much as a stream of discrete states that when rendered in succession yield this seamless experience. As it turns out, there's a very precise word for this sequence of discrete states in computer science and category theory. It's called a movie. We observe the movie as a single experience, but we know in fact that the content of the movie is subdivided into discrete static frames. Each frame has clearly defined bounds, it has a start, it has a finish, and each frame of content exists completely and totally independent of all the others. It's only when we take the static content and render it in succession through a player that the human experience emerges. Now a key point that I want to stress here is that even in the case where two of these frames contain the same information, that information is faithfully replicated in both. And what I mean by that is if you look at these two frames, the only things that are different are the positions of Charlie Chaplin and that weird scary masseuse. The walls, the towel racks, the sink, the faucets, they're all in exactly the same place and yet each is individually represented in both. And because of this, any frame that you care to take contains all of the information that's needed to render. And I can print it out, I can hang it on a wall, or I can take a piece of state that was generated almost 100 years ago, and I can render it for you now. And so at some level, a movie and an immutable JavaScript framework share the same architecture. They both work by separating this content from the player. The content or the stream of content is static. Each frame is unchanging. It's immutable. While the player is a thing that changes and rearranges itself in order to render that content. And when we play the content, that's when we see the experience. So how do we go about harnessing this pattern in our Ember applications? That's actually a trick question because the answer is, you already do. Every single Ember application is at its core a player of URLs. Those URLs, that's the stream of immutable content. And the application itself is the player. It's the thing that rearranges itself in order to render the content. And like a real movie, you can use the browser back button and forward button to rewind and fast forward. And it works well. It works flawlessly in most cases because of the way it's modeled. And so we use it here. But now let's look how we might apply this concept to an area where it's not something that we do by default. How do we take that password form that we were looking at from earlier? And how do we refactor that to be a movie? Well, it's pretty straightforward as it turns out. We want to break our component apart into two pieces, the content and the player. And we can do it in two simple steps. The first step is to disentangle the properties that we use in the template and bundle them into a single object. And that single object is going to represent one of those static frames of content. And so here in this template, you can see here before, these are intrinsic component properties. Is it long enough? And what's the rating? Is it a weak or moderate password? And what we're going to do is we're going to hide those inside this object called the model. And we're going to bundle them up in a single object. And that's step one. It's really easy. And then step two is replace the whole model with every change. Whenever an event happens, like an action that might change or update the state, we always want to generate this brand new state, this fully formed state that represents the next frame of content in your movie. So how will we do that? Well, here we've got this hypothetical action inside of our controller, where we're going to set the password text. And here's how we might have done it before. We're going to overwrite that password property on the model. And instead, what we're going to do is we're going to replace, we're going to set the whole model with this new object that we're creating, this new password form object, which is going to encapsulate the entire state. Now, this may strike you as a little odd at first. To use the new keyword to create plain old JavaScript objects in the middle of our component. And it's entirely possible that some of you may have never actually even seen this in an Ember application before. It is a small bit of heresy, but one that I think pays off big, as we'll see pretty shortly. Because now, that's it. Our component is now a movie. Following those two steps, that's really all there is to it. But sometimes, the tiniest shifts in thinking can open the door to entire new avenues of possibility. And one of these that presented itself immediately was a path towards a much, much, much simpler runtime. So to review, we've extracted our model into this stream of states comprised of static frames of content. And like a single frame of content in a movie, this content object is effectively a still life. It will never change. Because change is represented by generating another content object, not changing the old one. And so, because of that, these individual states, these contents objects do not have to be observable themselves. They can be just plain old JavaScript objects. So, for example, logging just works. I had a lot of problems with the JavaScript console. It wasn't a terrible thing, but it was constantly a paper cut. You remember this monstrosity right here? What if that were to look something like this? That would be pretty nice. And that's what you get from using a plain old JavaScript object. The same thing applies to tree structures. Those tree that was vexing me so completely and that was just incomprehensible inside the console, well, now it's no problem. What about those other things that were kind of giving me those troubles, those computed properties? Well, it turns out you don't need those either. And you might be thinking, really? Because I know that's what I was thinking. I was thinking, really? Computer properties, those are like my favorite things. Well, yes and no. I'm only telling half the story because it turns out that JavaScript already has the concept of computed properties. They're called getters. They've been a part of the spec for a really long time and most of the browsers support them. And because these static content objects are never going to change, you can pretty much just drop these in anywhere that you would have used a computed property before. And as you can see, they're really, really easy to look at and they are completely and totally immune to all of the problems that I was just describing. There are no dependent keys because the dependencies are just implicit to the computation. And when something does go wrong, well, you get this, instead of this error being buried in three levels of chained observation, you just get this simple synchronous stack that ends in your application code and not inside the framework. And so you get the stack, you get the logging, you get the simple properties all because your browser deeply understands POJOs in a way that it will never understand Ember Object, which means that you're speaking to it in its native language and it can help you out directly because it doesn't have to have talk to you through an interpreter like the Ember Inspector. It's this enormous weight off. I wasn't even expecting this part to feel like your platform is really, really, you know, pushing you forward. But whether you're using POJOs or not because this part of it is optional, the real ace that you get when you split your system into player and content, the real ace is knowing with certainty what happened when and why. Because you meant a fresh state every single time there's an event that causes a change. There's absolutely no doubt about what event gave rise to what state. They are effectively one to one. And what that means is that when you're trying to track down this tricky sequencing problem, you know, what was formerly murky waters become crystal clear. In concrete terms, before we had four events acting upon one object, but now that we're one to one, we have four events that are paired with four objects and it's very clear what happened and why. We can just put our finger right on it and say that's it. The second state up there, that is the first bad value. And what's more, it was the second event that caused that second state. And as a matter of fact, if we record each state as it happens, we can actually go back and examine it and see that first corrupt state and look at it under a microscope and find out exactly what went wrong with it. It's just like having a bug suspended in Ember. When we reconceive of that model as a stream of unchanging states and not just a chalkboard of properties, what we're really doing is preserving information. We're preserving information about both sides of a state transition, the state before and the state after. And it really makes it easier to make decisions. And not only that, but we're preserving information about the precise boundaries of an event and the implications that that event has on the application state and the state that that event produces. In other words, the consequences of an event will never leak outside of that single well-defined state. And it turns out in our line of work, information is really, really useful stuff. We shouldn't be intentionally destroying it because the more of it we have, the more powerful we become by default. For example, undo redo, that impossible dream. It actually becomes nearly trivial within an immutable system. And it's easy to see why. When you sequence your model like a movie, then an undo operation is just a simple exercise in storing and rewinding the tape. And a redo is nothing but a fast forward. That's it. And again, you're already doing this style of undo redo in your Ember applications today every time you use the browser's back and forward button with your Ember application. We're just taking the same concept and applying it to a state that's buried deeper within your application. And so undo redo wasn't really part of my initial requirements. And because I wasn't even attempting it, I wasn't experiencing any pain associated with it. But hey, you know, there's like a gold ingot in the condiment bar next to the pickles. I'm picking it up. Which brings us up to now. I feel really good about the way Ember is headed. And I feel confident that I'm going to be able to solve the class of problems that I want to solve with it. And I really couldn't be happier as an Ember developer today. And that's it. That's the end of that narrative. But the story of Ember and immutability is really just beginning. There are so many more techniques and so many more tools and so many more wonderful consequences to programming in this style that I didn't even get to talk about because 30 minutes is such a short time. But exploring those things is something that I would love to do together with all of you in the time ahead. Starting, you know, right after this talk. And all that will come eventually. But my goal for today is that you can walk out of this room with two things. One is the philosophical underpinnings of an immutable UI architecture, aka the movie. And two, some concrete steps that you can use to get started with it in your Ember applications today. Because Ember is really ready for it right now. It works so well with Glimmer. To review your application and your components are players of static frames of content. And to realize this, you first extract the model into its own object and then make a commitment to replacing that object with every change that you make. If you can do that, you can do those two things, then you will set your feet on the path. Same path that I've been walking for a little while. And you will be ready to both understand and benefit from all of the tools and techniques related to this that are coming in the future. Of course, it always helps to have some samples of this technique in action. We use it in our pagination library, as well as our library for doing reactive XML HTTP requests right in your handlebars templates. And finally, I would like to thank my company, the front side, for supporting me in these explorations, especially my team, who had to suffer through my proudling about immutability for almost a year now. And who had to suffer through the trenches of grinding out and figuring out what the best way to get these things to work in your Ember applications was. You guys are, you guys are amazing. And finally, I would like to thank you, EmberConf and the Ember community at large. When I look at other communities out there, it really is hard for me to imagine myself being happy or anywhere else. So thank you very much.