Josh Thompson     about     archive     tags

Deliberate Practice in Programming with Avdi Grimm and the Rake gem

I’ve had the concept of Deliberate Practice stuck in my head for a while.

I want to improve at things (all the things!) in general, but writing and reading code, specifically. Writing and reading code is germane to my primary occupation (software developer) and drives most of my effectiveness on my team.

If there are two people, one who knows more about something, and one who knows less, but the person who knows less is learning new things faster than the other person, in short order, they’ll switch places.

This concept comes from John Ousterhout, and his talk at Stanford about how the slope is more important than y-intercept.

slope and intercept

I know how to write the code I know how to write; I don’t know how to write better code than that. So, I’m taking advantage of code written by people who are really good at what they do, and I’m modeling my code after them.

Deliberate Practice

I’m trying to apply the principles of deliberate practice to writing code.

Eric Anders coined the term Deliberate Practice, and it boils down to four components:

  1. You must be motivated to attend to the task and exert effort to improve your performance.
  2. The design of the task should take into account your pre-existing knowledge so that the task can be correctly understood after a brief period of instruction.
  3. You should receive immediate informative feedback and knowledge of results of your performance.
  4. You should repeatedly perform the same or similar tasks.
>> Read more

Turing Prep Chapter 4: Arrays, Hashes, and Nested Collections

Index of this series:

So far, we’ve covered some string manipulation and did a few mythical creatures.

You totally don’t have to look through the screencasts in order. I just wanted to call out array/hash manipulation on its own page.

You can also look through the whole playlist.

>> Read more

Exploring source code via Griddler and Griddler-Mailgun

Proofpoint had a two-day “hack day” recently. My coworker John and I teamed up on a cool little feature. I’ll give some context in a moment, but this post isn’t about the hack day, or email - it’s about exploring source code.

Here’s the context:

In my day-to-day, I work on a simulated phishing tool; it lets our customers send simulated phishing attacks to their employees

We then gather and report data on things like:

  • who opened the email
  • who clicked the phishing link (or opened the attachment)
  • who read the subsequent training page
  • and more

One strong benefit of using this tool is our customers can send their employees very realistic, very tricky phish, and educate them how to avoid falling for those tricky phish “in the wild”.

The more realistic the phish, the higher-quality the training.

So, we wanted to set up an email inbox that our customers could forward real-life phish to, and our staff could look through all the submitted phish, preview the email, and decide to convert the real phish into a simulated phishing template available in our “phishing template library”.

Basically, if you got a really sneaky phish, you could forward it to [email protected], and we could quickly decide if we wanted to make this phishing template available to all our customers.

I’d heard this idea discussed before, always as a “nice-to-have”, but the feature ticket never got written, and we never prioritized it. John and I work closely with the Director of Support, and others, and when digging into their pain-points, they also said this would be a nice feature.

So, we decided to build it!

We still have to set up some SMTP stuff in Mailgun, and do a few other bits of configuration, but the actual rails app is functioning as expected, and can receive mail passed along from Mailgun.

I’m not writing about receiving mail in a Rails app, though - that’ll be another post. But at one point, John and I got pretty bogged down with some unexpected errors.

It wasn’t until we started exploring the source code of the gem generating the errors that we found the problem.

Had we been quicker to jump into the gem source code, we would have saved ourselves three hours, and maybe would have gotten the entire feature built and up for testing in the time-frame we had.

Recently I’ve been making it a habit to explore stack traces when I get them, because when they pop up in my terminal, it’s super easy to view the source of the problem.

So, here’s the error we were getting:

griddler gem

>> Read more

Turing Prep Chapter 3: Moar Mythical Creatures

Index of this series:

I’ve made a few more videos, focusing on the Mythical Creatures exercises.

Mythical Creatures: unicorn.rb

Once you’ve finished the strings, arrays, hashes, etc… you may want to take a spin at the infamous Mythical Creatures!

These exercises will give you lots of practice with “object oriented” programming. You will define an object (like a Person object) and create instances of that object that have certain behaviors and methods of interaction.

This is a lot to wrap your head around, and “object oriented programming” is a topic that fills dozens of books, hundreds of conference talks, and you’ll spend the rest of your life building a better understanding of. So don’t feel any rush to grasp it all in the next ten minutes.

Start with this guide: LaunchSchool: The Object Model

Read it carefully, but don’t worry that it all won’t make sense. Take notes, run the code examples. Take an hour on it. When you’ve gone through it once, tackle the first mythical creature.

It can be tricky getting set up, so here’s another video of the very first mythical creature:

A quick aside - as you work through these exercises, and all of the exercises to come, you’ll perhaps notice a constant tension between “results” vs. “process”. Here’s what I mean by this, explained in a conversation with a Turing student, working through this exact guide:

They said:

[…] In other words, there is more than one way to achieve the result, so do I focus on process or product? I am not expecting there to be a single “right” answer, but I am curious as to how Turing is going to evaluate us. Are the steps used more important than the outcome?

I responded with:

Your intuition is leading you well - the steps and the outcome, are important.

I’d recommend de-emphasizing the Turing evaluations in your mind, though, and just focusing on building the right kind of skills that will serve you well for the rest of your career as a developer. And, from that lens, there will always be tension between the best I know how to do right now and the best that can be done, ever.

Obviously, as you grow your skill-set as a developer, you would be able to go back and improve prior bits of code you’ve written. It’s rare to crank out a “perfect” project, no matter how small.

So, optimize for learning, which basically means… when you find something that works, use it, but next time you come across a similar kind of challenge, you might use something slightly different. I don’t know if any of this makes sense. It basically means don’t sweat not getting exposed to every single ruby method, but be open to using new ones as situations arise, and you get more comfortable with the ones you know.

Or, in summary:

There may be multiple ways to achieve the required outcome; use what you now know; be on the lookout for other methods that achieve the same result.

>> Read more

Turing Prep appendix: Troubleshooting Errors

Index of this series:

As you run into problems (and others) let me know. I’d like to collect a broad swath of the errors folks run into, and the solutions, so they don’t get too caught up.

Here’s a quick index of what’s in this guide:

Traceback... cannot load such file -- pry

This seems like an intimidating error message at first.

It’s not. The error just says:

Dear user, you’ve asked me to import code to run these tests, but I cannot find the code you require.

The code I was looking for (and cannot find) is called pry

Pry is an amazing tool. You’ll soon come to love it. In the mean time, just install it. It’s a ruby “gem” so you use the gem install <gem_name> command.

In your terminal, run gem install pry and then run the tests again.

Cannot open atom from the terminal

You may need to install the Atom Shell Commands. Atom makes it super easy to do this:

install shell commands

>> Read more