 Hush falls over the room because I'm not paying attention. My slides came up. Hi. So really quick first, there are seats kind of in the middle. If people can squish together, otherwise, people are going to be sitting in the aisles and fire marshal is going to get angry. I don't know that. I'm not a building guy. Hi, everybody. Sorry to make you move around. But also maybe that'll wake you up a little bit. This is going to be a shot of espresso. We've got to go, go, go, go. Hi. I have a very serious talk about the heart of architecture. As you know, as DHH said at the first talk, we are engineers. What we do is build bridges with code. We are architects. We build centuries-old castles. We are craftspeople. We are old-timey metalworkers. And we live in the cloud. I think JavaScript is ready for all of these things. I feel like JavaScript is ready for cloud-geneering. So if anybody knows what any of the things I said with the pretty pictures and stuff are, please grab me after the talk and explain them to me. I just say them to sound smart and serious about programming. It is serious business. Hi, I'm Brandon Hayes. I work with Charles, actually, at the front side. I'm a dedicated cloud-geneer. And no one ever asks which of us is the smart one when we converse together, which is a little weird. These are my credentials. As you can see, I am highly credentialed and ready to tell you all about programming. My wife gave me a few of these. Most of them are actually true. So I'm not here to talk about some core ideal or some big fancy thing. I live in the real world. I have to write programs that people want written fast and want them yesterday. And it's very, very challenging sometimes. So I understand that architecture is great, but I don't have a lot of use for ivory tower people. I think the universe has plenty of uncles in it. We live in a place. And I'm going to tell you a tale about a couple places. But it's actually a meta talk about the ball of mud architecture pattern. That's one I can really get behind. If you're not familiar with this, Brian Foote, I believe in the late 1970s, created an architecture pattern or described an architecture pattern that everyone here has seen called the ball of mud. But to do that, I need to talk about city planning. Most cities are not designed for growth. Salt Lake City would be a rare exception. You'll see that it handled its eventual growth pretty well from layout to infrastructure. It seems to have avoided many of the problems that plague large cities. But our code does not live in Salt Lake City. They don't work like that. My current hometown of Austin is a lot more typical. I actually look at that every day on my drive home while Charles rides his bike home, which is great. I get to sit in that every day for about 45 minutes on the way home. The city layout and infrastructure was not prepared for the kind of growth that they have experienced. And that results in the dreaded urban sprawl. But we don't actually even live here. Let's be honest about our code for a minute, people. We live here. It's not a sprawling metro plaques or a beautifully planned city. We live in a favela. A favela is a Brazilian slum, basically. It looks kind of cool, though, right? It's the definition of a walkable city. Well, hikeable. Let's zoom in. So a favela is a Brazilian shanty town made permanent. The structures require a little skill to create. And they pop up everywhere just out of whatever materials can be found. The problem is these structures are difficult to grow, to maintain, or protect. So there's little police presence or fire presence. And safety and crime issues are pretty rampant. So forget architecture stuff. We're going to go into a code favela. It will look familiar to you. You probably had some that made you nearly go crazy trying to maintain it. So I apologize in advance for making you look at this. But I really need you to feel my pain. All right, so that favela is a manifestation of the ball of mud pattern, which is really easy to create. You just need to build something temporary, add to it, and then rely on it for your business. They're so easy to create that it's the dominant architecture pattern I would contest in software today. So let's talk about how this happens. This should be pretty easy, right? You could probably make this happen this week. So I need a show of hands. How many of you hate being asked to raise your hands on a talk? OK, I should see no hands. That is insane. OK, how many of the rest of you have a prototype that is shipped to production? OK, so pretty good balance there. They say, oh, this is a two-week feature. Let's ship this thing in two weeks. I don't believe in two-week features. I don't think that's actually a thing. We do try to cram features into two weeks and then make sacrifices to get them out the door. Or we inherit code from less experienced developers than it has to ship. But mostly, these shantytowns start as a quick prototype. So let's go ahead and build a shantytown. It starts off like pretty much any other. So let's say we're all working on Giff and Doar. It's a social network for animated GIFs. The founder is a huge Harry Potter fan. Cost player, the whole thing, has the glasses. It's adorable. Personally, I'm more of a Hufflepuff. This is not my website, though. It's a vanilla server-side-out in Rails. One note on pronunciation. I'm going to take a stand. I'm going to say that GIF is pronounced like GitHub gist. I do the same thing with JSON and JSON. I like to make everybody mad. Mix tabs and spaces. People love me. All right, back to work. Let's just sprinkle in a little interactivity. So let's start with sprinkles. They're fun. Sprinkles are fun. Yay. Your boss calls. She says, we want a better experience on the site. Our users demand it. They should not have to go through a page refresh all the way to the new page to submit a new animated GIF. So you look at your JavaScript file. OK, so nothing there. Undaunted, you march forward. All right, easy, right? Just make a little HTML form on the page with show hide. All done. All right, so that worked. Except it submits and does a full page refresh on submit. Can you do that via Ajax? It's kind of irritating to our users. All right, that's what Ajax is for, right? So we submit this thing via Ajax. So that seems to work. All right, but now you actually have to add that new post to the list of posts that are on that page. All right, no problem. OK, a little bit of a problem. We're starting to duplicate some DOM code here, right? In your JavaScript. So you get to edit stuff in two places, but a little duplication. We know, we don't deduplicate first. So you're agile. So you agile that code right in there until this whole thing is agile. By the way, that's a trademark of Cloud Gineering Inc. So do not use that without written permission. So this sprinkle is like, all right, starting to turn into a little more of a rain shower. A little bit of a steady rain. But cheer up, Keanu. We shipped some software, right? OK, Sport. The product manager who tends to look like Fred McMurray, for some reason, is really happy. He has more ideas. He wants users to be able to click a cancel button so they zero out the form. Because if you open it, it's just stuck there. So dutifully, you implement the cancel button and zero out the form with jQuery. Awesome. Except now, users are hitting submit on empty and invalid forms. So we need some sort of client-side validation to prevent that from happening. But it shouldn't be too hard to tell if somebody has attached an animated GIF link. Oh, well, OK, so it wasn't super, super easy, but it was relatively straightforward. We disable the submit button unless it's valid and show messages with jQuery. This is starting to look a little weird, right? It's starting to really come down. Poor Al Roker. So your CEO comes in to congratulate you on all the great work you've done. You've really shipped a lot of code and agileed everything. And you just need a couple more enhancements, right? So let's add an inline preview for that image so users know what they're about to post before they post it. And a little character count that doesn't deem them for a long URL. So we want a smart character count. All right, so that's working, but actually broke a couple other things about the state of this form. So we do some double checking and enable or disable submit. So now you're caught between these two worlds, right? You want a craft code that you can be proud of and that lets you feel good about the things that you do. But you also want to be able to ship stuff. Your business needs you to move fast and break things. You need to get stuff done. GSD, right? Craftsmanship, ship it. I say craftsmanship it. It's a good thing. It's a good thing you're a cloud engineer and you can straddle these two worlds just perfectly. So look at all this code that we've craftsmanshiped. Sandy Metz talked yesterday about code shape and the squint test is an indicator. When I squint, this code has a shape. And that shape is a sack of hot garbage. It's like if you've ever been in, I don't know if Chicago has this, but in Manhattan in the summertime, you get this nice smell wafting off of the hot garbage. It's great. That's kind of how it feels. So here we are, a total tsunami of entangled jQuery code. Let's ship a feature against that, right? Please. It's really important. Your CEO is now putty in your hands. You are a superstar developer and the expectation is now that you just ship so fast. And a like button, let's do it. Okay, here's the thing. I was going to implement this in jQuery. I was gonna do it, but there was already so much double checking in interwoven states that I physically couldn't without getting really ill. The thought of touching this code made me wanna quit writing the talk and just be like, you know what, RailsConf, thanks anyway. So now what, what do we do? Well, actually Brian Foote has prescriptions for dealing with the ball of mud pattern. And it's not always what you think. You don't necessarily dive right into a refactor. Addressing a ball of mud is pretty difficult. We can sweep it all under the rug or put it inside of a black box, right? You can reconstruct it, like tear the whole thing down and raise it and rebuild. You can renovate block by block, which is, he calls keeping it working. Or you can quit your job, which in some cases, I mean, sometimes it's a thing to do. But black box is fine. If you know you're never gonna have to touch that code again. If it's some complicated math equation or something like that, I've seen that done where you just like hide it in the closet. And that's fine. A rewrite is a great way to learn really amazingly hidden lessons about your business logic. Things that are encoded in very strange places. And it's a really great way to make something that sounds like it takes two weeks, take six months. So I feel like you always discover hidden, that hidden business logic. So let's talk about a refactor. Why would we do that? We decide that refactor is probably the right thing to do because the feature has to be maintained, but it's now too expensive to manage. Users are starting to actually have a bad time with it because the longer they stay on the page, the more likely they are to have problems with it. And more importantly to me personally is that you are tossing and turning all night. You cannot sleep because you're dreaming about the JIRA tickets that are waiting for you in the morning. And why are we still using JIRA? Why is that a thing? Okay, anyway, separate deal. But you think about your frustrated users, your gut is telling you to fix it, and your gut is totally right. So you have two paths out of here. I think a person in this room, a super smart guy, is like, why don't you just refactor this to smart JavaScript objects? And he's largely right. That's an idiomatic way to dig out of this. And he also asked me if I did that as a straw man of how to build really terrible jQuery code. And I was like, yes, I was not doing my best. Okay, so the other option is to use a framework to abstract away the DOM and handle data. So our goal is to get the heck out of the DOM as fast as humanly possible. That's our biggest pain point right now. So for me, I'll choose a framework. The framework will manage the DOM and will just manage the underlying data. So all we need to do now is five steps to get out. These steps will probably apply for people that use plain JavaScript and don't use a framework or any framework that you choose. It's just nice to kind of build up against one. Personally, I certainly prefer it. So on our blog, we'll talk more about like why we choose Ember and why we like it. And you heard Charles mention earlier if you were here about why we like Ember's model layer. I feel like it's a really strong model layer for the case that we're trying to accomplish now. It has really great blindings to manage state and it's got a great drop in component library to tie it all together. All right, so step one, let's wrap it. Wrap it, wrap it, wrap it, wrap it. Okay, so now I think a lot of people, a little sidetrack, a lot of people don't realize that you can sprinkle Ember into an app. A lot of people think that Ember only works if you wanna start an app from scratch and build up from the ground up from floor zero all the way up to the top. But you can actually apply it to a lot of code bases and it's really great for refactoring existing code bases toward Ember. And that's just these three steps right here. At the front side, we do that pretty often where we take an existing Rails application and move it towards Ember, but it's actually not that hard. So first things first, it's time for some justice. We're gonna put that terrible code in the code jail. And that code jail is this init legacy code function. So we're gonna create a component, an Ember component. We're gonna put the stuff in the init legacy code, which is not a special name. I just chose it to tell me that this is the jail. And it bootstraps the old code inside the component. We do not alter that code at all. Also, we move the HTML into a handlebars template associated with this component. No structure of that HTML actually changes. So we're just isolating it. And then we can sprinkle. So now we use jQuery to stuff all of this old stuff that we had before back into the DOM. All right, another thing Sandy said yesterday that is, I hope it's self-evident. It certainly made itself self-evident to me over the course of the last year or two of doing this, that you have to test it. If you do not test your code, a refactor is essentially impossible. I cannot imagine trying to do it. And I was not a big testing advocate earlier. I was very skeptical, let's say, about testing. I was raised by cowboy coders in my first place when I was learning to program. So, but we're gonna do it. And we're gonna see that it's actually not that hard to actually test the thing itself. So we're just gonna test that it shows up and it passes. So I'm doing a little bit of a hand wave here over a JavaScript testing setup. JavaScript test setup story for getting Ember applications bootstrapped in Rails can be a little challenging. And so there's a growing body of knowledge about it. So I wanna give you guys a quick note on that. On its own, JavaScript testing is pretty easy, but when you add in frameworks and tie it to Rails, add in the asset pipeline, things can get a little complicated. It's a little bit of a Wild West. There's a lot of choices out there. There's a little bit of paralysis of choice, I think. It's really wide open. But not like home on the range, wide open. We're like this kind of Wild West. So it can lead to that. You look at the thing of like, I don't know what brand of toothpaste I want. I just want some toothpaste. There's not really a truly accepted happy path just yet, but it is getting better. Things are maturing. We're building schools. We're building hospitals still. There's a lot of a need for libraries and blog posts and people finding these happy paths. So take me aside for 15 minutes. There are screencasts being released right now. There's a thing called EmberSparks where he's teaching people how to set up your and bootstrap your application environment. We're all still sort of figuring this out though. So be prepared for a little bit of like rough takeoff on this deal. All right, another thing is testing Ajax can feel a little intimidating when you're trying to test JavaScript. But it's actually pretty simple. There are multiple libraries to do this kind of thing. I like IC Ajax. It's a way to basically build fixtures. Well, it intercepts Ajax calls and allows you to inject fixtures in. So here we're going to test each path through the experience. In this one, we're testing that clicking submit shows a success message. So we just want to go through and verify that all the things that the code says it does, it's actually doing. That we're not changing any code. We're just wrapping it in test existing. And that passes. Okay, so at this point, we repeat for each path to create sort of an integration test for the entire application, stubbed at the API level. So this took several hours, but it's really important. As I said, if you don't have a test harness, I do not know how you can refactor. Maybe if somebody has another answer, we can discuss it, testing is, it's not my favorite thing in the world. But we can now move forward with some confidence. So go ahead and take yourself a victory lap. You earned it. This is however just the start. All right, now step three is to identify models. So you have this blob of code. Like how do you find models in here? Well, your server and NBC might give you some hints. I don't believe that your models will map one to one, but it's a really great place to start. So in this one, we actually get to start driving with a test. Sometimes I test drive, sometimes I don't. I'm not an expert at either style. So, but I do think that in this case, it was a pretty good to say, hey, I know that I have a model and I know part of what a model is gonna do is to parse out an animated GIF URL and tell me whether it is one or is not one. So with no code, that thing should fail and it does. All right, now let's extract it. We can actually extract some of that logic to a model and we can extract the animated GIF link from the post body and give it a property here. This is called a computed property where you see parsed URL. It does some functioning stuff and then it has a little declaration at the end that says property body. It means that we're gonna depend on the body, which is the blob of data that somebody just types in, the text that they type in and it's going to, at any time a person changes that, any time that change is gonna observe and update this parsed URL property on this object. All right, now those unit tests will pass and we can start turning that static content into the dynamic content using handlebars. This lets us kill some code. That's pretty awesome. This should get the older acceptance tests passing again. It is the coolest feeling in the world. To write some tests, take some code, like scrub some garbage out of it, do something really dangerous feeling, like jump off the cliff and know, like when you rerun those tests and they start passing again and you start getting green again after a refactor. It's really fun. And in this case, we didn't do that much. We didn't have to write that much code because we let the framework carry our match luggage for it, which we cannot live without. So the models hold on to your data, they keep it up to date and the changes in the DOM are just gonna automatically propagate out of that. So now we're gonna lean even harder into the framework. It actually is sort of a fun part. Identifying the states is more fun than identifying models, I think, because we get to go back through the app and pick out what these states are. So in this little widget, the first state is a blank state, an initial state where the button is just visible and nothing else is. Then when we click it, the button goes away, the thing is in a ready to save state. While data is in flight, we're gonna disable the post button, leave everything else the same. And on an error state, we're gonna leave the text intact, but display a message. And on success, we're going to display a success message and hide the form. After five seconds, we want it to reset to that initial state. That's kind of the business logic that we wanted in the first place, but we incrementally built it. And that's an okay way to find out what you want, but not a great thing to shift to production, as we found. So the component starts in this initial state. We bind that state to a class on the components DOM. And then we'll use that later to let CSS manage what is shown and what is hidden. We want the DOM to just be a representation of the state of the app. The DOM is just there to represent the app's state at any given time. It's kind of almost read-only. So now instead of managing the DOM with jQuery, we're gonna have buttons fire off actions that just push the state around. Like you go here, you go here. They're sort of like the train conductors in a Japanese train station. It's kind of a lazy developer's state machine, but it's gonna do for now. All right, step four, that's done. That was all the code we needed for state. Step four is to break up the remaining code left in code jail. The states and model are in place and they're tested, but there's a couple of ugly things left. So let's look at it. All right, so code jail is not empty. The legacy code still reaches outside the component to delete things in sort of a wonky way. And, hi, how are ya? I wanna rub your nose in this code, even though I'm the one that wrote it. What could possibly go wrong here, right? This post is pretty scary, right? It's painful to modify. It invites pain for the user, but listing posts is outside the responsibility of this component we've created. So what can we do about it? Well, actually we have a pattern that we've already laid out. Let's create another component and sprinkle it in for listing those posts. Another quick detour into Ember data. At this point, I had a choice to make. Do I wanna make this, sharing this information with you more complicated by talking about Ember data? And I think I do. It actually made the next steps much easier. And this detour actually only took me about 20 minutes to replace the model with an Ember data model. Ember data is basically a wrapper that talks to Ajax for you and converts to an Ember model for you. So it buys us lots of good things. It basically took just a few minutes to do. That's it. We just declare it as a model on Ember data. I like to wire in ICAJax, just like we did before, to Ember data. And this is all the work that it takes to do. Fixtures will still work as written. This was all it took to get the tests passing again. That's pretty much it for the list component. As you can see, I have a delete function placed to reference the list. That's it. It has a list of those posts and a way to delete one of them. And all I'm doing is destroying a model record. So the second set of tests here is pretty much gonna follow the first. This test shows that the animated gifts show up as expected. And from here, we can drive out the delete functionality. So we have a second template to replace the server side markup. And then we sprinkle it in just like the first one. We just say, hey, jQuery, take this component and stuff it into the DOM for me where that list of posts used to be. And Ember's gonna show that for us now. Well, that's interesting. We have two components. How are they sort of talking to each other? Well, they both react to changes in underlying data. There's a pool underneath that is the same shared data set, but the components are completely isolated from one another. They can only communicate by altering that pool of underlying data. So changes in one place can affect the other. There's a lot of boilerplate code we did not write here. We just trust that the data layer is gonna do its job and the DOM will represent it properly. So one thing that happened though is because we're not doing stuff with jQuery UI animation stuff anymore, we lost show hide functionality. So let's put that back. We're gonna use CSS transitions which buys a lot of benefits including hardware acceleration on more modern browsers. So remember how we bound class name to form state earlier? We said, okay, like there was a thing there that says form state is bound to the class name for this component. So now we get these classes for free automatically. Ember's gonna stuff that into our component every time the state changes. So it pushes the state, it changes the name of the class. So I like to start by creating placeholders for the various states in a given component. And then put different behaviors under those states. So in this you can kind of see it almost tells a story that we start an initial state with a height of zero picks and an opacity of zero and then once, let's see, sorry. And then once it's in another state, it actually expands. So everything except initial, it will transition to that state. So we transition open to visible with 200 millisecond delay. And a, you know what, it's actually not great. I'm just gonna show it to you. It's not great to try to explain how CSS animations work. So let's do that. Let's see. Do you think I need to make that window smaller? It's great though. Thanks, Obama. So we're gonna submit and now it expands. And here we're in a validation error state. And so we have the GIF preview. We have zero characters because that smart preview is telling us that we're not using up any characters. And we'll post it. Oh, I just got trolled by Chrome caching. This one is just great. Julie Andrews is so awesome. Okay, I have many of these that I really love very much. Okay, but instead of doing that all day, maybe we should get back to the talk. Okay. So what we're not doing is we're not manipulating the DOM directly. If we want, our test can actually relax about the DOM a little bit. We don't necessarily need to test the framework. What we can focus on is application logic. We can still integration test if we want. But let's look back and see what we've done so far. There's some old code right here. Let's see if you can locate the business logic in here. Right, you can't. That's why I'm introducing a powerful encryption algorithm called JQCS 512 bit. It scatters your business logic across hundreds of lines of jQuery code. So you can stop worrying about whether hackers are gonna access your business logic in your front end because even your programmers can't. That's cloud engineering folks. Also trademark. So that turns out not to be such a super hot idea, right? We've now refactored this into a place where we moved that encrypted logic into an exposure via computed properties, states, and models. The business logic is actually front and center now. So we've gone from this sack of hot garbage to a tested and documented reliable implementation. It's not perfect, but now it begs to be extended and reused. So from here, what happens next is really up to you. You can, from here, you really actually, most of the rendering that's happening on the page is being done by Ember. So if you want to replace it and get all the benefits of having a router underneath your app, great. Go nuts. You can actually now take application handlebars and have it render those two components for you. And you're maybe a few hours from having a full single page application. Or you can continue to sprinkle in more components and let your Rails app do all the driving and let your components do the more dynamic pieces of your application for you with that pool of shared data underneath it. But now my brain is tired. Like, why do we do all this stuff? What even is my life? We had one job to do, right? A job that we were just about to quit. But right before you became millionaires in the IPO. It turns out recently, I found out a couple of years ago, I quit a job that just recently IPOed. Anyway, so I would, yeah, some yacht, yeah. Anyway, but we didn't quit because we love our users, right? We love our coworkers and we want to love our job. And software development, it really is fun. It can be frustrating, but it shouldn't give you night sweats. So let's try this one more time against our new and improved code base. Once we know the API, it's a small test to just verify that this thing does what we want. We can add a little favorite or like feature. We stub out the data, test that a favorite makes it favorite and an unfavorite makes it unfavorite. Build a little favorite model that talks to the server and it has many relationship here. You can see DS belongs to GIF posts and it has many on the other side. And add some dynamic content to the handlebars data or the handlebars template. So then we write a toggle action to create or destroy the favorite. And that's pretty much it. If Chrome caching will smile upon me, we will demo that as well. I'm gonna switch my branch. Everybody knows this trick, right? And also everybody knows the trick of typing Rails S. It's a little known thing. Most people don't know. It's how you load a Rails server up. So you can see my responsive design is so badass. Whoa, star just flies all around. All right, so now we can favorite this thing. And it's actually talking to the server on the back end. But it was so easy to do this that we actually were like, well, do you want me to filter this favorites for you? Cause I can do that and just show you my favorite ones. Oh, this one, this is legendary, right? So now we have all, we have favorites. If I unfavorite something, it will automatically pop out of the list. I'm not managing any of this stuff. I just built a little tiny filter that took like five minutes to do. This stuff becomes, it buys you so much and extending this actually becomes very fun. So we've changed our relationship now to this code base where we actually like working on it. We wake up in the morning instead of feeling sick about what's gonna be in our inbox. We're actually really excited about what we get to do next. So I just wanna tell you as a sort of an addendum to this that my personal story about, my first conference was about four years ago. And I think a lot of people, can I get a show of hands of who's here that's like pretty much their first conference? Okay, so I'm gonna tell you that it's a really great portion of the room. My first conference, I went to a hack night the night after the conference and it was put on by some really great people but I walked in and I looked around and I didn't know anybody. And I like listened to some people talk and they were talking, I was just learning the program. I was listening to people talking, they were so smart and they were people that were so well known in the community and I was so nobody that I immediately turned around, left, ran out of the room as fast as I could, got in my car and cried and drove home. Which is pretty awesome, I'm like super cool guy. After that point, the community picked me up and dusted me off and said get back in there kiddo. And many people in that community that I didn't know in the room at the time became some of my closest friends. These people in this room if you look around are some of your future closest friends and colleagues and mentors. And the community is the reason that I get to do this for a living when before I was doing just horrifying things if you can imagine what it would be like to do marketing for a multi-level marketing corporation. Just imagine the existential hell and imagine programming, we're pretty lucky to get to do this and I want everybody to have as good a time writing software as I get to have when I'm doing stuff like this. And the other thing I want to say, the last note I want to say on community is we have a tendency to do this sort of tent pole thing where we raise some people up and then gather around those people. That's not really what a community is about. A community is a mesh, it's not like hub and spoke. And every person in here has something to contribute and something amazing to do and I can't wait to go to your talks later. I'm told I'm pretty good at hugs. So I'm told I'm pretty good at hugs. So come say hi to me and thank you so much.