00:00:12.259
Thank you, we’re good. All right, imagine if you will, it’s Sunday night. You’re brushing your teeth, getting ready for bed. Are you looking forward to work the next morning? Is it even really work because you love it so much you'd be doing it anyways in your free time? Or did I just kind of bum you out by even invoking the concept of Sunday night?
00:00:37.200
This is 'Nobody Will Train You but You.' This talk will give you the tools to do what you love every single day for the rest of your life because you'll be so freaking awesome that people will line up to pay you money for it.
00:00:48.780
This is me on the internet. My name's Zach, and I work for Test Double. I started with them last week, so if you ever want to really spike out your anxiety level, start a new job with people who are way, way smarter than you, and then give a talk at a national conference the next week. It's been kind of amazing. Test Double focuses on building apps with a lot of user interactions, like Backbone, Ember, or Angular, and then taking those to build maintainable software. It’s an amazing concept.
00:01:28.979
A year ago though, I wasn’t a developer at all. I was doing direct mail analytics, which is approximately as exciting as it sounds. I was absolutely drowning in work. I Googled this Rails thing on May 2nd of 2012. It’s a framework that’s kind of popular; you might want to give it a shot. Within a couple of months, I was hired as a junior developer after shipping my first Rails app and almost immediately bumped up to 'developer flavor'—junior no more. I joined Test Double last week, and here I am today at RailsConf.
00:02:16.739
I’m not telling you this to brag, but I see a lot of people who seem to be waiting for something—maybe they're waiting for rescue or waiting for permission. Month after month, they look at these Sundays just strung out in front of them, and every single Sunday they just can’t stand going to work the following Monday.
00:02:30.540
I’m not sure if they think somebody's going to give them permission to do what they love, but it’s not going to come. You have to do this on your own. When I first started, I wasn’t very good at the whole Ruby thing. I was pretty notorious for using the heck out of Google, and was even accused of using 'Shadow Google', this parallel search engine that only I had access to because I could find these gems to do things almost better than anyone else.
00:02:57.360
But after about two months, I realized I wasn’t getting any better at all. I talked to one of my friends about this and asked them if maybe Stack Overflow was rotting my brain, but he didn’t buy it. He told me that I just needed more time and that I was being too impatient. After two months, I should expect to still kind of suck. It takes more and more conversations with the compiler to get better.
00:03:34.980
So we went back to pairing that afternoon. I don’t remember exactly what we were working on—maybe it was a Rails migration we wanted to do in a single transaction to avoid waiting multiple times for a large table. We went online to search for the syntax, and on his browser, there was just this big wall of visited links, almost like he had been there before.
00:04:06.659
If that was my browser, I would have seen the same thing—just walls of purple. So he obviously hadn’t had enough conversations with the compiler either. We did the migration, got back in the model, and finished up whatever we were working on. Neither one of us could remember what it was; it completely fled our brains. This struck me because we were not naturally getting better. Each one of these searches was expensive—it’s a context switch, and as programmers, we know how costly these context switches are.
00:04:51.720
It’s like being tapped on the shoulder and interrupted. It costs about 10 minutes per 10 minutes of pop. If you’re in a situation where you only have three hours of productive time during the day—pretty common—nine trips out to the web for some syntax you didn’t quite know costs you half of your day. That leaves an hour and a half left to work. I’m not good enough to get all my work done in an hour and a half—maybe you are. It doesn’t have to be that way, though.
00:05:35.280
Corey Haynes talks about making your searches your own after the fact. Every time I do a search, I write it down on an index card. I write the answer down on the other side, and when I have some free time, I review it—I make it my own. Typically, just the act of writing it down on paper has great features—it’s flexible, it’s visible in sunlight, and it has excellent battery life. But the act of writing it down seems to cement it into my brain in a way that typing it doesn’t.
00:05:54.600
In my previous position, we frequently dealt with business intelligence dashboarding. We had text files as inputs and eventually built a Backbone front end as an output. I had this collection of strings, and I didn't want the whole string, only a piece of it, so I had to learn regex. I took a break from being angry at regular expressions long enough to learn this recipe, which I was able to apply to various situations. Suddenly, there was a whole category of problems I didn’t have to go out to the web anymore; I could just adapt this.
00:06:35.760
Here's another one: We would have a hash, and we want a slightly different hash or radically different data structure. Now, I have each of those objects in my pocket. Anytime I hit this class of problems, I can adapt this. When looking at a blank screen, text editor, or a blank piece of paper, we can’t pretend we got it right. Do you know off the top of your head what the order of arguments is, or how to use each with object versus inject without looking it up? That’s important; just knowing it and being able to recall it quickly gives you a huge advantage.
00:07:03.539
Since I started doing this, I’m so much faster now. I can’t tell you how much faster. I’ve probably doubled my speed, maybe even more. I find myself being more creative too. I had a German teacher in high school who told me to think in German. When you’re fluent enough in a language to think about it, you can compose new sentences. Similarly, when you're fluent enough in Ruby and don’t have to keep going back to the web, you can start making these new connections and use lateral thinking, thinking outside of the box.
00:07:41.280
However, this only gets us so far. Each with object isn’t going to teach me about dependency injection. Regular expressions probably won’t teach me about composition. We need to find a way to know what we don’t know. Thank you Donald Rumsfeld for popularizing the concept of 'unknown unknowns'—this includes the stuff I know, the stuff I don’t know, and then the unknown unknowns.
00:08:08.220
In my case, the unknown unknowns are the dark matter—the interesting part of what we need to learn. An example of this for me was the law of Demeter—a dead simple concept that’s often misrepresented. I’d heard about it before, but it wasn’t until I began putting my code under test and trying to drive corner cases out of software that I really understood it. As I wrote new tests, I kept having to instantiate three other unrelated objects, which was a pain in the ass.
00:08:48.840
After about 20 minutes, it hit me—this shouldn’t suck so much. The way my code is structured is probably pretty bad, and if my tests are experiencing this annoyance, it means if those incidental objects change, other unrelated objects are just going to shatter at the same time. It was through that test pain that I gained a little wisdom; wisdom must be earned, not grown.
00:09:33.180
We don’t have to wait around on someone else’s schedule to earn more wisdom. It doesn’t take years of extra-curricular activities. We can go out and pick our own fights and advance beyond our years. We, as open-source developers, are lucky to have access to the collective knowledge available out there. If Google has all the world’s knowledge, then GitHub surely has its wisdom.
00:10:12.680
It’s fantastic to look at someone else’s source code and gain wisdom from it, but we can’t infer wisdom from a product any more than a pig can be inferred from a sausage. It is possible, however, to follow the process forward from a blank page to final draft and learn something along the way. Just because we’re looking at someone else's source code doesn’t mean we have any idea why those characters are laid out that way.
00:10:53.580
We need the microsteps, the minutia; it’s the only way we’re going to gain wisdom. We’re lucky in the Rails community to have these brilliant tutorials and books available to us to gain that wisdom. Michael Hartl is somewhere at this conference, and I went through his Ruby on Rails tutorial, which helped bootstrap me. Sandy Metz is also here; make sure to say hi to her. She has this amazing book on object-oriented design with Ruby.
00:11:12.300
We have these incredibly detailed tutorials out there. Some are available for free. I’ve recently been teaching myself more JavaScript after joining Test Double, and I feel lucky to be part of the Ruby community for the wealth of tutorials available. One of my favorites is 'Build an App with Corey Haynes,' a screencast series. There's also 'Objects on Rails' by Avi Grimm.
00:11:49.740
And the one I want to talk about today is 'Sucks Rocks,' part of the 'Destroy All Software' screencast series. Currently, subscriptions are suspended, but it is going to open up again at some point. This was the perfect tutorial for me—it’s super high in context. We’re not just building a bowling scorer with no inputs or outputs; we’re creating a web app that’s hitting an external API and serving JSON.
00:12:10.740
Every single piece of source code is typed out; nothing is just magically pasted on the screen. I hate that in tutorials. We see each bug being committed, and we witness the blind alleys and recover from them. Find somebody you trust, who has skills you want, and who inspires you—maybe that’s Gary Bernhardt or maybe it’s not.
00:12:35.460
The eight-part series on 'Sucks Rocks' has a runtime of about an hour and a half. I treated each episode like a kata, watching it, taking notes, and attempting to reproduce it character for character, going back through time and time again. After the fourth or fifth time watching an episode of someone else's screencast, you start to feel a little stalkery. You might start wondering, 'What do you think about a Gary Bernhardt tattoo?'
00:13:03.420
It took me 40 hours to fully memorize this tutorial—turns out he types kind of fast. That was time I wasn’t spending with my spouse, Mary, or doing billable side work. It was a measurable opportunity cost. I wasn't looking at other tutorials or teaching myself new things.
00:13:30.960
After hearing the phrase 'testing behavior versus testing implementation,' did you ever want to punch someone in the nose because it sounded so meaningless? I didn’t really get that concept at first—it wasn’t helpful. This is code that’s similar to what was in the original 'Sucks Rocks' app. It originally used 'Arbing' which is a Ruby Bing wrapper, but that API is long gone.
00:14:02.100
It’s been completely overhauled and then disappeared in favor of Windows Azure. So I just swapped it out for the Google gem. This is a fundamental component that makes the rest of the app run, and it was two lines of production code—zero lines of test code that changed when I swapped it out.
00:14:39.600
This, of course, is a subset of the single responsibility principle. We know it’s important because it has a lot of syllables, and the more syllables a principle or a law has, the more we have to pay attention to it. This is probably character for character out of the 'Sucks Rocks' app. It’s not super apparent at a glance, but at no point do we allow an Active Record object to leave the model and perform 'find by term'.
00:15:00.660
Typically, I would have structured my app differently. I would have written my tests first, but they would have just been a checkbox. I’d think, 'Oh, I’ll write my tests first,' and then just smear some more stuff on the model. However, when the tests were allowed to influence the design of the system, it ended up looking more like this.
00:15:31.620
I don’t think this structure had any transitions; it emerged naturally through TDD, and it was the first time I saw this truly occur in a Rails app. It was mind-blowing for me, like one of those Wizard of Oz moments. This wasn’t our planned outcome; it wasn’t some universal design approach. It just happened, and it was kind of awesome.
00:16:05.580
Notice that the third-party API is just sitting in the corner, keeping baby company. When it changes, it’s going to cause fewer breaks than the rest of the system. For example, think of something like Braintree in some of the Rails apps we’ve seen. Think of all the places in a user model that would have to change in an average app if a different payment processor was used.
00:16:35.100
On Friday, I had actually cargo culted this structure into a prototype JSON API backend I was building. My assumptions were way off to the point where I ended up rendering it all server-side. It took me 15 minutes to swap the structure of the application around from a JSON API into just a single template rendering because I could gather those components and plug them into something else.
00:17:05.520
This isn’t a universal solution for all of your problems, and this is also where I started to fight nil. The dreaded 'no method error undefined method each for nil:NilClass'—thank you, Ruby, for that. Typically, the origin of the nil isn’t even in that stack trace. That kind of garbage is what I expect from JavaScript; it's disappointing coming from Ruby.
00:17:31.560
Some of those nil errors start to sound like urban legends. I once saw a nil originate in one object, travel through two others, and back into a Rails backend, causing chaos. But I have to give props to Binding.pry, it can help track down a nil.
00:18:01.500
The kind of stuff happens; similar production code that I might have written back in January hits some kind of external API wrapper while I’m doing some work. It’s really common in Ruby to return nil when something isn’t found as a default behavior. If Active Record’s find doesn’t find something, we know it’s going to return nil.
00:18:32.520
This is how I would structure the code now—using a sentinel object. I was using this at work a few months ago, and my partner asked me, 'What the heck are you doing, Zach? That’s class.new? Exactly how much paint did you huff this morning?' I got kind of excited because Gale is awesome; I don’t get many opportunities to show her something new.
00:19:02.040
I told her that’s just an inner object since 'no score' is something that’s kind of okay to happen in our logic. We need something to represent that, but nils can be problematic. Almost on cue, 15 minutes later, we got a stack trace that said undefined method each for performance: no score. Holy crap, now that’s a stack trace we can work with!
00:19:31.920
Last week, I saw a stack trace like this in New Relic. Imagine a nil stack trace in New Relic. You probably don’t have to imagine that; you’ve probably pulled the app back down to get the database into the same state to use Binding.pry and protect your face.
00:20:06.840
When you encounter stack traces like this, you can look at the New Relic event console and think, 'Oh wow, I know what’s happening there,' and use it to diagnose and troubleshoot problems. I’ve had far fewer afternoons just lost to debugging.
00:20:40.920
I took the tools from that tutorial, the tools that Gary Bernhardt has in his brain, and through 40 hours of memorization—practicing over and over again, experimenting, and trying them in my projects, seeing where they worked or didn’t, and when I showed someone else, saying, 'Hey, this is so cool! Look at this.' I learned one, did one, and trained one.
00:21:07.920
The very first time I encountered these, I kind of made a copy of those tools for myself. I’m not arrogant enough to think I’m as good as him, or that my tools resemble his—but they’re mine, and that’s the point.
00:21:35.520
Since they're mine and they're not just things I'm mindlessly copying into an editor, I feel comfortable pulling them out when I see fit. And since it’s not dogma or a religion, I can put them away when they’re not the right tool for the job.
00:22:07.920
I still like the Rails generate scaffolds because quick demos are nice to have ready for someone. I still have my controllers talking directly to my models a lot of the time because that’s perfectly okay. Just because I know how to build a system that doesn’t do that doesn’t mean I can’t build systems that allow for it.
00:22:33.720
Memorizing a good tutorial made me a better developer. My code is much safer because I’m testing meaningful things. I’m writing tests that reflect reality, and since they’re not stapled directly to the production code, they’re less likely to shatter with minor changes. Writing tests like that means I had a test suite that was more reliable.
00:23:01.920
My code is more resilient; my tests don’t break as often, and the rest of the code suffers less as well. I’m a lot faster now because I know this stuff cold—these things spring to my fingertips without me having to think.
00:23:32.760
Writing down all of my Google searches is also faster. Remember that two-time speed increase when fluent in Ruby? It also fosters more creative lateral thinking—thinking outside of the box.
00:24:00.480
And I haven’t even told you the best part yet! The best part is every time I’m on the server side, starting a new project, or creating a new feature in an existing project, I have the skill and confidence to begin with a plain old Ruby object (PORO). I feel like I’m back on tryruby.org for the first time!
00:24:42.480
Can you remember your first time playing with Ruby? Maybe it wasn’t try Ruby, or maybe we have some Pickaxe babies in the crowd or Rails babies. This is programming; you’re not supposed to have that much fun!
00:25:19.560
Every time I do this, I’m having a blast! See, I just lied to you—these aren’t tools; these are toys. That’s Jim Wyrick up there, doing his Y Combinator keynote from RubyConf last year.
00:25:48.480
The code up on his slide isn’t production quality; in fact, I think your fingers would break if you tried to use it in production. But it’s just something he enjoys, and he’s sharing that enthusiasm. One time, I was watching a video from ConFreaks last December when my spouse, Mary, walked in, looked at the screen, looked at me, and asked, 'Is Santa Claus teaching you Ruby?'
00:26:19.740
Yeah, I guess so, kind of. The very best programmers—the ones who can work anywhere because their resumes are their name—the ones that don’t have to dread Sundays, because every day they’re doing what they love—those programmers didn’t get that way just from hard work; they got that way because they’re having so much fun they couldn’t bear to put down the keyboard.
00:27:00.240
My name is Zach. Have fun!