WEBVTT 00:00:17.539 --> 00:00:19.740 ERIC ROBERT: All right, hi. I'm Eric Roberts 00:00:19.740 --> 00:00:21.429 and I'm here to talk to you all about 00:00:21.429 --> 00:00:23.220 how you can use software design patterns 00:00:23.220 --> 00:00:24.939 to put your Rails app on a diet 00:00:24.939 --> 00:00:29.320 and make your tests run really, really fast. 00:00:35.700 --> 00:00:38.320 Jokes aside, we will be telling you about some 00:00:38.320 --> 00:00:41.610 design patterns. Not so much making your tests run 00:00:41.610 --> 00:00:44.559 fast. But we're here to talk about domain-driven design 00:00:44.559 --> 00:00:46.540 hexagonal architecture in Rails. 00:00:46.540 --> 00:00:48.790 I'm Eric Roberts. I'm a software developer and I 00:00:48.790 --> 00:00:52.509 work at a company in Waterloo, Ontario, Canada called 00:00:52.509 --> 00:00:56.570 Boltmade. I met Declan when we worked together at 00:00:56.570 --> 00:01:00.150 PrintChomp. Before that, I was a frontend developer for 00:01:00.150 --> 00:01:02.939 a number of years, and I'd worked around Rails 00:01:02.939 --> 00:01:06.430 applications, but mostly at the view layer until Declan 00:01:06.430 --> 00:01:09.680 dragged me kicking and screaming into backend development and 00:01:09.680 --> 00:01:12.470 made me care about stuff like we're talking about 00:01:12.470 --> 00:01:13.829 today. 00:01:13.829 --> 00:01:15.890 And this is the biggest crowd I have ever 00:01:15.890 --> 00:01:17.930 presented in front of. So if you'll excuse me, 00:01:17.930 --> 00:01:20.420 I need to take a picture and email my 00:01:20.420 --> 00:01:21.250 mom. 00:01:21.250 --> 00:01:26.820 DECLAN WHELAN: OK. Hi everybody. Real pleasure to be 00:01:26.820 --> 00:01:29.320 here. My name is Declan. I'm the co-founder of 00:01:29.320 --> 00:01:33.320 a company called PrintChomp, and my story is about 00:01:33.320 --> 00:01:36.530 two years ago, I had a opportunity to launch 00:01:36.530 --> 00:01:38.630 PrintChomp, and I was looking at technologies, and I 00:01:38.630 --> 00:01:41.030 decided that Ruby on Rails was really the best 00:01:41.030 --> 00:01:45.110 platform for us. The only challenge was that neither 00:01:45.110 --> 00:01:47.880 me nor anybody on my team knew Ruby nor 00:01:47.880 --> 00:01:48.960 Rails. 00:01:48.960 --> 00:01:52.170 So it was kind of a brave, maybe, decision, 00:01:52.170 --> 00:01:54.710 but it's one that I don't regret. And one 00:01:54.710 --> 00:01:56.590 of the things that drew me to the community 00:01:56.590 --> 00:01:58.950 was the fact that, or, to the platform, was 00:01:58.950 --> 00:02:05.260 the community around sharing, around the openness of, of, 00:02:05.260 --> 00:02:08.378 of sharing code and, also, a lot about, about 00:02:08.378 --> 00:02:12.500 the test-focus, which has been pretty important to me. 00:02:12.500 --> 00:02:14.319 But the cool part, I think, about it, was 00:02:14.319 --> 00:02:16.700 we intentionally took on a lot of technical debt, 00:02:16.700 --> 00:02:18.799 because I knew that, I knew that I would 00:02:18.799 --> 00:02:20.439 not know enough about our domain. It was a 00:02:20.439 --> 00:02:22.340 new domain for me, printing, and I also did 00:02:22.340 --> 00:02:24.790 not know enough about Ruby. I did not know 00:02:24.790 --> 00:02:28.959 about, enough about Rails. So, very intentionally decided to 00:02:28.959 --> 00:02:30.999 do our best, the best that we could, knowing 00:02:30.999 --> 00:02:33.159 that we would end up, very likely, with a 00:02:33.159 --> 00:02:36.249 pretty heaping mound of technical debt. 00:02:36.249 --> 00:02:39.599 And that turned out to be true. And has 00:02:39.599 --> 00:02:43.980 anyone had that experience? I don't know. Yeah. So, 00:02:43.980 --> 00:02:45.629 but recently we had an opportunity to build an 00:02:45.629 --> 00:02:47.849 API, and that was really exciting for me. And 00:02:47.849 --> 00:02:48.900 I know there are gonna be some other talks 00:02:48.900 --> 00:02:51.730 about APIs here later, and I realized that I 00:02:51.730 --> 00:02:54.870 had, I had two kind of competing things that 00:02:54.870 --> 00:02:57.480 could come together. The first was, I had, I 00:02:57.480 --> 00:03:00.319 had logic in our application that I needed to 00:03:00.319 --> 00:03:02.340 share in our API. How was I going to 00:03:02.340 --> 00:03:03.779 do that? 00:03:03.779 --> 00:03:07.489 And all of our code was sprinkled through various 00:03:07.489 --> 00:03:10.559 bits of our controller and model logic. Secondly, I 00:03:10.559 --> 00:03:13.430 wanted a mechanism to, to have a strategy for 00:03:13.430 --> 00:03:17.799 eliminating the technical debt, and what I turned to 00:03:17.799 --> 00:03:21.510 was domain-driven design hexagonal architectures, and I want to 00:03:21.510 --> 00:03:24.069 share what we've learnt along the way of doing 00:03:24.069 --> 00:03:26.069 that, and, and where we're going. So I hope 00:03:26.069 --> 00:03:29.900 you're able to learn something from what we've done. 00:03:29.900 --> 00:03:32.689 E.R.: That's great Declan. But what are they gonna 00:03:32.689 --> 00:03:33.629 get out of it? 00:03:33.629 --> 00:03:34.069 VIDEO 00:03:34.069 --> 00:03:37.370 ??: Here's a good idea. Have a point! Makes 00:03:37.370 --> 00:03:40.769 it so much more interesting for the listener! 00:03:40.769 --> 00:03:43.659 D.W.: Well, that was from Sandy Metz. He said, 00:03:43.659 --> 00:03:45.109 you know, if you're gonna have a talk, you 00:03:45.109 --> 00:03:46.779 should really have a point, and I think Steve 00:03:46.779 --> 00:03:50.079 Martin said it pretty funnily. And I guess, our, 00:03:50.079 --> 00:03:52.659 our number one point is that, there is complexity 00:03:52.659 --> 00:03:55.760 in the software that we build. There's complexities in 00:03:55.760 --> 00:03:57.400 the problems that we're solving. And we need to 00:03:57.400 --> 00:04:00.290 embrace that complexity and embrace it in such a 00:04:00.290 --> 00:04:02.349 way that we tackle it and deal with it. 00:04:02.349 --> 00:04:05.599 And deal with it head-on. And by doing that, 00:04:05.599 --> 00:04:07.730 then we end up having more joy and fun 00:04:07.730 --> 00:04:09.599 in our work because it's not just about getting 00:04:09.599 --> 00:04:11.969 this functional piece to work, it's about really trying 00:04:11.969 --> 00:04:14.809 to understand our domain and model it and express 00:04:14.809 --> 00:04:16.430 that in our code and make our code as 00:04:16.430 --> 00:04:18.639 expressive as possible. 00:04:18.639 --> 00:04:21.829 And the second thing that I really realized was 00:04:21.829 --> 00:04:23.690 I knew that our code was a mess, and 00:04:23.690 --> 00:04:26.590 I knew some point refactorings that we could do, 00:04:26.590 --> 00:04:28.860 but I didn't know how to, how to, you 00:04:28.860 --> 00:04:30.690 know, what did the end look like? If it 00:04:30.690 --> 00:04:33.780 was refactored significantly, what would it look like? What 00:04:33.780 --> 00:04:36.840 would the shape look like? What would the namespaces 00:04:36.840 --> 00:04:39.420 be? What would the classes be doing, et cetera. 00:04:39.420 --> 00:04:43.380 And domain-driven design and hexagonal architecture helped me envision 00:04:43.380 --> 00:04:45.100 and share with my team what it might look 00:04:45.100 --> 00:04:45.970 like. 00:04:45.970 --> 00:04:49.870 The third thing that, that, that we would like 00:04:49.870 --> 00:04:52.290 you to take away from this talk is that 00:04:52.290 --> 00:04:55.180 there's a lot more to just being a Rails 00:04:55.180 --> 00:04:58.700 developer, the, the ideas and patterns, if you will, 00:04:58.700 --> 00:05:01.340 that we, that we're talking about are, some of 00:05:01.340 --> 00:05:03.340 them have been written by some of those people 00:05:03.340 --> 00:05:08.120 that DHH had in his slide, including James Coplain. 00:05:08.120 --> 00:05:09.950 But a lot of those patterns have been around 00:05:09.950 --> 00:05:12.250 for a long time. SO those patterns and those 00:05:12.250 --> 00:05:15.820 ideas and those practices will serve you well beyond 00:05:15.820 --> 00:05:18.650 Rails. They would work in a node application. They 00:05:18.650 --> 00:05:20.680 could work in a desktop application. They can work 00:05:20.680 --> 00:05:23.260 in a wide variety of areas. So by getting 00:05:23.260 --> 00:05:26.400 some familiarity with these concepts, you're able to transfer 00:05:26.400 --> 00:05:30.090 those skills to things beyond Rails. 00:05:30.090 --> 00:05:33.180 And so I want to ask Eric just to 00:05:33.180 --> 00:05:34.810 walk us through kind of some of the, some 00:05:34.810 --> 00:05:36.720 of the pain that we had with our initial 00:05:36.720 --> 00:05:39.240 Rails development and see if it resonates with you. 00:05:39.240 --> 00:05:43.580 E.R.: All right. So everyone knows what this is. 00:05:43.580 --> 00:05:47.550 It's a Rails folder structure. And it's really great 00:05:47.550 --> 00:05:49.470 when you get started with Rails. You have these 00:05:49.470 --> 00:05:53.460 folders. OK. I, I logically, my things fall into 00:05:53.460 --> 00:05:56.300 these areas. Controllers, models, and views are really what 00:05:56.300 --> 00:05:59.240 we're focusing on right now. 00:05:59.240 --> 00:06:01.110 But if the responsibility of your code doesn't start 00:06:01.110 --> 00:06:05.110 with M, V or C, what do you do 00:06:05.110 --> 00:06:07.610 then? And we, and we find it kind of 00:06:07.610 --> 00:06:10.050 goes like this. You have, you have these areas 00:06:10.050 --> 00:06:12.970 of responsibility and you have something that doesn't really 00:06:12.970 --> 00:06:14.560 fit, and you don't know where it goes, so 00:06:14.560 --> 00:06:16.210 you just put it on somewhere and things get 00:06:16.210 --> 00:06:18.170 a little bigger. 00:06:18.170 --> 00:06:20.060 And continuing on, you keep doing this, things get 00:06:20.060 --> 00:06:23.520 bigger, and finally, like, the line between all of 00:06:23.520 --> 00:06:26.150 these things is, is blurred. You don't know what's 00:06:26.150 --> 00:06:29.500 what. It's hard to extract reusable parts from all 00:06:29.500 --> 00:06:31.810 of this, because the, the responsibilities are split across 00:06:31.810 --> 00:06:32.390 all these things. 00:06:32.390 --> 00:06:34.310 And you kind of end up with methods like 00:06:34.310 --> 00:06:37.720 this. This is one method. It starts on the 00:06:37.720 --> 00:06:40.360 left and ends on the right. It's about ninety 00:06:40.360 --> 00:06:43.370 lines. 00:06:43.370 --> 00:06:46.200 It's not from PrintChomp. It's from another, another project 00:06:46.200 --> 00:06:49.190 that I've worked on. And without setting, it doesn't 00:06:49.190 --> 00:06:51.210 really matter what it does. The point is it's 00:06:51.210 --> 00:06:55.330 ugly and you know, it is actually about setting 00:06:55.330 --> 00:06:59.750 prices on properties and the date ranges are available. 00:06:59.750 --> 00:07:03.060 So I have a question. We need to add 00:07:03.060 --> 00:07:05.140 sales tax to the prices. 00:07:05.140 --> 00:07:09.970 Anybody care to take on that refactoring? 00:07:09.970 --> 00:07:12.410 It's pretty horrible. But nobody, nobody sits down and 00:07:12.410 --> 00:07:14.270 says, I'm gonna write a ninety line method today 00:07:14.270 --> 00:07:19.590 that does property prices with date ranges. The initial 00:07:19.590 --> 00:07:23.330 spec was probably something a lot simpler. And because 00:07:23.330 --> 00:07:25.639 it's in that spot now, the next person who 00:07:25.639 --> 00:07:27.170 comes, comes and looks and that method and goes, 00:07:27.170 --> 00:07:28.500 oh, well OK, well if I just type this 00:07:28.500 --> 00:07:31.710 little bit more it'll, it'll do that now. 00:07:31.710 --> 00:07:33.870 And this was a little bit of a train 00:07:33.870 --> 00:07:36.570 wreck. At some point you probably, the people working 00:07:36.570 --> 00:07:39.300 on this, including myself, probably should have realized, you 00:07:39.300 --> 00:07:41.330 know, forty-five lines might have been the time to 00:07:41.330 --> 00:07:45.790 split it up. Maybe twenty. Maybe less. 00:07:45.790 --> 00:07:47.889 But this is, nonetheless, what we ended up with. 00:07:47.889 --> 00:07:51.120 Or, you end up with Rube Goldberg machines for 00:07:51.120 --> 00:07:53.260 sharpening pencils. 00:07:53.260 --> 00:07:56.210 So there's a lot of well-known patterns that can 00:07:56.210 --> 00:07:58.480 help you out with this. Has anyone read this 00:07:58.480 --> 00:08:03.210 blog post? Yeah. Anybody use any of the patterns 00:08:03.210 --> 00:08:04.150 in them? 00:08:04.150 --> 00:08:07.430 They're pretty great, right. We use a lot of 00:08:07.430 --> 00:08:09.450 them, and I'm, we're gonna tell you about some 00:08:09.450 --> 00:08:13.230 of them here. But the one thing you've, so 00:08:13.230 --> 00:08:16.300 you've extracted all of these things into small responsibilities. 00:08:16.300 --> 00:08:18.230 Your models, your controllers and your views. They're all 00:08:18.230 --> 00:08:19.250 small again. 00:08:19.250 --> 00:08:22.310 But, OK, so what? I have a bunch of 00:08:22.310 --> 00:08:24.889 little objects that all go, they all know too 00:08:24.889 --> 00:08:27.780 much about each other. They don't fit in any 00:08:27.780 --> 00:08:31.720 logical structure. They don't, how, how does this all 00:08:31.720 --> 00:08:35.019 fit together? You've made, like, an awesome first step, 00:08:35.019 --> 00:08:36.940 in that you have small little pieces that you 00:08:36.940 --> 00:08:40.250 can use. But where do you go from there? 00:08:40.250 --> 00:08:44.360 And we think that looks kind of like this. 00:08:44.360 --> 00:08:49.500 We think that your domain concepts, services, entities, should 00:08:49.500 --> 00:08:53.170 be in the middle, and everything else is outside. 00:08:53.170 --> 00:08:56.670 Your database is an extra concern, your views are 00:08:56.670 --> 00:08:58.889 an extra concern. The web, and you know, when 00:08:58.889 --> 00:09:01.499 you're designing the API, as Declan talked about a 00:09:01.499 --> 00:09:03.309 little bit, it's an extra concern. So you can 00:09:03.309 --> 00:09:05.550 really focus in on the middle of what your 00:09:05.550 --> 00:09:06.550 application actually does. 00:09:06.550 --> 00:09:09.339 I'm gonna let Declan talk a little bit more 00:09:09.339 --> 00:09:09.959 about that 00:09:09.959 --> 00:09:13.839 D.W.: Has anyone here heard of domain-driven design? Oh, 00:09:13.839 --> 00:09:16.009 quite a few people. Awesome. How many people have 00:09:16.009 --> 00:09:19.889 actually, you know, intentionally used it and, and have 00:09:19.889 --> 00:09:22.529 worked with it? So, a, a number. SO cool. 00:09:22.529 --> 00:09:25.680 And it can be quite, it can be quite, 00:09:25.680 --> 00:09:29.910 it can be quite daunting. And this book by 00:09:29.910 --> 00:09:31.850 Eric Evans is kind of what kicked it off. 00:09:31.850 --> 00:09:34.100 And this book was I think written in 2005, 00:09:34.100 --> 00:09:36.499 and it is a really, really great book, but 00:09:36.499 --> 00:09:39.269 it is actually quite difficult to read. But it's, 00:09:39.269 --> 00:09:41.319 I think it might be the only technical book 00:09:41.319 --> 00:09:43.040 I've read twice. 00:09:43.040 --> 00:09:44.449 And that's partly cause it was really good and 00:09:44.449 --> 00:09:47.600 partly cause it was rather difficult to get through 00:09:47.600 --> 00:09:49.259 some of it. Did anyone else read this book 00:09:49.259 --> 00:09:51.709 and have a similar experience? like, it's really great 00:09:51.709 --> 00:09:53.249 stuff and you kind of read and it and 00:09:53.249 --> 00:09:55.100 you go, wow, what does that mean to me? 00:09:55.100 --> 00:09:55.480 Right? 00:09:55.480 --> 00:09:57.920 And we, at the end, at the end, we'll 00:09:57.920 --> 00:10:00.050 be posting our deck, and we'll have some references 00:10:00.050 --> 00:10:02.230 to other material that, that I've actually found to 00:10:02.230 --> 00:10:05.170 be a bit more addressable or a little more 00:10:05.170 --> 00:10:07.350 consumable. 00:10:07.350 --> 00:10:10.550 But what Eric Evans talked about was really tackling 00:10:10.550 --> 00:10:13.490 complexity, and he talks about the, you know, the 00:10:13.490 --> 00:10:18.339 critical complexity is really understanding the domain. What are 00:10:18.339 --> 00:10:22.319 the business rules that take place inside our systems? 00:10:22.319 --> 00:10:23.680 If we're gonna add sales tax, what are the 00:10:23.680 --> 00:10:25.990 business rules for that sales tax? 00:10:25.990 --> 00:10:27.899 What are the, what are the rules around who 00:10:27.899 --> 00:10:30.740 can buy what? And by putting those insides and 00:10:30.740 --> 00:10:33.540 thinking of them as the domain of our system, 00:10:33.540 --> 00:10:36.339 then we're able to have our outside layers just 00:10:36.339 --> 00:10:42.649 be, if you will, relatively thin facades, which allows 00:10:42.649 --> 00:10:45.779 us to reuse that logic across APIs, across other 00:10:45.779 --> 00:10:48.529 applications. We don't have to duplicate all of those 00:10:48.529 --> 00:10:50.509 business rules. 00:10:50.509 --> 00:10:52.619 And the way that he proposes to do that 00:10:52.619 --> 00:10:56.480 is through ubiquitous language. And this is a picture 00:10:56.480 --> 00:10:58.920 of the tower of Babel and if anybody knows 00:10:58.920 --> 00:11:01.819 the story, it's where everyone in the world was 00:11:01.819 --> 00:11:04.850 speaking a different language and, I once worked on 00:11:04.850 --> 00:11:09.240 a project that was a financial transaction processing system, 00:11:09.240 --> 00:11:12.139 and when I inherited it, the guy who was 00:11:12.139 --> 00:11:15.579 proceeded me had this, was a model train aficionado, 00:11:15.579 --> 00:11:18.559 so he had the idea of model trains. So 00:11:18.559 --> 00:11:22.199 every transaction was like a car, and the payment 00:11:22.199 --> 00:11:25.689 engines were, were train tracks. And he had all 00:11:25.689 --> 00:11:28.829 of these metaphors around transaction processing and trains, and 00:11:28.829 --> 00:11:30.369 was written in Java. 00:11:30.369 --> 00:11:31.910 So when I was asked to add a new 00:11:31.910 --> 00:11:33.970 feature, fix a bug, I had to understand the 00:11:33.970 --> 00:11:35.879 business domain, and then I had to kind of 00:11:35.879 --> 00:11:39.059 understand, how did that translate into train speak, and 00:11:39.059 --> 00:11:40.360 then I had to go look at the Java 00:11:40.360 --> 00:11:43.369 code to figure it all out, right. So the 00:11:43.369 --> 00:11:46.240 coding was easy. The hard part was really trying 00:11:46.240 --> 00:11:48.350 to understand what was being asked and how did 00:11:48.350 --> 00:11:50.589 the code express that, right? 00:11:50.589 --> 00:11:52.149 And that's what Eric Evans is talking about with 00:11:52.149 --> 00:11:55.209 ubiquitous language. We want to have the language that 00:11:55.209 --> 00:11:58.670 we speak with domain experts should be readable in 00:11:58.670 --> 00:12:01.459 the code. If I'm order, if I'm a customer 00:12:01.459 --> 00:12:04.300 and I can purchase a product, there should be 00:12:04.300 --> 00:12:06.259 a class called customer. There should be a class 00:12:06.259 --> 00:12:08.319 called product. And there should be a verb in 00:12:08.319 --> 00:12:11.119 there that's somewhere that says purchase, et cetera. 00:12:11.119 --> 00:12:14.019 So that there's minimal translation between the domain experts' 00:12:14.019 --> 00:12:16.769 language and the language that my code is written 00:12:16.769 --> 00:12:18.959 in. Ruby gives us a great opportunity to do 00:12:18.959 --> 00:12:22.369 that, but this is much more difficult in, in 00:12:22.369 --> 00:12:26.679 other more statically typed languages. 00:12:26.679 --> 00:12:28.189 So that's kind of the, the key thing to 00:12:28.189 --> 00:12:30.999 take away from domain driven design is to try 00:12:30.999 --> 00:12:34.230 to have your, your concepts expressed in code that 00:12:34.230 --> 00:12:37.230 are meaningful in the words people use. 00:12:37.230 --> 00:12:38.449 If they use the word customer, you should have 00:12:38.449 --> 00:12:40.540 a customer class. If they use the word user, 00:12:40.540 --> 00:12:44.199 you should have a user class, et cetera. 00:12:44.199 --> 00:12:46.170 But beyond that, it also has some kind of 00:12:46.170 --> 00:12:50.339 key, I, I dare not say it, patterns? Now, 00:12:50.339 --> 00:12:53.929 I'm almost nervous now to say it. 00:12:53.929 --> 00:13:00.929 But let me be clear. This isn't science. It's 00:13:01.970 --> 00:13:05.819 not, right. Because these patterns were not dreamed up 00:13:05.819 --> 00:13:10.519 in academia ivory towers. These patterns that we talk 00:13:10.519 --> 00:13:15.170 about were empirically derived from people intentionally doing what 00:13:15.170 --> 00:13:17.899 we do, which is write code every day, intentionally 00:13:17.899 --> 00:13:20.279 thinking about, how does that, how does those, how 00:13:20.279 --> 00:13:22.119 do those things fit together, and what is the 00:13:22.119 --> 00:13:23.920 essence of what I'm doing? 00:13:23.920 --> 00:13:25.999 And can I extract that into words that I 00:13:25.999 --> 00:13:28.809 can use to communicate with other people? The beauty 00:13:28.809 --> 00:13:30.569 of patterns is I can talk about a value 00:13:30.569 --> 00:13:33.339 object, and if you know what a value object 00:13:33.339 --> 00:13:35.529 is and I know what a value object is, 00:13:35.529 --> 00:13:38.119 we can have a much richer conversation than, oh, 00:13:38.119 --> 00:13:40.079 I have to have an object whose state is, 00:13:40.079 --> 00:13:42.119 whose identity is defined by the state of its 00:13:42.119 --> 00:13:44.139 attributes and then, you know, we can have a 00:13:44.139 --> 00:13:45.420 much richer conversation. 00:13:45.420 --> 00:13:48.160 E.R.: You might say you ubiquitous language. 00:13:48.160 --> 00:13:50.420 D.W.: Yeah. So we're gonna touch a little bit 00:13:50.420 --> 00:13:53.209 on some of these patterns. But, but the idea 00:13:53.209 --> 00:13:59.230 is that these are not academic ivory tower concepts. 00:13:59.230 --> 00:14:01.420 These are empirically driven from people who've worked in 00:14:01.420 --> 00:14:03.429 the field. And if we're gonna, if we're gonna 00:14:03.429 --> 00:14:06.329 be successful as an organization, while I fully agree 00:14:06.329 --> 00:14:08.019 that we need to go out and write code 00:14:08.019 --> 00:14:09.920 and we need to read code, I totally think 00:14:09.920 --> 00:14:12.269 that's true, but we also have to have more 00:14:12.269 --> 00:14:15.509 effective ways of communicating knowledge, so that we're not 00:14:15.509 --> 00:14:17.550 all learning the same things from each other over 00:14:17.550 --> 00:14:19.300 and over. WE can learn more easily from each 00:14:19.300 --> 00:14:22.699 other. And that's what these patterns are. 00:14:22.699 --> 00:14:27.100 And the next kind of piece that we're gonna 00:14:27.100 --> 00:14:29.689 talk about is hexagonal architectures. And it's more than 00:14:29.689 --> 00:14:33.449 just that. I think we've alluded to a little 00:14:33.449 --> 00:14:36.239 bit. It's really the idea of, you're going to 00:14:36.239 --> 00:14:42.399 have this core domain in the middle, and in, 00:14:42.399 --> 00:14:45.119 inside your code, surrounding your outside core are gonna 00:14:45.119 --> 00:14:49.319 be some application level code that expresses the rules 00:14:49.319 --> 00:14:51.480 of your application. And I would draw it slightly 00:14:51.480 --> 00:14:53.949 differently, perhaps, but, and then we have adapters on 00:14:53.949 --> 00:14:56.910 the outside that adapt that code to web calls 00:14:56.910 --> 00:15:01.119 or database calls or SNTP, or in my case, 00:15:01.119 --> 00:15:01.629 APIs. 00:15:01.629 --> 00:15:03.999 And so that's the way that we want you 00:15:03.999 --> 00:15:05.639 to, that's the way that we are starting to 00:15:05.639 --> 00:15:08.129 approach the work at PrintChomp is thinking about it 00:15:08.129 --> 00:15:10.550 in those constructs. And now we want to jump 00:15:10.550 --> 00:15:13.860 to some specific patterns and, and show you some 00:15:13.860 --> 00:15:16.350 real code that actually, you know, brings these to 00:15:16.350 --> 00:15:19.660 life. So Eric, you want to talk about form 00:15:19.660 --> 00:15:19.970 object? 00:15:19.970 --> 00:15:21.769 E.R.: Sure. Unfortunately, I can't tell you what your 00:15:21.769 --> 00:15:24.139 domain is or what necessarily goes in the middle 00:15:24.139 --> 00:15:27.059 of that hexagon. But I can give you some 00:15:27.059 --> 00:15:29.879 ways to keep other things out of that hexagon 00:15:29.879 --> 00:15:32.269 that you don't need to be concerned with. 00:15:32.269 --> 00:15:34.239 One thing that I've been doing lately is form 00:15:34.239 --> 00:15:37.389 object. One of the really cool things, you know, 00:15:37.389 --> 00:15:40.350 if you run Rails scaffold, some model name, you 00:15:40.350 --> 00:15:43.069 get a form that you submit, creates the record, 00:15:43.069 --> 00:15:47.209 edits the record. And that's pretty great. 00:15:47.209 --> 00:15:49.110 But how do you do that when you don't 00:15:49.110 --> 00:15:53.220 have a direct one-one mapping with an ActiveModel record? 00:15:53.220 --> 00:15:56.829 So instead of instantiating an ActiveModel record, I've taken 00:15:56.829 --> 00:15:59.959 to instantiating, I'm gonna call it a form object. 00:15:59.959 --> 00:16:01.600 There's a lot of names for a lot of 00:16:01.600 --> 00:16:03.410 different things. But this is, this is what I've 00:16:03.410 --> 00:16:04.549 been calling it. 00:16:04.549 --> 00:16:08.009 So here's the actual thing that I was building. 00:16:08.009 --> 00:16:10.049 On the left hand side, you see that you 00:16:10.049 --> 00:16:11.999 select a ticket price. On the right hand side, 00:16:11.999 --> 00:16:15.230 your name, email address, and your payment details. And 00:16:15.230 --> 00:16:20.059 this is actually two ActiveRecord models in my database. 00:16:20.059 --> 00:16:22.939 The, the passengers over there on the right, you 00:16:22.939 --> 00:16:25.459 can add a passenger and keep adding it. 00:16:25.459 --> 00:16:27.160 And if you've ever worked with nested attributes, probably 00:16:27.160 --> 00:16:31.139 know it's not always that fun. So this is 00:16:31.139 --> 00:16:35.389 not using nested attributes. It's done like this. I 00:16:35.389 --> 00:16:39.239 have a class TicketForm that includes ActiveModel::Model, which is 00:16:39.239 --> 00:16:41.910 how I get nice things, like that magic initialize 00:16:41.910 --> 00:16:45.699 method of validators. 00:16:45.699 --> 00:16:47.839 And the passengers method, if I don't have any, 00:16:47.839 --> 00:16:50.110 returns me a passenger new. That's how it puts 00:16:50.110 --> 00:16:53.170 the name and email address for that first passenger. 00:16:53.170 --> 00:16:54.759 And then tickets, I get out of this by 00:16:54.759 --> 00:16:59.379 taking my passengers and mapping them into new objects. 00:16:59.379 --> 00:17:01.399 In the controller, it looks a little bit like 00:17:01.399 --> 00:17:04.819 this. So you just pass your params off into 00:17:04.819 --> 00:17:06.750 that. You get it back out and you have 00:17:06.750 --> 00:17:10.890 tickets. So instead of if ticket dot save, I 00:17:10.890 --> 00:17:16.099 do if ticket_form valid and ticketCharger charges successfully, then 00:17:16.099 --> 00:17:18.390 we've had success. And ticketCharge takes care of charging 00:17:18.390 --> 00:17:20.709 my tickets and knowing that, there was only, cause 00:17:20.709 --> 00:17:22.819 there's only one charge for all the tickets, right. 00:17:22.819 --> 00:17:24.930 You're paying all at once. No point to split 00:17:24.930 --> 00:17:26.450 that up. 00:17:26.450 --> 00:17:28.700 So that's a really useful thing that I've found 00:17:28.700 --> 00:17:31.790 to, to help when my mappings aren't just totally, 00:17:31.790 --> 00:17:33.250 I don't want to just take a record of 00:17:33.250 --> 00:17:35.990 the database, put it in, or update it. 00:17:35.990 --> 00:17:37.360 And now Declan's gonna tell you a little bit 00:17:37.360 --> 00:17:38.340 about request objects. 00:17:38.340 --> 00:17:40.300 D.W.: Yeah. In this case, has anyone used a 00:17:40.300 --> 00:17:42.450 form object or something like that? So quite a 00:17:42.450 --> 00:17:43.650 few people. Cool. 00:17:43.650 --> 00:17:46.500 Has, has anyone done, used something called a request 00:17:46.500 --> 00:17:50.760 object? Sort of? I was hoping that I invented 00:17:50.760 --> 00:17:53.490 this. So maybe I haven't. I don't know. OK. 00:17:53.490 --> 00:17:56.320 But, request object is now in, you know, think 00:17:56.320 --> 00:17:58.320 of an API as, we're trying to have a 00:17:58.320 --> 00:18:02.730 similar behavior to the form object, except we're trying 00:18:02.730 --> 00:18:05.170 to take, remember, we're trying to take complexity out 00:18:05.170 --> 00:18:06.770 of our controllers and out of our models and 00:18:06.770 --> 00:18:10.780 put them into more, to simplify our systems. 00:18:10.780 --> 00:18:13.870 So the idea with the request object is that 00:18:13.870 --> 00:18:15.240 we're gonna pull that code out and put it 00:18:15.240 --> 00:18:18.510 into the, into the controller. And now the request 00:18:18.510 --> 00:18:21.210 object is going to receive the request. And the 00:18:21.210 --> 00:18:23.150 code looks sort of like this, right. 00:18:23.150 --> 00:18:26.520 There's, I, I've done this slightly differently than Eric's, 00:18:26.520 --> 00:18:28.500 Eric's way, in terms of, of, the kind of 00:18:28.500 --> 00:18:29.880 the core of the class. The core of this 00:18:29.880 --> 00:18:33.310 class is using a gem called Verdis, which does 00:18:33.310 --> 00:18:38.800 something similar to ActiveModel::Model, except this allows you basically 00:18:38.800 --> 00:18:41.950 to have a plain-old Ruby object and, the way, 00:18:41.950 --> 00:18:44.720 and, the cool part is, that, or, I think 00:18:44.720 --> 00:18:47.620 it's cool. You can, you can declare attributes, like 00:18:47.620 --> 00:18:49.900 this. So I have actually, in my domain layer, 00:18:49.900 --> 00:18:51.710 I have something called the customer and the billing 00:18:51.710 --> 00:18:54.230 and the shipping. And if, if somebody supplies me 00:18:54.230 --> 00:18:56.990 those three things, then I can complete an order 00:18:56.990 --> 00:18:58.790 in my system. 00:18:58.790 --> 00:19:01.810 We've, there are a couple of pieces missing here, 00:19:01.810 --> 00:19:03.980 but we wanted to keep it, fit in a 00:19:03.980 --> 00:19:07.230 slide. But that's basically it. And we have the 00:19:07.230 --> 00:19:10.580 validation. And the cool part about this is that 00:19:10.580 --> 00:19:12.440 when a request comes in, we just, I just 00:19:12.440 --> 00:19:15.430 put in a before loop in the controller that 00:19:15.430 --> 00:19:18.380 has a before filter that just basically instantiates the 00:19:18.380 --> 00:19:23.740 request object using some, some reflection to figure out, 00:19:23.740 --> 00:19:25.920 you know, what is the, what is the controller 00:19:25.920 --> 00:19:29.660 and what is the action being asked, inferring the 00:19:29.660 --> 00:19:32.870 request class, instantiating it, and then just passing it 00:19:32.870 --> 00:19:34.900 what used to be the params hash. 00:19:34.900 --> 00:19:37.140 But now it's actually a rich object that I 00:19:37.140 --> 00:19:39.740 can have validations on, et cetera. So the net 00:19:39.740 --> 00:19:42.490 effect of this is that, why would I bother 00:19:42.490 --> 00:19:45.520 doing this, right? Well, now the controller, you know, 00:19:45.520 --> 00:19:48.100 the complexity around validating the request is at the 00:19:48.100 --> 00:19:50.490 boundary of my system. That doesn't need to leak 00:19:50.490 --> 00:19:55.640 into the rest of my system. It's almost like, 00:19:55.640 --> 00:19:57.150 you know, does anybody use, you know at the 00:19:57.150 --> 00:19:58.680 beginning of your methods, you want to put the 00:19:58.680 --> 00:20:01.100 guard clauses to catch the exceptions coming in at 00:20:01.100 --> 00:20:02.440 the beginning of your methods, so that the rest 00:20:02.440 --> 00:20:03.790 of your method is simpler? 00:20:03.790 --> 00:20:05.690 This is doing the same thing, except it's doing 00:20:05.690 --> 00:20:08.050 it at, at a higher level abstraction, at the 00:20:08.050 --> 00:20:10.110 API request level. And I, this has worked out 00:20:10.110 --> 00:20:11.950 really well for us. So I, I quite like 00:20:11.950 --> 00:20:13.820 that one. 00:20:13.820 --> 00:20:14.750 Yeah. 00:20:14.750 --> 00:20:18.230 E.R.: Great. Service objects are another one that we've 00:20:18.230 --> 00:20:21.410 been using. I think DHH actually had one in 00:20:21.410 --> 00:20:23.420 his presentation. I'll give you a hint, he didn't 00:20:23.420 --> 00:20:27.300 like it. 00:20:27.300 --> 00:20:29.900 He used one, it, it's something instantiated by the 00:20:29.900 --> 00:20:32.670 controller. We've been looking at controllers a little bit 00:20:32.670 --> 00:20:35.820 as just like, OK, I've received this thing, pass 00:20:35.820 --> 00:20:37.440 it off to somebody else, and then do something 00:20:37.440 --> 00:20:40.080 with the result. So we want to keep out 00:20:40.080 --> 00:20:42.770 that procedural code from our controllers, and service objects 00:20:42.770 --> 00:20:46.020 are one way you can do that using a 00:20:46.020 --> 00:20:49.370 order service to create orders, we've encapsulated all of 00:20:49.370 --> 00:20:53.700 the logic about how to create an order in 00:20:53.700 --> 00:20:54.270 this one area. 00:20:54.270 --> 00:20:56.070 So if you want to, you can use it 00:20:56.070 --> 00:20:57.760 from somewhere else, right. You don't have to hit 00:20:57.760 --> 00:21:01.760 a controller action to create an order. It's reusable 00:21:01.760 --> 00:21:06.870 and extendable. And it has Declan's magic repository object 00:21:06.870 --> 00:21:10.440 in there that we'll get to in a bit. 00:21:10.440 --> 00:21:14.270 And the controller, again, just, it's very simple. Do 00:21:14.270 --> 00:21:17.900 this thing, on success do this, on failure, do 00:21:17.900 --> 00:21:18.310 this. 00:21:18.310 --> 00:21:20.620 So those are a few of the patterns that 00:21:20.620 --> 00:21:25.920 we've been using to help us with this. So 00:21:25.920 --> 00:21:27.900 now what? 00:21:27.900 --> 00:21:34.550 What's, what's the elephant in the room? Anybody? 00:21:34.550 --> 00:21:41.550 How do you get them into Rails? Yeah. 00:21:45.430 --> 00:21:47.980 Yeah. That's the one we were thinking of. 00:21:47.980 --> 00:21:50.520 D.W.: That's, ActiveRecord. Yeah. I mean, I mean, the 00:21:50.520 --> 00:21:52.960 end, and how do you get into Rails. Yes, 00:21:52.960 --> 00:21:55.890 there are some interesting challenges around that. But I'm 00:21:55.890 --> 00:21:57.900 gonna flip you back to the architectural slide and 00:21:57.900 --> 00:22:00.750 just point out that you see what's happened here 00:22:00.750 --> 00:22:04.190 is that we're trying to view the application pieces 00:22:04.190 --> 00:22:07.190 of our solution here being really on the perimeter 00:22:07.190 --> 00:22:09.740 of our core system. And the core system composed 00:22:09.740 --> 00:22:13.980 of services that may be servicing API or application 00:22:13.980 --> 00:22:16.210 requests. 00:22:16.210 --> 00:22:19.260 We have some services that may be invariant across 00:22:19.260 --> 00:22:21.460 any call, and those would be at the very 00:22:21.460 --> 00:22:23.620 center. And we have things called entities which are 00:22:23.620 --> 00:22:26.440 on the inside. And the key part that's, that 00:22:26.440 --> 00:22:28.760 we haven't talked about, which actually I'm planning the 00:22:28.760 --> 00:22:32.250 most difficult part in this is this repository which 00:22:32.250 --> 00:22:33.800 is the bottom, which is the r in the 00:22:33.800 --> 00:22:35.570 bottom right hand corner. 00:22:35.570 --> 00:22:37.870 And it's job is to talk to the ActiveRecord 00:22:37.870 --> 00:22:39.730 model which is in the green, and create an 00:22:39.730 --> 00:22:42.280 entity object which is the blue object, and, and 00:22:42.280 --> 00:22:45.480 how does that actually work? So I'm gonna show 00:22:45.480 --> 00:22:48.500 you a bit of code, and this is, this 00:22:48.500 --> 00:22:50.860 is the first time I've shown my Ruby code 00:22:50.860 --> 00:22:52.420 in public. So please be kind. 00:22:52.420 --> 00:22:55.290 And there are probably way better ways to do 00:22:55.290 --> 00:22:58.650 this. but this is the repository that I've, I've, 00:22:58.650 --> 00:22:59.710 there are some other methods here, but I just 00:22:59.710 --> 00:23:01.980 wanted to fit on what happen, you know, show 00:23:01.980 --> 00:23:03.810 you the simple one. 00:23:03.810 --> 00:23:05.690 So this is what a save looks like. So 00:23:05.690 --> 00:23:08.830 the save takes a domain object and it converts 00:23:08.830 --> 00:23:11.140 it through something called a mapper, which maps the 00:23:11.140 --> 00:23:15.440 domain object onto a ActiveRecord object, which is called 00:23:15.440 --> 00:23:18.610 a record here. Then I, then it calls record 00:23:18.610 --> 00:23:22.400 dot save, assigns the id and returns the response. 00:23:22.400 --> 00:23:25.060 So that's pretty straightforward. All that's really happened is, 00:23:25.060 --> 00:23:26.390 and I really tried to do this and so 00:23:26.390 --> 00:23:28.290 far I've been able to, I don't want to 00:23:28.290 --> 00:23:31.010 have domain dot save. I want to have repository 00:23:31.010 --> 00:23:34.400 dot save domain, so that there's no persistence that's 00:23:34.400 --> 00:23:38.250 leaking into my domain objects. Persistence, I want to 00:23:38.250 --> 00:23:40.830 be a secondary concern to what that object is 00:23:40.830 --> 00:23:41.520 really doing. 00:23:41.520 --> 00:23:44.140 And so far, it's worked, although sometimes it's caused 00:23:44.140 --> 00:23:48.040 me some difficulty. The method messing down there is 00:23:48.040 --> 00:23:51.710 kind of cool. At least I think it's cool. 00:23:51.710 --> 00:23:54.500 And what it's doing is it's introducing a scope 00:23:54.500 --> 00:23:55.970 object, which I'll show you in a, well here's 00:23:55.970 --> 00:23:57.900 the scope object. That's OK. 00:23:57.900 --> 00:23:59.650 And it creates a scope object, and this was 00:23:59.650 --> 00:24:01.630 the trickiest code that I had to write, but 00:24:01.630 --> 00:24:03.900 what it does, what it, the end result of 00:24:03.900 --> 00:24:06.970 this code is, that allows you to chain call 00:24:06.970 --> 00:24:11.090 any of your ActiveRecord find methods of your scopes 00:24:11.090 --> 00:24:13.400 and chain them together. So you can now use, 00:24:13.400 --> 00:24:16.030 so in other words, with this logic, wherever you 00:24:16.030 --> 00:24:22.010 have like ActiveRecord dot, you know, find where id 00:24:22.010 --> 00:24:24.720 greater than 122 is activated and so on, wherever 00:24:24.720 --> 00:24:26.310 you might have a chain like that, you can 00:24:26.310 --> 00:24:28.570 still use that chain now because of this scope 00:24:28.570 --> 00:24:30.430 class with your domain objects. 00:24:30.430 --> 00:24:33.740 Except, instead of getting back your ActiveRecord object, you're 00:24:33.740 --> 00:24:38.000 getting back its domain representation. Does that make sense? 00:24:38.000 --> 00:24:38.600 yeah? 00:24:38.600 --> 00:24:41.180 OK. And then the mapper is what maps them 00:24:41.180 --> 00:24:43.950 across, right. And some cases, the mapping is like 00:24:43.950 --> 00:24:47.440 really, really simple. What's the next slide here? Oh, 00:24:47.440 --> 00:24:49.660 yeah. Yeah. There it is right there. 00:24:49.660 --> 00:24:51.830 So the mapper, because of the way vertice works 00:24:51.830 --> 00:24:55.030 and the way ActiveRecord works with attributes, you can 00:24:55.030 --> 00:24:57.940 almost just instantiate one from the other just passing 00:24:57.940 --> 00:25:00.280 the attributes back and forth. So it's actually quite 00:25:00.280 --> 00:25:04.040 easy except when it's not easy, and then what 00:25:04.040 --> 00:25:06.740 happens, what I'm doing now is just, wherever I 00:25:06.740 --> 00:25:09.260 have something that doesn't fit this model, I just 00:25:09.260 --> 00:25:12.030 subclass this mapper with a custom mapper and override 00:25:12.030 --> 00:25:13.650 those methods, more or less. 00:25:13.650 --> 00:25:17.360 And that's the part that I think there, would 00:25:17.360 --> 00:25:19.580 be more expressive ways to do that mapping and 00:25:19.580 --> 00:25:22.220 that's what I'm starting to look at now. But 00:25:22.220 --> 00:25:25.160 so far this has actually worked pretty well. 00:25:25.160 --> 00:25:27.830 And it's allowed me to completely separate the way 00:25:27.830 --> 00:25:30.540 I think about persistence from the way I think 00:25:30.540 --> 00:25:32.930 about my domain object. SO we before we, before 00:25:32.930 --> 00:25:34.910 I had this, we had, used to have an 00:25:34.910 --> 00:25:37.160 order class, and I kid you not, and I'm 00:25:37.160 --> 00:25:39.660 in, I'm a Rails noob so you can shoot 00:25:39.660 --> 00:25:44.650 me, but it had forty-eight attributes in the ActiveRecord::Model, 00:25:44.650 --> 00:25:45.540 right. 00:25:45.540 --> 00:25:48.380 That is now represented by about eight classes that 00:25:48.380 --> 00:25:50.960 separate out all the different aspects of the order, 00:25:50.960 --> 00:25:56.970 like the shipping, the billing, et cetera, et cetera. 00:25:56.970 --> 00:25:58.920 So that, but I think this mapping is, is, 00:25:58.920 --> 00:26:01.690 is, is one of the more challenging parts. And 00:26:01.690 --> 00:26:05.180 then finally, you now I've, then you quickly run 00:26:05.180 --> 00:26:09.890 into things like, oh, well what happens if I 00:26:09.890 --> 00:26:12.240 get the record. I get the record, I save 00:26:12.240 --> 00:26:13.640 it, then I save it again. I have to 00:26:13.640 --> 00:26:15.070 be able to keep track that I've saved it 00:26:15.070 --> 00:26:16.470 once already. 00:26:16.470 --> 00:26:18.380 So that I don't have multiple copies around. And 00:26:18.380 --> 00:26:20.490 this is an identity map. In fact, an identity 00:26:20.490 --> 00:26:25.250 map was built into Rails and I think it 00:26:25.250 --> 00:26:26.950 might, I don't, I don't work in Rails 4, 00:26:26.950 --> 00:26:29.030 but I think it might be taken out or, 00:26:29.030 --> 00:26:31.480 or changed slightly. But actually, on the next slide 00:26:31.480 --> 00:26:33.330 I'll show you what the identity map looks like, 00:26:33.330 --> 00:26:34.900 and this, actually, I stole from Rails and made 00:26:34.900 --> 00:26:36.510 it a bit simpler. 00:26:36.510 --> 00:26:37.830 But all it's doing is just making sure that 00:26:37.830 --> 00:26:42.150 there's a unique instance on, on a per-API request 00:26:42.150 --> 00:26:46.160 call for each entity object. So that I, I 00:26:46.160 --> 00:26:47.780 can, and it actually serves as a really cheap 00:26:47.780 --> 00:26:50.890 cache, but that's not what it's intent is. 00:26:50.890 --> 00:26:54.130 So, so that's kind of where, where we're, where 00:26:54.130 --> 00:26:57.430 I'm going now, is most of those service object, 00:26:57.430 --> 00:26:59.050 form object, request, those all kind of work well 00:26:59.050 --> 00:27:00.980 for us, and I'm not looking at what would 00:27:00.980 --> 00:27:04.190 a repository pattern look like fleshed out. And that 00:27:04.190 --> 00:27:06.080 is, by far, the most challenging piece. 00:27:06.080 --> 00:27:08.630 But I heard a question about where you put 00:27:08.630 --> 00:27:11.040 things. You can really just put them anywhere. You 00:27:11.040 --> 00:27:13.630 know. That's the thing, like, Rails just seems to 00:27:13.630 --> 00:27:17.820 be, there's a part that's, I just felt constrained. 00:27:17.820 --> 00:27:20.520 Like, Rails didn't give me any guidance on where 00:27:20.520 --> 00:27:22.300 do I put a service socket. Well, you can 00:27:22.300 --> 00:27:24.260 really put it anywhere you like. You could put 00:27:24.260 --> 00:27:26.030 it on the auto load path or you can 00:27:26.030 --> 00:27:28.520 put it where Rails might expect to see it. 00:27:28.520 --> 00:27:30.270 But it, you can just create a services directory 00:27:30.270 --> 00:27:32.070 and put your service objects there. Rails will find 00:27:32.070 --> 00:27:34.890 it. It's not hard. But Rails doesn't really kind 00:27:34.890 --> 00:27:36.710 of tell you what to do. So it doesn't 00:27:36.710 --> 00:27:39.390 make it easy to do these, to think of 00:27:39.390 --> 00:27:42.000 it, but it actually, it's not hard. 00:27:42.000 --> 00:27:45.090 And but that's where we're going with that, and 00:27:45.090 --> 00:27:46.940 we'll, we'll give you a link to it, to, 00:27:46.940 --> 00:27:48.970 I've started a Git Repo where I plan to 00:27:48.970 --> 00:27:51.100 share some of these ideas, and if you're interested 00:27:51.100 --> 00:27:53.380 in sharing ideas with us on that, we'll, we'll 00:27:53.380 --> 00:27:58.020 be happy to talk to you or, or join 00:27:58.020 --> 00:27:59.730 us on the, on the Git Repo. 00:27:59.730 --> 00:28:04.820 E.R.: Right. So what's the point, again? At the 00:28:04.820 --> 00:28:10.580 start, we had these three things. Embrace complexity. Getting, 00:28:10.580 --> 00:28:14.640 getting the solution to work is only part of 00:28:14.640 --> 00:28:18.090 the fun, right? It's, it's your first draft, as 00:28:18.090 --> 00:28:20.490 DHH said, talking about writing. You get, you do 00:28:20.490 --> 00:28:24.630 it over and over. And getting things to work, 00:28:24.630 --> 00:28:27.950 that ninety-line method I showed earlier, that worked. But 00:28:27.950 --> 00:28:31.050 does anyone want to go back and use that 00:28:31.050 --> 00:28:33.580 again? It's no, it's no fun to revisit, unless 00:28:33.580 --> 00:28:36.530 you're improving it, which, I did do eventually and, 00:28:36.530 --> 00:28:40.990 and now it's much nicer to work with. That, 00:28:40.990 --> 00:28:44.400 that's fun. At least, we think that's fun. Getting 00:28:44.400 --> 00:28:46.600 beyond the problem and getting it to a level 00:28:46.600 --> 00:28:49.340 where we actually don't mind going into our code, 00:28:49.340 --> 00:28:52.700 extending things, and changing things. 00:28:52.700 --> 00:28:54.890 And we do that by breaking them up into 00:28:54.890 --> 00:28:57.550 the smaller parts with the patterns that we've talked 00:28:57.550 --> 00:28:57.980 about. 00:28:57.980 --> 00:29:00.830 Knowing where you're going. In Alice in Wonderland, paraphrase, 00:29:00.830 --> 00:29:03.320 they said if you don't know where you're going, 00:29:03.320 --> 00:29:06.550 any road will take you there. We think it's 00:29:06.550 --> 00:29:08.460 important to know where you're going and pick a 00:29:08.460 --> 00:29:10.120 road that you think will take you there. It 00:29:10.120 --> 00:29:12.030 doesn't have to be our road. These are things 00:29:12.030 --> 00:29:14.850 that helped us, and, and we think they're good 00:29:14.850 --> 00:29:17.390 ideas. But it's not gonna solve every problem for 00:29:17.390 --> 00:29:21.220 everyone. These aren't rules. Like Declan said, they're not 00:29:21.220 --> 00:29:22.830 science. You can't just take them and throw them 00:29:22.830 --> 00:29:25.380 on and expect that your code will magically get 00:29:25.380 --> 00:29:28.320 better by going on a diet. 00:29:28.320 --> 00:29:31.230 And be more than just a Rails developer. Not 00:29:31.230 --> 00:29:33.810 that it's bad to be a Rails developer, but 00:29:33.810 --> 00:29:40.810 these things apply across, across languages and stuff. Like, 00:29:41.370 --> 00:29:45.370 don't just learn Ruby. Learn, learn beyond that. So 00:29:45.370 --> 00:29:49.360 as Declan mentioned, we have this GitHUb that we've 00:29:49.360 --> 00:29:51.980 set up, and right now it's just a readme. 00:29:51.980 --> 00:29:54.540 We don't actually have the code in their yet. 00:29:54.540 --> 00:29:56.300 We'll likely put some of the code we showed 00:29:56.300 --> 00:29:58.920 today, especially the repository bits. 00:29:58.920 --> 00:30:02.180 But we'd love to continue the discussion via issues, 00:30:02.180 --> 00:30:05.750 pull requests, whatever. That would be awesome. And, and 00:30:05.750 --> 00:30:07.000 we'd love to talk to you about some of 00:30:07.000 --> 00:30:10.530 it throughout this week as well. In fact, I'm 00:30:10.530 --> 00:30:15.130 gonna also mentioned, we have reading. You'll be able 00:30:15.130 --> 00:30:18.070 to get these slides after, so I'm just gonna 00:30:18.070 --> 00:30:19.070 gloss over them. 00:30:19.070 --> 00:30:21.690 These are a couple of the books that we've 00:30:21.690 --> 00:30:23.210 taken a look at to help us out with 00:30:23.210 --> 00:30:23.940 these things. 00:30:23.940 --> 00:30:26.420 D.W.: I think the crowd has spoken and it's 00:30:26.420 --> 00:30:28.990 time to wrap up. If you want to come 00:30:28.990 --> 00:30:31.370 up and talk, I'm happy to answer your questions. 00:30:31.370 --> 00:30:32.870 Thank you.