DEV Community

Cover image for Refactoring Code in Ruby
Amy Chen
Amy Chen

Posted on • Edited on

Refactoring Code in Ruby

In object-oriented programming, it's best to keep code DRY (Don't Repeat Yourself), as opposed to code that is WET (Write Every Time, Write Everything Twice, We Enjoy Typing, or Waste Everyone's Time).

If a line of code is repeatedly written or copied and pasted, it triggers a "code smell." A code smell is any characteristic in the source code of a program that possibly indicates a deeper problem. In the case of repeated code, the problem is repetition. This makes it an ideal time for refactoring.

Refactoring code is the process of simplifying existing code without modifying its functional behavior. The results in code that is easy to read, debug, and maintain. It also produces syntactic sugar, which is any aspect of the syntax of a programming language that makes programs easier to read, write, or understand.

In Ruby, one way to refactor code is using attr_accessor in a Class. Using attr_accessor eliminates the need to write the reader and writer methods as shown below:

class Dog
    attr_accessor :name, :breed
    @@all = []

    def initialize(name, breed)
      @name = name
      @breed = breed
      @@all << self
    end

    def self.all
      @@all
    end

    #def name=(name)
      #@name = name
    #end

    #def name
      #@name
    #end

    #def breed=(breed)
      #@breed = breed
    #end

    #def breed
      #@breed
    #end
end
Enter fullscreen mode Exit fullscreen mode

Another way to refactor code and keeping it DRY is using a helper method. Using helper methods can also help to reduce errors and make it easier to debug by having the logic in one place.

In the example below, the lifters method is refactored by reusing the previous method (memberships) as a helper method. If a helper method wasn't used, there would be repetitive code as seen in the two alternative methods.

# Get a list of all memberships at a specific gym:
  def memberships
    Membership.all.select {|m| m.gym == self}
  end

# Get a list of all the lifters that have a membership to a specific gym:
  def lifters
    memberships.map {|m| m.lifter}
  end

# Methods with repetitive code:
  def memberships
    Membership.all.select {|m| m.gym == self}.map {|m| m.lifter}
  end

  def lifters
    lifter_memberships = Membership.all.select {|m| m.gym == self}
    lifter_memberships.map {|m| m.lifter}
  end
Enter fullscreen mode Exit fullscreen mode

Sure, refactored code requires less typing and looks cleaner. However, the first priority should be writing code that is functional. Get the code working then edit and refine for increased efficiency.

In the example below, two methods are shown to return the average lift total of all lifters. Both methods have the same functions: mapping over an array to retrieve the lift total of each lifter, adding them up, and then divide the total by the number of lifters.

As you can see, the original method has more lines of code. The second method abstracts the steps and reduces it into two single line blocks:

  # Get the average lift total of all lifters:

  # ORIGINAL METHOD
  # def self.lifters_average
  #   lifts_total = @@all.map do |lifter| 
  #     lifter.lift_total
  #   end 
  #     return lifts_total.inject do |sum, element| 
  #       sum + element
  #     end / lifts_total.length 
  # end 

  def self.lifters_average
    lifts_total = @@all.map {|lifter| lifter.lift_total} 
      lifts_total.sum / lifts_total.length
  end 
Enter fullscreen mode Exit fullscreen mode

Alt Text

In conclusion, the first priority when writing code is always making sure the code works, no matter how long or messy it is. From there, clean it up by refactoring to make it more efficient.

Top comments (0)