[Script Info] Title: [Events] Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text Dialogue: 0,0:00:18.61,0:00:19.54,Default,,0000,0000,0000,,JUSTIN SEARLS: Good morning everybody. Dialogue: 0,0:00:19.54,0:00:21.14,Default,,0000,0000,0000,,That was an excellent talk that we just Dialogue: 0,0:00:21.14,0:00:22.89,Default,,0000,0000,0000,,saw from Brandon. Happy Friday. Dialogue: 0,0:00:22.89,0:00:24.77,Default,,0000,0000,0000,,It's been a long conference. Dialogue: 0,0:00:24.77,0:00:27.66,Default,,0000,0000,0000,,Thanks for being here. Friday hug to you all. Dialogue: 0,0:00:27.66,0:00:29.14,Default,,0000,0000,0000,,This, if the house lights were Dialogue: 0,0:00:29.14,0:00:30.64,Default,,0000,0000,0000,,up I'd take a picture. Yes. Dialogue: 0,0:00:30.64,0:00:34.18,Default,,0000,0000,0000,,The title of this talk is The Rails of Dialogue: 0,0:00:34.18,0:00:36.22,Default,,0000,0000,0000,,JavaScript won't be a framework. Dialogue: 0,0:00:36.22,0:00:37.15,Default,,0000,0000,0000,,And the slightly less Dialogue: 0,0:00:37.15,0:00:40.28,Default,,0000,0000,0000,,provocative version of that title is, the\NRails of Dialogue: 0,0:00:40.28,0:00:43.77,Default,,0000,0000,0000,,JavaScript will be more than just a framework. Dialogue: 0,0:00:43.77,0:00:46.99,Default,,0000,0000,0000,,My name is Justin. We're not gonna have time Dialogue: 0,0:00:46.99,0:00:48.99,Default,,0000,0000,0000,,for questions afterwards. It's gonna be a\Nvery, very Dialogue: 0,0:00:48.99,0:00:51.70,Default,,0000,0000,0000,,fast talk-y slide-decky thing. Dialogue: 0,0:00:51.70,0:00:53.23,Default,,0000,0000,0000,,So please Tweet me with Dialogue: 0,0:00:53.23,0:00:55.70,Default,,0000,0000,0000,,questions, feedback, praise is always Dialogue: 0,0:00:55.70,0:00:57.70,Default,,0000,0000,0000,,welcome, at searls, and Dialogue: 0,0:00:57.70,0:00:58.87,Default,,0000,0000,0000,,critical feedback is always welcome Dialogue: 0,0:00:58.87,0:00:59.88,Default,,0000,0000,0000,,at hello at testdouble Dialogue: 0,0:00:59.88,0:01:00.80,Default,,0000,0000,0000,,dot com. Dialogue: 0,0:01:00.80,0:01:04.83,Default,,0000,0000,0000,,Let's just talk about three of my favorite\Nthings. Dialogue: 0,0:01:04.83,0:01:08.38,Default,,0000,0000,0000,,One is cupcakes. Two is the planet earth.\NAnd Dialogue: 0,0:01:08.38,0:01:14.38,Default,,0000,0000,0000,,three is monolithic application architecture.\NSo, on cupcakes, say Dialogue: 0,0:01:14.38,0:01:17.67,Default,,0000,0000,0000,,that you own a bakery and a customer walks Dialogue: 0,0:01:17.67,0:01:20.39,Default,,0000,0000,0000,,in and they say they want something sweet.\NSo Dialogue: 0,0:01:20.39,0:01:23.09,Default,,0000,0000,0000,,you bake them up a beautiful cupcake, and\Nthey Dialogue: 0,0:01:23.09,0:01:24.50,Default,,0000,0000,0000,,say hey, you know, this is really good but Dialogue: 0,0:01:24.50,0:01:26.74,Default,,0000,0000,0000,,I like a little bit more sweetness. Maybe\Na Dialogue: 0,0:01:26.74,0:01:28.78,Default,,0000,0000,0000,,little crunch. So you put some sprinkles on\Ntop. Dialogue: 0,0:01:28.78,0:01:31.22,Default,,0000,0000,0000,,The customer is, like, digging the cupcake,\Nbut says Dialogue: 0,0:01:31.22,0:01:32.79,Default,,0000,0000,0000,,you know, on second thought, I really think\NI Dialogue: 0,0:01:32.79,0:01:35.45,Default,,0000,0000,0000,,want something like with some hot fruit filling.\NAnd Dialogue: 0,0:01:35.45,0:01:36.82,Default,,0000,0000,0000,,then you just think to yourself as the baker, Dialogue: 0,0:01:36.82,0:01:39.61,Default,,0000,0000,0000,,ah god damn it. What they really wanted was Dialogue: 0,0:01:39.61,0:01:41.56,Default,,0000,0000,0000,,a fresh-baked pie. Dialogue: 0,0:01:41.56,0:01:43.59,Default,,0000,0000,0000,,So you throw away the cupcake and you make Dialogue: 0,0:01:43.59,0:01:45.40,Default,,0000,0000,0000,,them a pie. And that's an honest mistake if Dialogue: 0,0:01:45.40,0:01:47.45,Default,,0000,0000,0000,,it happens once. But if your workflow as a Dialogue: 0,0:01:47.45,0:01:49.84,Default,,0000,0000,0000,,baker is to assume everyone needs a cupcake\Nonly Dialogue: 0,0:01:49.84,0:01:51.84,Default,,0000,0000,0000,,to have to inevitably throw it away and then Dialogue: 0,0:01:51.84,0:01:54.73,Default,,0000,0000,0000,,bake something else, that's a real problem,\Nyou know, Dialogue: 0,0:01:54.73,0:01:56.09,Default,,0000,0000,0000,,for your business. Dialogue: 0,0:01:56.09,0:01:59.61,Default,,0000,0000,0000,,So say you own a software studio, and a Dialogue: 0,0:01:59.61,0:02:01.62,Default,,0000,0000,0000,,customer walks in and says hey, I need a Dialogue: 0,0:02:01.62,0:02:03.25,Default,,0000,0000,0000,,web application, and so you say, oh great.\NWhat's Dialogue: 0,0:02:03.25,0:02:09.18,Default,,0000,0000,0000,,its name so that I can type rails new. Dialogue: 0,0:02:09.18,0:02:10.80,Default,,0000,0000,0000,,And you build them a little graph, you know, Dialogue: 0,0:02:10.80,0:02:12.20,Default,,0000,0000,0000,,you render it on the server and they say, Dialogue: 0,0:02:12.20,0:02:13.92,Default,,0000,0000,0000,,hey, you know, this graph is great but I Dialogue: 0,0:02:13.92,0:02:16.48,Default,,0000,0000,0000,,need some zooms and some filters. And so you're Dialogue: 0,0:02:16.48,0:02:19.13,Default,,0000,0000,0000,,like, hey, you know, I, we can do that. Dialogue: 0,0:02:19.13,0:02:21.45,Default,,0000,0000,0000,,Sprinkle some JavaScript on top. And then\Nthey say, Dialogue: 0,0:02:21.45,0:02:23.29,Default,,0000,0000,0000,,you know, this is awesome, but let's load\Nall Dialogue: 0,0:02:23.29,0:02:24.88,Default,,0000,0000,0000,,of the data all at once so that the Dialogue: 0,0:02:24.88,0:02:27.67,Default,,0000,0000,0000,,user can really, really like just see absolutely\Neverything Dialogue: 0,0:02:27.67,0:02:30.64,Default,,0000,0000,0000,,at a glance, really dynamically, like an app,\Nyou Dialogue: 0,0:02:30.64,0:02:32.45,Default,,0000,0000,0000,,know? And then you, the developer, are like\Nah, Dialogue: 0,0:02:32.45,0:02:35.53,Default,,0000,0000,0000,,god damn it. Cause there's no logical path\Nfrom Dialogue: 0,0:02:35.53,0:02:37.56,Default,,0000,0000,0000,,that solution to what they really wanted,\Nwhich was Dialogue: 0,0:02:37.56,0:02:39.12,Default,,0000,0000,0000,,a fat-client JavaScript application. Dialogue: 0,0:02:39.12,0:02:42.45,Default,,0000,0000,0000,,I mean, Rails is probably still involved,\Nproviding API Dialogue: 0,0:02:42.45,0:02:45.25,Default,,0000,0000,0000,,services. But it's not the center of the application. Dialogue: 0,0:02:45.25,0:02:48.68,Default,,0000,0000,0000,,That monolithic approach doesn't work. And\Nit's an honest Dialogue: 0,0:02:48.68,0:02:51.21,Default,,0000,0000,0000,,mistake, if it happens once. But if part of Dialogue: 0,0:02:51.21,0:02:54.44,Default,,0000,0000,0000,,your workflow is to immediately assume that\NRails is Dialogue: 0,0:02:54.44,0:02:56.45,Default,,0000,0000,0000,,the solution to every single web application,\Nand then Dialogue: 0,0:02:56.45,0:02:58.44,Default,,0000,0000,0000,,you only realize later that you've guilt a\Ngigantic Dialogue: 0,0:02:58.44,0:03:01.91,Default,,0000,0000,0000,,mess with JavaScript, that's a problem. Dialogue: 0,0:03:01.91,0:03:03.37,Default,,0000,0000,0000,,The reason that I think that a lot of Dialogue: 0,0:03:03.37,0:03:05.27,Default,,0000,0000,0000,,web developers fall into this trap is that\NRails Dialogue: 0,0:03:05.27,0:03:09.53,Default,,0000,0000,0000,,is too convenient. When you're a Ruby developer,\Nyou Dialogue: 0,0:03:09.53,0:03:12.47,Default,,0000,0000,0000,,have all these awesome tools right at your\Ndisposal. Dialogue: 0,0:03:12.47,0:03:14.42,Default,,0000,0000,0000,,We've got this great convention-based framework\Nso I can Dialogue: 0,0:03:14.42,0:03:16.46,Default,,0000,0000,0000,,just add a gem and it, maybe a couple Dialogue: 0,0:03:16.46,0:03:18.15,Default,,0000,0000,0000,,lines, and then I get all this great behavior Dialogue: 0,0:03:18.15,0:03:20.73,Default,,0000,0000,0000,,on the cheap. And when we ask Ruby developers Dialogue: 0,0:03:20.73,0:03:22.75,Default,,0000,0000,0000,,about their favorite client-side tools, they\Nusually come up Dialogue: 0,0:03:22.75,0:03:28.48,Default,,0000,0000,0000,,empty. Nobody hates JavaScript more than Rubyists. Dialogue: 0,0:03:28.48,0:03:30.20,Default,,0000,0000,0000,,So they, they, they just can't think of any. Dialogue: 0,0:03:30.20,0:03:32.20,Default,,0000,0000,0000,,And of course it's not like there's no client-side Dialogue: 0,0:03:32.20,0:03:35.43,Default,,0000,0000,0000,,tools. I'm just kidding. There are plenty\Nof client-side Dialogue: 0,0:03:35.43,0:03:41.63,Default,,0000,0000,0000,,tools available to Rubyists. But this is their\Nreputation, Dialogue: 0,0:03:41.63,0:03:45.74,Default,,0000,0000,0000,,right. They're jagged and rusty and terrible.\NSo, every Dialogue: 0,0:03:45.74,0:03:47.39,Default,,0000,0000,0000,,time a new story comes down the pike, we Dialogue: 0,0:03:47.39,0:03:49.67,Default,,0000,0000,0000,,have to make a decision, right. Where's the\Nbest Dialogue: 0,0:03:49.67,0:03:52.27,Default,,0000,0000,0000,,place for this to live? What's the concern\Nhere. Dialogue: 0,0:03:52.27,0:03:54.91,Default,,0000,0000,0000,,If a user brings me a, a user interface Dialogue: 0,0:03:54.91,0:03:57.22,Default,,0000,0000,0000,,card, it might be that the best place to Dialogue: 0,0:03:57.22,0:03:58.45,Default,,0000,0000,0000,,write that, the best place for that to live Dialogue: 0,0:03:58.45,0:04:00.49,Default,,0000,0000,0000,,is in the browser. But the second thing I Dialogue: 0,0:04:00.49,0:04:02.06,Default,,0000,0000,0000,,ask when I get a new card is like Dialogue: 0,0:04:02.06,0:04:04.31,Default,,0000,0000,0000,,hey, where's, what'd be the easiest thing\Nfor me Dialogue: 0,0:04:04.31,0:04:06.16,Default,,0000,0000,0000,,to actually do to build this? Take the least Dialogue: 0,0:04:06.16,0:04:08.40,Default,,0000,0000,0000,,time? Be the quickest to market? And because\NRails Dialogue: 0,0:04:08.40,0:04:11.80,Default,,0000,0000,0000,,is so convenient, the answer is often Rails.\NSo Dialogue: 0,0:04:11.80,0:04:13.45,Default,,0000,0000,0000,,even though the best place for the code to Dialogue: 0,0:04:13.45,0:04:16.53,Default,,0000,0000,0000,,live might be the frontend, I'm incentivised\Nto start Dialogue: 0,0:04:16.53,0:04:19.63,Default,,0000,0000,0000,,solving client-side problems on the server-side,\Nand taken to Dialogue: 0,0:04:19.63,0:04:21.78,Default,,0000,0000,0000,,an extreme that's really unhealthy. Dialogue: 0,0:04:21.78,0:04:25.47,Default,,0000,0000,0000,,So I have a provocative statement to make.\NNon-Rubyists Dialogue: 0,0:04:25.47,0:04:28.87,Default,,0000,0000,0000,,write better JavaScript. I went to a dot NET Dialogue: 0,0:04:28.87,0:04:31.44,Default,,0000,0000,0000,,conference, my first dot NET conference, last\Nyear in Dialogue: 0,0:04:31.44,0:04:35.02,Default,,0000,0000,0000,,Sophia, Bulgaria, and I was blown away by\Nhow Dialogue: 0,0:04:35.02,0:04:37.11,Default,,0000,0000,0000,,much we were talking the same language. We\Nwere Dialogue: 0,0:04:37.11,0:04:41.16,Default,,0000,0000,0000,,using great, brand new node.js based tooling.\NEveryone was Dialogue: 0,0:04:41.16,0:04:45.14,Default,,0000,0000,0000,,talking about and excited about Angular, even\NEmber. But Dialogue: 0,0:04:45.14,0:04:47.95,Default,,0000,0000,0000,,what my expectations were was it's dot NET,\Nthis Dialogue: 0,0:04:47.95,0:04:50.26,Default,,0000,0000,0000,,is crusty, you know. And what I found in Dialogue: 0,0:04:50.26,0:04:52.93,Default,,0000,0000,0000,,actually talking to people was, because dot\Nnet wasn't Dialogue: 0,0:04:52.93,0:04:56.95,Default,,0000,0000,0000,,so incredibly awesome, they didn't have that\Nsame moral Dialogue: 0,0:04:56.95,0:04:59.18,Default,,0000,0000,0000,,hazard, you know. They were willing to solve\Nthe Dialogue: 0,0:04:59.18,0:05:02.04,Default,,0000,0000,0000,,problem in the right place. Dialogue: 0,0:05:02.04,0:05:03.83,Default,,0000,0000,0000,,And when I think back over my own experience, Dialogue: 0,0:05:03.83,0:05:08.04,Default,,0000,0000,0000,,before Rails was easy, for me, whether that\Nwas Dialogue: 0,0:05:08.04,0:05:10.24,Default,,0000,0000,0000,,before 2005 or when I was doing projects in Dialogue: 0,0:05:10.24,0:05:13.93,Default,,0000,0000,0000,,other tech stacks, JavaScript wasn't hard.\NYou know, I Dialogue: 0,0:05:13.93,0:05:16.67,Default,,0000,0000,0000,,actually really quite enjoyed JavaScript until\NI was told, Dialogue: 0,0:05:16.67,0:05:18.37,Default,,0000,0000,0000,,you know, to hate it. Dialogue: 0,0:05:18.37,0:05:21.72,Default,,0000,0000,0000,,And granted, we can have a long discussion.\NWe Dialogue: 0,0:05:21.72,0:05:24.79,Default,,0000,0000,0000,,can have a lot, like, screencast here about\Nwhy, Dialogue: 0,0:05:24.79,0:05:26.89,Default,,0000,0000,0000,,is asking, is JavaScript a terrible language?\NAnd I Dialogue: 0,0:05:26.89,0:05:33.20,Default,,0000,0000,0000,,would just like clear the air, right. Yes\Ndefinitely. Dialogue: 0,0:05:33.20,0:05:35.11,Default,,0000,0000,0000,,I spend most of my time in JavaScript. I Dialogue: 0,0:05:35.11,0:05:37.47,Default,,0000,0000,0000,,agree, it is terrible. But I'm careful not\Nto Dialogue: 0,0:05:37.47,0:05:41.36,Default,,0000,0000,0000,,conflate that with hey, well, is that why\Nwriting Dialogue: 0,0:05:41.36,0:05:43.55,Default,,0000,0000,0000,,JavaScript is terrible? The problems I have\Nalways had Dialogue: 0,0:05:43.55,0:05:45.59,Default,,0000,0000,0000,,with JavaScript have nothing to do with, have\Nnothing Dialogue: 0,0:05:45.59,0:05:47.72,Default,,0000,0000,0000,,to do with map and parsein and fundamental\Nproblems Dialogue: 0,0:05:47.72,0:05:49.01,Default,,0000,0000,0000,,with the language, because I'm usually working\Nat a Dialogue: 0,0:05:49.01,0:05:50.15,Default,,0000,0000,0000,,higher level of abstraction, right. Dialogue: 0,0:05:50.15,0:05:52.34,Default,,0000,0000,0000,,The problems I have with JavaScript are all\Nof Dialogue: 0,0:05:52.34,0:05:56.08,Default,,0000,0000,0000,,the tooling. The ecosystem. The community.\NSo I, I Dialogue: 0,0:05:56.08,0:05:58.30,Default,,0000,0000,0000,,challenge you to ask again later if you think Dialogue: 0,0:05:58.30,0:06:02.18,Default,,0000,0000,0000,,the language is the one at fault. After this Dialogue: 0,0:06:02.18,0:06:03.85,Default,,0000,0000,0000,,talk, hopefully I'll be able to persuade you\Na Dialogue: 0,0:06:03.85,0:06:04.87,Default,,0000,0000,0000,,little bit. Dialogue: 0,0:06:04.87,0:06:09.22,Default,,0000,0000,0000,,Let's talk about the planet earth. I love\NRuby Dialogue: 0,0:06:09.22,0:06:11.99,Default,,0000,0000,0000,,and I love Ruby mostly for the community.\NI Dialogue: 0,0:06:11.99,0:06:14.20,Default,,0000,0000,0000,,love the language, but I love the community,\Nbecause Dialogue: 0,0:06:14.20,0:06:16.39,Default,,0000,0000,0000,,they changed the world when it comes to web Dialogue: 0,0:06:16.39,0:06:18.73,Default,,0000,0000,0000,,application development. If you were to chart\Nall of Dialogue: 0,0:06:18.73,0:06:20.41,Default,,0000,0000,0000,,the great new tools for the web that have Dialogue: 0,0:06:20.41,0:06:23.88,Default,,0000,0000,0000,,released over time, starting in 2005, the\Nfantastic gems Dialogue: 0,0:06:23.88,0:06:26.18,Default,,0000,0000,0000,,that were sort of the foundation for, for,\Nfor Dialogue: 0,0:06:26.18,0:06:29.80,Default,,0000,0000,0000,,Ruby on Rails and this community. Over time,\Nhaml, Dialogue: 0,0:06:29.80,0:06:33.09,Default,,0000,0000,0000,,sass, all of these great extensions. Alternate\Nstacks that Dialogue: 0,0:06:33.09,0:06:35.04,Default,,0000,0000,0000,,we can have an Omakase and a Prime stack. Dialogue: 0,0:06:35.04,0:06:38.49,Default,,0000,0000,0000,,Rspec. Cucumber. These great innovations,\Nhelping us build better Dialogue: 0,0:06:38.49,0:06:41.62,Default,,0000,0000,0000,,web applications. The world, Ruby with gems\Nbecame this Dialogue: 0,0:06:41.62,0:06:44.55,Default,,0000,0000,0000,,mature market place of free stuff that would\Nhelp Dialogue: 0,0:06:44.55,0:06:46.13,Default,,0000,0000,0000,,us write better code. Dialogue: 0,0:06:46.13,0:06:49.37,Default,,0000,0000,0000,,But then, right around 2012, I started to\Nnotice Dialogue: 0,0:06:49.37,0:06:51.73,Default,,0000,0000,0000,,that when a new feature would come out for, Dialogue: 0,0:06:51.73,0:06:54.66,Default,,0000,0000,0000,,like, say, webkit, it wasn't immediately followed\Nby gems Dialogue: 0,0:06:54.66,0:06:57.62,Default,,0000,0000,0000,,that would exploit it. Instead I was finding\NJavaScript Dialogue: 0,0:06:57.62,0:07:01.83,Default,,0000,0000,0000,,tooling written in JavaScript on node. And\Nthat started Dialogue: 0,0:07:01.83,0:07:03.75,Default,,0000,0000,0000,,popping up, and in 2013 it really seemed to Dialogue: 0,0:07:03.75,0:07:06.09,Default,,0000,0000,0000,,take off. And you come into 2014 and a Dialogue: 0,0:07:06.09,0:07:08.35,Default,,0000,0000,0000,,lot of Rubyists, I think, have this latent\Nfear Dialogue: 0,0:07:08.35,0:07:13.13,Default,,0000,0000,0000,,that JavaScript is gonna devour planet earth.\NAnd I'm Dialogue: 0,0:07:13.13,0:07:16.58,Default,,0000,0000,0000,,here to tell you that it probably will. Dialogue: 0,0:07:16.58,0:07:18.01,Default,,0000,0000,0000,,Where the best tools? If you were to ask Dialogue: 0,0:07:18.01,0:07:19.47,Default,,0000,0000,0000,,yourself this, you can add up a, add up Dialogue: 0,0:07:19.47,0:07:22.05,Default,,0000,0000,0000,,a bunch of fact values. For example, Ruby's\Ntool Dialogue: 0,0:07:22.05,0:07:24.86,Default,,0000,0000,0000,,ecosystem, it's mature but it's crowded. That's\Nnot a Dialogue: 0,0:07:24.86,0:07:26.98,Default,,0000,0000,0000,,lot of room for growth because everyone already\Nhas Dialogue: 0,0:07:26.98,0:07:28.84,Default,,0000,0000,0000,,a lot of tools available that they, that they Dialogue: 0,0:07:28.84,0:07:34.20,Default,,0000,0000,0000,,love. But node's ecosystem, it's immature,\Nright. It's innovative, Dialogue: 0,0:07:34.20,0:07:36.63,Default,,0000,0000,0000,,because so much new stuff gets pushed up,\Nand Dialogue: 0,0:07:36.63,0:07:40.09,Default,,0000,0000,0000,,it's frustrating, but it's great, because\Nas soon as Dialogue: 0,0:07:40.09,0:07:41.45,Default,,0000,0000,0000,,a new feature hits a browser, there's a tool Dialogue: 0,0:07:41.45,0:07:43.24,Default,,0000,0000,0000,,to exploit it. I mean, granted, I get as Dialogue: 0,0:07:43.24,0:07:44.84,Default,,0000,0000,0000,,frustrated as anybody else that when I run\NMPM Dialogue: 0,0:07:44.84,0:07:47.40,Default,,0000,0000,0000,,install on something, like, by the time the\Ninstall Dialogue: 0,0:07:47.40,0:07:49.67,Default,,0000,0000,0000,,finally finishes at least two of those dependencies\Nhave Dialogue: 0,0:07:49.67,0:07:53.06,Default,,0000,0000,0000,,probably had updates pushed. Dialogue: 0,0:07:53.06,0:07:55.28,Default,,0000,0000,0000,,But that's the fantastic, that's what I loved\Nabout Dialogue: 0,0:07:55.28,0:07:59.56,Default,,0000,0000,0000,,Ruby in 2006 and 2007. And tool authors are Dialogue: 0,0:07:59.56,0:08:01.11,Default,,0000,0000,0000,,not immune to trends. I read a lot of, Dialogue: 0,0:08:01.11,0:08:02.52,Default,,0000,0000,0000,,like, open source tools and I want to go Dialogue: 0,0:08:02.52,0:08:04.51,Default,,0000,0000,0000,,where the people are. I want to go where Dialogue: 0,0:08:04.51,0:08:06.81,Default,,0000,0000,0000,,I'm gonna have a big impact. And so tool Dialogue: 0,0:08:06.81,0:08:09.39,Default,,0000,0000,0000,,authors are now gravitating to, to the world\Nof Dialogue: 0,0:08:09.39,0:08:11.30,Default,,0000,0000,0000,,JavaScript, because the universe of people\Nwho have to Dialogue: 0,0:08:11.30,0:08:14.04,Default,,0000,0000,0000,,deal with JavaScript is about seven billion\Npeople, and Dialogue: 0,0:08:14.04,0:08:15.12,Default,,0000,0000,0000,,the universe of people who have to deal with Dialogue: 0,0:08:15.12,0:08:18.47,Default,,0000,0000,0000,,Ruby is in the tens of thousands. Dialogue: 0,0:08:18.47,0:08:21.55,Default,,0000,0000,0000,,Yeah. All seven billion are JavaScript developers.\NI realize Dialogue: 0,0:08:21.55,0:08:22.35,Default,,0000,0000,0000,,that's flawed. Dialogue: 0,0:08:22.35,0:08:26.88,Default,,0000,0000,0000,,Also, tools, they address the problems of\Ntheir day. Dialogue: 0,0:08:26.88,0:08:29.24,Default,,0000,0000,0000,,A gem that was written in 2008 was written Dialogue: 0,0:08:29.24,0:08:32.30,Default,,0000,0000,0000,,to solve problems that person was facing in\N2008. Dialogue: 0,0:08:32.30,0:08:35.21,Default,,0000,0000,0000,,Not 2014. A tool that was written in 2014 Dialogue: 0,0:08:35.21,0:08:36.95,Default,,0000,0000,0000,,surely must be useful in 2014, and so it's Dialogue: 0,0:08:36.95,0:08:38.75,Default,,0000,0000,0000,,just a better fit for the web as it Dialogue: 0,0:08:38.75,0:08:41.01,Default,,0000,0000,0000,,exists today. You add all that up and I, Dialogue: 0,0:08:41.01,0:08:42.51,Default,,0000,0000,0000,,you know, I really believe that web tools\Nin Dialogue: 0,0:08:42.51,0:08:46.48,Default,,0000,0000,0000,,node tend to better solve today's problems. Dialogue: 0,0:08:46.48,0:08:48.85,Default,,0000,0000,0000,,And this is maddening for those who insist\Non Dialogue: 0,0:08:48.85,0:08:52.11,Default,,0000,0000,0000,,only using Rails for absolutely everything.\NBut, hey, speaking Dialogue: 0,0:08:52.11,0:08:57.10,Default,,0000,0000,0000,,of Rails, let's talk about monolithic application\Narchitecture. Dialogue: 0,0:08:57.10,0:08:59.36,Default,,0000,0000,0000,,Rails won the war, right, on web application\Nframeworks. Dialogue: 0,0:08:59.36,0:09:01.30,Default,,0000,0000,0000,,It came in with a whole bunch of great Dialogue: 0,0:09:01.30,0:09:03.67,Default,,0000,0000,0000,,reasons that we can go into later about why Dialogue: 0,0:09:03.67,0:09:05.49,Default,,0000,0000,0000,,it was just the best. It was, it was Dialogue: 0,0:09:05.49,0:09:08.54,Default,,0000,0000,0000,,fantastic, and all of these frameworks since\Nthen have Dialogue: 0,0:09:08.54,0:09:11.23,Default,,0000,0000,0000,,adopted a ton of great ideas from Rails. But Dialogue: 0,0:09:11.23,0:09:13.54,Default,,0000,0000,0000,,what we don't often think about when we consider Dialogue: 0,0:09:13.54,0:09:16.55,Default,,0000,0000,0000,,that phenomenon is to ask ourselves, which\Nwar did Dialogue: 0,0:09:16.55,0:09:20.79,Default,,0000,0000,0000,,Rails win? All web applications? Like, generally?\NOr is Dialogue: 0,0:09:20.79,0:09:23.06,Default,,0000,0000,0000,,there some sub-set of applications for the\Nweb that Dialogue: 0,0:09:23.06,0:09:25.18,Default,,0000,0000,0000,,are a better fit for Rails than others? Dialogue: 0,0:09:25.18,0:09:28.04,Default,,0000,0000,0000,,DHH last year at RailsConf said that good\Nframeworks Dialogue: 0,0:09:28.04,0:09:31.88,Default,,0000,0000,0000,,are extractions, not inventions. Extracted\Nfrom real applications and Dialogue: 0,0:09:31.88,0:09:35.17,Default,,0000,0000,0000,,not just invented. And so when you look at Dialogue: 0,0:09:35.17,0:09:37.93,Default,,0000,0000,0000,,Rails, obviously the story is that the company\NBasecamp Dialogue: 0,0:09:37.93,0:09:40.67,Default,,0000,0000,0000,,made Basecamp and they extracted the good\Nbits, the Dialogue: 0,0:09:40.67,0:09:42.11,Default,,0000,0000,0000,,common bits that they were seeing across a\Nlot Dialogue: 0,0:09:42.11,0:09:45.61,Default,,0000,0000,0000,,of their projects into Ruby on Rails. Dialogue: 0,0:09:45.61,0:09:47.06,Default,,0000,0000,0000,,And those kinds of bits that are common to Dialogue: 0,0:09:47.06,0:09:51.40,Default,,0000,0000,0000,,many of us, almost all web applications: url\Nrouting, Dialogue: 0,0:09:51.40,0:09:54.58,Default,,0000,0000,0000,,to point you to custom actions that you write. Dialogue: 0,0:09:54.58,0:09:57.49,Default,,0000,0000,0000,,Modeling behavior of, of the models in your\Nobjects, Dialogue: 0,0:09:57.49,0:09:59.27,Default,,0000,0000,0000,,the validations and all of that at a fundamental Dialogue: 0,0:09:59.27,0:10:03.10,Default,,0000,0000,0000,,level. Persistence. Storing stuff in a database,\Nquerying for Dialogue: 0,0:10:03.10,0:10:07.48,Default,,0000,0000,0000,,the stuff. The relationships between stuff.\NSession management and, Dialogue: 0,0:10:07.48,0:10:08.92,Default,,0000,0000,0000,,in a way that's abstracted from where the\Nsession Dialogue: 0,0:10:08.92,0:10:11.54,Default,,0000,0000,0000,,stuff was stored was hugely convenient, obviously.\NAll of Dialogue: 0,0:10:11.54,0:10:13.23,Default,,0000,0000,0000,,those ancillary concerns of the wheels that\Nyou don't Dialogue: 0,0:10:13.23,0:10:16.21,Default,,0000,0000,0000,,want to reinvent like mailers. And then there's\Nthis Dialogue: 0,0:10:16.21,0:10:19.02,Default,,0000,0000,0000,,last little bit that's like all these JavaScript\Nalternatives. Dialogue: 0,0:10:19.02,0:10:21.56,Default,,0000,0000,0000,,Like there's sort of like the, the means by Dialogue: 0,0:10:21.56,0:10:24.29,Default,,0000,0000,0000,,which to sprinkle JavaScript on top. Like,\NAJAX erb Dialogue: 0,0:10:24.29,0:10:26.69,Default,,0000,0000,0000,,tags that dump a whole bunch of JavaScript\Ninto Dialogue: 0,0:10:26.69,0:10:29.84,Default,,0000,0000,0000,,your on-click handlers in your, in your markup,\Nor Dialogue: 0,0:10:29.84,0:10:33.67,Default,,0000,0000,0000,,later on r.js, or later on unintrusive AJAX\Nerb Dialogue: 0,0:10:33.67,0:10:37.89,Default,,0000,0000,0000,,tags. Or later on, turbolinks, right. It's\Nnot that Dialogue: 0,0:10:37.89,0:10:40.63,Default,,0000,0000,0000,,those are bad, that those alternatives are\Nbad tools. Dialogue: 0,0:10:40.63,0:10:43.13,Default,,0000,0000,0000,,It's that they're there to solve, they've\Nbeen abstracted Dialogue: 0,0:10:43.13,0:10:46.44,Default,,0000,0000,0000,,from an application that just didn't have\Nthe problem Dialogue: 0,0:10:46.44,0:10:48.98,Default,,0000,0000,0000,,of trying to solve and, and write JavaScript\Nin Dialogue: 0,0:10:48.98,0:10:51.00,Default,,0000,0000,0000,,the way that I want to write JavaScript. Dialogue: 0,0:10:51.00,0:10:53.30,Default,,0000,0000,0000,,Because if you consider Basecamp, you start\Na page. Dialogue: 0,0:10:53.30,0:10:55.03,Default,,0000,0000,0000,,It's a traditional web workflow. You start\Non a Dialogue: 0,0:10:55.03,0:10:56.18,Default,,0000,0000,0000,,page, you click on a thing, you get another Dialogue: 0,0:10:56.18,0:10:57.43,Default,,0000,0000,0000,,page, you click on a thing, you get another Dialogue: 0,0:10:57.43,0:11:00.29,Default,,0000,0000,0000,,page. It's a, it's a multi-break process,\Nand that Dialogue: 0,0:11:00.29,0:11:03.00,Default,,0000,0000,0000,,represents a huge proportion of the web. And\Nthat Dialogue: 0,0:11:03.00,0:11:05.18,Default,,0000,0000,0000,,percentage of the web was almost 100% in 2005 Dialogue: 0,0:11:05.18,0:11:07.51,Default,,0000,0000,0000,,but it's much lower now. If your app isn't Dialogue: 0,0:11:07.51,0:11:09.49,Default,,0000,0000,0000,,a one to one mapping of, like, CRUD in Dialogue: 0,0:11:09.49,0:11:11.14,Default,,0000,0000,0000,,the database and you're just exposing that\Nas an Dialogue: 0,0:11:11.14,0:11:13.67,Default,,0000,0000,0000,,interface to users, if there's any layer of\Nindirection Dialogue: 0,0:11:13.67,0:11:16.19,Default,,0000,0000,0000,,you, it might not be a good fit. Dialogue: 0,0:11:16.19,0:11:21.63,Default,,0000,0000,0000,,Yesterday, Sandi Metz made the comment, as\Nan aside, Dialogue: 0,0:11:21.63,0:11:22.96,Default,,0000,0000,0000,,that there are Rails apps and then there are Dialogue: 0,0:11:22.96,0:11:26.04,Default,,0000,0000,0000,,apps that use Rails. I'm finding that more\Nand Dialogue: 0,0:11:26.04,0:11:27.64,Default,,0000,0000,0000,,more, the apps that I'm writing are apps that Dialogue: 0,0:11:27.64,0:11:30.24,Default,,0000,0000,0000,,use Rails. I can love Rails and not necessarily Dialogue: 0,0:11:30.24,0:11:31.84,Default,,0000,0000,0000,,take advantage or, or really find a lot of Dialogue: 0,0:11:31.84,0:11:35.96,Default,,0000,0000,0000,,benefit from the front-end aspects. Dialogue: 0,0:11:35.96,0:11:39.55,Default,,0000,0000,0000,,So Rails promotes an html user interface in\Nthe Dialogue: 0,0:11:39.55,0:11:42.70,Default,,0000,0000,0000,,frontend, cause that's what Basecamp needed.\NAnd what I Dialogue: 0,0:11:42.70,0:11:43.58,Default,,0000,0000,0000,,mean when I say that is you're writing stuff Dialogue: 0,0:11:43.58,0:11:45.94,Default,,0000,0000,0000,,like html markup. I have an anchor tag here Dialogue: 0,0:11:45.94,0:11:48.12,Default,,0000,0000,0000,,with a, with a ref and, and content, or Dialogue: 0,0:11:48.12,0:11:50.16,Default,,0000,0000,0000,,I might have a form action here with, you Dialogue: 0,0:11:50.16,0:11:53.42,Default,,0000,0000,0000,,know, an input submit, and when you're writing\Nhtml Dialogue: 0,0:11:53.42,0:11:55.82,Default,,0000,0000,0000,,like this, it feels like you're making the\NUI. Dialogue: 0,0:11:55.82,0:11:58.21,Default,,0000,0000,0000,,But you're not writing, like, UI programming.\NWhat this Dialogue: 0,0:11:58.21,0:12:00.85,Default,,0000,0000,0000,,is is this is the specification of a UI. Dialogue: 0,0:12:00.85,0:12:02.70,Default,,0000,0000,0000,,The user agent, the browser, is the thing\Nresponsible Dialogue: 0,0:12:02.70,0:12:04.25,Default,,0000,0000,0000,,for figuring out how to render a link and Dialogue: 0,0:12:04.25,0:12:06.18,Default,,0000,0000,0000,,what to do when you click it. It's how Dialogue: 0,0:12:06.18,0:12:07.97,Default,,0000,0000,0000,,to render and what to do when, you know, Dialogue: 0,0:12:07.97,0:12:09.54,Default,,0000,0000,0000,,how to paint a button and so forth. Dialogue: 0,0:12:09.54,0:12:13.07,Default,,0000,0000,0000,,It's, you're not, you're kind of outsourcing\Nthe UI Dialogue: 0,0:12:13.07,0:12:15.55,Default,,0000,0000,0000,,programming. If you're building an application\Nwith the browser Dialogue: 0,0:12:15.55,0:12:17.14,Default,,0000,0000,0000,,as your runtime, though, I'd call that a JavaScript Dialogue: 0,0:12:17.14,0:12:19.70,Default,,0000,0000,0000,,UI, and fundamentally the activity is just\Ndifferent and Dialogue: 0,0:12:19.70,0:12:22.65,Default,,0000,0000,0000,,more complex. You know, you're responsible\Nfor finding the Dialogue: 0,0:12:22.65,0:12:24.23,Default,,0000,0000,0000,,point and the DOM where you want to render Dialogue: 0,0:12:24.23,0:12:27.13,Default,,0000,0000,0000,,stuff into. Or you're responsible for binding\Nto an Dialogue: 0,0:12:27.13,0:12:29.22,Default,,0000,0000,0000,,event that the user does something, and then\Nyou Dialogue: 0,0:12:29.22,0:12:31.36,Default,,0000,0000,0000,,need to take some custom action. You're the\None Dialogue: 0,0:12:31.36,0:12:34.90,Default,,0000,0000,0000,,in the driver's seat. They're fundamentally\Ndifferent concerns. Dialogue: 0,0:12:34.90,0:12:39.03,Default,,0000,0000,0000,,But our tools, I think, file, I like tree, Dialogue: 0,0:12:39.03,0:12:40.89,Default,,0000,0000,0000,,to tree stuff out, because I think that tools Dialogue: 0,0:12:40.89,0:12:44.35,Default,,0000,0000,0000,,tend to betray their biases based on the layout Dialogue: 0,0:12:44.35,0:12:46.40,Default,,0000,0000,0000,,of the files that they give us. You know, Dialogue: 0,0:12:46.40,0:12:47.87,Default,,0000,0000,0000,,a naive Rails app might look like this, and Dialogue: 0,0:12:47.87,0:12:51.53,Default,,0000,0000,0000,,it screams MVC and it screams server-side.\NBut, of Dialogue: 0,0:12:51.53,0:12:54.28,Default,,0000,0000,0000,,course, in reality, one of the kind of, like, Dialogue: 0,0:12:54.28,0:12:57.08,Default,,0000,0000,0000,,you know, dust-bin corners is that we have\Nthis, Dialogue: 0,0:12:57.08,0:13:00.83,Default,,0000,0000,0000,,this ghetto, right, under assets, and then\Nthe most, Dialogue: 0,0:13:00.83,0:13:06.17,Default,,0000,0000,0000,,you know, unfortunately named directory ever,\Njavascripts, and then Dialogue: 0,0:13:06.17,0:13:08.09,Default,,0000,0000,0000,,application.js, and it's telling us, all this\Nstuff at Dialogue: 0,0:13:08.09,0:13:09.87,Default,,0000,0000,0000,,the top - this matters. And this thing at Dialogue: 0,0:13:09.87,0:13:12.19,Default,,0000,0000,0000,,the bottom, just write one big long bowl of Dialogue: 0,0:13:12.19,0:13:13.97,Default,,0000,0000,0000,,spaghetti, and it'll work out. And that's\Nhow a Dialogue: 0,0:13:13.97,0:13:16.06,Default,,0000,0000,0000,,lot of people write, you know, JavaScript\Nand Rails Dialogue: 0,0:13:16.06,0:13:18.24,Default,,0000,0000,0000,,applications, still. Dialogue: 0,0:13:18.24,0:13:19.72,Default,,0000,0000,0000,,Some people, though, that's not good enough,\Nand so Dialogue: 0,0:13:19.72,0:13:22.37,Default,,0000,0000,0000,,they, they, they realize that they need to\Nwrite Dialogue: 0,0:13:22.37,0:13:24.08,Default,,0000,0000,0000,,more structured JavaScript, and so we end\Nup with Dialogue: 0,0:13:24.08,0:13:26.56,Default,,0000,0000,0000,,this new thing, like an html UI and a, Dialogue: 0,0:13:26.56,0:13:28.61,Default,,0000,0000,0000,,and a JavaScript UI combined. And you might\Nnotice Dialogue: 0,0:13:28.61,0:13:32.35,Default,,0000,0000,0000,,a pattern here, right. There is a, a, an Dialogue: 0,0:13:32.35,0:13:34.47,Default,,0000,0000,0000,,MVC in the back, and then it's also MVC Dialogue: 0,0:13:34.47,0:13:37.68,Default,,0000,0000,0000,,in the front. It makes command T really difficult, Dialogue: 0,0:13:37.68,0:13:41.28,Default,,0000,0000,0000,,but it, you know, we see this duplication\Nof Dialogue: 0,0:13:41.28,0:13:44.94,Default,,0000,0000,0000,,backend concerns and frontend concerns, and\Nthere's also this, Dialogue: 0,0:13:44.94,0:13:49.07,Default,,0000,0000,0000,,this little nit, negging doubt about, do we\Nreally Dialogue: 0,0:13:49.07,0:13:50.44,Default,,0000,0000,0000,,need this views here? Right, if we're building\Na Dialogue: 0,0:13:50.44,0:13:54.40,Default,,0000,0000,0000,,full-blown fat-client JavaScript application,\Nthe backend views that Rails Dialogue: 0,0:13:54.40,0:13:56.50,Default,,0000,0000,0000,,provides just are less useful. So those often\Nget Dialogue: 0,0:13:56.50,0:13:59.08,Default,,0000,0000,0000,,cut out now, and we, we just have sort Dialogue: 0,0:13:59.08,0:14:01.15,Default,,0000,0000,0000,,of a JSON API in Rails, and then this Dialogue: 0,0:14:01.15,0:14:03.18,Default,,0000,0000,0000,,deeply-nested JavaScript UI. Dialogue: 0,0:14:03.18,0:14:04.15,Default,,0000,0000,0000,,And so at this point, if like a new Dialogue: 0,0:14:04.15,0:14:05.92,Default,,0000,0000,0000,,person comes to your project and they ask,\Nhey, Dialogue: 0,0:14:05.92,0:14:08.83,Default,,0000,0000,0000,,so what exactly is that thing? Right. I would Dialogue: 0,0:14:08.83,0:14:12.43,Default,,0000,0000,0000,,call that a vestigial appendage. Because it\Ncan only Dialogue: 0,0:14:12.43,0:14:14.93,Default,,0000,0000,0000,,be explained in terms of the past. You have Dialogue: 0,0:14:14.93,0:14:17.13,Default,,0000,0000,0000,,to pull up your, you know, your forensics\Nof Dialogue: 0,0:14:17.13,0:14:18.83,Default,,0000,0000,0000,,like, well, in 2008 we were all, you know, Dialogue: 0,0:14:18.83,0:14:21.52,Default,,0000,0000,0000,,thinking this and now it's still like this. Dialogue: 0,0:14:21.52,0:14:24.17,Default,,0000,0000,0000,,What's wrong with that vestigial appendage?\NWell, what's fundamentally Dialogue: 0,0:14:24.17,0:14:28.25,Default,,0000,0000,0000,,wrong is that, a fundamental problem in, in\Nprogramming, Dialogue: 0,0:14:28.25,0:14:30.15,Default,,0000,0000,0000,,is that when we move way faster when we Dialogue: 0,0:14:30.15,0:14:31.58,Default,,0000,0000,0000,,can fit the whole application in our head\Nat Dialogue: 0,0:14:31.58,0:14:33.92,Default,,0000,0000,0000,,once, and when, on day one of any project, Dialogue: 0,0:14:33.92,0:14:35.04,Default,,0000,0000,0000,,you can fit the whole thing in your head Dialogue: 0,0:14:35.04,0:14:36.76,Default,,0000,0000,0000,,at once. But on day 1000 of the project Dialogue: 0,0:14:36.76,0:14:38.36,Default,,0000,0000,0000,,that's probably not gonna be true. Dialogue: 0,0:14:38.36,0:14:39.100,Default,,0000,0000,0000,,So if you build a monolithic thing up front, Dialogue: 0,0:14:39.100,0:14:41.73,Default,,0000,0000,0000,,as that app gets bigger, eventually you reach\Na Dialogue: 0,0:14:41.73,0:14:42.81,Default,,0000,0000,0000,,point where you can't fit it all in your Dialogue: 0,0:14:42.81,0:14:46.17,Default,,0000,0000,0000,,head and you start to page, right. Part of Dialogue: 0,0:14:46.17,0:14:47.71,Default,,0000,0000,0000,,the application that you're working in you\Ncan think Dialogue: 0,0:14:47.71,0:14:49.62,Default,,0000,0000,0000,,of, and then over here you sort of page Dialogue: 0,0:14:49.62,0:14:52.43,Default,,0000,0000,0000,,out. And if you don't modularize things well,\Nthen Dialogue: 0,0:14:52.43,0:14:55.31,Default,,0000,0000,0000,,that, that, that thrashing is really, really\Nrisky. Because Dialogue: 0,0:14:55.31,0:14:56.70,Default,,0000,0000,0000,,it might mean that, like, I'm in this part Dialogue: 0,0:14:56.70,0:14:57.70,Default,,0000,0000,0000,,of the app, and I just kind of have Dialogue: 0,0:14:57.70,0:15:00.21,Default,,0000,0000,0000,,to hope that my tests are gonna cover me. Dialogue: 0,0:15:00.21,0:15:01.87,Default,,0000,0000,0000,,Although by the time you're this big, your\Ntests Dialogue: 0,0:15:01.87,0:15:03.67,Default,,0000,0000,0000,,in a typical Rails app are like ten hours Dialogue: 0,0:15:03.67,0:15:05.66,Default,,0000,0000,0000,,long. So maybe tomorrow you can find out that Dialogue: 0,0:15:05.66,0:15:07.51,Default,,0000,0000,0000,,it worked. Dialogue: 0,0:15:07.51,0:15:10.14,Default,,0000,0000,0000,,But if you, via common concerns, and find\Na Dialogue: 0,0:15:10.14,0:15:14.31,Default,,0000,0000,0000,,good module point to, to separate on, if you Dialogue: 0,0:15:14.31,0:15:15.79,Default,,0000,0000,0000,,were to identify that you could have, like,\Na Dialogue: 0,0:15:15.79,0:15:17.78,Default,,0000,0000,0000,,frontend app and a backend app, as those two Dialogue: 0,0:15:17.78,0:15:20.93,Default,,0000,0000,0000,,things grew, even if the net complexity is\Nhigher, Dialogue: 0,0:15:20.93,0:15:22.25,Default,,0000,0000,0000,,at some point they're not gonna fit in your Dialogue: 0,0:15:22.25,0:15:26.28,Default,,0000,0000,0000,,head either, but the paging story is much\Nnicer. Dialogue: 0,0:15:26.28,0:15:29.21,Default,,0000,0000,0000,,Because they have a clean, well-defined separate\Ncontract. So Dialogue: 0,0:15:29.21,0:15:32.66,Default,,0000,0000,0000,,the application that you're working in the\Nbackend application, Dialogue: 0,0:15:32.66,0:15:33.84,Default,,0000,0000,0000,,if you have to work in it, you can Dialogue: 0,0:15:33.84,0:15:35.69,Default,,0000,0000,0000,,work in it, and then when you page out, Dialogue: 0,0:15:35.69,0:15:38.19,Default,,0000,0000,0000,,it's not thrashing, cause there's a clear,\Nunderstood contract Dialogue: 0,0:15:38.19,0:15:40.62,Default,,0000,0000,0000,,between the two. Dialogue: 0,0:15:40.62,0:15:43.49,Default,,0000,0000,0000,,Relatedly, I like to say that late extraction\Ncosts Dialogue: 0,0:15:43.49,0:15:46.09,Default,,0000,0000,0000,,more than early abstraction. Yesterday, Sandi's\Ntalk was great Dialogue: 0,0:15:46.09,0:15:49.01,Default,,0000,0000,0000,,at telling us about wrong abstractions that\Nhave been Dialogue: 0,0:15:49.01,0:15:51.10,Default,,0000,0000,0000,,found and refactoring away from those, but\Nwhen we've Dialogue: 0,0:15:51.10,0:15:54.21,Default,,0000,0000,0000,,seen the same project a dozen different times,\NI Dialogue: 0,0:15:54.21,0:16:00.46,Default,,0000,0000,0000,,would much rather extract seldom and, and,\Nand abstract Dialogue: 0,0:16:00.46,0:16:02.32,Default,,0000,0000,0000,,early, and that's really confusing sounded\Nso I'm gonna Dialogue: 0,0:16:02.32,0:16:03.86,Default,,0000,0000,0000,,talk about yarn now. Dialogue: 0,0:16:03.86,0:16:07.55,Default,,0000,0000,0000,,Imagine you have two balls of yarn. If you Dialogue: 0,0:16:07.55,0:16:09.22,Default,,0000,0000,0000,,decided, like, man, I really just wish instead\Nof Dialogue: 0,0:16:09.22,0:16:10.91,Default,,0000,0000,0000,,these two ugly balls of yarn, I had a Dialogue: 0,0:16:10.91,0:16:13.62,Default,,0000,0000,0000,,big know of yarn all tangled together, that's\Nreally Dialogue: 0,0:16:13.62,0:16:15.76,Default,,0000,0000,0000,,easy to do, thanks to the basic laws of Dialogue: 0,0:16:15.76,0:16:18.22,Default,,0000,0000,0000,,entropy. But if I have a big tangled know Dialogue: 0,0:16:18.22,0:16:20.41,Default,,0000,0000,0000,,of yarn and decide that I really would love Dialogue: 0,0:16:20.41,0:16:23.73,Default,,0000,0000,0000,,two nicely-balled, you know, nice balls of\Nyarn, turns Dialogue: 0,0:16:23.73,0:16:26.100,Default,,0000,0000,0000,,out that's very, very difficult to do. That\Ndoesn't Dialogue: 0,0:16:26.100,0:16:27.90,Default,,0000,0000,0000,,work. Dialogue: 0,0:16:27.90,0:16:29.17,Default,,0000,0000,0000,,So that's why, what I mean when I say Dialogue: 0,0:16:29.17,0:16:32.25,Default,,0000,0000,0000,,that late abstraction, all of these, like,\Nfancy refactorings Dialogue: 0,0:16:32.25,0:16:34.44,Default,,0000,0000,0000,,that we can do, cost a lot more than Dialogue: 0,0:16:34.44,0:16:36.11,Default,,0000,0000,0000,,just knowing you needed two things in the\Nfirst Dialogue: 0,0:16:36.11,0:16:40.25,Default,,0000,0000,0000,,place. So, back to this, this two step that Dialogue: 0,0:16:40.25,0:16:41.66,Default,,0000,0000,0000,,I see in a lot of Rails applications, where Dialogue: 0,0:16:41.66,0:16:43.09,Default,,0000,0000,0000,,one project, you've got the JSON API but you Dialogue: 0,0:16:43.09,0:16:46.34,Default,,0000,0000,0000,,also have all the JavaScript. This isn't problematic\Nuntil Dialogue: 0,0:16:46.34,0:16:49.80,Default,,0000,0000,0000,,you consider this kind of stuff. You, you\Nhave Dialogue: 0,0:16:49.80,0:16:51.86,Default,,0000,0000,0000,,a template that renders a script tag at the Dialogue: 0,0:16:51.86,0:16:54.71,Default,,0000,0000,0000,,top, and then in the erb certain bits of Dialogue: 0,0:16:54.71,0:16:57.71,Default,,0000,0000,0000,,data are kind of taking this sneaky back door Dialogue: 0,0:16:57.71,0:17:00.57,Default,,0000,0000,0000,,instead of actually using the, the proper\NAPI, to Dialogue: 0,0:17:00.57,0:17:03.71,Default,,0000,0000,0000,,just dump data into the JavaScript application\Nneeds. When Dialogue: 0,0:17:03.71,0:17:05.63,Default,,0000,0000,0000,,you see this, it really means your yarn is Dialogue: 0,0:17:05.63,0:17:08.02,Default,,0000,0000,0000,,tangled, right. Even though you think you\Nhave separate Dialogue: 0,0:17:08.02,0:17:10.24,Default,,0000,0000,0000,,things. And your API is a lie. Because it Dialogue: 0,0:17:10.24,0:17:12.14,Default,,0000,0000,0000,,means that even though your application is\Nmostly using Dialogue: 0,0:17:12.14,0:17:13.61,Default,,0000,0000,0000,,that API, if somebody were to come and say, Dialogue: 0,0:17:13.61,0:17:14.62,Default,,0000,0000,0000,,hey, I want to build a mobile app for Dialogue: 0,0:17:14.62,0:17:16.33,Default,,0000,0000,0000,,your site, they're gonna have to spend a month Dialogue: 0,0:17:16.33,0:17:20.62,Default,,0000,0000,0000,,figuring out how to get that token, right. Dialogue: 0,0:17:20.62,0:17:23.28,Default,,0000,0000,0000,,But it's hard not to cheat. And I agree. Dialogue: 0,0:17:23.28,0:17:25.26,Default,,0000,0000,0000,,It's very, very difficult, especially given\Nwhat we talked Dialogue: 0,0:17:25.26,0:17:27.62,Default,,0000,0000,0000,,about earlier, where the tooling is so bad.\NSo Dialogue: 0,0:17:27.62,0:17:29.23,Default,,0000,0000,0000,,my objective in the last four years of, of, Dialogue: 0,0:17:29.23,0:17:31.94,Default,,0000,0000,0000,,of my, my open source contributions, and now\Nat Dialogue: 0,0:17:31.94,0:17:34.88,Default,,0000,0000,0000,,TestDouble, where we spend a lot of our time? Dialogue: 0,0:17:34.88,0:17:37.76,Default,,0000,0000,0000,,We want to help make JavaScript apps easy.\NAs Dialogue: 0,0:17:37.76,0:17:39.05,Default,,0000,0000,0000,,easy as Rails. Dialogue: 0,0:17:39.05,0:17:41.96,Default,,0000,0000,0000,,When you think about Rails and the responsibilities\Nof Dialogue: 0,0:17:41.96,0:17:45.65,Default,,0000,0000,0000,,Rails, there's really three distinct parts.\NWe have an Dialogue: 0,0:17:45.65,0:17:47.89,Default,,0000,0000,0000,,application framework. Stuff that we extend\N- ActionController and Dialogue: 0,0:17:47.89,0:17:51.20,Default,,0000,0000,0000,,so forth. We have conventions and configurations\Nthat are Dialogue: 0,0:17:51.20,0:17:52.87,Default,,0000,0000,0000,,laid out for us, that we learn through the Dialogue: 0,0:17:52.87,0:17:56.37,Default,,0000,0000,0000,,community and the documentation. And we have\Nbuild automation Dialogue: 0,0:17:56.37,0:18:00.52,Default,,0000,0000,0000,,stuff, like Rails CLI and Rake. And Rails\Nowns Dialogue: 0,0:18:00.52,0:18:01.61,Default,,0000,0000,0000,,the whole stack. Dialogue: 0,0:18:01.61,0:18:04.05,Default,,0000,0000,0000,,If I had to grade them separately, I'd say Dialogue: 0,0:18:04.05,0:18:06.25,Default,,0000,0000,0000,,that Rails as an application framework - when\NI Dialogue: 0,0:18:06.25,0:18:07.76,Default,,0000,0000,0000,,first found it, I loved it. But I found Dialogue: 0,0:18:07.76,0:18:09.90,Default,,0000,0000,0000,,on, like, many year, five year, six year projects, Dialogue: 0,0:18:09.90,0:18:12.09,Default,,0000,0000,0000,,it encourages a lot of things that problematic.\NSo Dialogue: 0,0:18:12.09,0:18:14.04,Default,,0000,0000,0000,,maybe I'd give that a B minus, if I Dialogue: 0,0:18:14.04,0:18:16.66,Default,,0000,0000,0000,,was grading it separately. But the conventions\Nand configurations, Dialogue: 0,0:18:16.66,0:18:18.19,Default,,0000,0000,0000,,that's awesome. I love that I can hit a Dialogue: 0,0:18:18.19,0:18:20.77,Default,,0000,0000,0000,,new Rails team's project and, because of the\Ntribal Dialogue: 0,0:18:20.77,0:18:22.27,Default,,0000,0000,0000,,knowledge that we have as well as the conventions Dialogue: 0,0:18:22.27,0:18:24.25,Default,,0000,0000,0000,,laid out and the sensible defaults, I can\Nsee Dialogue: 0,0:18:24.25,0:18:26.17,Default,,0000,0000,0000,,how is their app different from the norm really Dialogue: 0,0:18:26.17,0:18:27.58,Default,,0000,0000,0000,,easily. Dialogue: 0,0:18:27.58,0:18:29.64,Default,,0000,0000,0000,,Build automation stuff is pretty good. I think\Nit's Dialogue: 0,0:18:29.64,0:18:32.47,Default,,0000,0000,0000,,gotten a little bit stagnant. Fantastic in\N2005 and Dialogue: 0,0:18:32.47,0:18:33.83,Default,,0000,0000,0000,,I haven't seen a lot of really cool stuff Dialogue: 0,0:18:33.83,0:18:37.35,Default,,0000,0000,0000,,lately. But it's still solid. What I really\Nwant Dialogue: 0,0:18:37.35,0:18:39.52,Default,,0000,0000,0000,,to talk about today is convention and configuration\Nand Dialogue: 0,0:18:39.52,0:18:41.22,Default,,0000,0000,0000,,the value that that can bring to our JavaScript Dialogue: 0,0:18:41.22,0:18:43.63,Default,,0000,0000,0000,,tooling. Also keep in mind that a lot of Dialogue: 0,0:18:43.63,0:18:45.13,Default,,0000,0000,0000,,people that are new in Rails or have only Dialogue: 0,0:18:45.13,0:18:47.35,Default,,0000,0000,0000,,ever worked in Rails just see one big things. Dialogue: 0,0:18:47.35,0:18:49.39,Default,,0000,0000,0000,,They don't see these as separate problems.\NSo if Dialogue: 0,0:18:49.39,0:18:52.22,Default,,0000,0000,0000,,that's you, try to think about these responsibilities\Nseparately, Dialogue: 0,0:18:52.22,0:18:53.56,Default,,0000,0000,0000,,because I think they can be solved by separate Dialogue: 0,0:18:53.56,0:18:54.37,Default,,0000,0000,0000,,tools. Dialogue: 0,0:18:54.37,0:18:57.66,Default,,0000,0000,0000,,For example, in JavaScript, application frameworks\Nare everywhere. If Dialogue: 0,0:18:57.66,0:18:59.48,Default,,0000,0000,0000,,I decided I wanted to solve that middle problem Dialogue: 0,0:18:59.48,0:19:02.14,Default,,0000,0000,0000,,by writing another application framework,\Nthen I'd have to, Dialogue: 0,0:19:02.14,0:19:04.07,Default,,0000,0000,0000,,you know, go and popularize it against all\Nthe Dialogue: 0,0:19:04.07,0:19:06.12,Default,,0000,0000,0000,,other application frameworks. I think that\Nthey can be Dialogue: 0,0:19:06.12,0:19:08.81,Default,,0000,0000,0000,,separated. You know, whether I'm writing backbone\Nor Angular Dialogue: 0,0:19:08.81,0:19:10.52,Default,,0000,0000,0000,,or Ember - lately I've been writing a lot Dialogue: 0,0:19:10.52,0:19:12.93,Default,,0000,0000,0000,,of Ember and I love it. But every six Dialogue: 0,0:19:12.93,0:19:15.22,Default,,0000,0000,0000,,months I keep changing my mind. It's a fact. Dialogue: 0,0:19:15.22,0:19:16.86,Default,,0000,0000,0000,,So, so at this point I just wanna be Dialogue: 0,0:19:16.86,0:19:19.01,Default,,0000,0000,0000,,like, eh, I want to write awesome tools that Dialogue: 0,0:19:19.01,0:19:21.40,Default,,0000,0000,0000,,are framework agnostic that anybody can, can\Nexploit. Dialogue: 0,0:19:21.40,0:19:25.50,Default,,0000,0000,0000,,From the build automation perspective, like\NI said, the Dialogue: 0,0:19:25.50,0:19:28.59,Default,,0000,0000,0000,,community is already in node.js. Worldwide.\NAs soon as Dialogue: 0,0:19:28.59,0:19:30.85,Default,,0000,0000,0000,,stuff is happening, great tools are showing\Nup in Dialogue: 0,0:19:30.85,0:19:33.69,Default,,0000,0000,0000,,node.js first. I just want to be this little Dialogue: 0,0:19:33.69,0:19:35.09,Default,,0000,0000,0000,,guy in the middle, right. I want to be Dialogue: 0,0:19:35.09,0:19:36.59,Default,,0000,0000,0000,,the convention and the configuration, right.\NAnd that's why Dialogue: 0,0:19:36.59,0:19:38.46,Default,,0000,0000,0000,,we built lineman. Dialogue: 0,0:19:38.46,0:19:42.91,Default,,0000,0000,0000,,Lineman, like a, like a lineman on a railroad, Dialogue: 0,0:19:42.91,0:19:45.37,Default,,0000,0000,0000,,is on Twitter here, and you can find his Dialogue: 0,0:19:45.37,0:19:47.66,Default,,0000,0000,0000,,url. And you install him with npm. So you Dialogue: 0,0:19:47.66,0:19:49.01,Default,,0000,0000,0000,,have node.js install and you can just say\Nnpm Dialogue: 0,0:19:49.01,0:19:51.87,Default,,0000,0000,0000,,install globally lineman, and you create a\Nnew app Dialogue: 0,0:19:51.87,0:19:53.89,Default,,0000,0000,0000,,really easily with the cli, just like Rails.\NLineman Dialogue: 0,0:19:53.89,0:19:55.71,Default,,0000,0000,0000,,new app. Dialogue: 0,0:19:55.71,0:20:00.48,Default,,0000,0000,0000,,So, here's me typing in lineman new, start\Na Dialogue: 0,0:20:00.48,0:20:02.06,Default,,0000,0000,0000,,new project, and I get a little. I get Dialogue: 0,0:20:02.06,0:20:05.17,Default,,0000,0000,0000,,a handful of commands that I can run. But Dialogue: 0,0:20:05.17,0:20:08.06,Default,,0000,0000,0000,,first I'm just gonna cd in and I'm gonna Dialogue: 0,0:20:08.06,0:20:11.13,Default,,0000,0000,0000,,tree out all of the files that I have. Dialogue: 0,0:20:11.13,0:20:12.67,Default,,0000,0000,0000,,Like I said, it betrays the biases, right.\NOne Dialogue: 0,0:20:12.67,0:20:14.68,Default,,0000,0000,0000,,way to learn the conventions is see what it Dialogue: 0,0:20:14.68,0:20:16.53,Default,,0000,0000,0000,,generates. So you can see I have an app Dialogue: 0,0:20:16.53,0:20:19.12,Default,,0000,0000,0000,,directory with css and images and JavaScript\Nand then Dialogue: 0,0:20:19.12,0:20:20.88,Default,,0000,0000,0000,,pages that render on the backend and templates\Non Dialogue: 0,0:20:20.88,0:20:23.72,Default,,0000,0000,0000,,the front. A handful of configuration files.\NA whole Dialogue: 0,0:20:23.72,0:20:25.93,Default,,0000,0000,0000,,bunch of spec helpers to help you test. And Dialogue: 0,0:20:25.93,0:20:30.69,Default,,0000,0000,0000,,then places for all of your vendored third-party\Nlibraries. Dialogue: 0,0:20:30.69,0:20:32.72,Default,,0000,0000,0000,,And it's convenient, right. It's nice to get\Nthat Dialogue: 0,0:20:32.72,0:20:34.82,Default,,0000,0000,0000,,bootstrap for you. But our goal is to make Dialogue: 0,0:20:34.82,0:20:36.99,Default,,0000,0000,0000,,it convenient throughout, to switch between\Nprojects to reduce Dialogue: 0,0:20:36.99,0:20:39.50,Default,,0000,0000,0000,,duplication to make things more common across\Nall of Dialogue: 0,0:20:39.50,0:20:41.89,Default,,0000,0000,0000,,our work. Dialogue: 0,0:20:41.89,0:20:44.74,Default,,0000,0000,0000,,One aspect of that is our productivity workflow.\NI Dialogue: 0,0:20:44.74,0:20:46.50,Default,,0000,0000,0000,,want to be able to write some code, save Dialogue: 0,0:20:46.50,0:20:48.88,Default,,0000,0000,0000,,the code, have that code automatically compile\Nfor me Dialogue: 0,0:20:48.88,0:20:51.43,Default,,0000,0000,0000,,every time I save. Have it concatenate every\Ntime Dialogue: 0,0:20:51.43,0:20:53.02,Default,,0000,0000,0000,,that I save, and then I want to be Dialogue: 0,0:20:53.02,0:20:54.84,Default,,0000,0000,0000,,able to hit command r and refresh and play Dialogue: 0,0:20:54.84,0:20:56.33,Default,,0000,0000,0000,,with it. But I want to be able to Dialogue: 0,0:20:56.33,0:20:57.56,Default,,0000,0000,0000,,do all of that in less than a hundred Dialogue: 0,0:20:57.56,0:20:59.25,Default,,0000,0000,0000,,milliseconds, because I want a fast feedback\Nloop so Dialogue: 0,0:20:59.25,0:21:01.08,Default,,0000,0000,0000,,that I can keep working quickly. Dialogue: 0,0:21:01.08,0:21:02.49,Default,,0000,0000,0000,,In lineman, we do this with a command called Dialogue: 0,0:21:02.49,0:21:04.65,Default,,0000,0000,0000,,lineman run. So you say lineman run, it does Dialogue: 0,0:21:04.65,0:21:06.67,Default,,0000,0000,0000,,a whole bunch of initial build stuff, but\Nthen Dialogue: 0,0:21:06.67,0:21:08.23,Default,,0000,0000,0000,,it just starts watching for file changes.\NSo I Dialogue: 0,0:21:08.23,0:21:10.90,Default,,0000,0000,0000,,can hit this server, the dev server. It says Dialogue: 0,0:21:10.90,0:21:13.60,Default,,0000,0000,0000,,Hello, World! I'm gonna make a quick changes,\Nsay Dialogue: 0,0:21:13.60,0:21:16.74,Default,,0000,0000,0000,,Goodbye, World! It's already updated. I refresh\Nthe page Dialogue: 0,0:21:16.74,0:21:17.57,Default,,0000,0000,0000,,and that's that. Dialogue: 0,0:21:17.57,0:21:19.63,Default,,0000,0000,0000,,Now, this is a simple app, but even on Dialogue: 0,0:21:19.63,0:21:22.22,Default,,0000,0000,0000,,large apps it scales very well. On our large Dialogue: 0,0:21:22.22,0:21:26.29,Default,,0000,0000,0000,,applications it's still roughly a hundred\Nmilliseconds. Dialogue: 0,0:21:26.29,0:21:30.76,Default,,0000,0000,0000,,So, this is great. But command-r driven development\Nisn't Dialogue: 0,0:21:30.76,0:21:32.64,Default,,0000,0000,0000,,the whole story, right. I also like to write Dialogue: 0,0:21:32.64,0:21:35.49,Default,,0000,0000,0000,,tests, too. Sometimes I'm doing test-driven\Ndevelopment. When I Dialogue: 0,0:21:35.49,0:21:39.05,Default,,0000,0000,0000,,do, I also want the same story to slot Dialogue: 0,0:21:39.05,0:21:41.69,Default,,0000,0000,0000,,in really nicely with, with tests. And I want Dialogue: 0,0:21:41.69,0:21:44.89,Default,,0000,0000,0000,,the same feedback cycle to be super duper\Nfast. Dialogue: 0,0:21:44.89,0:21:47.60,Default,,0000,0000,0000,,Lineman ships with a cool tool called testem,\Nwritten Dialogue: 0,0:21:47.60,0:21:49.96,Default,,0000,0000,0000,,by Toby Ho, that's really fantastic. What\Nyou do Dialogue: 0,0:21:49.96,0:21:51.78,Default,,0000,0000,0000,,is you open up another shell, a second shell, Dialogue: 0,0:21:51.78,0:21:53.65,Default,,0000,0000,0000,,and you run lineman spec. And you get this Dialogue: 0,0:21:53.65,0:21:58.35,Default,,0000,0000,0000,,interactive test runner, launches Chrome here,\Nand here I'm Dialogue: 0,0:21:58.35,0:22:01.88,Default,,0000,0000,0000,,running a test already. Gonna just change\Nthe spec Dialogue: 0,0:22:01.88,0:22:04.47,Default,,0000,0000,0000,,to say that I'm specifying that that function\Nreturned Dialogue: 0,0:22:04.47,0:22:05.73,Default,,0000,0000,0000,,Goodbye, World! Dialogue: 0,0:22:05.73,0:22:09.95,Default,,0000,0000,0000,,Save it off. Got a failure. That quickly.\NI Dialogue: 0,0:22:09.95,0:22:12.11,Default,,0000,0000,0000,,can debug cause it's in the browser. I'm just Dialogue: 0,0:22:12.11,0:22:14.69,Default,,0000,0000,0000,,gonna fix it. Save. And that's it. My tests Dialogue: 0,0:22:14.69,0:22:17.40,Default,,0000,0000,0000,,are passing. In addition to the interactive\Nrunner, we Dialogue: 0,0:22:17.40,0:22:19.50,Default,,0000,0000,0000,,want a really solid CI story. So you just Dialogue: 0,0:22:19.50,0:22:21.66,Default,,0000,0000,0000,,quit out of testem with the q key, and Dialogue: 0,0:22:21.66,0:22:24.09,Default,,0000,0000,0000,,you can type lineman spec ci, and this is Dialogue: 0,0:22:24.09,0:22:26.95,Default,,0000,0000,0000,,gonna run it all in phantom.js with a nice Dialogue: 0,0:22:26.95,0:22:31.07,Default,,0000,0000,0000,,reporter output. And every lineman project\Ngenerates a travis.yml Dialogue: 0,0:22:31.07,0:22:32.96,Default,,0000,0000,0000,,file when you lineman new. So you literally\Njust Dialogue: 0,0:22:32.96,0:22:34.74,Default,,0000,0000,0000,,push it to GitHub, and if you use Travis Dialogue: 0,0:22:34.74,0:22:37.02,Default,,0000,0000,0000,,as your CI service, it's a one button thing Dialogue: 0,0:22:37.02,0:22:38.31,Default,,0000,0000,0000,,and now you have a CI build for your Dialogue: 0,0:22:38.31,0:22:41.37,Default,,0000,0000,0000,,JavaScript. Which if we were to ask people\Nto Dialogue: 0,0:22:41.37,0:22:43.06,Default,,0000,0000,0000,,raise hands, I don't think every hand would\Ngo Dialogue: 0,0:22:43.06,0:22:46.71,Default,,0000,0000,0000,,up if, if I asked if you have one. Dialogue: 0,0:22:46.71,0:22:48.95,Default,,0000,0000,0000,,The deploy story is similar easy, because\Nsince lineman Dialogue: 0,0:22:48.95,0:22:51.88,Default,,0000,0000,0000,,is just a static asset generating tool, can\Nyour Dialogue: 0,0:22:51.88,0:22:54.75,Default,,0000,0000,0000,,server host static files? Then yeah, you're\Ngood. When Dialogue: 0,0:22:54.75,0:22:56.88,Default,,0000,0000,0000,,you write a lineman build, and then you tree Dialogue: 0,0:22:56.88,0:22:59.01,Default,,0000,0000,0000,,out its dist directory, which is where it\Nputs Dialogue: 0,0:22:59.01,0:23:00.97,Default,,0000,0000,0000,,its built artifacts, it looks a little like\Nthis Dialogue: 0,0:23:00.97,0:23:02.84,Default,,0000,0000,0000,,out of the box. You have an html file Dialogue: 0,0:23:02.84,0:23:05.00,Default,,0000,0000,0000,,that references a css file and a JavaScript\Nfile Dialogue: 0,0:23:05.00,0:23:06.39,Default,,0000,0000,0000,,and both of those have already been concatted\Nand Dialogue: 0,0:23:06.39,0:23:08.72,Default,,0000,0000,0000,,minified for you and they're ready to deploy. Dialogue: 0,0:23:08.72,0:23:10.20,Default,,0000,0000,0000,,There's a single flag in the config that you Dialogue: 0,0:23:10.20,0:23:12.00,Default,,0000,0000,0000,,can set, and then just like Rails, you get Dialogue: 0,0:23:12.00,0:23:13.97,Default,,0000,0000,0000,,asset fingerprinted that makes it really nice\Nfor deploying Dialogue: 0,0:23:13.97,0:23:16.84,Default,,0000,0000,0000,,when you have a CDN. Everything else that\Never Dialogue: 0,0:23:16.84,0:23:18.22,Default,,0000,0000,0000,,is gonna end up in your dist directory is Dialogue: 0,0:23:18.22,0:23:20.13,Default,,0000,0000,0000,,gonna be stuff that you added, so it'll be Dialogue: 0,0:23:20.13,0:23:23.07,Default,,0000,0000,0000,,stuff that you understand. It's a really easy\Nbuild Dialogue: 0,0:23:23.07,0:23:25.13,Default,,0000,0000,0000,,story. Dialogue: 0,0:23:25.13,0:23:27.13,Default,,0000,0000,0000,,Pushing to Heroku is also really easy. We\Nhost Dialogue: 0,0:23:27.13,0:23:29.70,Default,,0000,0000,0000,,most of our testable stuff on Heroku, so we Dialogue: 0,0:23:29.70,0:23:32.26,Default,,0000,0000,0000,,just set, we wrote a custom buildpack. You\Nset Dialogue: 0,0:23:32.26,0:23:34.39,Default,,0000,0000,0000,,that up and then you say git push. It'll Dialogue: 0,0:23:34.39,0:23:36.68,Default,,0000,0000,0000,,build it with node.js, but then at runtime\Nwe Dialogue: 0,0:23:36.68,0:23:38.30,Default,,0000,0000,0000,,don't need it and so it just runs statically Dialogue: 0,0:23:38.30,0:23:41.69,Default,,0000,0000,0000,,without node. Dialogue: 0,0:23:41.69,0:23:42.57,Default,,0000,0000,0000,,And we also have a whole bunch of starter Dialogue: 0,0:23:42.57,0:23:45.21,Default,,0000,0000,0000,,projects to help get people up and running\Nquickly. Dialogue: 0,0:23:45.21,0:23:48.27,Default,,0000,0000,0000,,Not everyone's just writing vanilla JavaScript,\Nright. We have Dialogue: 0,0:23:48.27,0:23:49.91,Default,,0000,0000,0000,,some people who want to get started with Angular Dialogue: 0,0:23:49.91,0:23:53.92,Default,,0000,0000,0000,,quickly, Backbone or Ember. You can just clone\Nand Dialogue: 0,0:23:53.92,0:23:55.71,Default,,0000,0000,0000,,go. Clone the project and get started. You'll\Nhave Dialogue: 0,0:23:55.71,0:23:57.38,Default,,0000,0000,0000,,a little bit of example code. It's a great Dialogue: 0,0:23:57.38,0:23:59.23,Default,,0000,0000,0000,,way, if you want to learn Angular or learn Dialogue: 0,0:23:59.23,0:24:01.34,Default,,0000,0000,0000,,Ember, just to clone our example project,\Nbecause it'll Dialogue: 0,0:24:01.34,0:24:03.07,Default,,0000,0000,0000,,build right away. Like, you already know how\Nto Dialogue: 0,0:24:03.07,0:24:04.31,Default,,0000,0000,0000,,run it. Dialogue: 0,0:24:04.31,0:24:07.18,Default,,0000,0000,0000,,We also have a, a really cool. It's because Dialogue: 0,0:24:07.18,0:24:08.49,Default,,0000,0000,0000,,it's all flexible, we also use lineman to\Nbuild Dialogue: 0,0:24:08.49,0:24:12.21,Default,,0000,0000,0000,,all of our JavaScript libs, libs that we maintain, Dialogue: 0,0:24:12.21,0:24:14.11,Default,,0000,0000,0000,,as well as our blog and, and you're free Dialogue: 0,0:24:14.11,0:24:16.26,Default,,0000,0000,0000,,to use lineman, of course, to, to write a Dialogue: 0,0:24:16.26,0:24:18.64,Default,,0000,0000,0000,,markdown blog. It's really, really convenient. Dialogue: 0,0:24:18.64,0:24:23.55,Default,,0000,0000,0000,,So back to planet earth. We're using Grunt.\NWe, Dialogue: 0,0:24:23.55,0:24:26.76,Default,,0000,0000,0000,,Grunt is a build tool descended from, you\Nknow, Dialogue: 0,0:24:26.76,0:24:29.90,Default,,0000,0000,0000,,a whole bunch of other build tools, that is Dialogue: 0,0:24:29.90,0:24:31.94,Default,,0000,0000,0000,,used for task definition. There's a lot of\Ndifferent, Dialogue: 0,0:24:31.94,0:24:33.34,Default,,0000,0000,0000,,there's a lot of competition here right now\Nin Dialogue: 0,0:24:33.34,0:24:35.38,Default,,0000,0000,0000,,node.js. A lot of people using Gulp. A thing Dialogue: 0,0:24:35.38,0:24:38.02,Default,,0000,0000,0000,,called Broccoli came out recently. It's really\Ncool. But Dialogue: 0,0:24:38.02,0:24:40.63,Default,,0000,0000,0000,,what we use Grunt for, primarily, is a place Dialogue: 0,0:24:40.63,0:24:43.50,Default,,0000,0000,0000,,to get awesome stuff from the community. Dialogue: 0,0:24:43.50,0:24:46.29,Default,,0000,0000,0000,,All these tasks ship with lineman out of the Dialogue: 0,0:24:46.29,0:24:48.39,Default,,0000,0000,0000,,box. Or are, and, and so many more are Dialogue: 0,0:24:48.39,0:24:52.40,Default,,0000,0000,0000,,available. We really, really love that we're\Nable to Dialogue: 0,0:24:52.40,0:24:56.51,Default,,0000,0000,0000,,so easily pull in new behavior through Grunt\Nin Dialogue: 0,0:24:56.51,0:25:01.38,Default,,0000,0000,0000,,a consistent manner. Lineman itself is comically\Nextensible. We Dialogue: 0,0:25:01.38,0:25:03.35,Default,,0000,0000,0000,,have a plugin system that is built a little Dialogue: 0,0:25:03.35,0:25:06.24,Default,,0000,0000,0000,,bit around this mental model. We'll talk about\Nit Dialogue: 0,0:25:06.24,0:25:08.75,Default,,0000,0000,0000,,in a second. But it's really easy from a Dialogue: 0,0:25:08.75,0:25:12.03,Default,,0000,0000,0000,,user's perspective. All you do is save it.\Nnpm Dialogue: 0,0:25:12.03,0:25:15.60,Default,,0000,0000,0000,,install, then you save the, save the dependency.\NRun, Dialogue: 0,0:25:15.60,0:25:18.59,Default,,0000,0000,0000,,like, lineman-bower. When you do that, after\Nyou run Dialogue: 0,0:25:18.59,0:25:20.62,Default,,0000,0000,0000,,lineman run, the next time after you save\Nthat, Dialogue: 0,0:25:20.62,0:25:22.24,Default,,0000,0000,0000,,lineman will pick it up from your packaged\NJSON, Dialogue: 0,0:25:22.24,0:25:24.00,Default,,0000,0000,0000,,know that it needs to load it, and bower Dialogue: 0,0:25:24.00,0:25:25.94,Default,,0000,0000,0000,,will be slotted in at the appropriate step\Ninto Dialogue: 0,0:25:25.94,0:25:28.73,Default,,0000,0000,0000,,your build's workflow. No more configuration.\NIt even generates Dialogue: 0,0:25:28.73,0:25:30.08,Default,,0000,0000,0000,,your bower JSON for you if it's not there. Dialogue: 0,0:25:30.08,0:25:33.86,Default,,0000,0000,0000,,Cause deep down, there is an npm module out Dialogue: 0,0:25:33.86,0:25:37.31,Default,,0000,0000,0000,,there, bower, right, published by Twitter,\Nand around it Dialogue: 0,0:25:37.31,0:25:39.95,Default,,0000,0000,0000,,is the, a, a grunt-bower-task that somebody\Nin the Dialogue: 0,0:25:39.95,0:25:42.10,Default,,0000,0000,0000,,community published, and then at the top we\Nhave Dialogue: 0,0:25:42.10,0:25:45.48,Default,,0000,0000,0000,,this lineman-bower plugin that we maintain.\NBower is the Dialogue: 0,0:25:45.48,0:25:47.21,Default,,0000,0000,0000,,thing that actually does the thing. That's\Nwhere most Dialogue: 0,0:25:47.21,0:25:48.37,Default,,0000,0000,0000,,of the hard work is. Dialogue: 0,0:25:48.37,0:25:52.34,Default,,0000,0000,0000,,This, this power-task here, from Grunt, it\Nautomates the Dialogue: 0,0:25:52.34,0:25:54.82,Default,,0000,0000,0000,,thing. There's a lot of hard work there, too. Dialogue: 0,0:25:54.82,0:25:57.29,Default,,0000,0000,0000,,What lineman does is it just knows, given\Nlineman's Dialogue: 0,0:25:57.29,0:25:59.40,Default,,0000,0000,0000,,conventions, how to configure the thing for\Nyou. And Dialogue: 0,0:25:59.40,0:26:01.39,Default,,0000,0000,0000,,so we have this kind of boxed approached to, Dialogue: 0,0:26:01.39,0:26:03.55,Default,,0000,0000,0000,,to how we conceptualize plugins. Dialogue: 0,0:26:03.55,0:26:05.30,Default,,0000,0000,0000,,So you, in your application, you might have\Na Dialogue: 0,0:26:05.30,0:26:06.75,Default,,0000,0000,0000,,lineman-bower plugin that you use, but you\Ncan also Dialogue: 0,0:26:06.75,0:26:08.60,Default,,0000,0000,0000,,have a lineman-ember plugin that's gonna handle\Nall your Dialogue: 0,0:26:08.60,0:26:11.21,Default,,0000,0000,0000,,templates the way that Ember likes to see\Nit. Dialogue: 0,0:26:11.21,0:26:13.64,Default,,0000,0000,0000,,And recently we, we learned and were really\Nexcited Dialogue: 0,0:26:13.64,0:26:17.23,Default,,0000,0000,0000,,that RackSpace is adopting lineman for its\Nfrontend development, Dialogue: 0,0:26:17.23,0:26:19.79,Default,,0000,0000,0000,,and I encouraged them to write a metaplugin,\Nbecause Dialogue: 0,0:26:19.79,0:26:22.82,Default,,0000,0000,0000,,you can have recursively arbitrarily many\Nplugins down the Dialogue: 0,0:26:22.82,0:26:24.99,Default,,0000,0000,0000,,line. So this plugin here - name it whatever Dialogue: 0,0:26:24.99,0:26:27.26,Default,,0000,0000,0000,,you want. Maybe your company's stack or something.\NIt Dialogue: 0,0:26:27.26,0:26:29.26,Default,,0000,0000,0000,,can bundle as many plugins at the appropriate\Nversions Dialogue: 0,0:26:29.26,0:26:31.30,Default,,0000,0000,0000,,that you want, but you can also override any Dialogue: 0,0:26:31.30,0:26:33.21,Default,,0000,0000,0000,,of the configurations in those plugins, get\Nthem just Dialogue: 0,0:26:33.21,0:26:34.48,Default,,0000,0000,0000,,how you like. That way you don't have all Dialogue: 0,0:26:34.48,0:26:37.42,Default,,0000,0000,0000,,this duplicated configuration across all of\Nyour team's files, Dialogue: 0,0:26:37.42,0:26:40.45,Default,,0000,0000,0000,,team's project. Dialogue: 0,0:26:40.45,0:26:42.69,Default,,0000,0000,0000,,Back to monolithic application architecture,\NI've painted a picture Dialogue: 0,0:26:42.69,0:26:44.43,Default,,0000,0000,0000,,where we can separate into two things. But\NI Dialogue: 0,0:26:44.43,0:26:45.12,Default,,0000,0000,0000,,want to talk a little bit more about the Dialogue: 0,0:26:45.12,0:26:47.44,Default,,0000,0000,0000,,benefits of doing that. So say that you have Dialogue: 0,0:26:47.44,0:26:49.18,Default,,0000,0000,0000,,a client in the server. One of the first Dialogue: 0,0:26:49.18,0:26:51.28,Default,,0000,0000,0000,,questions that comes up is like, hey, well,\Nhow Dialogue: 0,0:26:51.28,0:26:54.00,Default,,0000,0000,0000,,am I gonna run stuff in development, but it Dialogue: 0,0:26:54.00,0:26:55.33,Default,,0000,0000,0000,,still needs to see the server? I'm not gonna Dialogue: 0,0:26:55.33,0:26:58.16,Default,,0000,0000,0000,,build all these extra stubs for my server\Nside. Dialogue: 0,0:26:58.16,0:27:00.85,Default,,0000,0000,0000,,And we agree. That would be really onerous.\NSo Dialogue: 0,0:27:00.85,0:27:02.36,Default,,0000,0000,0000,,we built a feature into lineman that we call Dialogue: 0,0:27:02.36,0:27:07.10,Default,,0000,0000,0000,,API Proxying. Basically, think of the browser\Nhitting lineman, Dialogue: 0,0:27:07.10,0:27:10.30,Default,,0000,0000,0000,,and maybe we have Sinatra in the backend.\NThe Dialogue: 0,0:27:10.30,0:27:12.35,Default,,0000,0000,0000,,browser's only gonna know about lineman. It's\Ngonna make Dialogue: 0,0:27:12.35,0:27:14.26,Default,,0000,0000,0000,,all of its requests to lineman. But whenever\Nthey Dialogue: 0,0:27:14.26,0:27:16.25,Default,,0000,0000,0000,,ask for any API routes that lineman doesn't\Nknow Dialogue: 0,0:27:16.25,0:27:18.84,Default,,0000,0000,0000,,how to respond to, we've got it configured\Nto Dialogue: 0,0:27:18.84,0:27:21.73,Default,,0000,0000,0000,,call back to Sinatra. Sinatra responds and\Nthen lineman Dialogue: 0,0:27:21.73,0:27:23.71,Default,,0000,0000,0000,,proxies that request back to the browser. Dialogue: 0,0:27:23.71,0:27:25.62,Default,,0000,0000,0000,,So it's a seamless environment. It's as if\Nyou're Dialogue: 0,0:27:25.62,0:27:27.56,Default,,0000,0000,0000,,developing on one thing at runtime even though\Nthe Dialogue: 0,0:27:27.56,0:27:30.09,Default,,0000,0000,0000,,code has all the benefits of, of, of physical Dialogue: 0,0:27:30.09,0:27:30.85,Default,,0000,0000,0000,,separation. Dialogue: 0,0:27:30.85,0:27:33.45,Default,,0000,0000,0000,,It looks a little bit like this. So here Dialogue: 0,0:27:33.45,0:27:35.52,Default,,0000,0000,0000,,I'm gonna uncomment a little bit of configuration\Nthat Dialogue: 0,0:27:35.52,0:27:37.71,Default,,0000,0000,0000,,we give you. Change the port to 4567, for Dialogue: 0,0:27:37.71,0:27:44.71,Default,,0000,0000,0000,,Sinatra. My application's real simple. It's\Njust got a Dialogue: 0,0:27:45.93,0:27:48.06,Default,,0000,0000,0000,,simple route hi. It gets it and then it Dialogue: 0,0:27:48.06,0:27:51.68,Default,,0000,0000,0000,,paints it onto the screen, whatever the text\Nis. Dialogue: 0,0:27:51.68,0:27:54.35,Default,,0000,0000,0000,,And my Sinatra app just returns I heart Ruby Dialogue: 0,0:27:54.35,0:27:58.06,Default,,0000,0000,0000,,at that particular route. Dialogue: 0,0:27:58.06,0:28:02.07,Default,,0000,0000,0000,,So when I write lineman run, you can see Dialogue: 0,0:28:02.07,0:28:03.78,Default,,0000,0000,0000,,it, instead of proxying I'm gonna look at\NSinatra's Dialogue: 0,0:28:03.78,0:28:06.39,Default,,0000,0000,0000,,logs. I refresh, and it got the request from Dialogue: 0,0:28:06.39,0:28:11.35,Default,,0000,0000,0000,,lineman and it returned through the browser.\NSuper easy. Dialogue: 0,0:28:11.35,0:28:13.02,Default,,0000,0000,0000,,Now there's other cases, too, cause the benefit\Nof Dialogue: 0,0:28:13.02,0:28:15.16,Default,,0000,0000,0000,,separating frontend and backend, a big part\Nof that Dialogue: 0,0:28:15.16,0:28:17.25,Default,,0000,0000,0000,,story is that now development of those two\Nthings Dialogue: 0,0:28:17.25,0:28:19.50,Default,,0000,0000,0000,,doesn't have to run in lock step, right. We Dialogue: 0,0:28:19.50,0:28:20.83,Default,,0000,0000,0000,,can make a little bit of extra progress in Dialogue: 0,0:28:20.83,0:28:23.15,Default,,0000,0000,0000,,the frontend, maybe do some prototyping. We\Ncan have Dialogue: 0,0:28:23.15,0:28:26.91,Default,,0000,0000,0000,,a separate backend team after we get big.\NBut Dialogue: 0,0:28:26.91,0:28:28.56,Default,,0000,0000,0000,,a lot of times we have, like, you know, Dialogue: 0,0:28:28.56,0:28:30.04,Default,,0000,0000,0000,,it being handy to be able to stub stuff Dialogue: 0,0:28:30.04,0:28:32.07,Default,,0000,0000,0000,,out that doesn't actually exist on the server\Nyet, Dialogue: 0,0:28:32.07,0:28:33.89,Default,,0000,0000,0000,,so we can get faster feedback cycles while\Nwe're Dialogue: 0,0:28:33.89,0:28:35.48,Default,,0000,0000,0000,,developing our frontend. Dialogue: 0,0:28:35.48,0:28:36.82,Default,,0000,0000,0000,,And we offered this in lineman with a tool Dialogue: 0,0:28:36.82,0:28:40.32,Default,,0000,0000,0000,,that we called API stubbing. So same situation.\NWe Dialogue: 0,0:28:40.32,0:28:43.53,Default,,0000,0000,0000,,have a browser and it's gonna be hitting lineman. Dialogue: 0,0:28:43.53,0:28:45.34,Default,,0000,0000,0000,,And instead of actually phoning through to\NSinatra, we're Dialogue: 0,0:28:45.34,0:28:46.96,Default,,0000,0000,0000,,gonna kind of stub our a particular route\Nand Dialogue: 0,0:28:46.96,0:28:50.17,Default,,0000,0000,0000,,prevent Sinatra from getting it. And we're\Ngonna return Dialogue: 0,0:28:50.17,0:28:52.92,Default,,0000,0000,0000,,that stub back to the browser. Dialogue: 0,0:28:52.92,0:28:55.39,Default,,0000,0000,0000,,So same, same, same exact code base. We're\Ngonna Dialogue: 0,0:28:55.39,0:28:58.10,Default,,0000,0000,0000,,go into config slash server.js. This is a,\Nan Dialogue: 0,0:28:58.10,0:29:00.56,Default,,0000,0000,0000,,express application that's just kind of bundled\Nin. We Dialogue: 0,0:29:00.56,0:29:02.93,Default,,0000,0000,0000,,can define any route we'd like. We can overwrite Dialogue: 0,0:29:02.93,0:29:07.23,Default,,0000,0000,0000,,that hi route. And we're gonna, we're gonna\Ntroll Dialogue: 0,0:29:07.23,0:29:11.30,Default,,0000,0000,0000,,our coworkers here by sending that We heart\NNode Dialogue: 0,0:29:11.30,0:29:13.60,Default,,0000,0000,0000,,Even More. Sacrilege. Dialogue: 0,0:29:13.60,0:29:16.81,Default,,0000,0000,0000,,So run lineman. Refresh the page. And now\Nour Dialogue: 0,0:29:16.81,0:29:19.03,Default,,0000,0000,0000,,stubbing is in place. You can build entire\Ntoy Dialogue: 0,0:29:19.03,0:29:22.01,Default,,0000,0000,0000,,applications inside of that express application.\NWe've had clients Dialogue: 0,0:29:22.01,0:29:24.84,Default,,0000,0000,0000,,in the past, TestDouble is an agency, and\Nso Dialogue: 0,0:29:24.84,0:29:26.33,Default,,0000,0000,0000,,we're, we're as consultants. We've had clients\Nin the Dialogue: 0,0:29:26.33,0:29:27.72,Default,,0000,0000,0000,,past who've asked us, hey just give us the Dialogue: 0,0:29:27.72,0:29:30.26,Default,,0000,0000,0000,,specifications of the services that you want,\Nand our Dialogue: 0,0:29:30.26,0:29:32.09,Default,,0000,0000,0000,,specification is a living document of, well,\Njust make Dialogue: 0,0:29:32.09,0:29:34.34,Default,,0000,0000,0000,,it do this. And it's been a really, really Dialogue: 0,0:29:34.34,0:29:39.15,Default,,0000,0000,0000,,seamless - it's certainly better than traditional\Ndocumentation. Dialogue: 0,0:29:39.15,0:29:40.36,Default,,0000,0000,0000,,Another case that I like a lot is I Dialogue: 0,0:29:40.36,0:29:43.28,Default,,0000,0000,0000,,had a project once with a thirty-minute long\Ntest Dialogue: 0,0:29:43.28,0:29:46.60,Default,,0000,0000,0000,,build, and I split it up into, I split Dialogue: 0,0:29:46.60,0:29:48.97,Default,,0000,0000,0000,,the application up into two. A frontend and\Na Dialogue: 0,0:29:48.97,0:29:51.70,Default,,0000,0000,0000,,backend, just like we're talking about. Then\NI went Dialogue: 0,0:29:51.70,0:29:54.01,Default,,0000,0000,0000,,to recover that new application with tests,\Nand I Dialogue: 0,0:29:54.01,0:29:57.06,Default,,0000,0000,0000,,found that the frontend tests had a runtime\Nof Dialogue: 0,0:29:57.06,0:29:59.61,Default,,0000,0000,0000,,only four minutes. That made me very worried\Nabout Dialogue: 0,0:29:59.61,0:30:01.23,Default,,0000,0000,0000,,the state of affairs in the backend. I figured Dialogue: 0,0:30:01.23,0:30:03.19,Default,,0000,0000,0000,,that might mean that the twenty-six minutes\Nwas hiding Dialogue: 0,0:30:03.19,0:30:05.61,Default,,0000,0000,0000,,there somewhere. But as it turns out, I wrote Dialogue: 0,0:30:05.61,0:30:08.10,Default,,0000,0000,0000,,that, and that only took four minutes, too. Dialogue: 0,0:30:08.10,0:30:09.26,Default,,0000,0000,0000,,So then I got really suspicious and I'm like, Dialogue: 0,0:30:09.26,0:30:10.97,Default,,0000,0000,0000,,I should probably have some smoke test to\Nmake Dialogue: 0,0:30:10.97,0:30:12.48,Default,,0000,0000,0000,,sure that when this is all plugged into, plugged Dialogue: 0,0:30:12.48,0:30:15.18,Default,,0000,0000,0000,,together correctly, it works. And the smoke\Ntest, of Dialogue: 0,0:30:15.18,0:30:16.41,Default,,0000,0000,0000,,course, when you plug it in both, it's a Dialogue: 0,0:30:16.41,0:30:17.73,Default,,0000,0000,0000,,little bit slower, and that ran at a whole Dialogue: 0,0:30:17.73,0:30:19.79,Default,,0000,0000,0000,,two minutes. Dialogue: 0,0:30:19.79,0:30:22.66,Default,,0000,0000,0000,,So this thirty-minute test suite somehow got\Nreduce to Dialogue: 0,0:30:22.66,0:30:24.00,Default,,0000,0000,0000,,a ten minute build, even though the next,\Nthe Dialogue: 0,0:30:24.00,0:30:27.19,Default,,0000,0000,0000,,logical and physical complexity of the system\Nincreased. And Dialogue: 0,0:30:27.19,0:30:29.63,Default,,0000,0000,0000,,if you understand how build duration tends\Nto build Dialogue: 0,0:30:29.63,0:30:32.01,Default,,0000,0000,0000,,super linearly, any savings that you can get\Nupfront Dialogue: 0,0:30:32.01,0:30:34.10,Default,,0000,0000,0000,,in the beginning are going to mean a big Dialogue: 0,0:30:34.10,0:30:36.99,Default,,0000,0000,0000,,difference, you're going to get a lot longer\Nrunway Dialogue: 0,0:30:36.99,0:30:38.66,Default,,0000,0000,0000,,and traction out of the build suite in the Dialogue: 0,0:30:38.66,0:30:39.90,Default,,0000,0000,0000,,far future. Dialogue: 0,0:30:39.90,0:30:44.02,Default,,0000,0000,0000,,And, additionally, it's habit-forming, right.\NI mean, having a, Dialogue: 0,0:30:44.02,0:30:46.06,Default,,0000,0000,0000,,a, there's a lot of operational problems that\Nyou Dialogue: 0,0:30:46.06,0:30:48.08,Default,,0000,0000,0000,,have to solve when you have two different\Nthings Dialogue: 0,0:30:48.08,0:30:50.71,Default,,0000,0000,0000,,to maintain and manage and version, as a deploy Dialogue: 0,0:30:50.71,0:30:53.68,Default,,0000,0000,0000,,story, two different projects. You can make\Nit simple, Dialogue: 0,0:30:53.68,0:30:57.37,Default,,0000,0000,0000,,but I mean, once you solve that problem, once, Dialogue: 0,0:30:57.37,0:31:02.32,Default,,0000,0000,0000,,you can have arbitrarily many microservices\Npopping up. Dialogue: 0,0:31:02.32,0:31:04.35,Default,,0000,0000,0000,,And if you're viewing the world as going in Dialogue: 0,0:31:04.35,0:31:06.23,Default,,0000,0000,0000,,that direction, it's a great problem to solve\Nnow Dialogue: 0,0:31:06.23,0:31:08.55,Default,,0000,0000,0000,,with a problem that you already understand\Nreally well. Dialogue: 0,0:31:08.55,0:31:10.21,Default,,0000,0000,0000,,Frontends and backends. Dialogue: 0,0:31:10.21,0:31:13.85,Default,,0000,0000,0000,,Additionally, this is not a frontend versus\NRails talk. Dialogue: 0,0:31:13.85,0:31:16.19,Default,,0000,0000,0000,,It's an and. We love Rails. We use Rails Dialogue: 0,0:31:16.19,0:31:18.65,Default,,0000,0000,0000,,all the time for our services. And lineman\Nand Dialogue: 0,0:31:18.65,0:31:21.24,Default,,0000,0000,0000,,Rails play together really nicely. We've got\Na gem Dialogue: 0,0:31:21.24,0:31:24.22,Default,,0000,0000,0000,,called Rails lineman and lineman plugin called\Nlineman-rails. You Dialogue: 0,0:31:24.22,0:31:27.35,Default,,0000,0000,0000,,install both those things and you just magically,\Neverything Dialogue: 0,0:31:27.35,0:31:30.35,Default,,0000,0000,0000,,gets auto-configured. And, and your development\Nstory is great Dialogue: 0,0:31:30.35,0:31:32.84,Default,,0000,0000,0000,,and assets precompile is just wrapped with\Na lineman Dialogue: 0,0:31:32.84,0:31:33.66,Default,,0000,0000,0000,,build first. Dialogue: 0,0:31:33.66,0:31:36.38,Default,,0000,0000,0000,,You can learn more about that at linemanjs\Ndot Dialogue: 0,0:31:36.38,0:31:39.08,Default,,0000,0000,0000,,com dlash rails dot html. And we have this Dialogue: 0,0:31:39.08,0:31:42.06,Default,,0000,0000,0000,,fantastic little documentation site put together\Nfor us by Dialogue: 0,0:31:42.06,0:31:46.47,Default,,0000,0000,0000,,Derrick Briggs from neo. More recently, you\Ncan actually Dialogue: 0,0:31:46.47,0:31:48.91,Default,,0000,0000,0000,,see me do this myself, live coding, unedited,\Nin Dialogue: 0,0:31:48.91,0:31:51.52,Default,,0000,0000,0000,,an Ember screencast that I did - how to Dialogue: 0,0:31:51.52,0:31:54.34,Default,,0000,0000,0000,,get setup, like we would setup a project.\NAnd Dialogue: 0,0:31:54.34,0:31:56.71,Default,,0000,0000,0000,,that's at our blog. It's the current, most\Nrecent Dialogue: 0,0:31:56.71,0:31:58.90,Default,,0000,0000,0000,,article. So just hit the blog dot testdouble\Ndot Dialogue: 0,0:31:58.90,0:32:02.91,Default,,0000,0000,0000,,com and you'll see the, the embedded screencast. Dialogue: 0,0:32:02.91,0:32:04.98,Default,,0000,0000,0000,,It's a fantastic tool. We love working with\Nit. Dialogue: 0,0:32:04.98,0:32:08.01,Default,,0000,0000,0000,,I also, real quickly, I just want to thank Dialogue: 0,0:32:08.01,0:32:10.66,Default,,0000,0000,0000,,my friend Marissa Hile. She's a visual designer\Nwho's Dialogue: 0,0:32:10.66,0:32:12.69,Default,,0000,0000,0000,,available for contract. She did all of the\Ngood Dialogue: 0,0:32:12.69,0:32:19.66,Default,,0000,0000,0000,,illustrations in this talk. And, and, you\Nknow, we'd Dialogue: 0,0:32:19.66,0:32:21.55,Default,,0000,0000,0000,,love to help you. If these are problems that Dialogue: 0,0:32:21.55,0:32:23.77,Default,,0000,0000,0000,,are, that are, that are new and hard for Dialogue: 0,0:32:23.77,0:32:26.14,Default,,0000,0000,0000,,your team, let us know. You know, we are Dialogue: 0,0:32:26.14,0:32:27.75,Default,,0000,0000,0000,,consultants, and we'd love to like, engage\Nwith your Dialogue: 0,0:32:27.75,0:32:30.38,Default,,0000,0000,0000,,company and, and, and work on great stuff\Nalongside Dialogue: 0,0:32:30.38,0:32:31.94,Default,,0000,0000,0000,,you, but we'd also just love to answer your Dialogue: 0,0:32:31.94,0:32:33.92,Default,,0000,0000,0000,,questions, because I think we want to all\Nmake Dialogue: 0,0:32:33.92,0:32:37.03,Default,,0000,0000,0000,,an impact and, and move the conversation forward. Dialogue: 0,0:32:37.03,0:32:40.77,Default,,0000,0000,0000,,Also, like everyone else at RailsConf, we\Nare hiring. Dialogue: 0,0:32:40.77,0:32:42.39,Default,,0000,0000,0000,,Just set an email to join at testdouble dot Dialogue: 0,0:32:42.39,0:32:44.34,Default,,0000,0000,0000,,com and we'll respond to you promptly and\Nhave, Dialogue: 0,0:32:44.34,0:32:49.10,Default,,0000,0000,0000,,start the conversation. Also, a couple of\Nmy fellow Dialogue: 0,0:32:49.10,0:32:52.74,Default,,0000,0000,0000,,double agents, Todd Coffman and Zack Briggs,\Nare giving Dialogue: 0,0:32:52.74,0:32:55.00,Default,,0000,0000,0000,,a, a workshop this afternoon on JavaScript\Ntesting. I Dialogue: 0,0:32:55.00,0:32:56.83,Default,,0000,0000,0000,,think they'll probably be using lineman. So\Nit might Dialogue: 0,0:32:56.83,0:32:58.18,Default,,0000,0000,0000,,be a good place to practice both of those Dialogue: 0,0:32:58.18,0:33:00.22,Default,,0000,0000,0000,,things. Dialogue: 0,0:33:00.22,0:33:01.88,Default,,0000,0000,0000,,And I want to thank you. You know, please Dialogue: 0,0:33:01.88,0:33:03.75,Default,,0000,0000,0000,,reach out. I'd love to hear from you. It Dialogue: 0,0:33:03.75,0:33:05.49,Default,,0000,0000,0000,,was an absolute honor and a privilege to get Dialogue: 0,0:33:05.49,0:33:07.09,Default,,0000,0000,0000,,to speak to you today. Thank you very much.