0:00:17.190,0:00:19.160 STEPHAN HAGEMANN: Thanks for coming. 0:00:19.160,0:00:21.130 You came to Big Rails. 0:00:21.130,0:00:23.190 If you did not intend to go to Big Rails. 0:00:23.190,0:00:24.890 My wife's actually currently in a plane, 0:00:24.890,0:00:27.630 and so for some reason I had to think of a[br]plane metaphor. 0:00:27.630,0:00:29.350 And her flight just got canceled. 0:00:29.350,0:00:30.360 If you did not intend to go to Big 0:00:30.360,0:00:33.140 Rails, which I can understand. It can be messy. 0:00:33.140,0:00:37.750 Better get out now, the flight might be bumpy. 0:00:37.750,0:00:39.640 So I want to talk about really large Rails 0:00:39.640,0:00:41.840 apps, and my buddy Austin suggested, a couple[br]days 0:00:41.840,0:00:45.730 ago, let's use GitHub. Search for Rails. Sort[br]by 0:00:45.730,0:00:49.050 size. This is officially the biggest Rails[br]app you've 0:00:49.050,0:00:52.059 never heard of on GitHub. It's open source.[br]It 0:00:52.059,0:00:55.269 also only has eight models. Which is because[br]they 0:00:55.269,0:00:56.260 upload all their assets. 0:00:56.260,0:00:58.050 It's a hundred and fifty megabytes big, and[br]that's 0:00:58.050,0:01:01.230 not the kind of big I'm talking about. I 0:01:01.230,0:01:05.430 want to talk about component-based Rails architectures[br]and why 0:01:05.430,0:01:09.430 you should refactor towards them. And how[br]to do 0:01:09.430,0:01:11.770 that. 0:01:11.770,0:01:15.130 Component-based Rails architectures is a term[br]I use. I 0:01:15.130,0:01:19.020 tag my Tweets about it as #cbra, and I'm 0:01:19.020,0:01:20.360 the only person in the world doing it. But 0:01:20.360,0:01:24.590 if you use that too, I'm certainly replying.[br]And, 0:01:24.590,0:01:27.510 here's a memo for that. 0:01:27.510,0:01:32.410 If I can get one idea in straight off 0:01:32.410,0:01:35.720 the bat, then it is that this is, this 0:01:35.720,0:01:38.510 stuff is easy. If you can think about your 0:01:38.510,0:01:41.500 application by writing, by painting boxes[br]and drawing arrows 0:01:41.500,0:01:43.920 for things that depend on each other and how 0:01:43.920,0:01:47.040 they interact, then you know everything else[br]you need 0:01:47.040,0:01:50.040 to know about component-based architectures[br]and you just need 0:01:50.040,0:01:52.770 to start doing them to what I think will 0:01:52.770,0:01:55.560 be improving the quality of your application[br]and the 0:01:55.560,0:01:57.680 quality of your code. 0:01:57.680,0:02:01.390 Since I called this talk refactoring towards[br]component-based Rails 0:02:01.390,0:02:03.360 architectures, this talk assumes that you[br]all know what 0:02:03.360,0:02:06.420 that is. So, no. I will actually explain what 0:02:06.420,0:02:07.450 that is to you. You're not screwed if you 0:02:07.450,0:02:09.758 don't know what that is. 0:02:09.758,0:02:14.810 So, I started talking and actually writing[br]applications pretty 0:02:14.810,0:02:19.310 much exclusively in this kind of odd way,[br]so, 0:02:19.310,0:02:23.480 like, two, three years ago. And it, I wrote 0:02:23.480,0:02:26.090 this sample app that you find at this address. 0:02:26.090,0:02:29.900 I'm shageman with one n on GitHub. And there's 0:02:29.900,0:02:32.590 just the_next_big_thing sample app. 0:02:32.590,0:02:35.510 It does nothing. Only it shows you the structure 0:02:35.510,0:02:37.450 and how to hook certain things up. And let 0:02:37.450,0:02:40.060 me quickly go through what that means. So[br]this 0:02:40.060,0:02:42.540 is the root of the project. And, as you 0:02:42.540,0:02:45.410 can see, it's not a Rails application. But[br]it 0:02:45.410,0:02:47.810 is. There's actually no particular prescribed[br]way on how 0:02:47.810,0:02:50.150 to do this. In many apps where I've done 0:02:50.150,0:02:51.870 this, the Rails application is still at the[br]root 0:02:51.870,0:02:54.120 of the project. But in this particular one,[br]I 0:02:54.120,0:02:56.700 chose the other version, where Rails moves[br]into a 0:02:56.700,0:02:58.940 sub-folder and, as you can see here, so this 0:02:58.940,0:03:02.550 looks pretty much like Rails. But it doesn't[br]have 0:03:02.550,0:03:05.080 an app folder. There, and you might be asking, 0:03:05.080,0:03:06.880 is there nothing happening in this app? 0:03:06.880,0:03:10.209 Well, there is. Here, we see there's, at least 0:03:10.209,0:03:12.240 one thing is mounted. There is an engine that's 0:03:12.240,0:03:18.250 mounted. So, Teaser::Engine. I don't know[br]if anyone has 0:03:18.250,0:03:21.260 ever downloaded that from RubyGems. Well,[br]don't try. I 0:03:21.260,0:03:22.640 don't know what that gem would be. But I 0:03:22.640,0:03:23.990 didn't upload it there. 0:03:23.990,0:03:25.430 Let's look at the gem file to find out 0:03:25.430,0:03:28.280 what that gem is. So this is the, the 0:03:28.280,0:03:30.270 only kind of trick that you need to employ 0:03:30.270,0:03:33.700 when you want to write component-based architectures.[br]And that 0:03:33.700,0:03:36.310 is, you use gems as not a, not as 0:03:36.310,0:03:39.060 a distribution mechanism, but just as a packaging[br]mechanism 0:03:39.060,0:03:41.430 for parts of your application. 0:03:41.430,0:03:43.400 You leave them in the same source tree and 0:03:43.400,0:03:45.620 you just reference them. And then you can[br]do 0:03:45.620,0:03:47.700 everything you're used to with those things. 0:03:47.700,0:03:49.489 So, as you can see here, if we go 0:03:49.489,0:03:51.430 to the components folder, we expect to see[br]a 0:03:51.430,0:03:53.489 teaser folder. Ah. Which we do. And there[br]is 0:03:53.489,0:03:56.020 an engine. So that's just a Rails. Ah, sorry. 0:03:56.020,0:03:58.700 A RubyGem that is pimped a little bit so 0:03:58.700,0:04:02.900 it has Active star. All the Actives. So Rails 0:04:02.900,0:04:05.650 in it. And this, indeed, now looks like an 0:04:05.650,0:04:06.670 application. 0:04:06.670,0:04:09.730 If you don't know what an engine is, it's 0:04:09.730,0:04:12.099 essentially Rails minus everything you need[br]to actually get 0:04:12.099,0:04:15.800 it booted. So, if we look in here, what 0:04:15.800,0:04:18.279 we can see, you know, there's a routes file 0:04:18.279,0:04:21.199 and this engine is doing something, right.[br]There's. It's 0:04:21.199,0:04:23.960 normal. Here we'll look in apps. So the controller. 0:04:23.960,0:04:26.400 So you can see this is namespaced under the 0:04:26.400,0:04:28.930 name, which is nice. But it's just, you know, 0:04:28.930,0:04:32.789 your ordinary controller. But, again, everything's[br]namespaced. 0:04:32.789,0:04:38.220 There's assets in here. Yeah. This is pretty[br]normal, 0:04:38.220,0:04:42.620 standard stuff. We even have migrations down[br]here in 0:04:42.620,0:04:45.510 this engine. What else would I talk about?[br]Well, 0:04:45.510,0:04:48.190 ah, yes. Maybe the coolest part. There's specs[br]in 0:04:48.190,0:04:49.990 here. I like to use rSpec. That could be 0:04:49.990,0:04:52.220 tests in here if you're doing this and liking 0:04:52.220,0:04:53.330 those better. 0:04:53.330,0:04:57.980 But there's, there's a spec here for this[br]controller 0:04:57.980,0:05:00.080 that I just looked at, and the cool thing 0:05:00.080,0:05:02.540 about that, and I don't know how to emphasize 0:05:02.540,0:05:04.000 it more than to come up to the front 0:05:04.000,0:05:07.340 of the stage and say it's very important that 0:05:07.340,0:05:09.240 I can run these tests, and the only thing 0:05:09.240,0:05:11.300 that these tests are gonna load is the code 0:05:11.300,0:05:13.600 from this engine, and not from all the other 0:05:13.600,0:05:16.490 stuff in my Big Rails application. 0:05:16.490,0:05:20.090 So, just by there being a spec folder in 0:05:20.090,0:05:21.800 here, I have a part of which I can 0:05:21.800,0:05:24.650 prove that it is small. Or, at least, as 0:05:24.650,0:05:26.620 big as only this part, and not depending on 0:05:26.620,0:05:28.710 anything else. 0:05:28.710,0:05:33.100 I, for, what I typically do, then, to kind 0:05:33.100,0:05:36.100 of bind these components together - and there's[br]more 0:05:36.100,0:05:37.840 in this folder, as you can see. There's this 0:05:37.840,0:05:40.300 event counter signup and whatnot. So I write[br]a 0:05:40.300,0:05:42.290 little script here that binds all the tests.[br]As 0:05:42.290,0:05:43.840 you can see there's some request specs and[br]some 0:05:43.840,0:05:46.320 Jasmine specs, and if you look into the other 0:05:46.320,0:05:49.490 folders, you find more of these test files.[br]And 0:05:49.490,0:05:54.169 then in the root. I typically put this, this 0:05:54.169,0:05:56.500 build script here. And what this does is loops 0:05:56.500,0:05:58.449 over all the folders and tries to find test 0:05:58.449,0:05:59.320 files and runs them. 0:05:59.320,0:06:01.330 So you can still run this as the app, 0:06:01.330,0:06:03.449 as the specs to one application. But if you 0:06:03.449,0:06:05.229 just change one part, you can just test that 0:06:05.229,0:06:08.699 one part and still be sure that it works. 0:06:08.699,0:06:11.590 So, now that you know what these applications[br]are, 0:06:11.590,0:06:13.190 you don't need to think about all those little 0:06:13.190,0:06:14.780 things. How to hook them up. You'll find out 0:06:14.780,0:06:16.410 about that when you try to do it. What's 0:06:16.410,0:06:17.630 important about them is that you can now talk 0:06:17.630,0:06:22.280 about your application as a sum of smaller[br]parts. 0:06:22.280,0:06:24.030 For example, the app that I just showed you 0:06:24.030,0:06:26.759 is a empty Rails container that mounts an[br]engine 0:06:26.759,0:06:28.259 that uses two other engines that I didn't[br]talk 0:06:28.259,0:06:30.110 about and another gem. 0:06:30.110,0:06:31.900 This is a project that it recently, it o- 0:06:31.900,0:06:34.389 that was a tiny project, so this was Tiny 0:06:34.389,0:06:37.650 Rails. Empty Rails container. Two engines.[br]The one was 0:06:37.650,0:06:40.660 using two gems to talk to APIs, and the 0:06:40.660,0:06:45.290 other one was just straight-up, pretty much[br]normal application. 0:06:45.290,0:06:47.320 Or this site that was a travel site. It 0:06:47.320,0:06:49.780 was so small, we didn't even bother to use 0:06:49.780,0:06:51.620 engines. We just put a couple gems in there 0:06:51.620,0:06:53.630 that were talking to APIs. 0:06:53.630,0:06:55.889 This site was a bit bigger. It started out 0:06:55.889,0:06:59.080 like this. We had six engines, one gem, and 0:06:59.080,0:07:01.139 it ended up about like this. But this is 0:07:01.139,0:07:03.150 a lie, because there were about twice as many 0:07:03.150,0:07:05.440 engines, only the other ones are abstracted[br]away for 0:07:05.440,0:07:07.060 clarity in this picture. As you can see, it's 0:07:07.060,0:07:08.150 a very clear picture. 0:07:08.150,0:07:12.210 Now, this looks chaotic. But the fact that[br]I 0:07:12.210,0:07:14.770 can draw such a chaotic picture about your[br]application, 0:07:14.770,0:07:16.680 but if you, if you were to draw the 0:07:16.680,0:07:19.220 arrows a bit straighter, you would see that[br]the 0:07:19.220,0:07:23.009 dependencies all go in one direction, and[br]that there 0:07:23.009,0:07:25.500 are parts that other parts are based upon,[br]right. 0:07:25.500,0:07:28.330 So this app is composed of parts, and it's 0:07:28.330,0:07:31.360 no longer a ball of mud. 0:07:31.360,0:07:32.690 The fact that you can see that this is 0:07:32.690,0:07:36.539 a complicated domain is an improvement, despite[br]this picture 0:07:36.539,0:07:38.220 looking a bit weird. This picture is from[br]Ben 0:07:38.220,0:07:41.180 Smith's talk about how he architected his[br]Big Rails 0:07:41.180,0:07:43.630 app for success, which he gave at Rocky Mountain 0:07:43.630,0:07:46.630 Ruby last year. And I recommend you watch[br]that 0:07:46.630,0:07:47.550 talk. 0:07:47.550,0:07:51.139 So, if you're like, what? Now? Why would I 0:07:51.139,0:07:53.610 do that? As I just said. Because it helps. 0:07:53.610,0:07:57.160 When applications get big, I believe it's[br]fundamentally important 0:07:57.160,0:07:58.949 to be able to think about the parts of 0:07:58.949,0:08:04.919 the application independently, as much as[br]possible. 0:08:04.919,0:08:08.259 There's a bunch of resources that, you know.[br]I've 0:08:08.259,0:08:10.430 given talks about this. Ben's given talks[br]about this. 0:08:10.430,0:08:13.300 There's blog posts about this. And there's,[br]most importantly, 0:08:13.300,0:08:16.729 that repository that I recommend you look[br]at. 0:08:16.729,0:08:22.509 OK. Back to Big Rails. How big? Does anyone 0:08:22.509,0:08:25.039 here think they're working on a big Rails[br]application? 0:08:25.039,0:08:29.910 OK. That's about a third. So, I've, I think 0:08:29.910,0:08:31.590 I've worked on a couple, but I didn't know 0:08:31.590,0:08:33.818 what to show, because I work for Pivatol Labs 0:08:33.818,0:08:36.198 and we consult and the code is our clients', 0:08:36.198,0:08:38.509 so I can't show it here, so I won't. 0:08:38.509,0:08:41.130 But I went onto this thing called Google and 0:08:41.130,0:08:43.289 I searched for open source Rails apps, and[br]there 0:08:43.289,0:08:45.350 they were. So these claim to be big Rails 0:08:45.350,0:08:45.940 apps. 0:08:45.940,0:08:50.060 How big, I wondered. Well, if you have, currently, 0:08:50.060,0:08:53.660 on your laptop, your company's code, please,[br]execute this 0:08:53.660,0:08:57.279 script and Tweet the result with a #cbra hashtag, 0:08:57.279,0:08:58.930 cause this is just gonna open how many lines 0:08:58.930,0:09:00.630 of code your app has. 0:09:00.630,0:09:03.420 And here's the result for this list of applications. 0:09:03.420,0:09:06.580 So, as you can see, they're not all simi- 0:09:06.580,0:09:09.890 not all the same interpretation of big. So[br]we're 0:09:09.890,0:09:13.910 going from about 400,000 lines of code to[br]still 0:09:13.910,0:09:17.000 in the thousands. If you look at the files, 0:09:17.000,0:09:20.770 same picture. Thousands of files for the biggest[br]apps, 0:09:20.770,0:09:24.660 and still hundreds for the smaller ones. 0:09:24.660,0:09:28.300 I'll accept that as big. And I hope you 0:09:28.300,0:09:32.910 will too. Ever wonder what happens to the[br]complexity 0:09:32.910,0:09:37.110 within a system as it grows? Something like[br]this 0:09:37.110,0:09:40.390 happens. And maybe this is bad as that, and 0:09:40.390,0:09:43.649 you just can't take it anymore. 0:09:43.649,0:09:46.700 When you introduce structure, you fundamentally[br]change the game. 0:09:46.700,0:09:49.899 Oh. I'm supposed to say, first, that this[br]is 0:09:49.899,0:09:52.860 because the number of interactions between[br]the elements inside 0:09:52.860,0:09:56.370 the system grows somewhat like an exponential,[br]in an 0:09:56.370,0:10:00.089 exponential function when you add new, new[br]parts to 0:10:00.089,0:10:01.830 this system. 0:10:01.830,0:10:06.230 So it explodes in complexity. Well, what if[br]you 0:10:06.230,0:10:11.290 were able to split a system and use a 0:10:11.290,0:10:14.600 complex web of service objects, maybe, to[br]connect the 0:10:14.600,0:10:17.010 two. But you have two smaller parts that can 0:10:17.010,0:10:20.200 now, that are now isolated, in some way, what 0:10:20.200,0:10:21.510 happens to the complexity? 0:10:21.510,0:10:26.440 Well, turns out, it's still this, and probably[br]still 0:10:26.440,0:10:33.440 that. But only half as fast. And that's good. 0:10:35.760,0:10:37.430 If you. I wish I could run up to 0:10:37.430,0:10:39.310 the slide right now. But, you see that green 0:10:39.310,0:10:42.160 line at the bottom? It's almost flat. Now[br]imagine 0:10:42.160,0:10:44.680 you could split it again, and again, and again, 0:10:44.680,0:10:46.700 and you always stay in this flatter part,[br]so 0:10:46.700,0:10:50.040 your complexity never really explodes. You[br]get those crazy 0:10:50.040,0:10:52.320 diagrams that I was showing earlier, but your[br]complexity 0:10:52.320,0:10:55.060 doesn't explode quite as badly. You're still[br]writing a 0:10:55.060,0:10:57.200 huge app, and that's something that I'm not[br]gonna 0:10:57.200,0:11:00.010 discuss away. But you might be able to manage 0:11:00.010,0:11:06.480 it better. 0:11:06.480,0:11:11.260 The rich get rich and the poor get. Anyone? 0:11:11.260,0:11:17.420 Children. I. This is from a song from the 0:11:17.420,0:11:20.100 1920s, and while it's funny, the, the first[br]part 0:11:20.100,0:11:25.660 of this alludes to a thing called preferential[br]attachment. 0:11:25.660,0:11:29.200 Preferential attachment is a set of processes[br]where, when, 0:11:29.200,0:11:33.350 where, god. This is so hard to say. Where, 0:11:33.350,0:11:36.630 when you, where the amount of things you have, 0:11:36.630,0:11:38.230 whatever that might be - the thing, or you 0:11:38.230,0:11:42.899 - defines how much you will get. 0:11:42.899,0:11:47.830 So, 2006, Chris Anderson I think, wrote about[br]the 0:11:47.830,0:11:51.420 long tail in, in publishing and books. And[br]he, 0:11:51.420,0:11:53.870 this, this curve became very popular. He called,[br]I 0:11:53.870,0:11:55.600 think he even called the book The Long Tail. 0:11:55.600,0:11:57.160 And he was concentrated on the right side[br]of 0:11:57.160,0:11:58.930 this tail. 0:11:58.930,0:12:00.790 So you have many, many small things that don't 0:12:00.790,0:12:04.540 get any traction. But, you know, Netflix allows[br]us 0:12:04.540,0:12:06.870 to view all those movies that no one wants, 0:12:06.870,0:12:08.930 that no one else wants to see. But there's 0:12:08.930,0:12:11.370 just a very few movies at the front that 0:12:11.370,0:12:14.410 everyone wants to see. The Blockbusters. And,[br]while the 0:12:14.410,0:12:17.440 long tail is very interesting, it's the ones[br]in 0:12:17.440,0:12:22.760 the front that harvest most of the benefits,[br]well 0:12:22.760,0:12:24.700 I guess in the case of movies. 0:12:24.700,0:12:27.519 So, the green to the yellow relationship is[br]about, 0:12:27.519,0:12:32.829 80% of the, the tail versus 20% is inverse 0:12:32.829,0:12:34.769 in the relationship to how much they have.[br]So 0:12:34.769,0:12:38.500 it's 20/80, 80/20. 0:12:38.500,0:12:43.209 And, preferential attachment, as I said, happens[br]when you 0:12:43.209,0:12:45.910 already have a lot, so you get more. And 0:12:45.910,0:12:48.350 I have seen so many code bases that I 0:12:48.350,0:12:50.140 have the feeling there's something like that[br]going on 0:12:50.140,0:12:52.750 in code. So I looked at these code bases, 0:12:52.750,0:12:56.180 and again, I typed in this bash script. First 0:12:56.180,0:13:00.670 try of course. 0:13:00.670,0:13:02.230 And I urge you to do the same. Now, 0:13:02.230,0:13:04.029 you will not be able to Tweet this, because 0:13:04.029,0:13:06.579 this lists all the files, all the Ruby files, 0:13:06.579,0:13:10.790 in your app by size. And when you do 0:13:10.790,0:13:14.730 that, that looks about like this for these[br]applications. 0:13:14.730,0:13:19.860 Now, does that not look similar? 0:13:19.860,0:13:22.040 There's another way of saying this, you know,[br]the 0:13:22.040,0:13:24.700 rich get richer. There's a German proverb.[br]I'm from 0:13:24.700,0:13:29.860 Germany. Hi. That proverb is that Der Teufel[br]scheißt 0:13:29.860,0:13:32.310 immer auf den größten Haufen. Or, the Devil[br]always 0:13:32.310,0:13:35.560 shits on the biggest pile. 0:13:35.560,0:13:39.089 And I think something like that is going on 0:13:39.089,0:13:46.089 here. And which file might that be? So who 0:13:46.440,0:13:48.010 thinks that might be a good guess as to 0:13:48.010,0:13:51.700 which file that is? And, lower your, don't[br]lower 0:13:51.700,0:13:54.290 your hand, because it's probably actually[br]yours. I said 0:13:54.290,0:13:55.839 this two days ago and then the guy next 0:13:55.839,0:13:57.870 to me shows me his Ruby, his user file 0:13:57.870,0:14:00.160 and it's literally this long and I'm like,[br]oh 0:14:00.160,0:14:02.170 god, don't do this to me. 0:14:02.170,0:14:04.550 But everyone else knows this problem. The[br]user is 0:14:04.550,0:14:07.420 around earlier. He is important to the system,[br]so 0:14:07.420,0:14:10.950 he attaches, he attracts functionality. But[br]to the point 0:14:10.950,0:14:13.100 where I would say that is a pile of 0:14:13.100,0:14:15.310 shit, man. 0:14:15.310,0:14:19.570 And I thought that would be something else[br]I 0:14:19.570,0:14:22.420 could find. So I looked at associations. Associations[br]are 0:14:22.420,0:14:28.510 another way of expressing dependencies. In[br]fact, so when, 0:14:28.510,0:14:30.250 I want to talk about has_manys, because I[br]find 0:14:30.250,0:14:31.730 them particularly interesting. 0:14:31.730,0:14:38.730 So, you have something that has_many. User,[br]maybe. So 0:14:40.360,0:14:42.130 since I assumed it was user, I want you 0:14:42.130,0:14:45.029 to read this code and, kind of reflecting[br]on 0:14:45.029,0:14:48.950 yesterday's keynote, I find this file very[br]readable. The 0:14:48.950,0:14:55.810 user has_many :cars, :flowers, :trees, :houses,[br]:moods, :checks. Hopefully. 0:14:55.810,0:14:57.360 I think we can agree that it's very readable. 0:14:57.360,0:15:00.040 It makes a lot of sense and we can, 0:15:00.040,0:15:01.850 we can empathize with this class. 0:15:01.850,0:15:04.389 Have you ever wondered what's funny about[br]this when 0:15:04.389,0:15:05.769 you look at the table and there is no 0:15:05.769,0:15:09.019 mention of :cars, :flowers, :trees, :houses,[br]:moods, and :checks 0:15:09.019,0:15:13.000 in that table at all? You don't find it 0:15:13.000,0:15:14.779 funny to write that user class, but would[br]you 0:15:14.779,0:15:16.570 find it funny if I wrote a color class 0:15:16.570,0:15:18.750 like that? 0:15:18.750,0:15:20.060 Why do we not write that color class? Why 0:15:20.060,0:15:22.329 do we always write that user class? I'll tell 0:15:22.329,0:15:24.950 you why. Because users are important to us,[br]and 0:15:24.950,0:15:26.970 we always write them first, and then we attach 0:15:26.970,0:15:30.290 all sorts of stuff to them that doesn't belong 0:15:30.290,0:15:34.579 to them. This table clearly says what belongs[br]to, 0:15:34.579,0:15:37.399 sorry, a user. Namely, in this case, a name 0:15:37.399,0:15:39.880 and a home. 0:15:39.880,0:15:42.500 So I've kind of gotten the opinion that we 0:15:42.500,0:15:47.329 shouldn't be using has_many too much. You[br]can check, 0:15:47.329,0:15:49.220 and I would be very interested in the results, 0:15:49.220,0:15:52.560 again, so there's another gist. Please, try[br]it out 0:15:52.560,0:15:55.880 if you can. 0:15:55.880,0:16:02.639 Whoops. And guess which file is on the left? 0:16:02.639,0:16:07.170 Yeah. He shat on that again. The, it's the 0:16:07.170,0:16:10.740 user. And it's ot always actually the user.[br]I 0:16:10.740,0:16:13.470 shouldn't be saying that. I should say, it's[br]probably 0:16:13.470,0:16:15.810 always, to some extent, the user. But what's[br]your 0:16:15.810,0:16:21.079 domain? If your domain is, I don't know, money? 0:16:21.079,0:16:25.730 Houses? Properties? I don't know. It's probably[br]that file. 0:16:25.730,0:16:28.010 Whatever I just said or whatever is in your 0:16:28.010,0:16:30.300 name. That's that file. 0:16:30.300,0:16:32.160 And that attracts all the functionality. But[br]the user 0:16:32.160,0:16:36.040 is typically not far behind. And, because[br]I want 0:16:36.040,0:16:39.070 to. Yeah, I just. I think this is very 0:16:39.070,0:16:41.079 enlightening. So, I just opened to the project[br]I 0:16:41.079,0:16:43.029 just showed you. I opened all the user files, 0:16:43.029,0:16:46.220 and I'm just gonna scroll through them, K. 0:16:46.220,0:16:53.220 This is not very intimidating. Eh. This is[br]a 0:16:54.579,0:17:01.510 bit better. Ooh. I'm trying to be non-discriminatory[br]here 0:17:01.510,0:17:08.510 and go the same speed 0:17:15.130,0:17:15.599 all the time. Ooh. 0:17:15.599,0:17:22.378 Oh. Oh you wait. Now, I have to speed 0:17:22.378,0:17:26.039 up. 0:17:26.039,0:17:29.509 And it's, you, this one file looks particularly[br]bad 0:17:29.509,0:17:32.789 maybe, but it's probably the case that these[br]user 0:17:32.789,0:17:36.119 files are big to the extent that their applications 0:17:36.119,0:17:40.999 are big. These files just tend to do that. 0:17:40.999,0:17:44.359 These models just attract that. 0:17:44.359,0:17:51.359 So, what does that mean? 0:17:51.549,0:17:53.850 To recap. We have things that grow, and when 0:17:53.850,0:17:56.619 they grow, they get exponentially more, they[br]get more 0:17:56.619,0:17:59.879 complex. They get exponentially more complex.[br]And then in 0:17:59.879,0:18:01.399 those things, there are certain things that[br]are, you 0:18:01.399,0:18:05.700 know, that are the top of the badness scale. 0:18:05.700,0:18:09.879 And, and those things that also depend on[br]everything 0:18:09.879,0:18:15.859 else in the system. 0:18:15.859,0:18:22.100 I don't know. I think we can do better. 0:18:22.100,0:18:24.479 We can try to reduce the size of the 0:18:24.479,0:18:28.210 parts. Maybe flatten out that curve and reduce[br]the 0:18:28.210,0:18:34.859 number of dependencies in between those parts.[br]Something that 0:18:34.859,0:18:38.429 has helped me in doing that has been Solid, 0:18:38.429,0:18:45.159 the five ideas, principles. Signs, truths.[br]I don't know. 0:18:45.159,0:18:45.840 No. 0:18:45.840,0:18:48.950 And especially for this problem, the Single[br]Responsibility Principle. 0:18:48.950,0:18:52.859 I think if you just apply that as a 0:18:52.859,0:18:56.409 rule of thumb, as a, as a starter for 0:18:56.409,0:19:00.739 a conversation, it will, over time, on average,[br]improve 0:19:00.739,0:19:04.119 the quality of your code. But I think there's 0:19:04.119,0:19:06.859 something funny going on when we discuss single[br]responsibility. 0:19:06.859,0:19:10.999 Oh. Yes. What's single responsibility for?[br]To find things 0:19:10.999,0:19:17.999 that don't belong. Clearly it's the cat with[br]the 0:19:18.239,0:19:21.179 green eyes. 0:19:21.179,0:19:27.889 Where, where to apply Single Responsibility[br]Principle? If you've 0:19:27.889,0:19:29.489 been to any of the refactoring talks - I 0:19:29.489,0:19:31.190 didn't have a chance this time - but I'm 0:19:31.190,0:19:35.509 pretty sure you refactored some methods. We[br]look at 0:19:35.509,0:19:37.679 methods, we want them to be better. We make 0:19:37.679,0:19:40.210 them smaller. We find what they are about[br]and 0:19:40.210,0:19:44.249 we give them one responsibility. Class. We[br]probably did 0:19:44.249,0:19:46.639 the same, right. We look at a class, we're 0:19:46.639,0:19:48.909 like, oh, this does a little bit much. But 0:19:48.909,0:19:51.159 then we're like, OK, ActiveRecord is cool.[br]I'm like, 0:19:51.159,0:19:53.739 allowing it to save itself and soforth. So[br]maybe 0:19:53.739,0:19:55.519 that's OK. But it still kind of should be 0:19:55.519,0:19:57.799 about this one thing. 0:19:57.799,0:19:59.629 Except for user. 0:19:59.629,0:20:01.309 So we're, on these two levels, I think we're 0:20:01.309,0:20:06.600 really good. Module, and by that I mean a 0:20:06.600,0:20:08.929 namespace. If you use module as mixin, I get 0:20:08.929,0:20:10.769 like that I don't want to talk about that, 0:20:10.769,0:20:13.970 and that's why I continue to say namespace.[br]Why 0:20:13.970,0:20:15.720 do I think this about mixins? I should maybe 0:20:15.720,0:20:18.559 explain in one sentence. If you mixin stuff[br]into 0:20:18.559,0:20:21.159 your objects, the only thing you're doing[br]is hiding 0:20:21.159,0:20:23.190 away the fact that you have more complexity[br]than 0:20:23.190,0:20:24.869 you can bear to look at on one screen, 0:20:24.869,0:20:26.129 so you put it on another so you don't 0:20:26.129,0:20:29.179 have to see it. I would not do that. 0:20:29.179,0:20:31.119 I mean, I have done it. I have written 0:20:31.119,0:20:32.929 apps like that, and now I hate myself for 0:20:32.929,0:20:35.210 it. But, I want to not do it anymore. 0:20:35.210,0:20:37.749 So I think we shouldn't. So I use modules 0:20:37.749,0:20:42.289 a lot, but as namespaces, to group things[br]together. 0:20:42.289,0:20:44.489 I think you should do that. You know, look 0:20:44.489,0:20:47.450 at modules or namespaces and, and analyze[br]whether they 0:20:47.450,0:20:51.970 have one responsibility. But have you done[br]that lately? 0:20:51.970,0:20:54.099 It's harder, right? It doesn't mean a lot.[br]You 0:20:54.099,0:20:55.919 can, it doesn't, you know, no one cares if 0:20:55.919,0:20:57.909 you go across these things. You just, you[br]can 0:20:57.909,0:21:01.789 load any class anyways. 0:21:01.789,0:21:05.909 So I think we could get better at that. 0:21:05.909,0:21:09.149 Let me jump a level. Application. And I think, 0:21:09.149,0:21:11.169 again, you should. And the fact that we have 0:21:11.169,0:21:13.220 this Big Rails track, and the fact that I'm 0:21:13.220,0:21:15.499 talking about components, but pretty much[br]everyone else is 0:21:15.499,0:21:19.200 talking about SOAs, shows that we are talking[br]about, 0:21:19.200,0:21:21.879 what do applications mean? What does it mean[br]for 0:21:21.879,0:21:25.419 an application to do something? Or, yeah.[br]To have 0:21:25.419,0:21:27.849 a function in, in something bigger. 0:21:27.849,0:21:30.519 So, I encourage you to go to all those 0:21:30.519,0:21:34.039 tracks and make your applications better on[br]that level 0:21:34.039,0:21:35.889 as well. But I just talked to you about 0:21:35.889,0:21:37.919 the component, and I think that sits in the 0:21:37.919,0:21:40.749 middle. And in, in a certain way, the component 0:21:40.749,0:21:44.039 is, is an improved namespace. Because of that[br]thing 0:21:44.039,0:21:46.299 I said earlier, namely, I can run tests and 0:21:46.299,0:21:48.739 I can prove that those tests run without ever 0:21:48.739,0:21:52.399 touching any code that is not in that namespace. 0:21:52.399,0:21:56.799 So, now you can. And I urge you to 0:21:56.799,0:22:02.019 do it. Because the cat picture, the discussion[br]of 0:22:02.019,0:22:04.950 what doesn't belong. If you are in your Big 0:22:04.950,0:22:07.879 Rails app and you're writ- painting all those[br]classes 0:22:07.879,0:22:10.789 as boxes and the dependencies they have as[br]arrows, 0:22:10.789,0:22:14.700 first off, it's really easy to screw that[br]up. 0:22:14.700,0:22:16.389 Because there's no, you can't really prove[br]that you're 0:22:16.389,0:22:18.309 not using another class. At least not in run 0:22:18.309,0:22:21.519 time with big applications. 0:22:21.519,0:22:25.789 So components give you an arbitrarily scalable[br]and provably 0:22:25.789,0:22:29.509 independent way to talk about parts of your[br]application. 0:22:29.509,0:22:32.690 So I use it. Now, I said you should 0:22:32.690,0:22:36.099 look at SOAs, and when, if you're considering[br]refactoring 0:22:36.099,0:22:38.389 your application to improve its quality and[br]to make 0:22:38.389,0:22:40.470 it more maintainable, I think there are a[br]couple 0:22:40.470,0:22:45.080 things you should know about or consider when[br]deciding 0:22:45.080,0:22:47.729 between the two. Right, you're kind of feeling[br]pains 0:22:47.729,0:22:50.559 right now, or you're not even yet feeling[br]pains. 0:22:50.559,0:22:53.249 Great place to be in, too. But there's a 0:22:53.249,0:22:55.529 couple things that are really cool about just[br]splitting 0:22:55.529,0:22:57.379 up your application into these components. 0:22:57.379,0:23:01.489 And that is, you stick with one repo. You 0:23:01.489,0:23:04.399 have one test suite. But you can split it 0:23:04.399,0:23:07.899 up. You have, still, one deployment. You can,[br]however, 0:23:07.899,0:23:11.279 use, like, a load balancer to push traffic[br]to 0:23:11.279,0:23:13.849 certain parts of the application to make the[br]one 0:23:13.849,0:23:16.340 faster, the other, you know, has less of a 0:23:16.340,0:23:19.590 demand or, you know, you can go crazy. But 0:23:19.590,0:23:21.929 you don't get these additional versioning[br]constraints of where, 0:23:21.929,0:23:23.799 like, if you, if you have this app and 0:23:23.799,0:23:25.519 it needs that app and that app doesn't have 0:23:25.519,0:23:27.619 the API yet, then I need to add this 0:23:27.619,0:23:30.450 stuff here at the same time, and I need 0:23:30.450,0:23:31.690 to deploy them at the same time. And if 0:23:31.690,0:23:33.799 I didn't do that then everything goes down. 0:23:33.799,0:23:35.210 You don't have that because you're still talking[br]about 0:23:35.210,0:23:40.099 one application. And also, one other thing[br]that's very 0:23:40.099,0:23:41.830 interesting to me, at least, is that, I never 0:23:41.830,0:23:45.099 know which parts I need. On this crazy graph 0:23:45.099,0:23:47.379 project that I just showed you, it went on 0:23:47.379,0:23:50.450 for about six months. And, and there were[br]three 0:23:50.450,0:23:53.539 pairs on that. And at some point. Four pairs. 0:23:53.539,0:23:55.090 And at some point, there was always one pair 0:23:55.090,0:23:57.940 refactoring something. And they created, I[br]think there were 0:23:57.940,0:24:00.179 a couple weeks where they created basically[br]a component 0:24:00.179,0:24:02.519 a day. But they also removed a component. 0:24:02.519,0:24:03.929 Try to do that with a SOA. Try to 0:24:03.929,0:24:06.349 move that stuff around quickly. You can do[br]a 0:24:06.349,0:24:09.669 SOA, I think, when you, when you're sure you 0:24:09.669,0:24:12.409 need pieces. But when you're playing around[br]with parts 0:24:12.409,0:24:14.529 of your application and you, you want to just 0:24:14.529,0:24:16.009 structure it, and you want to still be able 0:24:16.009,0:24:18.840 to move a part from one to the other, 0:24:18.840,0:24:21.369 SOA is a bit heavy. 0:24:21.369,0:24:26.690 Within a SOA, you can still think about your 0:24:26.690,0:24:29.929 applications as being built of these components.[br]There's, you 0:24:29.929,0:24:34.129 know, nothing is exclusive there. Just do[br]both. 0:24:34.129,0:24:41.129 So, I've now spent about, most of my time 0:24:41.499,0:24:44.299 telling you why you should refactor towards[br]this. But 0:24:44.299,0:24:45.840 I haven't done what I said in my title 0:24:45.840,0:24:47.309 I would do, namely tell you how to refactor 0:24:47.309,0:24:51.469 towards it. I'm sorry about that. But I gave 0:24:51.469,0:24:55.429 you this idea, right. And you all believed[br]me. 0:24:55.429,0:24:58.659 This is easy. 0:24:58.659,0:25:01.769 Today's day of the, International Day of the[br]Book. 0:25:01.769,0:25:06.869 I looked in these books. Refactoring to Patterns.[br]Refactoring. 0:25:06.869,0:25:10.849 Awesome books. But they don't talk about this[br]either. 0:25:10.849,0:25:12.379 And I think the reason is that this stuff 0:25:12.379,0:25:15.429 is not very important in other languages.[br]In Java, 0:25:15.429,0:25:17.759 you do packages every day and you have implicit 0:25:17.759,0:25:20.070 imports. In Go, you do that. Other languages[br]do 0:25:20.070,0:25:22.859 not have this problem, because other languages[br]do not 0:25:22.859,0:25:25.580 allow for this kind of freedom and openness[br]that 0:25:25.580,0:25:31.210 we've gotten because we do Ruby. 0:25:31.210,0:25:35.259 So, I call these two refactorings, teasing[br]out an 0:25:35.259,0:25:39.090 app component and extracting a functional[br]component. And the 0:25:39.090,0:25:40.259 reason I don't want to spend much time on 0:25:40.259,0:25:42.049 it is because it's actually very simple to[br]do 0:25:42.049,0:25:46.429 it. The devil's just in the details. 0:25:46.429,0:25:48.969 And there is no book about this. But I'm 0:25:48.969,0:25:52.219 trying to write one. And if you, I don't 0:25:52.219,0:25:54.469 know, show, if you're interested in this,[br]send a 0:25:54.469,0:25:56.440 message there and I might be more inclined[br]to 0:25:56.440,0:25:58.059 actually sit down. 0:25:58.059,0:26:01.789 All right. But to the first one - teasing 0:26:01.789,0:26:08.729 out an app component. So, step zero. Got tests? 0:26:08.729,0:26:11.099 If, if you don't have tests, I wouldn't move 0:26:11.099,0:26:13.590 as much code as we're about to move. I 0:26:13.590,0:26:16.710 mean, virtually. But, you should add some[br]tests around 0:26:16.710,0:26:19.190 the stuff that you want to extract. 0:26:19.190,0:26:21.479 And then you, for the app component. So that's 0:26:21.479,0:26:24.539 this teaser thing we looked at. So we're,[br]a 0:26:24.539,0:26:27.119 component of your application, where you almost[br]thing, this 0:26:27.119,0:26:30.070 could be its own application, maybe. So you[br]look 0:26:30.070,0:26:35.139 for this vertical. Views, controllers, models.[br]You find that 0:26:35.139,0:26:38.149 vertical that makes sense on its own and you 0:26:38.149,0:26:39.479 namespace it. 0:26:39.479,0:26:42.059 A funny thing happens when you just namespace[br]it. 0:26:42.059,0:26:44.609 Suddenly, the things in there. Well, first[br]off, what's 0:26:44.609,0:26:46.369 awful about it is you have to rename all 0:26:46.369,0:26:49.479 your tables. OK. But that aside, you suddenly[br]start 0:26:49.479,0:26:53.499 seeing what's actually in your vertical and[br]what's not. 0:26:53.499,0:26:55.379 You could actually put colon colon in front[br]of 0:26:55.379,0:26:56.849 everything else that's not, and you would[br]get a 0:26:56.849,0:26:59.719 really easy view parsing or, or way of seeing 0:26:59.719,0:27:02.269 in your files what's not in your vertical. 0:27:02.269,0:27:06.200 Those are your external dependencies to, an[br]external to 0:27:06.200,0:27:08.259 the app. So when you do this at first, 0:27:08.259,0:27:09.929 you're apps gonna be unhappy. So please make[br]your 0:27:09.929,0:27:12.889 tests green. And to do that, you will need 0:27:12.889,0:27:15.340 to find other parts that you didn't know you 0:27:15.340,0:27:19.899 depended upon, and you move them into what's[br]gonna 0:27:19.899,0:27:25.379 be the component. Into this vertical. 0:27:25.379,0:27:28.599 And when you got this vertical green, you[br]extract 0:27:28.599,0:27:34.139 it into an engine. Extracting into an engine[br]is 0:27:34.139,0:27:37.519 rails plugin new component dash dash full,[br]dash dash 0:27:37.519,0:27:39.659 mountable. In most cases. 0:27:39.659,0:27:41.239 It doesn't matter. 0:27:41.239,0:27:48.239 And step three, profit. Now, most of the time, 0:27:49.460,0:27:52.200 this vertical will not be as easy to find 0:27:52.200,0:27:55.330 as I just pretended it would be. And that's 0:27:55.330,0:28:01.519 because of, you guessed it, user. Right? The[br]user 0:28:01.519,0:28:05.419 is probably somewhere, and other things as[br]well, are 0:28:05.419,0:28:08.589 used somewhere, are needed somewhere, but[br]don't really belong 0:28:08.589,0:28:09.940 to this verticle. 0:28:09.940,0:28:13.119 And what I've found is when you refactor towards 0:28:13.119,0:28:14.979 this, if you abstract. If you, if you're coming 0:28:14.979,0:28:17.649 from one big piece, if you want to abstract 0:28:17.649,0:28:20.570 one thing, you're gonna abstract two. The[br]one thing 0:28:20.570,0:28:24.200 you wanted and the common stuff. But please[br]do 0:28:24.200,0:28:26.339 not call that stuff common, because that's[br]just gonna 0:28:26.339,0:28:28.219 be another pile of shit that you can attach 0:28:28.219,0:28:30.169 stuff to. Call it something else. Call it[br]user 0:28:30.169,0:28:34.210 if you have to. 0:28:34.210,0:28:36.049 So this special case is not a special case. 0:28:36.049,0:28:38.460 I think this is, of course there is lots 0:28:38.460,0:28:40.529 of meat in how to do this and where 0:28:40.529,0:28:43.029 you get hung up on certain gem dependencies[br]and 0:28:43.029,0:28:45.210 engines not doing it exactly the way that[br]Rails 0:28:45.210,0:28:48.019 does it and blah, blah, blah. But essentially[br]this 0:28:48.019,0:28:52.139 is it. 0:28:52.139,0:28:55.109 The other side to this is, is, something even 0:28:55.109,0:29:01.839 more interesting. It's abstracting functional[br]components. Now your app 0:29:01.839,0:29:05.469 is round, suddenly. I don't know why. Again,[br]got 0:29:05.469,0:29:08.759 tests? Let's start there. 0:29:08.759,0:29:11.200 So you find a functional component, and yes,[br]I 0:29:11.200,0:29:14.029 made that much smaller than that verticle.[br]Because typically 0:29:14.029,0:29:16.239 you find a piece that is really, really separate. 0:29:16.239,0:29:20.369 A very special functionality. Maybe even something[br]mathematically a 0:29:20.369,0:29:23.839 function. In and out. Some processing. You[br]find that 0:29:23.839,0:29:27.909 and you create a gem. 0:29:27.909,0:29:30.109 And you move the tests in there as well, 0:29:30.109,0:29:31.960 and your gem is, when you run those tests, 0:29:31.960,0:29:34.440 the gem's gonna be unhappy, because of all[br]those 0:29:34.440,0:29:38.219 dependencies that you didn't see coming. So,[br]you take 0:29:38.219,0:29:42.419 all those and you move them in. And you 0:29:42.419,0:29:44.539 make your tests happy. 0:29:44.539,0:29:47.489 Well, and now you require that gem in the 0:29:47.489,0:29:50.349 main app, and your main app is totally unhappy. 0:29:50.349,0:29:51.719 Because it doesn't know how to talk to that 0:29:51.719,0:29:57.950 gem anymore. And if there were any ActiveRecord[br]dependencies, 0:29:57.950,0:30:00.690 or other dependencies on, on stuff that came[br]from 0:30:00.690,0:30:03.659 Rails, I would urge you to try and keep 0:30:03.659,0:30:06.139 that out of, of these kinds of gems, because 0:30:06.139,0:30:08.200 it just adds such a huge surface area and 0:30:08.200,0:30:11.339 stuff that could happen, could be done and[br]could 0:30:11.339,0:30:12.139 go wrong. 0:30:12.139,0:30:15.299 I, I would urge you to find these connections, 0:30:15.299,0:30:20.629 these, the shims, maybe. Call them ports and[br]adapters. 0:30:20.629,0:30:23.419 And move them in the app closer to the 0:30:23.419,0:30:25.799 surface area of this gem, so that you can 0:30:25.799,0:30:28.309 do the processing of whatever that is there,[br]and 0:30:28.309,0:30:30.969 that talks to the gem and makes it work 0:30:30.969,0:30:33.580 again. So now the app is happy. And you 0:30:33.580,0:30:37.080 got this weird kind of lump on the side. 0:30:37.080,0:30:38.349 But that's a good thing. 0:30:38.349,0:30:40.739 In, in one of the books, actually I think 0:30:40.739,0:30:42.909 it's Eric Evans, it's called Bound to Context.[br]Now 0:30:42.909,0:30:45.440 you have a thing that is only relevant for 0:30:45.440,0:30:49.639 a context. But that's how you take from that, 0:30:49.639,0:30:52.450 from that curve that has the huge left side. 0:30:52.450,0:30:54.149 That's how you chip away at the top and 0:30:54.149,0:30:56.529 put it somewhere at the end. Because this[br]thing, 0:30:56.529,0:30:59.149 in a bound context, it only has one meaning. 0:30:59.149,0:31:00.599 And that's why it's gonna be smaller. 0:31:00.599,0:31:07.599 So, step three. Profit. 0:31:07.820,0:31:14.299 I hope that made sense. And I know. It 0:31:14.299,0:31:16.649 doesn't work that easily. It's not five steps.[br]It 0:31:16.649,0:31:19.609 can take weeks. The first time we tried this, 0:31:19.609,0:31:22.089 it took three attempts and four weeks in one 0:31:22.089,0:31:24.759 app that we wanted to split into two. And 0:31:24.759,0:31:26.889 we ended up with three, and now I think 0:31:26.889,0:31:30.169 it's about ten. But, trust me, you can get 0:31:30.169,0:31:30.820 there. 0:31:30.820,0:31:35.570 And I kind of felt challenged by Far- by 0:31:35.570,0:31:40.489 Farrah's keynote yesterday. So, I will help.[br]If you 0:31:40.489,0:31:42.330 want to attempt this, and you don't find the 0:31:42.330,0:31:44.279 resources and any of those links that I gave 0:31:44.279,0:31:47.089 you, Tweet at me, talk to me, send me 0:31:47.089,0:31:49.669 an email. I'll respond to all of them. Maybe 0:31:49.669,0:31:53.389 publicly so it helps others, too. I just think 0:31:53.389,0:31:55.769 this is a great way to structure applications[br]and 0:31:55.769,0:31:58.269 to make them better, and that's why I just 0:31:58.269,0:32:00.769 will help. 0:32:00.769,0:32:04.330 So don't let these guys ruin your day. Make 0:32:04.330,0:32:06.609 friends with the #cbra, and thanks for your[br]attention.