[Script Info] Title: [Events] Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text Dialogue: 0,0:00:16.64,0:00:20.42,Default,,0000,0000,0000,,PETE HODGSON: OK. So, thanks for coming. Dialogue: 0,0:00:20.42,0:00:25.80,Default,,0000,0000,0000,,Today I'm talking about Rails as an SOA client. Dialogue: 0,0:00:25.80,0:00:30.02,Default,,0000,0000,0000,,So, in the beginning, there was a Rails application. Dialogue: 0,0:00:30.02,0:00:32.71,Default,,0000,0000,0000,,And in the beginning, most of these Rails\Napplications Dialogue: 0,0:00:32.71,0:00:33.71,Default,,0000,0000,0000,,were pretty straight-forward. Dialogue: 0,0:00:33.71,0:00:36.76,Default,,0000,0000,0000,,Pretty simple things. They were normally Dialogue: 0,0:00:36.76,0:00:39.49,Default,,0000,0000,0000,,just talking to a single database. Dialogue: 0,0:00:39.49,0:00:42.62,Default,,0000,0000,0000,,And this is how most of our Rails applications\Nstart. Dialogue: 0,0:00:42.62,0:00:46.32,Default,,0000,0000,0000,,They're green fields, and we're talking to Dialogue: 0,0:00:46.32,0:00:47.92,Default,,0000,0000,0000,,a single database. Dialogue: 0,0:00:47.92,0:00:51.44,Default,,0000,0000,0000,,Quite often, we, or pretty soon, particularly\Nnow days, Dialogue: 0,0:00:51.44,0:00:54.99,Default,,0000,0000,0000,,we start talking to services. These might\Nbe external Dialogue: 0,0:00:54.99,0:00:59.11,Default,,0000,0000,0000,,services like Twillo or Twitter, or they might\Nbe Dialogue: 0,0:00:59.11,0:01:01.13,Default,,0000,0000,0000,,internal services that we're using as part\Nof doing Dialogue: 0,0:01:01.13,0:01:04.77,Default,,0000,0000,0000,,our job in a, in a more enterprise-y situation. Dialogue: 0,0:01:04.77,0:01:09.51,Default,,0000,0000,0000,,And as time has gone on, we've noticed, or Dialogue: 0,0:01:09.51,0:01:12.04,Default,,0000,0000,0000,,I've noticed, that our Rails applications\Nare depending more Dialogue: 0,0:01:12.04,0:01:14.74,Default,,0000,0000,0000,,and more on services. So, I think there's\Nkind Dialogue: 0,0:01:14.74,0:01:18.03,Default,,0000,0000,0000,,of two big forces in play here. Force number Dialogue: 0,0:01:18.03,0:01:21.84,Default,,0000,0000,0000,,one is, as time has grown and as Rails Dialogue: 0,0:01:21.84,0:01:25.56,Default,,0000,0000,0000,,has matured and our community's matured, our\NRails applications Dialogue: 0,0:01:25.56,0:01:27.38,Default,,0000,0000,0000,,have been kind of growing into these big monoliths, Dialogue: 0,0:01:27.38,0:01:31.31,Default,,0000,0000,0000,,mono Rails, these big, bloated applications,\Nand now there's Dialogue: 0,0:01:31.31,0:01:34.43,Default,,0000,0000,0000,,this kind of movement, quite a widespread\Nmovement, meant Dialogue: 0,0:01:34.43,0:01:37.66,Default,,0000,0000,0000,,to break up our large, monolithic Rails apps\Ninto, Dialogue: 0,0:01:37.66,0:01:40.37,Default,,0000,0000,0000,,into services and, obviously, something needs\Nto talk to Dialogue: 0,0:01:40.37,0:01:42.14,Default,,0000,0000,0000,,those services. And normally that is a Rails\Napp Dialogue: 0,0:01:42.14,0:01:44.06,Default,,0000,0000,0000,,fronting those services. Dialogue: 0,0:01:44.06,0:01:47.91,Default,,0000,0000,0000,,The second big force is, Rails applications,\Nwhich I Dialogue: 0,0:01:47.91,0:01:49.92,Default,,0000,0000,0000,,think started off mainly being used by start\Nups, Dialogue: 0,0:01:49.92,0:01:52.93,Default,,0000,0000,0000,,have moved more and more into enterprise-y\Nplaces where Dialogue: 0,0:01:52.93,0:01:56.97,Default,,0000,0000,0000,,there are a lot, lot, lot of services. And Dialogue: 0,0:01:56.97,0:02:00.36,Default,,0000,0000,0000,,in these enterprise contexts, Rails apps are\Nnormally talking Dialogue: 0,0:02:00.36,0:02:01.53,Default,,0000,0000,0000,,to a lot of services to get their job Dialogue: 0,0:02:01.53,0:02:02.34,Default,,0000,0000,0000,,done. Dialogue: 0,0:02:02.34,0:02:05.59,Default,,0000,0000,0000,,And this is, even goes to the extreme where Dialogue: 0,0:02:05.59,0:02:07.03,Default,,0000,0000,0000,,we have Rails app that don't actually have\Nany Dialogue: 0,0:02:07.03,0:02:09.31,Default,,0000,0000,0000,,local data storage at all, are not doing any Dialogue: 0,0:02:09.31,0:02:12.98,Default,,0000,0000,0000,,kind of persistence. All they're doing is,\Nis interacting Dialogue: 0,0:02:12.98,0:02:15.20,Default,,0000,0000,0000,,with services to do all of their work. Dialogue: 0,0:02:15.20,0:02:19.31,Default,,0000,0000,0000,,So, I, I built an application like this fairly Dialogue: 0,0:02:19.31,0:02:24.81,Default,,0000,0000,0000,,recently, and I'm gonna talk to you guys about Dialogue: 0,0:02:24.81,0:02:27.12,Default,,0000,0000,0000,,what we built, some of the techniques we used Dialogue: 0,0:02:27.12,0:02:29.61,Default,,0000,0000,0000,,to be successful in building these kind of\Nservices Dialogue: 0,0:02:29.61,0:02:34.53,Default,,0000,0000,0000,,only application. Yup. So that's, that's gonna\Nbe the Dialogue: 0,0:02:34.53,0:02:35.80,Default,,0000,0000,0000,,talk today. Dialogue: 0,0:02:35.80,0:02:38.45,Default,,0000,0000,0000,,My name is Pete. I work for this consulting Dialogue: 0,0:02:38.45,0:02:41.84,Default,,0000,0000,0000,,company called ThoughtWorks. So, we work with\Nclients to Dialogue: 0,0:02:41.84,0:02:44.95,Default,,0000,0000,0000,,help them build software and get better at\Nbuilding Dialogue: 0,0:02:44.95,0:02:48.70,Default,,0000,0000,0000,,software. I've been with ThoughtWorks for\Nabout four years. Dialogue: 0,0:02:48.70,0:02:50.07,Default,,0000,0000,0000,,As you can tell from my accent, I'm in Dialogue: 0,0:02:50.07,0:02:53.29,Default,,0000,0000,0000,,the San Francisco office. Dialogue: 0,0:02:53.29,0:02:55.25,Default,,0000,0000,0000,,I really am in the San Francisco office. And Dialogue: 0,0:02:55.25,0:02:57.96,Default,,0000,0000,0000,,I, I, in my time in ThoughtWorks, I've done Dialogue: 0,0:02:57.96,0:02:59.87,Default,,0000,0000,0000,,a lot of different things. I've done a fair Dialogue: 0,0:02:59.87,0:03:01.99,Default,,0000,0000,0000,,amount of Ruby and Rails, but I've also done Dialogue: 0,0:03:01.99,0:03:05.48,Default,,0000,0000,0000,,some Scala, some JavaScript, some, some iOS.\NAnd I've Dialogue: 0,0:03:05.48,0:03:08.04,Default,,0000,0000,0000,,also worked in a lot of different contexts,\Norganizations. Dialogue: 0,0:03:08.04,0:03:10.57,Default,,0000,0000,0000,,So I've worked in really small start ups all Dialogue: 0,0:03:10.57,0:03:13.35,Default,,0000,0000,0000,,the way through to huge, lumbering banks. Dialogue: 0,0:03:13.35,0:03:15.63,Default,,0000,0000,0000,,And, one of the things that I love about Dialogue: 0,0:03:15.63,0:03:17.35,Default,,0000,0000,0000,,ThoughtWorks is I get to move in all these Dialogue: 0,0:03:17.35,0:03:19.15,Default,,0000,0000,0000,,different places. And one of the things that\NI Dialogue: 0,0:03:19.15,0:03:23.32,Default,,0000,0000,0000,,think ThoughtWorks brings to its clients is\Nideas from Dialogue: 0,0:03:23.32,0:03:26.79,Default,,0000,0000,0000,,one place applied in a different place. So,\Nwhat Dialogue: 0,0:03:26.79,0:03:28.49,Default,,0000,0000,0000,,we find ourselves doing a lot is taking ideas Dialogue: 0,0:03:28.49,0:03:30.59,Default,,0000,0000,0000,,from the Rails community and introducing them\Nto the Dialogue: 0,0:03:30.59,0:03:33.71,Default,,0000,0000,0000,,Scala community. Or taking ideas from mobile\Napplications and Dialogue: 0,0:03:33.71,0:03:36.75,Default,,0000,0000,0000,,introducing them to our client-side JavaScript\Napplications. Dialogue: 0,0:03:36.75,0:03:39.51,Default,,0000,0000,0000,,And, indeed, taking ideas from start ups and\Ntaking Dialogue: 0,0:03:39.51,0:03:42.98,Default,,0000,0000,0000,,them to the enterprise. And so, shockingly\Nenough, vice Dialogue: 0,0:03:42.98,0:03:44.60,Default,,0000,0000,0000,,versa. So, that's part of what I'm gonna be Dialogue: 0,0:03:44.60,0:03:47.01,Default,,0000,0000,0000,,talking about today is, there's this subtext\Nof kind Dialogue: 0,0:03:47.01,0:03:48.85,Default,,0000,0000,0000,,of taking ideas from other communities that\Nare successful Dialogue: 0,0:03:48.85,0:03:53.86,Default,,0000,0000,0000,,and bringing them into the Rails community. Dialogue: 0,0:03:53.86,0:03:55.21,Default,,0000,0000,0000,,And so this is gonna be a kind of Dialogue: 0,0:03:55.21,0:03:56.76,Default,,0000,0000,0000,,a talk in two parts. The first part I'm Dialogue: 0,0:03:56.76,0:03:59.21,Default,,0000,0000,0000,,gonna talk about some kind of more hand wave-y, Dialogue: 0,0:03:59.21,0:04:02.86,Default,,0000,0000,0000,,how do we live in this ecosystem environment.\NAnd Dialogue: 0,0:04:02.86,0:04:04.51,Default,,0000,0000,0000,,some tools and techniques that can help with\Nthat, Dialogue: 0,0:04:04.51,0:04:06.96,Default,,0000,0000,0000,,particularly in the context of Rails. And\Nthen I'm Dialogue: 0,0:04:06.96,0:04:09.60,Default,,0000,0000,0000,,gonna dive into some more kind of nitty gritty Dialogue: 0,0:04:09.60,0:04:10.81,Default,,0000,0000,0000,,kind of, how do we actually build these things Dialogue: 0,0:04:10.81,0:04:12.45,Default,,0000,0000,0000,,into our Rails applications? Dialogue: 0,0:04:12.45,0:04:18.24,Default,,0000,0000,0000,,So, first off. Co-dependence versus independence.\NSo, as I Dialogue: 0,0:04:18.24,0:04:20.79,Default,,0000,0000,0000,,said, I worked for a client. We were building Dialogue: 0,0:04:20.79,0:04:23.37,Default,,0000,0000,0000,,a large, we were building, actually, a pretty\Nsmall Dialogue: 0,0:04:23.37,0:04:26.04,Default,,0000,0000,0000,,Rails application in front of a very large\Nset Dialogue: 0,0:04:26.04,0:04:30.05,Default,,0000,0000,0000,,of services. We were building an online store\Nfor, Dialogue: 0,0:04:30.05,0:04:32.58,Default,,0000,0000,0000,,for a large book retailer. They were going\Nto Dialogue: 0,0:04:32.58,0:04:34.10,Default,,0000,0000,0000,,a new market, and they didn't want to have Dialogue: 0,0:04:34.10,0:04:37.70,Default,,0000,0000,0000,,to keep working in Java. So they were taking Dialogue: 0,0:04:37.70,0:04:40.60,Default,,0000,0000,0000,,this as an opportunity to build a green-filled\NRails Dialogue: 0,0:04:40.60,0:04:43.72,Default,,0000,0000,0000,,app for a new market, which was still gonna Dialogue: 0,0:04:43.72,0:04:46.13,Default,,0000,0000,0000,,be using all of their existing services, which\Nwere Dialogue: 0,0:04:46.13,0:04:50.80,Default,,0000,0000,0000,,implemented in a variety of languages. Dialogue: 0,0:04:50.80,0:04:52.32,Default,,0000,0000,0000,,So this is what the home page of this Dialogue: 0,0:04:52.32,0:04:54.78,Default,,0000,0000,0000,,application kind of looked like. There was\Nthis kind Dialogue: 0,0:04:54.78,0:04:57.72,Default,,0000,0000,0000,,of list of all the products and prices and Dialogue: 0,0:04:57.72,0:04:59.55,Default,,0000,0000,0000,,descriptions and all that kind of stuff. And\Nthen Dialogue: 0,0:04:59.55,0:05:01.09,Default,,0000,0000,0000,,across the top we had these kind of deals Dialogue: 0,0:05:01.09,0:05:03.58,Default,,0000,0000,0000,,of the day. Dialogue: 0,0:05:03.58,0:05:06.78,Default,,0000,0000,0000,,And the way that this worked was, was interesting Dialogue: 0,0:05:06.78,0:05:09.41,Default,,0000,0000,0000,,or, I, I suppose is, is interesting if you Dialogue: 0,0:05:09.41,0:05:11.48,Default,,0000,0000,0000,,haven't worked in like a large enterprise\Nlike this. Dialogue: 0,0:05:11.48,0:05:14.57,Default,,0000,0000,0000,,But the information to power this page was\Ncoming Dialogue: 0,0:05:14.57,0:05:17.23,Default,,0000,0000,0000,,from a lot of different places. And our Rails Dialogue: 0,0:05:17.23,0:05:19.45,Default,,0000,0000,0000,,app was really just responsible for stitching\Nthat information Dialogue: 0,0:05:19.45,0:05:21.91,Default,,0000,0000,0000,,together. So, we had the product service that\Nwas Dialogue: 0,0:05:21.91,0:05:24.33,Default,,0000,0000,0000,,kind of serving up product catalog data, and\Nthen Dialogue: 0,0:05:24.33,0:05:26.80,Default,,0000,0000,0000,,we had the deals service that was kind of Dialogue: 0,0:05:26.80,0:05:28.05,Default,,0000,0000,0000,,telling us what the deals of the day were. Dialogue: 0,0:05:28.05,0:05:29.35,Default,,0000,0000,0000,,And, as I said, the Rails app was just Dialogue: 0,0:05:29.35,0:05:30.88,Default,,0000,0000,0000,,kind of there to kind of, go over here Dialogue: 0,0:05:30.88,0:05:32.53,Default,,0000,0000,0000,,and get some information. Go over here and\Nget Dialogue: 0,0:05:32.53,0:05:33.82,Default,,0000,0000,0000,,some information, and then kind of plug it\Nall Dialogue: 0,0:05:33.82,0:05:38.17,Default,,0000,0000,0000,,together. So when you're building an app like\Nthis, Dialogue: 0,0:05:38.17,0:05:42.84,Default,,0000,0000,0000,,you get this interesting phenomenon, where\Nthis app, on Dialogue: 0,0:05:42.84,0:05:45.49,Default,,0000,0000,0000,,its own, really can't do much at all. In Dialogue: 0,0:05:45.49,0:05:47.62,Default,,0000,0000,0000,,fact, it can't do anything. We, there wasn't,\Nthere Dialogue: 0,0:05:47.62,0:05:51.00,Default,,0000,0000,0000,,was probably not a single page of this app Dialogue: 0,0:05:51.00,0:05:53.84,Default,,0000,0000,0000,,that would render if those services weren't\Nthere. Dialogue: 0,0:05:53.84,0:05:57.41,Default,,0000,0000,0000,,So, what, this is what I mean by co-dependence. Dialogue: 0,0:05:57.41,0:06:01.31,Default,,0000,0000,0000,,This application was incredibly co-dependent\Non the ecosystem of Dialogue: 0,0:06:01.31,0:06:05.32,Default,,0000,0000,0000,,services that it lived inside of. But ideally\Nwe Dialogue: 0,0:06:05.32,0:06:07.87,Default,,0000,0000,0000,,don't want to be co-dependent, because we\Nwant to Dialogue: 0,0:06:07.87,0:06:09.59,Default,,0000,0000,0000,,be able to run this thing in isolation, to Dialogue: 0,0:06:09.59,0:06:13.18,Default,,0000,0000,0000,,test it in isolation, to debug it in isolation. Dialogue: 0,0:06:13.18,0:06:15.78,Default,,0000,0000,0000,,So, we don't want to have to stand up Dialogue: 0,0:06:15.78,0:06:19.64,Default,,0000,0000,0000,,the entire enterprise on our laptops just\Nin order Dialogue: 0,0:06:19.64,0:06:20.84,Default,,0000,0000,0000,,to, to run this thing when we're, when we're Dialogue: 0,0:06:20.84,0:06:23.70,Default,,0000,0000,0000,,on a train or in a plane. So, we Dialogue: 0,0:06:23.70,0:06:26.66,Default,,0000,0000,0000,,want independence, but we're in a situation\Nof co-dependence. Dialogue: 0,0:06:26.66,0:06:30.23,Default,,0000,0000,0000,,And this gets even more interesting when you\Nstart Dialogue: 0,0:06:30.23,0:06:32.90,Default,,0000,0000,0000,,thinking about it in terms of teams. So, in Dialogue: 0,0:06:32.90,0:06:35.84,Default,,0000,0000,0000,,our case, we had our team, let's call us Dialogue: 0,0:06:35.84,0:06:39.84,Default,,0000,0000,0000,,the red team. We're building the Rails application.\NBut Dialogue: 0,0:06:39.84,0:06:42.58,Default,,0000,0000,0000,,we weren't building any of these services.\NThe deals Dialogue: 0,0:06:42.58,0:06:44.95,Default,,0000,0000,0000,,services might have been maintained by the\Ngreen team Dialogue: 0,0:06:44.95,0:06:47.16,Default,,0000,0000,0000,,and the blue team, of course, were working\Non Dialogue: 0,0:06:47.16,0:06:48.83,Default,,0000,0000,0000,,the product service. Dialogue: 0,0:06:48.83,0:06:53.08,Default,,0000,0000,0000,,And these teams were teams we sometimes, we\Ndidn't Dialogue: 0,0:06:53.08,0:06:54.90,Default,,0000,0000,0000,,even know where they, where they were. We\Nhad Dialogue: 0,0:06:54.90,0:06:56.52,Default,,0000,0000,0000,,vague ways of getting in contact with them,\Nbut Dialogue: 0,0:06:56.52,0:06:58.96,Default,,0000,0000,0000,,we, we didn't have a very good relationship\Nwith Dialogue: 0,0:06:58.96,0:07:03.66,Default,,0000,0000,0000,,them. And this leads to lots of interesting\Nside-effects. Dialogue: 0,0:07:03.66,0:07:06.07,Default,,0000,0000,0000,,So one thing that you might note here is Dialogue: 0,0:07:06.07,0:07:08.64,Default,,0000,0000,0000,,the shape of the teams. Lines up pretty closely Dialogue: 0,0:07:08.64,0:07:10.93,Default,,0000,0000,0000,,with the shape of the services. So this gets Dialogue: 0,0:07:10.93,0:07:15.26,Default,,0000,0000,0000,,to this thing called Conway's Law. Don't tell\NDHH Dialogue: 0,0:07:15.26,0:07:19.70,Default,,0000,0000,0000,,that I'm talking about laws. Dialogue: 0,0:07:19.70,0:07:22.26,Default,,0000,0000,0000,,Conway's Law, coined in the 60s, says that\Nthe Dialogue: 0,0:07:22.26,0:07:25.46,Default,,0000,0000,0000,,communication patterns of a software system\Ntend to mirror Dialogue: 0,0:07:25.46,0:07:28.04,Default,,0000,0000,0000,,the communication patterns of the people who\Nbuild that Dialogue: 0,0:07:28.04,0:07:31.72,Default,,0000,0000,0000,,system. How many people have heard of Conway's\NLaw, Dialogue: 0,0:07:31.72,0:07:34.14,Default,,0000,0000,0000,,by the way? Dialogue: 0,0:07:34.14,0:07:38.18,Default,,0000,0000,0000,,So, I'm trying to avoid calling it a law Dialogue: 0,0:07:38.18,0:07:40.25,Default,,0000,0000,0000,,but I'm not going to be able to do Dialogue: 0,0:07:40.25,0:07:42.63,Default,,0000,0000,0000,,that. I think Conway's Law is the most important Dialogue: 0,0:07:42.63,0:07:46.71,Default,,0000,0000,0000,,law for us to understand as software engineers.\NOh, Dialogue: 0,0:07:46.71,0:07:53.71,Default,,0000,0000,0000,,I said. As people. As software writers. Sorry. Dialogue: 0,0:07:55.91,0:07:58.56,Default,,0000,0000,0000,,Conway's Law says that how people work together\Neffects Dialogue: 0,0:07:58.56,0:08:04.27,Default,,0000,0000,0000,,system architecture. And, and the flip-side.\NSystem architecture effects Dialogue: 0,0:08:04.27,0:08:09.32,Default,,0000,0000,0000,,how people work together. And, this isn't\Nkind of Dialogue: 0,0:08:09.32,0:08:13.87,Default,,0000,0000,0000,,a, a possible outcome. This is reality. This\Nis Dialogue: 0,0:08:13.87,0:08:18.14,Default,,0000,0000,0000,,empirically shown for fifty years, sixty years\Nalmost. This Dialogue: 0,0:08:18.14,0:08:19.77,Default,,0000,0000,0000,,does happen. This is true. Dialogue: 0,0:08:19.77,0:08:21.89,Default,,0000,0000,0000,,So you can't, like, decide you don't want\Nit Dialogue: 0,0:08:21.89,0:08:23.45,Default,,0000,0000,0000,,to happen. But what you can do is you Dialogue: 0,0:08:23.45,0:08:26.64,Default,,0000,0000,0000,,can either wield Conway's Law to your advantage,\Ngo Dialogue: 0,0:08:26.64,0:08:29.28,Default,,0000,0000,0000,,with the grain and, and use it to your Dialogue: 0,0:08:29.28,0:08:30.56,Default,,0000,0000,0000,,advantage, or you can kind of yield to Conway's Dialogue: 0,0:08:30.56,0:08:32.12,Default,,0000,0000,0000,,Law and have it beat you up. Dialogue: 0,0:08:32.12,0:08:34.19,Default,,0000,0000,0000,,So I'm gonna talk a little bit today about Dialogue: 0,0:08:34.19,0:08:37.06,Default,,0000,0000,0000,,how we wielded Conway's Law to our advantage\Nrather Dialogue: 0,0:08:37.06,0:08:40.33,Default,,0000,0000,0000,,than have it beat us up. Dialogue: 0,0:08:40.33,0:08:45.01,Default,,0000,0000,0000,,So, here's our three teams. One of the most Dialogue: 0,0:08:45.01,0:08:48.77,Default,,0000,0000,0000,,fun aspects of, of working in a system that Dialogue: 0,0:08:48.77,0:08:50.00,Default,,0000,0000,0000,,has more than one team is, is when you Dialogue: 0,0:08:50.00,0:08:53.78,Default,,0000,0000,0000,,find a bug. So let's say we've got our Dialogue: 0,0:08:53.78,0:08:55.93,Default,,0000,0000,0000,,deal, deals of the day section, and we've\Nnoticed Dialogue: 0,0:08:55.93,0:08:59.33,Default,,0000,0000,0000,,that the prices are missing in some of the Dialogue: 0,0:08:59.33,0:09:01.87,Default,,0000,0000,0000,,deals section when we run the application.\NSo now Dialogue: 0,0:09:01.87,0:09:04.25,Default,,0000,0000,0000,,we start to play this game, it's called Who's Dialogue: 0,0:09:04.25,0:09:06.33,Default,,0000,0000,0000,,Bug is it Anyway? Dialogue: 0,0:09:06.33,0:09:09.83,Default,,0000,0000,0000,,Hands up if you've played this game. Awesome.\NOK. Dialogue: 0,0:09:09.83,0:09:12.08,Default,,0000,0000,0000,,I wasn't sure if that was a cultural reference Dialogue: 0,0:09:12.08,0:09:17.20,Default,,0000,0000,0000,,that people wouldn't get. So, we know that\Nthe Dialogue: 0,0:09:17.20,0:09:19.56,Default,,0000,0000,0000,,deals aren't loading correctly, but is that\Nthe deal Dialogue: 0,0:09:19.56,0:09:22.75,Default,,0000,0000,0000,,service's fault? Maybe the product service\Nisn't returning the Dialogue: 0,0:09:22.75,0:09:25.69,Default,,0000,0000,0000,,right data for those deals. Maybe we're asking\Nit Dialogue: 0,0:09:25.69,0:09:27.56,Default,,0000,0000,0000,,the wrong questions. Or maybe we just have\Na Dialogue: 0,0:09:27.56,0:09:32.14,Default,,0000,0000,0000,,bug in our rendering code. Dialogue: 0,0:09:32.14,0:09:34.76,Default,,0000,0000,0000,,The fundamental issue of all of these things\Nis Dialogue: 0,0:09:34.76,0:09:40.56,Default,,0000,0000,0000,,this tension between co-dependence and independence.\NWe are co-dependent. Dialogue: 0,0:09:40.56,0:09:44.65,Default,,0000,0000,0000,,We want to be independent. Some people solve\Na Dialogue: 0,0:09:44.65,0:09:48.64,Default,,0000,0000,0000,,lot of these problems by embracing co-dependence.\NSo, if Dialogue: 0,0:09:48.64,0:09:50.14,Default,,0000,0000,0000,,our Rails app needs the services to be up Dialogue: 0,0:09:50.14,0:09:52.01,Default,,0000,0000,0000,,and running in order to run, we'll stand up Dialogue: 0,0:09:52.01,0:09:54.83,Default,,0000,0000,0000,,the services. You can do that. You can stand Dialogue: 0,0:09:54.83,0:09:57.21,Default,,0000,0000,0000,,up copies of the services locally on your\Nlaptop. Dialogue: 0,0:09:57.21,0:09:59.94,Default,,0000,0000,0000,,This is more and more easy to do nowadays Dialogue: 0,0:09:59.94,0:10:01.86,Default,,0000,0000,0000,,cause we've got kind of trendy dev-ops things\Nlike Dialogue: 0,0:10:01.86,0:10:04.75,Default,,0000,0000,0000,,Vagrant and Chef and Puppet. Dialogue: 0,0:10:04.75,0:10:06.72,Default,,0000,0000,0000,,That will only get you so far. Try standing Dialogue: 0,0:10:06.72,0:10:10.39,Default,,0000,0000,0000,,up a bank on your laptop. It's not happening. Dialogue: 0,0:10:10.39,0:10:12.95,Default,,0000,0000,0000,,Very, very common approach here is to, to\Nuse Dialogue: 0,0:10:12.95,0:10:15.95,Default,,0000,0000,0000,,kind of shared services. So a shared dev environment. Dialogue: 0,0:10:15.95,0:10:20.19,Default,,0000,0000,0000,,A shared kind of staging environment. That\Nkind of Dialogue: 0,0:10:20.19,0:10:22.28,Default,,0000,0000,0000,,thing. And that, that works quite well. But,\Nfor Dialogue: 0,0:10:22.28,0:10:25.39,Default,,0000,0000,0000,,our team, we decided to go the alternate route. Dialogue: 0,0:10:25.39,0:10:28.93,Default,,0000,0000,0000,,We wanted to, as much as possible, push for Dialogue: 0,0:10:28.93,0:10:33.90,Default,,0000,0000,0000,,independence. And, the main way we did that\Nwas Dialogue: 0,0:10:33.90,0:10:38.70,Default,,0000,0000,0000,,by rem- replacing our dependency on services\Nwith fake Dialogue: 0,0:10:38.70,0:10:39.76,Default,,0000,0000,0000,,services. Dialogue: 0,0:10:39.76,0:10:44.70,Default,,0000,0000,0000,,So, when we wanted to test our application,\Nwe Dialogue: 0,0:10:44.70,0:10:47.03,Default,,0000,0000,0000,,wanted to test just our application in independence.\NAnd Dialogue: 0,0:10:47.03,0:10:49.20,Default,,0000,0000,0000,,the way that we did that was, for each Dialogue: 0,0:10:49.20,0:10:51.62,Default,,0000,0000,0000,,of our dependent services, we replaced those\Nservices with Dialogue: 0,0:10:51.62,0:10:55.75,Default,,0000,0000,0000,,kind of a fake version of that service. And Dialogue: 0,0:10:55.75,0:10:57.70,Default,,0000,0000,0000,,by doing that, we were allowed to run these Dialogue: 0,0:10:57.70,0:11:01.81,Default,,0000,0000,0000,,things that, that we called bounded integration\Ntests. Dialogue: 0,0:11:01.81,0:11:05.75,Default,,0000,0000,0000,,So, these were tests that tested the entire\Nstack Dialogue: 0,0:11:05.75,0:11:08.99,Default,,0000,0000,0000,,of our application, of our Rails application,\Nfrom top Dialogue: 0,0:11:08.99,0:11:11.14,Default,,0000,0000,0000,,to bottom, from kind of html all the way Dialogue: 0,0:11:11.14,0:11:16.42,Default,,0000,0000,0000,,down to the network. But, we weren't, we were Dialogue: 0,0:11:16.42,0:11:19.93,Default,,0000,0000,0000,,testing that in isolation. We weren't actually\Nhitting those Dialogue: 0,0:11:19.93,0:11:23.96,Default,,0000,0000,0000,,shared services. Dialogue: 0,0:11:23.96,0:11:26.31,Default,,0000,0000,0000,,And what's really interesting here is, do\Nyou see Dialogue: 0,0:11:26.31,0:11:29.28,Default,,0000,0000,0000,,the, the boundary of those tests lines up\Nalmost Dialogue: 0,0:11:29.28,0:11:31.85,Default,,0000,0000,0000,,perfectly with the boundary of our team. So\Nthis Dialogue: 0,0:11:31.85,0:11:33.96,Default,,0000,0000,0000,,is a really good example of using Conway's\NLaw Dialogue: 0,0:11:33.96,0:11:37.88,Default,,0000,0000,0000,,to your advantage. Embracing Conway's Law\Nand shaping your Dialogue: 0,0:11:37.88,0:11:41.55,Default,,0000,0000,0000,,approach, shaping your software, with the\Nshape of your Dialogue: 0,0:11:41.55,0:11:43.61,Default,,0000,0000,0000,,team. And this was something that helped us\Nwin. Dialogue: 0,0:11:43.61,0:11:46.57,Default,,0000,0000,0000,,So, if you want to build these fake services, Dialogue: 0,0:11:46.57,0:11:49.28,Default,,0000,0000,0000,,what are your options? Comes down to, to two Dialogue: 0,0:11:49.28,0:11:52.31,Default,,0000,0000,0000,,different kind of techniques, really. In-process\Nand out-of-process. So Dialogue: 0,0:11:52.31,0:11:55.20,Default,,0000,0000,0000,,in-process means you're kind of messing around\Nwith the Dialogue: 0,0:11:55.20,0:11:57.87,Default,,0000,0000,0000,,actual Rails, running Rails process, and like\Nreplacing the Dialogue: 0,0:11:57.87,0:12:00.69,Default,,0000,0000,0000,,network stack with a fake network stack maybe. Dialogue: 0,0:12:00.69,0:12:02.93,Default,,0000,0000,0000,,Out of process means you're standing up a\Nreal Dialogue: 0,0:12:02.93,0:12:05.38,Default,,0000,0000,0000,,http server. It's an actual, you know, you\Ncan Dialogue: 0,0:12:05.38,0:12:08.52,Default,,0000,0000,0000,,actually talk to it over http. And your application, Dialogue: 0,0:12:08.52,0:12:11.41,Default,,0000,0000,0000,,your Rails app, rather than pointing to a\Nreal Dialogue: 0,0:12:11.41,0:12:13.21,Default,,0000,0000,0000,,deal service, it's going to point to this\Nfake Dialogue: 0,0:12:13.21,0:12:14.83,Default,,0000,0000,0000,,deal service. It's gonna look and smell like\Na Dialogue: 0,0:12:14.83,0:12:16.91,Default,,0000,0000,0000,,deal service. You send it a request. It gives Dialogue: 0,0:12:16.91,0:12:19.12,Default,,0000,0000,0000,,you a response. It's not a real deals service. Dialogue: 0,0:12:19.12,0:12:21.83,Default,,0000,0000,0000,,It's a fake service that we have control over. Dialogue: 0,0:12:21.83,0:12:24.10,Default,,0000,0000,0000,,So, you can imagine if we wanted to test Dialogue: 0,0:12:24.10,0:12:26.81,Default,,0000,0000,0000,,unicode rendering, we could stand up a fake\Nproduct Dialogue: 0,0:12:26.81,0:12:30.09,Default,,0000,0000,0000,,service that returned a product tied tool\Nthat was Dialogue: 0,0:12:30.09,0:12:32.21,Default,,0000,0000,0000,,all kind of snow man and that kind of Dialogue: 0,0:12:32.21,0:12:35.35,Default,,0000,0000,0000,,stuff. And, and that allows us to test how Dialogue: 0,0:12:35.35,0:12:38.49,Default,,0000,0000,0000,,we handle unicode titles without having, then,\Nto need Dialogue: 0,0:12:38.49,0:12:39.46,Default,,0000,0000,0000,,a unicode title. Dialogue: 0,0:12:39.46,0:12:43.13,Default,,0000,0000,0000,,So, in process, a couple of popular options,\Nvcr Dialogue: 0,0:12:43.13,0:12:45.04,Default,,0000,0000,0000,,and webmock. We actually used vcr quite heavily\Non Dialogue: 0,0:12:45.04,0:12:47.50,Default,,0000,0000,0000,,this project that I'm talking about. So basically\Nit Dialogue: 0,0:12:47.50,0:12:49.98,Default,,0000,0000,0000,,just kind of sits, it kind of injects itself Dialogue: 0,0:12:49.98,0:12:53.28,Default,,0000,0000,0000,,in between your application and the network\Nlayer and Dialogue: 0,0:12:53.28,0:12:55.78,Default,,0000,0000,0000,,records all the interactions between your\Napplication and the Dialogue: 0,0:12:55.78,0:12:57.65,Default,,0000,0000,0000,,network, and then you can kind of flip it Dialogue: 0,0:12:57.65,0:12:59.76,Default,,0000,0000,0000,,into playback mode, and rather than, next\Nyou time Dialogue: 0,0:12:59.76,0:13:01.69,Default,,0000,0000,0000,,you go and make a, make a network call, Dialogue: 0,0:13:01.69,0:13:03.32,Default,,0000,0000,0000,,it's not actually gonna call the network.\NIt's going Dialogue: 0,0:13:03.32,0:13:07.90,Default,,0000,0000,0000,,to just play back the previously recorded\Ninteraction. So Dialogue: 0,0:13:07.90,0:13:12.65,Default,,0000,0000,0000,,that worked out well for us with some caveats. Dialogue: 0,0:13:12.65,0:13:14.35,Default,,0000,0000,0000,,Out of process, you've got a lot more options, Dialogue: 0,0:13:14.35,0:13:16.44,Default,,0000,0000,0000,,because you're not running out of process.\NYou don't Dialogue: 0,0:13:16.44,0:13:19.12,Default,,0000,0000,0000,,have to use Ruby. You can use whatever tool Dialogue: 0,0:13:19.12,0:13:21.44,Default,,0000,0000,0000,,makes the most sense. So mimic is a really Dialogue: 0,0:13:21.44,0:13:23.53,Default,,0000,0000,0000,,good option here. This is actually a Ruby\Ngem Dialogue: 0,0:13:23.53,0:13:27.88,Default,,0000,0000,0000,,written by Luke Redpath. It's a Sinatra application\Nthat Dialogue: 0,0:13:27.88,0:13:30.95,Default,,0000,0000,0000,,pretends to be whatever you want it to be. Dialogue: 0,0:13:30.95,0:13:32.90,Default,,0000,0000,0000,,Outside of the Ruby community, or outside\Nof the Dialogue: 0,0:13:32.90,0:13:37.06,Default,,0000,0000,0000,,Ruby language, I suppose, there's a library\Ncalled moco. Dialogue: 0,0:13:37.06,0:13:41.41,Default,,0000,0000,0000,,It's quite powerful. Stubby is another one.\NAnd then Dialogue: 0,0:13:41.41,0:13:44.95,Default,,0000,0000,0000,,there's this interesting one called montebank.\NWhat makes montebank Dialogue: 0,0:13:44.95,0:13:47.64,Default,,0000,0000,0000,,interesting is it doesn't just fake out http,\Nit Dialogue: 0,0:13:47.64,0:13:49.92,Default,,0000,0000,0000,,will fake out whatever protocol you want.\NSo it Dialogue: 0,0:13:49.92,0:13:51.53,Default,,0000,0000,0000,,can fake out smtp to it, so you can Dialogue: 0,0:13:51.53,0:13:54.09,Default,,0000,0000,0000,,check emails. It'll fake out web sockets.\NThat kind Dialogue: 0,0:13:54.09,0:13:57.22,Default,,0000,0000,0000,,of stuff. So that's an interesting one to\Nlook Dialogue: 0,0:13:57.22,0:13:59.02,Default,,0000,0000,0000,,at. Dialogue: 0,0:13:59.02,0:14:01.57,Default,,0000,0000,0000,,So now we've got these bounded integration\Ntests. And Dialogue: 0,0:14:01.57,0:14:04.92,Default,,0000,0000,0000,,that means we have some confidence that it\Nwasn't Dialogue: 0,0:14:04.92,0:14:08.34,Default,,0000,0000,0000,,us that, that's creating this bug. Because\Nour bounded Dialogue: 0,0:14:08.34,0:14:10.66,Default,,0000,0000,0000,,integration tests are passing. So all was\Nhappy and Dialogue: 0,0:14:10.66,0:14:13.02,Default,,0000,0000,0000,,we can go on with our day. Dialogue: 0,0:14:13.02,0:14:15.74,Default,,0000,0000,0000,,Well, obviously not, because we actually still\Ndon't know Dialogue: 0,0:14:15.74,0:14:18.25,Default,,0000,0000,0000,,where the bug is. And the goal here is Dialogue: 0,0:14:18.25,0:14:20.60,Default,,0000,0000,0000,,not for us to kind of, prove that we, Dialogue: 0,0:14:20.60,0:14:22.97,Default,,0000,0000,0000,,it's not our fault. The goal is to identify Dialogue: 0,0:14:22.97,0:14:24.84,Default,,0000,0000,0000,,the problem and fix it, because at the end Dialogue: 0,0:14:24.84,0:14:26.66,Default,,0000,0000,0000,,of the day it's a system. We're a part Dialogue: 0,0:14:26.66,0:14:28.22,Default,,0000,0000,0000,,of that system and we need to fix the Dialogue: 0,0:14:28.22,0:14:31.28,Default,,0000,0000,0000,,system and move on. Dialogue: 0,0:14:31.28,0:14:33.42,Default,,0000,0000,0000,,So, so we're left saying, OK. We know it's Dialogue: 0,0:14:33.42,0:14:35.73,Default,,0000,0000,0000,,not our fault. We'd like to help our, our Dialogue: 0,0:14:35.73,0:14:40.72,Default,,0000,0000,0000,,comrades on other teams figure out where the\Nproblem Dialogue: 0,0:14:40.72,0:14:43.41,Default,,0000,0000,0000,,is. And for that we used a technique called Dialogue: 0,0:14:43.41,0:14:49.18,Default,,0000,0000,0000,,contract tests. So, contract tests, also sometimes\Nreferred to Dialogue: 0,0:14:49.18,0:14:55.23,Default,,0000,0000,0000,,as consumer-driven contracts. The idea with\Nthese is we Dialogue: 0,0:14:55.23,0:15:00.30,Default,,0000,0000,0000,,write test code that expresses what we expect\Na Dialogue: 0,0:15:00.30,0:15:03.12,Default,,0000,0000,0000,,dependency, an external service to do, and\Nthen we Dialogue: 0,0:15:03.12,0:15:05.05,Default,,0000,0000,0000,,run those tests against a real version of\Nthat Dialogue: 0,0:15:05.05,0:15:07.29,Default,,0000,0000,0000,,service, and we find out if that service actually Dialogue: 0,0:15:07.29,0:15:10.98,Default,,0000,0000,0000,,does what we expect. Quite simple. Dialogue: 0,0:15:10.98,0:15:13.34,Default,,0000,0000,0000,,What's weird is we're testing someone else's\Ncode. We're Dialogue: 0,0:15:13.34,0:15:16.54,Default,,0000,0000,0000,,not testing our code. We're, we're writing\Ntests, but Dialogue: 0,0:15:16.54,0:15:21.58,Default,,0000,0000,0000,,we're testing another team's services. So\Nhere's, again, our Dialogue: 0,0:15:21.58,0:15:27.10,Default,,0000,0000,0000,,boundary, our bounded integration tests. And,\Nso we verified Dialogue: 0,0:15:27.10,0:15:29.38,Default,,0000,0000,0000,,that the way that the Rails app is, that Dialogue: 0,0:15:29.38,0:15:30.92,Default,,0000,0000,0000,,the Rails app does the right thing when it Dialogue: 0,0:15:30.92,0:15:34.48,Default,,0000,0000,0000,,talks to what we think these services are\Ndoing. Dialogue: 0,0:15:34.48,0:15:37.11,Default,,0000,0000,0000,,Contract tests, once we add these, actually\Nverify that Dialogue: 0,0:15:37.11,0:15:39.02,Default,,0000,0000,0000,,what the service does is what we think it's Dialogue: 0,0:15:39.02,0:15:39.75,Default,,0000,0000,0000,,gonna do. Dialogue: 0,0:15:39.75,0:15:42.42,Default,,0000,0000,0000,,Cause it could be that there's a bug in Dialogue: 0,0:15:42.42,0:15:44.73,Default,,0000,0000,0000,,the service, and these tests will find those\Nbugs, Dialogue: 0,0:15:44.73,0:15:46.28,Default,,0000,0000,0000,,hopefully, because we'll ask it to do something\Nand Dialogue: 0,0:15:46.28,0:15:48.46,Default,,0000,0000,0000,,it won't do what we expect. There could be Dialogue: 0,0:15:48.46,0:15:51.29,Default,,0000,0000,0000,,a bug in our understanding of the service,\Nand Dialogue: 0,0:15:51.29,0:15:52.84,Default,,0000,0000,0000,,that's why these are called contract tests,\Nbecause they Dialogue: 0,0:15:52.84,0:15:55.22,Default,,0000,0000,0000,,define a contract between our team and the\Nother Dialogue: 0,0:15:55.22,0:15:59.66,Default,,0000,0000,0000,,team. Again, Conway's Law is coming in here. Dialogue: 0,0:15:59.66,0:16:02.31,Default,,0000,0000,0000,,How many of you have worked with an external Dialogue: 0,0:16:02.31,0:16:05.36,Default,,0000,0000,0000,,service where the, the Wiki page that documented\Nthe Dialogue: 0,0:16:05.36,0:16:08.73,Default,,0000,0000,0000,,API was out of date? How many of you Dialogue: 0,0:16:08.73,0:16:10.79,Default,,0000,0000,0000,,have ever worked on a service where it wasn't Dialogue: 0,0:16:10.79,0:16:16.89,Default,,0000,0000,0000,,wrong? It's always wrong. And that's OK. Documentation\Ntends Dialogue: 0,0:16:16.89,0:16:19.06,Default,,0000,0000,0000,,to be stale. API documentation I think is\Nnever Dialogue: 0,0:16:19.06,0:16:22.96,Default,,0000,0000,0000,,not stale. It just is born that way. Dialogue: 0,0:16:22.96,0:16:25.31,Default,,0000,0000,0000,,These contract tests are a way to, to, to Dialogue: 0,0:16:25.31,0:16:28.95,Default,,0000,0000,0000,,mitigate that. Because you're expressing your\Nexpectations in code Dialogue: 0,0:16:28.95,0:16:32.52,Default,,0000,0000,0000,,rather than in words. Dialogue: 0,0:16:32.52,0:16:35.86,Default,,0000,0000,0000,,So we, on, on my, on my team, we Dialogue: 0,0:16:35.86,0:16:38.11,Default,,0000,0000,0000,,wrote contract tests for every single one\Nof our Dialogue: 0,0:16:38.11,0:16:41.23,Default,,0000,0000,0000,,dependencies. This was the most productive\Nthing we did Dialogue: 0,0:16:41.23,0:16:44.19,Default,,0000,0000,0000,,on this team is, in terms of improving efficiency Dialogue: 0,0:16:44.19,0:16:49.46,Default,,0000,0000,0000,,of, of us creating software. It really, really\Nhelped Dialogue: 0,0:16:49.46,0:16:51.49,Default,,0000,0000,0000,,us nail down, whenever there was an issue,\Nwhere Dialogue: 0,0:16:51.49,0:16:53.61,Default,,0000,0000,0000,,that issue was. And it really helped us communicate Dialogue: 0,0:16:53.61,0:16:56.18,Default,,0000,0000,0000,,with, with our friends on other teams. Dialogue: 0,0:16:56.18,0:16:58.56,Default,,0000,0000,0000,,So, if you want to do these, you've got Dialogue: 0,0:16:58.56,0:17:00.50,Default,,0000,0000,0000,,a few different options for contract tests.\NWe actually Dialogue: 0,0:17:00.50,0:17:03.91,Default,,0000,0000,0000,,just did plain old RSpec. We just used standard Dialogue: 0,0:17:03.91,0:17:07.10,Default,,0000,0000,0000,,RSpec test runner to make network calls to\Nour Dialogue: 0,0:17:07.10,0:17:09.00,Default,,0000,0000,0000,,dependencies and then look at the results\Nand make Dialogue: 0,0:17:09.00,0:17:11.30,Default,,0000,0000,0000,,sure that things looked the way that we expected Dialogue: 0,0:17:11.30,0:17:12.48,Default,,0000,0000,0000,,them to look. Dialogue: 0,0:17:12.48,0:17:15.41,Default,,0000,0000,0000,,There's two more kind of sophisticated options\Nout there. Dialogue: 0,0:17:15.41,0:17:17.54,Default,,0000,0000,0000,,There's a gem called pacto and another gem\Ncalled Dialogue: 0,0:17:17.54,0:17:20.54,Default,,0000,0000,0000,,pact. And these are kind of like real power Dialogue: 0,0:17:20.54,0:17:24.59,Default,,0000,0000,0000,,tools. They're quite sophisticated. They're,\Nthey're very fully-featured. If Dialogue: 0,0:17:24.59,0:17:26.34,Default,,0000,0000,0000,,you want to really kind of get into this, Dialogue: 0,0:17:26.34,0:17:28.91,Default,,0000,0000,0000,,into this mind set. Dialogue: 0,0:17:28.91,0:17:31.40,Default,,0000,0000,0000,,So once we had these bounded integration tests\Nand Dialogue: 0,0:17:31.40,0:17:34.41,Default,,0000,0000,0000,,these contract tests, we were left with this\Nkind Dialogue: 0,0:17:34.41,0:17:38.73,Default,,0000,0000,0000,,of CI dashboard that looked something like\Nthis. So Dialogue: 0,0:17:38.73,0:17:40.54,Default,,0000,0000,0000,,whenever we checked in code, we'd run our\Nunit Dialogue: 0,0:17:40.54,0:17:42.97,Default,,0000,0000,0000,,tests, we'd run our functional tests. And\Nassuming those Dialogue: 0,0:17:42.97,0:17:45.14,Default,,0000,0000,0000,,passed, we'd run our kind of bounded integration\Ntests Dialogue: 0,0:17:45.14,0:17:46.33,Default,,0000,0000,0000,,up there at the top right. Dialogue: 0,0:17:46.33,0:17:50.90,Default,,0000,0000,0000,,Assuming those passed, we'd then run our end-to-end\Ntests. Dialogue: 0,0:17:50.90,0:17:54.04,Default,,0000,0000,0000,,So these were running, testing as much of\Nthe Dialogue: 0,0:17:54.04,0:17:56.93,Default,,0000,0000,0000,,stack as we could possibly stand up. So, our Dialogue: 0,0:17:56.93,0:18:00.39,Default,,0000,0000,0000,,code, our team's code, maybe our team's dependency's\Ncode. Dialogue: 0,0:18:00.39,0:18:02.52,Default,,0000,0000,0000,,So as much of the stack as possible. So Dialogue: 0,0:18:02.52,0:18:04.69,Default,,0000,0000,0000,,really verifying, from a user's point of view,\Nthat Dialogue: 0,0:18:04.69,0:18:08.51,Default,,0000,0000,0000,,this, this system worked as we expected. Dialogue: 0,0:18:08.51,0:18:11.39,Default,,0000,0000,0000,,In theory, this was the picture. In reality\Nit Dialogue: 0,0:18:11.39,0:18:15.24,Default,,0000,0000,0000,,was almost never green. That was OK. So, this Dialogue: 0,0:18:15.24,0:18:16.85,Default,,0000,0000,0000,,is what things looked like a lot of the Dialogue: 0,0:18:16.85,0:18:21.11,Default,,0000,0000,0000,,time. Our tests were passing, the end-to-end\Ntests were Dialogue: 0,0:18:21.11,0:18:23.89,Default,,0000,0000,0000,,failing. If that was the end of the story, Dialogue: 0,0:18:23.89,0:18:26.65,Default,,0000,0000,0000,,we'd be left constantly fighting fires of,\Nwhy is Dialogue: 0,0:18:26.65,0:18:28.59,Default,,0000,0000,0000,,it not working in product- or, why is it Dialogue: 0,0:18:28.59,0:18:31.22,Default,,0000,0000,0000,,not working in staging? And is it the deals Dialogue: 0,0:18:31.22,0:18:33.14,Default,,0000,0000,0000,,service or the product service, blah, blah,\Nblah. Dialogue: 0,0:18:33.14,0:18:35.24,Default,,0000,0000,0000,,But we had these contract tests. So now we Dialogue: 0,0:18:35.24,0:18:37.86,Default,,0000,0000,0000,,can see here that service D's contract tests\Nseem Dialogue: 0,0:18:37.86,0:18:40.50,Default,,0000,0000,0000,,to be failing. So we've got some end-to-end\Ntests Dialogue: 0,0:18:40.50,0:18:44.21,Default,,0000,0000,0000,,that are failing. This contract is failing.\NThat's where Dialogue: 0,0:18:44.21,0:18:46.42,Default,,0000,0000,0000,,we can start looking for, for the cause of Dialogue: 0,0:18:46.42,0:18:47.16,Default,,0000,0000,0000,,this problem. Dialogue: 0,0:18:47.16,0:18:48.62,Default,,0000,0000,0000,,So this is what we spent a lot of Dialogue: 0,0:18:48.62,0:18:49.91,Default,,0000,0000,0000,,our time, not a lot of our time doing, Dialogue: 0,0:18:49.91,0:18:52.60,Default,,0000,0000,0000,,but this was a very frequent occurrence. The\Nbuild Dialogue: 0,0:18:52.60,0:18:54.43,Default,,0000,0000,0000,,would go red. We'd have a look at our Dialogue: 0,0:18:54.43,0:18:58.42,Default,,0000,0000,0000,,dashboard. Oh, it's service D, again. Service\ND, you Dialogue: 0,0:18:58.42,0:19:00.37,Default,,0000,0000,0000,,guys. Dialogue: 0,0:19:00.37,0:19:03.31,Default,,0000,0000,0000,,So we go to our CI system and we Dialogue: 0,0:19:03.31,0:19:06.86,Default,,0000,0000,0000,,would look at the logs. We'd get the log Dialogue: 0,0:19:06.86,0:19:08.64,Default,,0000,0000,0000,,data that showed the request we were sending\Nthe Dialogue: 0,0:19:08.64,0:19:11.59,Default,,0000,0000,0000,,response we, we got back. And we'd have a Dialogue: 0,0:19:11.59,0:19:13.42,Default,,0000,0000,0000,,look and say, yup. It looks like they've broken Dialogue: 0,0:19:13.42,0:19:15.17,Default,,0000,0000,0000,,it again. They forgot to turn on the database Dialogue: 0,0:19:15.17,0:19:18.84,Default,,0000,0000,0000,,after doing a deployment, again. And we would\Nwrite Dialogue: 0,0:19:18.84,0:19:20.34,Default,,0000,0000,0000,,an email to them saying, hey, I think it's Dialogue: 0,0:19:20.34,0:19:23.22,Default,,0000,0000,0000,,probably a bug in our code, but we've noticed Dialogue: 0,0:19:23.22,0:19:24.86,Default,,0000,0000,0000,,when we send this request we get back this Dialogue: 0,0:19:24.86,0:19:28.67,Default,,0000,0000,0000,,500 error from your service, I don't know\Nwhat's Dialogue: 0,0:19:28.67,0:19:29.95,Default,,0000,0000,0000,,going on there. Dialogue: 0,0:19:29.95,0:19:32.64,Default,,0000,0000,0000,,You can tell I'm a consultant. Dialogue: 0,0:19:32.64,0:19:37.00,Default,,0000,0000,0000,,And, things moved a lot smoother. It, it wasn't Dialogue: 0,0:19:37.00,0:19:38.96,Default,,0000,0000,0000,,all kind of rainbows and unicorns, but it\Nwas Dialogue: 0,0:19:38.96,0:19:40.28,Default,,0000,0000,0000,,a lot better than if these tests hadn't have Dialogue: 0,0:19:40.28,0:19:42.73,Default,,0000,0000,0000,,been there. We would have still ended up telling Dialogue: 0,0:19:42.73,0:19:43.88,Default,,0000,0000,0000,,them and they would have fixed it, but it Dialogue: 0,0:19:43.88,0:19:46.00,Default,,0000,0000,0000,,would have sucked a lot more of our time. Dialogue: 0,0:19:46.00,0:19:49.18,Default,,0000,0000,0000,,So that's all the hand wave-y, let's all work Dialogue: 0,0:19:49.18,0:19:51.90,Default,,0000,0000,0000,,as teams stuff. Let's talk about how we're\Nactually Dialogue: 0,0:19:51.90,0:19:56.72,Default,,0000,0000,0000,,gonna build this, this inside of our team. Dialogue: 0,0:19:56.72,0:19:57.80,Default,,0000,0000,0000,,So I want to talk about this idea called Dialogue: 0,0:19:57.80,0:20:01.48,Default,,0000,0000,0000,,service gateways. The main thing I'm gonna\Ntalk about Dialogue: 0,0:20:01.48,0:20:04.15,Default,,0000,0000,0000,,with service gateways is this gem called faraday.\NAnd Dialogue: 0,0:20:04.15,0:20:06.25,Default,,0000,0000,0000,,in order to talk about this gem called faraday, Dialogue: 0,0:20:06.25,0:20:08.01,Default,,0000,0000,0000,,I need to talk about this other gem called Dialogue: 0,0:20:08.01,0:20:08.60,Default,,0000,0000,0000,,rack. Dialogue: 0,0:20:08.60,0:20:10.82,Default,,0000,0000,0000,,So, how many of you know what rack is? Dialogue: 0,0:20:10.82,0:20:13.41,Default,,0000,0000,0000,,Yeah, everyone knows what rack is. How many\Nof Dialogue: 0,0:20:13.41,0:20:15.42,Default,,0000,0000,0000,,you hate people that ask you raise your hands Dialogue: 0,0:20:15.42,0:20:19.35,Default,,0000,0000,0000,,when you're in the audience? I have all the Dialogue: 0,0:20:19.35,0:20:22.53,Default,,0000,0000,0000,,power. You guys have the power but don't realize Dialogue: 0,0:20:22.53,0:20:23.54,Default,,0000,0000,0000,,that. Dialogue: 0,0:20:23.54,0:20:27.66,Default,,0000,0000,0000,,So, rack is this awesome abstraction over\Nhttp servers. Dialogue: 0,0:20:27.66,0:20:31.99,Default,,0000,0000,0000,,And the main idea, the main thing that makes Dialogue: 0,0:20:31.99,0:20:36.15,Default,,0000,0000,0000,,rack awesome is, by abstracting over the concept\Nof Dialogue: 0,0:20:36.15,0:20:38.38,Default,,0000,0000,0000,,a request and the concept of a response, we Dialogue: 0,0:20:38.38,0:20:41.30,Default,,0000,0000,0000,,can kind of stack these middleware components\Nin between Dialogue: 0,0:20:41.30,0:20:45.93,Default,,0000,0000,0000,,our application, and the, the underlying http\Nserver. Dialogue: 0,0:20:45.93,0:20:49.43,Default,,0000,0000,0000,,So, as a request comes in, from the outside Dialogue: 0,0:20:49.43,0:20:55.47,Default,,0000,0000,0000,,world, it travels through this stack of middleware.\NSo, Dialogue: 0,0:20:55.47,0:20:58.30,Default,,0000,0000,0000,,each piece of middleware can, as this request\Nis Dialogue: 0,0:20:58.30,0:21:03.54,Default,,0000,0000,0000,,traveling through, has the opportunity to\Nkind of modify, Dialogue: 0,0:21:03.54,0:21:06.04,Default,,0000,0000,0000,,modify the request and kind of transform it\Nin Dialogue: 0,0:21:06.04,0:21:09.04,Default,,0000,0000,0000,,some way, add some information to the request,\Nor Dialogue: 0,0:21:09.04,0:21:11.06,Default,,0000,0000,0000,,to kind of have some side-effect. Dialogue: 0,0:21:11.06,0:21:13.41,Default,,0000,0000,0000,,And then, a Rails app is gonna deal with Dialogue: 0,0:21:13.41,0:21:16.09,Default,,0000,0000,0000,,that request and then, and then send back\Na Dialogue: 0,0:21:16.09,0:21:18.12,Default,,0000,0000,0000,,response. And, again, as that response is\Ntraveling back Dialogue: 0,0:21:18.12,0:21:23.67,Default,,0000,0000,0000,,up through the pipeline, through the, the\Nmiddleware stacks, Dialogue: 0,0:21:23.67,0:21:26.89,Default,,0000,0000,0000,,again, each of those pieces of middleware\Ncan modify Dialogue: 0,0:21:26.89,0:21:29.15,Default,,0000,0000,0000,,that request in some way, can add some information Dialogue: 0,0:21:29.15,0:21:32.32,Default,,0000,0000,0000,,to it or can have some side effect. Dialogue: 0,0:21:32.32,0:21:35.89,Default,,0000,0000,0000,,Rails loves rack. So this is the, the kind Dialogue: 0,0:21:35.89,0:21:40.96,Default,,0000,0000,0000,,of the stop stack of rack middlewares that\Ncomes Dialogue: 0,0:21:40.96,0:21:42.97,Default,,0000,0000,0000,,when you, when you just do rails generate\Nnew Dialogue: 0,0:21:42.97,0:21:46.58,Default,,0000,0000,0000,,project. So, yeah. Pretty, pretty popular.\NAnd the reason Dialogue: 0,0:21:46.58,0:21:48.18,Default,,0000,0000,0000,,that this is popular is because the guys that Dialogue: 0,0:21:48.18,0:21:50.21,Default,,0000,0000,0000,,built rack are smart and the guys that, guys Dialogue: 0,0:21:50.21,0:21:52.23,Default,,0000,0000,0000,,and gals, excuse me, that built rack are smart Dialogue: 0,0:21:52.23,0:21:55.98,Default,,0000,0000,0000,,and, likewise, Rails. And they realized that\Nthis is Dialogue: 0,0:21:55.98,0:21:57.88,Default,,0000,0000,0000,,a very powerful abstraction and so they're\Nreally leveraging Dialogue: 0,0:21:57.88,0:22:00.10,Default,,0000,0000,0000,,this power. Dialogue: 0,0:22:00.10,0:22:02.15,Default,,0000,0000,0000,,So why was I talking about rack when I Dialogue: 0,0:22:02.15,0:22:04.56,Default,,0000,0000,0000,,was supposed to be talking about faraday?\NFaraday is Dialogue: 0,0:22:04.56,0:22:07.60,Default,,0000,0000,0000,,the exact same idea of rack, but applied for Dialogue: 0,0:22:07.60,0:22:11.20,Default,,0000,0000,0000,,an http client. So, again, we have this abstraction Dialogue: 0,0:22:11.20,0:22:13.72,Default,,0000,0000,0000,,over request and response. This time in the\Ncontext Dialogue: 0,0:22:13.72,0:22:16.17,Default,,0000,0000,0000,,of making a request and receiving a response\Nrather Dialogue: 0,0:22:16.17,0:22:19.18,Default,,0000,0000,0000,,than receiving a request and sending back\Na response. Dialogue: 0,0:22:19.18,0:22:23.12,Default,,0000,0000,0000,,And, again, we can stack these pieces of middleware Dialogue: 0,0:22:23.12,0:22:27.69,Default,,0000,0000,0000,,in between our application and the underlying\Nnetwork library. Dialogue: 0,0:22:27.69,0:22:30.26,Default,,0000,0000,0000,,So, in this case, it's us making a request. Dialogue: 0,0:22:30.26,0:22:32.81,Default,,0000,0000,0000,,So, as we send the request out to the Dialogue: 0,0:22:32.81,0:22:36.38,Default,,0000,0000,0000,,network, again, that request travels through\Nall of these Dialogue: 0,0:22:36.38,0:22:38.42,Default,,0000,0000,0000,,middlewares, and these middlewares, again,\Nhave the opportunity to Dialogue: 0,0:22:38.42,0:22:40.85,Default,,0000,0000,0000,,either modify that request in some way, have\Na Dialogue: 0,0:22:40.85,0:22:43.72,Default,,0000,0000,0000,,side effect, add some information to the request.\NEventually Dialogue: 0,0:22:43.72,0:22:45.01,Default,,0000,0000,0000,,it gets on the wire. Eventually it gets to Dialogue: 0,0:22:45.01,0:22:47.29,Default,,0000,0000,0000,,our dependency. Hopefully not service D because\Nthey'll probably Dialogue: 0,0:22:47.29,0:22:50.26,Default,,0000,0000,0000,,go down again. Dialogue: 0,0:22:50.26,0:22:53.64,Default,,0000,0000,0000,,And then service D hopefully sends a response,\Nand Dialogue: 0,0:22:53.64,0:22:57.16,Default,,0000,0000,0000,,again, as that response travels back through\Nthe stack, Dialogue: 0,0:22:57.16,0:23:01.11,Default,,0000,0000,0000,,the stack is able to modify that, that response Dialogue: 0,0:23:01.11,0:23:02.62,Default,,0000,0000,0000,,as it comes through, add some information.\NHave a Dialogue: 0,0:23:02.62,0:23:04.69,Default,,0000,0000,0000,,side effect. Dialogue: 0,0:23:04.69,0:23:07.99,Default,,0000,0000,0000,,So, how do we use this thing? So here's Dialogue: 0,0:23:07.99,0:23:10.23,Default,,0000,0000,0000,,a, this is a service gateway. This is a Dialogue: 0,0:23:10.23,0:23:14.36,Default,,0000,0000,0000,,class that represents a, a connection to the\Noutside Dialogue: 0,0:23:14.36,0:23:19.48,Default,,0000,0000,0000,,world. Here's us building a faraday middleware\Nstack. So Dialogue: 0,0:23:19.48,0:23:24.16,Default,,0000,0000,0000,,we're building a connection. We're saying\Nhey, new faraday. Dialogue: 0,0:23:24.16,0:23:26.40,Default,,0000,0000,0000,,Please use the instrumentation middleware\Nand do some JSON Dialogue: 0,0:23:26.40,0:23:30.84,Default,,0000,0000,0000,,stuff and follow redirects and do some logging. Dialogue: 0,0:23:30.84,0:23:33.93,Default,,0000,0000,0000,,And that's it. We've now got a faraday connection. Dialogue: 0,0:23:33.93,0:23:37.19,Default,,0000,0000,0000,,This is how we use a faraday connection. So, Dialogue: 0,0:23:37.19,0:23:40.49,Default,,0000,0000,0000,,we say, hey, faraday connection, hey, http\Nclient, we Dialogue: 0,0:23:40.49,0:23:43.16,Default,,0000,0000,0000,,want to get this url, or this path. And Dialogue: 0,0:23:43.16,0:23:46.03,Default,,0000,0000,0000,,we get a response back. Pretty simple stuff.\NI Dialogue: 0,0:23:46.03,0:23:47.95,Default,,0000,0000,0000,,would say this is readable code. DHH would\Nbe Dialogue: 0,0:23:47.95,0:23:49.99,Default,,0000,0000,0000,,pleased with me. Dialogue: 0,0:23:49.99,0:23:51.59,Default,,0000,0000,0000,,And what's really nice, the real power of,\Nof Dialogue: 0,0:23:51.59,0:23:54.42,Default,,0000,0000,0000,,faraday, is there's all this extra stuff that\Nwe Dialogue: 0,0:23:54.42,0:23:58.84,Default,,0000,0000,0000,,set up, this middleware, this technical junk\Ngoing on. Dialogue: 0,0:23:58.84,0:24:01.33,Default,,0000,0000,0000,,But our, the rest of our code doesn't have Dialogue: 0,0:24:01.33,0:24:03.14,Default,,0000,0000,0000,,to care about it. So we've kind of abstracted Dialogue: 0,0:24:03.14,0:24:07.97,Default,,0000,0000,0000,,over all of that stuff of JSON, following\Nredirects Dialogue: 0,0:24:07.97,0:24:11.68,Default,,0000,0000,0000,,and logging and caching. Dialogue: 0,0:24:11.68,0:24:13.47,Default,,0000,0000,0000,,So we used faraday a lot in these things Dialogue: 0,0:24:13.47,0:24:19.25,Default,,0000,0000,0000,,that, that I was calling service gateways.\NSo the, Dialogue: 0,0:24:19.25,0:24:20.54,Default,,0000,0000,0000,,as I said, the really nice thing about things Dialogue: 0,0:24:20.54,0:24:22.31,Default,,0000,0000,0000,,like rack and faraday is they allow us to Dialogue: 0,0:24:22.31,0:24:28.56,Default,,0000,0000,0000,,segregate the boring tech-y stuff, http, logging,\Ncaching, instrumentation, Dialogue: 0,0:24:28.56,0:24:30.53,Default,,0000,0000,0000,,the stuff that computer people talk about\Nat conferences Dialogue: 0,0:24:30.53,0:24:33.58,Default,,0000,0000,0000,,like this, from the business domain, which\Nis the Dialogue: 0,0:24:33.58,0:24:35.92,Default,,0000,0000,0000,,stuff that people actually care about. Dialogue: 0,0:24:35.92,0:24:38.89,Default,,0000,0000,0000,,So, these service gateways acted as the place\Nwhere Dialogue: 0,0:24:38.89,0:24:43.42,Default,,0000,0000,0000,,we pushed all of the boring techy goop out Dialogue: 0,0:24:43.42,0:24:45.96,Default,,0000,0000,0000,,to the boundaries of our system, so the core Dialogue: 0,0:24:45.96,0:24:48.63,Default,,0000,0000,0000,,of our system, the core of our Rails application, Dialogue: 0,0:24:48.63,0:24:53.63,Default,,0000,0000,0000,,wasn't talking about JSON requests, urls,\Ncaching, logging, deserialization. Dialogue: 0,0:24:53.63,0:24:56.94,Default,,0000,0000,0000,,It was talking about books and products and\Nprices. Dialogue: 0,0:24:56.94,0:25:01.08,Default,,0000,0000,0000,,Things that our application really should\Nbe caring about. Dialogue: 0,0:25:01.08,0:25:07.09,Default,,0000,0000,0000,,So this is this idea of hexagonal architectures.\NPush Dialogue: 0,0:25:07.09,0:25:09.37,Default,,0000,0000,0000,,all of the goopy boring techy stuff out to Dialogue: 0,0:25:09.37,0:25:11.17,Default,,0000,0000,0000,,the boundaries of your system, so that the\Ncore Dialogue: 0,0:25:11.17,0:25:15.24,Default,,0000,0000,0000,,of your system can focus on the domain. The Dialogue: 0,0:25:15.24,0:25:17.06,Default,,0000,0000,0000,,stuff that you really care about. The stuff\Nthat Dialogue: 0,0:25:17.06,0:25:22.53,Default,,0000,0000,0000,,makes your system valuable to other people. Dialogue: 0,0:25:22.53,0:25:24.35,Default,,0000,0000,0000,,So what kind of things did we put into Dialogue: 0,0:25:24.35,0:25:26.29,Default,,0000,0000,0000,,these? What kind of stuff, boring techy stuff\Ndid Dialogue: 0,0:25:26.29,0:25:30.61,Default,,0000,0000,0000,,we isolate in these service gateways? One\Nthing that Dialogue: 0,0:25:30.61,0:25:35.76,Default,,0000,0000,0000,,we did was we isolated serialization. So,\Nserialization means Dialogue: 0,0:25:35.76,0:25:39.71,Default,,0000,0000,0000,,JSON parsing or, in our case, XML parsing,\Ncause Dialogue: 0,0:25:39.71,0:25:44.19,Default,,0000,0000,0000,,we were in an enterprise. Yay. Dialogue: 0,0:25:44.19,0:25:47.12,Default,,0000,0000,0000,,Comes down to the same thing actually. So,\Nwhen Dialogue: 0,0:25:47.12,0:25:49.32,Default,,0000,0000,0000,,we talk about parsing JSON or XML, we're actually Dialogue: 0,0:25:49.32,0:25:52.02,Default,,0000,0000,0000,,talking about two different things. And I\Nthink often Dialogue: 0,0:25:52.02,0:25:55.63,Default,,0000,0000,0000,,we conflate these two. So, step one, is we Dialogue: 0,0:25:55.63,0:25:57.83,Default,,0000,0000,0000,,have this stream of bytes or this raw string, Dialogue: 0,0:25:57.83,0:25:59.39,Default,,0000,0000,0000,,and we want to turn it into this kind Dialogue: 0,0:25:59.39,0:26:02.92,Default,,0000,0000,0000,,of generic structure, like a hash of arrays\Nof, Dialogue: 0,0:26:02.92,0:26:04.93,Default,,0000,0000,0000,,of objects, right. So that's, that's something,\Nyou know. Dialogue: 0,0:26:04.93,0:26:06.91,Default,,0000,0000,0000,,You do JSON dot parse or whatever and you Dialogue: 0,0:26:06.91,0:26:09.39,Default,,0000,0000,0000,,get this kind of generic data structure out. Dialogue: 0,0:26:09.39,0:26:13.76,Default,,0000,0000,0000,,But, if we are following the principles of\Nhexagonal Dialogue: 0,0:26:13.76,0:26:17.18,Default,,0000,0000,0000,,architecture, we don't want to deal with JSON\Ndata Dialogue: 0,0:26:17.18,0:26:18.90,Default,,0000,0000,0000,,structures or generic data structures. We\Nwant to deal Dialogue: 0,0:26:18.90,0:26:21.73,Default,,0000,0000,0000,,with products and books and deals. So the\Nnext Dialogue: 0,0:26:21.73,0:26:23.95,Default,,0000,0000,0000,,step is to actually take that generic structure\Nand Dialogue: 0,0:26:23.95,0:26:26.52,Default,,0000,0000,0000,,map it into a domain object that we actually Dialogue: 0,0:26:26.52,0:26:27.30,Default,,0000,0000,0000,,want to work with. Dialogue: 0,0:26:27.30,0:26:30.24,Default,,0000,0000,0000,,Cause our goal here is to stop talking about Dialogue: 0,0:26:30.24,0:26:32.58,Default,,0000,0000,0000,,things like JSON as quickly as possible, at\Nthe Dialogue: 0,0:26:32.58,0:26:35.41,Default,,0000,0000,0000,,boundaries of our system, and start talking\Nabout products Dialogue: 0,0:26:35.41,0:26:39.94,Default,,0000,0000,0000,,and prices and deals. So this is two steps. Dialogue: 0,0:26:39.94,0:26:42.85,Default,,0000,0000,0000,,So, the other thing that you'll, I noticed\Nworking Dialogue: 0,0:26:42.85,0:26:47.12,Default,,0000,0000,0000,,particularly in larger organizations, is these\Nresponses that you Dialogue: 0,0:26:47.12,0:26:49.82,Default,,0000,0000,0000,,get back are huge. And really, often times,\Nyou Dialogue: 0,0:26:49.82,0:26:52.34,Default,,0000,0000,0000,,only really care about a small subset of the Dialogue: 0,0:26:52.34,0:26:54.47,Default,,0000,0000,0000,,response you get back. So you get back this Dialogue: 0,0:26:54.47,0:26:56.75,Default,,0000,0000,0000,,big chunk of bytes. You turn it into this Dialogue: 0,0:26:56.75,0:26:59.45,Default,,0000,0000,0000,,big generic structure, and then you actually\Njust want Dialogue: 0,0:26:59.45,0:27:00.73,Default,,0000,0000,0000,,to pluck three or four or five or six Dialogue: 0,0:27:00.73,0:27:03.49,Default,,0000,0000,0000,,things out of that structure, that represent\Nthe product Dialogue: 0,0:27:03.49,0:27:04.98,Default,,0000,0000,0000,,in your, in your domain. Dialogue: 0,0:27:04.98,0:27:07.24,Default,,0000,0000,0000,,You don't care about the, the short description.\NYou Dialogue: 0,0:27:07.24,0:27:09.69,Default,,0000,0000,0000,,certainly don't care about the response time.\NReally all Dialogue: 0,0:27:09.69,0:27:11.50,Default,,0000,0000,0000,,you care about is the, you know, the title Dialogue: 0,0:27:11.50,0:27:13.76,Default,,0000,0000,0000,,or the author, you know, that kind of thing. Dialogue: 0,0:27:13.76,0:27:16.57,Default,,0000,0000,0000,,So there's some gems that can help you make Dialogue: 0,0:27:16.57,0:27:19.22,Default,,0000,0000,0000,,this easier. So, very popular one is this\Nthing Dialogue: 0,0:27:19.22,0:27:20.98,Default,,0000,0000,0000,,called hashie. Hashie will just make it a\Nlittle Dialogue: 0,0:27:20.98,0:27:22.63,Default,,0000,0000,0000,,bit easier for you to work with these generic Dialogue: 0,0:27:22.63,0:27:24.47,Default,,0000,0000,0000,,data structures. But at the end of the day, Dialogue: 0,0:27:24.47,0:27:27.09,Default,,0000,0000,0000,,they're still generic data structures. Dialogue: 0,0:27:27.09,0:27:31.30,Default,,0000,0000,0000,,The second step that we took was to take Dialogue: 0,0:27:31.30,0:27:32.88,Default,,0000,0000,0000,,all of that boring boiler plate that we were Dialogue: 0,0:27:32.88,0:27:35.07,Default,,0000,0000,0000,,doing of saying, you know, get this dot that Dialogue: 0,0:27:35.07,0:27:37.53,Default,,0000,0000,0000,,dot the other thing and get me the price. Dialogue: 0,0:27:37.53,0:27:38.94,Default,,0000,0000,0000,,And then this dot that dot the other thing, Dialogue: 0,0:27:38.94,0:27:41.65,Default,,0000,0000,0000,,get me the, the offer details. And turn that Dialogue: 0,0:27:41.65,0:27:44.10,Default,,0000,0000,0000,,into a declarative statement that we could\Njust make Dialogue: 0,0:27:44.10,0:27:46.06,Default,,0000,0000,0000,,at the top of a class that would make Dialogue: 0,0:27:46.06,0:27:46.25,Default,,0000,0000,0000,,these things. Dialogue: 0,0:27:46.25,0:27:48.81,Default,,0000,0000,0000,,So we turn that mapping, that boring boilerplate\Nmapping, Dialogue: 0,0:27:48.81,0:27:52.10,Default,,0000,0000,0000,,into something that was declarative rather\Nthan imperative. We Dialogue: 0,0:27:52.10,0:27:55.58,Default,,0000,0000,0000,,actually ended up extracting that little library\Nthat we Dialogue: 0,0:27:55.58,0:27:58.59,Default,,0000,0000,0000,,built into this thing called lazy_doc. There's\Nanother couple Dialogue: 0,0:27:58.59,0:28:00.97,Default,,0000,0000,0000,,of gems that are very, that have very similar Dialogue: 0,0:28:00.97,0:28:04.45,Default,,0000,0000,0000,,goals. Embedded_doc is another one. And there's\Nthis really Dialogue: 0,0:28:04.45,0:28:08.57,Default,,0000,0000,0000,,quite powerful one called representable, which\Nis very good. Dialogue: 0,0:28:08.57,0:28:10.81,Default,,0000,0000,0000,,It's, it's very powerful. It almost does too\Nmany Dialogue: 0,0:28:10.81,0:28:13.18,Default,,0000,0000,0000,,things for my taste, but it's definitely,\Ndefinitely a Dialogue: 0,0:28:13.18,0:28:14.96,Default,,0000,0000,0000,,good option. Dialogue: 0,0:28:14.96,0:28:17.12,Default,,0000,0000,0000,,The reason, by the way, embedded_doc is called\Nembedded_doc Dialogue: 0,0:28:17.12,0:28:19.23,Default,,0000,0000,0000,,is cause it's, what we're kind of talking\Nabout Dialogue: 0,0:28:19.23,0:28:22.49,Default,,0000,0000,0000,,here is this embedded document pattern. That's\Nthe name Dialogue: 0,0:28:22.49,0:28:24.35,Default,,0000,0000,0000,,of the pattern. Sorry, now I'm talking about\Npatterns. Dialogue: 0,0:28:24.35,0:28:28.17,Default,,0000,0000,0000,,I'm really off-message. Dialogue: 0,0:28:28.17,0:28:29.55,Default,,0000,0000,0000,,So what else did we put in our faraday Dialogue: 0,0:28:29.55,0:28:35.72,Default,,0000,0000,0000,,stack? Caching. This is the most, for me,\Nthe Dialogue: 0,0:28:35.72,0:28:38.92,Default,,0000,0000,0000,,most exciting thing to talk about. So let\Nme Dialogue: 0,0:28:38.92,0:28:41.45,Default,,0000,0000,0000,,talk about it. So, back to our example, let's Dialogue: 0,0:28:41.45,0:28:44.00,Default,,0000,0000,0000,,say we've got our Rails app. And we've got Dialogue: 0,0:28:44.00,0:28:47.20,Default,,0000,0000,0000,,our product service and we've got this pricing\Nservice. Dialogue: 0,0:28:47.20,0:28:48.64,Default,,0000,0000,0000,,Fun fact that I didn't know before I worked Dialogue: 0,0:28:48.64,0:28:51.45,Default,,0000,0000,0000,,on this application. Prices can change, like,\Nmultiple times Dialogue: 0,0:28:51.45,0:28:54.22,Default,,0000,0000,0000,,a minute in some of these systems. They're\Nreally Dialogue: 0,0:28:54.22,0:28:56.84,Default,,0000,0000,0000,,trying to optimize for prices. Dialogue: 0,0:28:56.84,0:29:01.82,Default,,0000,0000,0000,,So, can't really cache pricing information.\NProduct information tends Dialogue: 0,0:29:01.82,0:29:03.53,Default,,0000,0000,0000,,to be pretty static. The author of a book Dialogue: 0,0:29:03.53,0:29:06.11,Default,,0000,0000,0000,,doesn't change very often. The title of a\Nbook Dialogue: 0,0:29:06.11,0:29:09.65,Default,,0000,0000,0000,,doesn't change very often. But we're always\Nlooking up Dialogue: 0,0:29:09.65,0:29:12.16,Default,,0000,0000,0000,,this product information, almost every single\Nrequest. So let's Dialogue: 0,0:29:12.16,0:29:13.85,Default,,0000,0000,0000,,cache that. Let's make this performant. Dialogue: 0,0:29:13.85,0:29:16.68,Default,,0000,0000,0000,,So, a lot of you are automatically starting\Nto Dialogue: 0,0:29:16.68,0:29:18.91,Default,,0000,0000,0000,,think about how we would implement this and,\Nwell, Dialogue: 0,0:29:18.91,0:29:20.73,Default,,0000,0000,0000,,we would have a product cache, and then when Dialogue: 0,0:29:20.73,0:29:22.43,Default,,0000,0000,0000,,we need a product we'll go to the cache, Dialogue: 0,0:29:22.43,0:29:24.75,Default,,0000,0000,0000,,and if it's there, then we'll check the freshness. Dialogue: 0,0:29:24.75,0:29:27.16,Default,,0000,0000,0000,,And if the freshness is up to some configured Dialogue: 0,0:29:27.16,0:29:28.89,Default,,0000,0000,0000,,thing, then we'll get it. Otherwise we'll\Ngo to Dialogue: 0,0:29:28.89,0:29:30.28,Default,,0000,0000,0000,,the network. And then when we get back from Dialogue: 0,0:29:30.28,0:29:31.95,Default,,0000,0000,0000,,network, put it in the cache, blah, blah,\Nblah. Dialogue: 0,0:29:31.95,0:29:34.56,Default,,0000,0000,0000,,All of this stuff, right. And we're, we're\Nback Dialogue: 0,0:29:34.56,0:29:37.09,Default,,0000,0000,0000,,to thinking about boring technical goop and\Nwe're not Dialogue: 0,0:29:37.09,0:29:40.50,Default,,0000,0000,0000,,talking about our domain anymore. We didn't\Nwant to Dialogue: 0,0:29:40.50,0:29:44.79,Default,,0000,0000,0000,,do this. I'm, honestly, bored with getting\Ncaching wrong Dialogue: 0,0:29:44.79,0:29:46.69,Default,,0000,0000,0000,,over and over again in each of my applications. Dialogue: 0,0:29:46.69,0:29:48.70,Default,,0000,0000,0000,,And so, we just pretended to be a web Dialogue: 0,0:29:48.70,0:29:50.69,Default,,0000,0000,0000,,browser. Dialogue: 0,0:29:50.69,0:29:53.56,Default,,0000,0000,0000,,As web developers, we know that images are\Nvery Dialogue: 0,0:29:53.56,0:29:56.05,Default,,0000,0000,0000,,cacheable, and we should put caching headers\Non our, Dialogue: 0,0:29:56.05,0:29:59.06,Default,,0000,0000,0000,,on our images, so that the browser can do Dialogue: 0,0:29:59.06,0:30:00.45,Default,,0000,0000,0000,,the right thing and cache this so that every Dialogue: 0,0:30:00.45,0:30:02.15,Default,,0000,0000,0000,,time we want to get this image, if it's Dialogue: 0,0:30:02.15,0:30:04.20,Default,,0000,0000,0000,,already in the cache, we don't have to go Dialogue: 0,0:30:04.20,0:30:09.20,Default,,0000,0000,0000,,onto the network. Kind of very common practice. Dialogue: 0,0:30:09.20,0:30:12.82,Default,,0000,0000,0000,,We don't write JavaScript cache repositories\Nand then go Dialogue: 0,0:30:12.82,0:30:13.98,Default,,0000,0000,0000,,and check and see if the image is in Dialogue: 0,0:30:13.98,0:30:16.06,Default,,0000,0000,0000,,there and then, if it's not, we'll go to Dialogue: 0,0:30:16.06,0:30:17.23,Default,,0000,0000,0000,,the network and then put it in the cache Dialogue: 0,0:30:17.23,0:30:18.32,Default,,0000,0000,0000,,repository. Dialogue: 0,0:30:18.32,0:30:19.91,Default,,0000,0000,0000,,The web browser just does this for us. All Dialogue: 0,0:30:19.91,0:30:21.99,Default,,0000,0000,0000,,we need to do is set the caching headers Dialogue: 0,0:30:21.99,0:30:26.57,Default,,0000,0000,0000,,on this, this ping. So, my argument is, and Dialogue: 0,0:30:26.57,0:30:28.99,Default,,0000,0000,0000,,what we did was, just apply the same principle Dialogue: 0,0:30:28.99,0:30:33.00,Default,,0000,0000,0000,,to our API. So product dot, or product slash Dialogue: 0,0:30:33.00,0:30:35.81,Default,,0000,0000,0000,,wherever this is at - my pretend url for, Dialogue: 0,0:30:35.81,0:30:39.75,Default,,0000,0000,0000,,for this product. We had caching headers on\Nthis Dialogue: 0,0:30:39.75,0:30:43.98,Default,,0000,0000,0000,,API call, that said this, this url is cacheable Dialogue: 0,0:30:43.98,0:30:46.59,Default,,0000,0000,0000,,for twenty minutes. Dialogue: 0,0:30:46.59,0:30:49.79,Default,,0000,0000,0000,,In our faraday stack, we had a caching middleware. Dialogue: 0,0:30:49.79,0:30:52.88,Default,,0000,0000,0000,,So, the first time that we requested that\Nurl Dialogue: 0,0:30:52.88,0:30:55.24,Default,,0000,0000,0000,,for that product, first time we wanted that\Nproduct, Dialogue: 0,0:30:55.24,0:30:57.14,Default,,0000,0000,0000,,our Rails app would say to our service gateway, Dialogue: 0,0:30:57.14,0:30:58.81,Default,,0000,0000,0000,,I want this product. The service gateway would\Nsay, Dialogue: 0,0:30:58.81,0:31:01.55,Default,,0000,0000,0000,,OK, it's at this url. I'm gonna make a Dialogue: 0,0:31:01.55,0:31:05.21,Default,,0000,0000,0000,,request through my faraday stack for that\Nurl. Dialogue: 0,0:31:05.21,0:31:08.32,Default,,0000,0000,0000,,That request would go through our stack, and\Nthe Dialogue: 0,0:31:08.32,0:31:09.83,Default,,0000,0000,0000,,response would go through our response on\Nthe way Dialogue: 0,0:31:09.83,0:31:11.31,Default,,0000,0000,0000,,back, and the caching layer would say, oh\Nlook Dialogue: 0,0:31:11.31,0:31:13.82,Default,,0000,0000,0000,,at that. There's this caching header on this\NJSON Dialogue: 0,0:31:13.82,0:31:15.44,Default,,0000,0000,0000,,that says it's gonna be valid for twenty minutes. Dialogue: 0,0:31:15.44,0:31:17.45,Default,,0000,0000,0000,,Let me just put this response in my little Dialogue: 0,0:31:17.45,0:31:19.40,Default,,0000,0000,0000,,cache on disk here. Dialogue: 0,0:31:19.40,0:31:23.59,Default,,0000,0000,0000,,And, five minutes later, another user comes\Nin and Dialogue: 0,0:31:23.59,0:31:26.43,Default,,0000,0000,0000,,wants to, by chance, look at the same product. Dialogue: 0,0:31:26.43,0:31:30.45,Default,,0000,0000,0000,,Again, our service gateway, our code doesn't\Ndo anything Dialogue: 0,0:31:30.45,0:31:31.95,Default,,0000,0000,0000,,different. It just says, hey, service gateway,\NI want Dialogue: 0,0:31:31.95,0:31:34.69,Default,,0000,0000,0000,,this product. Our service gateway doesn't\Ndo anything different. Dialogue: 0,0:31:34.69,0:31:36.63,Default,,0000,0000,0000,,It just says to faraday, hey, I want to Dialogue: 0,0:31:36.63,0:31:39.08,Default,,0000,0000,0000,,get this url. Dialogue: 0,0:31:39.08,0:31:41.29,Default,,0000,0000,0000,,The request comes through to the caching layer.\NThe Dialogue: 0,0:31:41.29,0:31:44.05,Default,,0000,0000,0000,,caching layer says, oh look. That's the same\Nurl Dialogue: 0,0:31:44.05,0:31:46.15,Default,,0000,0000,0000,,I just pulled five minutes, and the, the caching Dialogue: 0,0:31:46.15,0:31:48.27,Default,,0000,0000,0000,,headers say it's valid for twenty minutes.\NI'll just Dialogue: 0,0:31:48.27,0:31:49.94,Default,,0000,0000,0000,,return what I've got in my local cache. I Dialogue: 0,0:31:49.94,0:31:52.79,Default,,0000,0000,0000,,won't go on the network. I won't bother with Dialogue: 0,0:31:52.79,0:31:56.06,Default,,0000,0000,0000,,all that stuff. I'll just read it from the Dialogue: 0,0:31:56.06,0:31:56.73,Default,,0000,0000,0000,,disc. Dialogue: 0,0:31:56.73,0:31:59.16,Default,,0000,0000,0000,,This is what web browsers do all the time. Dialogue: 0,0:31:59.16,0:32:01.44,Default,,0000,0000,0000,,We can do this all this time with, literally, Dialogue: 0,0:32:01.44,0:32:04.53,Default,,0000,0000,0000,,a single line of code. Sorry. That's not a Dialogue: 0,0:32:04.53,0:32:09.05,Default,,0000,0000,0000,,single line. It's a single method call. Would\Nbe Dialogue: 0,0:32:09.05,0:32:10.34,Default,,0000,0000,0000,,a single line, I guess everything could be\Na Dialogue: 0,0:32:10.34,0:32:14.11,Default,,0000,0000,0000,,single line of code, right. Dialogue: 0,0:32:14.11,0:32:18.96,Default,,0000,0000,0000,,So, we've just said to our faraday stack,\Nhey, Dialogue: 0,0:32:18.96,0:32:21.03,Default,,0000,0000,0000,,add some caching middleware. Write it to disc\Nat Dialogue: 0,0:32:21.03,0:32:24.45,Default,,0000,0000,0000,,this location, and there we go. We, we've\Nnow Dialogue: 0,0:32:24.45,0:32:27.00,Default,,0000,0000,0000,,got all the semantics of a web browser. And, Dialogue: 0,0:32:27.00,0:32:28.75,Default,,0000,0000,0000,,we didn't have to do any work apart from Dialogue: 0,0:32:28.75,0:32:33.46,Default,,0000,0000,0000,,this single method call. And what's really\Npowerful is Dialogue: 0,0:32:33.46,0:32:37.61,Default,,0000,0000,0000,,the team that knows the most about the data, Dialogue: 0,0:32:37.61,0:32:40.29,Default,,0000,0000,0000,,so the product team in this case, can define Dialogue: 0,0:32:40.29,0:32:43.30,Default,,0000,0000,0000,,the caching semantics of their data. Dialogue: 0,0:32:43.30,0:32:45.95,Default,,0000,0000,0000,,So, if they realized, like, you know what,\Nthese, Dialogue: 0,0:32:45.95,0:32:47.97,Default,,0000,0000,0000,,this, the name of the author keeps on changing. Dialogue: 0,0:32:47.97,0:32:51.72,Default,,0000,0000,0000,,We need to drop down the caching freshness,\Nthey Dialogue: 0,0:32:51.72,0:32:53.69,Default,,0000,0000,0000,,can just say, you know what, it's gonna be Dialogue: 0,0:32:53.69,0:32:56.69,Default,,0000,0000,0000,,ten minutes. And we just get that semantics,\Nwe Dialogue: 0,0:32:56.69,0:32:59.58,Default,,0000,0000,0000,,just start, we change our caching rules. No,\Nno Dialogue: 0,0:32:59.58,0:33:02.85,Default,,0000,0000,0000,,code change. No configuration change. No redeployment.\NIt just Dialogue: 0,0:33:02.85,0:33:03.54,Default,,0000,0000,0000,,happens. Dialogue: 0,0:33:03.54,0:33:06.99,Default,,0000,0000,0000,,So, again, Conway's Law. The team that knows\Nthe Dialogue: 0,0:33:06.99,0:33:10.31,Default,,0000,0000,0000,,most about the data has control over the caching Dialogue: 0,0:33:10.31,0:33:15.58,Default,,0000,0000,0000,,of that data. Really, really, really powerful\Nstuff. Dialogue: 0,0:33:15.58,0:33:18.72,Default,,0000,0000,0000,,This goes back to this principle that, that\NI'm Dialogue: 0,0:33:18.72,0:33:21.09,Default,,0000,0000,0000,,really passionate about. I think a lot of\Ntimes Dialogue: 0,0:33:21.09,0:33:22.56,Default,,0000,0000,0000,,we, we, we, we think of ourselves as building Dialogue: 0,0:33:22.56,0:33:24.65,Default,,0000,0000,0000,,these systems on the web. We, we're building\Nour Dialogue: 0,0:33:24.65,0:33:28.24,Default,,0000,0000,0000,,stuff on top of http. I don't think we Dialogue: 0,0:33:28.24,0:33:29.32,Default,,0000,0000,0000,,should be doing that. I think we should be Dialogue: 0,0:33:29.32,0:33:32.13,Default,,0000,0000,0000,,building systems that are of the web. Dialogue: 0,0:33:32.13,0:33:37.11,Default,,0000,0000,0000,,So, we should be using principles like, like\NREST, Dialogue: 0,0:33:37.11,0:33:42.88,Default,,0000,0000,0000,,like hypermedia, like caching, http caching,\Nbecause these, these Dialogue: 0,0:33:42.88,0:33:46.40,Default,,0000,0000,0000,,are the principles that have made the most\Nsuccessful, Dialogue: 0,0:33:46.40,0:33:49.54,Default,,0000,0000,0000,,biggest distributed system in the world work.\NIt's really Dialogue: 0,0:33:49.54,0:33:53.20,Default,,0000,0000,0000,,messy, and sometimes it's a bit of a pain Dialogue: 0,0:33:53.20,0:33:56.08,Default,,0000,0000,0000,,to use, but it works really well, and it's Dialogue: 0,0:33:56.08,0:33:58.85,Default,,0000,0000,0000,,all done for us already. We don't have to Dialogue: 0,0:33:58.85,0:34:01.30,Default,,0000,0000,0000,,figure this stuff out ourselves. It's all\Nout there Dialogue: 0,0:34:01.30,0:34:03.70,Default,,0000,0000,0000,,and it's been working for decades. Dialogue: 0,0:34:03.70,0:34:06.32,Default,,0000,0000,0000,,We use it, in some cases, hypermedia is something Dialogue: 0,0:34:06.32,0:34:08.95,Default,,0000,0000,0000,,we're starting to understand more and more.\NWe can Dialogue: 0,0:34:08.95,0:34:10.83,Default,,0000,0000,0000,,use it in more places. Caching is, is an Dialogue: 0,0:34:10.83,0:34:12.97,Default,,0000,0000,0000,,example of that. Dialogue: 0,0:34:12.97,0:34:17.03,Default,,0000,0000,0000,,So, some principles. I could have talked about\Nall Dialogue: 0,0:34:17.03,0:34:18.69,Default,,0000,0000,0000,,this stuff for hours and hours and hours,\Nbut Dialogue: 0,0:34:18.69,0:34:20.33,Default,,0000,0000,0000,,I don't have time to do that. So I'm Dialogue: 0,0:34:20.33,0:34:22.36,Default,,0000,0000,0000,,just gonna shove a bunch of words at the Dialogue: 0,0:34:22.36,0:34:26.21,Default,,0000,0000,0000,,end of this talk, and, and hope that, that Dialogue: 0,0:34:26.21,0:34:27.68,Default,,0000,0000,0000,,if they're new words to you that you go Dialogue: 0,0:34:27.68,0:34:29.93,Default,,0000,0000,0000,,out and, and research them. Dialogue: 0,0:34:29.93,0:34:32.79,Default,,0000,0000,0000,,Conway's Law is, is the big one. This is Dialogue: 0,0:34:32.79,0:34:36.43,Default,,0000,0000,0000,,something I'm really passionate about. If\Nyou, software, building Dialogue: 0,0:34:36.43,0:34:38.69,Default,,0000,0000,0000,,software today is very much a team sport.\NIf Dialogue: 0,0:34:38.69,0:34:40.74,Default,,0000,0000,0000,,you don't understand how to work with other\Nteams, Dialogue: 0,0:34:40.74,0:34:42.55,Default,,0000,0000,0000,,then someone else is gonna do it better than Dialogue: 0,0:34:42.55,0:34:45.14,Default,,0000,0000,0000,,you. So this is important stuff. Dialogue: 0,0:34:45.14,0:34:47.91,Default,,0000,0000,0000,,Domain-Driven Design, I kind of touched on\Nthis talking Dialogue: 0,0:34:47.91,0:34:51.56,Default,,0000,0000,0000,,about domain objects and talking about kind\Nof bounded Dialogue: 0,0:34:51.56,0:34:53.96,Default,,0000,0000,0000,,contexts. It's a really, really good book.\NIt's really, Dialogue: 0,0:34:53.96,0:34:57.66,Default,,0000,0000,0000,,really hard to read. Eric Evans is an incredibly Dialogue: 0,0:34:57.66,0:35:00.20,Default,,0000,0000,0000,,smart guy who's not necessarily the best at\Nkind Dialogue: 0,0:35:00.20,0:35:02.97,Default,,0000,0000,0000,,of succinctly expressing ideas. Dialogue: 0,0:35:02.97,0:35:04.77,Default,,0000,0000,0000,,If you do get this book, read the second Dialogue: 0,0:35:04.77,0:35:07.53,Default,,0000,0000,0000,,half before you read the first half. He himself Dialogue: 0,0:35:07.53,0:35:09.13,Default,,0000,0000,0000,,has said he got the order around wrong in Dialogue: 0,0:35:09.13,0:35:11.17,Default,,0000,0000,0000,,retrospect. The, the second half has loads\Nof really Dialogue: 0,0:35:11.17,0:35:12.94,Default,,0000,0000,0000,,good stuff in it. The first half does too. Dialogue: 0,0:35:12.94,0:35:14.93,Default,,0000,0000,0000,,But the second half, I think, is where the Dialogue: 0,0:35:14.93,0:35:17.14,Default,,0000,0000,0000,,real, the real, real great stuff is. Dialogue: 0,0:35:17.14,0:35:20.53,Default,,0000,0000,0000,,Postel's Law. I didn't really talk about this\Nat Dialogue: 0,0:35:20.53,0:35:24.36,Default,,0000,0000,0000,,all. But if you're building SOA systems, this\Nis Dialogue: 0,0:35:24.36,0:35:27.95,Default,,0000,0000,0000,,the way that you evolve these systems over\Ntime, Dialogue: 0,0:35:27.95,0:35:31.09,Default,,0000,0000,0000,,without having to redeploy your entire enterprise\Nat once. Dialogue: 0,0:35:31.09,0:35:34.45,Default,,0000,0000,0000,,So, Postel's Law is very, very valuable. Another\Nreason Dialogue: 0,0:35:34.45,0:35:36.71,Default,,0000,0000,0000,,why the web has been so successful is Postel's Dialogue: 0,0:35:36.71,0:35:41.35,Default,,0000,0000,0000,,Law. html is incredibly permissive. It draws,\Nit causes Dialogue: 0,0:35:41.35,0:35:42.96,Default,,0000,0000,0000,,a bunch of pain, but it also is the Dialogue: 0,0:35:42.96,0:35:45.67,Default,,0000,0000,0000,,reason why html is the system that we still Dialogue: 0,0:35:45.67,0:35:46.61,Default,,0000,0000,0000,,use today. Dialogue: 0,0:35:46.61,0:35:50.15,Default,,0000,0000,0000,,Hexagonal architectures. Talked about this\Na fair bit. This Dialogue: 0,0:35:50.15,0:35:52.16,Default,,0000,0000,0000,,is a really, really important principle. I'm\Nreally excited Dialogue: 0,0:35:52.16,0:35:53.81,Default,,0000,0000,0000,,that the Rails community is starting to kind\Nof Dialogue: 0,0:35:53.81,0:35:55.78,Default,,0000,0000,0000,,get, to get excited about this. But it's been Dialogue: 0,0:35:55.78,0:35:58.34,Default,,0000,0000,0000,,around for awhile. There's loads of really\Ngood talks Dialogue: 0,0:35:58.34,0:36:01.13,Default,,0000,0000,0000,,out there about hexagonal architectures as\Nthey apply to Dialogue: 0,0:36:01.13,0:36:02.10,Default,,0000,0000,0000,,Rails. There's been a couple of talks at the Dialogue: 0,0:36:02.10,0:36:03.85,Default,,0000,0000,0000,,conference already. Dialogue: 0,0:36:03.85,0:36:05.36,Default,,0000,0000,0000,,There's a, there's a Birds of a Feather session Dialogue: 0,0:36:05.36,0:36:08.66,Default,,0000,0000,0000,,tonight about it, I believe. So there's loads\Nof Dialogue: 0,0:36:08.66,0:36:10.58,Default,,0000,0000,0000,,res- loads of good resources out there. Not\Njust Dialogue: 0,0:36:10.58,0:36:14.10,Default,,0000,0000,0000,,for Rails specifically, but just, hexagonal\Narchitectures in general. Dialogue: 0,0:36:14.10,0:36:16.74,Default,,0000,0000,0000,,Because it is a general architectural principle. Dialogue: 0,0:36:16.74,0:36:21.49,Default,,0000,0000,0000,,Finally, we should be embracing the web. It's\Nbeen Dialogue: 0,0:36:21.49,0:36:23.05,Default,,0000,0000,0000,,around for a long time. The patterns are very Dialogue: 0,0:36:23.05,0:36:26.44,Default,,0000,0000,0000,,well understood, very well established. The\Ntooling is amazingly Dialogue: 0,0:36:26.44,0:36:30.16,Default,,0000,0000,0000,,powerful. We keep on reinventing wheels. Let's\Nnot keep Dialogue: 0,0:36:30.16,0:36:32.88,Default,,0000,0000,0000,,reinventing this particular wheel. When it\Nmakes sense to Dialogue: 0,0:36:32.88,0:36:34.68,Default,,0000,0000,0000,,make the web and the principles of the web, Dialogue: 0,0:36:34.68,0:36:35.74,Default,,0000,0000,0000,,we should be doing that. Dialogue: 0,0:36:35.74,0:36:37.10,Default,,0000,0000,0000,,Thank you.