0:00:17.800,0:00:21.970 JOEL TURNBULL: Thanks for coming. 0:00:21.970,0:00:23.730 My name is Joel Turnbull. 0:00:23.730,0:00:26.399 I'm a developer for Gaslight in Cincinnatti,[br]Ohio. 0:00:26.399,0:00:30.449 I also head up and coordinate a blog over[br]there, 0:00:30.449,0:00:33.410 in case anybody ever wants to talk about that. 0:00:33.410,0:00:36.769 But today, I'm here to talk about debugger[br]driven 0:00:36.769,0:00:43.769 development with Pry. Most Rubyists I know[br]don't use 0:00:44.320,0:00:51.280 debuggers. Rubyists I know, when faced with[br]a problem, 0:00:51.280,0:00:56.550 would prefer to ponder code than pop open[br]a 0:00:56.550,0:00:59.440 debugger and poke around. 0:00:59.440,0:01:02.510 This is crazy to me. I've always thought it 0:01:02.510,0:01:05.880 was, because to me, trying to solve a problem 0:01:05.880,0:01:09.670 by pondering code is like trying to find your 0:01:09.670,0:01:13.920 keys in the dark, when you're holding a flashlight, 0:01:13.920,0:01:19.770 but you're consciously deciding not to use[br]it. 0:01:19.770,0:01:22.190 So why is this? I, I used to think 0:01:22.190,0:01:24.560 it might be about egos or culture or something 0:01:24.560,0:01:28.130 like that, but really it's pretty simple.[br]I think 0:01:28.130,0:01:30.420 we've had a lack of really good tools up 0:01:30.420,0:01:36.690 to this point. But ultimately, my talk isn't[br]about 0:01:36.690,0:01:40.739 using debuggers in a traditional sense to[br]fix software, 0:01:40.739,0:01:44.250 but using debuggers as a tool in your workflow 0:01:44.250,0:01:47.090 to build software. 0:01:47.090,0:01:51.000 And, so why do I think we can do 0:01:51.000,0:01:55.440 this right now? I feel like we finally have 0:01:55.440,0:01:59.929 a tool that we can use to explore this 0:01:59.929,0:02:06.489 debugger driven, debugger driven workflow.[br]And that tool is 0:02:06.489,0:02:06.860 Pry. 0:02:06.860,0:02:09.190 Can I get a show of hands of who 0:02:09.190,0:02:16.190 uses Pry? Awesome. Like, everybody. All right.[br]Cool. So 0:02:16.970,0:02:21.489 I'm talking about debugger driven development[br]with Pry. Conrad 0:02:21.489,0:02:23.920 Erwin gave a talk not even like six months 0:02:23.920,0:02:26.880 ago called REPL Driven Development with Pry.[br]I swear 0:02:26.880,0:02:28.850 to god I had no idea. 0:02:28.850,0:02:35.850 But, and both are accurate, I think. You know, 0:02:36.840,0:02:39.560 but I think both terms kind of undersell what 0:02:39.560,0:02:42.140 the power of Pry is. So here's my favorite 0:02:42.140,0:02:47.100 definition. Pry is an IRB alternative and[br]runtime developer 0:02:47.100,0:02:49.660 console. So if we take the first part of 0:02:49.660,0:02:53.610 that and we think about Pry as an IRB 0:02:53.610,0:02:57.990 alternative, you know, anything that you can[br]do with, 0:02:57.990,0:03:02.930 with, both, both are REPLs, right. And, and[br]a 0:03:02.930,0:03:05.460 debugger is a REPL, too. Anything you can[br]do 0:03:05.460,0:03:08.350 in Ruby, you can do in IRB. Anything you 0:03:08.350,0:03:11.900 can do in IRB, you can do in Pry. 0:03:11.900,0:03:15.290 What makes both of them powerful, is they[br]both 0:03:15.290,0:03:20.620 leverage this idea of runtime. And, to me,[br]runtime 0:03:20.620,0:03:24.440 is all about immersion. It's about being immersed[br]in 0:03:24.440,0:03:28.590 a live system, where you can play with code 0:03:28.590,0:03:30.580 and you can look at your objects and, and 0:03:30.580,0:03:33.920 all that kind of thing. You can validate your 0:03:33.920,0:03:40.920 implementations. Everything you need to do.[br]And it's like, 0:03:42.290,0:03:45.020 looking for your keys with a flashlight. 0:03:45.020,0:03:49.140 So, given that Pry and IRB are both REPLs 0:03:49.140,0:03:51.099 and they both have this idea of runtime, why 0:03:51.099,0:03:56.520 should you use Pry instead of IRB? It's got 0:03:56.520,0:03:59.280 a couple vital workflow features right out[br]of the 0:03:59.280,0:04:03.750 box. Syntax highlighting and tab completion.[br]Both super handy. 0:04:03.750,0:04:06.620 But, what I want to talk about today is 0:04:06.620,0:04:11.489 some of the bigger, game-changing features[br]of Pry. The 0:04:11.489,0:04:18.488 first one is enhanced introspection. Here's[br]our friend again. 0:04:19.220,0:04:21.849 Introspection is the ability to, of, of a[br]language, 0:04:21.849,0:04:25.210 where you can ask a language questions about[br]itself. 0:04:25.210,0:04:29.250 And it's built into Ruby, and that's awesome. 0:04:29.250,0:04:31.970 If you've ever asked a class what method you 0:04:31.970,0:04:34.680 can call on it, or you've asked an instance 0:04:34.680,0:04:41.449 what class it is, you're doing introspection. 0:04:41.449,0:04:42.939 What if you want to go deeper? Like, what 0:04:42.939,0:04:44.860 if you want to know what the class methods 0:04:44.860,0:04:47.379 are versus the instance methods? You know,[br]what if 0:04:47.379,0:04:50.860 you want to know what methods are inherited,[br]and 0:04:50.860,0:04:52.610 from where? What if you want to know what 0:04:52.610,0:04:58.099 state an instance holds onto during its life[br]cycle? 0:04:58.099,0:05:00.849 You can answer all these questions with plain[br]Ruby 0:05:00.849,0:05:05.289 and IRB. But the problem is, is that, it's, 0:05:05.289,0:05:09.059 the, the amount of effort involved is non-trivial.[br]I 0:05:09.059,0:05:14.499 would classify it as daunting. 0:05:14.499,0:05:21.499 So. Given that. You know. I would, I would 0:05:29.050,0:05:35.400 classify this as DRTFM. This is what I, this 0:05:35.400,0:05:40.710 is what I point to. I mean, this is 0:05:40.710,0:05:44.289 the workflow that I like. 0:05:44.289,0:05:46.939 I like to take the things out of the 0:05:46.939,0:05:48.539 box. I like to get a feel for what 0:05:48.539,0:05:51.819 the pieces are. I like to play around with 0:05:51.819,0:05:54.300 them. I like to try to put it together 0:05:54.300,0:05:56.889 without reading the manual, and if I get stuck, 0:05:56.889,0:06:01.089 then I read the manual, right. 0:06:01.089,0:06:06.229 The second really game-changing feature of[br]Pry, to me, 0:06:06.229,0:06:10.439 is extendability through plugins. And the[br]best way that 0:06:10.439,0:06:13.509 I can show this is to just demo some 0:06:13.509,0:06:18.139 of my favorites for you. 0:06:18.139,0:06:24.080 So, I'm gonna show you a Rails app. Instead 0:06:24.080,0:06:27.699 of calling it in a normal way, like rails 0:06:27.699,0:06:31.740 s, I'm gonna call it like this. Under the 0:06:31.740,0:06:34.550 umbrella of Pry rescue. And I'll show you[br]why 0:06:34.550,0:06:40.330 in a minute. 0:06:40.330,0:06:43.449 But here we are. This is an app I've 0:06:43.449,0:06:46.300 been working on late, late nights, you know.[br]Please 0:06:46.300,0:06:50.400 don't steal this. This is a bowling score[br]count, 0:06:50.400,0:06:53.409 tracker, right. You can push any number after[br]you 0:06:53.409,0:06:56.289 bowl and it will record what you, what, how 0:06:56.289,0:06:59.029 many pins you knocked down, right. 0:06:59.029,0:07:01.430 So, the first thing I'm gonna show you about 0:07:01.430,0:07:08.430 Pry, for those who aren't necessarily familiar,[br]is how 0:07:09.969,0:07:15.319 you invoke a runtime at any point in your 0:07:15.319,0:07:18.520 application, where you're running Ruby, right. 0:07:18.520,0:07:22.050 Here, I've inserted a couple binding dot prys.[br]One 0:07:22.050,0:07:24.999 into my controller action and one into my[br]template. 0:07:24.999,0:07:28.029 On the lower left we have our model. OK, 0:07:28.029,0:07:32.069 so let's rerun it with that in mind. 0:07:32.069,0:07:34.360 Let's go back to our running server, and we'll 0:07:34.360,0:07:38.180 see that we've halted our execution here,[br]and we've 0:07:38.180,0:07:40.520 been dropped into a run time. And we can 0:07:40.520,0:07:45.710 do things in here like look around. We can 0:07:45.710,0:07:48.259 play lines of code. Let's play the line that 0:07:48.259,0:07:52.219 sets the bowling game. And then we can look 0:07:52.219,0:07:54.819 again. 0:07:54.819,0:07:57.139 When we exit from this, we've returned from[br]our 0:07:57.139,0:08:00.149 controller. We're starting to render our template,[br]and we've 0:08:00.149,0:08:02.490 hit our next binding dot pry. You can put 0:08:02.490,0:08:07.149 binding dot prys inside your erb tags, right. 0:08:07.149,0:08:10.110 Same drill. We can look at bowling games.[br]We 0:08:10.110,0:08:17.110 can, we can step into our next, our, our, 0:08:18.360,0:08:21.020 our implementations of our methods. Here we've[br]stepped into 0:08:21.020,0:08:24.860 the frames method of our bowling game model. 0:08:24.860,0:08:29.499 Same drill. We can look around here. We can 0:08:29.499,0:08:33.979 look at ourself. We can go to the next, 0:08:33.979,0:08:38.690 or we can continue. 0:08:38.690,0:08:43.779 So, you can see how handy that would be 0:08:43.779,0:08:48.649 if things aren't necessarily blowing up, but,[br]you know, 0:08:48.649,0:08:55.649 something's not quite right, either. So what[br]if things 0:08:56.940,0:09:00.709 do blow up, though? Right. 0:09:00.709,0:09:04.540 So, here I am. I'm gonna, I'm gonna spark 0:09:04.540,0:09:07.940 an exception here by bullet, trying to bowl[br]the 0:09:07.940,0:09:11.269 next ball of my next frame. I'm gonna bowl 0:09:11.269,0:09:14.910 a big nine. I'm gonna come back here and 0:09:14.910,0:09:18.750 we've been dropped into a runtime, because[br]an exception 0:09:18.750,0:09:22.240 was thrown. That's what being under the watchful[br]eye 0:09:22.240,0:09:25.120 of Pry rescue is gonna do for us within 0:09:25.120,0:09:27.730 this context here. 0:09:27.730,0:09:33.230 So, some interesting, interesting things we[br]can do here. 0:09:33.230,0:09:36.089 We can call the show-stack command of the[br]Pry 0:09:36.089,0:09:40.540 stack explorer plugin. And we're seeing the[br]whole stack 0:09:40.540,0:09:44.880 here. this is like caller, but it's alive,[br]right. 0:09:44.880,0:09:49.259 We can move up the stack. We can move 0:09:49.259,0:09:52.130 up the stack nine frames. We can move down 0:09:52.130,0:09:54.380 the stack. We can take a look at the 0:09:54.380,0:09:58.540 state of any object here at any level of 0:09:58.540,0:10:00.470 our stack trace. 0:10:00.470,0:10:02.060 We can look at our stack again just to 0:10:02.060,0:10:05.360 see where we're at. We're on frame ten. But 0:10:05.360,0:10:07.610 this is a big hairy kind of Rails stack 0:10:07.610,0:10:09.019 trace, and we're not getting a whole lot of 0:10:09.019,0:10:11.310 value out of that right now. 0:10:11.310,0:10:15.440 So let's call the cd-cause command of Pry[br]rescue. 0:10:15.440,0:10:18.769 And see if it can track down what caused 0:10:18.769,0:10:23.269 this problem in the first place. 0:10:23.269,0:10:25.399 There we go. This looks more familiar, right.[br]Here 0:10:25.399,0:10:28.990 we are in our template. And I will guess 0:10:28.990,0:10:32.040 that on line thirteen we have a problem with 0:10:32.040,0:10:35.449 frame one. And that's true. So we just need 0:10:35.449,0:10:36.709 to add a little bit of a guard in 0:10:36.709,0:10:40.399 here, and say, you know, if we have pins 0:10:40.399,0:10:44.050 on frame one, let's render that. Otherwise[br]let's just 0:10:44.050,0:10:46.259 render a dash. 0:10:46.259,0:10:48.959 And we get feedback that that's going, that's[br]what's 0:10:48.959,0:10:52.019 gonna happen, right. We know that this is[br]a 0:10:52.019,0:10:54.199 working implementation. 0:10:54.199,0:10:57.379 So let's copy our history. This is another[br]plugin 0:10:57.379,0:11:01.720 called Pry clipboard. That's gonna copy that[br]implementation into 0:11:01.720,0:11:06.470 my clipboard. I'm gonna edit a file where[br]the 0:11:06.470,0:11:10.529 last exception was raised. It drops me right[br]where 0:11:10.529,0:11:13.220 I need to be. I'm gonna paste in that 0:11:13.220,0:11:20.220 implementation, drop back in, and I'm gonna[br]ask Pry 0:11:23.180,0:11:24.569 rescue to try it again. 0:11:24.569,0:11:31.569 And we're back. And we've got our dash. So, 0:11:31.620,0:11:35.899 and we can continue to bowl, right. That's[br]legit, 0:11:35.899,0:11:42.899 right. A five and a six. OK, cool. 0:11:44.670,0:11:51.480 So, what do we do here? We used binding 0:11:51.480,0:11:54.480 dot pry to invoke a runtime anywhere in our 0:11:54.480,0:11:58.290 app where we're doing Ruby code. We used the 0:11:58.290,0:12:02.810 pry-debugger gem to give us our step, next,[br]and 0:12:02.810,0:12:05.699 continue functionality that we expect out[br]of our debugging 0:12:05.699,0:12:09.379 tools. We used pry-rescue and ran our Rails[br]app 0:12:09.379,0:12:11.879 under the umbrella of pry-rescue to drop us[br]into 0:12:11.879,0:12:13.920 a runtime when things go wrong, so that we 0:12:13.920,0:12:17.750 can poke around. We used the pry-stack_explorer[br]gem to 0:12:17.750,0:12:22.170 navigate the stack and explore state at any[br]level. 0:12:22.170,0:12:27.110 A few commands we saw were cd-cause in pry-rescue 0:12:27.110,0:12:30.269 that took us to the, the root of our 0:12:30.269,0:12:36.870 problem. We used play and we used copy-history[br]to 0:12:36.870,0:12:40.680 not mess around with, you know, copying things[br]with 0:12:40.680,0:12:44.029 our mouse and pasting them into our REPL,[br]which 0:12:44.029,0:12:47.060 can be a pain. We used the edit command 0:12:47.060,0:12:49.149 with the e flag to take us to the 0:12:49.149,0:12:51.379 file where the exception occurred so that[br]we could 0:12:51.379,0:12:56.930 fix it. And then we used pry-rescue, try-again,[br]which 0:12:56.930,0:13:01.850 under this, under the context of Rails, just[br]replayed 0:13:01.850,0:13:04.600 our request. We didn't have to reload our,[br]our 0:13:04.600,0:13:08.370 page, or do any of that nonsense. Reload the 0:13:08.370,0:13:11.540 whole environment or anything like that, right.[br]So it 0:13:11.540,0:13:13.279 was fast. 0:13:13.279,0:13:18.560 So, the, that's, that's great, and having[br]demoed Pry 0:13:18.560,0:13:20.740 in a debugger context, you know, I can show 0:13:20.740,0:13:24.069 some of those things. But, really, what I[br]find 0:13:24.069,0:13:27.160 interesting is this idea of Pry as a runtime 0:13:27.160,0:13:30.839 developer console, right. 0:13:30.839,0:13:34.589 So there's some really awspect- really awesome[br]aspects of 0:13:34.589,0:13:37.019 Ruby, right. It's introspective, which we've[br]talked about a 0:13:37.019,0:13:39.040 little bit and we'll talk about more. And[br]it's 0:13:39.040,0:13:41.629 a dynamic and it's reflective, which means,[br]you know, 0:13:41.629,0:13:43.000 we don't have to compile it and we can 0:13:43.000,0:13:46.970 change things on the fly in its runtime. 0:13:46.970,0:13:49.019 And I think we, we take advantage of these 0:13:49.019,0:13:51.720 things, you know, a lot in the code that 0:13:51.720,0:13:55.939 we write, whether we're doing metaprogramming[br]or monkeypatching or, 0:13:55.939,0:13:58.980 or anything like that. But we, we haven't[br]really 0:13:58.980,0:14:01.839 taken advantage of, of these things in the[br]tools 0:14:01.839,0:14:04.879 and in our workflow yet. 0:14:04.879,0:14:08.899 So, when I talk about workflow and our problems 0:14:08.899,0:14:12.029 with our workflow, I see big problems with[br]the 0:14:12.029,0:14:16.439 traditional workflow in, in Ruby development[br]that I, that 0:14:16.439,0:14:18.610 I see. Right, I mean. By that I mean 0:14:18.610,0:14:21.180 we write some code in an editor. We save 0:14:21.180,0:14:24.060 it. We hop over to a terminal or we 0:14:24.060,0:14:26.389 pop over to a webpage and reload it and 0:14:26.389,0:14:28.600 run it to see if it worked and, if 0:14:28.600,0:14:31.079 it worked, we go back and continue on. If 0:14:31.079,0:14:33.310 it didn't, we fix it, we save. We go 0:14:33.310,0:14:38.860 back. We reload it, rerun it. Rinse, repeat,[br]right? 0:14:38.860,0:14:42.980 What, what are, what problems do I see with 0:14:42.980,0:14:46.939 this? First of all, it's disruptive and it's[br]distracting 0:14:46.939,0:14:49.629 to keep switching back and forth, right. Some[br]amount 0:14:49.629,0:14:53.810 of context-switching is always gonna be imminent,[br]right. But 0:14:53.810,0:14:56.410 any effort you can make to reduce that is 0:14:56.410,0:14:58.949 just gonna be a huge win for your flow, 0:14:58.949,0:15:02.300 you know, and your focus. 0:15:02.300,0:15:03.910 The second problem I see with that is it's 0:15:03.910,0:15:06.060 just guess work. We just write some code.[br]Oh, 0:15:06.060,0:15:08.430 yeah, I think it's gonna work. We save it. 0:15:08.430,0:15:10.519 We go over. We run it to see if 0:15:10.519,0:15:13.009 it works. We're just taking shots in the dark, 0:15:13.009,0:15:16.050 you know. You can ask this guy. 0:15:16.050,0:15:19.910 Taking shots with a flashlight is much more[br]accurate. 0:15:19.910,0:15:23.339 And recommended, apparently. So do that. 0:15:23.339,0:15:26.569 And, to me, it just seems backwards, right.[br]We, 0:15:26.569,0:15:31.300 we're like solidifying and codifying our code[br]into our 0:15:31.300,0:15:33.939 code base just in an attempt to see if 0:15:33.939,0:15:37.579 it works. It should be the opposite. Our code 0:15:37.579,0:15:42.459 base, it should be the, the record of code 0:15:42.459,0:15:46.559 that we've, we've already validated, right.[br]And I, I 0:15:46.559,0:15:49.939 mean these things are just kind of things[br]that 0:15:49.939,0:15:52.970 we accept and, and we, we take for granted, 0:15:52.970,0:15:53.410 right. 0:15:53.410,0:15:57.040 But I mean, I think other languages have,[br]have 0:15:57.040,0:16:01.410 been more effective and intentional about[br]integrating this idea 0:16:01.410,0:16:06.050 of a runtime into the, their workflow, you[br]know. 0:16:06.050,0:16:09.689 And blurring this line between static and[br]running code. 0:16:09.689,0:16:11.949 Clojure comes to mind, right. 0:16:11.949,0:16:14.759 But, we've talked about the awesome aspects[br]of Ruby, 0:16:14.759,0:16:17.809 and there's really nothing that restricts[br]or limits us 0:16:17.809,0:16:19.689 from doing the same, right. I mean, I think 0:16:19.689,0:16:23.519 the Ruby language is, the Ruby language enables[br]it, 0:16:23.519,0:16:26.249 you know. It's just that up to this point, 0:16:26.249,0:16:29.680 we really haven't had the tools to do so. 0:16:29.680,0:16:33.939 So, we talked about these workflow problems.[br]How does 0:16:33.939,0:16:38.759 Pry solve these workflow problems, right?[br]I see that, 0:16:38.759,0:16:41.730 you know, the introspection and the documentation[br]and the 0:16:41.730,0:16:46.199 source code browsing, which we'll see in a[br]minute, 0:16:46.199,0:16:50.860 that's, that's baked into Pry, gives us ninety[br]percent 0:16:50.860,0:16:53.610 of the information that we need to write code 0:16:53.610,0:16:57.529 right now, you know, in most cases. 0:16:57.529,0:16:59.079 It has a runtime that you can throw your 0:16:59.079,0:17:01.569 code against and validate it and get feedback[br]on 0:17:01.569,0:17:05.089 whether it, whether it works or not, immediately.[br]And 0:17:05.089,0:17:07.280 it's smart about editing. You don't have to[br]think 0:17:07.280,0:17:10.770 about what file you need to open. Pry usually 0:17:10.770,0:17:13.449 knows what file you want to edit and usually 0:17:13.449,0:17:15.800 knows exactly where you want to edit it. Which 0:17:15.800,0:17:18.300 is really nice. 0:17:18.300,0:17:25.300 So, when I talk about this idea of runtime 0:17:27.300,0:17:32.050 development, I'm really talking about being[br]immersed in this, 0:17:32.050,0:17:36.510 in this environment that, you know, loves[br]us and 0:17:36.510,0:17:40.580 can give us feedback, and, and is alive, right. 0:17:40.580,0:17:42.220 So we want to spend the majority of our 0:17:42.220,0:17:45.560 development time there, and we want our editor[br]to 0:17:45.560,0:17:47.270 just be an after thought. And that's just[br]a 0:17:47.270,0:17:49.710 place where we just push working code when[br]it's 0:17:49.710,0:17:51.190 done, right. 0:17:51.190,0:17:54.620 So, let me demo to you a little bit 0:17:54.620,0:18:01.620 about how I see that working, right. 0:18:02.580,0:18:08.040 So. Our mission is to write an empty class 0:18:08.040,0:18:11.200 definition, OK. This is just a script. No[br]Rails 0:18:11.200,0:18:15.160 involved here or anything. But given a class[br]like 0:18:15.160,0:18:18.400 name like BowlingGame, we want to create a[br]file, 0:18:18.400,0:18:22.190 bowling_game dot rb, and write a class definition[br]to 0:18:22.190,0:18:26.590 it, like class BowlingGame empty space end.[br]Right, and 0:18:26.590,0:18:30.060 I've created a little skeleton here of, of[br]how 0:18:30.060,0:18:31.870 I think that might work, right. 0:18:31.870,0:18:33.930 We're gonna, we're gonna read in a string[br]from 0:18:33.930,0:18:36.680 the command line, we're gonna pass that string[br]into 0:18:36.680,0:18:39.640 a method called file_name_for_class and get[br]a file name. 0:18:39.640,0:18:42.200 We're gonna pass that string into a method[br]called 0:18:42.200,0:18:45.800 class_definition for class and get a class[br]definition, and 0:18:45.800,0:18:48.070 then we're gonna create that class by writing[br]that 0:18:48.070,0:18:52.740 class definition to that file. Right. 0:18:52.740,0:18:54.800 So let's step out here and let's just run 0:18:54.800,0:18:58.320 that. So, we get an expected error, right.[br]We 0:18:58.320,0:19:02.570 haven't implemented anything called file_name_for_class,[br]yet. So we could 0:19:02.570,0:19:04.880 jump into our editor and start coding and[br]all 0:19:04.880,0:19:10.220 that, but why don't we see what this is 0:19:10.220,0:19:13.130 like. 0:19:13.130,0:19:16.770 Why don't we use Pry rescue and leverage that 0:19:16.770,0:19:19.610 exception to drop us into a runtime and start 0:19:19.610,0:19:25.570 this runtime development process. So we do[br]that. We 0:19:25.570,0:19:28.030 get the same error, but the difference is,[br]we're 0:19:28.030,0:19:32.920 inside of a runtime now, OK. So, the first 0:19:32.920,0:19:35.200 problem is pretty easy. We know that we need 0:19:35.200,0:19:41.380 to define file_name_for_class. And we do so,[br]right. 0:19:41.380,0:19:44.370 The difference is in here, I'm gonna raise,[br]in 0:19:44.370,0:19:47.760 the implementation of this class, and drop[br]back out. 0:19:47.760,0:19:50.240 And I'll show you why. When we ask Pry 0:19:50.240,0:19:54.800 to try again, we get in here. We're right 0:19:54.800,0:19:58.030 where we need to be to define the implementa- 0:19:58.030,0:20:01.790 working implementation of this class. Although,[br]I already know 0:20:01.790,0:20:06.090 that I have forgotten to pass in the BowlingGame 0:20:06.090,0:20:07.760 string, like I always do. 0:20:07.760,0:20:12.340 OK. Now we have everything we need. So we 0:20:12.340,0:20:15.130 have something like BowlingGame, right, and[br]we're looking for 0:20:15.130,0:20:20.770 something like bowling_game dot rb, OK. So[br]I'm just 0:20:20.770,0:20:24.970 gonna preview my favorite Pry command of all[br]time 0:20:24.970,0:20:28.080 here. ls. 0:20:28.080,0:20:31.320 When I call ls, and give it the class 0:20:31.320,0:20:34.520 or the object I'm working with, I immediately[br]know 0:20:34.520,0:20:37.400 I'm working with a string and I'm seeing all 0:20:37.400,0:20:39.890 of the methods that are available to me on 0:20:39.890,0:20:42.300 that string. And when I say all of the 0:20:42.300,0:20:45.240 methods, I don't mean all of them. Notice[br]that 0:20:45.240,0:20:50.040 the object methods are not in here. And, you 0:20:50.040,0:20:53.680 know that if you've ever used IRB to get 0:20:53.680,0:20:56.680 the method, you always do, thing dot method[br]minus 0:20:56.680,0:20:59.660 object dot methods blah, blah, blah. 0:20:59.660,0:21:02.440 The, that's just noise, right, in most cases.[br]So 0:21:02.440,0:21:06.530 the default is just to leave that out. The 0:21:06.530,0:21:10.170 developers of Pry have thought of that, right.[br]So 0:21:10.170,0:21:15.570 we can try to class downcase, which gets us 0:21:15.570,0:21:18.250 so close, but yet so far away. We don't 0:21:18.250,0:21:20.820 really know where to put that underscore. 0:21:20.820,0:21:26.360 But, as Ruby devs, Rails devs, we know we 0:21:26.360,0:21:29.250 have things like ActiveSupport that can help[br]us out 0:21:29.250,0:21:34.570 with that. 0:21:34.570,0:21:37.360 So we include that, and now when we ls 0:21:37.360,0:21:39.980 our class, we've got some extra stuff in here, 0:21:39.980,0:21:43.650 right. Demodulalize, deconstantize, right.[br]That kind of stuff. And 0:21:43.650,0:21:46.390 if it, that's hard to see, we can just 0:21:46.390,0:21:51.400 ls ActiveSupport::Inflector itself and see[br]what's available to us 0:21:51.400,0:21:53.070 there, right. 0:21:53.070,0:21:55.530 So we need an und, we needed an underscore. 0:21:55.530,0:21:59.570 I see a method called underscore there. Tab[br]completion 0:21:59.570,0:22:02.450 is nice. All right. So now we're getting a 0:22:02.450,0:22:05.930 lot closer. All we need to do is stick 0:22:05.930,0:22:10.870 on our file exception, and I think we're done, 0:22:10.870,0:22:11.780 right. 0:22:11.780,0:22:16.350 So that, there's our filename. So let's copy[br]that. 0:22:16.350,0:22:22.750 Let's drop back into our file. Right here,[br]exactly 0:22:22.750,0:22:26.320 where we need to put the implementation, let's[br]put 0:22:26.320,0:22:30.100 it in there. And let's save it and continue 0:22:30.100,0:22:32.810 on. OK, I know, I'm not gonna continue through 0:22:32.810,0:22:37.140 this whole thing, in the interest of time,[br]but 0:22:37.140,0:22:42.150 I do want to, to implement this last method 0:22:42.150,0:22:44.070 inside of the create_class, so I can talk[br]a 0:22:44.070,0:22:47.280 little bit more about what I love about introspection, 0:22:47.280,0:22:48.750 right. 0:22:48.750,0:22:50.800 Let's just reflect on what we did there, though, 0:22:50.800,0:22:54.070 with the workflow, OK. So we used, the, we 0:22:54.070,0:22:56.930 used pry-rescue to leverage the power, you[br]know, to 0:22:56.930,0:23:00.050 leverage that exception, to pop us into a[br]runtime, 0:23:00.050,0:23:03.300 and we used the runtime of the debugger not 0:23:03.300,0:23:09.620 to fix code, but to drive our development[br]process, 0:23:09.620,0:23:12.020 right. 0:23:12.020,0:23:17.030 So. We're in here. We've raised inside of[br]our 0:23:17.030,0:23:20.850 create_class method. We try again. We've got[br]our file 0:23:20.850,0:23:27.850 name, and we've got our class definition.[br]And we 0:23:28.860,0:23:32.380 have this file class, right. And, and I know 0:23:32.380,0:23:34.450 about this file class, and I know this is 0:23:34.450,0:23:36.990 exactly what I need to get the job done. 0:23:36.990,0:23:39.090 But, I mean, this is exactly what I, what 0:23:39.090,0:23:42.250 happened to me. I don't really remember exactly[br]what 0:23:42.250,0:23:44.370 I need to do here, OK. 0:23:44.370,0:23:47.670 So I can pop out to StackOverflow or I 0:23:47.670,0:23:50.780 can pop out to, to Ruby-docs or something[br]and 0:23:50.780,0:23:54.650 take a look. Or I can just ls file, 0:23:54.650,0:24:01.020 right here. And just take a minute to look 0:24:01.020,0:24:04.330 at this, and think about all of the low-level 0:24:04.330,0:24:07.640 Ruby instrospection acrobatics you would have[br]to go through 0:24:07.640,0:24:11.930 to get this brain dump of information right[br]here. 0:24:11.930,0:24:13.940 We've got all of the methods that you can 0:24:13.940,0:24:16.480 call on instances of file. We've got all the 0:24:16.480,0:24:19.250 methods you can call on the file class. We've 0:24:19.250,0:24:22.690 got all of the methods that file inherits,[br]and, 0:24:22.690,0:24:25.650 from its superclass, and we know what that[br]superclass 0:24:25.650,0:24:26.950 is. IO. 0:24:26.950,0:24:29.070 We also know all the constants involved and[br]if 0:24:29.070,0:24:33.200 there was state involved in class or instance[br]variables. 0:24:33.200,0:24:37.870 We would see that here as well. So, all 0:24:37.870,0:24:42.600 of a sudden, I'm informed about, about everything[br]I 0:24:42.600,0:24:45.270 need to know about this class, and I have 0:24:45.270,0:24:47.770 a pretty good idea, just from a, from a 0:24:47.770,0:24:50.750 moment's notice, of how I can use it, or 0:24:50.750,0:24:54.380 what I can do to play around with it. 0:24:54.380,0:24:59.730 So let's. I see the right method. And I 0:24:59.730,0:25:02.390 don't really want to write anything or mess[br]with 0:25:02.390,0:25:04.990 anything right now, so I'm just gonna look[br]at 0:25:04.990,0:25:09.150 the documentation for it. OK. It opens the[br]file. 0:25:09.150,0:25:11.490 It optimally seeks to the given offset. Writes[br]a 0:25:11.490,0:25:14.690 string, then returns the length written. Write[br]ensures that 0:25:14.690,0:25:17.090 the files close before returning. This sounds[br]like what 0:25:17.090,0:25:18.320 I want. 0:25:18.320,0:25:22.110 I page down. I see some examples there. Great. 0:25:22.110,0:25:26.670 I'm ready to go. 0:25:26.670,0:25:33.520 Alternatively, I can do the same and call[br]show-source, 0:25:33.520,0:25:36.190 OK. Which isn't doing a lot for me here, 0:25:36.190,0:25:40.490 but when I'm in my, my own code base, 0:25:40.490,0:25:43.450 this is what I lean on more often, right. 0:25:43.450,0:25:50.410 So, let's get our bearings again. 0:25:50.410,0:25:57.410 And let's give it a try, right. File.write(file_name.class_definition).[br]OK. 0:26:02.190,0:26:04.570 Something happened. It seemed to work, right.[br]How do 0:26:04.570,0:26:09.590 I know? Really easy to shell out in Pry. 0:26:09.590,0:26:13.240 You get really nice output. Exactly what you[br]would 0:26:13.240,0:26:15.290 expect, which is, I can't say the same for 0:26:15.290,0:26:18.290 IRB in that, in that case. 0:26:18.290,0:26:20.560 I have this thing called bowling_game in there.[br]Let's 0:26:20.560,0:26:27.520 take a look at it. That looks correct to 0:26:27.520,0:26:30.250 me. So let's just do that again. I'm gonna 0:26:30.250,0:26:34.380 copy the history again. And then I'm gonna[br]remove 0:26:34.380,0:26:39.030 bowling_game, just to make sure that my script[br]is 0:26:39.030,0:26:45.190 doing what it promises, right. Oops. 0:26:45.190,0:26:51.020 And it's not there anymore. So let's go back. 0:26:51.020,0:26:58.020 Let's put in that, let's put in that implementation. 0:27:02.320,0:27:06.150 And drop back in. Let's ask Pry to try 0:27:06.150,0:27:12.130 again. No more exceptions. Do we have our[br]bowling_game? 0:27:12.130,0:27:14.210 We do. 0:27:14.210,0:27:21.210 OK. So, what happened there, right? We used[br]the 0:27:22.450,0:27:27.750 debugger and the runtime as, as, as a tool 0:27:27.750,0:27:32.380 for driving our development process and build[br]our implementation. 0:27:32.380,0:27:35.140 Not just to fix software, right. 0:27:35.140,0:27:38.340 We validated our implementation before codifying[br]it, and we 0:27:38.340,0:27:42.350 reversed this traditional workflow that I've[br]got so many 0:27:42.350,0:27:47.010 problems with. We explored and we informed[br]ourselves about 0:27:47.010,0:27:52.700 how to, how to use our classes without context 0:27:52.700,0:27:56.270 switching. Right, we stayed focused in one[br]tool. And 0:27:56.270,0:27:59.870 then we didn't have to reload our, our libraries 0:27:59.870,0:28:02.460 and our environment every time we wanted to[br]run 0:28:02.460,0:28:05.920 code, so it was fast. 0:28:05.920,0:28:11.330 So, and, you know. We're in the testing track 0:28:11.330,0:28:13.370 here, so I should probably talk about testing[br]a 0:28:13.370,0:28:17.990 little bit. And, that might have felt a little 0:28:17.990,0:28:19.850 bit like TDD to you. I mean, it does 0:28:19.850,0:28:26.340 to me, right. As, as practitioners of TDD,[br]you 0:28:26.340,0:28:30.030 know, I may not, I'm, I'm, I love TDD. 0:28:30.030,0:28:35.030 I think most, many Rubyists do. 0:28:35.030,0:28:38.110 But I mean, what I love about it most 0:28:38.110,0:28:41.320 is it keeps me focused and, and, and, having 0:28:41.320,0:28:46.660 a test suite allows me to aggressively refactor[br]my 0:28:46.660,0:28:48.240 code, you know, and have the confidence to[br]do 0:28:48.240,0:28:50.610 that. You know, and I'd rather do that upfront 0:28:50.610,0:28:54.300 than after the fact, right. But, as practitioners[br]of 0:28:54.300,0:28:59.190 TDD, you know, we've learned to love failure,[br]you 0:28:59.190,0:28:59.360 know. 0:28:59.360,0:29:02.230 TDD is all about making something fail, then[br]writing 0:29:02.230,0:29:04.130 the code to make it pass. When we have 0:29:04.130,0:29:08.030 bugs, we want to exercise that exact piece[br]of 0:29:08.030,0:29:11.190 code that's giving us the error and get that 0:29:11.190,0:29:13.250 error, you know, before we then go, cause[br]we 0:29:13.250,0:29:15.010 know we're about to do something cool and[br]fix 0:29:15.010,0:29:16.750 it, right. 0:29:16.750,0:29:21.730 So, we love to see red. And so a, 0:29:21.730,0:29:26.200 a practice that's, that's centered around[br]failure is naturally 0:29:26.200,0:29:28.590 suited to a debugging tool, right. I mean,[br]that's 0:29:28.590,0:29:32.520 what a debugging tool does. It's meant to[br]handle 0:29:32.520,0:29:35.770 failures, catch failures, and then give you[br]the tools 0:29:35.770,0:29:38.750 you need and enable you to fix them as 0:29:38.750,0:29:41.760 quickly as you can. And we've seen how awesome, 0:29:41.760,0:29:45.060 you know, a debugger Pry can be. 0:29:45.060,0:29:49.360 And, so, the promise of this talk is that 0:29:49.360,0:29:53.220 I'm going to, you know, deliver a, a, a 0:29:53.220,0:29:57.220 Pry-enabled TDD workflow. But before I do[br]that, I 0:29:57.220,0:29:59.850 mean, I mentioned that, you know, I've had[br]a, 0:29:59.850,0:30:04.340 kind of specific experience that made me a[br]believer 0:30:04.340,0:30:07.000 that this workflow even happens. I mean, I've[br]actually 0:30:07.000,0:30:10.350 done this before. I'm not creating this, right. 0:30:10.350,0:30:14.750 And, and that specific experience was this.[br]Does anybody 0:30:14.750,0:30:19.910 know what this is? Smalltalk. Yeah. This is[br]a 0:30:19.910,0:30:24.990 screenshot of a Farrow Smalltalk IDE, right.[br]And I 0:30:24.990,0:30:29.250 spent about a year or so in the 2000s 0:30:29.250,0:30:32.010 writing a web application in the C-side framework[br]in 0:30:32.010,0:30:35.200 Smalltalk for a company in New York City with, 0:30:35.200,0:30:37.240 with a team of guys. 0:30:37.240,0:30:41.740 And, really delving into object-oriented programming,[br]and learning so 0:30:41.740,0:30:44.830 much about it, I really learned to love this, 0:30:44.830,0:30:48.910 right. But what first, what first struck me[br]when 0:30:48.910,0:30:52.250 I saw Pry and I saw the ls command 0:30:52.250,0:30:57.060 was it reminded me of this, right. Right here, 0:30:57.060,0:31:00.580 we are looking at a ZnClient class in a 0:31:00.580,0:31:05.160 Zinc HTTP package. We see the class definition[br]right 0:31:05.160,0:31:07.730 there at the bottom, with all of the instance 0:31:07.730,0:31:11.510 variables that this class makes use of listed[br]out. 0:31:11.510,0:31:13.930 On the right hand side, we see all the 0:31:13.930,0:31:17.260 methods that we can call on this, on a, 0:31:17.260,0:31:19.530 on an instance of class, and we can click 0:31:19.530,0:31:22.860 on any of those to see the source code 0:31:22.860,0:31:27.090 of that method. I mean, that's all, that's[br]all 0:31:27.090,0:31:31.340 you need, as far as I'm concerned. I mean, 0:31:31.340,0:31:34.760 that gets you ninety percent of the way there 0:31:34.760,0:31:38.750 almost every, like, almost every time, right. 0:31:38.750,0:31:43.400 So, I wanted to, I wanted to demo, like 0:31:43.400,0:31:46.040 a, a Smalltalk TDD workflow, cause that's[br]the other 0:31:46.040,0:31:49.580 really cool thing about Smalltalk and different[br]thing about 0:31:49.580,0:31:52.960 Smalltalk is that it really, like, enables[br]this awesome 0:31:52.960,0:31:55.270 TDD workflow. And I don't think I'm gonna[br]have 0:31:55.270,0:31:58.110 the time to do that unfortunately. 0:31:58.110,0:32:04.870 But the TL;DR is this, basically. OK. So if 0:32:04.870,0:32:07.970 I write a test, and I try to exercise 0:32:07.970,0:32:14.020 a class that doesn't exist, like BowlingGame[br]here, Smalltalk's, 0:32:14.020,0:32:17.630 when I save this, Smalltalk's gonna say, that[br]doesn't 0:32:17.630,0:32:19.280 exist. Do you wanna, what do you want to 0:32:19.280,0:32:20.460 do? 0:32:20.460,0:32:23.990 And the first option there is define new class. 0:32:23.990,0:32:27.850 You just click it and it does it, right. 0:32:27.850,0:32:30.410 When I try to call a method on that 0:32:30.410,0:32:36.240 class that doesn't exist, Smalltalk asks me[br]if I 0:32:36.240,0:32:39.990 want to implement that method, and when I[br]say 0:32:39.990,0:32:44.250 yes, it drops me into a debugger, right. A 0:32:44.250,0:32:47.630 runtime, where I have everything available[br]I need to 0:32:47.630,0:32:50.100 create the implementation of that class, and[br]I can 0:32:50.100,0:32:52.650 expect all the things I need to do so. 0:32:52.650,0:32:56.340 Right, I'm not in a static code editor here. 0:32:56.340,0:33:00.970 This is like, living system, right. So I can 0:33:00.970,0:33:03.830 do so. Just want to return zero. And when 0:33:03.830,0:33:08.980 I save, my tests pass. So that's. That's,[br]that's 0:33:08.980,0:33:13.010 the idea, right. And, and it, it's small,[br]but, 0:33:13.010,0:33:17.190 you know, small changes in your user interface,[br]you 0:33:17.190,0:33:20.630 know, can really turn, like a daunting experience[br]into 0:33:20.630,0:33:23.290 a really motivating flow, right. 0:33:23.290,0:33:25.870 It doesn't take much. 0:33:25.870,0:33:29.650 So, when I talk about, you know, this power 0:33:29.650,0:33:31.830 of Pry and, and we've talked about some of 0:33:31.830,0:33:35.980 the plugins and how powerful they are and[br]how, 0:33:35.980,0:33:39.630 you know, Pry is so easy to extend, you 0:33:39.630,0:33:43.680 know, even I can do it. And, and so, 0:33:43.680,0:33:46.350 I've kind of gotten the ball rolling. 0:33:46.350,0:33:51.770 I pushed a little code up to GitHub. It 0:33:51.770,0:33:55.270 defines a new command called define-it in[br]Pry. Right 0:33:55.270,0:33:57.860 now, it's just a PryRC, and you can define 0:33:57.860,0:34:00.000 Pry commands in your PryRC or you can do 0:34:00.000,0:34:03.470 gems or whatever, and that's, that's where[br]I want 0:34:03.470,0:34:05.360 to move it. 0:34:05.360,0:34:09.119 But, this is my attempt to kind of get 0:34:09.119,0:34:16.119 this workflow going in, in Ruby, right. So,[br]all 0:34:22.280,0:34:27.590 right. So here it is. Here's my PryRC. I'm 0:34:27.590,0:34:33.429 creating a command called define-it, and then[br]I'm implementing 0:34:33.429,0:34:38.250 - every Pry command implements this method[br]called process, 0:34:38.250,0:34:40.290 and that is what is going to happen when 0:34:40.290,0:34:43.168 you call the command from within the Pry REPL, 0:34:43.168,0:34:43.949 right. 0:34:43.949,0:34:45.980 And so I'm kind of using this idea that 0:34:45.980,0:34:50.179 we demoed in the last demo of, when I 0:34:50.179,0:34:52.940 hit a name error, I just want to automatically 0:34:52.940,0:34:57.510 generate an empty class definition and move[br]on. What 0:34:57.510,0:34:59.000 it will also do is when I hit a 0:34:59.000,0:35:05.230 NoMethodError, it's gonna generate an empty[br]method definition and 0:35:05.230,0:35:07.210 put you right in there where you need to 0:35:07.210,0:35:11.990 be to implement it, right. 0:35:11.990,0:35:18.990 So let's take a look. So, once again. Oh, 0:35:19.080,0:35:23.490 let me just show you this real quick, though. 0:35:23.490,0:35:25.770 So here is a spec and a set of 0:35:25.770,0:35:29.790 tests that exercise this BowlingGame class,[br]right. The first 0:35:29.790,0:35:34.560 test just verifies that BowlingGame is a thing.[br]The 0:35:34.560,0:35:37.710 second test says if I ask a new BowlingGame 0:35:37.710,0:35:40.840 for its score, it should return zero. The[br]third 0:35:40.840,0:35:43.430 test says, if I bowl a four then the 0:35:43.430,0:35:46.290 game's score should reflect that. 0:35:46.290,0:35:50.580 And the last test says, if I bowl twice, 0:35:50.580,0:35:54.440 you know, the, the score should reflect that,[br]that 0:35:54.440,0:36:01.440 sum. So, when I run rSpec under pry-rescue,[br]pry-rescue, 0:36:07.120,0:36:10.640 you know, it does different things in different[br]contexts, 0:36:10.640,0:36:14.950 right. So just like before, pry-rescue's gonna[br]break on 0:36:14.950,0:36:19.700 unhandled exceptions, just like it always[br]has done, but 0:36:19.700,0:36:23.040 in the context of rSpec, it's also gonna break 0:36:23.040,0:36:25.580 on assertion failures, all right. So you can[br]poke 0:36:25.580,0:36:28.040 around and get those fixed. 0:36:28.040,0:36:34.210 So, here we are. We. We've got our first 0:36:34.210,0:36:41.210 exception, right. It's the name error. Uninitialized[br]constant BowlingGame. 0:36:41.880,0:36:45.670 So let's define it. 0:36:45.670,0:36:52.520 All right. Didn't see it, but it did it. 0:36:52.520,0:36:56.290 Next. Believe me. 0:36:56.290,0:37:01.450 All right. So next. Next, we've got our next 0:37:01.450,0:37:04.720 exception here right. Undefined method 'score'[br]for BowlingGame. Our 0:37:04.720,0:37:10.500 NoMethodError. So let's define-it. You guys[br]didn't believe me, 0:37:10.500,0:37:13.710 but there it is. All right. There we go. 0:37:13.710,0:37:18.370 We're in our empty method. Let's TDD, right.[br]We 0:37:18.370,0:37:20.350 just need to make the test pass so we 0:37:20.350,0:37:23.650 return zero out of there. Ask pry-rescue to[br]try 0:37:23.650,0:37:28.730 again. We got another exception here. NoMethodError:[br]undefined method 0:37:28.730,0:37:30.210 'bowl' for BowlingGame. 0:37:30.210,0:37:34.180 So, let's define-it. Now I feel like we're[br]gonna 0:37:34.180,0:37:37.550 need to keep track of a little state, so 0:37:37.550,0:37:44.550 let's. We want to make that the fixnum. 0:37:46.450,0:37:49.860 We want to return @score out of here now, 0:37:49.860,0:37:56.460 instead. And let's initialize @score to be[br]zero when 0:37:56.460,0:38:02.790 you create a new BowlingGame. Let's save that[br]and 0:38:02.790,0:38:03.830 let's try again. 0:38:03.830,0:38:08.090 All right. That worked. We're in our last[br]test 0:38:08.090,0:38:11.780 here, and we've hit our first assertion error,[br]right. 0:38:11.780,0:38:14.650 It expected nine and it got five, cause we're 0:38:14.650,0:38:18.570 not doing any of the, the totaling yet. So 0:38:18.570,0:38:23.540 let's, this is another way you can call edit. 0:38:23.540,0:38:27.130 You can just ask it to edit the class, 0:38:27.130,0:38:30.690 and it'll know what file to drop into. So 0:38:30.690,0:38:32.280 I feel like we're gonna want to keep track 0:38:32.280,0:38:35.420 of our scores now. So let's just push those 0:38:35.420,0:38:40.640 fixnums on a scores array. Let's get our score 0:38:40.640,0:38:44.480 by reducing those values. That's how you keep[br]score 0:38:44.480,0:38:47.220 in bowling, right. You just add everything[br]up. All 0:38:47.220,0:38:48.570 right. Cool. 0:38:48.570,0:38:53.280 And let's, let's initialize it with an array[br]with 0:38:53.280,0:38:58.890 initial value of zero as well. Let's try again. 0:38:58.890,0:39:05.890 Something's wrong there. There it is. 0:39:07.080,0:39:14.080 All right. Four examples, zero failures. rSpec[br]thought we 0:39:14.840,0:39:21.840 didn't fail at all, you know. It's pretty[br]cool. 0:39:25.340,0:39:32.340 So. So what happened there? All right. I mean, 0:39:34.080,0:39:40.130 basically, you know, we. We, again, we used[br]Pry 0:39:40.130,0:39:44.580 to drive our development process. We used[br]our own 0:39:44.580,0:39:47.700 Pry plugin there to kind of make that a 0:39:47.700,0:39:52.390 little bit easier, and within one runtime,[br]we fixed 0:39:52.390,0:39:56.890 all of our assertions, exercised our class[br]and implemented 0:39:56.890,0:39:58.590 the whole solution, right. 0:39:58.590,0:40:01.730 No reloading, no nothing like that. 0:40:01.730,0:40:08.730 So, in conclusion, embrace your runtime and[br]all things. 0:40:10.150,0:40:14.570 Don't read the effing manual. 0:40:14.570,0:40:20.920 Use a kickass flashlight. 0:40:20.920,0:40:24.340 If you're fixing software, use a debugger.[br]If you're 0:40:24.340,0:40:27.850 building software, use a debugger. And when[br]you use 0:40:27.850,0:40:30.369 a debugger, use Pry. 0:40:30.369,0:40:32.369 Thank you very much.