0:00:16.655,0:00:18.387 Brandon:Oh, hi. 0:00:18.387,0:00:20.877 A hush falls over the room[br]because I'm not paying attention. 0:00:21.434,0:00:22.767 My slides came up. Hi. 0:00:25.551,0:00:27.090 Really quick first, 0:00:27.512,0:00:30.517 there are seats in the middle[br]if people can squish together, 0:00:31.873,0:00:33.990 otherwise people are[br]going to be sitting in the 0:00:33.990,0:00:37.349 aisles and the fire marshal[br]is going to get angry. 0:00:38.651,0:00:41.849 I don't know that, I'm not a building guy. 0:00:42.947,0:00:44.764 Hi everybody, sorry to[br]make you move around 0:00:44.764,0:00:46.354 but also maybe that will[br]wake you up a little bit. 0:00:46.354,0:00:47.593 This is going to be a shot of espresso, 0:00:47.593,0:00:48.960 we've got to go, go, go, go. 0:00:49.067,0:00:51.890 I have a very serious talk[br]about the heart of architecture. 0:00:53.828,0:00:57.526 As you know, as DHH said at the[br]first talk, we are engineers. 0:00:57.526,0:00:59.503 What we do is build bridges with code. 0:01:01.698,0:01:04.741 We are architects, we build[br]centuries old castles. 0:01:05.772,0:01:09.038 We are craftspeople, we are[br]old-timey metal workers. 0:01:09.388,0:01:10.853 And we live in the cloud. 0:01:10.853,0:01:12.959 I think Javascript is ready[br]for all of these things. 0:01:13.631,0:01:16.809 I feel like Javascript is[br]ready for Cloudgineering. 0:01:20.574,0:01:22.165 If anybody knows what any of the things 0:01:22.165,0:01:23.943 I said with the pretty pictures are, 0:01:23.943,0:01:26.221 please grab me after the[br]talk and explain them to me. 0:01:26.682,0:01:29.154 I just say them to sound smart and serious 0:01:29.154,0:01:31.116 about programming, it is serious business. 0:01:31.116,0:01:32.225 Hi I'm Brandon Hayes, 0:01:32.225,0:01:34.935 I work with Charles[br]actually at The Frontside. 0:01:35.308,0:01:41.748 I'm a dedicated Cloudgineer[br]and no one ever asks which of 0:01:41.748,0:01:44.087 us is the smart one when[br]we converse together, 0:01:44.087,0:01:45.549 which is a little weird. 0:01:45.778,0:01:46.975 These are my credentials. 0:01:46.975,0:01:49.352 As you can see I'm highly credentialed and 0:01:49.352,0:01:51.349 ready to tell you all about programming. 0:01:52.369,0:01:54.024 My wife gave me a few of these, 0:01:54.024,0:01:55.850 most of them are actually true. 0:02:00.271,0:02:02.350 I'm not here to talk about some 0:02:02.350,0:02:06.897 core ideal or some big fancy thing. 0:02:07.334,0:02:08.132 I live in the real world. 0:02:08.725,0:02:12.972 I have to write programs that[br]people want written fast and 0:02:12.972,0:02:16.693 want them yesterday and it's[br]very challenging some times. 0:02:17.389,0:02:21.122 I understand that[br]architecture is great but 0:02:21.122,0:02:22.978 I don't have a lot of use[br]for ivory tower people, 0:02:22.978,0:02:25.284 I think the universe has[br]plenty of uncles in it. 0:02:26.587,0:02:28.695 We live in a place, 0:02:29.148,0:02:31.070 and I'm going to tell you a[br]tale about a couple of places. 0:02:31.557,0:02:33.521 It's actually a meta talk about the 0:02:33.521,0:02:35.099 ball of mud architecture pattern, 0:02:35.099,0:02:36.710 that's one I can really get behind. 0:02:36.929,0:02:39.563 If you're not familiar[br]with this, Brian Foote, 0:02:39.563,0:02:43.288 I believe in the late 1970s,[br]described an architecture 0:02:43.288,0:02:46.149 pattern that everyone here has[br]seen called the ball of mud. 0:02:47.349,0:02:48.693 To do that I need to[br]talk about city planning. 0:02:50.006,0:02:51.743 Most cities are not designed for growth. 0:02:52.320,0:02:53.976 Salt Lake City would be a rare exception. 0:02:54.683,0:02:57.350 You'll see it handled its[br]eventual growth pretty well. 0:02:58.413,0:03:00.839 From layout to infrastructure[br]it seems to have avoided 0:03:00.839,0:03:03.515 many of the problems[br]that plague large cities. 0:03:04.163,0:03:06.122 Our code does not live in Salt Lake City, 0:03:06.122,0:03:07.376 they don't work like that. 0:03:08.288,0:03:11.272 My current home town of[br]Austin is a lot more typical. 0:03:13.048,0:03:15.510 I look at that every day[br]on my drive home while 0:03:15.510,0:03:17.852 Charles rides his bike[br]home, which is great. 0:03:18.223,0:03:19.678 I get to sit in that every day for 0:03:19.678,0:03:21.330 about 45 minutes on the way home. 0:03:21.772,0:03:23.664 The city layout and[br]infrastructure was not prepared 0:03:23.664,0:03:25.819 for the kind of growth[br]that they've experienced. 0:03:26.165,0:03:28.489 That results in the dreaded urban sprawl. 0:03:29.458,0:03:31.612 But we don't actually even live here. 0:03:31.637,0:03:33.445 Let's be honest about our[br]code for a minute people. 0:03:34.054,0:03:35.127 We live here. 0:03:37.761,0:03:39.531 It's not a sprawling metroplex 0:03:39.531,0:03:40.934 or a beautifully planned city. 0:03:40.934,0:03:42.562 We live in a favela. 0:03:42.631,0:03:45.307 A favela is a Brazilian slum, basically. 0:03:45.307,0:03:46.902 It looks like cool though, right? 0:03:47.041,0:03:51.116 It's the definition of a[br]walkable city -- well, hikeable. 0:03:51.869,0:03:53.494 Let's zoom in. 0:03:54.617,0:03:57.835 A favela is a Brazilian[br]shanty town made permanent. 0:03:58.382,0:04:02.384 The structures require little[br]skill to create and they 0:04:02.384,0:04:05.830 pop up everywhere out of[br]whatever materials can be found. 0:04:06.214,0:04:08.102 The problem is these structures are 0:04:08.102,0:04:10.350 difficult to grow, to maintain or protect. 0:04:10.898,0:04:13.319 There's little police[br]presence or fire presence, 0:04:13.465,0:04:15.929 and safety and crime[br]issues are pretty rampant. 0:04:17.244,0:04:19.351 Forget architecture stuff, 0:04:19.353,0:04:21.414 we're going to go in to a code favela, 0:04:21.866,0:04:23.354 it will look familiar to you. 0:04:23.354,0:04:24.929 You've probably had some that made you 0:04:24.929,0:04:26.897 nearly go crazy trying to maintain it. 0:04:27.320,0:04:29.244 I apologize in advance[br]for making you look at 0:04:29.244,0:04:31.773 this but I really need[br]you to feel my pain. 0:04:34.020,0:04:36.913 That favela is a[br]manifestation of the ball of 0:04:36.913,0:04:39.147 mud pattern, which is[br]really easy to create. 0:04:39.229,0:04:42.137 You just need to build[br]something temporary, 0:04:42.137,0:04:44.972 add to it, and then rely[br]on it for your business. 0:04:45.241,0:04:47.319 They're so easy to create[br]that it's the dominant 0:04:47.319,0:04:50.565 architecture pattern, I would[br]contest, in software today. 0:04:51.680,0:04:53.164 Let's talk about how this happens. 0:04:53.867,0:04:55.213 Should be pretty easy right, 0:04:55.213,0:04:56.679 you can probably make[br]this happen this week. 0:04:58.765,0:05:02.437 I need a show of hands.[br]How many of you hate being 0:05:02.437,0:05:04.494 asked to raise your hands in a talk? 0:05:05.684,0:05:08.477 I should see no hands, that is insane. 0:05:09.523,0:05:11.419 How many of the rest of you have a 0:05:11.419,0:05:13.504 prototype that is shipped to production? 0:05:14.666,0:05:16.351 Pretty good balance there. 0:05:20.445,0:05:21.773 They say, "This is a two week feature, 0:05:21.773,0:05:23.102 "let's ship this thing in two weeks." 0:05:23.373,0:05:24.483 I don't believe in two week features, 0:05:24.483,0:05:25.872 I don't think that's actually a thing. 0:05:26.337,0:05:28.540 We do try to cram features[br]in to two weeks and then make 0:05:28.540,0:05:31.307 sacrifices to get them out the[br]door, or we inherit code from 0:05:31.307,0:05:34.118 less experienced developers[br]and it has to ship. 0:05:34.809,0:05:37.678 But mostly these shanty towns[br]start as a quick prototype. 0:05:38.915,0:05:40.790 Let's go ahead and build a shanty town. 0:05:41.417,0:05:43.009 It starts off like pretty much any other. 0:05:44.492,0:05:46.417 Let's say we're all working on Giffindor. 0:05:46.774,0:05:48.727 It's a social network for animated gifs. 0:05:49.888,0:05:52.138 The founder is a huge Harry[br]Potter fan, cosplayer, 0:05:52.152,0:05:54.618 the whole thing. Has the[br]glasses, it's adorable. 0:05:54.667,0:05:55.945 Personally I'm more a Hufflepuff, 0:05:55.945,0:05:57.259 this is not my website though. 0:05:57.887,0:06:00.399 It's a vanilla server-side app in Rails. 0:06:01.290,0:06:04.680 One note on pronunciation.[br]I'm going to stake a stand. 0:06:04.680,0:06:07.227 I'm going to say that gif is[br]pronounced like GitHub Gist. 0:06:09.178,0:06:11.461 I do the same thing[br]with JSON and [JAY-sin]. 0:06:11.961,0:06:12.867 I like to make everybody mad. 0:06:12.867,0:06:14.977 Mix tabs and spaces, people love me. 0:06:15.932,0:06:16.617 Back to work. 0:06:17.510,0:06:19.946 Let's just sprinkle in[br]a little interactivity. 0:06:21.013,0:06:22.392 Let's start with sprinkles, they're fun, 0:06:22.392,0:06:23.713 sprinkles are fun, yay! 0:06:25.523,0:06:28.445 Your boss calls. She says,[br]"We want a better experience 0:06:28.445,0:06:30.193 "on the site. Our users[br]demand it. They should not 0:06:30.193,0:06:32.445 "have to go through a[br]page refresh all the way 0:06:32.445,0:06:34.696 "to the new page to submit[br]a new animated gif." 0:06:36.148,0:06:37.320 You look at your Javascript file. 0:06:38.950,0:06:41.511 Nothing there, undaunted[br]you march forward. 0:06:42.117,0:06:44.665 Easy right? Just make a little HTML form 0:06:44.665,0:06:46.941 on the page with show hide, all done. 0:06:48.196,0:06:51.037 That worked, except it submits and 0:06:51.037,0:06:52.871 does a full page refresh on submit. 0:06:52.871,0:06:54.070 "Can you do that by AJAX, 0:06:54.070,0:06:55.754 "it's kind of irritating to our users?" 0:06:56.195,0:06:57.896 All right, that's what AJAX is for, right? 0:06:57.946,0:06:59.973 We submit this thing via AJAX. 0:07:00.867,0:07:03.103 That seems to work, all right. 0:07:03.510,0:07:05.792 But now you actually[br]have to add that new POST 0:07:05.792,0:07:08.292 to the list of POSTs[br]that are on that page. 0:07:08.946,0:07:09.853 All right, no problem. 0:07:10.445,0:07:12.274 Okay, a little bit of a problem. 0:07:13.087,0:07:16.139 We're starting to duplicate[br]some DOM code here in your 0:07:16.139,0:07:18.877 Javascript so you get to[br]edit stuff in two places. 0:07:19.304,0:07:23.623 A little duplication. We know,[br]we don't de-duplicate first. 0:07:24.837,0:07:26.620 You're agile so you agile that code right 0:07:26.620,0:07:29.277 in there until this whole thing is agile![br](laughter and applause) 0:07:29.861,0:07:32.649 By the way that's a trademark[br]of Cloudgineering Inc. 0:07:32.663,0:07:35.616 so do not use that without[br]written permission. 0:07:37.200,0:07:39.792 So this sprinkle is starting[br]to turn in to a little more 0:07:39.792,0:07:42.633 of a rain shower, a little[br]bit of a steady rain. 0:07:42.633,0:07:45.128 But cheer up Keanu, we[br]shipped some software, right? 0:07:46.382,0:07:49.415 Okay, sport. The product[br]manager, who tends to look 0:07:49.415,0:07:52.133 like Fred MacMurray for some[br]reason, is really happy. 0:07:52.648,0:07:55.416 He has more ideas. He wants[br]users to be able to click 0:07:55.416,0:07:57.492 a cancel button so that[br]they zero out the form, 0:07:57.492,0:07:59.399 because if you open it[br]it's just stuck there. 0:08:00.648,0:08:02.798 Dutifully you implement the cancel button 0:08:02.798,0:08:04.706 and zero out the form with jQuery. 0:08:04.933,0:08:07.852 Awesome, except now users[br]are hitting submit on 0:08:07.852,0:08:10.134 empty and invalid forms,[br]so we need some sort of 0:08:10.134,0:08:12.542 client-side validation to[br]prevent that from happening. 0:08:12.696,0:08:14.292 It shouldn't be too hard to tell if 0:08:14.292,0:08:17.091 somebody has attached[br]an animated gif link. 0:08:19.030,0:08:21.956 It wasn't super, super[br]easy but it was relatively 0:08:21.956,0:08:24.294 straight forward. We disable[br]the submit button unless 0:08:24.294,0:08:26.726 it's valid and show messages with jQuery. 0:08:27.292,0:08:29.008 This is starting to look[br]a little weird, right? 0:08:29.031,0:08:30.772 It's starting to really come down. 0:08:32.306,0:08:33.580 Poor Al Roker. 0:08:34.789,0:08:36.697 Your CEO comes in to congratulate you 0:08:36.697,0:08:38.260 on all the great work you've done. 0:08:38.260,0:08:40.712 You've really shipped a lot[br]of code and agiled everything 0:08:40.712,0:08:43.821 and you just need a[br]couple more enhancements. 0:08:44.058,0:08:46.933 Let's add an inline preview[br]for that image so users know 0:08:46.933,0:08:49.254 what they're about to[br]post before they post it, 0:08:49.297,0:08:51.765 and a little character[br]count that doesn't ding them 0:08:51.765,0:08:53.977 for long urls. We want[br]a smart character count. 0:08:55.602,0:08:57.292 That's working but[br]actually broke a couple of 0:08:57.292,0:08:59.807 other things about the state of this form. 0:09:00.011,0:09:03.483 We do some double checking[br]and enable or disable submit. 0:09:04.697,0:09:06.730 Now you're caught[br]between these two worlds. 0:09:06.730,0:09:09.523 You want to craft code that[br]you can be proud of and that 0:09:09.635,0:09:12.525 lets you feel good about[br]the things that you do, 0:09:12.624,0:09:14.481 but you also want to[br]be able to ship stuff. 0:09:14.481,0:09:16.692 Your business needs you to[br]move fast and break things. 0:09:16.702,0:09:20.399 You need to get stuff done,[br]GSD. Craftsmanship, ship it. 0:09:20.516,0:09:22.300 I say craftmanship it. 0:09:22.377,0:09:24.777 (laughter) 0:09:24.777,0:09:28.392 (hesitant applause) 0:09:29.484,0:09:31.256 It's a good thing you're[br]a cloudgineer and you 0:09:31.256,0:09:33.370 can straddle these two[br]worlds just perfectly. 0:09:34.181,0:09:36.820 Look at all this code that[br]we've craftsmanshipped. 0:09:38.245,0:09:40.945 Sandy Metz talked[br]yesterday about code shape 0:09:40.945,0:09:42.787 and the squint test as an indicator. 0:09:42.787,0:09:45.630 When I squint this code has a shape and 0:09:45.630,0:09:47.656 that shape is a sack of hot garbage. 0:09:47.656,0:09:50.102 (laughter) 0:09:50.102,0:09:51.849 I don't know if Chicago[br]has this but in Manhattan 0:09:51.849,0:09:54.119 in the summer time you get this nice smell 0:09:54.119,0:09:56.115 wafting off of the hot[br]garbage, it's great. 0:09:56.381,0:09:57.843 That's kind of how it feels. 0:09:58.277,0:10:03.035 Here we are, a total tsunami[br]of entangled jQuery code. 0:10:03.035,0:10:05.675 (laughter) 0:10:05.675,0:10:07.775 Let's ship a feature against that. 0:10:10.476,0:10:13.256 Please, it's really important! 0:10:14.204,0:10:16.411 Your CEO is now putty in your hands, 0:10:16.411,0:10:18.819 you are a superstar[br]developer and the expectation 0:10:18.819,0:10:21.374 is now that you just shipped so fast. 0:10:21.374,0:10:23.809 And a light button, let's do it. 0:10:23.901,0:10:27.005 Here's the thing. I was going[br]to implement this in jQuery, 0:10:27.323,0:10:28.958 I was going to do it[br]but there was already so 0:10:28.958,0:10:31.071 much double checking and[br]interwoven states that 0:10:31.071,0:10:34.146 I physically couldn't[br]without getting really ill. 0:10:34.680,0:10:36.583 The thought of touching[br]this code made me want 0:10:36.583,0:10:38.275 to quit writing the talk and just be like, 0:10:38.275,0:10:40.147 "You know what RailsConf, thanks anyway." 0:10:41.283,0:10:43.107 Now what, what do we do? 0:10:43.380,0:10:46.054 Actually Brian Foote has prescriptions for 0:10:46.054,0:10:47.286 dealing with the ball of mud pattern, 0:10:47.286,0:10:48.916 and it's not always what you think. 0:10:48.916,0:10:51.190 You don't necessarily dive[br]right into a refactor. 0:10:51.450,0:10:53.470 Addressing a ball of[br]mud is pretty difficult. 0:10:53.685,0:10:55.386 We can sweep it all under the rug, 0:10:55.386,0:10:57.033 or put it inside of a black box. 0:10:57.586,0:10:58.978 You can reconstruct it, 0:10:58.978,0:11:02.672 tear the whole thing down[br]and raze it and rebuild it. 0:11:02.786,0:11:04.036 You can renovate block-by-block, 0:11:04.036,0:11:05.768 which he calls keeping it working, 0:11:05.914,0:11:08.517 or you can quit you job,[br]which in some cases, 0:11:08.517,0:11:10.797 sometimes it's the thing to do. 0:11:11.637,0:11:13.459 Black box is fine if you know you're never 0:11:13.459,0:11:15.150 going to have to touch that code again. 0:11:15.150,0:11:16.686 If it's some complicated math equation or 0:11:16.686,0:11:18.156 something I've seen that done, where you 0:11:18.156,0:11:20.668 just hide it in the[br]closet and that's fine. 0:11:21.252,0:11:23.976 A rewrite is a great way[br]to learn really amazingly 0:11:23.976,0:11:27.007 hidden lessons about your business logic. 0:11:27.133,0:11:29.240 Things that are encoded[br]in very strange places. 0:11:29.416,0:11:31.009 It's a really great way[br]to make something that 0:11:31.009,0:11:33.253 sounds like it takes two[br]weeks take six months. 0:11:35.589,0:11:38.408 I feel like you always[br]discover that hidden 0:11:38.408,0:11:40.970 business logic so let's[br]talk about a refactor. 0:11:41.511,0:11:42.972 Why would we do that? 0:11:43.697,0:11:45.358 We decided that refactor[br]is probably the right 0:11:45.358,0:11:46.761 thing to do because the feature has to be 0:11:46.761,0:11:49.193 maintained but it's now[br]too expensive to manage. 0:11:49.331,0:11:51.240 Users are starting to[br]actually have a bad time with 0:11:51.240,0:11:53.216 it because the longer[br]they stay on the page the 0:11:53.216,0:11:55.457 more likely they are to[br]have problems with it. 0:11:56.417,0:11:58.958 And more importantly to me personally is 0:11:58.958,0:12:00.807 that you are tossing[br]and turning all night. 0:12:00.807,0:12:02.662 You cannot sleep because[br]you're dreaming about the JIRA 0:12:02.662,0:12:04.552 tickets that are waiting[br]for you in the morning. 0:12:04.552,0:12:06.396 Why are we still using[br]JIRA, why is that a thing?! 0:12:06.396,0:12:08.085 Okay, anyway, separate deal. 0:12:09.922,0:12:12.584 You think about your[br]frustrated users, your gut is 0:12:12.584,0:12:15.111 telling you to fix it and[br]your gut is totally right. 0:12:16.446,0:12:17.977 You have two paths out of here. 0:12:17.977,0:12:21.038 I think the person in this[br]room, super smart guy, is like, 0:12:21.038,0:12:24.769 "Why don't you refactor this[br]to smart Javascript objects?" 0:12:25.353,0:12:29.486 He's largely right. That's an[br]ideomatic way to dig out of this. 0:12:29.634,0:12:32.111 He also asked me if I[br]did that as a strawman 0:12:32.111,0:12:34.663 of how to build really[br]terrible jQuery code. 0:12:34.949,0:12:39.256 I was like, "Yeees. I[br]was not doing my best." 0:12:40.675,0:12:42.241 The other option is to use a framework 0:12:42.241,0:12:44.697 to abstract away the DOM and handle data. 0:12:46.059,0:12:47.684 Our goal is to get the heck out of 0:12:47.684,0:12:49.308 the DOM as fast as humanly possible. 0:12:50.162,0:12:52.063 That's our biggest pain point right now. 0:12:52.388,0:12:54.203 For me I'll choose a framework. 0:12:54.209,0:12:55.478 The framework will manage the DOM and 0:12:55.478,0:12:57.101 we'll just manage the underlying data. 0:12:58.401,0:13:01.366 All we need to do now is[br]five steps to get out. 0:13:02.634,0:13:04.983 These steps will probably[br]apply for people that 0:13:04.983,0:13:08.399 use plain Javascript and[br]don't use a framework, 0:13:08.399,0:13:10.306 or any framework that you choose. 0:13:10.306,0:13:12.162 It's just nice to build up against one, 0:13:12.202,0:13:13.662 personally I certainly prefer it. 0:13:14.679,0:13:16.834 On our blog we'll talk more about why 0:13:16.834,0:13:18.788 we choose Ember and why we like it, 0:13:18.788,0:13:21.197 and you heard Charles mention[br]earlier if you were here, 0:13:21.197,0:13:23.303 about why we like Ember's model layer. 0:13:23.431,0:13:25.912 I feel like it's a really[br]strong model layer for 0:13:25.912,0:13:28.038 the case that we're[br]trying to accomplish now. 0:13:28.038,0:13:29.588 It has really great[br]bindings and managed state, 0:13:29.588,0:13:31.099 and it's got a great drop in component 0:13:31.099,0:13:32.770 library to tie it all together. 0:13:33.371,0:13:36.955 Step one, let's rap it. Rap[br]it, rap it, rap it, wrap it. 0:13:40.313,0:13:42.289 A little sidetrack, a lot[br]of people don't realize 0:13:42.289,0:13:44.381 that you can sprinkle Ember into an app. 0:13:44.556,0:13:47.116 A lot of people think that[br]Ember only works if you want to 0:13:47.116,0:13:49.684 start an app from scratch and[br]build up from the ground up, 0:13:49.684,0:13:52.617 from floor zero all the way to[br]the top, but you can actually 0:13:52.617,0:13:54.479 apply it to a lot of[br]codebases and it's really 0:13:54.479,0:13:57.431 great for refactoring[br]existing codebases toward it. 0:13:58.051,0:14:01.626 That's just these three steps right here. 0:14:01.825,0:14:04.312 At The Frontside we do[br]that pretty often where 0:14:04.312,0:14:07.668 we take an existing Rails[br]application and move 0:14:07.668,0:14:11.161 it towards Ember, but it's[br]actually not that hard. 0:14:11.201,0:14:13.199 First things first it's[br]time for some justice. 0:14:13.199,0:14:15.619 We're going to put that[br]terrible code in code jail. 0:14:15.619,0:14:18.508 That code jail is this[br]initLegacyCode function. 0:14:18.508,0:14:21.778 We're going to create an Ember[br]component, we're going to 0:14:21.778,0:14:25.179 put the stuff in initLegacyCode,[br]which is not a special name, 0:14:25.179,0:14:28.635 I just chose it to tell[br]me that this is the jail. 0:14:28.635,0:14:31.542 It bootstraps the old[br]code inside the component. 0:14:31.542,0:14:33.675 We do not alter that code at all. 0:14:33.977,0:14:37.288 Also we move the HTML in to a handlebars 0:14:37.288,0:14:39.461 template associated with this component. 0:14:39.743,0:14:42.028 No structure of that[br]HTML actually changes, 0:14:42.384,0:14:44.038 we're just isolating. 0:14:44.918,0:14:48.366 Then we can sprinkle. Now we[br]use jQuery to stuff all of 0:14:48.366,0:14:51.677 this old stuff that we had[br]before back in to the DOM. 0:14:53.822,0:14:56.525 Another thing Sandy said[br]yesterday that I hope 0:14:56.525,0:14:59.163 it's self evident, it's certainly[br]made itself self evident 0:14:59.163,0:15:02.529 to me over the course of the[br]last year or two doing this, 0:15:02.529,0:15:04.425 that you have to test it. 0:15:04.713,0:15:08.575 If you do not test your code a refactor is 0:15:08.575,0:15:11.648 essentially impossible, I[br]cannot imagine trying to do it. 0:15:11.648,0:15:13.820 I was not a big testing advocate earlier. 0:15:13.820,0:15:16.930 I was very skeptical,[br]let's say, about testing. 0:15:16.930,0:15:19.641 I was raised by cowboy coders in my first 0:15:19.641,0:15:22.065 place when I was learning to program. 0:15:22.390,0:15:24.821 But we're going to do it and[br]we're going to see that it's 0:15:24.821,0:15:27.492 actually not that hard to[br]actually test the thing itself. 0:15:27.835,0:15:30.257 We're going to test that[br]it shows up and it passes. 0:15:33.684,0:15:35.418 I'm doing a little bit of a hand wave 0:15:35.418,0:15:38.148 here over Javascript testing setup. 0:15:39.181,0:15:43.435 Javascript test setup story[br]for getting Ember applications 0:15:43.435,0:15:47.016 bootstrapped in Rails can[br]be a little challenging. 0:15:47.016,0:15:48.985 There's a growing body[br]of knowledge about it. 0:15:48.985,0:15:50.991 I want to give you guys[br]a quick note on that. 0:15:51.011,0:15:52.835 On its own, Javascript[br]testing is pretty easy 0:15:52.835,0:15:55.005 but when you add in frameworks[br]and tie it to Rails, 0:15:55.021,0:15:56.478 add in the asset pipeline, 0:15:56.478,0:15:58.010 things can get a little complicated. 0:15:58.167,0:15:59.617 It's a little bit of a wild west, 0:15:59.913,0:16:01.085 there's a lot of choices out there. 0:16:01.335,0:16:02.790 There's a little bit of[br]paralysis of choice I think. 0:16:03.211,0:16:05.400 It's really wide open,[br]but not like home on the 0:16:05.400,0:16:09.332 range wide open, more like[br]this kind of wild west. 0:16:10.362,0:16:13.930 It can lead to that, you[br]look at the thing of, 0:16:13.930,0:16:15.663 "I don't know what brand[br]of toothpaste I want, 0:16:15.663,0:16:17.206 "I just want some toothpaste." 0:16:17.538,0:16:19.431 There's not really a truly accepted happy 0:16:19.431,0:16:21.355 path just yet but it is getting better. 0:16:21.992,0:16:23.433 Things are maturing,[br]we're building schools, 0:16:23.433,0:16:25.004 we're building hospitals still. 0:16:25.773,0:16:27.897 There's a lot of a need[br]for libraries and blog 0:16:27.897,0:16:30.811 posts and people finding[br]these happy paths. 0:16:30.811,0:16:33.080 Taking aside for 15 minutes,[br]there are screen casts 0:16:33.080,0:16:34.836 being released right now,[br]there's a thing called 0:16:34.836,0:16:37.806 Ember Sparks where he's[br]teaching people how to 0:16:37.806,0:16:40.414 set up and bootstrap your[br]application environment. 0:16:40.414,0:16:43.414 We're all still figuring this[br]out there, so be prepared 0:16:43.414,0:16:47.006 for a little bit of rough[br]take off on this still. 0:16:48.322,0:16:50.682 Another thing is testing[br]AJAX can feel a little 0:16:50.682,0:16:52.214 intimidating when you're[br]trying to test Javascript 0:16:52.214,0:16:53.491 but it's actually pretty simple. 0:16:53.491,0:16:55.308 There are multiple libraries[br]to do this kind of thing 0:16:55.308,0:16:56.914 I like ic-ajax. 0:16:59.995,0:17:03.663 It intercepts AJAX calls and[br]allows you to inject fixtures in. 0:17:04.760,0:17:09.314 Here we're going to test each[br]path through the experience. 0:17:09.444,0:17:11.085 In this one we're testing that clicking 0:17:11.085,0:17:13.009 submit shows a success message. 0:17:13.461,0:17:15.396 We just want to go through[br]and verify that all the 0:17:15.396,0:17:18.242 things that the code says[br]it does it's actually doing. 0:17:19.237,0:17:21.056 We're not changing any code, 0:17:21.056,0:17:23.423 we're just wrapping it in test existing. 0:17:24.528,0:17:25.744 And that passes. 0:17:26.325,0:17:28.855 Okay. At this point we[br]repeat for each path 0:17:28.855,0:17:31.066 to create an integration[br]test for the entire 0:17:31.066,0:17:33.676 application stubbed at the API level. 0:17:33.965,0:17:37.164 This took several hours[br]but it's really important. 0:17:37.164,0:17:38.514 As I said if you don't have a test harness 0:17:38.514,0:17:40.148 I do not know how you can refactor. 0:17:40.464,0:17:42.946 Maybe if somebody has another[br]answer we can discuss it, 0:17:42.946,0:17:45.481 because testing is not my[br]favorite thing in the world. 0:17:46.867,0:17:48.867 We can now move forward[br]with some confidence. 0:17:48.867,0:17:51.118 Go ahead and take yourself a[br]victory lap, you earned it. 0:17:51.118,0:17:53.051 This is, however, just the start. 0:17:54.483,0:17:56.711 Step three is to identify models. 0:17:56.711,0:17:59.743 You have this blob of code,[br]how do you find models in here? 0:17:59.743,0:18:02.167 Your server MVC might give you some hints. 0:18:02.712,0:18:05.609 I don't believe that your[br]models will map one to one, 0:18:05.609,0:18:07.885 but it's a really great place to start. 0:18:08.986,0:18:12.290 In this one we actually get to[br]start driving with the tests. 0:18:12.635,0:18:14.961 Sometimes I test drive, sometimes I don't, 0:18:14.961,0:18:19.033 I'm not an expert at either[br]style, but I do think that 0:18:19.033,0:18:21.979 in this case it was pretty[br]good to say, "I know that I 0:18:21.979,0:18:23.648 "have a model and I know[br]part of what a model is 0:18:23.648,0:18:26.949 "going to parse out an animated gif url 0:18:26.949,0:18:29.164 "and tell me whether it[br]is one or is not one." 0:18:30.605,0:18:33.640 With no code that thing[br]should fail, and it does. 0:18:34.652,0:18:36.748 Now let's extract it. 0:18:36.748,0:18:39.461 We can actually extract some[br]of that logic to a model. 0:18:40.308,0:18:43.230 And we can extract the[br]animated gif link from 0:18:43.230,0:18:45.648 the POST body and give it a property here. 0:18:45.648,0:18:47.991 This is called a computed[br]property where you see parsedUrl. 0:18:48.297,0:18:50.118 It does some functiony stuff[br]and then it has a little 0:18:50.118,0:18:52.165 declaration at the end[br]that says property body. 0:18:52.298,0:18:54.686 It means that we're going[br]to depend on the body, 0:18:54.686,0:18:57.727 which is the blob of data[br]that somebody just types in, 0:18:57.727,0:18:59.921 the text that they type in. 0:19:00.874,0:19:02.387 At any time a person changes that, 0:19:02.387,0:19:03.729 any time that changes[br]it's going to observe and 0:19:03.729,0:19:06.400 update this parsedUrl[br]property on this object. 0:19:08.540,0:19:13.183 Now those unit tests will pass[br]and we can start turning that 0:19:13.183,0:19:17.521 static content into the dynamic[br]content using handlebars. 0:19:18.597,0:19:21.246 This lets us kill some[br]code, that's pretty awesome. 0:19:21.579,0:19:24.888 This should get the older[br]acceptance test passing again. 0:19:24.888,0:19:28.820 It is the coolest feeling in[br]the world to write some tests, 0:19:28.820,0:19:31.479 take some code, scrub[br]some garbage out of it, 0:19:31.479,0:19:33.586 do something really dangerous feeling, 0:19:33.586,0:19:35.337 like jump off the cliff[br]and know, when you rerun 0:19:35.337,0:19:37.586 those tests and they start passing again, 0:19:37.586,0:19:39.236 and you start getting green[br]again after a refactor, 0:19:39.236,0:19:40.700 it's really fun. 0:19:41.311,0:19:42.842 In this case we didn't do that much, 0:19:42.842,0:19:44.227 we didn't have to write[br]that much code because 0:19:44.227,0:19:46.058 we let the framework[br]carry our matched luggage 0:19:46.058,0:19:48.428 for it which we cannot live without. 0:19:49.112,0:19:50.815 The models hold onto your data, 0:19:50.815,0:19:53.826 they keep it up to date and[br]the changes in the DOM are 0:19:53.826,0:19:56.790 just going to automatically[br]propagate out of that. 0:19:58.231,0:20:00.415 Now we're going to lean even[br]harder into the framework. 0:20:01.029,0:20:03.482 It actually is sort of the[br]fun part, identifying the 0:20:03.482,0:20:05.431 states is more fun than[br]identifying models, I think, 0:20:05.431,0:20:06.696 because we get to go back through the 0:20:06.696,0:20:08.337 app and pick out what these states are. 0:20:09.164,0:20:11.197 In this little widget the first state is 0:20:11.197,0:20:12.949 a blank state, a initial state where the 0:20:12.949,0:20:14.962 button is just visible[br]and nothing else is. 0:20:15.561,0:20:17.149 When we click it the button goes away and 0:20:17.149,0:20:19.086 the thing is in a ready-to-save state. 0:20:20.169,0:20:21.916 While data is in flight[br]we're going to disable 0:20:21.916,0:20:24.087 the post button, leave[br]everything else the same. 0:20:25.061,0:20:26.462 On an error state we're going to leave 0:20:26.462,0:20:28.915 the text intact but display a message. 0:20:30.747,0:20:32.547 On success we're going to display a 0:20:32.547,0:20:34.319 success message and hide the form. 0:20:34.513,0:20:37.162 After five seconds we want it[br]to reset to that initial state. 0:20:37.262,0:20:38.854 That's kind of the business[br]logic that we wanted 0:20:38.854,0:20:41.884 in the first place but we[br]incrementally built it. 0:20:41.884,0:20:44.700 That's an okay way to[br]find out what you want but 0:20:44.700,0:20:47.081 not a great way to ship to[br]production, as we found. 0:20:47.994,0:20:49.713 The component starts[br]in this initial state. 0:20:49.793,0:20:52.408 We bind that state to a[br]class on the component's DOM, 0:20:53.154,0:20:55.574 and then we'll use that later to let CSS 0:20:55.574,0:20:57.693 manage what is shown and what is hidden. 0:20:58.309,0:21:00.517 We want the DOM to just[br]be a representation of the 0:21:00.517,0:21:03.338 state of the app. The DOM[br]is just there to represent 0:21:03.338,0:21:05.269 the app's state at any given time. 0:21:05.374,0:21:07.687 It's kind of almost read-only. 0:21:08.106,0:21:10.186 Now instead of managing[br]the DOM with jQuery 0:21:10.186,0:21:11.416 we're going to have buttons fire off 0:21:11.416,0:21:13.087 actions that just push the state around. 0:21:13.479,0:21:14.764 "You go here, you go here," 0:21:14.764,0:21:18.574 they're like the train conductors[br]in a Japanese train station. 0:21:19.306,0:21:21.087 It's kind of a lazy developer's state 0:21:21.087,0:21:22.510 machine but it's going to do for now. 0:21:23.894,0:21:25.328 Step four, that's done. 0:21:25.328,0:21:26.763 That was all the code we needed for state. 0:21:27.009,0:21:29.634 Step four is to break up the[br]remaining code left in code jail. 0:21:29.810,0:21:31.868 The states and model are[br]in place and are tested, 0:21:31.868,0:21:33.598 but there's a couple of ugly things left. 0:21:33.731,0:21:36.774 Let's look at it. Code jail is not empty. 0:21:36.774,0:21:38.790 The legacy code still reaches outside the 0:21:38.790,0:21:41.756 component to delete things in a wonky way. 0:21:42.795,0:21:45.603 And, heh heh, hi, how are you. 0:21:46.809,0:21:48.759 I want to rub your nose in this code, 0:21:48.825,0:21:50.087 even though I'm the one that wrote it. 0:21:51.510,0:21:53.412 What could possibly go wrong here, right? 0:21:54.753,0:21:58.951 This POST is pretty scary.[br]It's painful to modify, 0:21:58.951,0:22:01.732 it invites pain for the[br]user but listing POST 0:22:01.732,0:22:03.827 is outside the responsibility[br]of this component 0:22:03.827,0:22:05.969 we've created so what can we do about it? 0:22:07.757,0:22:09.213 Actually we have a pattern[br]that we've already laid out. 0:22:09.213,0:22:10.369 Let's create another component and 0:22:10.369,0:22:12.041 sprinkle it in for listing those POSTs. 0:22:13.141,0:22:15.119 Another quick detour in to Ember Data. 0:22:15.311,0:22:16.778 At this point I have a choice to make. 0:22:16.778,0:22:20.462 Do I want to make sharing[br]this information with you more 0:22:20.462,0:22:22.900 complicated by talking about[br]Ember Data and I think I do, 0:22:22.900,0:22:24.792 it actually made the[br]next steps much easier, 0:22:25.064,0:22:27.672 and this detour actually[br]took me about 20 minutes to 0:22:27.672,0:22:30.073 replace the model with[br]an Ember Data model. 0:22:30.281,0:22:33.260 Ember data is basically a[br]wrapper that talks to AJAX 0:22:33.260,0:22:36.510 for you and converts to[br]an Ember model for you. 0:22:38.077,0:22:39.857 It buys us lots of good things. 0:22:39.964,0:22:41.791 Basically took just a few minutes to do. 0:22:41.904,0:22:46.369 That's it, we just declare[br]it as a model on Ember Data. 0:22:47.685,0:22:51.119 I like to wire in an ic-ajax,[br]just like we did before, 0:22:51.119,0:22:53.901 to Ember Data and this is all[br]the work that it takes to do. 0:22:54.166,0:22:56.198 Fixtures will still work as written. 0:22:56.252,0:22:58.887 This was all it took to get[br]the tests passing again. 0:23:00.264,0:23:02.041 That's pretty much it[br]for the list component. 0:23:02.041,0:23:03.666 As you can see I have a delete function, 0:23:03.666,0:23:05.574 a place to reference the list, that's it. 0:23:05.574,0:23:08.901 It has a list of those posts[br]and a way to delete one of them. 0:23:09.308,0:23:11.885 All I'm doing is[br]destroying a model record. 0:23:13.505,0:23:15.282 The second set of tests here is pretty 0:23:15.282,0:23:17.684 much going to follow the[br]first. This test shows 0:23:17.684,0:23:20.808 that the animated gifs[br]show up as expected, 0:23:21.041,0:23:23.495 and from here we can drive[br]out the delete functionality. 0:23:24.245,0:23:27.308 We have a second template to[br]replace the server-side markup 0:23:28.310,0:23:30.527 and then we sprinkle it in[br]just like the first one. 0:23:30.605,0:23:32.972 We say, "Hey, jQuery, take this[br]component and stuff it in to 0:23:32.972,0:23:35.432 "the DOM for me where that[br]list of posts used to be," 0:23:35.688,0:23:37.494 and Ember is going to[br]show that for us now. 0:23:37.513,0:23:39.113 That's interesting, we[br]have two components. 0:23:39.113,0:23:40.808 How are they talking to each other? 0:23:41.063,0:23:43.309 Well they both react to[br]changes to the underlying data. 0:23:43.309,0:23:46.059 There's a pool underneath that is the 0:23:46.059,0:23:47.885 same shared data set but the components 0:23:47.885,0:23:49.766 are completely isolated from one another. 0:23:49.766,0:23:51.728 They can only communicate by altering 0:23:51.728,0:23:53.497 that pool of underlying data. 0:23:54.532,0:23:56.588 Changes in one place can affect the other. 0:23:57.542,0:23:59.870 There's a lot of boilerplate[br]code we did not write here. 0:23:59.870,0:24:01.261 We just trust that the[br]data layer is going to do 0:24:01.261,0:24:03.552 its job and the DOM will[br]represent it properly. 0:24:05.177,0:24:07.779 One thing that happened though is because 0:24:07.779,0:24:11.214 we're not doing stuff[br]with jQuery UI animation 0:24:11.214,0:24:13.264 stuff any more we lost[br]show hide functionality, 0:24:13.264,0:24:14.555 so let's put that back. 0:24:15.091,0:24:16.636 We're going to use CSS transitions 0:24:16.636,0:24:17.854 which buys a lot of benefits, 0:24:17.854,0:24:21.198 including hardware acceleration[br]on more modern browsers. 0:24:22.245,0:24:25.366 Remember how we bound class[br]name to form state earlier? 0:24:25.563,0:24:28.016 We said there was a thing[br]there that says form 0:24:28.016,0:24:31.291 state is bound to the class[br]name for this component. 0:24:31.373,0:24:33.589 Now we get these classes[br]for free automatically, 0:24:33.716,0:24:35.015 Ember is going to stuff that in to our 0:24:35.015,0:24:37.312 component every time the state changes. 0:24:37.312,0:24:39.774 It pushes the state, it[br]changes the name of the class. 0:24:40.199,0:24:41.930 I like to start by creating placeholders 0:24:41.930,0:24:46.340 for the various states[br]in a given component, 0:24:47.436,0:24:49.964 and then put different[br]behaviors under those states. 0:24:50.171,0:24:52.356 In this you can see it[br]almost tells a story. 0:24:52.453,0:24:54.327 We start an initial state with a height of 0:24:54.327,0:24:56.464 zero px and an opacity of zero. 0:25:02.961,0:25:06.063 Then once it's in another[br]state it actually expands. 0:25:06.434,0:25:09.027 Everything except initial it[br]will transition to that state. 0:25:09.671,0:25:11.174 We transition open to visible 0:25:11.174,0:25:14.542 with a 200 millisecond delay and a ... 0:25:16.140,0:25:18.504 You know what, I'm just[br]going to show it to you. 0:25:18.504,0:25:21.167 It's not great to try to[br]explain how CSS animations work. 0:25:22.172,0:25:23.120 Let's do that. 0:25:31.465,0:25:33.044 I think I need to make[br]that window smaller. 0:25:35.939,0:25:37.652 That's great. Thanks Obama. 0:25:41.882,0:25:44.737 We're going to submit and now it expands. 0:25:44.737,0:25:47.859 Here we're in a validation error state. 0:25:50.809,0:25:52.507 We have the gif preview. 0:25:52.530,0:25:54.373 We have zero characters[br]because that smart preview is 0:25:54.373,0:25:57.188 telling us that we're not[br]using up any characters. 0:26:00.791,0:26:02.766 And we'll post it. 0:26:03.747,0:26:05.676 Oh, I just got trolled by chrome caching. 0:26:08.970,0:26:13.800 This one is just great.[br]Julie Andrews is so awesome. 0:26:18.030,0:26:20.402 I have many of these that[br]I really love very much. 0:26:21.844,0:26:23.547 Instead of doing that all day maybe 0:26:23.547,0:26:25.404 we should go back to the talk. 0:26:26.877,0:26:28.152 What we're not doing is we're not 0:26:28.152,0:26:29.878 manipulating the DOM directly. 0:26:29.892,0:26:32.120 If we want our tests can[br]actually relax about the DOM 0:26:32.120,0:26:35.224 a little bit, we don't need to[br]necessarily test the framework. 0:26:35.835,0:26:38.460 What we can focus on is application logic. 0:26:38.574,0:26:40.894 We can still integration test if we want 0:26:42.173,0:26:44.292 but let's look back and[br]see what we've done so far. 0:26:45.076,0:26:48.554 There's some old code right here. 0:26:48.554,0:26:50.631 Let's see if you can locate[br]the business logic in here. 0:26:52.786,0:26:54.373 Right? You can't. 0:26:54.373,0:26:56.261 That's why I'm introducing a powerful 0:26:56.261,0:26:59.145 encryption algorithm called jQCS, 512-bit. 0:26:59.597,0:27:01.185 It scatters your business logic across 0:27:01.185,0:27:03.043 hundreds of lines of jQuery code. 0:27:04.506,0:27:06.214 You can stop worrying[br]about whether hackers 0:27:06.214,0:27:07.918 are going to access your[br]business logic in your 0:27:07.918,0:27:10.637 front end because even[br]your programmers can't. 0:27:10.637,0:27:11.976 (laughter) 0:27:11.976,0:27:13.523 That's cloudgineering folks. 0:27:14.814,0:27:16.175 Also a trademark. 0:27:17.262,0:27:19.464 That turns out not to be[br]such a super hot idea. 0:27:20.556,0:27:22.919 We've now refactored[br]this into a place where 0:27:22.919,0:27:25.141 we've moved that encrypted[br]logic and exposed 0:27:25.141,0:27:27.509 it via computed properties,[br]states and models. 0:27:27.739,0:27:29.701 The business logic is[br]actually front and center now. 0:27:30.120,0:27:32.294 We've got from this[br]sack of hot garbage to a 0:27:32.294,0:27:34.832 tested and documented[br]reliable implementation. 0:27:34.832,0:27:37.996 It's not perfect but now it[br]begs to be extended and reused. 0:27:39.798,0:27:41.917 From here what happens[br]next is really up to you. 0:27:43.273,0:27:45.747 From here, most of the rendering that's 0:27:45.747,0:27:47.635 happening on the page[br]is being done by Ember. 0:27:47.715,0:27:49.606 If you want to replace it[br]and get all the benefits of 0:27:49.606,0:27:52.027 having a router underneath[br]your app, great, go nuts. 0:27:52.331,0:27:56.279 You can actually now take[br]application handlebars and 0:27:56.279,0:27:58.715 have it render those to components[br]for you, and you're maybe 0:27:58.715,0:28:01.058 a few hours from having a[br]full single page application. 0:28:01.386,0:28:03.657 Or you can continue to[br]sprinkle in more components 0:28:03.657,0:28:05.765 and let your Rails app do[br]all the driving and let your 0:28:05.765,0:28:08.376 components do the more dynamic[br]pieces of your application 0:28:08.376,0:28:10.820 for you with that pool of[br]shared data underneath it. 0:28:12.665,0:28:14.459 Now my brain is tired. 0:28:14.668,0:28:16.902 Why did we do all this[br]stuff, what even is my life. 0:28:18.407,0:28:22.322 We had one job to do, a job[br]that we were just about to quit, 0:28:23.940,0:28:26.777 but right before you became[br]millionaires in the IPO. 0:28:26.777,0:28:28.465 I found out a couple years ago I quit 0:28:28.465,0:28:33.515 a job that just recently IPO'd.[br]I would be on some yacht. 0:28:35.349,0:28:37.543 But we didn't quit,[br]because we love our users, 0:28:37.543,0:28:40.992 we love our coworkers, and[br]we want to love our job. 0:28:41.766,0:28:43.652 Software development, it really is fun. 0:28:43.827,0:28:46.947 It can be frustrating but it[br]shouldn't give you night sweats. 0:28:48.450,0:28:50.230 Let's try this one more time against 0:28:50.230,0:28:51.748 our new and improved code base. 0:28:51.748,0:28:53.763 Once we know the API[br]it's a small test to just 0:28:53.763,0:28:55.711 verify that this thing does what we want. 0:28:55.711,0:28:57.790 We can add a little[br]favorite or like feature. 0:28:58.795,0:29:02.122 We stub out the data, test that[br]a favorite makes it favorite 0:29:02.122,0:29:03.840 and an unfavorite makes it unfavorite. 0:29:04.391,0:29:06.234 Build a little favorite[br]model that talks to 0:29:06.234,0:29:08.946 the server and it has[br]many relationship here. 0:29:09.202,0:29:11.004 You can see DS belongs to gifPost 0:29:11.004,0:29:12.778 and it has many on the other side. 0:29:13.463,0:29:14.876 And add some dynamic content 0:29:14.876,0:29:17.170 to the handlebars template. 0:29:18.317,0:29:20.481 Then we write a toggle action to create or 0:29:20.481,0:29:23.154 destroy the favorite and[br]that's pretty much it. 0:29:23.793,0:29:26.736 If chrome caching will smile upon me 0:29:26.774,0:29:29.655 We'll demo that as well, I'm[br]going to switch my branch. 0:29:47.257,0:29:49.397 Everybody knows this trick, right? 0:29:50.557,0:29:53.086 Also everybody knows the[br]trick of typing rails s. 0:29:55.614,0:29:58.614 It's a little known thing,[br]most people don't know. 0:29:59.048,0:30:01.653 It's how you load a Rails server up. 0:30:02.391,0:30:04.357 (laughter) 0:30:06.911,0:30:09.139 You can see my responsive[br]design is so badass. 0:30:09.408,0:30:12.306 Woah, star just flies all around. 0:30:13.119,0:30:16.038 Now we can favorite this thing. 0:30:16.093,0:30:18.622 It's actually talking to the[br]server on the back end but 0:30:18.622,0:30:20.758 it was so easy to do this[br]that we actually were like, 0:30:20.851,0:30:23.115 Well, do you want me to filter[br]these favorites for you? 0:30:23.115,0:30:26.424 I can do that and just[br]show you my favorite ones. 0:30:26.424,0:30:29.061 This one, this is legendary. 0:30:32.967,0:30:34.799 (laughter) 0:30:36.029,0:30:38.322 (laughter) 0:30:42.967,0:30:45.505 (laughter) 0:30:46.766,0:30:49.720 Now we have favorites.[br]If I unfavorite something 0:30:49.720,0:30:51.579 it will automatically pop out of the list. 0:30:51.579,0:30:54.083 I'm not managing any of[br]this stuff. I just built a 0:30:54.083,0:30:56.557 little tiny filter that took[br]like five minutes to do. 0:30:57.091,0:30:59.734 This stuff buys you so much and extending 0:30:59.734,0:31:01.546 this actually becomes very fun. 0:31:06.944,0:31:09.808 We've changed our relationship[br]now to this code base, 0:31:09.808,0:31:11.838 where we actually like working on it. 0:31:11.919,0:31:13.216 We wake up in the morning[br]instead of feeling 0:31:13.216,0:31:15.581 sick about what's going[br]to be in our inbox we're 0:31:15.581,0:31:17.931 actually really excited[br]about what we get to do next. 0:31:20.074,0:31:22.812 I just want to tell you as[br]an addendum to this that my 0:31:22.812,0:31:26.080 personal story about, my[br]first conference was about 0:31:26.080,0:31:31.017 four years ago and I think[br]a lot of people, can I get a 0:31:31.017,0:31:35.185 show of hands of who's hear[br]that's their first conference? 0:31:37.454,0:31:39.488 That's a really great portion of the room. 0:31:39.488,0:31:40.744 My first conference, 0:31:40.744,0:31:43.275 I went to a hack night the[br]night after the conference. 0:31:43.367,0:31:45.420 It was put on by some really great people 0:31:45.420,0:31:48.277 but I walked in, I looked around[br]and I didn't know anybody. 0:31:49.419,0:31:51.537 I listened to some people talk. 0:31:51.537,0:31:53.607 I was just learning to program. 0:31:53.607,0:31:56.118 I was listening to people[br]talk and they were so smart 0:31:56.118,0:31:57.804 and they were people that[br]were so well known in the 0:31:57.804,0:32:01.348 community and I was so[br]nobody that I immediately 0:32:01.348,0:32:03.180 turned around, left, ran[br]out of the room as fast 0:32:03.180,0:32:05.523 as I could, got in my car[br]and cried and drove home. 0:32:06.078,0:32:08.198 Which is pretty awesome,[br]I'm like super cool guy. 0:32:08.198,0:32:10.154 (laughter) 0:32:10.154,0:32:12.858 After that point the[br]community picked me up and 0:32:12.858,0:32:15.089 dusted me off and said,[br]"Get back in there kiddo." 0:32:15.647,0:32:17.828 Many people in that community[br]that I didn't know in the 0:32:17.828,0:32:19.861 room at the time became[br]some of my closest friends. 0:32:21.373,0:32:23.795 These people in this room, if[br]you'll look around, are some 0:32:23.795,0:32:27.372 of your future closest friends[br]and colleagues and mentors. 0:32:28.045,0:32:30.841 The community is the reason that 0:32:30.841,0:32:32.602 I get to do this for a living, 0:32:32.602,0:32:35.112 when before I was doing[br]just horrifying things. 0:32:35.112,0:32:36.717 If you can imagine what[br]it would be like to do 0:32:36.717,0:32:38.761 marketing for a multi-level[br]marketing corporation. 0:32:39.644,0:32:42.934 Just imagine the existential[br]hell and imagine programming. 0:32:42.934,0:32:44.859 We're pretty lucky to[br]get to do this and I want 0:32:44.859,0:32:47.078 everybody to have as good[br]a time writing software 0:32:47.078,0:32:49.966 as I get to have when I'm[br]doing stuff like this. 0:32:52.241,0:32:53.765 The other thing I want[br]to say, the last note 0:32:53.765,0:32:57.532 I want to say on community[br]is we have a tendency 0:32:57.532,0:32:59.439 to do this tent pole[br]thing where we raise some 0:32:59.439,0:33:02.016 people up and then gather[br]around those people. 0:33:02.032,0:33:03.748 That's not really what[br]a community is about, 0:33:03.748,0:33:06.124 a community is a mesh, it's[br]not like hub and spoke. 0:33:06.748,0:33:08.266 Every person in here has something to 0:33:08.266,0:33:09.795 contribute and something amazing to do 0:33:09.795,0:33:11.434 and I can't wait to go[br]to your talks later. 0:33:11.452,0:33:13.872 I'm told I'm pretty good at hugs ... 0:33:13.872,0:33:18.092 (applause) 0:33:28.217,0:33:29.894 I'm told I'm pretty good at hugs so come 0:33:29.894,0:33:34.454 say hi to me and thank[br]you so much. (applause) 0:33:38.593,0:33:42.999 (energetic big band music)