1 00:00:00,512 --> 00:00:17,222 (jazzy music) 2 00:00:17,222 --> 00:00:20,166 Sandi:So you'd think that writing 3 00:00:20,166 --> 00:00:23,288 object-oriented code was hard. 4 00:00:23,288 --> 00:00:26,661 All you have to do is look at our apps, alright? 5 00:00:26,661 --> 00:00:29,972 We mean well, and we write code that almost always 6 00:00:29,972 --> 00:00:35,261 inevitably we eventually come to hate it. 7 00:00:35,261 --> 00:00:36,965 And the more I think about this, these days, 8 00:00:36,965 --> 00:00:39,449 somehow my job is to think about how to write better code. 9 00:00:39,449 --> 00:00:42,598 And the more I think about it, the more I think that 10 00:00:42,598 --> 00:00:47,340 all of the problems we cause have the same simple solution, 11 00:00:47,340 --> 00:00:49,463 and that when people ask me now 12 00:00:49,463 --> 00:00:51,254 how to write object-oriented code, 13 00:00:51,254 --> 00:00:54,771 I give them one small piece of advice. 14 00:00:54,771 --> 00:00:58,425 I say make smaller things, that's all it is. 15 00:00:58,425 --> 00:01:00,593 Make smaller classes, make smaller methods, 16 00:01:00,593 --> 00:01:04,931 and let them know as little about each other as possible. 17 00:01:04,931 --> 00:01:06,640 And lately I've been on a quest. 18 00:01:06,640 --> 00:01:08,234 I've had this obsession for the last couple of months, 19 00:01:08,234 --> 00:01:10,483 and it's been about conditionals. 20 00:01:10,483 --> 00:01:11,448 There's a lot of code out there 21 00:01:11,448 --> 00:01:12,867 with nasty conditionals in it, 22 00:01:12,867 --> 00:01:15,685 and I've been wondering, when should I replace 23 00:01:15,685 --> 00:01:17,874 conditionals with small objects, 24 00:01:17,874 --> 00:01:19,634 and how should I do this, 25 00:01:19,634 --> 00:01:22,594 and what would happen to my code if I do? 26 00:01:22,594 --> 00:01:24,378 And I was really confident in Miami in November 27 00:01:24,378 --> 00:01:26,970 and I inflicted this obsession upon Jim Weirich, 28 00:01:26,970 --> 00:01:29,650 whom some of you probably knew, 29 00:01:29,650 --> 00:01:33,449 and he pointed me in the direction of the Gilded Rose. 30 00:01:33,449 --> 00:01:34,879 Now this is a Kata, it's apparently 31 00:01:34,879 --> 00:01:37,226 really well known, but I don't get out much, 32 00:01:37,226 --> 00:01:38,838 so I had... (laughter) 33 00:01:38,838 --> 00:01:40,629 never heard of it. 34 00:01:40,629 --> 00:01:43,689 And so, it is so famous that you can just Google it, 35 00:01:43,689 --> 00:01:46,729 and get an explanation of the problem, but I didn't do that. 36 00:01:46,729 --> 00:01:48,379 I wanted to treat this problem as if 37 00:01:48,379 --> 00:01:50,345 it was a real production problem, 38 00:01:50,345 --> 00:01:51,973 and that my only source of information 39 00:01:51,973 --> 00:01:54,152 was the test and the code. 40 00:01:54,152 --> 00:01:56,337 And so I looked at his. 41 00:01:56,337 --> 00:01:58,391 I checked it out of his [repo], 42 00:01:58,391 --> 00:01:59,317 and I looked at the problem, 43 00:01:59,317 --> 00:02:02,330 and I was so interested in it that it became the skeleton 44 00:02:02,330 --> 00:02:06,776 around which I have hung the ideas for today's talk. 45 00:02:06,776 --> 00:02:09,574 I have altered his code just a little bit, 46 00:02:09,574 --> 00:02:11,256 but it's just to make it easier to talk about. 47 00:02:11,256 --> 00:02:13,688 This really is the Gilded Rose Kata, 48 00:02:13,688 --> 00:02:14,514 and here's how it goes. 49 00:02:14,514 --> 00:02:17,368 There's a Gilded Rose class, and it's structured like this. 50 00:02:17,368 --> 00:02:20,454 It has attributes for name, quality, and days remaining, 51 00:02:20,454 --> 00:02:22,326 it sets those in an initializer, 52 00:02:22,326 --> 00:02:24,934 and then there's a tick method. 53 00:02:24,934 --> 00:02:27,527 Now here's the tick method, well actually, no, 54 00:02:27,527 --> 00:02:32,836 that's just the first half of it, here's the rest. 55 00:02:32,836 --> 00:02:34,336 Now, I know you can't read this. 56 00:02:34,336 --> 00:02:36,229 Well, don't even try, even if you can, alright? 57 00:02:36,229 --> 00:02:37,384 This is the whole method. 58 00:02:37,384 --> 00:02:38,999 I just want you to get some sense 59 00:02:38,999 --> 00:02:39,845 of the size and shape of it. 60 00:02:39,845 --> 00:02:43,255 It's a 43-line "if" statement. 61 00:02:43,255 --> 00:02:45,441 And this seems really, really hard to me, 62 00:02:45,441 --> 00:02:48,752 but I am known to be Bullion-impaired. 63 00:02:48,752 --> 00:02:50,440 (laughter) 64 00:02:50,440 --> 00:02:52,344 So, I know that my subjective sense of how difficult this is 65 00:02:52,344 --> 00:02:55,268 to understand is probably not correct, 66 00:02:55,268 --> 00:02:57,330 and so instead I used some metrics. 67 00:02:57,330 --> 00:03:00,513 I ran a complexity metric called "Flog" against it. 68 00:03:00,513 --> 00:03:02,476 So Flog is a metric. OK, what's a metric? 69 00:03:02,476 --> 00:03:06,391 A metric is a crowdsource idea about something. 70 00:03:06,391 --> 00:03:09,619 Right? I have my own opinion about how complex this is, 71 00:03:09,619 --> 00:03:12,563 but I can use this sort of wisdom-of-the-crowd metric, 72 00:03:12,563 --> 00:03:14,658 the Flog metric, which scores... 73 00:03:14,658 --> 00:03:17,250 It's an ABC metric, so it scores assignments, 74 00:03:17,250 --> 00:03:18,789 branches, and conditionals. 75 00:03:18,789 --> 00:03:20,660 It just counts things, and adds them up. 76 00:03:20,660 --> 00:03:21,957 Higher scores are worse. 77 00:03:21,957 --> 00:03:23,890 They indicate a more complex code, 78 00:03:23,890 --> 00:03:25,240 a code that's going to be harder 79 00:03:25,240 --> 00:03:26,951 to understand and reason about. 80 00:03:26,951 --> 00:03:30,454 And so, Flog says the Gilded Rose class scored a 50, 81 00:03:30,454 --> 00:03:33,611 and that one method tick scored a 45. 82 00:03:33,611 --> 00:03:36,121 (moans) Yeah, just hurts, doesn't it? 83 00:03:36,121 --> 00:03:38,153 So, Flog says it's complicated, 84 00:03:38,153 --> 00:03:40,169 but before we go on I want to introduce 85 00:03:40,169 --> 00:03:44,370 a very subjective metric about complexity. 86 00:03:44,370 --> 00:03:45,686 So, I spend a lot of time these days 87 00:03:45,686 --> 00:03:51,200 going to places and looking at code I know nothing about. 88 00:03:51,200 --> 00:03:52,641 People call me up, and I go to their shop, 89 00:03:52,641 --> 00:03:54,305 and I spend a few days. 90 00:03:54,305 --> 00:03:55,943 And as you might imagine, 91 00:03:55,943 --> 00:03:59,749 no one calls me if things are going well. 92 00:03:59,749 --> 00:04:01,800 (laughter) Alright? 93 00:04:01,800 --> 00:04:03,593 And when I get there, they don't ask me 94 00:04:03,593 --> 00:04:06,650 to look at the code they're proud of. 95 00:04:06,650 --> 00:04:09,304 They ask me to look at the most heinous bits of their apps, 96 00:04:09,304 --> 00:04:11,178 the things that have sort of complex, 97 00:04:11,178 --> 00:04:13,650 lengthy contexts in history. 98 00:04:13,650 --> 00:04:16,584 Code that has just absolutely gotten out of hand. 99 00:04:16,584 --> 00:04:19,509 And not only are the explanations long and confusing 100 00:04:19,509 --> 00:04:21,750 because the problem is hard, 101 00:04:21,750 --> 00:04:22,490 but they do that thing that we all do, 102 00:04:22,490 --> 00:04:24,504 you know that thing you do when you have to 103 00:04:24,504 --> 00:04:26,406 explain a bit of code that you wrote 104 00:04:26,406 --> 00:04:28,416 that you're embarrassed about to someone? 105 00:04:28,416 --> 00:04:30,489 You don't just tell them how it works. 106 00:04:30,489 --> 00:04:31,559 You feel compelled to explain 107 00:04:31,559 --> 00:04:34,914 all the reasons why it got that way. (laughter) Right? 108 00:04:34,914 --> 00:04:37,155 You laugh. I do it. I know you do it, too, right? 109 00:04:37,155 --> 00:04:38,594 It just hurts. We hate that. 110 00:04:38,594 --> 00:04:40,177 And so, these explanations are long 111 00:04:40,177 --> 00:04:41,367 and confusing and they have lots of 112 00:04:41,367 --> 00:04:44,332 sort of sideways kind of information. 113 00:04:44,332 --> 00:04:46,199 And there's a point in time, I really mean well, 114 00:04:46,199 --> 00:04:47,449 but there's a point in time during every 115 00:04:47,449 --> 00:04:50,210 explanation when I start feeling like that dog, 116 00:04:50,210 --> 00:04:54,720 Ginger, in this Gary Larson's cartoon 117 00:04:54,720 --> 00:04:56,483 where it starts turning into, blah, blah, blah, 118 00:04:56,483 --> 00:04:58,474 Sandi, blah, blah, blah. (laughs) (laughter) 119 00:04:58,474 --> 00:05:00,400 And then suddenly I get startled back 120 00:05:00,400 --> 00:05:01,512 into awareness when I hear them say, 121 00:05:01,512 --> 00:05:03,556 "So, what do you think we should do 122 00:05:03,556 --> 00:05:07,211 "about this line of code?" (laughs) (laughter) 123 00:05:07,211 --> 00:05:08,937 And it used to terrify me, right? 124 00:05:08,937 --> 00:05:10,801 I felt like I had to understand everything 125 00:05:10,801 --> 00:05:12,931 in order to help with anything. 126 00:05:12,931 --> 00:05:14,371 But it turned out that after a few trips, 127 00:05:14,371 --> 00:05:15,956 I realized that there was a really 128 00:05:15,956 --> 00:05:17,413 simple thing I could do to help me 129 00:05:17,413 --> 00:05:19,977 identify code that they could benefit from changing. 130 00:05:19,977 --> 00:05:24,242 And I call this the "squint test". (laughter) 131 00:05:24,242 --> 00:05:25,862 Here's how it works. 132 00:05:25,862 --> 00:05:29,173 You squint your eyes, you lean back, 133 00:05:29,173 --> 00:05:30,856 and you look at the code. 134 00:05:30,856 --> 00:05:36,329 And we're looking for changes in shape, (laughter) 135 00:05:36,329 --> 00:05:39,701 and changes in color. 136 00:05:39,701 --> 00:05:41,270 Changes in shape mean you have nested conditionals 137 00:05:41,270 --> 00:05:44,208 and they are always going to be hard to reason about. 138 00:05:44,208 --> 00:05:45,640 Changes in color mean that your code is 139 00:05:45,640 --> 00:05:48,890 at differing levels of abstraction, 140 00:05:48,890 --> 00:05:50,337 and it means the story it tells 141 00:05:50,337 --> 00:05:52,343 is going to be hard to follow. 142 00:05:52,343 --> 00:05:53,685 Now, what is it about this code? 143 00:05:53,685 --> 00:05:55,512 Well, it has 16 if statements, 144 00:05:55,512 --> 00:05:56,977 some of those are not equal to them, 145 00:05:56,977 --> 00:05:58,570 and connect something with an "&", 146 00:05:58,570 --> 00:06:00,730 there are three magic strings, they're used all over, 147 00:06:00,730 --> 00:06:01,559 and a number of magic numbers, 148 00:06:01,559 --> 00:06:04,554 I don't even know how many. (laughter) 149 00:06:04,554 --> 00:06:06,210 Now, at least it has tests. 150 00:06:06,210 --> 00:06:07,956 Oh, I'm sorry, here are the magic strings. 151 00:06:07,956 --> 00:06:08,856 These three things: 152 00:06:08,856 --> 00:06:11,655 Brie, Sulfuras, and Backstage passes, 153 00:06:11,655 --> 00:06:13,365 whatever that means. 154 00:06:13,365 --> 00:06:17,797 And it does have tests, and they pass. 155 00:06:17,797 --> 00:06:21,632 Now, there are six skipped tests, alright? (laughter) 156 00:06:21,632 --> 00:06:24,820 So, I don't know what that's about. 157 00:06:24,820 --> 00:06:26,934 And so, I pry open the code, I just look at this first test. 158 00:06:26,934 --> 00:06:31,153 Oh, sorry, the tests cluster around the magic strings, 159 00:06:31,153 --> 00:06:32,736 except for this set, which is for 160 00:06:32,736 --> 00:06:34,185 something called "Normal", 161 00:06:34,185 --> 00:06:37,712 which is never mentioned in the "if" statement. (laughter) 162 00:06:37,712 --> 00:06:40,370 I suspect there's something in an [L's] branch 163 00:06:40,370 --> 00:06:41,410 somewhere that matters here, alright? 164 00:06:41,410 --> 00:06:42,976 So, I pry open the test and I look at it. 165 00:06:42,976 --> 00:06:46,199 Here's one, they all look just like this. 166 00:06:46,199 --> 00:06:50,410 I'm selling something, ok? 167 00:06:50,410 --> 00:06:51,622 Given a Gilded Rose that has this name, 168 00:06:51,622 --> 00:06:55,106 attribute, and quality, those are our three [add-a-readers], 169 00:06:55,106 --> 00:06:59,704 When I tick, in this case, quality goes down by one, 170 00:06:59,704 --> 00:07:02,305 days remaining goes down by one, 171 00:07:02,305 --> 00:07:03,224 they both go down by one. 172 00:07:03,224 --> 00:07:04,258 So, it's as if I'm selling milk, 173 00:07:04,258 --> 00:07:06,563 or eggs, or cheese or something that has a sell-by date, 174 00:07:06,563 --> 00:07:10,377 that's going to expire, where they go bad at some date. 175 00:07:10,377 --> 00:07:12,625 OK, so, I'm still exploring around, 176 00:07:12,625 --> 00:07:15,145 I don't even know what my job is yet, 177 00:07:15,145 --> 00:07:17,576 and I look at the six skipped tests, 178 00:07:17,576 --> 00:07:22,850 and there is something called "Conjured", (laughter) 179 00:07:22,850 --> 00:07:23,279 and they all follow the same pattern, 180 00:07:23,279 --> 00:07:24,872 all of the tests look like given that 181 00:07:24,872 --> 00:07:26,809 when I tick, I see this change. 182 00:07:26,809 --> 00:07:30,138 And at this point, I realize, holy crap, 183 00:07:30,138 --> 00:07:33,457 I'm supposed to change this code. (laughter) 184 00:07:33,457 --> 00:07:36,948 And so I tried, I tried, 185 00:07:36,948 --> 00:07:41,961 very obediently, I tried, but I was a miserable failure. 186 00:07:41,961 --> 00:07:43,121 I couldn't do it. 187 00:07:43,121 --> 00:07:44,704 That 43 lines of statement defeated me. 188 00:07:44,704 --> 00:07:47,920 Every time I went, I would like pry open a Conjured test 189 00:07:47,920 --> 00:07:49,123 and I'd go make some change in that "if" statement 190 00:07:49,123 --> 00:07:51,940 to make that test pass, it would break something else. 191 00:07:51,940 --> 00:07:53,129 I spent hours on it. 192 00:07:53,129 --> 00:07:54,793 Now, I am impaired, but really, it was hard. 193 00:07:54,793 --> 00:07:56,916 It would be hard for you, too, I think. 194 00:07:56,916 --> 00:07:58,743 And so, if changing that "if" statement 195 00:07:58,743 --> 00:08:00,308 was so hard, you have to ask, 196 00:08:00,308 --> 00:08:02,297 why was I trying? Why did I try to do, 197 00:08:02,297 --> 00:08:03,457 what possessed me to try to alter 198 00:08:03,457 --> 00:08:09,145 that incredibly complicated bit of code? 199 00:08:09,145 --> 00:08:12,456 And the answer is, I felt like I was supposed to. 200 00:08:12,456 --> 00:08:13,634 And here's what happens, right? 201 00:08:13,634 --> 00:08:16,720 You write some code, someone asks for a change. 202 00:08:16,720 --> 00:08:17,610 What do we do? 203 00:08:17,610 --> 00:08:18,279 You go look around at the code base 204 00:08:18,279 --> 00:08:20,743 for a code that's the closest thing 205 00:08:20,743 --> 00:08:22,495 to the new thing you're trying to do, 206 00:08:22,495 --> 00:08:24,657 and you put the new code there. 207 00:08:24,657 --> 00:08:25,368 That's how we behave. 208 00:08:25,368 --> 00:08:28,480 Novices especially, they're afraid to make new objects, 209 00:08:28,480 --> 00:08:30,615 so they just go put more code in where they can 210 00:08:30,615 --> 00:08:32,515 find a thing like the thing they're trying to add, 211 00:08:32,515 --> 00:08:34,283 and if that place already has an "if" statement, 212 00:08:34,283 --> 00:08:36,948 they just put another branch on it, right? 213 00:08:36,948 --> 00:08:38,590 That's how it works. 214 00:08:38,590 --> 00:08:40,111 And what happens is, so the natural tendency 215 00:08:40,111 --> 00:08:41,288 of code is to grow bigger, 216 00:08:41,288 --> 00:08:42,460 and bigger, and bigger. 217 00:08:42,460 --> 00:08:43,465 And there comes a point, right? 218 00:08:43,465 --> 00:08:44,416 It gets bigger, and bigger, and bigger. 219 00:08:44,416 --> 00:08:46,306 And there comes a point where it tips, 220 00:08:46,306 --> 00:08:48,115 and at that point it's so big that 221 00:08:48,115 --> 00:08:50,536 you cannot imagine putting code anywhere else. 222 00:08:50,536 --> 00:08:53,216 We have a bargain to follow the pattern, 223 00:08:53,216 --> 00:08:55,863 and if the pattern is a good one, code gets better. 224 00:08:55,863 --> 00:08:59,193 And if the pattern is a bad one, we exacerbate the problem. 225 00:08:59,193 --> 00:09:01,720 Nobody adds a 10-line helper class to a 226 00:09:01,720 --> 00:09:04,213 5000-line active record object. 227 00:09:04,213 --> 00:09:05,636 They just get bigger. 228 00:09:05,636 --> 00:09:09,235 Once they reach a certain size, they just get bigger. 229 00:09:09,235 --> 00:09:12,809 And so, I could not follow the pattern. 230 00:09:12,809 --> 00:09:14,295 I was not good enough to follow the pattern, 231 00:09:14,295 --> 00:09:17,170 and so I decided I was going to make a new pattern, 232 00:09:17,170 --> 00:09:19,410 That I was going to refactor this code. 233 00:09:19,410 --> 00:09:21,390 Now, this is real refactoring according 234 00:09:21,390 --> 00:09:23,290 to the definition of refactoring, 235 00:09:23,290 --> 00:09:25,810 I'm going to refactor this code, 236 00:09:25,810 --> 00:09:26,673 I'm going to change its arrangement 237 00:09:26,673 --> 00:09:28,888 without altering its behavior. 238 00:09:28,888 --> 00:09:30,515 I'm not going to try to add Conjured, 239 00:09:30,515 --> 00:09:31,643 I'm going to try to move this code 240 00:09:31,643 --> 00:09:34,979 around so that I can add Conjured. 241 00:09:34,979 --> 00:09:36,681 And for refactoring, for refactoring 242 00:09:36,681 --> 00:09:38,966 it's like this test with a wall at your back. 243 00:09:38,966 --> 00:09:39,890 You've got to have tests, 244 00:09:39,890 --> 00:09:41,814 or you don't know what you're doing. 245 00:09:41,814 --> 00:09:43,304 And so, I'm just going to start at the top. 246 00:09:43,304 --> 00:09:44,726 I'm going to start with these Normal tests, 247 00:09:44,726 --> 00:09:45,731 and I've got this code. 248 00:09:45,731 --> 00:09:47,270 This is what tick looks like. 249 00:09:47,270 --> 00:09:49,412 Now this is a big, long procedure. 250 00:09:49,412 --> 00:09:51,367 This is not object-oriented code. 251 00:09:51,367 --> 00:09:54,550 In object-oriented code, you have lots of little objects, 252 00:09:54,550 --> 00:09:56,197 and you send messages between them. 253 00:09:56,197 --> 00:09:57,701 And those messages give you a level of 254 00:09:57,701 --> 00:09:59,624 indirection so that you can substitute 255 00:09:59,624 --> 00:10:01,608 different objects at the back. 256 00:10:01,608 --> 00:10:04,871 Messages create seams so that you can do a different thing, 257 00:10:04,871 --> 00:10:08,533 and there is no seam here because this is a procedure. 258 00:10:08,533 --> 00:10:09,793 And so the first thing I have to do 259 00:10:09,793 --> 00:10:13,139 if I want to refactor is I have to make a seam, 260 00:10:13,139 --> 00:10:15,353 and I'm going to do that just by 261 00:10:15,353 --> 00:10:17,928 tracking Normal and Bailing. 262 00:10:17,928 --> 00:10:23,173 At this point, four tests should fail, and they do, alright? 263 00:10:23,173 --> 00:10:26,962 And I am not about to add more code to the tick method, 264 00:10:26,962 --> 00:10:29,733 so I'm just going to send a message to myself, 265 00:10:29,733 --> 00:10:33,144 and four tests should still fail, and they do. 266 00:10:33,144 --> 00:10:34,340 And so, now that I believe that I have 267 00:10:34,340 --> 00:10:36,625 caught that execution path, 268 00:10:36,625 --> 00:10:38,434 I'm going to just break open the first test 269 00:10:38,434 --> 00:10:41,862 and I'm going to write the code and make it pass. 270 00:10:41,862 --> 00:10:45,242 Quality goes down by one, that's easy enough. 271 00:10:45,242 --> 00:10:47,710 I can write that code. 272 00:10:47,710 --> 00:10:52,248 Days remaining goes down by one, and that test passes. 273 00:10:52,248 --> 00:10:54,575 Alright? One down, three to go. 274 00:10:54,575 --> 00:10:56,431 Here's the next test. 275 00:10:56,431 --> 00:10:58,826 In this case, it looks like I'm out of time, 276 00:10:58,826 --> 00:11:03,226 I'm on the sale-by-date, so now quality goes down by two. 277 00:11:03,226 --> 00:11:07,300 So, I'll just make sure my old test keeps on passing, 278 00:11:07,300 --> 00:11:10,513 and I'll write code to make this test pass. 279 00:11:10,513 --> 00:11:12,513 And so, now I think two tests should pass, 280 00:11:12,513 --> 00:11:14,993 so I should have two failures. 281 00:11:14,993 --> 00:11:17,511 But something I just did made some test 282 00:11:17,511 --> 00:11:20,320 I haven't looked at pass, and we love that. 283 00:11:20,320 --> 00:11:24,839 I'm not even going to look at it. (laughter) Alright? 284 00:11:24,839 --> 00:11:26,962 I don't need to understand it, I've got tests. (laughter) 285 00:11:26,962 --> 00:11:28,688 OK, so I'm going to just go, 286 00:11:28,688 --> 00:11:30,371 I'm going to make this one pass, alright? 287 00:11:30,371 --> 00:11:32,922 I'll just open the last one. 288 00:11:32,922 --> 00:11:37,993 So, this one says if the quality is already zero, 289 00:11:37,993 --> 00:11:39,936 don't change it. 290 00:11:39,936 --> 00:11:41,817 And so I'm just going to wrap this whole thing 291 00:11:41,817 --> 00:11:46,145 in an "if" statement, and not do anything if quality is zero. 292 00:11:46,145 --> 00:11:49,105 OK, so now I'm back to green. 293 00:11:49,105 --> 00:11:51,761 That code was not smart or clever, 294 00:11:51,761 --> 00:11:53,831 but that's the whole point. 295 00:11:53,831 --> 00:11:56,248 Once I get to green, I can now refactor. 296 00:11:56,248 --> 00:11:58,968 So my goal is to get to green as quickly as possible. 297 00:11:58,968 --> 00:12:02,551 Red is not when you ponder the abstraction. 298 00:12:02,551 --> 00:12:05,650 Red is when you scramble toward green. 299 00:12:05,650 --> 00:12:06,311 You're trying to reach to look for the 300 00:12:06,311 --> 00:12:08,246 lowest hanging green here, 301 00:12:08,246 --> 00:12:10,920 and so I got there, I'm at green now, 302 00:12:10,920 --> 00:12:13,970 and I confessed to you already that I am Bullion-impaired, 303 00:12:13,970 --> 00:12:14,211 and I have written code that even 304 00:12:14,211 --> 00:12:17,825 I at this moment do not understand, 305 00:12:17,825 --> 00:12:20,546 but now I'm green, so I can refactor. 306 00:12:20,546 --> 00:12:22,273 It looks to me that they always 307 00:12:22,273 --> 00:12:24,695 subtract one from days remaining, 308 00:12:24,695 --> 00:12:25,929 so I'm going to do that first. 309 00:12:25,929 --> 00:12:28,537 I like that story better. 310 00:12:28,537 --> 00:12:31,138 It looks to me like they don't do anything, 311 00:12:31,138 --> 00:12:33,190 I can just bail if quality is zero, 312 00:12:33,190 --> 00:12:34,364 so I can take that whole outer 313 00:12:34,364 --> 00:12:36,472 nesting out of that "if" statement, 314 00:12:36,472 --> 00:12:37,482 and now once I get to here, 315 00:12:37,482 --> 00:12:39,936 I can ponder these two remaining cases. 316 00:12:39,936 --> 00:12:42,259 Are there two cases here? 317 00:12:42,259 --> 00:12:43,960 Is there a case where I subtract one from quality 318 00:12:43,960 --> 00:12:46,640 and two from quality, or is this, I don't think so. 319 00:12:46,640 --> 00:12:48,378 Now that I look at it this way, 320 00:12:48,378 --> 00:12:51,367 I think I always subtract one from quality, 321 00:12:51,367 --> 00:12:52,725 and there's a special case in which 322 00:12:52,725 --> 00:12:56,772 I subtract another, if I'm past the sell-by date. 323 00:12:56,772 --> 00:12:57,925 And so, I can just delete all that, 324 00:12:57,925 --> 00:13:00,579 and now I have this, which is all the same 325 00:13:00,579 --> 00:13:02,658 level of abstraction, and I can understand it. 326 00:13:02,658 --> 00:13:04,322 I love the story this code tells. 327 00:13:04,322 --> 00:13:05,528 It's very simple. 328 00:13:05,528 --> 00:13:08,922 It was easy to get here, and now my test will pass. 329 00:13:08,922 --> 00:13:09,830 Alright, so we're going to do this 330 00:13:09,830 --> 00:13:11,521 over and over again, much more quickly than this one. 331 00:13:11,521 --> 00:13:13,581 I'm going to just take you through a quick reprise here. 332 00:13:13,581 --> 00:13:17,470 So, I create a seam, I send a message to myself, 333 00:13:17,470 --> 00:13:19,107 I tracked all the execution paths into here, 334 00:13:19,107 --> 00:13:20,582 I wrote some code, I hated it, 335 00:13:20,582 --> 00:13:21,755 I got to green as quick as possible, 336 00:13:21,755 --> 00:13:22,868 and then I used green to let me 337 00:13:22,868 --> 00:13:25,225 refactor to code that was sensible, 338 00:13:25,225 --> 00:13:27,000 and now Normal is done. 339 00:13:27,000 --> 00:13:28,728 All the Normal tests passed. 340 00:13:28,728 --> 00:13:29,985 So, now I'm just going to bust right 341 00:13:29,985 --> 00:13:31,525 through all the other cases. 342 00:13:31,525 --> 00:13:33,809 Here's Brie, there's a whole bunch of stuff. 343 00:13:33,809 --> 00:13:34,835 I'm going to turn that into a case 344 00:13:34,835 --> 00:13:37,121 statement so I can track Brie. 345 00:13:37,121 --> 00:13:38,968 There are seven tests, and they're all failing now, 346 00:13:38,968 --> 00:13:41,539 so I have confidence that I have caught them. 347 00:13:41,539 --> 00:13:42,647 I'm going to write the code, 348 00:13:42,647 --> 00:13:43,986 but you don't even need to look at it 349 00:13:43,986 --> 00:13:45,417 because you can see how easy it is, right? 350 00:13:45,417 --> 00:13:48,900 Now that I am only having to write code for 351 00:13:48,900 --> 00:13:50,461 one test at a time, it's pretty simple to write the code. 352 00:13:50,461 --> 00:13:53,497 What I end up with looks like this. 353 00:13:53,497 --> 00:13:55,523 And now Brie is done. 354 00:13:55,523 --> 00:13:59,924 And now a really interesting thing happens. 355 00:13:59,924 --> 00:14:01,178 When this stuff was buried in the 356 00:14:01,178 --> 00:14:02,499 43-line "if" statement, 357 00:14:02,499 --> 00:14:06,537 I had no idea the ways in which Normal and Brie were like, 358 00:14:06,537 --> 00:14:10,297 but now that I'm using this, they seem a lot alike to me. 359 00:14:10,297 --> 00:14:12,547 Now, there's differences sort of in the driving data here, 360 00:14:12,547 --> 00:14:14,690 but the algorithm, you can see the shape 361 00:14:14,690 --> 00:14:17,297 of the algorithm here, and the algorithm is really the same. 362 00:14:17,297 --> 00:14:18,799 And it is very tempting. 363 00:14:18,799 --> 00:14:22,193 We've had the DRY rule browbeat into us so strongly, 364 00:14:22,193 --> 00:14:23,704 it's very tempting at this point. 365 00:14:23,704 --> 00:14:25,891 I'm on a road, I'm on a refactoring road. 366 00:14:25,891 --> 00:14:28,393 It's very tempting now to go on a tangent 367 00:14:28,393 --> 00:14:29,697 and try to clean this up. 368 00:14:29,697 --> 00:14:30,840 Because we believe the greatest, 369 00:14:30,840 --> 00:14:33,703 we've been taught like the greatest virtue is DRY. 370 00:14:33,703 --> 00:14:36,256 And I will tell you that's the wrong idea here. 371 00:14:36,256 --> 00:14:37,589 I'm about to get a lot more information 372 00:14:37,589 --> 00:14:39,520 about what this algorithm looks like, 373 00:14:39,520 --> 00:14:42,710 and I need to finish the refactoring I'm on 374 00:14:42,710 --> 00:14:44,393 before I go on any tangents, so I'm going to notice 375 00:14:44,393 --> 00:14:47,606 that similarity and keep the duplication, 376 00:14:47,606 --> 00:14:50,700 and just keep on going down this path to see where it leads. 377 00:14:50,700 --> 00:14:52,599 And this brings me to my first big point of this talk. 378 00:14:52,599 --> 00:14:56,818 It is far cheaper to keep duplication 379 00:14:56,818 --> 00:14:59,545 than it is to have to mess with the wrong abstraction. 380 00:14:59,545 --> 00:15:00,984 The first rule we teach novices 381 00:15:00,984 --> 00:15:03,157 is don't repeat yourself - DRY. 382 00:15:03,157 --> 00:15:05,849 But have you ever thought about why we teach them that rule? 383 00:15:05,849 --> 00:15:09,443 It's because they can't understand anything else. (laughter) 384 00:15:09,443 --> 00:15:10,857 They don't know anything, but by God, 385 00:15:10,857 --> 00:15:13,790 they can recognize duplication, and it's a good rule. 386 00:15:13,790 --> 00:15:15,178 I'm not saying it's a bad rule, 387 00:15:15,178 --> 00:15:20,916 but I'm saying that now you're grown up, you know more, 388 00:15:20,916 --> 00:15:22,989 and you have enough experience 389 00:15:22,989 --> 00:15:24,903 now to tolerate a little duplication 390 00:15:24,903 --> 00:15:26,448 and wait on a better abstraction. 391 00:15:26,448 --> 00:15:29,842 It's really hard to deal with the wrong abstraction. 392 00:15:29,842 --> 00:15:31,921 I often make a "dup tag". 393 00:15:31,921 --> 00:15:33,930 You know how you can make a "to do" tag? 394 00:15:33,930 --> 00:15:35,207 Like people say, "Oh, I'm going to 395 00:15:35,207 --> 00:15:36,627 "lose track of my duplication." 396 00:15:36,627 --> 00:15:37,697 Well, fix that problem. 397 00:15:37,697 --> 00:15:40,119 Make a "dup tag" and give every "dup" a number, 398 00:15:40,119 --> 00:15:43,386 so if you have the same code in two or three places, 399 00:15:43,386 --> 00:15:45,571 like if that's the sixth instance of duplication, 400 00:15:45,571 --> 00:15:46,988 give it an ID like a database, 401 00:15:46,988 --> 00:15:49,270 and put "dup six" in a bunch of places in your code. 402 00:15:49,270 --> 00:15:50,178 You'll know. 403 00:15:50,178 --> 00:15:51,825 You'll see the duplication if you change a part, 404 00:15:51,825 --> 00:15:54,147 like fix the problem of not being able to find it, 405 00:15:54,147 --> 00:15:56,561 rather than reaching too soon for an abstraction. 406 00:15:56,561 --> 00:15:59,554 It's much easier to deal with a duplication. 407 00:15:59,554 --> 00:16:00,714 Alright, so moving on. 408 00:16:00,714 --> 00:16:02,840 Here's Sulfuras. There's three tests. 409 00:16:02,840 --> 00:16:06,104 You would think if I put my shim in and put an empty method, 410 00:16:06,104 --> 00:16:12,178 I would have three test failures. (laughter) 411 00:16:12,178 --> 00:16:13,949 And yet they all pass. 412 00:16:13,949 --> 00:16:14,826 So, what's this about? 413 00:16:14,826 --> 00:16:16,560 Well, I look at the test and I realize 414 00:16:16,560 --> 00:16:17,866 in all the tests [unintelligible] that 415 00:16:17,866 --> 00:16:20,527 nothing happens if it's Sulfuras. 416 00:16:20,527 --> 00:16:22,230 And again, I had no idea when I was 417 00:16:22,230 --> 00:16:23,446 looking at that 43 lines of statement 418 00:16:23,446 --> 00:16:26,155 that somehow it all asserted that nothing happened, 419 00:16:26,155 --> 00:16:30,617 so it turns out this is the code that makes the tests pass. (laughter) 420 00:16:30,617 --> 00:16:33,945 How nice is that? We love that, OK? 421 00:16:33,945 --> 00:16:35,475 So here's Backstage, and there's a whole bunch of these, 422 00:16:35,475 --> 00:16:37,346 and it looks like this. 423 00:16:37,346 --> 00:16:39,462 That's the code that makes the tests pass. 424 00:16:39,462 --> 00:16:41,820 And so now, we're totally back to green. 425 00:16:41,820 --> 00:16:44,231 This looks exactly like it did when I started. 426 00:16:44,231 --> 00:16:46,922 And this is what I got. 427 00:16:46,922 --> 00:16:48,407 I put this case statement in the front, 428 00:16:48,407 --> 00:16:50,634 and it tracked all the execution paths. 429 00:16:50,634 --> 00:16:52,933 I have a bunch of methods that look like this 430 00:16:52,933 --> 00:16:55,785 that I created and added to the Gilded Rose class, 431 00:16:55,785 --> 00:16:57,207 and the rest of the tick methods still 432 00:16:57,207 --> 00:17:00,230 contains that monstrous 43-line "if" statement, 433 00:17:00,230 --> 00:17:02,851 which I don't understand, but I no longer need, 434 00:17:02,851 --> 00:17:06,607 so I'm just going to delete it, it's gone. 435 00:17:06,607 --> 00:17:11,640 Now if you don't have good tests, this may freak you out, (laughter) 436 00:17:11,640 --> 00:17:13,512 but then if you feel freaked out by this 437 00:17:13,512 --> 00:17:14,664 and you don't have good tests, 438 00:17:14,664 --> 00:17:16,329 you're really making a choice here, right? 439 00:17:16,329 --> 00:17:19,016 If you have code that you don't understand 440 00:17:19,016 --> 00:17:20,690 and that you're afraid to change, 441 00:17:20,690 --> 00:17:24,992 you can keep it forever, if you think that's a good idea, 442 00:17:24,992 --> 00:17:27,950 or you can put some kind of test [harness) 443 00:17:27,950 --> 00:17:29,267 around it so that you can refactor, 444 00:17:29,267 --> 00:17:31,750 but keeping it forever is not really a good choice, 445 00:17:31,750 --> 00:17:32,165 so you want to get to the point where 446 00:17:32,165 --> 00:17:34,773 you have confidence that you can safely refactor, 447 00:17:34,773 --> 00:17:37,347 and it means you never have to understand that code, 448 00:17:37,347 --> 00:17:39,894 you can do characterization tests around the edges, 449 00:17:39,894 --> 00:17:41,154 so that you'll have green, 450 00:17:41,154 --> 00:17:42,406 you'll have a wall at your back for tests, 451 00:17:42,406 --> 00:17:43,719 and then you can refactor your way, 452 00:17:43,719 --> 00:17:44,833 to the point where you can delete 453 00:17:44,833 --> 00:17:47,560 the code that you don't understand. 454 00:17:47,560 --> 00:17:48,612 And the moral of this story is that 455 00:17:48,612 --> 00:17:51,556 small methods are simple. 456 00:17:51,556 --> 00:17:52,393 Here we have it. 457 00:17:52,393 --> 00:17:53,651 This is the code we just wrote. 458 00:17:53,651 --> 00:17:55,423 This is the squint test version, don't try to read it. 459 00:17:55,423 --> 00:17:56,737 This is the code we just wrote on the right, 460 00:17:56,737 --> 00:17:58,492 and this is how we start it on the left. 461 00:17:58,492 --> 00:18:02,166 You notice that the shape is flat, 462 00:18:02,166 --> 00:18:04,216 and the colors are starting to cluster. 463 00:18:04,216 --> 00:18:06,510 Now, again I believe in metrics, because 464 00:18:06,510 --> 00:18:08,248 I know that my personal notion of what 465 00:18:08,248 --> 00:18:10,866 is simple or complex is just my opinion, 466 00:18:10,866 --> 00:18:14,915 and I totally know that metrics are fallible, 467 00:18:14,915 --> 00:18:18,182 but human opinion is no more precise. 468 00:18:18,182 --> 00:18:20,665 And that metrics are kind of a crowdsource idea 469 00:18:20,665 --> 00:18:22,810 of what a bunch of people thought a metric could be. 470 00:18:22,810 --> 00:18:26,194 It is a useful data point for me to compare to my own. 471 00:18:26,194 --> 00:18:27,847 The original class Flogged to 50, 472 00:18:27,847 --> 00:18:30,808 and this new class Flogs to 40, 473 00:18:30,808 --> 00:18:32,580 but that overstates its complexity 474 00:18:32,580 --> 00:18:33,419 because now there's a bunch of methods, 475 00:18:33,419 --> 00:18:36,855 and the most complex method is Backstage and if Flogs to 12. 476 00:18:36,855 --> 00:18:39,688 This code is way simpler. 477 00:18:39,688 --> 00:18:41,361 Well, this is great, and you'd think that 478 00:18:41,361 --> 00:18:43,673 everyone would just do this. 479 00:18:43,673 --> 00:18:46,168 And so, it's an interesting question why they don't. 480 00:18:46,168 --> 00:18:47,380 Now, one of the things I already told you, 481 00:18:47,380 --> 00:18:48,640 I already gave you one reason, right? 482 00:18:48,640 --> 00:18:50,809 We do more of what's there. 483 00:18:50,809 --> 00:18:53,342 And so, the tendency is to add more 484 00:18:53,342 --> 00:18:54,498 to the "if" statement, if that's there, 485 00:18:54,498 --> 00:18:55,856 but I think there's another reason 486 00:18:55,856 --> 00:18:58,609 why we don't undertake these refactorings, 487 00:18:58,609 --> 00:18:59,824 and it's because of this. 488 00:18:59,824 --> 00:19:02,615 I'm just going to make the 50 smaller and move it over. 489 00:19:02,615 --> 00:19:05,863 It took me 10 refactoring steps to get 490 00:19:05,863 --> 00:19:09,957 from the big conditional to a bunch of small methods, 491 00:19:09,957 --> 00:19:15,285 and here's the Flog score of all the intermediate steps. 492 00:19:15,285 --> 00:19:16,823 All the intermediate refactorings 493 00:19:16,823 --> 00:19:19,578 made code more complicated. 494 00:19:19,578 --> 00:19:21,865 I know that I'm going to get to that 40. 495 00:19:21,865 --> 00:19:24,266 I understand the principles of object-oriented design, 496 00:19:24,266 --> 00:19:25,974 and I know the value of small methods, 497 00:19:25,974 --> 00:19:29,209 and because of that, I believe in the refactorings, 498 00:19:29,209 --> 00:19:31,715 and that lets me tolerate the intermediate complexity. 499 00:19:31,715 --> 00:19:35,250 But if you don't know, if you haven't learned 500 00:19:35,250 --> 00:19:36,278 about the value of small methods, 501 00:19:36,278 --> 00:19:38,646 it's hard to undertake those intermediate steps. 502 00:19:38,646 --> 00:19:43,819 They seem like academic things that 503 00:19:43,819 --> 00:19:48,551 people will do that are for some pie-in-the-sky 504 00:19:48,551 --> 00:19:51,186 principle that don't improve code, 505 00:19:51,186 --> 00:19:53,240 but I can promise you that if you can see 506 00:19:53,240 --> 00:19:55,492 far enough to see to the end, 507 00:19:55,492 --> 00:19:59,817 this intermediate complexity leads to ultimate simplicity. 508 00:19:59,817 --> 00:20:02,822 And, so now I'm going to circle back around my task, 509 00:20:02,822 --> 00:20:04,170 now that I've done this refactoring, 510 00:20:04,170 --> 00:20:05,593 I can circle back around my original task 511 00:20:05,593 --> 00:20:08,490 which is to implement Conjure. 512 00:20:08,490 --> 00:20:10,183 How should I do this? 513 00:20:10,183 --> 00:20:13,764 Here's what I got, I've got this. 514 00:20:13,764 --> 00:20:17,569 Should I do that? 515 00:20:17,569 --> 00:20:20,935 It would be easy, it would be really easy. 516 00:20:20,935 --> 00:20:23,797 The answer to that is "no", I should not do that. 517 00:20:23,797 --> 00:20:26,830 That is not the way I should solve this problem, 518 00:20:26,830 --> 00:20:29,960 and it's because this code is not open/closed. 519 00:20:29,960 --> 00:20:34,327 It is not open for extension, and closed for modification. 520 00:20:34,327 --> 00:20:37,861 Open/closed supplies the "O" in [solid], and it is, 521 00:20:37,861 --> 00:20:38,951 and I'm going to say it right out loud, 522 00:20:38,951 --> 00:20:43,450 it's a principle of object-oriented design. 523 00:20:43,450 --> 00:20:46,424 It's one of the pieces of cumulative wisdom 524 00:20:46,424 --> 00:20:47,543 created by folks who've written 525 00:20:47,543 --> 00:20:49,496 a mountain of object-oriented code, 526 00:20:49,496 --> 00:20:51,772 and they have experienced every 527 00:20:51,772 --> 00:20:54,680 possible kind of programming pain. 528 00:20:54,680 --> 00:20:58,135 And over time, they have noticed some principles, 529 00:20:58,135 --> 00:21:01,264 and they developed a style guide 530 00:21:01,264 --> 00:21:03,749 about how to organize code. 531 00:21:03,749 --> 00:21:05,144 That's what object-oriented design is. 532 00:21:05,144 --> 00:21:07,206 That's what the rules of object-oriented design are. 533 00:21:07,206 --> 00:21:10,598 It's a style guide about how to organize code 534 00:21:10,598 --> 00:21:12,585 with all the obvious tradeoffs, 535 00:21:12,585 --> 00:21:14,636 all the places where you can make your own decisions. 536 00:21:14,636 --> 00:21:19,216 In this case, you can feel free to ignore their discoveries, 537 00:21:19,216 --> 00:21:20,341 in which case you'll get to experience 538 00:21:20,341 --> 00:21:23,465 all that pain over again for yourself. 539 00:21:23,465 --> 00:21:24,789 That's what will happen. 540 00:21:24,789 --> 00:21:26,576 On the macro level, this style guide says 541 00:21:26,576 --> 00:21:30,617 it's best to arrange code so that adding new behavior 542 00:21:30,617 --> 00:21:34,326 does not require that you edit existing code. 543 00:21:34,326 --> 00:21:35,661 I know that seems impossible. 544 00:21:35,661 --> 00:21:37,155 I'm going to say it again, right? 545 00:21:37,155 --> 00:21:40,460 Open/closed says you ought to be able to add new behavior 546 00:21:40,460 --> 00:21:43,247 without editing existing code. 547 00:21:43,247 --> 00:21:45,367 Now, forget about how impossible that seems for a minute. 548 00:21:45,367 --> 00:21:47,400 I just want you to imagine something for me. 549 00:21:47,400 --> 00:21:53,150 Imagine the world, imagine your apps, if that is true. 550 00:21:53,150 --> 00:21:55,713 Imagine that you can add new behavior 551 00:21:55,713 --> 00:21:57,559 without editing existing code. 552 00:21:57,559 --> 00:22:00,890 Think about what that means. 553 00:22:00,890 --> 00:22:02,483 It means you always have green tests, 554 00:22:02,483 --> 00:22:04,100 it means you are always safe, 555 00:22:04,100 --> 00:22:06,504 it means you never cause some 556 00:22:06,504 --> 00:22:08,680 distant and unrelated side-effect. 557 00:22:08,680 --> 00:22:10,921 That is a sweet, sweet world, 558 00:22:10,921 --> 00:22:12,991 if your code is open/closed. 559 00:22:12,991 --> 00:22:14,528 And so, on the macro level, we are trying to get 560 00:22:14,528 --> 00:22:16,438 to the point where we can add new behavior, 561 00:22:16,438 --> 00:22:18,223 without editing existing code. 562 00:22:18,223 --> 00:22:20,568 And on the micro level, what that means here, 563 00:22:20,568 --> 00:22:22,989 right now, in this code, 564 00:22:22,989 --> 00:22:24,553 is that when we see methods that have 565 00:22:24,553 --> 00:22:27,946 a repeating prefix or repeating suffix, 566 00:22:27,946 --> 00:22:30,440 there is a tortured object in there 567 00:22:30,440 --> 00:22:34,694 that's trying to get out. (laughter) 568 00:22:34,694 --> 00:22:36,726 Right here, in this place, 569 00:22:36,726 --> 00:22:38,374 you're about to make a decision 570 00:22:38,374 --> 00:22:40,500 that's going to have consequences 571 00:22:40,500 --> 00:22:43,341 that echo through your code base forever. 572 00:22:43,341 --> 00:22:45,736 Are you going to write procedures, 573 00:22:45,736 --> 00:22:48,264 or are you going to trust objects? 574 00:22:48,264 --> 00:22:50,775 If you insist on having all the logic visible, 575 00:22:50,775 --> 00:22:52,753 right here where you can see it, 576 00:22:52,753 --> 00:22:54,176 you are insisting really on knowing 577 00:22:54,176 --> 00:22:56,633 both the condition on which you switch, 578 00:22:56,633 --> 00:22:57,966 and the thing that you do, 579 00:22:57,966 --> 00:23:00,358 the action that you take when that switch happens. 580 00:23:00,358 --> 00:23:02,103 If you're uncomfortable, and unless 581 00:23:02,103 --> 00:23:05,890 you know both those things at once in this file, 582 00:23:05,890 --> 00:23:07,225 under your eyes, in this code, then you're going to 583 00:23:07,225 --> 00:23:09,814 be forced to add a new method right here. 584 00:23:09,814 --> 00:23:12,631 You have to put that conjured tick method right here. 585 00:23:12,631 --> 00:23:14,503 But if you don't, if you're OK with that, 586 00:23:14,503 --> 00:23:16,231 you can listen to object-oriented design. 587 00:23:16,231 --> 00:23:18,784 It says that when you have differing prefixes, 588 00:23:18,784 --> 00:23:21,313 and common suffixes, then what you really have 589 00:23:21,313 --> 00:23:25,110 is a normal class that ought to have a method tick, 590 00:23:25,110 --> 00:23:27,378 and a Gilded Rose ought to be holding on 591 00:23:27,378 --> 00:23:29,990 to an instance of it. 592 00:23:29,990 --> 00:23:31,833 And it is real easy to right that code. 593 00:23:31,833 --> 00:23:34,983 If you can think of that thing, thinking of the thing 594 00:23:34,983 --> 00:23:36,755 is far harder than writing the code. 595 00:23:36,755 --> 00:23:38,131 Here's how the code looks. 596 00:23:38,131 --> 00:23:39,704 I've got this Normal tick method, 597 00:23:39,704 --> 00:23:41,505 I'm just going to call it "tick", 598 00:23:41,505 --> 00:23:43,018 I'm going to put in a Normal class, 599 00:23:43,018 --> 00:23:44,525 I'm going to throw a cruft in there to get 600 00:23:44,525 --> 00:23:47,611 the initialization and the attributes defined, 601 00:23:47,611 --> 00:23:49,352 I'm going to go back into Gilded Rose 602 00:23:49,352 --> 00:23:50,855 and the Normal tick method there, 603 00:23:50,855 --> 00:23:52,672 I'll get an instance of my new class, 604 00:23:52,672 --> 00:23:56,534 and I'll forward this message - boom, that's it. 605 00:23:56,534 --> 00:23:59,431 Alright, well, so I've got this, 606 00:23:59,431 --> 00:24:02,355 so Normal is an object, but nothing else is, 607 00:24:02,355 --> 00:24:03,813 and I'm about to go back on the path where 608 00:24:03,813 --> 00:24:07,206 I have to increase intermediate complexity, 609 00:24:07,206 --> 00:24:08,825 because look what just happened, alright? 610 00:24:08,825 --> 00:24:10,994 My new Normal tick method looks like this. 611 00:24:10,994 --> 00:24:12,163 It uses this item class. 612 00:24:12,163 --> 00:24:13,765 But Brie, the Brie tick method is still 613 00:24:13,765 --> 00:24:16,564 calculated inside the Gilded Rose. 614 00:24:16,564 --> 00:24:18,248 The quality and days remaining are part 615 00:24:18,248 --> 00:24:20,180 of the public API for Gilded Rose, 616 00:24:20,180 --> 00:24:21,188 and so now I have to say, well, 617 00:24:21,188 --> 00:24:23,204 if I have an item, go get the item's quality, 618 00:24:23,204 --> 00:24:25,445 otherwise, get the one I know about. 619 00:24:25,445 --> 00:24:28,800 And I have to do the same thing for days remaining, alright? 620 00:24:28,800 --> 00:24:32,600 It looks messy, but it's short-term, it will go away. 621 00:24:32,600 --> 00:24:34,560 And so, let's just walk through all the other objects. 622 00:24:34,560 --> 00:24:35,584 Now that you understand this pattern, 623 00:24:35,584 --> 00:24:36,873 it's really easy, right? 624 00:24:36,873 --> 00:24:38,851 Class Brie, move method tick, 625 00:24:38,851 --> 00:24:41,924 put the cruft in there, forward the message. 626 00:24:41,924 --> 00:24:43,333 Easy enough. 627 00:24:43,333 --> 00:24:45,492 This is really interesting. 628 00:24:45,492 --> 00:24:47,570 Now some trust is coming into play, right? 629 00:24:47,570 --> 00:24:49,317 I have an empty method, look what I have to do. 630 00:24:49,317 --> 00:24:50,919 Make a new class, put the method in, 631 00:24:50,919 --> 00:24:52,486 pry this method open, get an instance 632 00:24:52,486 --> 00:24:53,800 of that class, forward the message. 633 00:24:53,800 --> 00:24:58,296 You can be forgiven for being suspicious about this, 634 00:24:58,296 --> 00:24:59,783 but if you trust the refactorings, 635 00:24:59,783 --> 00:25:00,890 you have confidence that this is 636 00:25:00,890 --> 00:25:02,680 going to turn out well in the end. 637 00:25:02,680 --> 00:25:05,766 I'm not going to diverge, I'm not taking a detour, 638 00:25:05,766 --> 00:25:06,838 I'm going to go all the way down 639 00:25:06,838 --> 00:25:09,472 this path and finish this refactoring. 640 00:25:09,472 --> 00:25:11,344 Backstage, I'll make the tick method, 641 00:25:11,344 --> 00:25:15,800 I'll make that stuff, I'll do the forwarding. 642 00:25:15,800 --> 00:25:21,332 Alright, so now they're all objects and I've got this. 643 00:25:21,332 --> 00:25:23,250 And I'm back here. 644 00:25:23,250 --> 00:25:27,442 So now, in the beginning, I moved logic 645 00:25:27,442 --> 00:25:28,423 into methods of their own, 646 00:25:28,423 --> 00:25:29,765 because I didn't want to put a bunch 647 00:25:29,765 --> 00:25:31,491 of code in this case statement, 648 00:25:31,491 --> 00:25:33,995 but now that I have objects, everything is simpler, 649 00:25:33,995 --> 00:25:37,350 and I'm going to just start rewinding my decisions. 650 00:25:37,350 --> 00:25:39,410 I'm just going to delete the method, 651 00:25:39,410 --> 00:25:41,444 and shove the code that used to be in the method 652 00:25:41,444 --> 00:25:44,906 back up in the branches of the case statement. 653 00:25:44,906 --> 00:25:46,510 We'll do that. 654 00:25:46,510 --> 00:25:48,400 Now, earlier I said that duplication was 655 00:25:48,400 --> 00:25:49,560 cheaper than the wrong abstraction, 656 00:25:49,560 --> 00:25:51,800 but now we're starting to see abstractions, 657 00:25:51,800 --> 00:25:55,122 and I'm just going to go and abstract away some duplication. 658 00:25:55,122 --> 00:25:56,616 I'm going to put the cruft back up in here 659 00:25:56,616 --> 00:25:59,664 so in Gilded Rose, I no longer need that. 660 00:25:59,664 --> 00:26:02,455 What I really need to do is be able to get an item. 661 00:26:02,455 --> 00:26:04,633 And the way I need to get an item is that. 662 00:26:04,633 --> 00:26:05,576 That's how I'm going to get it. 663 00:26:05,576 --> 00:26:06,711 If I just knew the class name, 664 00:26:06,711 --> 00:26:09,723 I could send that message to it, and it would work. 665 00:26:09,723 --> 00:26:12,217 And it's actually really easy to figure out the class name. 666 00:26:12,217 --> 00:26:14,540 The code's already here. 667 00:26:14,540 --> 00:26:17,162 It's this, there it is. 668 00:26:17,162 --> 00:26:18,552 That will get me the class name back, 669 00:26:18,552 --> 00:26:20,820 so if I just give that a name, 670 00:26:20,820 --> 00:26:22,530 I can send that message to myself, 671 00:26:22,530 --> 00:26:25,697 and now I have the right kind of item. 672 00:26:25,697 --> 00:26:28,810 I don't need a name anymore, so that got simpler. 673 00:26:28,810 --> 00:26:31,266 So now, I have separated the reason I'm switching 674 00:26:31,266 --> 00:26:34,920 from the thing I do when I switch. 675 00:26:34,920 --> 00:26:36,345 And I can just forget about what's 676 00:26:36,345 --> 00:26:37,702 inside that class [form] method. 677 00:26:37,702 --> 00:26:38,904 I don't really care anymore. 678 00:26:38,904 --> 00:26:40,000 It just answers the right class. 679 00:26:40,000 --> 00:26:41,930 It's going to work. 680 00:26:41,930 --> 00:26:42,514 It's going to hand back a thing that can 681 00:26:42,514 --> 00:26:44,793 answer the message I'm going to send to it. 682 00:26:44,793 --> 00:26:46,612 And now tick looks like that and these now, 683 00:26:46,612 --> 00:26:48,430 so I'm rewinding the complexity, 684 00:26:48,430 --> 00:26:49,288 I don't need this anymore. 685 00:26:49,288 --> 00:26:52,686 I have items in every case, so I'll get rid of all that. 686 00:26:52,686 --> 00:26:56,371 And now here's the whole body of code that I have. 687 00:26:56,371 --> 00:26:58,262 I'm holding an instance of the correct item object, 688 00:26:58,262 --> 00:27:00,709 and I just sent it the tick method. 689 00:27:00,709 --> 00:27:02,476 so, we have four different, down at the bottom there, 690 00:27:02,476 --> 00:27:04,856 you can see we have four different kinds of item classes, 691 00:27:04,856 --> 00:27:08,916 but from Gilded Rose's point of view, item is a role. 692 00:27:08,916 --> 00:27:12,857 It doesn't think of it like this, it thinks of it like that. 693 00:27:12,857 --> 00:27:15,907 You just need someone in there that can answer that API, 694 00:27:15,907 --> 00:27:19,201 that knows those messages, it's a [duck] type, if you will. 695 00:27:19,201 --> 00:27:20,433 And if you look at the code I have now, 696 00:27:20,433 --> 00:27:22,999 the message passing works like this. 697 00:27:22,999 --> 00:27:24,358 All these messages get forwarded, 698 00:27:24,358 --> 00:27:26,580 and if you had a Foo that had a Gilded Rose 699 00:27:26,580 --> 00:27:29,400 that sent those messages, it would look like this. 700 00:27:29,400 --> 00:27:32,437 And so, now I'm in a situation like this. 701 00:27:32,437 --> 00:27:34,390 When an object's only purpose is to 702 00:27:34,390 --> 00:27:35,644 forward messages somewhere else, 703 00:27:35,644 --> 00:27:38,852 you have to wonder if it justifies its existence. 704 00:27:38,852 --> 00:27:40,662 This actually is a code [unintelligible] that has a name, 705 00:27:40,662 --> 00:27:43,297 and its name is Middleman. 706 00:27:43,297 --> 00:27:46,500 So, if that's all the Gilded Rose does, 707 00:27:46,500 --> 00:27:48,128 it probably shouldn't exist, but it turns out 708 00:27:48,128 --> 00:27:50,595 it still does something important. 709 00:27:50,595 --> 00:27:55,750 Given a string like Normal, it can figure out what 710 00:27:55,750 --> 00:27:59,495 item class, what class plays the appropriate item role. 711 00:27:59,495 --> 00:28:01,699 And so now, I'm going to use another word 712 00:28:01,699 --> 00:28:05,110 that you should love, you should love this word. 713 00:28:05,110 --> 00:28:06,368 Gilded Rose, the only thing that 714 00:28:06,368 --> 00:28:09,677 Gilded Rose is is an item factory. 715 00:28:09,677 --> 00:28:11,767 I just need to figure out how to get the right object, 716 00:28:11,767 --> 00:28:13,217 and then I can send it a message. 717 00:28:13,217 --> 00:28:15,396 We've simplified our problem by 718 00:28:15,396 --> 00:28:17,976 separating the thing I'm switching on 719 00:28:17,976 --> 00:28:19,794 from the thing I do when I switch. 720 00:28:19,794 --> 00:28:21,235 We've divided those things in half, 721 00:28:21,235 --> 00:28:23,881 so I can make the code [unintelligible] less, 722 00:28:23,881 --> 00:28:26,334 and we can do smaller things. 723 00:28:26,334 --> 00:28:28,425 I don't need to know what they do, 724 00:28:28,425 --> 00:28:31,492 I just need to know how to get the right one. 725 00:28:31,492 --> 00:28:33,384 And so, I'm going to change this code to reflect the reality. 726 00:28:33,384 --> 00:28:35,417 I'm going to make Gilded Rose a module. 727 00:28:35,417 --> 00:28:37,737 I'm going to say four, some people put new. 728 00:28:37,737 --> 00:28:39,609 They make a new method on module, 729 00:28:39,609 --> 00:28:41,940 and I just can't bear that, 730 00:28:41,940 --> 00:28:44,199 but it's OK with me if you do it that way. 731 00:28:44,199 --> 00:28:45,476 So, I have to make it a class method 732 00:28:45,476 --> 00:28:46,825 because I'm calling it. 733 00:28:46,825 --> 00:28:48,274 I'm no longer keeping an instance of anything, 734 00:28:48,274 --> 00:28:50,346 so I don't need an [add-a-reader]. 735 00:28:50,346 --> 00:28:51,849 All these Middleman messages now, 736 00:28:51,849 --> 00:28:53,349 since you're really going to talk to the item 737 00:28:53,349 --> 00:28:54,834 that you get back when you call four, 738 00:28:54,834 --> 00:28:57,706 all these messages, they just go away. 739 00:28:57,706 --> 00:28:59,684 So now, this is what we have. 740 00:28:59,684 --> 00:29:01,818 And the way you use it is you send four 741 00:29:01,818 --> 00:29:04,390 to Gilded Rose, and it gives back an item, 742 00:29:04,390 --> 00:29:07,420 and it's the item that you talked to. 743 00:29:07,420 --> 00:29:09,367 And so, now that we've fixed the Gilded Rose, 744 00:29:09,367 --> 00:29:11,238 I'm going to turn my attention to the 745 00:29:11,238 --> 00:29:16,404 classes that play the item role. 746 00:29:16,404 --> 00:29:18,670 There's a lot of duplication here that 747 00:29:18,670 --> 00:29:19,713 we've been tolerating for a long time. 748 00:29:19,713 --> 00:29:20,983 They all have this in them. 749 00:29:20,983 --> 00:29:23,556 And I'm going to create an inheritance hierarchy, 750 00:29:23,556 --> 00:29:25,590 and clean that up. 751 00:29:25,590 --> 00:29:27,310 I'm going to make a little item class, 752 00:29:27,310 --> 00:29:29,783 push all that stuff up to it, then all these guys, 753 00:29:29,783 --> 00:29:31,368 I can delete that code from all these guys, 754 00:29:31,368 --> 00:29:34,903 and make them subclasses of item. 755 00:29:34,903 --> 00:29:37,684 Now, despite what you may have heard, 756 00:29:37,684 --> 00:29:41,138 inheritance is not evil, 757 00:29:41,138 --> 00:29:43,973 and I can tell you exactly when it's safe to use it. 758 00:29:43,973 --> 00:29:45,190 Now here's what you want. 759 00:29:45,190 --> 00:29:48,274 You want a shallow, narrow hierarchy, 760 00:29:48,274 --> 00:29:49,768 you don't want it to be deep, 761 00:29:49,768 --> 00:29:51,506 and you don't want it to be wide, alright? 762 00:29:51,506 --> 00:29:54,457 Shallow and narrow, you would like the subclasses to be, 763 00:29:54,457 --> 00:29:56,553 OK, I will say this twice. 764 00:29:56,553 --> 00:29:57,736 You would like the subclasses to be 765 00:29:57,736 --> 00:30:01,699 at the leaf nodes of your object graph, right? 766 00:30:01,699 --> 00:30:03,221 So, you have objects, and you've got other objects, 767 00:30:03,221 --> 00:30:04,166 and you've got other objects, 768 00:30:04,166 --> 00:30:06,494 and down at the end of your sort of tree, 769 00:30:06,494 --> 00:30:09,610 there are objects that don't know about any other things. 770 00:30:09,610 --> 00:30:11,401 Right? So we want the subclasses to be 771 00:30:11,401 --> 00:30:14,425 the leaf nodes of the object we have to be at the edge, 772 00:30:14,425 --> 00:30:17,286 and we want all the subclasses to use 773 00:30:17,286 --> 00:30:19,633 all the codes in the superclass. 774 00:30:19,633 --> 00:30:20,642 Now, I'm going to repeat that again. 775 00:30:20,642 --> 00:30:24,458 Shallow, narrow, subclasses at the leaf nodes, 776 00:30:24,458 --> 00:30:26,995 and subclasses use all the behavior in the superclass. 777 00:30:26,995 --> 00:30:29,398 If that is the problem that you have, 778 00:30:29,398 --> 00:30:31,457 there is no better solution than inheritance, 779 00:30:31,457 --> 00:30:34,535 and you are free to use it. 780 00:30:34,535 --> 00:30:37,146 So, however, although I love inheritance, 781 00:30:37,146 --> 00:30:40,339 I use it in appropriate ways, and it is not evil, 782 00:30:40,339 --> 00:30:42,741 but sometimes we are. (laughter) 783 00:30:42,741 --> 00:30:44,388 You might be. 784 00:30:44,388 --> 00:30:46,196 And it's easy to get inheritance wrong, 785 00:30:46,196 --> 00:30:50,227 and this tree has a little problem, 786 00:30:50,227 --> 00:30:52,104 and it's this, I don't like this. 787 00:30:52,104 --> 00:30:55,240 The public API of item is quality of days remaining, 788 00:30:55,240 --> 00:30:57,193 and the public API of those four subclasses 789 00:30:57,193 --> 00:30:59,291 contains one additional method tick. 790 00:30:59,291 --> 00:31:01,906 And I think that superclass ought to play the item role, 791 00:31:01,906 --> 00:31:04,372 which means to me it's got to implement tick. 792 00:31:04,372 --> 00:31:06,515 And the question then becomes, 793 00:31:06,515 --> 00:31:08,150 what is the appropriate implementation 794 00:31:08,150 --> 00:31:10,819 of tick to put in the superclass? 795 00:31:10,819 --> 00:31:13,352 You could define tick and have it raise an error 796 00:31:13,352 --> 00:31:15,494 that says subclasses have to implement tick. 797 00:31:15,494 --> 00:31:17,514 You could do that, I do that sometimes, 798 00:31:17,514 --> 00:31:19,563 but here I think there's a default implementation 799 00:31:19,563 --> 00:31:23,746 that's appropriate, and it's this. 800 00:31:23,746 --> 00:31:26,499 Do nothing. 801 00:31:26,499 --> 00:31:29,352 It's perfectly OK with me, tick to do nothing. 802 00:31:29,352 --> 00:31:30,802 And now, I did that because the 803 00:31:30,802 --> 00:31:32,372 inheritance heirarchy bothered me, 804 00:31:32,372 --> 00:31:35,200 and I'm just removing code now. 805 00:31:35,200 --> 00:31:37,700 Now that I've done that, you might notice something 806 00:31:37,700 --> 00:31:39,511 about Sulfuras' implementation of tick. 807 00:31:39,511 --> 00:31:42,400 It overrides item, it subclasses item to 808 00:31:42,400 --> 00:31:45,640 override tick to do exactly what the superclass does. 809 00:31:45,640 --> 00:31:50,104 And what that means is that here 810 00:31:50,104 --> 00:31:54,933 it would be equally correct to say this, 811 00:31:54,933 --> 00:31:59,496 which means that this class is not necessary 812 00:31:59,496 --> 00:32:01,673 and all the intermediate complexity that I created 813 00:32:01,673 --> 00:32:06,470 as I was following this refactoring just went away. 814 00:32:06,470 --> 00:32:09,671 There is no more Sulfuras class. 815 00:32:09,671 --> 00:32:11,770 So, I'm going to do one last thing. 816 00:32:11,770 --> 00:32:12,167 We're almost finished here. 817 00:32:12,167 --> 00:32:14,126 So, this case statement contains 818 00:32:14,126 --> 00:32:17,248 two different types of information. 819 00:32:17,248 --> 00:32:20,886 It contains a set of string to class mappings, 820 00:32:20,886 --> 00:32:24,384 and it contains the algorithm to hook them up. 821 00:32:24,384 --> 00:32:26,392 And I contend to you that case statements 822 00:32:26,392 --> 00:32:27,717 are meant for business logic, 823 00:32:27,717 --> 00:32:30,387 and this doesn't really feel like business logic. 824 00:32:30,387 --> 00:32:33,123 This feels like configuration information. 825 00:32:33,123 --> 00:32:37,361 And so, I'm just going to extract configuration data here. 826 00:32:37,361 --> 00:32:39,989 I'm going to make a hash, and then I'm going to change 827 00:32:39,989 --> 00:32:44,470 the algorithm to just be the algorithm that uses that hash. 828 00:32:44,470 --> 00:32:46,530 Now, in real life, this would probably go 829 00:32:46,530 --> 00:32:48,645 through some transitions where now the hash 830 00:32:48,645 --> 00:32:51,154 can change independently of the algorithm 831 00:32:51,154 --> 00:32:52,675 that matches these things up, 832 00:32:52,675 --> 00:32:54,220 and if you find the hash changing a lot, 833 00:32:54,220 --> 00:32:57,202 you might be tempted to maybe make it a Yamo file, 834 00:32:57,202 --> 00:32:58,634 and if you find the Yamo file changing a lot, 835 00:32:58,634 --> 00:33:01,830 you might be tempted to put in the database. 836 00:33:01,830 --> 00:33:03,140 Now I can vary that data independently of 837 00:33:03,140 --> 00:33:07,360 this rule about how they get hooked up together. 838 00:33:07,360 --> 00:33:10,419 And so, that's it, that's the whole refactoring. 839 00:33:10,419 --> 00:33:12,522 We've got a bunch of small objects 840 00:33:12,522 --> 00:33:14,200 now instead of small methods. 841 00:33:14,200 --> 00:33:15,902 Here's the whole code. 842 00:33:15,902 --> 00:33:18,545 In the Gilded Rose module, there's an item class, 843 00:33:18,545 --> 00:33:21,570 and then there's three item subclasses, 844 00:33:21,570 --> 00:33:23,989 each of which contains a tick method. 845 00:33:23,989 --> 00:33:26,499 There's a set of configuration information 846 00:33:26,499 --> 00:33:28,759 that's used by this algorithm to decide 847 00:33:28,759 --> 00:33:31,989 what item class is appropriate for what string. 848 00:33:31,989 --> 00:33:35,507 Here's the squint testable version of small objects, 849 00:33:35,507 --> 00:33:38,326 and this is it compared to the original big conditional. 850 00:33:38,326 --> 00:33:40,663 Now that's interesting that in the small objects string, 851 00:33:40,663 --> 00:33:42,277 it looks like it's nested too deep, but it's not. 852 00:33:42,277 --> 00:33:44,101 I just have the classes inside the modules. 853 00:33:44,101 --> 00:33:47,810 Right? So, that is only really one level of indenting. 854 00:33:47,810 --> 00:33:48,601 The more interesting comparison here is 855 00:33:48,601 --> 00:33:51,730 the squint test between the intermediate solution, 856 00:33:51,730 --> 00:33:54,377 the small method solution, and the small object solution. 857 00:33:54,377 --> 00:33:56,789 Notice that small objects is a little bit longer, 858 00:33:56,789 --> 00:34:00,990 but the colors are clustered more tightly together. 859 00:34:00,990 --> 00:34:02,170 So we have really distilled the things 860 00:34:02,170 --> 00:34:05,714 that change together in single places. 861 00:34:05,714 --> 00:34:08,179 Here's the Flog scores that we used to have. 862 00:34:08,179 --> 00:34:11,400 So, OK, I have time to make you guess. 863 00:34:11,400 --> 00:34:14,351 I made a bunch of small objects...what's the Flog score? 864 00:34:14,351 --> 00:34:18,951 Male:Well, 15. 865 00:34:18,951 --> 00:34:20,775 Sandi:But you know what? OK, here. 866 00:34:20,775 --> 00:34:23,827 What's in the intermediate, we'll come back to that. 867 00:34:23,827 --> 00:34:25,475 I like that 15 guess, that was an excellent guess, 868 00:34:25,475 --> 00:34:26,474 and you'll know why in a minute. 869 00:34:26,474 --> 00:34:29,928 Here's the intermediate complexity scores. 870 00:34:29,928 --> 00:34:30,755 Alright, so I've got this. 871 00:34:30,755 --> 00:34:33,159 That 33 vastly overstates the complexity 872 00:34:33,159 --> 00:34:36,830 of the final solution, and it's because of this. 873 00:34:36,830 --> 00:34:38,855 When you have the first [string] was one class, 874 00:34:38,855 --> 00:34:40,510 the whole Gilded Rose class, 875 00:34:40,510 --> 00:34:41,905 and you gotta kind of know all about that class. 876 00:34:41,905 --> 00:34:43,956 And the second solution of the small methods 877 00:34:43,956 --> 00:34:46,405 it was the Gilded Rose version two, right? 878 00:34:46,405 --> 00:34:48,565 It was a single class, and you gotta kind of know, 879 00:34:48,565 --> 00:34:50,321 you've gotta hold that class in your head. 880 00:34:50,321 --> 00:34:53,201 This third solution is a bunch of small classes, 881 00:34:53,201 --> 00:34:54,385 it's a bunch of different classes, 882 00:34:54,385 --> 00:34:57,670 and you don't need to reason about all of them at once. 883 00:34:57,670 --> 00:34:59,130 As a matter of fact, you really only need to 884 00:34:59,130 --> 00:35:00,856 read the most complicated object in there, 885 00:35:00,856 --> 00:35:02,629 and the most complicated class is a backstage class 886 00:35:02,629 --> 00:35:05,401 and it Flogs to 12, close to the 15, 887 00:35:05,401 --> 00:35:07,212 and the average complexity of the set of 888 00:35:07,212 --> 00:35:10,537 classes in that final solution is seven. 889 00:35:10,537 --> 00:35:13,921 And so, I contend to you, the complexity 890 00:35:13,921 --> 00:35:19,622 has fallen by 75% because I made many small objects. 891 00:35:19,622 --> 00:35:20,724 And so now I'm going to circle back around 892 00:35:20,724 --> 00:35:23,350 to my task, implement Conjured. 893 00:35:23,350 --> 00:35:30,343 Take a minute and imagine how to do it. 894 00:35:30,343 --> 00:35:34,580 There's a code that makes all the tests pass. 895 00:35:34,580 --> 00:35:38,387 Here's how to use it. 896 00:35:38,387 --> 00:35:41,242 And now we're done. 897 00:35:41,242 --> 00:35:45,100 Alright, so, summary. 898 00:35:45,100 --> 00:35:48,314 When you are new at this, they told you DRY. 899 00:35:48,314 --> 00:35:49,697 Right? Don't repeat yourself. 900 00:35:49,697 --> 00:35:51,255 And I'm not saying it's bad, 901 00:35:51,255 --> 00:35:53,170 and I'm not saying that duplication is good, 902 00:35:53,170 --> 00:35:54,442 but I'm telling you that if your choice 903 00:35:54,442 --> 00:35:57,169 is between duplication and the wrong abstraction, 904 00:35:57,169 --> 00:35:58,886 you should choose duplication. 905 00:35:58,886 --> 00:36:01,477 Trying to fix a problem by increasing 906 00:36:01,477 --> 00:36:03,574 the complexity of the wrong abstraction 907 00:36:03,574 --> 00:36:06,496 is like chasing a beach ball in the outgoing tide. 908 00:36:06,496 --> 00:36:08,295 Every time you take a stroke, it recedes ahead of you, 909 00:36:08,295 --> 00:36:10,548 and pretty soon, you're out way over your head. 910 00:36:10,548 --> 00:36:14,215 It's very hard to fix those problems. 911 00:36:14,215 --> 00:36:16,200 Next, don't try to get to the future. 912 00:36:16,200 --> 00:36:18,250 Open/closed, the right code that can 913 00:36:18,250 --> 00:36:20,564 adapt to the future when it arrives. 914 00:36:20,564 --> 00:36:22,645 New requirements, this requirement to implement Conjured 915 00:36:22,645 --> 00:36:26,152 was the impetus to make a change. 916 00:36:26,152 --> 00:36:29,609 It gives you the information you need about how 917 00:36:29,609 --> 00:36:32,202 to make a choice about how to rearrange your code now, 918 00:36:32,202 --> 00:36:35,500 so that you can do the next thing. 919 00:36:35,500 --> 00:36:38,712 Kent Beck has a wonderfully succinct way to put this. 920 00:36:38,712 --> 00:36:42,768 He says, "Make the change easy, 921 00:36:42,768 --> 00:36:45,420 "and then make the easy change." 922 00:36:45,420 --> 00:36:46,855 He actually put it a little bit longer. 923 00:36:46,855 --> 00:36:50,761 He said, "Make the change easy, this might be hard, 924 00:36:50,761 --> 00:36:52,419 "and then make the easy change." 925 00:36:52,419 --> 00:36:56,330 And so, we spent 99% of this talk making the change easy, 926 00:36:56,330 --> 00:37:00,326 and then it took one slide to make the easy change. 927 00:37:00,326 --> 00:37:02,524 At the core of this, at the underpinnings of all this 928 00:37:02,524 --> 00:37:04,545 is the idea of making small objects, 929 00:37:04,545 --> 00:37:07,832 making objects that had a single responsibility. 930 00:37:07,832 --> 00:37:12,152 And finally, trust the principles of object-oriented design. 931 00:37:12,152 --> 00:37:14,678 They let you predict the consequences 932 00:37:14,678 --> 00:37:17,630 of your code arrangement choices, 933 00:37:17,630 --> 00:37:20,148 and learning something about what those consequences are, 934 00:37:20,148 --> 00:37:22,514 is going to let you raise your game. 935 00:37:22,514 --> 00:37:25,306 Metrics are useful, but they're fallible, 936 00:37:25,306 --> 00:37:26,952 but opinions are no more precise, 937 00:37:26,952 --> 00:37:30,308 so use metrics to give you another body of information 938 00:37:30,308 --> 00:37:32,458 about how complicated your code is, 939 00:37:32,458 --> 00:37:35,320 and then learn the rules of object-oriented design 940 00:37:35,320 --> 00:37:39,400 so that you can choose which direction you want to go in. 941 00:37:39,400 --> 00:37:43,130 Intermediate refactorings often make code more complicated, 942 00:37:43,130 --> 00:37:44,371 but if you know the rules, you can 943 00:37:44,371 --> 00:37:46,919 trust yourself to work through complexity, 944 00:37:46,919 --> 00:37:50,393 and finally reach more open/closed code that's simpler, 945 00:37:50,393 --> 00:37:53,604 and smaller, and that lets you have straightforward, 946 00:37:53,604 --> 00:37:56,945 changeable, beautiful code. 947 00:37:56,945 --> 00:38:01,522 I'm Sandi Metz, I wrote this book, 948 00:38:01,522 --> 00:38:04,565 I'm writing this book, (laughter) 949 00:38:04,565 --> 00:38:06,780 It'll be in the slide deck. 950 00:38:06,780 --> 00:38:07,173 I'm teaching in London. 951 00:38:07,173 --> 00:38:09,310 There's a public course in London coming up in June or July, 952 00:38:09,310 --> 00:38:11,681 in case you're from over there. 953 00:38:11,681 --> 00:38:13,921 Thanks to you all, and thanks to Jim Weirich 954 00:38:13,921 --> 00:38:15,541 who gave me this Kata. 955 00:38:15,541 --> 00:38:26,890 (applause) 956 00:38:26,890 --> 00:38:44,484 (jazzy music)