1 00:00:17,539 --> 00:00:19,740 ERIC ROBERT: All right, hi. I'm Eric Roberts 2 00:00:19,740 --> 00:00:21,429 and I'm here to talk to you all about 3 00:00:21,429 --> 00:00:23,220 how you can use software design patterns 4 00:00:23,220 --> 00:00:24,939 to put your Rails app on a diet 5 00:00:24,939 --> 00:00:29,320 and make your tests run really, really fast. 6 00:00:35,700 --> 00:00:38,320 Jokes aside, we will be telling you about some 7 00:00:38,320 --> 00:00:41,610 design patterns. Not so much making your tests run 8 00:00:41,610 --> 00:00:44,559 fast. But we're here to talk about domain-driven design 9 00:00:44,559 --> 00:00:46,540 hexagonal architecture in Rails. 10 00:00:46,540 --> 00:00:48,790 I'm Eric Roberts. I'm a software developer and I 11 00:00:48,790 --> 00:00:52,509 work at a company in Waterloo, Ontario, Canada called 12 00:00:52,509 --> 00:00:56,570 Boltmade. I met Declan when we worked together at 13 00:00:56,570 --> 00:01:00,150 PrintChomp. Before that, I was a frontend developer for 14 00:01:00,150 --> 00:01:02,939 a number of years, and I'd worked around Rails 15 00:01:02,939 --> 00:01:06,430 applications, but mostly at the view layer until Declan 16 00:01:06,430 --> 00:01:09,680 dragged me kicking and screaming into backend development and 17 00:01:09,680 --> 00:01:12,470 made me care about stuff like we're talking about 18 00:01:12,470 --> 00:01:13,829 today. 19 00:01:13,829 --> 00:01:15,890 And this is the biggest crowd I have ever 20 00:01:15,890 --> 00:01:17,930 presented in front of. So if you'll excuse me, 21 00:01:17,930 --> 00:01:20,420 I need to take a picture and email my 22 00:01:20,420 --> 00:01:21,250 mom. 23 00:01:21,250 --> 00:01:26,820 DECLAN WHELAN: OK. Hi everybody. Real pleasure to be 24 00:01:26,820 --> 00:01:29,320 here. My name is Declan. I'm the co-founder of 25 00:01:29,320 --> 00:01:33,320 a company called PrintChomp, and my story is about 26 00:01:33,320 --> 00:01:36,530 two years ago, I had a opportunity to launch 27 00:01:36,530 --> 00:01:38,630 PrintChomp, and I was looking at technologies, and I 28 00:01:38,630 --> 00:01:41,030 decided that Ruby on Rails was really the best 29 00:01:41,030 --> 00:01:45,110 platform for us. The only challenge was that neither 30 00:01:45,110 --> 00:01:47,880 me nor anybody on my team knew Ruby nor 31 00:01:47,880 --> 00:01:48,960 Rails. 32 00:01:48,960 --> 00:01:52,170 So it was kind of a brave, maybe, decision, 33 00:01:52,170 --> 00:01:54,710 but it's one that I don't regret. And one 34 00:01:54,710 --> 00:01:56,590 of the things that drew me to the community 35 00:01:56,590 --> 00:01:58,950 was the fact that, or, to the platform, was 36 00:01:58,950 --> 00:02:05,260 the community around sharing, around the openness of, of, 37 00:02:05,260 --> 00:02:08,378 of sharing code and, also, a lot about, about 38 00:02:08,378 --> 00:02:12,500 the test-focus, which has been pretty important to me. 39 00:02:12,500 --> 00:02:14,319 But the cool part, I think, about it, was 40 00:02:14,319 --> 00:02:16,700 we intentionally took on a lot of technical debt, 41 00:02:16,700 --> 00:02:18,799 because I knew that, I knew that I would 42 00:02:18,799 --> 00:02:20,439 not know enough about our domain. It was a 43 00:02:20,439 --> 00:02:22,340 new domain for me, printing, and I also did 44 00:02:22,340 --> 00:02:24,790 not know enough about Ruby. I did not know 45 00:02:24,790 --> 00:02:28,959 about, enough about Rails. So, very intentionally decided to 46 00:02:28,959 --> 00:02:30,999 do our best, the best that we could, knowing 47 00:02:30,999 --> 00:02:33,159 that we would end up, very likely, with a 48 00:02:33,159 --> 00:02:36,249 pretty heaping mound of technical debt. 49 00:02:36,249 --> 00:02:39,599 And that turned out to be true. And has 50 00:02:39,599 --> 00:02:43,980 anyone had that experience? I don't know. Yeah. So, 51 00:02:43,980 --> 00:02:45,629 but recently we had an opportunity to build an 52 00:02:45,629 --> 00:02:47,849 API, and that was really exciting for me. And 53 00:02:47,849 --> 00:02:48,900 I know there are gonna be some other talks 54 00:02:48,900 --> 00:02:51,730 about APIs here later, and I realized that I 55 00:02:51,730 --> 00:02:54,870 had, I had two kind of competing things that 56 00:02:54,870 --> 00:02:57,480 could come together. The first was, I had, I 57 00:02:57,480 --> 00:03:00,319 had logic in our application that I needed to 58 00:03:00,319 --> 00:03:02,340 share in our API. How was I going to 59 00:03:02,340 --> 00:03:03,779 do that? 60 00:03:03,779 --> 00:03:07,489 And all of our code was sprinkled through various 61 00:03:07,489 --> 00:03:10,559 bits of our controller and model logic. Secondly, I 62 00:03:10,559 --> 00:03:13,430 wanted a mechanism to, to have a strategy for 63 00:03:13,430 --> 00:03:17,799 eliminating the technical debt, and what I turned to 64 00:03:17,799 --> 00:03:21,510 was domain-driven design hexagonal architectures, and I want to 65 00:03:21,510 --> 00:03:24,069 share what we've learnt along the way of doing 66 00:03:24,069 --> 00:03:26,069 that, and, and where we're going. So I hope 67 00:03:26,069 --> 00:03:29,900 you're able to learn something from what we've done. 68 00:03:29,900 --> 00:03:32,689 E.R.: That's great Declan. But what are they gonna 69 00:03:32,689 --> 00:03:33,629 get out of it? 70 00:03:33,629 --> 00:03:34,069 VIDEO 71 00:03:34,069 --> 00:03:37,370 ??: Here's a good idea. Have a point! Makes 72 00:03:37,370 --> 00:03:40,769 it so much more interesting for the listener! 73 00:03:40,769 --> 00:03:43,659 D.W.: Well, that was from Sandy Metz. He said, 74 00:03:43,659 --> 00:03:45,109 you know, if you're gonna have a talk, you 75 00:03:45,109 --> 00:03:46,779 should really have a point, and I think Steve 76 00:03:46,779 --> 00:03:50,079 Martin said it pretty funnily. And I guess, our, 77 00:03:50,079 --> 00:03:52,659 our number one point is that, there is complexity 78 00:03:52,659 --> 00:03:55,760 in the software that we build. There's complexities in 79 00:03:55,760 --> 00:03:57,400 the problems that we're solving. And we need to 80 00:03:57,400 --> 00:04:00,290 embrace that complexity and embrace it in such a 81 00:04:00,290 --> 00:04:02,349 way that we tackle it and deal with it. 82 00:04:02,349 --> 00:04:05,599 And deal with it head-on. And by doing that, 83 00:04:05,599 --> 00:04:07,730 then we end up having more joy and fun 84 00:04:07,730 --> 00:04:09,599 in our work because it's not just about getting 85 00:04:09,599 --> 00:04:11,969 this functional piece to work, it's about really trying 86 00:04:11,969 --> 00:04:14,809 to understand our domain and model it and express 87 00:04:14,809 --> 00:04:16,430 that in our code and make our code as 88 00:04:16,430 --> 00:04:18,639 expressive as possible. 89 00:04:18,639 --> 00:04:21,829 And the second thing that I really realized was 90 00:04:21,829 --> 00:04:23,690 I knew that our code was a mess, and 91 00:04:23,690 --> 00:04:26,590 I knew some point refactorings that we could do, 92 00:04:26,590 --> 00:04:28,860 but I didn't know how to, how to, you 93 00:04:28,860 --> 00:04:30,690 know, what did the end look like? If it 94 00:04:30,690 --> 00:04:33,780 was refactored significantly, what would it look like? What 95 00:04:33,780 --> 00:04:36,840 would the shape look like? What would the namespaces 96 00:04:36,840 --> 00:04:39,420 be? What would the classes be doing, et cetera. 97 00:04:39,420 --> 00:04:43,380 And domain-driven design and hexagonal architecture helped me envision 98 00:04:43,380 --> 00:04:45,100 and share with my team what it might look 99 00:04:45,100 --> 00:04:45,970 like. 100 00:04:45,970 --> 00:04:49,870 The third thing that, that, that we would like 101 00:04:49,870 --> 00:04:52,290 you to take away from this talk is that 102 00:04:52,290 --> 00:04:55,180 there's a lot more to just being a Rails 103 00:04:55,180 --> 00:04:58,700 developer, the, the ideas and patterns, if you will, 104 00:04:58,700 --> 00:05:01,340 that we, that we're talking about are, some of 105 00:05:01,340 --> 00:05:03,340 them have been written by some of those people 106 00:05:03,340 --> 00:05:08,120 that DHH had in his slide, including James Coplain. 107 00:05:08,120 --> 00:05:09,950 But a lot of those patterns have been around 108 00:05:09,950 --> 00:05:12,250 for a long time. SO those patterns and those 109 00:05:12,250 --> 00:05:15,820 ideas and those practices will serve you well beyond 110 00:05:15,820 --> 00:05:18,650 Rails. They would work in a node application. They 111 00:05:18,650 --> 00:05:20,680 could work in a desktop application. They can work 112 00:05:20,680 --> 00:05:23,260 in a wide variety of areas. So by getting 113 00:05:23,260 --> 00:05:26,400 some familiarity with these concepts, you're able to transfer 114 00:05:26,400 --> 00:05:30,090 those skills to things beyond Rails. 115 00:05:30,090 --> 00:05:33,180 And so I want to ask Eric just to 116 00:05:33,180 --> 00:05:34,810 walk us through kind of some of the, some 117 00:05:34,810 --> 00:05:36,720 of the pain that we had with our initial 118 00:05:36,720 --> 00:05:39,240 Rails development and see if it resonates with you. 119 00:05:39,240 --> 00:05:43,580 E.R.: All right. So everyone knows what this is. 120 00:05:43,580 --> 00:05:47,550 It's a Rails folder structure. And it's really great 121 00:05:47,550 --> 00:05:49,470 when you get started with Rails. You have these 122 00:05:49,470 --> 00:05:53,460 folders. OK. I, I logically, my things fall into 123 00:05:53,460 --> 00:05:56,300 these areas. Controllers, models, and views are really what 124 00:05:56,300 --> 00:05:59,240 we're focusing on right now. 125 00:05:59,240 --> 00:06:01,110 But if the responsibility of your code doesn't start 126 00:06:01,110 --> 00:06:05,110 with M, V or C, what do you do 127 00:06:05,110 --> 00:06:07,610 then? And we, and we find it kind of 128 00:06:07,610 --> 00:06:10,050 goes like this. You have, you have these areas 129 00:06:10,050 --> 00:06:12,970 of responsibility and you have something that doesn't really 130 00:06:12,970 --> 00:06:14,560 fit, and you don't know where it goes, so 131 00:06:14,560 --> 00:06:16,210 you just put it on somewhere and things get 132 00:06:16,210 --> 00:06:18,170 a little bigger. 133 00:06:18,170 --> 00:06:20,060 And continuing on, you keep doing this, things get 134 00:06:20,060 --> 00:06:23,520 bigger, and finally, like, the line between all of 135 00:06:23,520 --> 00:06:26,150 these things is, is blurred. You don't know what's 136 00:06:26,150 --> 00:06:29,500 what. It's hard to extract reusable parts from all 137 00:06:29,500 --> 00:06:31,810 of this, because the, the responsibilities are split across 138 00:06:31,810 --> 00:06:32,390 all these things. 139 00:06:32,390 --> 00:06:34,310 And you kind of end up with methods like 140 00:06:34,310 --> 00:06:37,720 this. This is one method. It starts on the 141 00:06:37,720 --> 00:06:40,360 left and ends on the right. It's about ninety 142 00:06:40,360 --> 00:06:43,370 lines. 143 00:06:43,370 --> 00:06:46,200 It's not from PrintChomp. It's from another, another project 144 00:06:46,200 --> 00:06:49,190 that I've worked on. And without setting, it doesn't 145 00:06:49,190 --> 00:06:51,210 really matter what it does. The point is it's 146 00:06:51,210 --> 00:06:55,330 ugly and you know, it is actually about setting 147 00:06:55,330 --> 00:06:59,750 prices on properties and the date ranges are available. 148 00:06:59,750 --> 00:07:03,060 So I have a question. We need to add 149 00:07:03,060 --> 00:07:05,140 sales tax to the prices. 150 00:07:05,140 --> 00:07:09,970 Anybody care to take on that refactoring? 151 00:07:09,970 --> 00:07:12,410 It's pretty horrible. But nobody, nobody sits down and 152 00:07:12,410 --> 00:07:14,270 says, I'm gonna write a ninety line method today 153 00:07:14,270 --> 00:07:19,590 that does property prices with date ranges. The initial 154 00:07:19,590 --> 00:07:23,330 spec was probably something a lot simpler. And because 155 00:07:23,330 --> 00:07:25,639 it's in that spot now, the next person who 156 00:07:25,639 --> 00:07:27,170 comes, comes and looks and that method and goes, 157 00:07:27,170 --> 00:07:28,500 oh, well OK, well if I just type this 158 00:07:28,500 --> 00:07:31,710 little bit more it'll, it'll do that now. 159 00:07:31,710 --> 00:07:33,870 And this was a little bit of a train 160 00:07:33,870 --> 00:07:36,570 wreck. At some point you probably, the people working 161 00:07:36,570 --> 00:07:39,300 on this, including myself, probably should have realized, you 162 00:07:39,300 --> 00:07:41,330 know, forty-five lines might have been the time to 163 00:07:41,330 --> 00:07:45,790 split it up. Maybe twenty. Maybe less. 164 00:07:45,790 --> 00:07:47,889 But this is, nonetheless, what we ended up with. 165 00:07:47,889 --> 00:07:51,120 Or, you end up with Rube Goldberg machines for 166 00:07:51,120 --> 00:07:53,260 sharpening pencils. 167 00:07:53,260 --> 00:07:56,210 So there's a lot of well-known patterns that can 168 00:07:56,210 --> 00:07:58,480 help you out with this. Has anyone read this 169 00:07:58,480 --> 00:08:03,210 blog post? Yeah. Anybody use any of the patterns 170 00:08:03,210 --> 00:08:04,150 in them? 171 00:08:04,150 --> 00:08:07,430 They're pretty great, right. We use a lot of 172 00:08:07,430 --> 00:08:09,450 them, and I'm, we're gonna tell you about some 173 00:08:09,450 --> 00:08:13,230 of them here. But the one thing you've, so 174 00:08:13,230 --> 00:08:16,300 you've extracted all of these things into small responsibilities. 175 00:08:16,300 --> 00:08:18,230 Your models, your controllers and your views. They're all 176 00:08:18,230 --> 00:08:19,250 small again. 177 00:08:19,250 --> 00:08:22,310 But, OK, so what? I have a bunch of 178 00:08:22,310 --> 00:08:24,889 little objects that all go, they all know too 179 00:08:24,889 --> 00:08:27,780 much about each other. They don't fit in any 180 00:08:27,780 --> 00:08:31,720 logical structure. They don't, how, how does this all 181 00:08:31,720 --> 00:08:35,019 fit together? You've made, like, an awesome first step, 182 00:08:35,019 --> 00:08:36,940 in that you have small little pieces that you 183 00:08:36,940 --> 00:08:40,250 can use. But where do you go from there? 184 00:08:40,250 --> 00:08:44,360 And we think that looks kind of like this. 185 00:08:44,360 --> 00:08:49,500 We think that your domain concepts, services, entities, should 186 00:08:49,500 --> 00:08:53,170 be in the middle, and everything else is outside. 187 00:08:53,170 --> 00:08:56,670 Your database is an extra concern, your views are 188 00:08:56,670 --> 00:08:58,889 an extra concern. The web, and you know, when 189 00:08:58,889 --> 00:09:01,499 you're designing the API, as Declan talked about a 190 00:09:01,499 --> 00:09:03,309 little bit, it's an extra concern. So you can 191 00:09:03,309 --> 00:09:05,550 really focus in on the middle of what your 192 00:09:05,550 --> 00:09:06,550 application actually does. 193 00:09:06,550 --> 00:09:09,339 I'm gonna let Declan talk a little bit more 194 00:09:09,339 --> 00:09:09,959 about that 195 00:09:09,959 --> 00:09:13,839 D.W.: Has anyone here heard of domain-driven design? Oh, 196 00:09:13,839 --> 00:09:16,009 quite a few people. Awesome. How many people have 197 00:09:16,009 --> 00:09:19,889 actually, you know, intentionally used it and, and have 198 00:09:19,889 --> 00:09:22,529 worked with it? So, a, a number. SO cool. 199 00:09:22,529 --> 00:09:25,680 And it can be quite, it can be quite, 200 00:09:25,680 --> 00:09:29,910 it can be quite daunting. And this book by 201 00:09:29,910 --> 00:09:31,850 Eric Evans is kind of what kicked it off. 202 00:09:31,850 --> 00:09:34,100 And this book was I think written in 2005, 203 00:09:34,100 --> 00:09:36,499 and it is a really, really great book, but 204 00:09:36,499 --> 00:09:39,269 it is actually quite difficult to read. But it's, 205 00:09:39,269 --> 00:09:41,319 I think it might be the only technical book 206 00:09:41,319 --> 00:09:43,040 I've read twice. 207 00:09:43,040 --> 00:09:44,449 And that's partly cause it was really good and 208 00:09:44,449 --> 00:09:47,600 partly cause it was rather difficult to get through 209 00:09:47,600 --> 00:09:49,259 some of it. Did anyone else read this book 210 00:09:49,259 --> 00:09:51,709 and have a similar experience? like, it's really great 211 00:09:51,709 --> 00:09:53,249 stuff and you kind of read and it and 212 00:09:53,249 --> 00:09:55,100 you go, wow, what does that mean to me? 213 00:09:55,100 --> 00:09:55,480 Right? 214 00:09:55,480 --> 00:09:57,920 And we, at the end, at the end, we'll 215 00:09:57,920 --> 00:10:00,050 be posting our deck, and we'll have some references 216 00:10:00,050 --> 00:10:02,230 to other material that, that I've actually found to 217 00:10:02,230 --> 00:10:05,170 be a bit more addressable or a little more 218 00:10:05,170 --> 00:10:07,350 consumable. 219 00:10:07,350 --> 00:10:10,550 But what Eric Evans talked about was really tackling 220 00:10:10,550 --> 00:10:13,490 complexity, and he talks about the, you know, the 221 00:10:13,490 --> 00:10:18,339 critical complexity is really understanding the domain. What are 222 00:10:18,339 --> 00:10:22,319 the business rules that take place inside our systems? 223 00:10:22,319 --> 00:10:23,680 If we're gonna add sales tax, what are the 224 00:10:23,680 --> 00:10:25,990 business rules for that sales tax? 225 00:10:25,990 --> 00:10:27,899 What are the, what are the rules around who 226 00:10:27,899 --> 00:10:30,740 can buy what? And by putting those insides and 227 00:10:30,740 --> 00:10:33,540 thinking of them as the domain of our system, 228 00:10:33,540 --> 00:10:36,339 then we're able to have our outside layers just 229 00:10:36,339 --> 00:10:42,649 be, if you will, relatively thin facades, which allows 230 00:10:42,649 --> 00:10:45,779 us to reuse that logic across APIs, across other 231 00:10:45,779 --> 00:10:48,529 applications. We don't have to duplicate all of those 232 00:10:48,529 --> 00:10:50,509 business rules. 233 00:10:50,509 --> 00:10:52,619 And the way that he proposes to do that 234 00:10:52,619 --> 00:10:56,480 is through ubiquitous language. And this is a picture 235 00:10:56,480 --> 00:10:58,920 of the tower of Babel and if anybody knows 236 00:10:58,920 --> 00:11:01,819 the story, it's where everyone in the world was 237 00:11:01,819 --> 00:11:04,850 speaking a different language and, I once worked on 238 00:11:04,850 --> 00:11:09,240 a project that was a financial transaction processing system, 239 00:11:09,240 --> 00:11:12,139 and when I inherited it, the guy who was 240 00:11:12,139 --> 00:11:15,579 proceeded me had this, was a model train aficionado, 241 00:11:15,579 --> 00:11:18,559 so he had the idea of model trains. So 242 00:11:18,559 --> 00:11:22,199 every transaction was like a car, and the payment 243 00:11:22,199 --> 00:11:25,689 engines were, were train tracks. And he had all 244 00:11:25,689 --> 00:11:28,829 of these metaphors around transaction processing and trains, and 245 00:11:28,829 --> 00:11:30,369 was written in Java. 246 00:11:30,369 --> 00:11:31,910 So when I was asked to add a new 247 00:11:31,910 --> 00:11:33,970 feature, fix a bug, I had to understand the 248 00:11:33,970 --> 00:11:35,879 business domain, and then I had to kind of 249 00:11:35,879 --> 00:11:39,059 understand, how did that translate into train speak, and 250 00:11:39,059 --> 00:11:40,360 then I had to go look at the Java 251 00:11:40,360 --> 00:11:43,369 code to figure it all out, right. So the 252 00:11:43,369 --> 00:11:46,240 coding was easy. The hard part was really trying 253 00:11:46,240 --> 00:11:48,350 to understand what was being asked and how did 254 00:11:48,350 --> 00:11:50,589 the code express that, right? 255 00:11:50,589 --> 00:11:52,149 And that's what Eric Evans is talking about with 256 00:11:52,149 --> 00:11:55,209 ubiquitous language. We want to have the language that 257 00:11:55,209 --> 00:11:58,670 we speak with domain experts should be readable in 258 00:11:58,670 --> 00:12:01,459 the code. If I'm order, if I'm a customer 259 00:12:01,459 --> 00:12:04,300 and I can purchase a product, there should be 260 00:12:04,300 --> 00:12:06,259 a class called customer. There should be a class 261 00:12:06,259 --> 00:12:08,319 called product. And there should be a verb in 262 00:12:08,319 --> 00:12:11,119 there that's somewhere that says purchase, et cetera. 263 00:12:11,119 --> 00:12:14,019 So that there's minimal translation between the domain experts' 264 00:12:14,019 --> 00:12:16,769 language and the language that my code is written 265 00:12:16,769 --> 00:12:18,959 in. Ruby gives us a great opportunity to do 266 00:12:18,959 --> 00:12:22,369 that, but this is much more difficult in, in 267 00:12:22,369 --> 00:12:26,679 other more statically typed languages. 268 00:12:26,679 --> 00:12:28,189 So that's kind of the, the key thing to 269 00:12:28,189 --> 00:12:30,999 take away from domain driven design is to try 270 00:12:30,999 --> 00:12:34,230 to have your, your concepts expressed in code that 271 00:12:34,230 --> 00:12:37,230 are meaningful in the words people use. 272 00:12:37,230 --> 00:12:38,449 If they use the word customer, you should have 273 00:12:38,449 --> 00:12:40,540 a customer class. If they use the word user, 274 00:12:40,540 --> 00:12:44,199 you should have a user class, et cetera. 275 00:12:44,199 --> 00:12:46,170 But beyond that, it also has some kind of 276 00:12:46,170 --> 00:12:50,339 key, I, I dare not say it, patterns? Now, 277 00:12:50,339 --> 00:12:53,929 I'm almost nervous now to say it. 278 00:12:53,929 --> 00:13:00,929 But let me be clear. This isn't science. It's 279 00:13:01,970 --> 00:13:05,819 not, right. Because these patterns were not dreamed up 280 00:13:05,819 --> 00:13:10,519 in academia ivory towers. These patterns that we talk 281 00:13:10,519 --> 00:13:15,170 about were empirically derived from people intentionally doing what 282 00:13:15,170 --> 00:13:17,899 we do, which is write code every day, intentionally 283 00:13:17,899 --> 00:13:20,279 thinking about, how does that, how does those, how 284 00:13:20,279 --> 00:13:22,119 do those things fit together, and what is the 285 00:13:22,119 --> 00:13:23,920 essence of what I'm doing? 286 00:13:23,920 --> 00:13:25,999 And can I extract that into words that I 287 00:13:25,999 --> 00:13:28,809 can use to communicate with other people? The beauty 288 00:13:28,809 --> 00:13:30,569 of patterns is I can talk about a value 289 00:13:30,569 --> 00:13:33,339 object, and if you know what a value object 290 00:13:33,339 --> 00:13:35,529 is and I know what a value object is, 291 00:13:35,529 --> 00:13:38,119 we can have a much richer conversation than, oh, 292 00:13:38,119 --> 00:13:40,079 I have to have an object whose state is, 293 00:13:40,079 --> 00:13:42,119 whose identity is defined by the state of its 294 00:13:42,119 --> 00:13:44,139 attributes and then, you know, we can have a 295 00:13:44,139 --> 00:13:45,420 much richer conversation. 296 00:13:45,420 --> 00:13:48,160 E.R.: You might say you ubiquitous language. 297 00:13:48,160 --> 00:13:50,420 D.W.: Yeah. So we're gonna touch a little bit 298 00:13:50,420 --> 00:13:53,209 on some of these patterns. But, but the idea 299 00:13:53,209 --> 00:13:59,230 is that these are not academic ivory tower concepts. 300 00:13:59,230 --> 00:14:01,420 These are empirically driven from people who've worked in 301 00:14:01,420 --> 00:14:03,429 the field. And if we're gonna, if we're gonna 302 00:14:03,429 --> 00:14:06,329 be successful as an organization, while I fully agree 303 00:14:06,329 --> 00:14:08,019 that we need to go out and write code 304 00:14:08,019 --> 00:14:09,920 and we need to read code, I totally think 305 00:14:09,920 --> 00:14:12,269 that's true, but we also have to have more 306 00:14:12,269 --> 00:14:15,509 effective ways of communicating knowledge, so that we're not 307 00:14:15,509 --> 00:14:17,550 all learning the same things from each other over 308 00:14:17,550 --> 00:14:19,300 and over. WE can learn more easily from each 309 00:14:19,300 --> 00:14:22,699 other. And that's what these patterns are. 310 00:14:22,699 --> 00:14:27,100 And the next kind of piece that we're gonna 311 00:14:27,100 --> 00:14:29,689 talk about is hexagonal architectures. And it's more than 312 00:14:29,689 --> 00:14:33,449 just that. I think we've alluded to a little 313 00:14:33,449 --> 00:14:36,239 bit. It's really the idea of, you're going to 314 00:14:36,239 --> 00:14:42,399 have this core domain in the middle, and in, 315 00:14:42,399 --> 00:14:45,119 inside your code, surrounding your outside core are gonna 316 00:14:45,119 --> 00:14:49,319 be some application level code that expresses the rules 317 00:14:49,319 --> 00:14:51,480 of your application. And I would draw it slightly 318 00:14:51,480 --> 00:14:53,949 differently, perhaps, but, and then we have adapters on 319 00:14:53,949 --> 00:14:56,910 the outside that adapt that code to web calls 320 00:14:56,910 --> 00:15:01,119 or database calls or SNTP, or in my case, 321 00:15:01,119 --> 00:15:01,629 APIs. 322 00:15:01,629 --> 00:15:03,999 And so that's the way that we want you 323 00:15:03,999 --> 00:15:05,639 to, that's the way that we are starting to 324 00:15:05,639 --> 00:15:08,129 approach the work at PrintChomp is thinking about it 325 00:15:08,129 --> 00:15:10,550 in those constructs. And now we want to jump 326 00:15:10,550 --> 00:15:13,860 to some specific patterns and, and show you some 327 00:15:13,860 --> 00:15:16,350 real code that actually, you know, brings these to 328 00:15:16,350 --> 00:15:19,660 life. So Eric, you want to talk about form 329 00:15:19,660 --> 00:15:19,970 object? 330 00:15:19,970 --> 00:15:21,769 E.R.: Sure. Unfortunately, I can't tell you what your 331 00:15:21,769 --> 00:15:24,139 domain is or what necessarily goes in the middle 332 00:15:24,139 --> 00:15:27,059 of that hexagon. But I can give you some 333 00:15:27,059 --> 00:15:29,879 ways to keep other things out of that hexagon 334 00:15:29,879 --> 00:15:32,269 that you don't need to be concerned with. 335 00:15:32,269 --> 00:15:34,239 One thing that I've been doing lately is form 336 00:15:34,239 --> 00:15:37,389 object. One of the really cool things, you know, 337 00:15:37,389 --> 00:15:40,350 if you run Rails scaffold, some model name, you 338 00:15:40,350 --> 00:15:43,069 get a form that you submit, creates the record, 339 00:15:43,069 --> 00:15:47,209 edits the record. And that's pretty great. 340 00:15:47,209 --> 00:15:49,110 But how do you do that when you don't 341 00:15:49,110 --> 00:15:53,220 have a direct one-one mapping with an ActiveModel record? 342 00:15:53,220 --> 00:15:56,829 So instead of instantiating an ActiveModel record, I've taken 343 00:15:56,829 --> 00:15:59,959 to instantiating, I'm gonna call it a form object. 344 00:15:59,959 --> 00:16:01,600 There's a lot of names for a lot of 345 00:16:01,600 --> 00:16:03,410 different things. But this is, this is what I've 346 00:16:03,410 --> 00:16:04,549 been calling it. 347 00:16:04,549 --> 00:16:08,009 So here's the actual thing that I was building. 348 00:16:08,009 --> 00:16:10,049 On the left hand side, you see that you 349 00:16:10,049 --> 00:16:11,999 select a ticket price. On the right hand side, 350 00:16:11,999 --> 00:16:15,230 your name, email address, and your payment details. And 351 00:16:15,230 --> 00:16:20,059 this is actually two ActiveRecord models in my database. 352 00:16:20,059 --> 00:16:22,939 The, the passengers over there on the right, you 353 00:16:22,939 --> 00:16:25,459 can add a passenger and keep adding it. 354 00:16:25,459 --> 00:16:27,160 And if you've ever worked with nested attributes, probably 355 00:16:27,160 --> 00:16:31,139 know it's not always that fun. So this is 356 00:16:31,139 --> 00:16:35,389 not using nested attributes. It's done like this. I 357 00:16:35,389 --> 00:16:39,239 have a class TicketForm that includes ActiveModel::Model, which is 358 00:16:39,239 --> 00:16:41,910 how I get nice things, like that magic initialize 359 00:16:41,910 --> 00:16:45,699 method of validators. 360 00:16:45,699 --> 00:16:47,839 And the passengers method, if I don't have any, 361 00:16:47,839 --> 00:16:50,110 returns me a passenger new. That's how it puts 362 00:16:50,110 --> 00:16:53,170 the name and email address for that first passenger. 363 00:16:53,170 --> 00:16:54,759 And then tickets, I get out of this by 364 00:16:54,759 --> 00:16:59,379 taking my passengers and mapping them into new objects. 365 00:16:59,379 --> 00:17:01,399 In the controller, it looks a little bit like 366 00:17:01,399 --> 00:17:04,819 this. So you just pass your params off into 367 00:17:04,819 --> 00:17:06,750 that. You get it back out and you have 368 00:17:06,750 --> 00:17:10,890 tickets. So instead of if ticket dot save, I 369 00:17:10,890 --> 00:17:16,099 do if ticket_form valid and ticketCharger charges successfully, then 370 00:17:16,099 --> 00:17:18,390 we've had success. And ticketCharge takes care of charging 371 00:17:18,390 --> 00:17:20,709 my tickets and knowing that, there was only, cause 372 00:17:20,709 --> 00:17:22,819 there's only one charge for all the tickets, right. 373 00:17:22,819 --> 00:17:24,930 You're paying all at once. No point to split 374 00:17:24,930 --> 00:17:26,450 that up. 375 00:17:26,450 --> 00:17:28,700 So that's a really useful thing that I've found 376 00:17:28,700 --> 00:17:31,790 to, to help when my mappings aren't just totally, 377 00:17:31,790 --> 00:17:33,250 I don't want to just take a record of 378 00:17:33,250 --> 00:17:35,990 the database, put it in, or update it. 379 00:17:35,990 --> 00:17:37,360 And now Declan's gonna tell you a little bit 380 00:17:37,360 --> 00:17:38,340 about request objects. 381 00:17:38,340 --> 00:17:40,300 D.W.: Yeah. In this case, has anyone used a 382 00:17:40,300 --> 00:17:42,450 form object or something like that? So quite a 383 00:17:42,450 --> 00:17:43,650 few people. Cool. 384 00:17:43,650 --> 00:17:46,500 Has, has anyone done, used something called a request 385 00:17:46,500 --> 00:17:50,760 object? Sort of? I was hoping that I invented 386 00:17:50,760 --> 00:17:53,490 this. So maybe I haven't. I don't know. OK. 387 00:17:53,490 --> 00:17:56,320 But, request object is now in, you know, think 388 00:17:56,320 --> 00:17:58,320 of an API as, we're trying to have a 389 00:17:58,320 --> 00:18:02,730 similar behavior to the form object, except we're trying 390 00:18:02,730 --> 00:18:05,170 to take, remember, we're trying to take complexity out 391 00:18:05,170 --> 00:18:06,770 of our controllers and out of our models and 392 00:18:06,770 --> 00:18:10,780 put them into more, to simplify our systems. 393 00:18:10,780 --> 00:18:13,870 So the idea with the request object is that 394 00:18:13,870 --> 00:18:15,240 we're gonna pull that code out and put it 395 00:18:15,240 --> 00:18:18,510 into the, into the controller. And now the request 396 00:18:18,510 --> 00:18:21,210 object is going to receive the request. And the 397 00:18:21,210 --> 00:18:23,150 code looks sort of like this, right. 398 00:18:23,150 --> 00:18:26,520 There's, I, I've done this slightly differently than Eric's, 399 00:18:26,520 --> 00:18:28,500 Eric's way, in terms of, of, the kind of 400 00:18:28,500 --> 00:18:29,880 the core of the class. The core of this 401 00:18:29,880 --> 00:18:33,310 class is using a gem called Verdis, which does 402 00:18:33,310 --> 00:18:38,800 something similar to ActiveModel::Model, except this allows you basically 403 00:18:38,800 --> 00:18:41,950 to have a plain-old Ruby object and, the way, 404 00:18:41,950 --> 00:18:44,720 and, the cool part is, that, or, I think 405 00:18:44,720 --> 00:18:47,620 it's cool. You can, you can declare attributes, like 406 00:18:47,620 --> 00:18:49,900 this. So I have actually, in my domain layer, 407 00:18:49,900 --> 00:18:51,710 I have something called the customer and the billing 408 00:18:51,710 --> 00:18:54,230 and the shipping. And if, if somebody supplies me 409 00:18:54,230 --> 00:18:56,990 those three things, then I can complete an order 410 00:18:56,990 --> 00:18:58,790 in my system. 411 00:18:58,790 --> 00:19:01,810 We've, there are a couple of pieces missing here, 412 00:19:01,810 --> 00:19:03,980 but we wanted to keep it, fit in a 413 00:19:03,980 --> 00:19:07,230 slide. But that's basically it. And we have the 414 00:19:07,230 --> 00:19:10,580 validation. And the cool part about this is that 415 00:19:10,580 --> 00:19:12,440 when a request comes in, we just, I just 416 00:19:12,440 --> 00:19:15,430 put in a before loop in the controller that 417 00:19:15,430 --> 00:19:18,380 has a before filter that just basically instantiates the 418 00:19:18,380 --> 00:19:23,740 request object using some, some reflection to figure out, 419 00:19:23,740 --> 00:19:25,920 you know, what is the, what is the controller 420 00:19:25,920 --> 00:19:29,660 and what is the action being asked, inferring the 421 00:19:29,660 --> 00:19:32,870 request class, instantiating it, and then just passing it 422 00:19:32,870 --> 00:19:34,900 what used to be the params hash. 423 00:19:34,900 --> 00:19:37,140 But now it's actually a rich object that I 424 00:19:37,140 --> 00:19:39,740 can have validations on, et cetera. So the net 425 00:19:39,740 --> 00:19:42,490 effect of this is that, why would I bother 426 00:19:42,490 --> 00:19:45,520 doing this, right? Well, now the controller, you know, 427 00:19:45,520 --> 00:19:48,100 the complexity around validating the request is at the 428 00:19:48,100 --> 00:19:50,490 boundary of my system. That doesn't need to leak 429 00:19:50,490 --> 00:19:55,640 into the rest of my system. It's almost like, 430 00:19:55,640 --> 00:19:57,150 you know, does anybody use, you know at the 431 00:19:57,150 --> 00:19:58,680 beginning of your methods, you want to put the 432 00:19:58,680 --> 00:20:01,100 guard clauses to catch the exceptions coming in at 433 00:20:01,100 --> 00:20:02,440 the beginning of your methods, so that the rest 434 00:20:02,440 --> 00:20:03,790 of your method is simpler? 435 00:20:03,790 --> 00:20:05,690 This is doing the same thing, except it's doing 436 00:20:05,690 --> 00:20:08,050 it at, at a higher level abstraction, at the 437 00:20:08,050 --> 00:20:10,110 API request level. And I, this has worked out 438 00:20:10,110 --> 00:20:11,950 really well for us. So I, I quite like 439 00:20:11,950 --> 00:20:13,820 that one. 440 00:20:13,820 --> 00:20:14,750 Yeah. 441 00:20:14,750 --> 00:20:18,230 E.R.: Great. Service objects are another one that we've 442 00:20:18,230 --> 00:20:21,410 been using. I think DHH actually had one in 443 00:20:21,410 --> 00:20:23,420 his presentation. I'll give you a hint, he didn't 444 00:20:23,420 --> 00:20:27,300 like it. 445 00:20:27,300 --> 00:20:29,900 He used one, it, it's something instantiated by the 446 00:20:29,900 --> 00:20:32,670 controller. We've been looking at controllers a little bit 447 00:20:32,670 --> 00:20:35,820 as just like, OK, I've received this thing, pass 448 00:20:35,820 --> 00:20:37,440 it off to somebody else, and then do something 449 00:20:37,440 --> 00:20:40,080 with the result. So we want to keep out 450 00:20:40,080 --> 00:20:42,770 that procedural code from our controllers, and service objects 451 00:20:42,770 --> 00:20:46,020 are one way you can do that using a 452 00:20:46,020 --> 00:20:49,370 order service to create orders, we've encapsulated all of 453 00:20:49,370 --> 00:20:53,700 the logic about how to create an order in 454 00:20:53,700 --> 00:20:54,270 this one area. 455 00:20:54,270 --> 00:20:56,070 So if you want to, you can use it 456 00:20:56,070 --> 00:20:57,760 from somewhere else, right. You don't have to hit 457 00:20:57,760 --> 00:21:01,760 a controller action to create an order. It's reusable 458 00:21:01,760 --> 00:21:06,870 and extendable. And it has Declan's magic repository object 459 00:21:06,870 --> 00:21:10,440 in there that we'll get to in a bit. 460 00:21:10,440 --> 00:21:14,270 And the controller, again, just, it's very simple. Do 461 00:21:14,270 --> 00:21:17,900 this thing, on success do this, on failure, do 462 00:21:17,900 --> 00:21:18,310 this. 463 00:21:18,310 --> 00:21:20,620 So those are a few of the patterns that 464 00:21:20,620 --> 00:21:25,920 we've been using to help us with this. So 465 00:21:25,920 --> 00:21:27,900 now what? 466 00:21:27,900 --> 00:21:34,550 What's, what's the elephant in the room? Anybody? 467 00:21:34,550 --> 00:21:41,550 How do you get them into Rails? Yeah. 468 00:21:45,430 --> 00:21:47,980 Yeah. That's the one we were thinking of. 469 00:21:47,980 --> 00:21:50,520 D.W.: That's, ActiveRecord. Yeah. I mean, I mean, the 470 00:21:50,520 --> 00:21:52,960 end, and how do you get into Rails. Yes, 471 00:21:52,960 --> 00:21:55,890 there are some interesting challenges around that. But I'm 472 00:21:55,890 --> 00:21:57,900 gonna flip you back to the architectural slide and 473 00:21:57,900 --> 00:22:00,750 just point out that you see what's happened here 474 00:22:00,750 --> 00:22:04,190 is that we're trying to view the application pieces 475 00:22:04,190 --> 00:22:07,190 of our solution here being really on the perimeter 476 00:22:07,190 --> 00:22:09,740 of our core system. And the core system composed 477 00:22:09,740 --> 00:22:13,980 of services that may be servicing API or application 478 00:22:13,980 --> 00:22:16,210 requests. 479 00:22:16,210 --> 00:22:19,260 We have some services that may be invariant across 480 00:22:19,260 --> 00:22:21,460 any call, and those would be at the very 481 00:22:21,460 --> 00:22:23,620 center. And we have things called entities which are 482 00:22:23,620 --> 00:22:26,440 on the inside. And the key part that's, that 483 00:22:26,440 --> 00:22:28,760 we haven't talked about, which actually I'm planning the 484 00:22:28,760 --> 00:22:32,250 most difficult part in this is this repository which 485 00:22:32,250 --> 00:22:33,800 is the bottom, which is the r in the 486 00:22:33,800 --> 00:22:35,570 bottom right hand corner. 487 00:22:35,570 --> 00:22:37,870 And it's job is to talk to the ActiveRecord 488 00:22:37,870 --> 00:22:39,730 model which is in the green, and create an 489 00:22:39,730 --> 00:22:42,280 entity object which is the blue object, and, and 490 00:22:42,280 --> 00:22:45,480 how does that actually work? So I'm gonna show 491 00:22:45,480 --> 00:22:48,500 you a bit of code, and this is, this 492 00:22:48,500 --> 00:22:50,860 is the first time I've shown my Ruby code 493 00:22:50,860 --> 00:22:52,420 in public. So please be kind. 494 00:22:52,420 --> 00:22:55,290 And there are probably way better ways to do 495 00:22:55,290 --> 00:22:58,650 this. but this is the repository that I've, I've, 496 00:22:58,650 --> 00:22:59,710 there are some other methods here, but I just 497 00:22:59,710 --> 00:23:01,980 wanted to fit on what happen, you know, show 498 00:23:01,980 --> 00:23:03,810 you the simple one. 499 00:23:03,810 --> 00:23:05,690 So this is what a save looks like. So 500 00:23:05,690 --> 00:23:08,830 the save takes a domain object and it converts 501 00:23:08,830 --> 00:23:11,140 it through something called a mapper, which maps the 502 00:23:11,140 --> 00:23:15,440 domain object onto a ActiveRecord object, which is called 503 00:23:15,440 --> 00:23:18,610 a record here. Then I, then it calls record 504 00:23:18,610 --> 00:23:22,400 dot save, assigns the id and returns the response. 505 00:23:22,400 --> 00:23:25,060 So that's pretty straightforward. All that's really happened is, 506 00:23:25,060 --> 00:23:26,390 and I really tried to do this and so 507 00:23:26,390 --> 00:23:28,290 far I've been able to, I don't want to 508 00:23:28,290 --> 00:23:31,010 have domain dot save. I want to have repository 509 00:23:31,010 --> 00:23:34,400 dot save domain, so that there's no persistence that's 510 00:23:34,400 --> 00:23:38,250 leaking into my domain objects. Persistence, I want to 511 00:23:38,250 --> 00:23:40,830 be a secondary concern to what that object is 512 00:23:40,830 --> 00:23:41,520 really doing. 513 00:23:41,520 --> 00:23:44,140 And so far, it's worked, although sometimes it's caused 514 00:23:44,140 --> 00:23:48,040 me some difficulty. The method messing down there is 515 00:23:48,040 --> 00:23:51,710 kind of cool. At least I think it's cool. 516 00:23:51,710 --> 00:23:54,500 And what it's doing is it's introducing a scope 517 00:23:54,500 --> 00:23:55,970 object, which I'll show you in a, well here's 518 00:23:55,970 --> 00:23:57,900 the scope object. That's OK. 519 00:23:57,900 --> 00:23:59,650 And it creates a scope object, and this was 520 00:23:59,650 --> 00:24:01,630 the trickiest code that I had to write, but 521 00:24:01,630 --> 00:24:03,900 what it does, what it, the end result of 522 00:24:03,900 --> 00:24:06,970 this code is, that allows you to chain call 523 00:24:06,970 --> 00:24:11,090 any of your ActiveRecord find methods of your scopes 524 00:24:11,090 --> 00:24:13,400 and chain them together. So you can now use, 525 00:24:13,400 --> 00:24:16,030 so in other words, with this logic, wherever you 526 00:24:16,030 --> 00:24:22,010 have like ActiveRecord dot, you know, find where id 527 00:24:22,010 --> 00:24:24,720 greater than 122 is activated and so on, wherever 528 00:24:24,720 --> 00:24:26,310 you might have a chain like that, you can 529 00:24:26,310 --> 00:24:28,570 still use that chain now because of this scope 530 00:24:28,570 --> 00:24:30,430 class with your domain objects. 531 00:24:30,430 --> 00:24:33,740 Except, instead of getting back your ActiveRecord object, you're 532 00:24:33,740 --> 00:24:38,000 getting back its domain representation. Does that make sense? 533 00:24:38,000 --> 00:24:38,600 yeah? 534 00:24:38,600 --> 00:24:41,180 OK. And then the mapper is what maps them 535 00:24:41,180 --> 00:24:43,950 across, right. And some cases, the mapping is like 536 00:24:43,950 --> 00:24:47,440 really, really simple. What's the next slide here? Oh, 537 00:24:47,440 --> 00:24:49,660 yeah. Yeah. There it is right there. 538 00:24:49,660 --> 00:24:51,830 So the mapper, because of the way vertice works 539 00:24:51,830 --> 00:24:55,030 and the way ActiveRecord works with attributes, you can 540 00:24:55,030 --> 00:24:57,940 almost just instantiate one from the other just passing 541 00:24:57,940 --> 00:25:00,280 the attributes back and forth. So it's actually quite 542 00:25:00,280 --> 00:25:04,040 easy except when it's not easy, and then what 543 00:25:04,040 --> 00:25:06,740 happens, what I'm doing now is just, wherever I 544 00:25:06,740 --> 00:25:09,260 have something that doesn't fit this model, I just 545 00:25:09,260 --> 00:25:12,030 subclass this mapper with a custom mapper and override 546 00:25:12,030 --> 00:25:13,650 those methods, more or less. 547 00:25:13,650 --> 00:25:17,360 And that's the part that I think there, would 548 00:25:17,360 --> 00:25:19,580 be more expressive ways to do that mapping and 549 00:25:19,580 --> 00:25:22,220 that's what I'm starting to look at now. But 550 00:25:22,220 --> 00:25:25,160 so far this has actually worked pretty well. 551 00:25:25,160 --> 00:25:27,830 And it's allowed me to completely separate the way 552 00:25:27,830 --> 00:25:30,540 I think about persistence from the way I think 553 00:25:30,540 --> 00:25:32,930 about my domain object. SO we before we, before 554 00:25:32,930 --> 00:25:34,910 I had this, we had, used to have an 555 00:25:34,910 --> 00:25:37,160 order class, and I kid you not, and I'm 556 00:25:37,160 --> 00:25:39,660 in, I'm a Rails noob so you can shoot 557 00:25:39,660 --> 00:25:44,650 me, but it had forty-eight attributes in the ActiveRecord::Model, 558 00:25:44,650 --> 00:25:45,540 right. 559 00:25:45,540 --> 00:25:48,380 That is now represented by about eight classes that 560 00:25:48,380 --> 00:25:50,960 separate out all the different aspects of the order, 561 00:25:50,960 --> 00:25:56,970 like the shipping, the billing, et cetera, et cetera. 562 00:25:56,970 --> 00:25:58,920 So that, but I think this mapping is, is, 563 00:25:58,920 --> 00:26:01,690 is, is one of the more challenging parts. And 564 00:26:01,690 --> 00:26:05,180 then finally, you now I've, then you quickly run 565 00:26:05,180 --> 00:26:09,890 into things like, oh, well what happens if I 566 00:26:09,890 --> 00:26:12,240 get the record. I get the record, I save 567 00:26:12,240 --> 00:26:13,640 it, then I save it again. I have to 568 00:26:13,640 --> 00:26:15,070 be able to keep track that I've saved it 569 00:26:15,070 --> 00:26:16,470 once already. 570 00:26:16,470 --> 00:26:18,380 So that I don't have multiple copies around. And 571 00:26:18,380 --> 00:26:20,490 this is an identity map. In fact, an identity 572 00:26:20,490 --> 00:26:25,250 map was built into Rails and I think it 573 00:26:25,250 --> 00:26:26,950 might, I don't, I don't work in Rails 4, 574 00:26:26,950 --> 00:26:29,030 but I think it might be taken out or, 575 00:26:29,030 --> 00:26:31,480 or changed slightly. But actually, on the next slide 576 00:26:31,480 --> 00:26:33,330 I'll show you what the identity map looks like, 577 00:26:33,330 --> 00:26:34,900 and this, actually, I stole from Rails and made 578 00:26:34,900 --> 00:26:36,510 it a bit simpler. 579 00:26:36,510 --> 00:26:37,830 But all it's doing is just making sure that 580 00:26:37,830 --> 00:26:42,150 there's a unique instance on, on a per-API request 581 00:26:42,150 --> 00:26:46,160 call for each entity object. So that I, I 582 00:26:46,160 --> 00:26:47,780 can, and it actually serves as a really cheap 583 00:26:47,780 --> 00:26:50,890 cache, but that's not what it's intent is. 584 00:26:50,890 --> 00:26:54,130 So, so that's kind of where, where we're, where 585 00:26:54,130 --> 00:26:57,430 I'm going now, is most of those service object, 586 00:26:57,430 --> 00:26:59,050 form object, request, those all kind of work well 587 00:26:59,050 --> 00:27:00,980 for us, and I'm not looking at what would 588 00:27:00,980 --> 00:27:04,190 a repository pattern look like fleshed out. And that 589 00:27:04,190 --> 00:27:06,080 is, by far, the most challenging piece. 590 00:27:06,080 --> 00:27:08,630 But I heard a question about where you put 591 00:27:08,630 --> 00:27:11,040 things. You can really just put them anywhere. You 592 00:27:11,040 --> 00:27:13,630 know. That's the thing, like, Rails just seems to 593 00:27:13,630 --> 00:27:17,820 be, there's a part that's, I just felt constrained. 594 00:27:17,820 --> 00:27:20,520 Like, Rails didn't give me any guidance on where 595 00:27:20,520 --> 00:27:22,300 do I put a service socket. Well, you can 596 00:27:22,300 --> 00:27:24,260 really put it anywhere you like. You could put 597 00:27:24,260 --> 00:27:26,030 it on the auto load path or you can 598 00:27:26,030 --> 00:27:28,520 put it where Rails might expect to see it. 599 00:27:28,520 --> 00:27:30,270 But it, you can just create a services directory 600 00:27:30,270 --> 00:27:32,070 and put your service objects there. Rails will find 601 00:27:32,070 --> 00:27:34,890 it. It's not hard. But Rails doesn't really kind 602 00:27:34,890 --> 00:27:36,710 of tell you what to do. So it doesn't 603 00:27:36,710 --> 00:27:39,390 make it easy to do these, to think of 604 00:27:39,390 --> 00:27:42,000 it, but it actually, it's not hard. 605 00:27:42,000 --> 00:27:45,090 And but that's where we're going with that, and 606 00:27:45,090 --> 00:27:46,940 we'll, we'll give you a link to it, to, 607 00:27:46,940 --> 00:27:48,970 I've started a Git Repo where I plan to 608 00:27:48,970 --> 00:27:51,100 share some of these ideas, and if you're interested 609 00:27:51,100 --> 00:27:53,380 in sharing ideas with us on that, we'll, we'll 610 00:27:53,380 --> 00:27:58,020 be happy to talk to you or, or join 611 00:27:58,020 --> 00:27:59,730 us on the, on the Git Repo. 612 00:27:59,730 --> 00:28:04,820 E.R.: Right. So what's the point, again? At the 613 00:28:04,820 --> 00:28:10,580 start, we had these three things. Embrace complexity. Getting, 614 00:28:10,580 --> 00:28:14,640 getting the solution to work is only part of 615 00:28:14,640 --> 00:28:18,090 the fun, right? It's, it's your first draft, as 616 00:28:18,090 --> 00:28:20,490 DHH said, talking about writing. You get, you do 617 00:28:20,490 --> 00:28:24,630 it over and over. And getting things to work, 618 00:28:24,630 --> 00:28:27,950 that ninety-line method I showed earlier, that worked. But 619 00:28:27,950 --> 00:28:31,050 does anyone want to go back and use that 620 00:28:31,050 --> 00:28:33,580 again? It's no, it's no fun to revisit, unless 621 00:28:33,580 --> 00:28:36,530 you're improving it, which, I did do eventually and, 622 00:28:36,530 --> 00:28:40,990 and now it's much nicer to work with. That, 623 00:28:40,990 --> 00:28:44,400 that's fun. At least, we think that's fun. Getting 624 00:28:44,400 --> 00:28:46,600 beyond the problem and getting it to a level 625 00:28:46,600 --> 00:28:49,340 where we actually don't mind going into our code, 626 00:28:49,340 --> 00:28:52,700 extending things, and changing things. 627 00:28:52,700 --> 00:28:54,890 And we do that by breaking them up into 628 00:28:54,890 --> 00:28:57,550 the smaller parts with the patterns that we've talked 629 00:28:57,550 --> 00:28:57,980 about. 630 00:28:57,980 --> 00:29:00,830 Knowing where you're going. In Alice in Wonderland, paraphrase, 631 00:29:00,830 --> 00:29:03,320 they said if you don't know where you're going, 632 00:29:03,320 --> 00:29:06,550 any road will take you there. We think it's 633 00:29:06,550 --> 00:29:08,460 important to know where you're going and pick a 634 00:29:08,460 --> 00:29:10,120 road that you think will take you there. It 635 00:29:10,120 --> 00:29:12,030 doesn't have to be our road. These are things 636 00:29:12,030 --> 00:29:14,850 that helped us, and, and we think they're good 637 00:29:14,850 --> 00:29:17,390 ideas. But it's not gonna solve every problem for 638 00:29:17,390 --> 00:29:21,220 everyone. These aren't rules. Like Declan said, they're not 639 00:29:21,220 --> 00:29:22,830 science. You can't just take them and throw them 640 00:29:22,830 --> 00:29:25,380 on and expect that your code will magically get 641 00:29:25,380 --> 00:29:28,320 better by going on a diet. 642 00:29:28,320 --> 00:29:31,230 And be more than just a Rails developer. Not 643 00:29:31,230 --> 00:29:33,810 that it's bad to be a Rails developer, but 644 00:29:33,810 --> 00:29:40,810 these things apply across, across languages and stuff. Like, 645 00:29:41,370 --> 00:29:45,370 don't just learn Ruby. Learn, learn beyond that. So 646 00:29:45,370 --> 00:29:49,360 as Declan mentioned, we have this GitHUb that we've 647 00:29:49,360 --> 00:29:51,980 set up, and right now it's just a readme. 648 00:29:51,980 --> 00:29:54,540 We don't actually have the code in their yet. 649 00:29:54,540 --> 00:29:56,300 We'll likely put some of the code we showed 650 00:29:56,300 --> 00:29:58,920 today, especially the repository bits. 651 00:29:58,920 --> 00:30:02,180 But we'd love to continue the discussion via issues, 652 00:30:02,180 --> 00:30:05,750 pull requests, whatever. That would be awesome. And, and 653 00:30:05,750 --> 00:30:07,000 we'd love to talk to you about some of 654 00:30:07,000 --> 00:30:10,530 it throughout this week as well. In fact, I'm 655 00:30:10,530 --> 00:30:15,130 gonna also mentioned, we have reading. You'll be able 656 00:30:15,130 --> 00:30:18,070 to get these slides after, so I'm just gonna 657 00:30:18,070 --> 00:30:19,070 gloss over them. 658 00:30:19,070 --> 00:30:21,690 These are a couple of the books that we've 659 00:30:21,690 --> 00:30:23,210 taken a look at to help us out with 660 00:30:23,210 --> 00:30:23,940 these things. 661 00:30:23,940 --> 00:30:26,420 D.W.: I think the crowd has spoken and it's 662 00:30:26,420 --> 00:30:28,990 time to wrap up. If you want to come 663 00:30:28,990 --> 00:30:31,370 up and talk, I'm happy to answer your questions. 664 00:30:31,370 --> 00:30:32,870 Thank you.