Tips for Refactoring

Lately I’ve been making a lot of mistakes while refactoring large projects. You know – the kind of mistakes that leave you scratching your head for an hour or two wondering why your test just won’t turn green. With help from my mentor, I’ve come up with a few tips that decrease the amount of time I spend scratching my head and make refactoring a bit smoother.

Add before you delete

When you add or update methods, add the new code before you delete your old code. I often write test and methods before realizing that my method should be two or three methods instead of just one. I use to cut and paste to a new method or delete that section and rewrite it in a new method. I would be often be left with broken tests for a while and have a lot of trouble figuring out where I went wrong.

This problem can usually be prevented by creating tests for a new method, and then writing that method before you even delete the old code. Make sure you’re tests are passing before you link to your new method and delete the old code. Once everything looks good you can make the switch from the old method to the new method.

Here’s a good example:

example.rb

class ExampleOfBadMethod
  def long_method(animal)
    if animal == "golden retriever" || selection == "poodle" || selection == "pug"
      "Bark!
    elsif animal == "kitten" || selection == "siamese" || selection == "cat"
      "Meow!"
    else
      puts "What is that?!"
    end
  end
end

#rspec tests below

describe "Example of bad method" do 
  it "responds bark if animal is a dog" do 
    expect(long_method("poodle").to eq("Bark!")
  end

  it "responds meow if animal is a cat" do 
    expect(long_method("cat").to eq("Meow!")
  end
end

Now write your new code before deleting old.

class ExampleOfBadMethod
  def long_method(animal)
    if animal == "golden retriever" || selection == "poodle" || selection == "pug"
      "Bark!
    elsif animal == "kitten" || selection == "siamese" || selection == "cat"
      "Meow!"
    else
      puts "What is that?!"
    end
  end

  def is_dog?(animal)
    if animal == "golden retriever" || selection == "poodle" || selection == "pug"
       return true 
    else
       return false
    end
  end

  def is_cat?(animal)
    if animal == "kitten" || selection == "siamese" || selection == "cat"
       return true 
    else
       return false
    end
  end
    
end

#rspec tests below

describe "Example of bad method" do 
  it "responds bark if animal is a dog" do 
    expect(long_method("poodle")).to eq("Bark!")
  end

  it "responds meow if animal is a cat" do 
    expect(long_method("cat")).to eq("Meow!")
  end

  it "responds bark if animal is a dog" do 
    expect(is_dog?("poodle")).to eq(true)
    expect(is_dog?("cat")).to eq(false)
  end

  it "responds meow if animal is a cat" do 
    expect(is_cat?("cat")).to eq(true)
    expect(is_cat?("poodle")).to eq(false)
  end
end

Now delete the old code.

class ExampleOfGoodMethod
  def long_method(animal)
    if is_dog?(animal)
      "Bark!
    elsif is_cat?(animal)
      "Meow!"
    else
      puts "What is that?!"
    end
  end

  def is_dog?(animal)
    if animal == "golden retriever" || selection == "poodle" || selection == "pug"
       return true 
    else
       return false
    end
  end

  def is_cat?(animal)
    if animal == "kitten" || selection == "siamese" || selection == "cat"
       return true 
    else
       return false
    end
  end
    
end

#rspec tests below

describe "Example of good method" do 
  it "responds bark if animal is a dog" do 
    expect(long_method("poodle")).to eq("Bark!")
  end

  it "responds meow if animal is a cat" do 
    expect(long_method("cat")).to eq("Meow!")
  end

  it "responds bark if animal is a dog" do 
    expect(is_dog?("poodle")).to eq(true)
    expect(is_dog?("cat")).to eq(false)
  end

  it "responds meow if animal is a cat" do 
    expect(is_cat?("cat")).to eq(true)
    expect(is_cat?("poodle")).to eq(false)
  end
end

There you go! Cleaned up code and nothing broke.

Google (No really, google more)

Googling is an important skill for every developer. It’s impossible to remember every method and pattern for every language you use. As much as I understand this, I recently realized that I’m not googling enough. I’m still pretty new to the world of programming and working on a lot of small projects and challenges. I always make a valiant effort to figure these out on my own and try my best not to look for or copy code from the internet. So because of that, I don’t Google enough. I’ve been missing out on really helpful methods, knowledge and tips from StackOverflow, and blog posts that discuss strategies and patterns.

Plan ahead

In projects where I have a runner class or other high-level classes, I don’t always want to create them first. But it still helps to have an idea of how they will run your program. It might help to write down the order of your runner, i.e., the list of steps you’ll take to run your program. Then just try to knock them off one-by-one in order or start with the easier classes or methods first to get them out of the way. Then you might want to go ahead and create your high-level classes which end up piecing everything together.

It also helps to draw pictures of your class structures or your data structures to visualize what you’re going to build.

Leave a Reply

Your email address will not be published. Required fields are marked *