WEBVTT 00:00:00.512 --> 00:00:17.222 (jazzy music) 00:00:17.222 --> 00:00:20.166 Sandi:So you'd think that writing 00:00:20.166 --> 00:00:23.288 object-oriented code was hard. 00:00:23.288 --> 00:00:26.661 All you have to do is look at our apps, alright? 00:00:26.661 --> 00:00:29.972 We mean well, and we write code that almost always 00:00:29.972 --> 00:00:35.261 inevitably we eventually come to hate it. 00:00:35.261 --> 00:00:36.965 And the more I think about this, these days, 00:00:36.965 --> 00:00:39.449 somehow my job is to think about how to write better code. 00:00:39.449 --> 00:00:42.598 And the more I think about it, the more I think that 00:00:42.598 --> 00:00:47.340 all of the problems we cause have the same simple solution, 00:00:47.340 --> 00:00:49.463 and that when people ask me now 00:00:49.463 --> 00:00:51.254 how to write object-oriented code, 00:00:51.254 --> 00:00:54.771 I give them one small piece of advice. 00:00:54.771 --> 00:00:58.425 I say make smaller things, that's all it is. 00:00:58.425 --> 00:01:00.593 Make smaller classes, make smaller methods, 00:01:00.593 --> 00:01:04.931 and let them know as little about each other as possible. 00:01:04.931 --> 00:01:06.640 And lately I've been on a quest. 00:01:06.640 --> 00:01:08.234 I've had this obsession for the last couple of months, 00:01:08.234 --> 00:01:10.483 and it's been about conditionals. 00:01:10.483 --> 00:01:11.448 There's a lot of code out there 00:01:11.448 --> 00:01:12.867 with nasty conditionals in it, 00:01:12.867 --> 00:01:15.685 and I've been wondering, when should I replace 00:01:15.685 --> 00:01:17.874 conditionals with small objects, 00:01:17.874 --> 00:01:19.634 and how should I do this, 00:01:19.634 --> 00:01:22.594 and what would happen to my code if I do? 00:01:22.594 --> 00:01:24.378 And I was really confident in Miami in November 00:01:24.378 --> 00:01:26.970 and I inflicted this obsession upon Jim Weirich, 00:01:26.970 --> 00:01:29.650 whom some of you probably knew, 00:01:29.650 --> 00:01:33.449 and he pointed me in the direction of the Gilded Rose. 00:01:33.449 --> 00:01:34.879 Now this is a Kata, it's apparently 00:01:34.879 --> 00:01:37.226 really well known, but I don't get out much, 00:01:37.226 --> 00:01:38.838 so I had... (laughter) 00:01:38.838 --> 00:01:40.629 never heard of it. 00:01:40.629 --> 00:01:43.689 And so, it is so famous that you can just Google it, 00:01:43.689 --> 00:01:46.729 and get an explanation of the problem, but I didn't do that. 00:01:46.729 --> 00:01:48.379 I wanted to treat this problem as if 00:01:48.379 --> 00:01:50.345 it was a real production problem, 00:01:50.345 --> 00:01:51.973 and that my only source of information 00:01:51.973 --> 00:01:54.152 was the test and the code. 00:01:54.152 --> 00:01:56.337 And so I looked at his. 00:01:56.337 --> 00:01:58.391 I checked it out of his [repo], 00:01:58.391 --> 00:01:59.317 and I looked at the problem, 00:01:59.317 --> 00:02:02.330 and I was so interested in it that it became the skeleton 00:02:02.330 --> 00:02:06.776 around which I have hung the ideas for today's talk. 00:02:06.776 --> 00:02:09.574 I have altered his code just a little bit, 00:02:09.574 --> 00:02:11.256 but it's just to make it easier to talk about. 00:02:11.256 --> 00:02:13.688 This really is the Gilded Rose Kata, 00:02:13.688 --> 00:02:14.514 and here's how it goes. 00:02:14.514 --> 00:02:17.368 There's a Gilded Rose class, and it's structured like this. 00:02:17.368 --> 00:02:20.454 It has attributes for name, quality, and days remaining, 00:02:20.454 --> 00:02:22.326 it sets those in an initializer, 00:02:22.326 --> 00:02:24.934 and then there's a tick method. 00:02:24.934 --> 00:02:27.527 Now here's the tick method, well actually, no, 00:02:27.527 --> 00:02:32.836 that's just the first half of it, here's the rest. 00:02:32.836 --> 00:02:34.336 Now, I know you can't read this. 00:02:34.336 --> 00:02:36.229 Well, don't even try, even if you can, alright? 00:02:36.229 --> 00:02:37.384 This is the whole method. 00:02:37.384 --> 00:02:38.999 I just want you to get some sense 00:02:38.999 --> 00:02:39.845 of the size and shape of it. 00:02:39.845 --> 00:02:43.255 It's a 43-line "if" statement. 00:02:43.255 --> 00:02:45.441 And this seems really, really hard to me, 00:02:45.441 --> 00:02:48.752 but I am known to be Bullion-impaired. 00:02:48.752 --> 00:02:50.440 (laughter) 00:02:50.440 --> 00:02:52.344 So, I know that my subjective sense of how difficult this is 00:02:52.344 --> 00:02:55.268 to understand is probably not correct, 00:02:55.268 --> 00:02:57.330 and so instead I used some metrics. 00:02:57.330 --> 00:03:00.513 I ran a complexity metric called "Flog" against it. 00:03:00.513 --> 00:03:02.476 So Flog is a metric. OK, what's a metric? 00:03:02.476 --> 00:03:06.391 A metric is a crowdsource idea about something. 00:03:06.391 --> 00:03:09.619 Right? I have my own opinion about how complex this is, 00:03:09.619 --> 00:03:12.563 but I can use this sort of wisdom-of-the-crowd metric, 00:03:12.563 --> 00:03:14.658 the Flog metric, which scores... 00:03:14.658 --> 00:03:17.250 It's an ABC metric, so it scores assignments, 00:03:17.250 --> 00:03:18.789 branches, and conditionals. 00:03:18.789 --> 00:03:20.660 It just counts things, and adds them up. 00:03:20.660 --> 00:03:21.957 Higher scores are worse. 00:03:21.957 --> 00:03:23.890 They indicate a more complex code, 00:03:23.890 --> 00:03:25.240 a code that's going to be harder 00:03:25.240 --> 00:03:26.951 to understand and reason about. 00:03:26.951 --> 00:03:30.454 And so, Flog says the Gilded Rose class scored a 50, 00:03:30.454 --> 00:03:33.611 and that one method tick scored a 45. 00:03:33.611 --> 00:03:36.121 (moans) Yeah, just hurts, doesn't it? 00:03:36.121 --> 00:03:38.153 So, Flog says it's complicated, 00:03:38.153 --> 00:03:40.169 but before we go on I want to introduce 00:03:40.169 --> 00:03:44.370 a very subjective metric about complexity. 00:03:44.370 --> 00:03:45.686 So, I spend a lot of time these days 00:03:45.686 --> 00:03:51.200 going to places and looking at code I know nothing about. 00:03:51.200 --> 00:03:52.641 People call me up, and I go to their shop, 00:03:52.641 --> 00:03:54.305 and I spend a few days. 00:03:54.305 --> 00:03:55.943 And as you might imagine, 00:03:55.943 --> 00:03:59.749 no one calls me if things are going well. 00:03:59.749 --> 00:04:01.800 (laughter) Alright? 00:04:01.800 --> 00:04:03.593 And when I get there, they don't ask me 00:04:03.593 --> 00:04:06.650 to look at the code they're proud of. 00:04:06.650 --> 00:04:09.304 They ask me to look at the most heinous bits of their apps, 00:04:09.304 --> 00:04:11.178 the things that have sort of complex, 00:04:11.178 --> 00:04:13.650 lengthy contexts in history. 00:04:13.650 --> 00:04:16.584 Code that has just absolutely gotten out of hand. 00:04:16.584 --> 00:04:19.509 And not only are the explanations long and confusing 00:04:19.509 --> 00:04:21.750 because the problem is hard, 00:04:21.750 --> 00:04:22.490 but they do that thing that we all do, 00:04:22.490 --> 00:04:24.504 you know that thing you do when you have to 00:04:24.504 --> 00:04:26.406 explain a bit of code that you wrote 00:04:26.406 --> 00:04:28.416 that you're embarrassed about to someone? 00:04:28.416 --> 00:04:30.489 You don't just tell them how it works. 00:04:30.489 --> 00:04:31.559 You feel compelled to explain 00:04:31.559 --> 00:04:34.914 all the reasons why it got that way. (laughter) Right? 00:04:34.914 --> 00:04:37.155 You laugh. I do it. I know you do it, too, right? 00:04:37.155 --> 00:04:38.594 It just hurts. We hate that. 00:04:38.594 --> 00:04:40.177 And so, these explanations are long 00:04:40.177 --> 00:04:41.367 and confusing and they have lots of 00:04:41.367 --> 00:04:44.332 sort of sideways kind of information. 00:04:44.332 --> 00:04:46.199 And there's a point in time, I really mean well, 00:04:46.199 --> 00:04:47.449 but there's a point in time during every 00:04:47.449 --> 00:04:50.210 explanation when I start feeling like that dog, 00:04:50.210 --> 00:04:54.720 Ginger, in this Gary Larson's cartoon 00:04:54.720 --> 00:04:56.483 where it starts turning into, blah, blah, blah, 00:04:56.483 --> 00:04:58.474 Sandi, blah, blah, blah. (laughs) (laughter) 00:04:58.474 --> 00:05:00.400 And then suddenly I get startled back 00:05:00.400 --> 00:05:01.512 into awareness when I hear them say, 00:05:01.512 --> 00:05:03.556 "So, what do you think we should do 00:05:03.556 --> 00:05:07.211 "about this line of code?" (laughs) (laughter) 00:05:07.211 --> 00:05:08.937 And it used to terrify me, right? 00:05:08.937 --> 00:05:10.801 I felt like I had to understand everything 00:05:10.801 --> 00:05:12.931 in order to help with anything. 00:05:12.931 --> 00:05:14.371 But it turned out that after a few trips, 00:05:14.371 --> 00:05:15.956 I realized that there was a really 00:05:15.956 --> 00:05:17.413 simple thing I could do to help me 00:05:17.413 --> 00:05:19.977 identify code that they could benefit from changing. 00:05:19.977 --> 00:05:24.242 And I call this the "squint test". (laughter) 00:05:24.242 --> 00:05:25.862 Here's how it works. 00:05:25.862 --> 00:05:29.173 You squint your eyes, you lean back, 00:05:29.173 --> 00:05:30.856 and you look at the code. 00:05:30.856 --> 00:05:36.329 And we're looking for changes in shape, (laughter) 00:05:36.329 --> 00:05:39.701 and changes in color. 00:05:39.701 --> 00:05:41.270 Changes in shape mean you have nested conditionals 00:05:41.270 --> 00:05:44.208 and they are always going to be hard to reason about. 00:05:44.208 --> 00:05:45.640 Changes in color mean that your code is 00:05:45.640 --> 00:05:48.890 at differing levels of abstraction, 00:05:48.890 --> 00:05:50.337 and it means the story it tells 00:05:50.337 --> 00:05:52.343 is going to be hard to follow. 00:05:52.343 --> 00:05:53.685 Now, what is it about this code? 00:05:53.685 --> 00:05:55.512 Well, it has 16 if statements, 00:05:55.512 --> 00:05:56.977 some of those are not equal to them, 00:05:56.977 --> 00:05:58.570 and connect something with an "&", 00:05:58.570 --> 00:06:00.730 there are three magic strings, they're used all over, 00:06:00.730 --> 00:06:01.559 and a number of magic numbers, 00:06:01.559 --> 00:06:04.554 I don't even know how many. (laughter) 00:06:04.554 --> 00:06:06.210 Now, at least it has tests. 00:06:06.210 --> 00:06:07.956 Oh, I'm sorry, here are the magic strings. 00:06:07.956 --> 00:06:08.856 These three things: 00:06:08.856 --> 00:06:11.655 Brie, Sulfuras, and Backstage passes, 00:06:11.655 --> 00:06:13.365 whatever that means. 00:06:13.365 --> 00:06:17.797 And it does have tests, and they pass. 00:06:17.797 --> 00:06:21.632 Now, there are six skipped tests, alright? (laughter) 00:06:21.632 --> 00:06:24.820 So, I don't know what that's about. 00:06:24.820 --> 00:06:26.934 And so, I pry open the code, I just look at this first test. 00:06:26.934 --> 00:06:31.153 Oh, sorry, the tests cluster around the magic strings, 00:06:31.153 --> 00:06:32.736 except for this set, which is for 00:06:32.736 --> 00:06:34.185 something called "Normal", 00:06:34.185 --> 00:06:37.712 which is never mentioned in the "if" statement. (laughter) 00:06:37.712 --> 00:06:40.370 I suspect there's something in an [L's] branch 00:06:40.370 --> 00:06:41.410 somewhere that matters here, alright? 00:06:41.410 --> 00:06:42.976 So, I pry open the test and I look at it. 00:06:42.976 --> 00:06:46.199 Here's one, they all look just like this. 00:06:46.199 --> 00:06:50.410 I'm selling something, ok? 00:06:50.410 --> 00:06:51.622 Given a Gilded Rose that has this name, 00:06:51.622 --> 00:06:55.106 attribute, and quality, those are our three [add-a-readers], 00:06:55.106 --> 00:06:59.704 When I tick, in this case, quality goes down by one, 00:06:59.704 --> 00:07:02.305 days remaining goes down by one, 00:07:02.305 --> 00:07:03.224 they both go down by one. 00:07:03.224 --> 00:07:04.258 So, it's as if I'm selling milk, 00:07:04.258 --> 00:07:06.563 or eggs, or cheese or something that has a sell-by date, 00:07:06.563 --> 00:07:10.377 that's going to expire, where they go bad at some date. 00:07:10.377 --> 00:07:12.625 OK, so, I'm still exploring around, 00:07:12.625 --> 00:07:15.145 I don't even know what my job is yet, 00:07:15.145 --> 00:07:17.576 and I look at the six skipped tests, 00:07:17.576 --> 00:07:22.850 and there is something called "Conjured", (laughter) 00:07:22.850 --> 00:07:23.279 and they all follow the same pattern, 00:07:23.279 --> 00:07:24.872 all of the tests look like given that 00:07:24.872 --> 00:07:26.809 when I tick, I see this change. 00:07:26.809 --> 00:07:30.138 And at this point, I realize, holy crap, 00:07:30.138 --> 00:07:33.457 I'm supposed to change this code. (laughter) 00:07:33.457 --> 00:07:36.948 And so I tried, I tried, 00:07:36.948 --> 00:07:41.961 very obediently, I tried, but I was a miserable failure. 00:07:41.961 --> 00:07:43.121 I couldn't do it. 00:07:43.121 --> 00:07:44.704 That 43 lines of statement defeated me. 00:07:44.704 --> 00:07:47.920 Every time I went, I would like pry open a Conjured test 00:07:47.920 --> 00:07:49.123 and I'd go make some change in that "if" statement 00:07:49.123 --> 00:07:51.940 to make that test pass, it would break something else. 00:07:51.940 --> 00:07:53.129 I spent hours on it. 00:07:53.129 --> 00:07:54.793 Now, I am impaired, but really, it was hard. 00:07:54.793 --> 00:07:56.916 It would be hard for you, too, I think. 00:07:56.916 --> 00:07:58.743 And so, if changing that "if" statement 00:07:58.743 --> 00:08:00.308 was so hard, you have to ask, 00:08:00.308 --> 00:08:02.297 why was I trying? Why did I try to do, 00:08:02.297 --> 00:08:03.457 what possessed me to try to alter 00:08:03.457 --> 00:08:09.145 that incredibly complicated bit of code? 00:08:09.145 --> 00:08:12.456 And the answer is, I felt like I was supposed to. 00:08:12.456 --> 00:08:13.634 And here's what happens, right? 00:08:13.634 --> 00:08:16.720 You write some code, someone asks for a change. 00:08:16.720 --> 00:08:17.610 What do we do? 00:08:17.610 --> 00:08:18.279 You go look around at the code base 00:08:18.279 --> 00:08:20.743 for a code that's the closest thing 00:08:20.743 --> 00:08:22.495 to the new thing you're trying to do, 00:08:22.495 --> 00:08:24.657 and you put the new code there. 00:08:24.657 --> 00:08:25.368 That's how we behave. 00:08:25.368 --> 00:08:28.480 Novices especially, they're afraid to make new objects, 00:08:28.480 --> 00:08:30.615 so they just go put more code in where they can 00:08:30.615 --> 00:08:32.515 find a thing like the thing they're trying to add, 00:08:32.515 --> 00:08:34.283 and if that place already has an "if" statement, 00:08:34.283 --> 00:08:36.948 they just put another branch on it, right? 00:08:36.948 --> 00:08:38.590 That's how it works. 00:08:38.590 --> 00:08:40.111 And what happens is, so the natural tendency 00:08:40.111 --> 00:08:41.288 of code is to grow bigger, 00:08:41.288 --> 00:08:42.460 and bigger, and bigger. 00:08:42.460 --> 00:08:43.465 And there comes a point, right? 00:08:43.465 --> 00:08:44.416 It gets bigger, and bigger, and bigger. 00:08:44.416 --> 00:08:46.306 And there comes a point where it tips, 00:08:46.306 --> 00:08:48.115 and at that point it's so big that 00:08:48.115 --> 00:08:50.536 you cannot imagine putting code anywhere else. 00:08:50.536 --> 00:08:53.216 We have a bargain to follow the pattern, 00:08:53.216 --> 00:08:55.863 and if the pattern is a good one, code gets better. 00:08:55.863 --> 00:08:59.193 And if the pattern is a bad one, we exacerbate the problem. 00:08:59.193 --> 00:09:01.720 Nobody adds a 10-line helper class to a 00:09:01.720 --> 00:09:04.213 5000-line active record object. 00:09:04.213 --> 00:09:05.636 They just get bigger. 00:09:05.636 --> 00:09:09.235 Once they reach a certain size, they just get bigger. 00:09:09.235 --> 00:09:12.809 And so, I could not follow the pattern. 00:09:12.809 --> 00:09:14.295 I was not good enough to follow the pattern, 00:09:14.295 --> 00:09:17.170 and so I decided I was going to make a new pattern, 00:09:17.170 --> 00:09:19.410 That I was going to refactor this code. 00:09:19.410 --> 00:09:21.390 Now, this is real refactoring according 00:09:21.390 --> 00:09:23.290 to the definition of refactoring, 00:09:23.290 --> 00:09:25.810 I'm going to refactor this code, 00:09:25.810 --> 00:09:26.673 I'm going to change its arrangement 00:09:26.673 --> 00:09:28.888 without altering its behavior. 00:09:28.888 --> 00:09:30.515 I'm not going to try to add Conjured, 00:09:30.515 --> 00:09:31.643 I'm going to try to move this code 00:09:31.643 --> 00:09:34.979 around so that I can add Conjured. 00:09:34.979 --> 00:09:36.681 And for refactoring, for refactoring 00:09:36.681 --> 00:09:38.966 it's like this test with a wall at your back. 00:09:38.966 --> 00:09:39.890 You've got to have tests, 00:09:39.890 --> 00:09:41.814 or you don't know what you're doing. 00:09:41.814 --> 00:09:43.304 And so, I'm just going to start at the top. 00:09:43.304 --> 00:09:44.726 I'm going to start with these Normal tests, 00:09:44.726 --> 00:09:45.731 and I've got this code. 00:09:45.731 --> 00:09:47.270 This is what tick looks like. 00:09:47.270 --> 00:09:49.412 Now this is a big, long procedure. 00:09:49.412 --> 00:09:51.367 This is not object-oriented code. 00:09:51.367 --> 00:09:54.550 In object-oriented code, you have lots of little objects, 00:09:54.550 --> 00:09:56.197 and you send messages between them. 00:09:56.197 --> 00:09:57.701 And those messages give you a level of 00:09:57.701 --> 00:09:59.624 indirection so that you can substitute 00:09:59.624 --> 00:10:01.608 different objects at the back. 00:10:01.608 --> 00:10:04.871 Messages create seams so that you can do a different thing, 00:10:04.871 --> 00:10:08.533 and there is no seam here because this is a procedure. 00:10:08.533 --> 00:10:09.793 And so the first thing I have to do 00:10:09.793 --> 00:10:13.139 if I want to refactor is I have to make a seam, 00:10:13.139 --> 00:10:15.353 and I'm going to do that just by 00:10:15.353 --> 00:10:17.928 tracking Normal and Bailing. 00:10:17.928 --> 00:10:23.173 At this point, four tests should fail, and they do, alright? 00:10:23.173 --> 00:10:26.962 And I am not about to add more code to the tick method, 00:10:26.962 --> 00:10:29.733 so I'm just going to send a message to myself, 00:10:29.733 --> 00:10:33.144 and four tests should still fail, and they do. 00:10:33.144 --> 00:10:34.340 And so, now that I believe that I have 00:10:34.340 --> 00:10:36.625 caught that execution path, 00:10:36.625 --> 00:10:38.434 I'm going to just break open the first test 00:10:38.434 --> 00:10:41.862 and I'm going to write the code and make it pass. 00:10:41.862 --> 00:10:45.242 Quality goes down by one, that's easy enough. 00:10:45.242 --> 00:10:47.710 I can write that code. 00:10:47.710 --> 00:10:52.248 Days remaining goes down by one, and that test passes. 00:10:52.248 --> 00:10:54.575 Alright? One down, three to go. 00:10:54.575 --> 00:10:56.431 Here's the next test. 00:10:56.431 --> 00:10:58.826 In this case, it looks like I'm out of time, 00:10:58.826 --> 00:11:03.226 I'm on the sale-by-date, so now quality goes down by two. 00:11:03.226 --> 00:11:07.300 So, I'll just make sure my old test keeps on passing, 00:11:07.300 --> 00:11:10.513 and I'll write code to make this test pass. 00:11:10.513 --> 00:11:12.513 And so, now I think two tests should pass, 00:11:12.513 --> 00:11:14.993 so I should have two failures. 00:11:14.993 --> 00:11:17.511 But something I just did made some test 00:11:17.511 --> 00:11:20.320 I haven't looked at pass, and we love that. 00:11:20.320 --> 00:11:24.839 I'm not even going to look at it. (laughter) Alright? 00:11:24.839 --> 00:11:26.962 I don't need to understand it, I've got tests. (laughter) 00:11:26.962 --> 00:11:28.688 OK, so I'm going to just go, 00:11:28.688 --> 00:11:30.371 I'm going to make this one pass, alright? 00:11:30.371 --> 00:11:32.922 I'll just open the last one. 00:11:32.922 --> 00:11:37.993 So, this one says if the quality is already zero, 00:11:37.993 --> 00:11:39.936 don't change it. 00:11:39.936 --> 00:11:41.817 And so I'm just going to wrap this whole thing 00:11:41.817 --> 00:11:46.145 in an "if" statement, and not do anything if quality is zero. 00:11:46.145 --> 00:11:49.105 OK, so now I'm back to green. 00:11:49.105 --> 00:11:51.761 That code was not smart or clever, 00:11:51.761 --> 00:11:53.831 but that's the whole point. 00:11:53.831 --> 00:11:56.248 Once I get to green, I can now refactor. 00:11:56.248 --> 00:11:58.968 So my goal is to get to green as quickly as possible. 00:11:58.968 --> 00:12:02.551 Red is not when you ponder the abstraction. 00:12:02.551 --> 00:12:05.650 Red is when you scramble toward green. 00:12:05.650 --> 00:12:06.311 You're trying to reach to look for the 00:12:06.311 --> 00:12:08.246 lowest hanging green here, 00:12:08.246 --> 00:12:10.920 and so I got there, I'm at green now, 00:12:10.920 --> 00:12:13.970 and I confessed to you already that I am Bullion-impaired, 00:12:13.970 --> 00:12:14.211 and I have written code that even 00:12:14.211 --> 00:12:17.825 I at this moment do not understand, 00:12:17.825 --> 00:12:20.546 but now I'm green, so I can refactor. 00:12:20.546 --> 00:12:22.273 It looks to me that they always 00:12:22.273 --> 00:12:24.695 subtract one from days remaining, 00:12:24.695 --> 00:12:25.929 so I'm going to do that first. 00:12:25.929 --> 00:12:28.537 I like that story better. 00:12:28.537 --> 00:12:31.138 It looks to me like they don't do anything, 00:12:31.138 --> 00:12:33.190 I can just bail if quality is zero, 00:12:33.190 --> 00:12:34.364 so I can take that whole outer 00:12:34.364 --> 00:12:36.472 nesting out of that "if" statement, 00:12:36.472 --> 00:12:37.482 and now once I get to here, 00:12:37.482 --> 00:12:39.936 I can ponder these two remaining cases. 00:12:39.936 --> 00:12:42.259 Are there two cases here? 00:12:42.259 --> 00:12:43.960 Is there a case where I subtract one from quality 00:12:43.960 --> 00:12:46.640 and two from quality, or is this, I don't think so. 00:12:46.640 --> 00:12:48.378 Now that I look at it this way, 00:12:48.378 --> 00:12:51.367 I think I always subtract one from quality, 00:12:51.367 --> 00:12:52.725 and there's a special case in which 00:12:52.725 --> 00:12:56.772 I subtract another, if I'm past the sell-by date. 00:12:56.772 --> 00:12:57.925 And so, I can just delete all that, 00:12:57.925 --> 00:13:00.579 and now I have this, which is all the same 00:13:00.579 --> 00:13:02.658 level of abstraction, and I can understand it. 00:13:02.658 --> 00:13:04.322 I love the story this code tells. 00:13:04.322 --> 00:13:05.528 It's very simple. 00:13:05.528 --> 00:13:08.922 It was easy to get here, and now my test will pass. 00:13:08.922 --> 00:13:09.830 Alright, so we're going to do this 00:13:09.830 --> 00:13:11.521 over and over again, much more quickly than this one. 00:13:11.521 --> 00:13:13.581 I'm going to just take you through a quick reprise here. 00:13:13.581 --> 00:13:17.470 So, I create a seam, I send a message to myself, 00:13:17.470 --> 00:13:19.107 I tracked all the execution paths into here, 00:13:19.107 --> 00:13:20.582 I wrote some code, I hated it, 00:13:20.582 --> 00:13:21.755 I got to green as quick as possible, 00:13:21.755 --> 00:13:22.868 and then I used green to let me 00:13:22.868 --> 00:13:25.225 refactor to code that was sensible, 00:13:25.225 --> 00:13:27.000 and now Normal is done. 00:13:27.000 --> 00:13:28.728 All the Normal tests passed. 00:13:28.728 --> 00:13:29.985 So, now I'm just going to bust right 00:13:29.985 --> 00:13:31.525 through all the other cases. 00:13:31.525 --> 00:13:33.809 Here's Brie, there's a whole bunch of stuff. 00:13:33.809 --> 00:13:34.835 I'm going to turn that into a case 00:13:34.835 --> 00:13:37.121 statement so I can track Brie. 00:13:37.121 --> 00:13:38.968 There are seven tests, and they're all failing now, 00:13:38.968 --> 00:13:41.539 so I have confidence that I have caught them. 00:13:41.539 --> 00:13:42.647 I'm going to write the code, 00:13:42.647 --> 00:13:43.986 but you don't even need to look at it 00:13:43.986 --> 00:13:45.417 because you can see how easy it is, right? 00:13:45.417 --> 00:13:48.900 Now that I am only having to write code for 00:13:48.900 --> 00:13:50.461 one test at a time, it's pretty simple to write the code. 00:13:50.461 --> 00:13:53.497 What I end up with looks like this. 00:13:53.497 --> 00:13:55.523 And now Brie is done. 00:13:55.523 --> 00:13:59.924 And now a really interesting thing happens. 00:13:59.924 --> 00:14:01.178 When this stuff was buried in the 00:14:01.178 --> 00:14:02.499 43-line "if" statement, 00:14:02.499 --> 00:14:06.537 I had no idea the ways in which Normal and Brie were like, 00:14:06.537 --> 00:14:10.297 but now that I'm using this, they seem a lot alike to me. 00:14:10.297 --> 00:14:12.547 Now, there's differences sort of in the driving data here, 00:14:12.547 --> 00:14:14.690 but the algorithm, you can see the shape 00:14:14.690 --> 00:14:17.297 of the algorithm here, and the algorithm is really the same. 00:14:17.297 --> 00:14:18.799 And it is very tempting. 00:14:18.799 --> 00:14:22.193 We've had the DRY rule browbeat into us so strongly, 00:14:22.193 --> 00:14:23.704 it's very tempting at this point. 00:14:23.704 --> 00:14:25.891 I'm on a road, I'm on a refactoring road. 00:14:25.891 --> 00:14:28.393 It's very tempting now to go on a tangent 00:14:28.393 --> 00:14:29.697 and try to clean this up. 00:14:29.697 --> 00:14:30.840 Because we believe the greatest, 00:14:30.840 --> 00:14:33.703 we've been taught like the greatest virtue is DRY. 00:14:33.703 --> 00:14:36.256 And I will tell you that's the wrong idea here. 00:14:36.256 --> 00:14:37.589 I'm about to get a lot more information 00:14:37.589 --> 00:14:39.520 about what this algorithm looks like, 00:14:39.520 --> 00:14:42.710 and I need to finish the refactoring I'm on 00:14:42.710 --> 00:14:44.393 before I go on any tangents, so I'm going to notice 00:14:44.393 --> 00:14:47.606 that similarity and keep the duplication, 00:14:47.606 --> 00:14:50.700 and just keep on going down this path to see where it leads. 00:14:50.700 --> 00:14:52.599 And this brings me to my first big point of this talk. 00:14:52.599 --> 00:14:56.818 It is far cheaper to keep duplication 00:14:56.818 --> 00:14:59.545 than it is to have to mess with the wrong abstraction. 00:14:59.545 --> 00:15:00.984 The first rule we teach novices 00:15:00.984 --> 00:15:03.157 is don't repeat yourself - DRY. 00:15:03.157 --> 00:15:05.849 But have you ever thought about why we teach them that rule? 00:15:05.849 --> 00:15:09.443 It's because they can't understand anything else. (laughter) 00:15:09.443 --> 00:15:10.857 They don't know anything, but by God, 00:15:10.857 --> 00:15:13.790 they can recognize duplication, and it's a good rule. 00:15:13.790 --> 00:15:15.178 I'm not saying it's a bad rule, 00:15:15.178 --> 00:15:20.916 but I'm saying that now you're grown up, you know more, 00:15:20.916 --> 00:15:22.989 and you have enough experience 00:15:22.989 --> 00:15:24.903 now to tolerate a little duplication 00:15:24.903 --> 00:15:26.448 and wait on a better abstraction. 00:15:26.448 --> 00:15:29.842 It's really hard to deal with the wrong abstraction. 00:15:29.842 --> 00:15:31.921 I often make a "dup tag". 00:15:31.921 --> 00:15:33.930 You know how you can make a "to do" tag? 00:15:33.930 --> 00:15:35.207 Like people say, "Oh, I'm going to 00:15:35.207 --> 00:15:36.627 "lose track of my duplication." 00:15:36.627 --> 00:15:37.697 Well, fix that problem. 00:15:37.697 --> 00:15:40.119 Make a "dup tag" and give every "dup" a number, 00:15:40.119 --> 00:15:43.386 so if you have the same code in two or three places, 00:15:43.386 --> 00:15:45.571 like if that's the sixth instance of duplication, 00:15:45.571 --> 00:15:46.988 give it an ID like a database, 00:15:46.988 --> 00:15:49.270 and put "dup six" in a bunch of places in your code. 00:15:49.270 --> 00:15:50.178 You'll know. 00:15:50.178 --> 00:15:51.825 You'll see the duplication if you change a part, 00:15:51.825 --> 00:15:54.147 like fix the problem of not being able to find it, 00:15:54.147 --> 00:15:56.561 rather than reaching too soon for an abstraction. 00:15:56.561 --> 00:15:59.554 It's much easier to deal with a duplication. 00:15:59.554 --> 00:16:00.714 Alright, so moving on. 00:16:00.714 --> 00:16:02.840 Here's Sulfuras. There's three tests. 00:16:02.840 --> 00:16:06.104 You would think if I put my shim in and put an empty method, 00:16:06.104 --> 00:16:12.178 I would have three test failures. (laughter) 00:16:12.178 --> 00:16:13.949 And yet they all pass. 00:16:13.949 --> 00:16:14.826 So, what's this about? 00:16:14.826 --> 00:16:16.560 Well, I look at the test and I realize 00:16:16.560 --> 00:16:17.866 in all the tests [unintelligible] that 00:16:17.866 --> 00:16:20.527 nothing happens if it's Sulfuras. 00:16:20.527 --> 00:16:22.230 And again, I had no idea when I was 00:16:22.230 --> 00:16:23.446 looking at that 43 lines of statement 00:16:23.446 --> 00:16:26.155 that somehow it all asserted that nothing happened, 00:16:26.155 --> 00:16:30.617 so it turns out this is the code that makes the tests pass. (laughter) 00:16:30.617 --> 00:16:33.945 How nice is that? We love that, OK? 00:16:33.945 --> 00:16:35.475 So here's Backstage, and there's a whole bunch of these, 00:16:35.475 --> 00:16:37.346 and it looks like this. 00:16:37.346 --> 00:16:39.462 That's the code that makes the tests pass. 00:16:39.462 --> 00:16:41.820 And so now, we're totally back to green. 00:16:41.820 --> 00:16:44.231 This looks exactly like it did when I started. 00:16:44.231 --> 00:16:46.922 And this is what I got. 00:16:46.922 --> 00:16:48.407 I put this case statement in the front, 00:16:48.407 --> 00:16:50.634 and it tracked all the execution paths. 00:16:50.634 --> 00:16:52.933 I have a bunch of methods that look like this 00:16:52.933 --> 00:16:55.785 that I created and added to the Gilded Rose class, 00:16:55.785 --> 00:16:57.207 and the rest of the tick methods still 00:16:57.207 --> 00:17:00.230 contains that monstrous 43-line "if" statement, 00:17:00.230 --> 00:17:02.851 which I don't understand, but I no longer need, 00:17:02.851 --> 00:17:06.607 so I'm just going to delete it, it's gone. 00:17:06.607 --> 00:17:11.640 Now if you don't have good tests, this may freak you out, (laughter) 00:17:11.640 --> 00:17:13.512 but then if you feel freaked out by this 00:17:13.512 --> 00:17:14.664 and you don't have good tests, 00:17:14.664 --> 00:17:16.329 you're really making a choice here, right? 00:17:16.329 --> 00:17:19.016 If you have code that you don't understand 00:17:19.016 --> 00:17:20.690 and that you're afraid to change, 00:17:20.690 --> 00:17:24.992 you can keep it forever, if you think that's a good idea, 00:17:24.992 --> 00:17:27.950 or you can put some kind of test [harness) 00:17:27.950 --> 00:17:29.267 around it so that you can refactor, 00:17:29.267 --> 00:17:31.750 but keeping it forever is not really a good choice, 00:17:31.750 --> 00:17:32.165 so you want to get to the point where 00:17:32.165 --> 00:17:34.773 you have confidence that you can safely refactor, 00:17:34.773 --> 00:17:37.347 and it means you never have to understand that code, 00:17:37.347 --> 00:17:39.894 you can do characterization tests around the edges, 00:17:39.894 --> 00:17:41.154 so that you'll have green, 00:17:41.154 --> 00:17:42.406 you'll have a wall at your back for tests, 00:17:42.406 --> 00:17:43.719 and then you can refactor your way, 00:17:43.719 --> 00:17:44.833 to the point where you can delete 00:17:44.833 --> 00:17:47.560 the code that you don't understand. 00:17:47.560 --> 00:17:48.612 And the moral of this story is that 00:17:48.612 --> 00:17:51.556 small methods are simple. 00:17:51.556 --> 00:17:52.393 Here we have it. 00:17:52.393 --> 00:17:53.651 This is the code we just wrote. 00:17:53.651 --> 00:17:55.423 This is the squint test version, don't try to read it. 00:17:55.423 --> 00:17:56.737 This is the code we just wrote on the right, 00:17:56.737 --> 00:17:58.492 and this is how we start it on the left. 00:17:58.492 --> 00:18:02.166 You notice that the shape is flat, 00:18:02.166 --> 00:18:04.216 and the colors are starting to cluster. 00:18:04.216 --> 00:18:06.510 Now, again I believe in metrics, because 00:18:06.510 --> 00:18:08.248 I know that my personal notion of what 00:18:08.248 --> 00:18:10.866 is simple or complex is just my opinion, 00:18:10.866 --> 00:18:14.915 and I totally know that metrics are fallible, 00:18:14.915 --> 00:18:18.182 but human opinion is no more precise. 00:18:18.182 --> 00:18:20.665 And that metrics are kind of a crowdsource idea 00:18:20.665 --> 00:18:22.810 of what a bunch of people thought a metric could be. 00:18:22.810 --> 00:18:26.194 It is a useful data point for me to compare to my own. 00:18:26.194 --> 00:18:27.847 The original class Flogged to 50, 00:18:27.847 --> 00:18:30.808 and this new class Flogs to 40, 00:18:30.808 --> 00:18:32.580 but that overstates its complexity 00:18:32.580 --> 00:18:33.419 because now there's a bunch of methods, 00:18:33.419 --> 00:18:36.855 and the most complex method is Backstage and if Flogs to 12. 00:18:36.855 --> 00:18:39.688 This code is way simpler. 00:18:39.688 --> 00:18:41.361 Well, this is great, and you'd think that 00:18:41.361 --> 00:18:43.673 everyone would just do this. 00:18:43.673 --> 00:18:46.168 And so, it's an interesting question why they don't. 00:18:46.168 --> 00:18:47.380 Now, one of the things I already told you, 00:18:47.380 --> 00:18:48.640 I already gave you one reason, right? 00:18:48.640 --> 00:18:50.809 We do more of what's there. 00:18:50.809 --> 00:18:53.342 And so, the tendency is to add more 00:18:53.342 --> 00:18:54.498 to the "if" statement, if that's there, 00:18:54.498 --> 00:18:55.856 but I think there's another reason 00:18:55.856 --> 00:18:58.609 why we don't undertake these refactorings, 00:18:58.609 --> 00:18:59.824 and it's because of this. 00:18:59.824 --> 00:19:02.615 I'm just going to make the 50 smaller and move it over. 00:19:02.615 --> 00:19:05.863 It took me 10 refactoring steps to get 00:19:05.863 --> 00:19:09.957 from the big conditional to a bunch of small methods, 00:19:09.957 --> 00:19:15.285 and here's the Flog score of all the intermediate steps. 00:19:15.285 --> 00:19:16.823 All the intermediate refactorings 00:19:16.823 --> 00:19:19.578 made code more complicated. 00:19:19.578 --> 00:19:21.865 I know that I'm going to get to that 40. 00:19:21.865 --> 00:19:24.266 I understand the principles of object-oriented design, 00:19:24.266 --> 00:19:25.974 and I know the value of small methods, 00:19:25.974 --> 00:19:29.209 and because of that, I believe in the refactorings, 00:19:29.209 --> 00:19:31.715 and that lets me tolerate the intermediate complexity. 00:19:31.715 --> 00:19:35.250 But if you don't know, if you haven't learned 00:19:35.250 --> 00:19:36.278 about the value of small methods, 00:19:36.278 --> 00:19:38.646 it's hard to undertake those intermediate steps. 00:19:38.646 --> 00:19:43.819 They seem like academic things that 00:19:43.819 --> 00:19:48.551 people will do that are for some pie-in-the-sky 00:19:48.551 --> 00:19:51.186 principle that don't improve code, 00:19:51.186 --> 00:19:53.240 but I can promise you that if you can see 00:19:53.240 --> 00:19:55.492 far enough to see to the end, 00:19:55.492 --> 00:19:59.817 this intermediate complexity leads to ultimate simplicity. 00:19:59.817 --> 00:20:02.822 And, so now I'm going to circle back around my task, 00:20:02.822 --> 00:20:04.170 now that I've done this refactoring, 00:20:04.170 --> 00:20:05.593 I can circle back around my original task 00:20:05.593 --> 00:20:08.490 which is to implement Conjure. 00:20:08.490 --> 00:20:10.183 How should I do this? 00:20:10.183 --> 00:20:13.764 Here's what I got, I've got this. 00:20:13.764 --> 00:20:17.569 Should I do that? 00:20:17.569 --> 00:20:20.935 It would be easy, it would be really easy. 00:20:20.935 --> 00:20:23.797 The answer to that is "no", I should not do that. 00:20:23.797 --> 00:20:26.830 That is not the way I should solve this problem, 00:20:26.830 --> 00:20:29.960 and it's because this code is not open/closed. 00:20:29.960 --> 00:20:34.327 It is not open for extension, and closed for modification. 00:20:34.327 --> 00:20:37.861 Open/closed supplies the "O" in [solid], and it is, 00:20:37.861 --> 00:20:38.951 and I'm going to say it right out loud, 00:20:38.951 --> 00:20:43.450 it's a principle of object-oriented design. 00:20:43.450 --> 00:20:46.424 It's one of the pieces of cumulative wisdom 00:20:46.424 --> 00:20:47.543 created by folks who've written 00:20:47.543 --> 00:20:49.496 a mountain of object-oriented code, 00:20:49.496 --> 00:20:51.772 and they have experienced every 00:20:51.772 --> 00:20:54.680 possible kind of programming pain. 00:20:54.680 --> 00:20:58.135 And over time, they have noticed some principles, 00:20:58.135 --> 00:21:01.264 and they developed a style guide 00:21:01.264 --> 00:21:03.749 about how to organize code. 00:21:03.749 --> 00:21:05.144 That's what object-oriented design is. 00:21:05.144 --> 00:21:07.206 That's what the rules of object-oriented design are. 00:21:07.206 --> 00:21:10.598 It's a style guide about how to organize code 00:21:10.598 --> 00:21:12.585 with all the obvious tradeoffs, 00:21:12.585 --> 00:21:14.636 all the places where you can make your own decisions. 00:21:14.636 --> 00:21:19.216 In this case, you can feel free to ignore their discoveries, 00:21:19.216 --> 00:21:20.341 in which case you'll get to experience 00:21:20.341 --> 00:21:23.465 all that pain over again for yourself. 00:21:23.465 --> 00:21:24.789 That's what will happen. 00:21:24.789 --> 00:21:26.576 On the macro level, this style guide says 00:21:26.576 --> 00:21:30.617 it's best to arrange code so that adding new behavior 00:21:30.617 --> 00:21:34.326 does not require that you edit existing code. 00:21:34.326 --> 00:21:35.661 I know that seems impossible. 00:21:35.661 --> 00:21:37.155 I'm going to say it again, right? 00:21:37.155 --> 00:21:40.460 Open/closed says you ought to be able to add new behavior 00:21:40.460 --> 00:21:43.247 without editing existing code. 00:21:43.247 --> 00:21:45.367 Now, forget about how impossible that seems for a minute. 00:21:45.367 --> 00:21:47.400 I just want you to imagine something for me. 00:21:47.400 --> 00:21:53.150 Imagine the world, imagine your apps, if that is true. 00:21:53.150 --> 00:21:55.713 Imagine that you can add new behavior 00:21:55.713 --> 00:21:57.559 without editing existing code. 00:21:57.559 --> 00:22:00.890 Think about what that means. 00:22:00.890 --> 00:22:02.483 It means you always have green tests, 00:22:02.483 --> 00:22:04.100 it means you are always safe, 00:22:04.100 --> 00:22:06.504 it means you never cause some 00:22:06.504 --> 00:22:08.680 distant and unrelated side-effect. 00:22:08.680 --> 00:22:10.921 That is a sweet, sweet world, 00:22:10.921 --> 00:22:12.991 if your code is open/closed. 00:22:12.991 --> 00:22:14.528 And so, on the macro level, we are trying to get 00:22:14.528 --> 00:22:16.438 to the point where we can add new behavior, 00:22:16.438 --> 00:22:18.223 without editing existing code. 00:22:18.223 --> 00:22:20.568 And on the micro level, what that means here, 00:22:20.568 --> 00:22:22.989 right now, in this code, 00:22:22.989 --> 00:22:24.553 is that when we see methods that have 00:22:24.553 --> 00:22:27.946 a repeating prefix or repeating suffix, 00:22:27.946 --> 00:22:30.440 there is a tortured object in there 00:22:30.440 --> 00:22:34.694 that's trying to get out. (laughter) 00:22:34.694 --> 00:22:36.726 Right here, in this place, 00:22:36.726 --> 00:22:38.374 you're about to make a decision 00:22:38.374 --> 00:22:40.500 that's going to have consequences 00:22:40.500 --> 00:22:43.341 that echo through your code base forever. 00:22:43.341 --> 00:22:45.736 Are you going to write procedures, 00:22:45.736 --> 00:22:48.264 or are you going to trust objects? 00:22:48.264 --> 00:22:50.775 If you insist on having all the logic visible, 00:22:50.775 --> 00:22:52.753 right here where you can see it, 00:22:52.753 --> 00:22:54.176 you are insisting really on knowing 00:22:54.176 --> 00:22:56.633 both the condition on which you switch, 00:22:56.633 --> 00:22:57.966 and the thing that you do, 00:22:57.966 --> 00:23:00.358 the action that you take when that switch happens. 00:23:00.358 --> 00:23:02.103 If you're uncomfortable, and unless 00:23:02.103 --> 00:23:05.890 you know both those things at once in this file, 00:23:05.890 --> 00:23:07.225 under your eyes, in this code, then you're going to 00:23:07.225 --> 00:23:09.814 be forced to add a new method right here. 00:23:09.814 --> 00:23:12.631 You have to put that conjured tick method right here. 00:23:12.631 --> 00:23:14.503 But if you don't, if you're OK with that, 00:23:14.503 --> 00:23:16.231 you can listen to object-oriented design. 00:23:16.231 --> 00:23:18.784 It says that when you have differing prefixes, 00:23:18.784 --> 00:23:21.313 and common suffixes, then what you really have 00:23:21.313 --> 00:23:25.110 is a normal class that ought to have a method tick, 00:23:25.110 --> 00:23:27.378 and a Gilded Rose ought to be holding on 00:23:27.378 --> 00:23:29.990 to an instance of it. 00:23:29.990 --> 00:23:31.833 And it is real easy to right that code. 00:23:31.833 --> 00:23:34.983 If you can think of that thing, thinking of the thing 00:23:34.983 --> 00:23:36.755 is far harder than writing the code. 00:23:36.755 --> 00:23:38.131 Here's how the code looks. 00:23:38.131 --> 00:23:39.704 I've got this Normal tick method, 00:23:39.704 --> 00:23:41.505 I'm just going to call it "tick", 00:23:41.505 --> 00:23:43.018 I'm going to put in a Normal class, 00:23:43.018 --> 00:23:44.525 I'm going to throw a cruft in there to get 00:23:44.525 --> 00:23:47.611 the initialization and the attributes defined, 00:23:47.611 --> 00:23:49.352 I'm going to go back into Gilded Rose 00:23:49.352 --> 00:23:50.855 and the Normal tick method there, 00:23:50.855 --> 00:23:52.672 I'll get an instance of my new class, 00:23:52.672 --> 00:23:56.534 and I'll forward this message - boom, that's it. 00:23:56.534 --> 00:23:59.431 Alright, well, so I've got this, 00:23:59.431 --> 00:24:02.355 so Normal is an object, but nothing else is, 00:24:02.355 --> 00:24:03.813 and I'm about to go back on the path where 00:24:03.813 --> 00:24:07.206 I have to increase intermediate complexity, 00:24:07.206 --> 00:24:08.825 because look what just happened, alright? 00:24:08.825 --> 00:24:10.994 My new Normal tick method looks like this. 00:24:10.994 --> 00:24:12.163 It uses this item class. 00:24:12.163 --> 00:24:13.765 But Brie, the Brie tick method is still 00:24:13.765 --> 00:24:16.564 calculated inside the Gilded Rose. 00:24:16.564 --> 00:24:18.248 The quality and days remaining are part 00:24:18.248 --> 00:24:20.180 of the public API for Gilded Rose, 00:24:20.180 --> 00:24:21.188 and so now I have to say, well, 00:24:21.188 --> 00:24:23.204 if I have an item, go get the item's quality, 00:24:23.204 --> 00:24:25.445 otherwise, get the one I know about. 00:24:25.445 --> 00:24:28.800 And I have to do the same thing for days remaining, alright? 00:24:28.800 --> 00:24:32.600 It looks messy, but it's short-term, it will go away. 00:24:32.600 --> 00:24:34.560 And so, let's just walk through all the other objects. 00:24:34.560 --> 00:24:35.584 Now that you understand this pattern, 00:24:35.584 --> 00:24:36.873 it's really easy, right? 00:24:36.873 --> 00:24:38.851 Class Brie, move method tick, 00:24:38.851 --> 00:24:41.924 put the cruft in there, forward the message. 00:24:41.924 --> 00:24:43.333 Easy enough. 00:24:43.333 --> 00:24:45.492 This is really interesting. 00:24:45.492 --> 00:24:47.570 Now some trust is coming into play, right? 00:24:47.570 --> 00:24:49.317 I have an empty method, look what I have to do. 00:24:49.317 --> 00:24:50.919 Make a new class, put the method in, 00:24:50.919 --> 00:24:52.486 pry this method open, get an instance 00:24:52.486 --> 00:24:53.800 of that class, forward the message. 00:24:53.800 --> 00:24:58.296 You can be forgiven for being suspicious about this, 00:24:58.296 --> 00:24:59.783 but if you trust the refactorings, 00:24:59.783 --> 00:25:00.890 you have confidence that this is 00:25:00.890 --> 00:25:02.680 going to turn out well in the end. 00:25:02.680 --> 00:25:05.766 I'm not going to diverge, I'm not taking a detour, 00:25:05.766 --> 00:25:06.838 I'm going to go all the way down 00:25:06.838 --> 00:25:09.472 this path and finish this refactoring. 00:25:09.472 --> 00:25:11.344 Backstage, I'll make the tick method, 00:25:11.344 --> 00:25:15.800 I'll make that stuff, I'll do the forwarding. 00:25:15.800 --> 00:25:21.332 Alright, so now they're all objects and I've got this. 00:25:21.332 --> 00:25:23.250 And I'm back here. 00:25:23.250 --> 00:25:27.442 So now, in the beginning, I moved logic 00:25:27.442 --> 00:25:28.423 into methods of their own, 00:25:28.423 --> 00:25:29.765 because I didn't want to put a bunch 00:25:29.765 --> 00:25:31.491 of code in this case statement, 00:25:31.491 --> 00:25:33.995 but now that I have objects, everything is simpler, 00:25:33.995 --> 00:25:37.350 and I'm going to just start rewinding my decisions. 00:25:37.350 --> 00:25:39.410 I'm just going to delete the method, 00:25:39.410 --> 00:25:41.444 and shove the code that used to be in the method 00:25:41.444 --> 00:25:44.906 back up in the branches of the case statement. 00:25:44.906 --> 00:25:46.510 We'll do that. 00:25:46.510 --> 00:25:48.400 Now, earlier I said that duplication was 00:25:48.400 --> 00:25:49.560 cheaper than the wrong abstraction, 00:25:49.560 --> 00:25:51.800 but now we're starting to see abstractions, 00:25:51.800 --> 00:25:55.122 and I'm just going to go and abstract away some duplication. 00:25:55.122 --> 00:25:56.616 I'm going to put the cruft back up in here 00:25:56.616 --> 00:25:59.664 so in Gilded Rose, I no longer need that. 00:25:59.664 --> 00:26:02.455 What I really need to do is be able to get an item. 00:26:02.455 --> 00:26:04.633 And the way I need to get an item is that. 00:26:04.633 --> 00:26:05.576 That's how I'm going to get it. 00:26:05.576 --> 00:26:06.711 If I just knew the class name, 00:26:06.711 --> 00:26:09.723 I could send that message to it, and it would work. 00:26:09.723 --> 00:26:12.217 And it's actually really easy to figure out the class name. 00:26:12.217 --> 00:26:14.540 The code's already here. 00:26:14.540 --> 00:26:17.162 It's this, there it is. 00:26:17.162 --> 00:26:18.552 That will get me the class name back, 00:26:18.552 --> 00:26:20.820 so if I just give that a name, 00:26:20.820 --> 00:26:22.530 I can send that message to myself, 00:26:22.530 --> 00:26:25.697 and now I have the right kind of item. 00:26:25.697 --> 00:26:28.810 I don't need a name anymore, so that got simpler. 00:26:28.810 --> 00:26:31.266 So now, I have separated the reason I'm switching 00:26:31.266 --> 00:26:34.920 from the thing I do when I switch. 00:26:34.920 --> 00:26:36.345 And I can just forget about what's 00:26:36.345 --> 00:26:37.702 inside that class [form] method. 00:26:37.702 --> 00:26:38.904 I don't really care anymore. 00:26:38.904 --> 00:26:40.000 It just answers the right class. 00:26:40.000 --> 00:26:41.930 It's going to work. 00:26:41.930 --> 00:26:42.514 It's going to hand back a thing that can 00:26:42.514 --> 00:26:44.793 answer the message I'm going to send to it. 00:26:44.793 --> 00:26:46.612 And now tick looks like that and these now, 00:26:46.612 --> 00:26:48.430 so I'm rewinding the complexity, 00:26:48.430 --> 00:26:49.288 I don't need this anymore. 00:26:49.288 --> 00:26:52.686 I have items in every case, so I'll get rid of all that. 00:26:52.686 --> 00:26:56.371 And now here's the whole body of code that I have. 00:26:56.371 --> 00:26:58.262 I'm holding an instance of the correct item object, 00:26:58.262 --> 00:27:00.709 and I just sent it the tick method. 00:27:00.709 --> 00:27:02.476 so, we have four different, down at the bottom there, 00:27:02.476 --> 00:27:04.856 you can see we have four different kinds of item classes, 00:27:04.856 --> 00:27:08.916 but from Gilded Rose's point of view, item is a role. 00:27:08.916 --> 00:27:12.857 It doesn't think of it like this, it thinks of it like that. 00:27:12.857 --> 00:27:15.907 You just need someone in there that can answer that API, 00:27:15.907 --> 00:27:19.201 that knows those messages, it's a [duck] type, if you will. 00:27:19.201 --> 00:27:20.433 And if you look at the code I have now, 00:27:20.433 --> 00:27:22.999 the message passing works like this. 00:27:22.999 --> 00:27:24.358 All these messages get forwarded, 00:27:24.358 --> 00:27:26.580 and if you had a Foo that had a Gilded Rose 00:27:26.580 --> 00:27:29.400 that sent those messages, it would look like this. 00:27:29.400 --> 00:27:32.437 And so, now I'm in a situation like this. 00:27:32.437 --> 00:27:34.390 When an object's only purpose is to 00:27:34.390 --> 00:27:35.644 forward messages somewhere else, 00:27:35.644 --> 00:27:38.852 you have to wonder if it justifies its existence. 00:27:38.852 --> 00:27:40.662 This actually is a code [unintelligible] that has a name, 00:27:40.662 --> 00:27:43.297 and its name is Middleman. 00:27:43.297 --> 00:27:46.500 So, if that's all the Gilded Rose does, 00:27:46.500 --> 00:27:48.128 it probably shouldn't exist, but it turns out 00:27:48.128 --> 00:27:50.595 it still does something important. 00:27:50.595 --> 00:27:55.750 Given a string like Normal, it can figure out what 00:27:55.750 --> 00:27:59.495 item class, what class plays the appropriate item role. 00:27:59.495 --> 00:28:01.699 And so now, I'm going to use another word 00:28:01.699 --> 00:28:05.110 that you should love, you should love this word. 00:28:05.110 --> 00:28:06.368 Gilded Rose, the only thing that 00:28:06.368 --> 00:28:09.677 Gilded Rose is is an item factory. 00:28:09.677 --> 00:28:11.767 I just need to figure out how to get the right object, 00:28:11.767 --> 00:28:13.217 and then I can send it a message. 00:28:13.217 --> 00:28:15.396 We've simplified our problem by 00:28:15.396 --> 00:28:17.976 separating the thing I'm switching on 00:28:17.976 --> 00:28:19.794 from the thing I do when I switch. 00:28:19.794 --> 00:28:21.235 We've divided those things in half, 00:28:21.235 --> 00:28:23.881 so I can make the code [unintelligible] less, 00:28:23.881 --> 00:28:26.334 and we can do smaller things. 00:28:26.334 --> 00:28:28.425 I don't need to know what they do, 00:28:28.425 --> 00:28:31.492 I just need to know how to get the right one. 00:28:31.492 --> 00:28:33.384 And so, I'm going to change this code to reflect the reality. 00:28:33.384 --> 00:28:35.417 I'm going to make Gilded Rose a module. 00:28:35.417 --> 00:28:37.737 I'm going to say four, some people put new. 00:28:37.737 --> 00:28:39.609 They make a new method on module, 00:28:39.609 --> 00:28:41.940 and I just can't bear that, 00:28:41.940 --> 00:28:44.199 but it's OK with me if you do it that way. 00:28:44.199 --> 00:28:45.476 So, I have to make it a class method 00:28:45.476 --> 00:28:46.825 because I'm calling it. 00:28:46.825 --> 00:28:48.274 I'm no longer keeping an instance of anything, 00:28:48.274 --> 00:28:50.346 so I don't need an [add-a-reader]. 00:28:50.346 --> 00:28:51.849 All these Middleman messages now, 00:28:51.849 --> 00:28:53.349 since you're really going to talk to the item 00:28:53.349 --> 00:28:54.834 that you get back when you call four, 00:28:54.834 --> 00:28:57.706 all these messages, they just go away. 00:28:57.706 --> 00:28:59.684 So now, this is what we have. 00:28:59.684 --> 00:29:01.818 And the way you use it is you send four 00:29:01.818 --> 00:29:04.390 to Gilded Rose, and it gives back an item, 00:29:04.390 --> 00:29:07.420 and it's the item that you talked to. 00:29:07.420 --> 00:29:09.367 And so, now that we've fixed the Gilded Rose, 00:29:09.367 --> 00:29:11.238 I'm going to turn my attention to the 00:29:11.238 --> 00:29:16.404 classes that play the item role. 00:29:16.404 --> 00:29:18.670 There's a lot of duplication here that 00:29:18.670 --> 00:29:19.713 we've been tolerating for a long time. 00:29:19.713 --> 00:29:20.983 They all have this in them. 00:29:20.983 --> 00:29:23.556 And I'm going to create an inheritance hierarchy, 00:29:23.556 --> 00:29:25.590 and clean that up. 00:29:25.590 --> 00:29:27.310 I'm going to make a little item class, 00:29:27.310 --> 00:29:29.783 push all that stuff up to it, then all these guys, 00:29:29.783 --> 00:29:31.368 I can delete that code from all these guys, 00:29:31.368 --> 00:29:34.903 and make them subclasses of item. 00:29:34.903 --> 00:29:37.684 Now, despite what you may have heard, 00:29:37.684 --> 00:29:41.138 inheritance is not evil, 00:29:41.138 --> 00:29:43.973 and I can tell you exactly when it's safe to use it. 00:29:43.973 --> 00:29:45.190 Now here's what you want. 00:29:45.190 --> 00:29:48.274 You want a shallow, narrow hierarchy, 00:29:48.274 --> 00:29:49.768 you don't want it to be deep, 00:29:49.768 --> 00:29:51.506 and you don't want it to be wide, alright? 00:29:51.506 --> 00:29:54.457 Shallow and narrow, you would like the subclasses to be, 00:29:54.457 --> 00:29:56.553 OK, I will say this twice. 00:29:56.553 --> 00:29:57.736 You would like the subclasses to be 00:29:57.736 --> 00:30:01.699 at the leaf nodes of your object graph, right? 00:30:01.699 --> 00:30:03.221 So, you have objects, and you've got other objects, 00:30:03.221 --> 00:30:04.166 and you've got other objects, 00:30:04.166 --> 00:30:06.494 and down at the end of your sort of tree, 00:30:06.494 --> 00:30:09.610 there are objects that don't know about any other things. 00:30:09.610 --> 00:30:11.401 Right? So we want the subclasses to be 00:30:11.401 --> 00:30:14.425 the leaf nodes of the object we have to be at the edge, 00:30:14.425 --> 00:30:17.286 and we want all the subclasses to use 00:30:17.286 --> 00:30:19.633 all the codes in the superclass. 00:30:19.633 --> 00:30:20.642 Now, I'm going to repeat that again. 00:30:20.642 --> 00:30:24.458 Shallow, narrow, subclasses at the leaf nodes, 00:30:24.458 --> 00:30:26.995 and subclasses use all the behavior in the superclass. 00:30:26.995 --> 00:30:29.398 If that is the problem that you have, 00:30:29.398 --> 00:30:31.457 there is no better solution than inheritance, 00:30:31.457 --> 00:30:34.535 and you are free to use it. 00:30:34.535 --> 00:30:37.146 So, however, although I love inheritance, 00:30:37.146 --> 00:30:40.339 I use it in appropriate ways, and it is not evil, 00:30:40.339 --> 00:30:42.741 but sometimes we are. (laughter) 00:30:42.741 --> 00:30:44.388 You might be. 00:30:44.388 --> 00:30:46.196 And it's easy to get inheritance wrong, 00:30:46.196 --> 00:30:50.227 and this tree has a little problem, 00:30:50.227 --> 00:30:52.104 and it's this, I don't like this. 00:30:52.104 --> 00:30:55.240 The public API of item is quality of days remaining, 00:30:55.240 --> 00:30:57.193 and the public API of those four subclasses 00:30:57.193 --> 00:30:59.291 contains one additional method tick. 00:30:59.291 --> 00:31:01.906 And I think that superclass ought to play the item role, 00:31:01.906 --> 00:31:04.372 which means to me it's got to implement tick. 00:31:04.372 --> 00:31:06.515 And the question then becomes, 00:31:06.515 --> 00:31:08.150 what is the appropriate implementation 00:31:08.150 --> 00:31:10.819 of tick to put in the superclass? 00:31:10.819 --> 00:31:13.352 You could define tick and have it raise an error 00:31:13.352 --> 00:31:15.494 that says subclasses have to implement tick. 00:31:15.494 --> 00:31:17.514 You could do that, I do that sometimes, 00:31:17.514 --> 00:31:19.563 but here I think there's a default implementation 00:31:19.563 --> 00:31:23.746 that's appropriate, and it's this. 00:31:23.746 --> 00:31:26.499 Do nothing. 00:31:26.499 --> 00:31:29.352 It's perfectly OK with me, tick to do nothing. 00:31:29.352 --> 00:31:30.802 And now, I did that because the 00:31:30.802 --> 00:31:32.372 inheritance heirarchy bothered me, 00:31:32.372 --> 00:31:35.200 and I'm just removing code now. 00:31:35.200 --> 00:31:37.700 Now that I've done that, you might notice something 00:31:37.700 --> 00:31:39.511 about Sulfuras' implementation of tick. 00:31:39.511 --> 00:31:42.400 It overrides item, it subclasses item to 00:31:42.400 --> 00:31:45.640 override tick to do exactly what the superclass does. 00:31:45.640 --> 00:31:50.104 And what that means is that here 00:31:50.104 --> 00:31:54.933 it would be equally correct to say this, 00:31:54.933 --> 00:31:59.496 which means that this class is not necessary 00:31:59.496 --> 00:32:01.673 and all the intermediate complexity that I created 00:32:01.673 --> 00:32:06.470 as I was following this refactoring just went away. 00:32:06.470 --> 00:32:09.671 There is no more Sulfuras class. 00:32:09.671 --> 00:32:11.770 So, I'm going to do one last thing. 00:32:11.770 --> 00:32:12.167 We're almost finished here. 00:32:12.167 --> 00:32:14.126 So, this case statement contains 00:32:14.126 --> 00:32:17.248 two different types of information. 00:32:17.248 --> 00:32:20.886 It contains a set of string to class mappings, 00:32:20.886 --> 00:32:24.384 and it contains the algorithm to hook them up. 00:32:24.384 --> 00:32:26.392 And I contend to you that case statements 00:32:26.392 --> 00:32:27.717 are meant for business logic, 00:32:27.717 --> 00:32:30.387 and this doesn't really feel like business logic. 00:32:30.387 --> 00:32:33.123 This feels like configuration information. 00:32:33.123 --> 00:32:37.361 And so, I'm just going to extract configuration data here. 00:32:37.361 --> 00:32:39.989 I'm going to make a hash, and then I'm going to change 00:32:39.989 --> 00:32:44.470 the algorithm to just be the algorithm that uses that hash. 00:32:44.470 --> 00:32:46.530 Now, in real life, this would probably go 00:32:46.530 --> 00:32:48.645 through some transitions where now the hash 00:32:48.645 --> 00:32:51.154 can change independently of the algorithm 00:32:51.154 --> 00:32:52.675 that matches these things up, 00:32:52.675 --> 00:32:54.220 and if you find the hash changing a lot, 00:32:54.220 --> 00:32:57.202 you might be tempted to maybe make it a Yamo file, 00:32:57.202 --> 00:32:58.634 and if you find the Yamo file changing a lot, 00:32:58.634 --> 00:33:01.830 you might be tempted to put in the database. 00:33:01.830 --> 00:33:03.140 Now I can vary that data independently of 00:33:03.140 --> 00:33:07.360 this rule about how they get hooked up together. 00:33:07.360 --> 00:33:10.419 And so, that's it, that's the whole refactoring. 00:33:10.419 --> 00:33:12.522 We've got a bunch of small objects 00:33:12.522 --> 00:33:14.200 now instead of small methods. 00:33:14.200 --> 00:33:15.902 Here's the whole code. 00:33:15.902 --> 00:33:18.545 In the Gilded Rose module, there's an item class, 00:33:18.545 --> 00:33:21.570 and then there's three item subclasses, 00:33:21.570 --> 00:33:23.989 each of which contains a tick method. 00:33:23.989 --> 00:33:26.499 There's a set of configuration information 00:33:26.499 --> 00:33:28.759 that's used by this algorithm to decide 00:33:28.759 --> 00:33:31.989 what item class is appropriate for what string. 00:33:31.989 --> 00:33:35.507 Here's the squint testable version of small objects, 00:33:35.507 --> 00:33:38.326 and this is it compared to the original big conditional. 00:33:38.326 --> 00:33:40.663 Now that's interesting that in the small objects string, 00:33:40.663 --> 00:33:42.277 it looks like it's nested too deep, but it's not. 00:33:42.277 --> 00:33:44.101 I just have the classes inside the modules. 00:33:44.101 --> 00:33:47.810 Right? So, that is only really one level of indenting. 00:33:47.810 --> 00:33:48.601 The more interesting comparison here is 00:33:48.601 --> 00:33:51.730 the squint test between the intermediate solution, 00:33:51.730 --> 00:33:54.377 the small method solution, and the small object solution. 00:33:54.377 --> 00:33:56.789 Notice that small objects is a little bit longer, 00:33:56.789 --> 00:34:00.990 but the colors are clustered more tightly together. 00:34:00.990 --> 00:34:02.170 So we have really distilled the things 00:34:02.170 --> 00:34:05.714 that change together in single places. 00:34:05.714 --> 00:34:08.179 Here's the Flog scores that we used to have. 00:34:08.179 --> 00:34:11.400 So, OK, I have time to make you guess. 00:34:11.400 --> 00:34:14.351 I made a bunch of small objects...what's the Flog score? 00:34:14.351 --> 00:34:18.951 Male:Well, 15. 00:34:18.951 --> 00:34:20.775 Sandi:But you know what? OK, here. 00:34:20.775 --> 00:34:23.827 What's in the intermediate, we'll come back to that. 00:34:23.827 --> 00:34:25.475 I like that 15 guess, that was an excellent guess, 00:34:25.475 --> 00:34:26.474 and you'll know why in a minute. 00:34:26.474 --> 00:34:29.928 Here's the intermediate complexity scores. 00:34:29.928 --> 00:34:30.755 Alright, so I've got this. 00:34:30.755 --> 00:34:33.159 That 33 vastly overstates the complexity 00:34:33.159 --> 00:34:36.830 of the final solution, and it's because of this. 00:34:36.830 --> 00:34:38.855 When you have the first [string] was one class, 00:34:38.855 --> 00:34:40.510 the whole Gilded Rose class, 00:34:40.510 --> 00:34:41.905 and you gotta kind of know all about that class. 00:34:41.905 --> 00:34:43.956 And the second solution of the small methods 00:34:43.956 --> 00:34:46.405 it was the Gilded Rose version two, right? 00:34:46.405 --> 00:34:48.565 It was a single class, and you gotta kind of know, 00:34:48.565 --> 00:34:50.321 you've gotta hold that class in your head. 00:34:50.321 --> 00:34:53.201 This third solution is a bunch of small classes, 00:34:53.201 --> 00:34:54.385 it's a bunch of different classes, 00:34:54.385 --> 00:34:57.670 and you don't need to reason about all of them at once. 00:34:57.670 --> 00:34:59.130 As a matter of fact, you really only need to 00:34:59.130 --> 00:35:00.856 read the most complicated object in there, 00:35:00.856 --> 00:35:02.629 and the most complicated class is a backstage class 00:35:02.629 --> 00:35:05.401 and it Flogs to 12, close to the 15, 00:35:05.401 --> 00:35:07.212 and the average complexity of the set of 00:35:07.212 --> 00:35:10.537 classes in that final solution is seven. 00:35:10.537 --> 00:35:13.921 And so, I contend to you, the complexity 00:35:13.921 --> 00:35:19.622 has fallen by 75% because I made many small objects. 00:35:19.622 --> 00:35:20.724 And so now I'm going to circle back around 00:35:20.724 --> 00:35:23.350 to my task, implement Conjured. 00:35:23.350 --> 00:35:30.343 Take a minute and imagine how to do it. 00:35:30.343 --> 00:35:34.580 There's a code that makes all the tests pass. 00:35:34.580 --> 00:35:38.387 Here's how to use it. 00:35:38.387 --> 00:35:41.242 And now we're done. 00:35:41.242 --> 00:35:45.100 Alright, so, summary. 00:35:45.100 --> 00:35:48.314 When you are new at this, they told you DRY. 00:35:48.314 --> 00:35:49.697 Right? Don't repeat yourself. 00:35:49.697 --> 00:35:51.255 And I'm not saying it's bad, 00:35:51.255 --> 00:35:53.170 and I'm not saying that duplication is good, 00:35:53.170 --> 00:35:54.442 but I'm telling you that if your choice 00:35:54.442 --> 00:35:57.169 is between duplication and the wrong abstraction, 00:35:57.169 --> 00:35:58.886 you should choose duplication. 00:35:58.886 --> 00:36:01.477 Trying to fix a problem by increasing 00:36:01.477 --> 00:36:03.574 the complexity of the wrong abstraction 00:36:03.574 --> 00:36:06.496 is like chasing a beach ball in the outgoing tide. 00:36:06.496 --> 00:36:08.295 Every time you take a stroke, it recedes ahead of you, 00:36:08.295 --> 00:36:10.548 and pretty soon, you're out way over your head. 00:36:10.548 --> 00:36:14.215 It's very hard to fix those problems. 00:36:14.215 --> 00:36:16.200 Next, don't try to get to the future. 00:36:16.200 --> 00:36:18.250 Open/closed, the right code that can 00:36:18.250 --> 00:36:20.564 adapt to the future when it arrives. 00:36:20.564 --> 00:36:22.645 New requirements, this requirement to implement Conjured 00:36:22.645 --> 00:36:26.152 was the impetus to make a change. 00:36:26.152 --> 00:36:29.609 It gives you the information you need about how 00:36:29.609 --> 00:36:32.202 to make a choice about how to rearrange your code now, 00:36:32.202 --> 00:36:35.500 so that you can do the next thing. 00:36:35.500 --> 00:36:38.712 Kent Beck has a wonderfully succinct way to put this. 00:36:38.712 --> 00:36:42.768 He says, "Make the change easy, 00:36:42.768 --> 00:36:45.420 "and then make the easy change." 00:36:45.420 --> 00:36:46.855 He actually put it a little bit longer. 00:36:46.855 --> 00:36:50.761 He said, "Make the change easy, this might be hard, 00:36:50.761 --> 00:36:52.419 "and then make the easy change." 00:36:52.419 --> 00:36:56.330 And so, we spent 99% of this talk making the change easy, 00:36:56.330 --> 00:37:00.326 and then it took one slide to make the easy change. 00:37:00.326 --> 00:37:02.524 At the core of this, at the underpinnings of all this 00:37:02.524 --> 00:37:04.545 is the idea of making small objects, 00:37:04.545 --> 00:37:07.832 making objects that had a single responsibility. 00:37:07.832 --> 00:37:12.152 And finally, trust the principles of object-oriented design. 00:37:12.152 --> 00:37:14.678 They let you predict the consequences 00:37:14.678 --> 00:37:17.630 of your code arrangement choices, 00:37:17.630 --> 00:37:20.148 and learning something about what those consequences are, 00:37:20.148 --> 00:37:22.514 is going to let you raise your game. 00:37:22.514 --> 00:37:25.306 Metrics are useful, but they're fallible, 00:37:25.306 --> 00:37:26.952 but opinions are no more precise, 00:37:26.952 --> 00:37:30.308 so use metrics to give you another body of information 00:37:30.308 --> 00:37:32.458 about how complicated your code is, 00:37:32.458 --> 00:37:35.320 and then learn the rules of object-oriented design 00:37:35.320 --> 00:37:39.400 so that you can choose which direction you want to go in. 00:37:39.400 --> 00:37:43.130 Intermediate refactorings often make code more complicated, 00:37:43.130 --> 00:37:44.371 but if you know the rules, you can 00:37:44.371 --> 00:37:46.919 trust yourself to work through complexity, 00:37:46.919 --> 00:37:50.393 and finally reach more open/closed code that's simpler, 00:37:50.393 --> 00:37:53.604 and smaller, and that lets you have straightforward, 00:37:53.604 --> 00:37:56.945 changeable, beautiful code. 00:37:56.945 --> 00:38:01.522 I'm Sandi Metz, I wrote this book, 00:38:01.522 --> 00:38:04.565 I'm writing this book, (laughter) 00:38:04.565 --> 00:38:06.780 It'll be in the slide deck. 00:38:06.780 --> 00:38:07.173 I'm teaching in London. 00:38:07.173 --> 00:38:09.310 There's a public course in London coming up in June or July, 00:38:09.310 --> 00:38:11.681 in case you're from over there. 00:38:11.681 --> 00:38:13.921 Thanks to you all, and thanks to Jim Weirich 00:38:13.921 --> 00:38:15.541 who gave me this Kata. 00:38:15.541 --> 00:38:26.890 (applause) 00:38:26.890 --> 00:38:44.484 (jazzy music)