Josh Thompson     about     blog     projects

Mythical Creatures: Refactoring wizard.rb

Article Table of Contents


Preparing for Turing Series Index #

What follows is an eight-part series that will help you pick up useful information about a number of topics related to Ruby, specifically geared for students learning the Ruby programming language, as part of the Turing School’s Backend Software Development Program

It’s generally intended that you progress sequentially, but there’s no “right way” or “right order” to encounter these topics. You could convince me I have the order exactly backwards. I’d disagree, but only slightly.

I encourage you to skim around these chapters, get the “shape” of what’s to come, in your mind, and then dive in wherever you want. Good luck, and bug reports are welcome.


Today we’re refactoring some code.

I find it extremely fruitful when others look over my code and help me clean it up. Quite a few Turing students have told me that the process of refactoring their own code with the help of someone who knows a bit more than them has been super helpful.

This is an exercise from Turing School’s ruby-exercises repository.

Specifically, we’re refactoring a solution that makes this test pass.

How to get the maximum value from this exercise #

So far, I’ve found it most helpful to have my own code refactored. I wish I could help every single person who might read this post refactor their own code.

But I cannot.

But here’s the thing - when you’re working, you’ll often not be refactoring your own code either. It’s most likely you’ll be reading (and updating) code that someone else wrote.

Or you’ll be nestling in new code and new features alongside existing code and existing features.

So it’s useful to get practice reading other people’s code, and being able to work with it.

Video Walk-through #

Sometimes video walk-throughs are helpful, so I put one together. It is 7 minutes long, and covers useful material.

Copy-paste this code into your editor and run the tests:

# ruby-exercises/mythical-creatures/wizard.rb
class Wizard
  attr_reader :name
  def initialize(name, bearded: false)
    @name = name
    @rested = 0
  end
  def bearded?
    if name == "Ben"
      true
    else
      false
    end
  end
  def incantation(saying)
    "sudo " + saying
  end
  def rested?
    if @rested >= 3
      false
    else
      true
    end
  end
  def cast
    @rested += 1
    "MAGIC MISSILE!"
  end
end

The tests should pass.

We’re going to cover a few things:

  • Guard Clauses
  • Default variables
  • Running just a single test from a test file instead of the whole thing
  • Sometimes simple things go wrong and are deeply frustrating

Guard Clauses #

Here’s the guard clauses I mention: guard clauses (thechrisoshow.com)

Default variables #

the test wizard are bearded by default implies that in the initialization method, we should set bearded equal to true, rather than false.

Run just a specific test in a test file (Minitest) #

Sometimes it’s helpful to run just a single test in a test file, rather than the whole thing.

Here’s the format:

ruby something_test.rb --name=/a-string-that-matches-something-in-the-test-you-want-to-run/

instead of --name=/abc/, you can use -n=/abc. I’ll often append the string zzz to the test I want to run, then append -n/zzz/ to the test running command. (With rspec you can identify test by line number.)

Things go so, so wrong #

The video walk-through was my second time recording the video, because I’d wandered so much in my explanations in the first video.

Then, mid-way through the video, I closed the terminal window, CD’d into the wrong directory, and got a bunch of errors. I got it fixed, then fat-fingered my way back into closing the terminal. I was super frustrated.

I’m ostensibly a “professional”, in that I get paid to “develop software”, but I thought it a useful reminder that we all do things that are frustrating and cause us to waste time. When you do this yourself, don’t worry about it to much. Our entire craft is hard. Reality has a surprising amount of detail and it’s annoying when we get bit by that detail.

Here’s the final version:

class Wizard
  attr_reader :name, :bearded, :rested, :spell_counter
  def initialize(name, bearded: true)
    @name = name
    @rested = true
    @bearded = bearded
    @spell_counter = 0
  end
  
  def bearded?
    bearded
  end
  
  def incantation(saying)
    "sudo " + saying
  end
  
  def rested?
    return false if spell_counter >= 3 # this is a "guard clause", sorta
    rested
  end
  
  def cast
    @spell_counter += 1
    "MAGIC MISSILE!"
  end
end

Preparing for Turing Series Index #

What follows is an eight-part series that will help you pick up useful information about a number of topics related to Ruby, specifically geared for students learning the Ruby programming language, as part of the Turing School’s Backend Software Development Program

It’s generally intended that you progress sequentially, but there’s no “right way” or “right order” to encounter these topics. You could convince me I have the order exactly backwards. I’d disagree, but only slightly.

I encourage you to skim around these chapters, get the “shape” of what’s to come, in your mind, and then dive in wherever you want. Good luck, and bug reports are welcome.