[Script Info] Title: [Events] Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text Dialogue: 0,0:00:05.65,0:00:09.32,Default,,0000,0000,0000,,Few things draw my attention\Nlike a looming deadline. Dialogue: 0,0:00:10.96,0:00:14.56,Default,,0000,0000,0000,,Some part of my brain\Nwatches in morbid fascination Dialogue: 0,0:00:14.56,0:00:16.12,Default,,0000,0000,0000,,as the deadline approaches Dialogue: 0,0:00:16.12,0:00:20.12,Default,,0000,0000,0000,,wondering whether to\Ncall emergency services; Dialogue: 0,0:00:20.12,0:00:21.99,Default,,0000,0000,0000,,or maybe just settle in, Dialogue: 0,0:00:21.99,0:00:23.70,Default,,0000,0000,0000,,make popcorn,\Nand watch the show. Dialogue: 0,0:00:24.87,0:00:28.75,Default,,0000,0000,0000,,I can't help but keep a wary eye on it. Dialogue: 0,0:00:28.75,0:00:33.97,Default,,0000,0000,0000,,A wary eye that is no longer\Npaying attention to the code at hand. Dialogue: 0,0:00:34.30,0:00:37.14,Default,,0000,0000,0000,,I need all the wary eyes I can get. Dialogue: 0,0:00:37.14,0:00:39.08,Default,,0000,0000,0000,,Without them, forget best practices. Dialogue: 0,0:00:39.77,0:00:43.04,Default,,0000,0000,0000,,I revert to less successful strategies Dialogue: 0,0:00:43.05,0:00:44.49,Default,,0000,0000,0000,,like guessing; Dialogue: 0,0:00:44.70,0:00:47.99,Default,,0000,0000,0000,,and desperately copying code off\Nof Stack Overflow. Dialogue: 0,0:00:51.85,0:00:53.86,Default,,0000,0000,0000,,Sometimes I'm happy. Dialogue: 0,0:00:54.53,0:00:57.30,Default,,0000,0000,0000,,There are moments when\Nthe world melts away. Dialogue: 0,0:00:58.33,0:01:00.83,Default,,0000,0000,0000,,Your sense of self dissipates. Dialogue: 0,0:01:01.76,0:01:05.32,Default,,0000,0000,0000,,You become\Ncompletely absorbed in what you're doing. Dialogue: 0,0:01:06.31,0:01:11.25,Default,,0000,0000,0000,,Time appears to slow down\Nand speed up simultaneously. Dialogue: 0,0:01:12.14,0:01:15.08,Default,,0000,0000,0000,,Being awesome feels effortless. Dialogue: 0,0:01:16.26,0:01:19.47,Default,,0000,0000,0000,,I've taken to coming into\Nthe office early in the morning Dialogue: 0,0:01:19.48,0:01:22.29,Default,,0000,0000,0000,,and committing random acts of refactoring. Dialogue: 0,0:01:22.29,0:01:25.38,Default,,0000,0000,0000,,Some people are calling this\Nguilt-driven development. Dialogue: 0,0:01:27.85,0:01:29.30,Default,,0000,0000,0000,,But really it's not. Dialogue: 0,0:01:29.30,0:01:31.13,Default,,0000,0000,0000,,Refactoring just makes me happy. Dialogue: 0,0:01:31.70,0:01:33.62,Default,,0000,0000,0000,,More refactoring is an optimization. Dialogue: 0,0:01:34.39,0:01:37.73,Default,,0000,0000,0000,,So today I am going to tell you a story. Dialogue: 0,0:01:43.87,0:01:47.98,Default,,0000,0000,0000,,The arrow needs to point the other way\Nbecause this is a refactoring story. Dialogue: 0,0:01:49.86,0:01:52.35,Default,,0000,0000,0000,,Anyway it has a middle... Dialogue: 0,0:01:52.35,0:01:55.68,Default,,0000,0000,0000,,Actually it has a beginning,\Ntwo middles and an end. Dialogue: 0,0:01:55.70,0:01:57.13,Default,,0000,0000,0000,,And a moral. Dialogue: 0,0:01:57.84,0:02:00.71,Default,,0000,0000,0000,,So to be clear, before I get started, Dialogue: 0,0:02:00.73,0:02:02.53,Default,,0000,0000,0000,,when I say refactoring, I mean Dialogue: 0,0:02:02.53,0:02:07.52,Default,,0000,0000,0000,,small careful steps that improve the\Nstructure and the readability of the code Dialogue: 0,0:02:07.52,0:02:09.70,Default,,0000,0000,0000,,without changing its behavior. Dialogue: 0,0:02:10.28,0:02:11.93,Default,,0000,0000,0000,,Tests are implied. Dialogue: 0,0:02:14.15,0:02:15.28,Default,,0000,0000,0000,,So. Dialogue: 0,0:02:16.69,0:02:18.23,Default,,0000,0000,0000,,Once upon a time Dialogue: 0,0:02:18.91,0:02:23.13,Default,,0000,0000,0000,,there was an application that\Nperformed some incredibly dirty hacks Dialogue: 0,0:02:23.13,0:02:26.55,Default,,0000,0000,0000,,in order to deliver data straight\Ninto a number of real-world, Dialogue: 0,0:02:26.56,0:02:29.78,Default,,0000,0000,0000,,old-school, hardcopy publishing systems. Dialogue: 0,0:02:30.56,0:02:34.100,Default,,0000,0000,0000,,I found this particular specimen\Nin the dark recesses of that codebase. Dialogue: 0,0:02:36.46,0:02:39.42,Default,,0000,0000,0000,,It was in a module that\Nwas 300-or-so lines long Dialogue: 0,0:02:39.42,0:02:41.70,Default,,0000,0000,0000,,most of which was in a single method. Dialogue: 0,0:02:45.50,0:02:48.30,Default,,0000,0000,0000,,This module talked to code\Nall over the application. Dialogue: 0,0:02:48.30,0:02:52.47,Default,,0000,0000,0000,,It dealt in temporary files, FTP;\Nit shelled out; Dialogue: 0,0:02:52.47,0:02:55.16,Default,,0000,0000,0000,,used Exif 2 to write\Nmetadata into JPEG files; Dialogue: 0,0:02:55.16,0:02:57.38,Default,,0000,0000,0000,,it handled encoding. Dialogue: 0,0:02:58.16,0:03:00.09,Default,,0000,0000,0000,,It had a comment in it that read: Dialogue: 0,0:03:00.09,0:03:03.47,Default,,0000,0000,0000,,"A kitten dies every time\Nthis code is run." Dialogue: 0,0:03:07.15,0:03:09.46,Default,,0000,0000,0000,,We had it running on a cron job. Dialogue: 0,0:03:15.56,0:03:17.89,Default,,0000,0000,0000,,It had no tests Dialogue: 0,0:03:17.89,0:03:20.17,Default,,0000,0000,0000,,and there was no documentation. Dialogue: 0,0:03:22.09,0:03:24.84,Default,,0000,0000,0000,,This is essentially\Na bucket of business logic. Dialogue: 0,0:03:24.84,0:03:27.13,Default,,0000,0000,0000,,It jumps through hoops\Nin order to name files Dialogue: 0,0:03:27.13,0:03:29.52,Default,,0000,0000,0000,,so that they end up where they need to be. Dialogue: 0,0:03:29.71,0:03:32.05,Default,,0000,0000,0000,,Now there's a comment Dialogue: 0,0:03:32.05,0:03:34.61,Default,,0000,0000,0000,,but it's almost as bad as the code. Dialogue: 0,0:03:35.34,0:03:36.74,Default,,0000,0000,0000,,Also it's wrong. Dialogue: 0,0:03:42.75,0:03:44.100,Default,,0000,0000,0000,,The input to the method is a target, Dialogue: 0,0:03:44.100,0:03:47.61,Default,,0000,0000,0000,,which is the God object\Nin this application. Dialogue: 0,0:03:47.61,0:03:49.51,Default,,0000,0000,0000,,It's an ActiveRecord model. Dialogue: 0,0:03:49.51,0:03:52.10,Default,,0000,0000,0000,,That class is 500 lines long. Dialogue: 0,0:03:53.31,0:03:56.50,Default,,0000,0000,0000,,The big picture here is\Nthat information is being shoved Dialogue: 0,0:03:56.50,0:03:59.19,Default,,0000,0000,0000,,onto a string in order to\Nbuild up the file name. Dialogue: 0,0:03:59.65,0:04:03.82,Default,,0000,0000,0000,,There is a bit of code that's not actually\Nshovelling things onto the string. Dialogue: 0,0:04:04.58,0:04:06.15,Default,,0000,0000,0000,,This draws the eye. Dialogue: 0,0:04:06.15,0:04:09.24,Default,,0000,0000,0000,,It appears to be a chunk of something. Dialogue: 0,0:04:09.68,0:04:12.75,Default,,0000,0000,0000,,And it's probably a good\Ncandidate for extraction. Dialogue: 0,0:04:13.50,0:04:16.61,Default,,0000,0000,0000,,Another striking aspect of the code\Nis that it's littered Dialogue: 0,0:04:16.61,0:04:18.32,Default,,0000,0000,0000,,with a bunch of low-level details. Dialogue: 0,0:04:18.76,0:04:21.48,Default,,0000,0000,0000,,It makes it harder to see what's going on. Dialogue: 0,0:04:21.48,0:04:23.97,Default,,0000,0000,0000,,But amidst all the clutter Dialogue: 0,0:04:23.97,0:04:27.48,Default,,0000,0000,0000,,there does seem to be things... Dialogue: 0,0:04:27.48,0:04:30.86,Default,,0000,0000,0000,,chunks that could probably be named. Dialogue: 0,0:04:30.86,0:04:32.65,Default,,0000,0000,0000,,So what are we looking at? Dialogue: 0,0:04:33.84,0:04:35.96,Default,,0000,0000,0000,,We've got a very large method. Dialogue: 0,0:04:35.96,0:04:39.39,Default,,0000,0000,0000,,It appears to be doing things\Nat 2 different levels of abstraction. Dialogue: 0,0:04:39.39,0:04:42.98,Default,,0000,0000,0000,,And nothing at the lower level\Nof abstraction is being named. Dialogue: 0,0:04:44.08,0:04:46.84,Default,,0000,0000,0000,,These are not\Ncharacteristics of good code. Dialogue: 0,0:04:48.11,0:04:53.63,Default,,0000,0000,0000,,The thing to do with big ugly code\Nis to break it apart into small ugly code. Dialogue: 0,0:04:55.86,0:04:59.51,Default,,0000,0000,0000,,There's a critical difference\Nbetween breaking code down, Dialogue: 0,0:04:59.51,0:05:01.09,Default,,0000,0000,0000,,and breaking code. Dialogue: 0,0:05:02.14,0:05:06.78,Default,,0000,0000,0000,,The first middle of this story\Nis gonna be about adding Dialogue: 0,0:05:06.78,0:05:09.35,Default,,0000,0000,0000,,characterization tests to the method. Dialogue: 0,0:05:09.35,0:05:12.12,Default,,0000,0000,0000,,And then the second middle is\Nthe actual refactoring. Dialogue: 0,0:05:17.81,0:05:20.56,Default,,0000,0000,0000,,Where do you even begin\Ntesting something like this? Dialogue: 0,0:05:22.41,0:05:26.30,Default,,0000,0000,0000,,We don't really know\Nwhat the inputs look like. Dialogue: 0,0:05:27.11,0:05:29.67,Default,,0000,0000,0000,,We certainly don't know\Nwhat the output looks like. Dialogue: 0,0:05:29.94,0:05:31.85,Default,,0000,0000,0000,,We do know that it's in production, Dialogue: 0,0:05:31.85,0:05:33.54,Default,,0000,0000,0000,,and it appears to be working Dialogue: 0,0:05:33.54,0:05:37.04,Default,,0000,0000,0000,,because we haven't had any complaints\Nfrom the customer about it. Dialogue: 0,0:05:39.06,0:05:42.50,Default,,0000,0000,0000,,The easiest way to discover inputs\Nis to just send something— Dialogue: 0,0:05:42.50,0:05:44.43,Default,,0000,0000,0000,,anything really—into the method Dialogue: 0,0:05:44.43,0:05:46.46,Default,,0000,0000,0000,,and then see what comes back out. Dialogue: 0,0:05:47.10,0:05:49.18,Default,,0000,0000,0000,,We need an assertion to work against. Dialogue: 0,0:05:49.18,0:05:51.62,Default,,0000,0000,0000,,And again, it doesn't matter\Nwhat that assertion is. Dialogue: 0,0:05:51.62,0:05:54.08,Default,,0000,0000,0000,,It is going to be wrong. Dialogue: 0,0:05:55.10,0:05:58.55,Default,,0000,0000,0000,,The nice thing about being wrong\Nis it tells you what 'right' looks like. Dialogue: 0,0:05:58.93,0:06:01.16,Default,,0000,0000,0000,,Running this fails, obviously. Dialogue: 0,0:06:01.16,0:06:04.47,Default,,0000,0000,0000,,The error message tells us\Nthat we're missing an input. Dialogue: 0,0:06:05.31,0:06:08.91,Default,,0000,0000,0000,,It also points us to the exact spot\Nin the code where this is happening. Dialogue: 0,0:06:09.71,0:06:13.98,Default,,0000,0000,0000,,What we find on line 6—\Nit comes as no surprise at this point— Dialogue: 0,0:06:13.98,0:06:18.51,Default,,0000,0000,0000,,the message publish_on\Nis being sent to target Dialogue: 0,0:06:18.51,0:06:20.07,Default,,0000,0000,0000,,and it returns a date. Dialogue: 0,0:06:20.89,0:06:22.44,Default,,0000,0000,0000,,Meanwhile back in our tests, Dialogue: 0,0:06:22.44,0:06:24.72,Default,,0000,0000,0000,,we know that the stub represents a target. Dialogue: 0,0:06:25.11,0:06:28.71,Default,,0000,0000,0000,,And we are ready to start\Nfleshing out those inputs. Dialogue: 0,0:06:28.71,0:06:31.54,Default,,0000,0000,0000,,The one we need right now is publish_on, Dialogue: 0,0:06:31.54,0:06:32.91,Default,,0000,0000,0000,,which we know is a date. Dialogue: 0,0:06:33.44,0:06:36.21,Default,,0000,0000,0000,,And the failure tells us\Nwhat our next input is. Dialogue: 0,0:06:37.00,0:06:39.01,Default,,0000,0000,0000,,Digging around in the code reveals Dialogue: 0,0:06:39.01,0:06:42.13,Default,,0000,0000,0000,,that xyz_category_prefix is a string. Dialogue: 0,0:06:42.70,0:06:45.32,Default,,0000,0000,0000,,Next up is kind, which is also a string. Dialogue: 0,0:06:45.75,0:06:48.68,Default,,0000,0000,0000,,personal is a boolean. Dialogue: 0,0:06:48.68,0:06:51.35,Default,,0000,0000,0000,,id is an integer. Dialogue: 0,0:06:51.35,0:06:54.13,Default,,0000,0000,0000,,And title is a string. Dialogue: 0,0:06:54.65,0:06:58.72,Default,,0000,0000,0000,,And this gives us our first real failure. Dialogue: 0,0:06:58.72,0:07:01.27,Default,,0000,0000,0000,,Meaning that we've gotten\Nall the inputs right. Dialogue: 0,0:07:03.08,0:07:04.94,Default,,0000,0000,0000,,These are the inputs. Dialogue: 0,0:07:04.94,0:07:07.12,Default,,0000,0000,0000,,The messages that we need\Nto send to target Dialogue: 0,0:07:07.12,0:07:08.94,Default,,0000,0000,0000,,in order to build up a file name. Dialogue: 0,0:07:09.24,0:07:10.74,Default,,0000,0000,0000,,And with the inputs in place, Dialogue: 0,0:07:10.74,0:07:12.18,Default,,0000,0000,0000,,we're also given the output, Dialogue: 0,0:07:12.18,0:07:13.40,Default,,0000,0000,0000,,which looks like this. Dialogue: 0,0:07:14.74,0:07:18.01,Default,,0000,0000,0000,,And now all that practice\Ncopying-and-pasting from Stack Overflow Dialogue: 0,0:07:18.01,0:07:19.24,Default,,0000,0000,0000,,comes in handy. Dialogue: 0,0:07:19.24,0:07:23.43,Default,,0000,0000,0000,,Copy that string from the failure into\Nthe assertion and the test should pass. Dialogue: 0,0:07:25.80,0:07:27.52,Default,,0000,0000,0000,,It doesn't. Dialogue: 0,0:07:30.49,0:07:32.97,Default,,0000,0000,0000,,The fix for this is to use a regex. Dialogue: 0,0:07:32.97,0:07:35.08,Default,,0000,0000,0000,,This gives us our first passing test. Dialogue: 0,0:07:35.91,0:07:37.77,Default,,0000,0000,0000,,We're not quite done yet. Dialogue: 0,0:07:38.61,0:07:42.43,Default,,0000,0000,0000,,There are a bunch of low-level details\Nthat aren't being exercised. Dialogue: 0,0:07:42.34,0:07:44.75,Default,,0000,0000,0000,,And there are alternate paths\Nthrough the method. Dialogue: 0,0:07:45.01,0:07:48.17,Default,,0000,0000,0000,,We need to improve the inputs\Nfor these 3 lines of code Dialogue: 0,0:07:48.17,0:07:52.14,Default,,0000,0000,0000,,and add test cases for the lines\Nthat have conditionals in them. Dialogue: 0,0:07:54.51,0:07:57.67,Default,,0000,0000,0000,,At every step, failing tests tell us\Nhow to tweak our assertions. Dialogue: 0,0:07:57.67,0:08:00.59,Default,,0000,0000,0000,,These are trivial to fix; boring to watch. Dialogue: 0,0:08:00.59,0:08:02.58,Default,,0000,0000,0000,,So I'll show you some highlights. Dialogue: 0,0:08:03.42,0:08:06.14,Default,,0000,0000,0000,,publish_on gets zero-padded, Dialogue: 0,0:08:06.14,0:08:08.56,Default,,0000,0000,0000,,and pi doesn't actually\Nget affected by this Dialogue: 0,0:08:08.56,0:08:09.92,Default,,0000,0000,0000,,so we'll fall back on e. Dialogue: 0,0:08:11.00,0:08:13.40,Default,,0000,0000,0000,,kind gsubs out underscores. Dialogue: 0,0:08:13.40,0:08:15.98,Default,,0000,0000,0000,,We need an underscore\Nso we can see it being removed. Dialogue: 0,0:08:16.56,0:08:19.88,Default,,0000,0000,0000,,title appears to strip out everything. Dialogue: 0,0:08:19.88,0:08:22.76,Default,,0000,0000,0000,,And the existing input\Ndoesn't have very much cruft in it. Dialogue: 0,0:08:22.76,0:08:25.25,Default,,0000,0000,0000,,So we need some numbers\Nand some funky characters Dialogue: 0,0:08:25.25,0:08:27.78,Default,,0000,0000,0000,,and a couple of upper-case letters. Dialogue: 0,0:08:31.55,0:08:34.01,Default,,0000,0000,0000,,There's something fishy about that regex. Dialogue: 0,0:08:40.76,0:08:42.30,Default,,0000,0000,0000,,What's with the square brackets? Dialogue: 0,0:08:44.09,0:08:46.08,Default,,0000,0000,0000,,I'm too lazy to reason about this Dialogue: 0,0:08:46.08,0:08:47.63,Default,,0000,0000,0000,,so I'm adding a test case, Dialogue: 0,0:08:47.63,0:08:49.69,Default,,0000,0000,0000,,overriding the stub's input for title, Dialogue: 0,0:08:49.69,0:08:51.30,Default,,0000,0000,0000,,giving it some square brackets. Dialogue: 0,0:08:51.30,0:08:53.68,Default,,0000,0000,0000,,And that proves that\Nbrackets get left in place. Dialogue: 0,0:08:54.42,0:08:56.59,Default,,0000,0000,0000,,This is probably not\Nthe intended behavior. Dialogue: 0,0:08:57.68,0:09:00.26,Default,,0000,0000,0000,,This test now serves as documentation Dialogue: 0,0:09:00.26,0:09:02.44,Default,,0000,0000,0000,,until we can clarify this\Nwith the customer. Dialogue: 0,0:09:03.54,0:09:05.97,Default,,0000,0000,0000,,The first conditional deals in\Npersonalization Dialogue: 0,0:09:05.97,0:09:07.80,Default,,0000,0000,0000,,and our stub doesn't personalize. Dialogue: 0,0:09:07.80,0:09:11.72,Default,,0000,0000,0000,,So we need a test for the case\Nthat actually does. Dialogue: 0,0:09:13.97,0:09:17.06,Default,,0000,0000,0000,,We're informed about yet another input\Nthat's missing. Dialogue: 0,0:09:17.06,0:09:18.57,Default,,0000,0000,0000,,It's trivial to supply. Dialogue: 0,0:09:18.57,0:09:23.35,Default,,0000,0000,0000,,The other conditional on that line of code\Nprovides a fallback in case age is nil. Dialogue: 0,0:09:23.35,0:09:26.59,Default,,0000,0000,0000,,And the test for this stubs out\Nthe same inputs as the previous one. Dialogue: 0,0:09:27.57,0:09:30.63,Default,,0000,0000,0000,,The final conditional is\Na ternary statement Dialogue: 0,0:09:30.63,0:09:34.19,Default,,0000,0000,0000,,that is trying to determine\Nwhere to truncate the title. Dialogue: 0,0:09:36.06,0:09:38.94,Default,,0000,0000,0000,,Our default input for the title is\Nneither long nor short. Dialogue: 0,0:09:38.94,0:09:42.05,Default,,0000,0000,0000,,So by making it longer\Nwe can make sure that it gets truncated. Dialogue: 0,0:09:42.05,0:09:46.97,Default,,0000,0000,0000,,And then the only case left to test for\Nis a title that is too short Dialogue: 0,0:09:46.97,0:09:48.12,Default,,0000,0000,0000,,to get truncated. Dialogue: 0,0:09:50.20,0:09:54.01,Default,,0000,0000,0000,,At this point we have\Nprotection against regressions. Dialogue: 0,0:09:57.85,0:09:59.87,Default,,0000,0000,0000,,What have we actually accomplished so far? Dialogue: 0,0:10:01.71,0:10:05.65,Default,,0000,0000,0000,,We took a piece of\Nundocumented, untested code. Dialogue: 0,0:10:05.65,0:10:07.34,Default,,0000,0000,0000,,And with a bit of hand-waving, Dialogue: 0,0:10:07.34,0:10:10.66,Default,,0000,0000,0000,,we got fake assertions\Nto give us the inputs. Dialogue: 0,0:10:10.66,0:10:13.26,Default,,0000,0000,0000,,The inputs gave us the outputs. Dialogue: 0,0:10:13.26,0:10:16.86,Default,,0000,0000,0000,,And the outputs\Ngave us the real assertions. Dialogue: 0,0:10:17.35,0:10:19.23,Default,,0000,0000,0000,,It's almost karmic. Dialogue: 0,0:10:20.06,0:10:21.86,Default,,0000,0000,0000,,Then we had to reason about the code. Dialogue: 0,0:10:21.86,0:10:23.32,Default,,0000,0000,0000,,We inspected every line. Dialogue: 0,0:10:23.32,0:10:28.87,Default,,0000,0000,0000,,Made sure that we had inputs\Nthat would actually exercise those lines Dialogue: 0,0:10:28.87,0:10:31.68,Default,,0000,0000,0000,,and then we made sure that\Nevery branch of every conditional Dialogue: 0,0:10:31.68,0:10:33.10,Default,,0000,0000,0000,,was called from a test. Dialogue: 0,0:10:37.62,0:10:40.90,Default,,0000,0000,0000,,There's no specification here. Dialogue: 0,0:10:40.90,0:10:42.47,Default,,0000,0000,0000,,There's no design being done. Dialogue: 0,0:10:43.22,0:10:46.38,Default,,0000,0000,0000,,We're getting a regression test suite. Dialogue: 0,0:10:47.20,0:10:50.67,Default,,0000,0000,0000,,We are also getting documentation\Nup to and including the fact Dialogue: 0,0:10:50.67,0:10:52.54,Default,,0000,0000,0000,,that we probably have a bug. Dialogue: 0,0:10:53.38,0:10:56.100,Default,,0000,0000,0000,,The biggest win at this point\Nis that we can start changing things Dialogue: 0,0:10:56.100,0:10:58.85,Default,,0000,0000,0000,,without breaking into a cold sweat. Dialogue: 0,0:11:00.38,0:11:01.91,Default,,0000,0000,0000,,So here's what we're gonna do. Dialogue: 0,0:11:01.91,0:11:03.56,Default,,0000,0000,0000,,We're gonna isolate the method. Dialogue: 0,0:11:03.56,0:11:08.49,Default,,0000,0000,0000,,And then we're going to\Nextract a bunch of smaller methods. Dialogue: 0,0:11:08.49,0:11:12.24,Default,,0000,0000,0000,,I'm gonna borrow a detailed prescription\Nfrom Martin Fowler's book Refactoring, Dialogue: 0,0:11:12.24,0:11:15.14,Default,,0000,0000,0000,,called Replace Method with Method Object. Dialogue: 0,0:11:15.60,0:11:18.86,Default,,0000,0000,0000,,Traditionally you do this refactoring\Nwhen you have big computation Dialogue: 0,0:11:18.86,0:11:20.48,Default,,0000,0000,0000,,and a bunch of temporary variables Dialogue: 0,0:11:20.48,0:11:23.54,Default,,0000,0000,0000,,and you don't want to be passing\Nthose temporary variables around Dialogue: 0,0:11:23.54,0:11:25.52,Default,,0000,0000,0000,,as you extract methods. Dialogue: 0,0:11:25.52,0:11:29.49,Default,,0000,0000,0000,,Here, we pretty much only have\Nthis one target to worry about. Dialogue: 0,0:11:30.41,0:11:33.73,Default,,0000,0000,0000,,So first of all,\Nwe need to make a home for this code. Dialogue: 0,0:11:33.73,0:11:36.61,Default,,0000,0000,0000,,Add an initializer that takes the target. Dialogue: 0,0:11:36.61,0:11:37.87,Default,,0000,0000,0000,,Add an attribute for it. Dialogue: 0,0:11:37.87,0:11:40.06,Default,,0000,0000,0000,,And just copy-paste\Nthe whole thing in there. Dialogue: 0,0:11:41.97,0:11:44.03,Default,,0000,0000,0000,,The method shouldn't be called\Non the class. Dialogue: 0,0:11:44.03,0:11:45.67,Default,,0000,0000,0000,,It needs a better name. Dialogue: 0,0:11:45.67,0:11:47.84,Default,,0000,0000,0000,,And it no longer takes any arguments. Dialogue: 0,0:11:47.84,0:11:49.72,Default,,0000,0000,0000,,Back in the old module, Dialogue: 0,0:11:49.72,0:11:52.21,Default,,0000,0000,0000,,we need to reference the new method\Nfrom the old one, Dialogue: 0,0:11:52.21,0:11:54.30,Default,,0000,0000,0000,,so just delete the whole body\Nof the method, Dialogue: 0,0:11:54.30,0:11:55.62,Default,,0000,0000,0000,,reference the new file, Dialogue: 0,0:11:55.62,0:11:56.80,Default,,0000,0000,0000,,instantiate the class, Dialogue: 0,0:11:56.80,0:11:58.46,Default,,0000,0000,0000,,pass in the target,\Ncall name on it, Dialogue: 0,0:11:58.46,0:11:59.50,Default,,0000,0000,0000,,and we're green. Dialogue: 0,0:11:59.50,0:12:02.49,Default,,0000,0000,0000,,Which means that we have\Na license to go to town on this code. Dialogue: 0,0:12:04.68,0:12:05.82,Default,,0000,0000,0000,,Where to begin? Dialogue: 0,0:12:06.98,0:12:08.70,Default,,0000,0000,0000,,You could start anywhere. Dialogue: 0,0:12:08.70,0:12:11.07,Default,,0000,0000,0000,,I always like to delete something. Dialogue: 0,0:12:11.07,0:12:13.80,Default,,0000,0000,0000,,Let's go ahead and\Nget rid of that comment. Dialogue: 0,0:12:14.90,0:12:16.55,Default,,0000,0000,0000,,And now somewhat arbitrarily, Dialogue: 0,0:12:16.55,0:12:18.64,Default,,0000,0000,0000,,I've chosen to go\Nfrom biggest to smallest. Dialogue: 0,0:12:18.64,0:12:20.88,Default,,0000,0000,0000,,The biggest chunk\Nthat we've seen for extraction Dialogue: 0,0:12:20.88,0:12:22.18,Default,,0000,0000,0000,,is the truncated title bit. Dialogue: 0,0:12:22.18,0:12:26.94,Default,,0000,0000,0000,,The actual mechanics of\Na method extraction is as follows: Dialogue: 0,0:12:27.72,0:12:31.61,Default,,0000,0000,0000,,Create an empty method\Nand name it by what it does Dialogue: 0,0:12:31.61,0:12:34.31,Default,,0000,0000,0000,,or what it is, Dialogue: 0,0:12:34.31,0:12:35.94,Default,,0000,0000,0000,,not by how it does it. Dialogue: 0,0:12:36.63,0:12:39.10,Default,,0000,0000,0000,,Coming up with a good name\Nis often the hardest thing Dialogue: 0,0:12:39.10,0:12:40.72,Default,,0000,0000,0000,,you'll ever do in a refactoring. Dialogue: 0,0:12:41.100,0:12:46.04,Default,,0000,0000,0000,,The next step is to copy the lines of code\Nfrom the source method into the new one. Dialogue: 0,0:12:46.04,0:12:48.88,Default,,0000,0000,0000,,Scan the new method for local variables. Dialogue: 0,0:12:48.88,0:12:52.25,Default,,0000,0000,0000,,filename here is declared\Nin the source method, Dialogue: 0,0:12:52.25,0:12:54.11,Default,,0000,0000,0000,,so we have a choice to make. Dialogue: 0,0:12:54.11,0:12:55.78,Default,,0000,0000,0000,,We can either do the mutation here, Dialogue: 0,0:12:55.78,0:12:57.50,Default,,0000,0000,0000,,which means passing the filename in, Dialogue: 0,0:12:57.50,0:12:59.58,Default,,0000,0000,0000,,or making it an instance variable. Dialogue: 0,0:12:59.58,0:13:02.15,Default,,0000,0000,0000,,Or we could make this a query method. Dialogue: 0,0:13:02.15,0:13:06.16,Default,,0000,0000,0000,,Now the whole point of the refactoring is\Nto separate the 2 levels of abstraction— Dialogue: 0,0:13:06.16,0:13:07.92,Default,,0000,0000,0000,,building up the filename in one place Dialogue: 0,0:13:07.92,0:13:10.46,Default,,0000,0000,0000,,and putting together all the little pieces\Nin another. Dialogue: 0,0:13:10.46,0:13:12.88,Default,,0000,0000,0000,,So we're gonna just return\Nthe value that we need. Dialogue: 0,0:13:13.54,0:13:16.64,Default,,0000,0000,0000,,The other temporary variables here\Nare all local to this method. Dialogue: 0,0:13:18.05,0:13:20.54,Default,,0000,0000,0000,,We need to assign the result\Nof our new query method Dialogue: 0,0:13:20.54,0:13:23.26,Default,,0000,0000,0000,,and delete the temporary variables\Nthat are no longer used Dialogue: 0,0:13:23.26,0:13:24.61,Default,,0000,0000,0000,,in the source method. Dialogue: 0,0:13:24.61,0:13:26.28,Default,,0000,0000,0000,,And then we're green again. Dialogue: 0,0:13:27.30,0:13:28.15,Default,,0000,0000,0000,,Before we move on Dialogue: 0,0:13:28.15,0:13:29.98,Default,,0000,0000,0000,,I'd like to tidy this up a bit. Dialogue: 0,0:13:30.21,0:13:33.50,Default,,0000,0000,0000,,There's some unnecessary work\Ngoing on in the regex. Dialogue: 0,0:13:33.50,0:13:36.12,Default,,0000,0000,0000,,We're doing a case-insensitive match, Dialogue: 0,0:13:36.12,0:13:38.32,Default,,0000,0000,0000,,and then we're downcasing afterwards. Dialogue: 0,0:13:40.62,0:13:42.47,Default,,0000,0000,0000,,That's kinda backwards. Dialogue: 0,0:13:42.80,0:13:46.00,Default,,0000,0000,0000,,There's also something in the\Nmatch-if brackets that drives me nuts. Dialogue: 0,0:13:46.87,0:13:49.76,Default,,0000,0000,0000,,The spurious parentheses have got to go. Dialogue: 0,0:13:50.10,0:13:53.44,Default,,0000,0000,0000,,Another thing that bugs me is\Nthe fact that we have a ternary statement Dialogue: 0,0:13:53.44,0:13:55.54,Default,,0000,0000,0000,,to decide the range for the match-if. Dialogue: 0,0:13:56.18,0:13:58.97,Default,,0000,0000,0000,,A match-if is not going\Nto raise an exception. Dialogue: 0,0:13:58.97,0:14:01.86,Default,,0000,0000,0000,,If you try to truncate a 4-character\Nstring to 9 characters, Dialogue: 0,0:14:01.86,0:14:03.79,Default,,0000,0000,0000,,it'll just return 4 characters. Dialogue: 0,0:14:04.61,0:14:06.28,Default,,0000,0000,0000,,The ternary statement can go. Dialogue: 0,0:14:06.87,0:14:08.76,Default,,0000,0000,0000,,Since we no longer need truncate_to, Dialogue: 0,0:14:08.76,0:14:11.23,Default,,0000,0000,0000,,we don't need to worry\Nabout the length of the title. Dialogue: 0,0:14:11.23,0:14:12.16,Default,,0000,0000,0000,,So that can go too. Dialogue: 0,0:14:12.76,0:14:15.10,Default,,0000,0000,0000,,And with those 2 lines gone, Dialogue: 0,0:14:15.10,0:14:19.10,Default,,0000,0000,0000,,there seems very little point\Nin having a temporary variable, Dialogue: 0,0:14:19.10,0:14:20.64,Default,,0000,0000,0000,,so we can ditch that as well Dialogue: 0,0:14:20.64,0:14:24.12,Default,,0000,0000,0000,,effectively leaving us with\Na single line of code in truncated_title. Dialogue: 0,0:14:25.77,0:14:29.01,Default,,0000,0000,0000,,The longest line of code\Nis now the hexdigest stuff. Dialogue: 0,0:14:29.01,0:14:32.64,Default,,0000,0000,0000,,Now, hexdigest is a terrible name\Nin this context. Dialogue: 0,0:14:37.80,0:14:39.03,Default,,0000,0000,0000,,Copy stuff in. Dialogue: 0,0:14:39.03,0:14:40.39,Default,,0000,0000,0000,,Assign the result. Dialogue: 0,0:14:40.39,0:14:41.72,Default,,0000,0000,0000,,And we're green again. Dialogue: 0,0:14:41.72,0:14:43.92,Default,,0000,0000,0000,,The personalization line\Nis now the longest. Dialogue: 0,0:14:45.16,0:14:46.60,Default,,0000,0000,0000,,Perform a quick extraction. Dialogue: 0,0:14:47.64,0:14:49.23,Default,,0000,0000,0000,,publication_day Dialogue: 0,0:14:51.54,0:14:54.24,Default,,0000,0000,0000,,and xyz_category_prefix. Dialogue: 0,0:14:54.24,0:14:56.74,Default,,0000,0000,0000,,Inside this class, xyz is redundant. Dialogue: 0,0:14:56.74,0:14:59.56,Default,,0000,0000,0000,,The fact that it's a prefix is irrelevant. Dialogue: 0,0:14:59.56,0:15:02.10,Default,,0000,0000,0000,,So we can drop the xyz prefix Dialogue: 0,0:15:02.10,0:15:04.30,Default,,0000,0000,0000,,as well as the prefix suffix Dialogue: 0,0:15:04.30,0:15:06.57,Default,,0000,0000,0000,,and just call the new method category. Dialogue: 0,0:15:08.65,0:15:10.12,Default,,0000,0000,0000,,And then we've got kind. Dialogue: 0,0:15:10.12,0:15:12.56,Default,,0000,0000,0000,,This leaves us with\Na fairly readable method. Dialogue: 0,0:15:12.56,0:15:14.86,Default,,0000,0000,0000,,We could totally leave it at this Dialogue: 0,0:15:14.86,0:15:17.06,Default,,0000,0000,0000,,but there's still\Nsome spurious stuff in here. Dialogue: 0,0:15:17.06,0:15:19.58,Default,,0000,0000,0000,,publication_day for instance. Dialogue: 0,0:15:21.25,0:15:23.03,Default,,0000,0000,0000,,publication_day returns a string. Dialogue: 0,0:15:23.80,0:15:26.06,Default,,0000,0000,0000,,So, why are we interpolating it? Dialogue: 0,0:15:27.92,0:15:29.46,Default,,0000,0000,0000,,Same goes for category Dialogue: 0,0:15:29.46,0:15:30.82,Default,,0000,0000,0000,,and kind. Dialogue: 0,0:15:32.16,0:15:33.58,Default,,0000,0000,0000,,target.id is an integer Dialogue: 0,0:15:33.58,0:15:36.26,Default,,0000,0000,0000,,but string interpolation\Nimplicitly calls to_s on it. Dialogue: 0,0:15:38.34,0:15:41.09,Default,,0000,0000,0000,,This next move might seem\Na little bit subtle Dialogue: 0,0:15:41.09,0:15:43.62,Default,,0000,0000,0000,,until you recognize that kids' game\NFive Differences. Dialogue: 0,0:15:43.62,0:15:47.83,Default,,0000,0000,0000,,Which line of code here is different\Nfrom all of the other pieces? Dialogue: 0,0:15:48.96,0:15:54.25,Default,,0000,0000,0000,,The first line was the only one that's\Nnot being shovelled onto the string, Dialogue: 0,0:15:54.25,0:15:57.79,Default,,0000,0000,0000,,so we can start off with an empty string Dialogue: 0,0:15:57.79,0:16:00.40,Default,,0000,0000,0000,,and then make the first piece\Njust like all the others. Dialogue: 0,0:16:00.90,0:16:02.17,Default,,0000,0000,0000,,Up to a point. Dialogue: 0,0:16:02.17,0:16:04.48,Default,,0000,0000,0000,,The extension is also different. Dialogue: 0,0:16:04.48,0:16:07.66,Default,,0000,0000,0000,,If you conceptually separate\Nthis into 2 jobs— Dialogue: 0,0:16:07.66,0:16:09.06,Default,,0000,0000,0000,,building up the filename, Dialogue: 0,0:16:09.06,0:16:10.83,Default,,0000,0000,0000,,and then slapping the extension on it Dialogue: 0,0:16:10.83,0:16:12.64,Default,,0000,0000,0000,,—we're left with 2 distinct sections: Dialogue: 0,0:16:12.64,0:16:15.01,Default,,0000,0000,0000,,one where everything is smooshed together, Dialogue: 0,0:16:15.01,0:16:18.83,Default,,0000,0000,0000,,and another where the pieces\Nare separated by underscores. Dialogue: 0,0:16:19.33,0:16:22.04,Default,,0000,0000,0000,,If we extract\Nthe smooshed together pieces, Dialogue: 0,0:16:22.04,0:16:26.74,Default,,0000,0000,0000,,then all the remaining pieces\Nare separated by an underscore. Dialogue: 0,0:16:27.66,0:16:30.48,Default,,0000,0000,0000,,We can now shovel them into an array\Nrather than a string. Dialogue: 0,0:16:32.06,0:16:35.10,Default,,0000,0000,0000,,This gets rid of a bunch more\Nof the interpolation syntax, Dialogue: 0,0:16:35.10,0:16:37.25,Default,,0000,0000,0000,,joining them with an underscore. Dialogue: 0,0:16:40.76,0:16:41.71,Default,,0000,0000,0000,,Done. Dialogue: 0,0:16:43.28,0:16:44.60,Default,,0000,0000,0000,,Is it perfect? Dialogue: 0,0:16:44.60,0:16:45.71,Default,,0000,0000,0000,,Of course not. Dialogue: 0,0:16:46.06,0:16:47.32,Default,,0000,0000,0000,,Is it better? Dialogue: 0,0:16:47.32,0:16:48.45,Default,,0000,0000,0000,,Hell yeah! Dialogue: 0,0:16:49.48,0:16:52.86,Default,,0000,0000,0000,,We went from this to this\Nin less than 30 steps. Dialogue: 0,0:16:54.10,0:16:55.66,Default,,0000,0000,0000,,Let me just show you that again. Dialogue: 0,0:16:56.37,0:16:57.46,Default,,0000,0000,0000,,Before. Dialogue: 0,0:16:58.31,0:16:59.53,Default,,0000,0000,0000,,After. Dialogue: 0,0:17:01.30,0:17:02.45,Default,,0000,0000,0000,,Before. Dialogue: 0,0:17:02.45,0:17:03.76,Default,,0000,0000,0000,,After. Dialogue: 0,0:17:06.61,0:17:08.35,Default,,0000,0000,0000,,So first we quarantined the method. Dialogue: 0,0:17:08.35,0:17:10.26,Default,,0000,0000,0000,,Then we extracted stuff. Dialogue: 0,0:17:11.04,0:17:13.70,Default,,0000,0000,0000,,Extracting stuff basically boils down to Dialogue: 0,0:17:13.70,0:17:16.82,Default,,0000,0000,0000,,identifying a piece of code\Nthat performs a subtask Dialogue: 0,0:17:16.82,0:17:18.52,Default,,0000,0000,0000,,and then giving that code a name. Dialogue: 0,0:17:19.78,0:17:21.38,Default,,0000,0000,0000,,Back when we started out, Dialogue: 0,0:17:21.38,0:17:23.03,Default,,0000,0000,0000,,we identified 3 code smells: Dialogue: 0,0:17:23.03,0:17:24.26,Default,,0000,0000,0000,,a large method, Dialogue: 0,0:17:24.26,0:17:25.92,Default,,0000,0000,0000,,2 different levels of abstraction, Dialogue: 0,0:17:25.92,0:17:27.78,Default,,0000,0000,0000,,unnamed abstractions. Dialogue: 0,0:17:27.78,0:17:31.02,Default,,0000,0000,0000,,Abstracting methods addressed\Nall 3 of those issues. Dialogue: 0,0:17:32.89,0:17:35.57,Default,,0000,0000,0000,,At that point we still had\Nsome ragged edges though. Dialogue: 0,0:17:35.57,0:17:36.95,Default,,0000,0000,0000,,So we kinda picked through it Dialogue: 0,0:17:36.95,0:17:38.83,Default,,0000,0000,0000,,and removed pointless cruft. Dialogue: 0,0:17:42.07,0:17:44.74,Default,,0000,0000,0000,,This concludes the second middle\Nof the refactoring story Dialogue: 0,0:17:44.74,0:17:47.80,Default,,0000,0000,0000,,and I'm gonna end by taking a closer look\Nat pointless cruft. Dialogue: 0,0:17:51.01,0:17:54.02,Default,,0000,0000,0000,,In the field of information design, Dialogue: 0,0:17:54.02,0:17:57.34,Default,,0000,0000,0000,,chartjunk refers to visual elements\Nin charts and graphs Dialogue: 0,0:17:57.34,0:17:59.48,Default,,0000,0000,0000,,that add noise. Dialogue: 0,0:17:59.63,0:18:01.87,Default,,0000,0000,0000,,They don't help you understand the data. Dialogue: 0,0:18:01.87,0:18:04.88,Default,,0000,0000,0000,,They often get in the way of\Ncomprehension. Dialogue: 0,0:18:04.88,0:18:07.18,Default,,0000,0000,0000,,To give you an idea of\Nwhat we're talking about Dialogue: 0,0:18:07.18,0:18:09.43,Default,,0000,0000,0000,,this graph gets just about\Neverything wrong. Dialogue: 0,0:18:12.49,0:18:15.46,Default,,0000,0000,0000,,This is the exact same data\Npresented without chartjunk. Dialogue: 0,0:18:15.46,0:18:18.31,Default,,0000,0000,0000,,Codejunk is the Ruby equivalent\Nof chartjunk. Dialogue: 0,0:18:18.31,0:18:20.61,Default,,0000,0000,0000,,This is not about coding practices. Dialogue: 0,0:18:20.61,0:18:24.68,Default,,0000,0000,0000,,It's not about naming and SRP\Nand small methods and DRY. Dialogue: 0,0:18:24.68,0:18:26.12,Default,,0000,0000,0000,,It's about noise. Dialogue: 0,0:18:26.89,0:18:30.12,Default,,0000,0000,0000,,I've tried to classify codejunk\Nand I came up with this list. Dialogue: 0,0:18:31.14,0:18:32.22,Default,,0000,0000,0000,,#10 Dialogue: 0,0:18:35.49,0:18:37.88,Default,,0000,0000,0000,,Does a bear shit in the woods? Dialogue: 0,0:18:40.07,0:18:42.86,Default,,0000,0000,0000,,Comments shouldn't echo\Nthe implementation. Dialogue: 0,0:18:43.52,0:18:44.91,Default,,0000,0000,0000,,They shouldn't be wrong. Dialogue: 0,0:18:48.91,0:18:50.54,Default,,0000,0000,0000,,They shouldn't be imprecise. Dialogue: 0,0:18:51.47,0:18:53.16,Default,,0000,0000,0000,,And they shouldn't be misspelled. Dialogue: 0,0:18:55.87,0:18:56.86,Default,,0000,0000,0000,,#9 Dialogue: 0,0:18:56.86,0:18:58.04,Default,,0000,0000,0000,,It is my conviction Dialogue: 0,0:18:58.04,0:19:01.70,Default,,0000,0000,0000,,that everyone should make their editor\Nshow them trailing whitespace. Dialogue: 0,0:19:06.62,0:19:08.86,Default,,0000,0000,0000,,If you leave it in,\Nyou have noise in your code. Dialogue: 0,0:19:08.86,0:19:11.40,Default,,0000,0000,0000,,If you then take it out,\Nyou have noise in your diffs, Dialogue: 0,0:19:11.40,0:19:13.44,Default,,0000,0000,0000,,which is just wrong on so many levels. Dialogue: 0,0:19:14.37,0:19:17.68,Default,,0000,0000,0000,,#8 If it's dead, let it rest in peace. Dialogue: 0,0:19:20.69,0:19:22.74,Default,,0000,0000,0000,,What were you saving it for? Dialogue: 0,0:19:25.08,0:19:26.80,Default,,0000,0000,0000,,You need to learn to let go. Dialogue: 0,0:19:34.17,0:19:36.90,Default,,0000,0000,0000,,What is this doing in source control? Dialogue: 0,0:19:38.54,0:19:39.47,Default,,0000,0000,0000,,#7 Dialogue: 0,0:19:50.49,0:19:52.12,Default,,0000,0000,0000,,More parentheses. Dialogue: 0,0:19:52.12,0:19:53.33,Default,,0000,0000,0000,,This is vile. Dialogue: 0,0:19:55.70,0:19:57.63,Default,,0000,0000,0000,,When I see this,\NI secretly wonder if you Dialogue: 0,0:19:57.63,0:20:00.26,Default,,0000,0000,0000,,wash your hands after you\Ngo to the bathroom. Dialogue: 0,0:20:04.01,0:20:06.69,Default,,0000,0000,0000,,#6 Intelligent defaults. Dialogue: 0,0:20:07.79,0:20:14.29,Default,,0000,0000,0000,,Yes. 4 characters saved are 4 characters\Nthat you can spend another day. Dialogue: 0,0:20:15.19,0:20:16.83,Default,,0000,0000,0000,,Or something. Dialogue: 0,0:20:17.45,0:20:19.12,Default,,0000,0000,0000,,Let's talk about dependencies. Dialogue: 0,0:20:19.12,0:20:23.17,Default,,0000,0000,0000,,In particular, dependencies that\Nyou're not actually depending on. Dialogue: 0,0:20:24.38,0:20:26.46,Default,,0000,0000,0000,,This may or may not impact performance. Dialogue: 0,0:20:26.46,0:20:29.34,Default,,0000,0000,0000,,It probably will impact the performance\Nof your tests. Dialogue: 0,0:20:29.34,0:20:30.84,Default,,0000,0000,0000,,A whole different story. Dialogue: 0,0:20:30.84,0:20:33.78,Default,,0000,0000,0000,,Mostly you just added noise to the code. Dialogue: 0,0:20:34.65,0:20:36.76,Default,,0000,0000,0000,,#4 This is familiar territory. Dialogue: 0,0:20:38.04,0:20:39.46,Default,,0000,0000,0000,,Recognize this? Dialogue: 0,0:20:39.46,0:20:41.16,Default,,0000,0000,0000,,Not to beat a dead horse, Dialogue: 0,0:20:41.16,0:20:43.57,Default,,0000,0000,0000,,but ew. Dialogue: 0,0:20:44.74,0:20:48.66,Default,,0000,0000,0000,,#3 Don't do work that the computer\Nis already doing for you. Dialogue: 0,0:20:51.25,0:20:52.51,Default,,0000,0000,0000,,More string interpolation. Dialogue: 0,0:20:52.51,0:20:55.18,Default,,0000,0000,0000,,I could've technicallly folded this into\Nthe previous one Dialogue: 0,0:20:55.18,0:20:56.66,Default,,0000,0000,0000,,but I'm trying to get to 10. Dialogue: 0,0:20:59.09,0:21:00.22,Default,,0000,0000,0000,,This is the same thing. Dialogue: 0,0:21:00.20,0:21:02.38,Default,,0000,0000,0000,,The call to map is superfluous here. Dialogue: 0,0:21:02.75,0:21:04.91,Default,,0000,0000,0000,,The match-if brackets\Ndon't need your help. Dialogue: 0,0:21:04.91,0:21:05.96,Default,,0000,0000,0000,,We've seen that one. Dialogue: 0,0:21:06.42,0:21:10.14,Default,,0000,0000,0000,,In this example the computer isn't\Ndoing the work for you but should be. Dialogue: 0,0:21:10.95,0:21:13.23,Default,,0000,0000,0000,,#2 Test suites. Dialogue: 0,0:21:13.23,0:21:20.71,Default,,0000,0000,0000,,They should be curated, maintained, fed,\Nwatered, coddled and minimized. Dialogue: 0,0:21:22.26,0:21:26.46,Default,,0000,0000,0000,,The only exception I can think of is if\Ndocumenting behavior outweighs the cost. Dialogue: 0,0:21:26.46,0:21:28.29,Default,,0000,0000,0000,,Choose wisely. Dialogue: 0,0:21:29.33,0:21:31.83,Default,,0000,0000,0000,,And finally, the compounding sin. Dialogue: 0,0:21:31.83,0:21:36.01,Default,,0000,0000,0000,,You know the old saying,\N"1 + 1 = 3 for very large values of 1"? Dialogue: 0,0:21:39.90,0:21:41.14,Default,,0000,0000,0000,,This is revolting. Dialogue: 0,0:21:41.68,0:21:44.62,Default,,0000,0000,0000,,In fact, it bears a horrifying resemblance\Nto the code that Dialogue: 0,0:21:44.62,0:21:45.87,Default,,0000,0000,0000,,we started out with today. Dialogue: 0,0:21:46.40,0:21:49.06,Default,,0000,0000,0000,,When people say that\Nsoftware is grown, not built, Dialogue: 0,0:21:49.06,0:21:51.68,Default,,0000,0000,0000,,I'm pretty sure that this\Nis what they're talking about. Dialogue: 0,0:21:52.02,0:21:53.19,Default,,0000,0000,0000,,It's kinda like fungus. Dialogue: 0,0:21:56.15,0:21:59.36,Default,,0000,0000,0000,,Earlier I said about the refactoring\Nthat after we extracted methods Dialogue: 0,0:21:59.36,0:22:02.17,Default,,0000,0000,0000,,we kinda polished up the code a little. Dialogue: 0,0:22:02.17,0:22:05.38,Default,,0000,0000,0000,,I'm gonna restate that\Nin light of the previous section. Dialogue: 0,0:22:05.38,0:22:07.62,Default,,0000,0000,0000,,First, we extracted methods. Dialogue: 0,0:22:07.62,0:22:09.42,Default,,0000,0000,0000,,Then we eliminated codejunk. Dialogue: 0,0:22:11.15,0:22:13.45,Default,,0000,0000,0000,,That was the ending of\Nthe refactoring story. Dialogue: 0,0:22:13.68,0:22:15.82,Default,,0000,0000,0000,,Before I get to the moral,\NI'd like to mention Dialogue: 0,0:22:15.82,0:22:17.65,Default,,0000,0000,0000,,the whole thing lives on Github. Dialogue: 0,0:22:18.25,0:22:19.69,Default,,0000,0000,0000,,It was committed step-by-step, Dialogue: 0,0:22:19.69,0:22:21.74,Default,,0000,0000,0000,,so if you wanna look\Nat any of the mechanics Dialogue: 0,0:22:21.74,0:22:23.13,Default,,0000,0000,0000,,or run the tests or anything, Dialogue: 0,0:22:23.13,0:22:25.63,Default,,0000,0000,0000,,just dig through the commit history.\NIt's all there. Dialogue: 0,0:22:29.88,0:22:36.99,Default,,0000,0000,0000,,I have a vague recollection of the night\Nwhen that code was written. Dialogue: 0,0:22:38.37,0:22:39.72,Default,,0000,0000,0000,,Let me rephrase that: Dialogue: 0,0:22:40.55,0:22:42.52,Default,,0000,0000,0000,,I vaguely recall writing it. Dialogue: 0,0:22:44.21,0:22:45.02,Default,,0000,0000,0000,,Yeah. Dialogue: 0,0:22:47.45,0:22:49.96,Default,,0000,0000,0000,,When I panic, I write godawful code. Dialogue: 0,0:22:50.64,0:22:55.16,Default,,0000,0000,0000,,Other people do yoga, or meditate,\Nor go white water rafting. Dialogue: 0,0:22:55.81,0:22:57.22,Default,,0000,0000,0000,,I refactor. Dialogue: 0,0:22:57.22,0:22:59.50,Default,,0000,0000,0000,,It soothes me. Dialogue: 0,0:23:00.31,0:23:03.98,Default,,0000,0000,0000,,Science—if you believe that sorta thing— Dialogue: 0,0:23:03.98,0:23:06.38,Default,,0000,0000,0000,,actually explains why. Dialogue: 0,0:23:06.38,0:23:08.63,Default,,0000,0000,0000,,The key player in the game\Nis working memory. Dialogue: 0,0:23:08.63,0:23:11.91,Default,,0000,0000,0000,,Working memory is the thing\Nthat allows you to do mental arithmetic. Dialogue: 0,0:23:11.91,0:23:16.20,Default,,0000,0000,0000,,You store temporary results off in memory\Nas you work through Dialogue: 0,0:23:16.20,0:23:17.51,Default,,0000,0000,0000,,other parts of the problem. Dialogue: 0,0:23:18.48,0:23:23.74,Default,,0000,0000,0000,,The main differentiator in performance\Nof tasks that rely on working memory, Dialogue: 0,0:23:23.74,0:23:27.88,Default,,0000,0000,0000,,is the type of strategy\Nyou're able to apply to a problem. Dialogue: 0,0:23:27.88,0:23:29.69,Default,,0000,0000,0000,,If you have better working memory Dialogue: 0,0:23:29.69,0:23:33.83,Default,,0000,0000,0000,,you can apply more complex,\Nmore successful strategies. Dialogue: 0,0:23:34.06,0:23:35.44,Default,,0000,0000,0000,,Here's the deal: Dialogue: 0,0:23:36.66,0:23:39.57,Default,,0000,0000,0000,,when you worry in ways\Nthat involve mental chatter, Dialogue: 0,0:23:39.57,0:23:43.20,Default,,0000,0000,0000,,you use up available slots\Nin your working memory. Dialogue: 0,0:23:43.20,0:23:48.60,Default,,0000,0000,0000,,You no longer have the swap space\Nnecessary to use complex strategies Dialogue: 0,0:23:48.60,0:23:52.97,Default,,0000,0000,0000,,and you revert to less successful ones\Nlike copying stuff off of Stack Overflow. Dialogue: 0,0:23:53.64,0:23:55.77,Default,,0000,0000,0000,,This is where refactoring comes in. Dialogue: 0,0:23:55.93,0:23:57.52,Default,,0000,0000,0000,,Refactoring makes you smarter. Dialogue: 0,0:23:58.52,0:24:01.80,Default,,0000,0000,0000,,Refactoring basically gives you\Nan exobrain. Dialogue: 0,0:24:01.80,0:24:05.72,Default,,0000,0000,0000,,You offload a bunch of those\Nlittle details—that Dialogue: 0,0:24:05.72,0:24:08.01,Default,,0000,0000,0000,,under normal circumstances\Ngo into working memory Dialogue: 0,0:24:08.01,0:24:09.81,Default,,0000,0000,0000,,—into your tests. Dialogue: 0,0:24:10.26,0:24:13.39,Default,,0000,0000,0000,,Once you start refactoring,\Nyou start reclaiming your brain. Dialogue: 0,0:24:13.100,0:24:16.21,Default,,0000,0000,0000,,It actively counteracts panic. Dialogue: 0,0:24:17.32,0:24:21.32,Default,,0000,0000,0000,,One of the really unexpected things\Nthat happened when I started refactoring Dialogue: 0,0:24:21.32,0:24:23.78,Default,,0000,0000,0000,,simply for the act\Nof refactoring itself was Dialogue: 0,0:24:23.78,0:24:26.86,Default,,0000,0000,0000,,that I started optimizing\Nfor happiness. Dialogue: 0,0:24:28.46,0:24:30.99,Default,,0000,0000,0000,,I would specifically put something\Ninto its own class Dialogue: 0,0:24:30.99,0:24:33.75,Default,,0000,0000,0000,,just so that I could load\Njust that class and nothing else. Dialogue: 0,0:24:34.28,0:24:37.72,Default,,0000,0000,0000,,The feedback loop you get\Nwhen you have subsecond test suites Dialogue: 0,0:24:37.72,0:24:40.76,Default,,0000,0000,0000,,for the thing that you're working on\Nis unbelievable. Dialogue: 0,0:24:41.70,0:24:44.05,Default,,0000,0000,0000,,It's a huge enabler for flow. Dialogue: 0,0:24:45.68,0:24:46.88,Default,,0000,0000,0000,,Flow is nice. Dialogue: 0,0:24:47.77,0:24:49.20,Default,,0000,0000,0000,,Flow is more than nice. Dialogue: 0,0:24:49.20,0:24:51.08,Default,,0000,0000,0000,,It's like a bliss cocktail. Dialogue: 0,0:24:52.61,0:24:56.72,Default,,0000,0000,0000,,Selfishly isolating code\Nto improve my own happiness Dialogue: 0,0:24:56.72,0:24:59.40,Default,,0000,0000,0000,,turned out to be a pretty good deal\Nfor the code as well. Dialogue: 0,0:24:59.87,0:25:01.69,Default,,0000,0000,0000,,Suddenly I was avoiding dependencies. Dialogue: 0,0:25:01.69,0:25:04.81,Default,,0000,0000,0000,,I was constantly asking myself Dialogue: 0,0:25:04.81,0:25:06.88,Default,,0000,0000,0000,,"Can this be a separate class?" Dialogue: 0,0:25:06.88,0:25:08.21,Default,,0000,0000,0000,,"How about a gem?" Dialogue: 0,0:25:08.21,0:25:12.15,Default,,0000,0000,0000,,"What is the unrelated subproblem here?" Dialogue: 0,0:25:12.15,0:25:14.73,Default,,0000,0000,0000,,It made a dramatic difference. Dialogue: 0,0:25:16.27,0:25:19.94,Default,,0000,0000,0000,,In summary, refactoring makes you smarter\Nby giving you an exobrain. Dialogue: 0,0:25:19.94,0:25:23.38,Default,,0000,0000,0000,,It is preventative and curative\Nwith respect to panic. Dialogue: 0,0:25:23.38,0:25:28.07,Default,,0000,0000,0000,,If you optimize for developer happiness\Nby making your tests really fast, Dialogue: 0,0:25:28.07,0:25:32.41,Default,,0000,0000,0000,,you get loosely coupled code that adheres\Nto the Single Responsibility Principle. Dialogue: 0,0:25:33.15,0:25:34.33,Default,,0000,0000,0000,,Thank you.