Posted on 27 mins read

Introduction

Let’s begin by considering: “What is Refactoring?”

The definition of refactoring is:

a disciplined technique for restructuring an existing body of code, altering its internal structure without changing its external behaviour

Refactoring is a term originated from the Smalltalk community of developers back in the mid-late nineties.

Two of the most prolific programmers of recent times, Martin Fowler and Kent Beck literally wrote the book on the subject of refactoring called “Refactoring: Improving the Design of Existing Code” (well, written by Martin with contributions from Kent).

In 2009 both Martin and Kent helped with a rewrite of the book that focused more on the Ruby language than the original book’s target language of Java. This follow-up book was called “Refactoring: The Ruby Edition” and it’s that book which is the primary driving force of this post.

Since reading the Ruby edition I wanted to have a short summarised version of some of the more commonly used refactoring techniques (mainly for my own reference). By that I mean the techniques described in the book that I find interesting and use a lot in my day to day programming life.

Languages

These refactoring techniques aren’t specific to the Ruby language (although my implementation examples are). You can use them when working with JavaScript or PHP (or any other language for that matter).

Programming languages don’t all offer identical APIs and so sometimes you might need to tweak the examples slightly to fit your environment.

Regardless, the idioms and syntax differences between languages become redundant when you just focus on the pattern(s) behind the proposed solution.


But before we get into it... time for some self-promotion 🙊

Why refactor?

The purpose of refactoring is to improve the quality, clarity and maintainability of your code. Simple really.

But also, refactoring can be a great lesson in understanding an unfamiliar code base.

Think about it, if you inherit a poorly designed code base that you’ve not seen before and you now need to either fix a bug or add a new feature, then implementing the code necessary would be a lot easier once you had refactored it to be in a more stable, maintainable and ultimately ‘understandable’ state.

Otherwise you would be forced to retro fit your new code on top of a poorly designed foundation and that would be the start of a very unhappy relationship.

When should you refactor?

You’ll usually find the time you start refactoring the most is when you are fixing bugs or adding new features.

For example, you typically first need to understand the code that has already been written (regardless of whether it was you who wrote it originally or someone else).

The process of refactoring helps you better understand the code, in preparation for modifying it.

But don’t fall into the trap of thinking that refactoring is something you set aside time for, or only consider at the start/end of a project. It’s not. Refactoring should be done in small chunks throughout the entire life cycle of the project.

As the great Uncle Bob once said:

leave a module in a better state than you found it

…what this suggests is that refactoring is essential to your daily coding process.

Tests

Before we get started, it’s important to mention that you should have tests in place when you’re refactoring.

You can refactor without tests, but realise that without tests to back you up then you can have no confidence in the refactoring you are implementing.

Refactoring can result in substantial changes to the code and architecture but still leave the top layer API the same. So while you’re refactoring remember the old adage…

program to an interface, not an implementation

We want to avoid changing a public API where ever possible (as that’s one of the tenets of refactoring).

If you don’t have tests then I recommend you write some (now)… don’t worry, I’ll wait.

Remember, the process of writing tests (even for an application you don’t know) will help solidify your understanding and expectations of the code you’re about to work on.

Code should be tested regularly while refactoring to ensure you don’t break anything. Keep the ‘red, green, refactor’ feedback loop tight. Tests help confirm if your refactoring has worked or not. Without them you’re effectively flying blind.

So although I won’t explicitly mention it below when discussing the different refactoring techniques, it is implied that on every change to your code you should really be running the relevant tests to ensure no broken code appears.

Refactoring Techniques

There are many documented refactoring techniques and I do not attempt to cover them all, as this post would end up becoming a book in itself. So I’ve picked what I feel are the most common and useful refactoring techniques and I try my best to explain them in a short and concise way.

I’ve put these techniques in order of how you might approach refactoring a piece of code, in a linear, top to bottom order. This is a personal preference and doesn’t necessarily represent the best way to refactor.

Final note: with some of the techniques I have provided a basic code example, but to be honest some techniques are so simple they do not need any example. The Extract Method is one such technique that although really useful and important, providing a code example would be a waste of time and space.

So without further ado, let’s begin…

Rename Method

The single most effective and simple refactoring you can implement is to rename a property/attribute, method or object.

Renaming identifiers can reduce the need for code comments and nearly always helps to promote greater clarity.

You’ll find that renaming things is a fundamental part of other refactoring techniques to aid understanding of the code.

This technique relies on giving items a descriptive name to ensure the developer knows at a glance exactly what it does. The following technique Introduce Explaining Variable is effectively the same.

Introduce Explaining Variable

So here is a technique specifically based around the premise of renaming.

If you have a complicated expression (for example, you’ll typically have a long winded set of conditions within an if statement) then place that complex expression into a temp variable and give it a descriptive identifier.

For example:

unless "This is a String with some CAPS".scan(/([A-Z])/).empty?
  puts "capitalised text was found"
end

Should be:

caps_not_found = "This is a String with some CAPS".scan(/([A-Z])/).empty?

unless caps_not_found
  puts "capitalised text was found"
end

Note: this is the only technique that finds temps (i.e. local variables) acceptable. This is because temps are deemed to be less reusable than methods (due to their very nature being ’local’) and so introducing temps is something that shouldn’t be considered lightly. Maybe consider using the Extract Method technique instead before using this particular technique.

Also, don’t worry about performance until you know you have a performance issue to worry about. Developers will always suggest that calling methods is slower than running code inline, but good programming is about readability and maintainability, and extracted methods are not only easier to understand but are much more reusable by other methods.

So if you are considering using the Introduce Explaining Variable technique, first decide whether the temp would be more useful if it was available to other methods (that way you could use Extract Method instead and avoid defining a temp altogether).

Inline Temp

Temp variables are a bit of a code smell as they make methods longer and can make the Extract Method more awkward (as you’d have to pass through more data to the extracted method).

Inline Temp effectively removes the temp variable altogether by just using the value assigned to it (I’d only suggest doing this if the temp is only used once or if the resulting value has come from a method invocation).

For example:

def add_stuff
    1 + 1
end

def do_something
    temp_variable_with_descriptive_name = add_stuff
    puts "Number is #{temp_variable_with_descriptive_name}"
end

Should be:

def add_stuff
    1 + 1
end

def do_something
    puts "Number is #{add_stuff}"
end

Note: a temp by itself doesn’t do any harm, and in some instances can actually make the code clearer (especially if using a result from a method invocation and the method identifier doesn’t indicate the intent as well as it should).

But most likely you’ll end up using this technique to aid the Extract Method technique as less temp vars means less requirement to pass through additional parameters to the extracted method.

Split Temp Variable

This technique aims to resolve the concern of violating the SRP (Single Responsibility Principle), although slightly tamer in the sense that SRP is aimed more at Classes/Objects and methods, not typically variable assignments.

But regardless if a temporary variable is assigned to more than once and it is not a loop variable or a collecting/accumulator variable then it is a temp considered to have too many responsibilities.

For example: (this is a daft example, but what the heck)

temp = 2 * (height + width)
temp = height * width

Becomes:

perimeter = 2 * (height + width)
area = height * width

As you can see, the temp variable was handling more responsibility than it should be and so by creating two appropriately distinct temps we ensure greater code clarity.

Replace Temp With Query

This technique has a very similar intent to Inline Temp in that one of its primary focuses is to aid the Extract Method.

The subtle but important difference between this technique and Inline Temp is that the complex expression assigned to the temp needs to be first moved to a method (whereas the Inline Temp technique is different in that the temp may already be using a method invocation).

For example:

class Box
  attr_reader :length, :width, :height

  def initialize length, width, height
    @length = length
    @width  = width
    @height = height
  end

  def volume
    # `area` is the temp
    area = length * width
    area * height
  end
end

Becomes:

class Box
  attr_reader :length, :width, :height

  def initialize length, width, height
    @length = length
    @width  = width
    @height = height
  end

  def volume
    # notice `area` is now a direct method call
    area * height
  end

  def area
    length * width
  end
end

This technique can help to shorten a long method by not having to define lots of temp variables just to hold values.

If the extracted query method is given an identifier that aptly describes its purpose then the code still can be considered clear and descriptive.

Also, it is considered bad form to define a variable which changes once it has been set (hence moving to a method better indicates an unstable value).

Note: this technique can sometimes be made easier to implement once you’ve used Split Temp Variable.

Remember this technique (as with other techniques) is an incremental step towards removing non-essential temps, so consider using Inline Temp afterwards, thus removing the need for the temp altogether.

Replace Temp With Chain

This is yet another technique designed to rid your code of temp variables.

If you have a temp variable holding the result of calling an object’s method, and follow the assignment by using that temp to carry out more method calls, then you should consider chaining method calls instead.

The implementation is quite simple, you just have to ensure the methods called return self (or this if using a language like JavaScript).

By allowing methods to chain we again have the opportunity to remove an unnecessary temps.

For example:

class College
    def create_course
        puts "create course"
    end

    def add_student
        puts "add student"
    end
end

temp = College.new
temp.create_course
temp.add_student
temp.add_student
temp.add_student

Becomes:

class College
    # static method so can be accessed without creating an instance
    def self.create_course
        college = College.new
        puts "create course"
        college # return new object instance
    end

    def add_student
        puts "add student"
        self # refers to the new object instance
    end
end

college = College.create_course
                 .add_student
                 .add_student
                 .add_student

Extract Method

Here it is! In my opinion ‘The’ most used and important refactoring technique.

The implementation behind this technique is very simple. It consists of breaking up long methods by shifting overly complex chunks of code into new methods which have very descriptive identifiers.

For example:

class Foo
  attr_reader :bar

  def initialize bar
    @bar = bar
  end

  def do_something
    puts "my baz" # notice this is duplication
    puts bar
  end

  def do_something_else
    puts "my baz" # notice this is duplication
    puts "Something else"
    puts bar
  end
end

Becomes:

class Foo
  attr_reader :bar

  def initialize bar
    @bar = bar
  end

  def do_something
    baz
    puts bar
  end

  def do_something_else
    baz
    puts "Something else"
    puts bar
  end

  def baz
    puts "my baz"
  end
end

But be careful with handling local variables as you’ll need to pass them through to the extracted method and that can be difficult if there are lots of temps in use. Sometimes to facility the Extract Method you’ll need to first incorporate other techniques such as Replace Temp With Query and Inline Temp.

Inline Method

Sometimes you want the opposite of the Extract Method technique. Imagine a method exists whose content is already simple and clear, and whose identifier adds no extra benefit. In this instance we’re just making an extra call for no real benefit.

So to fix this problem we’ll convert the method invocation into an inlined piece of code (unless of course the method is used in multiple places, in that case leave it where it is as having it in a separate method keeps our code DRY).

Move Method

In a previous post about Object-Oriented Design I explained that you should query your classes/objects to ensure the methods they define are actually where they should be (another reason is ‘feature envy’, if a method is asking another class a lot of questions then it may be an indication the method is on the wrong object).

The Move Method technique ensures this decoupling by simply moving the identified misplaced method onto the correct one.

Once the method has been moved you should clean up the previously passed parameters by seeing what can be moved over to the other object or whether additional data needs to be passed over now via the method invocation.

For example:

class Gear
    attr_reader :chainring, :cog, :rim, :tire

    def initialize (chainring, cog, rim, tire)
      @chainring = chainring
      @cog       = cog
      @rim       = rim
      @tire      = tire

      # let's asked the question:
      # "Please Mr. Gear what is your tire size?"
      # hmm? notice this doesn't sound like it quite fits the purpose of a 'Gears' class
    end

    def ratio
      chainring / cog.to_f
    end

    def gear_inches
        # tire goes around rim twice for diameter
        ratio * (rim + (tire * 2))
    end
end

Becomes:

class Gear
    attr_reader :chainring, :cog, :rim, :tire

    def initialize (chainring, cog, rim, tire)
      @chainring = chainring
      @cog       = cog
      @rim       = rim
      @tire      = tire.size
    end

    def ratio
      chainring / cog.to_f
    end

    def gear_inches
        # tire goes around rim twice for diameter
        ratio * (rim + (tire * 2))
    end
end

class Tire
  def self.size
    5
  end
end

From the original class/object keep the original method in place while you test and change it so it now delegates to the method on the new object. Then slowly refactor by replacing delegating calls throughout your code base with direct calls to the method via its new host.

Finally, remove the old method altogether and the tests should tell you if you missed a replacement somewhere.

Replace Method With Method Object

You may run into a problem where you have a long method you want to use Extract Method on, but the number of temporary local variables are too great to allow you to utilise the Extract Method technique (because passing around that many variables would be just as messy as the long method itself).

To resolve this issue you could look at different types of smaller refactors (such as Inline Temp) but in some cases it would actually be better to first move the contents of the long method into an entirely new object.

So the first thing to do is create a new class named after the long method and add the temp local vars as properties/attributes of the class/object.

Now when you try to implement Extract Method you don’t have to pass around the temp vars because they are now available throughout the class/object.

Then from within the original class/object you can delegate any calls to the original method on to the object (you’ll still pass on the original arguments to the method within the new object but from there on the method extraction becomes easier).

For example:

class Foo
  def bar
    puts "We're doing some bar stuff"
  end

  def baz(a, b, c)
    if a == 'something'
      # do something
    end

    if b == 'else'
      # do else
    end

    if c == 'none'
      # do none
    end
  end
end

Becomes:

class Foo
  def bar
    puts "We're doing some bar stuff"
  end
end

class Baz
  attr_accessor :a, :b, :c

  def initialize(a, b, c)
    @a = a
    @b = b
    @c = c

    if a == 'something'
      # do something
    end

    if b == 'else'
      # do else
    end

    if c == 'none'
      # do none
    end
  end
end

From here we’re now in a better state to use both the Extract Method and Replace Conditional with Polymorphism techniques to refactor the Baz class.

Replace Loop With Collection Closure Method

If you write a loop that parses a collection and interacts with the individual elements within the collection then move that interaction out into a separate closure based method (meaning you replace the loop with an Enumerable method).

This refactoring may not be as clear or impressive as other refactoring techniques but the motivation behind it is that you hide the ugly details of the loop behind a nicer iteration method, allowing the developer looking at the code to focus on the business logic instead.

For example:

managers = []
employees.each do |e|
    managers << e if e.manager?
end

Becomes:

managers = employees.select { |e| e.manager? }

Ruby has a few of these types of enumerable methods but other languages such as PHP and JavaScript aren’t so lucky.

JavaScript has a couple of accumulators: Array#reduce and Array#reduceRight but they aren’t very useful as closure based collection methods compared to Ruby which has methods such as Enumerable#inject, Enumerable#select (seen in above example) or Enumerable#collect.

Note: in JavaScript you can implement a similar effect with clever use of closures.

Pull Up Method

When you have duplicated code across two separate classes then the best refactoring technique to implement is to pull that duplicate code up into a super class so we DRY (Don’t Repeat Yourself) out the code and allow it to be used in multiple places without duplication (meaning changes in future only have to happen in one place).

For example:

class Person
  attr_reader :first_name, :last_name

  def initialize first_name, last_name
    @first_name = first_name
    @last_name = last_name
  end

end

class MalePerson < Person
  # This is duplicated in the `FemalePerson` class
  def full_name
    first_name + " " + last_name
  end

  def gender
    "M"
  end
end

class FemalePerson < Person
  # This is duplicated in the `MalePerson` class
  def full_name
    first_name + " " + last_name
  end

  def gender
    "F"
  end
end

Becomes:

class Person
  attr_reader :first_name, :last_name

  def initialize first_name, last_name
    @first_name = first_name
    @last_name = last_name
  end

  def full_name
    first_name + " " + last_name
  end
end

class MalePerson < Person
  def gender
    "M"
  end
end

class FemalePerson < Person
  def gender
    "F"
  end
end

Form Template Method

The technique is reliant on inheritance: a parent class and two sub classes of that parent. The two sub classes have methods which have similar steps, in the same order and yet the steps themselves are different.

The technique involves moving the sequence of steps into the parent class and then using polymorphism to allow the sub classes to handle the differences in the steps.

Here is a silly example (I’m no good at giving real examples; you may have noticed), here is an example of our problematic code…

class Foo; end

class Bar < Foo
  def initialize
    @hey = 1
    @hai = 2
  end

  def qux
    @a = @hey + @hai
    @b = @a * 10
    @a + @b
  end
end

class Baz < Foo
  def initialize
    @hey = 5
    @hai = 7
  end

  def qux
    @a = @hey + @hai
    @b = @a * 10 * 20
    @a + @b
  end
end

bar = Bar.new
baz = Baz.new

puts bar.qux
puts baz.qux

…we could try to inject the values each sub class requires but then we still have a lot of duplication in this code.

We can see the sequence of steps is:

determine what a should be
determine what b should be
return a specific calculation

…so we can clean up our code a little by abstracting the commonality…

class Foo
  def initialize(hey=1, hai=1)
    @hey = hey
    @hai = hai
  end

  def qux
    determine_a
    determine_b
    result
  end

  def determine_a
    @a = @hey + @hai
  end

  def result
    @a + @b
  end
end

class Bar < Foo
  protected

  def determine_b
    @b = @a * 10
  end
end

class Baz < Foo
  protected

  def determine_b
    @b = @a * 10 * 20
  end
end

bar = Bar.new(1, 2)
baz = Baz.new(5, 7)

puts bar.qux
puts baz.qux

Extract Surrounding Method

If you find you have different methods which contain almost identical code but with a slight variant in the middle, then pull up the duplicated code into a single method and pass a code block to the newly created method which it yields to in order to execute the unique behaviour…

def do_something
    puts 1
    yield
    puts 3
end

do_something { puts 2 }

This is actually a common pattern in Ruby known as the ‘wrap around’ method. This technique is similar to the Form Template Method, but is different in that you can use it without forcing an inheritance model on your code.

Note: JavaScript doesn’t have the ability to pass a code block but it can be replicated by passing a function that acts like a callback…

function doSomething (callback) {
        console.log(1);
        callback();
        console.log(3);
}

doSomething(function(){
        console.log(2);
});

…although in the latest versions of Node (as of November 2013) Generators are implemented and would allow JavaScript code to yield similar to how Ruby works.

Self Encapsulate Field

When inheriting properties from a parent class/object then it can be more flexible if the parent class only allows access to the properties from within a getter/setter.

The motivation for this technique is that a sub class can override and modify the behaviour of the getter/setter without affecting the parent class’ implementation. Which is similar to how the Decorator design pattern works (e.g. modifying the behaviour without affecting the original).

This technique should only be used once you find the coupling between objects is becoming a problem. Otherwise direct access to properties and instance variables should be acceptable initially.

For example:

def total
  @base_price * (1 + @tax_rate)
end

Becomes:

attr_reader :base_price, :tax_rate

def total
  base_price * (1 + tax_rate)
end

Introduce Named Parameter

When method arguments are unclear then convert them into named parameters so they become clearer (and easier to remember).

Although Ruby supports named parameters…

def turnOnTheTV (channel: 1, volume: 1); end
turnOnTheTV(channel: 101, volume: 10)

…neither PHP or JavaScript do, so for PHP you can pass an associated Array and with JavaScript you can pass an Object/Hash.

For example (JavaScript):

function turnOnTheTV(c, v){}
turnOnTheTV(101, 10);

Becomes:

function turnOnTheTV (config) {
    // config.channel === 101
    // config.volume  === 10
}
turnOnTheTV({ channel: 101, volume: 10 });

Note: ECMAScript 6.0 (the latest JavaScript specification - which is still being worked on as of Nov 2013) implements named parameters.

Remove Redundancy

This isn’t an explicit technique, more a grouping of techniques.

The principle idea being that: code evolves, and as it evolves you may find techniques you previously implemented (as part of an earlier refactoring) have since become redundant.

Imagine you implemented the “Introduce Named Parameter” technique (passing a hash with named properties as a single argument instead of multiple unidentified arguments).

Now, after some other refactorings have taken place, you discover the method originally refactored is no longer as complex and so your argument hash refactor has been reduced down to just a single named property.

In this particular scenario you should remove the named parameter and simply pass a single argument instead.

This principle applies with other refactoring techniques.

Imagine an earlier refactoring included implementing a default parameter value for a method call. As your code evolves, if you discover you now only ever call the method with an argument then the default value becomes redundant and makes the code more complex than it needs to be by providing a default value. So just remove the redundant code.

Dynamic Method Definition

Sometimes defining multiple methods can be wasteful when functionally they carry out similar steps.

For example, imagine we had the following code…

def failure do 
  self.result = "failure" 
end 

def success do 
  self.result = "success" 
end 

def error do 
  self.result = "error" 
end 

Notice how the functions are structurally identical. They simply set a result property to have a value This can be refactored using Ruby’s define_method method (which let’s you create methods dynamically at run time)…

[:failure, :success, :error].each do |method| 
  define_method method do 
    self.result = method.to_s 
  end 
end 

Note: you could also abstract this code into a more reusable (and easier to maintain) function like so…

def dynamic_methods(*method_names, &block) 
  method_names.each do |method_name| 
    define_method method_name do 
      instance_exec(method_name, &block)
    end 
  end 
end 

You can also use this technique to help ease creating properties on an object. For example, I used this technique in my MVCP blog post to dynamically create instance variables…

require 'app/presenters/base' 
require 'app/models/person' 

class Presenters::Person < Presenters::Base 
  attr_reader :run, :name, :age 

  def initialize 
    @run = true 

    model = Person.new('Mark', '99') 
    prepare_view_data({ :name => model.name, :age => model.age }) 
  end 
end 

module Presenters 
  class Base 
    attr_accessor :model 

    def prepare_view_data hash 
      hash.each do |name, value| 
        instance_variable_set("@#{name}", value) 
      end 
    end 
  end 
end 

Extract Class

This is a pretty standard technique which helps ensure your objects abide by the SRP (Single Responsibility Principle).

If you find your classes are doing too much then simply create a new class and move the relevant fields and methods over one by one (while running the tests as you go to ensure all code continues working as expected).

Doing so you’ll end up with two small, focused and clean classes which are easier to manage.

Hide Delegate

This technique focuses on the principle of object encapsulation. Specifically decoupling two or more objects by reducing the context the objects have of each other.

The following code demonstrates the idea…

module Bar
  def display
    puts "Bar Stuff"
  end
end

module Baz
  def display
    puts "Baz Stuff"
  end
end

class Foo
  include Bar

  def do_something
    display
  end
end

foo = Foo.new
foo.do_something

…as you can see, the user only needs to rely on the interface having a do_something method.

The implementation details of do_somthing (in this case the delegation off to another method) are hidden.

If we changed include Bar for include Baz, or maybe we don’t mixin a module at all and just write some code inside of do_something, it doesn’t matter because the public interface is set as far as the user is concerned.

Replace Array with Object

The motivation for this technique is to convert a simple data container which holds multiple data types into an object with clear and descriptive identifiers.

This principle helps to present your complex data into a more sensible format (I demonstrated this in a previous post on object-oriented design). This technique also makes the data interaction more maintainable by providing an easier and understandable interface to the data.

Here is an example where we’re violating the principle of a clean data interaction…

class Foo 
  attr_reader :data 

  def initialize(data) 
    @data = data 
  end 

  def do_something 
    data.each do |item| 
      puts item[0] 
      puts item[1] 
      puts '---' 
    end 
  end 
end 

obj = Foo.new([[10, 25],[3, 9],[41, 7]]) 
obj.do_something 

Notice in the first example how our code has far too much knowledge (context) about the object it’s interacting with. It knows that the Array index zero holds an X coordinate and the Array index one holds a Y coordinate.

If that format was to change (let’s say the X and Y swap places) then that would cause our code to break in unexpected ways.

But now take a look at the following example which works around this issue by converting our complex data structure into a cleaner data format…

class Foo 
  attr_reader :new_data 

  def initialize(data) 
    @new_data = transform(data) 
  end 

  def do_something 
    new_data.each do |item| 
      # now we are able to reference easily understandable 
      # property names (rather than item[0], item[1]) 
      puts item.coord_x 
      puts item.coord_y 
      puts '---' 
    end 
  end 

  Transform = Struct.new(:coord_x, :coord_y) 

  def transform(data) 
    data.collect { |item| Transform.new(item[0], item[1]) } 
  end 
end 

obj = Foo.new([[10, 25],[3, 9],[41, 7]]) 
obj.do_something 

…here we convert the Array into an object and instead can more easily and safely reference the data we’re interested in via recognisable property identifiers. This doesn’t mean if the data source changes that we’ll totally avoid all problems but it’ll be clearer where the problem is arising.

Replace Conditional with Polymorphism

This is one of the most useful refactoring techniques available to you, and there are two ways it can help:

  1. It removes the code smell of conditional logic
  2. It demonstrates perfectly the principle of object-oriented design

The following example shows the typical procedural attempt to handle different scenarios based on the data object type being passed…

class Foo
  def initialize(data)
    @data = data
  end

  def do_something
    if @data.class == Bar
      puts "Bar!"
    elsif @data.class == Baz
      puts "Baz!"
    elsif @data.class == Qux
      puts "Qux!"
    end
  end
end

class Bar; end
class Baz; end
class Qux; end

foo_bar = Foo.new(Bar.new)
foo_bar.do_something

foo_baz = Foo.new(Baz.new)
foo_baz.do_something

foo_qux = Foo.new(Qux.new)
foo_qux.do_something

…as you can see, if we have a new Class type we need to go back and to modify the Foo base class. This violates the OCP (Open/Closed Principle) which states a file should be open for extension but closed for modification.

For us to abide by OCP we can use polymorphism and a trusted interface/duck typing to solve the problem…

class Foo
  def initialize(data)
    @data = data
  end

  def do_something
    @data.identifier
  end
end

class Bar
  def identifier
    puts "#{self.class}!"
  end
end

class Baz
  def identifier
    puts "#{self.class}!"
  end
end

class Qux
  def identifier
    puts "#{self.class}!"
  end
end

foo_bar = Foo.new(Bar.new)
foo_bar.do_something

foo_baz = Foo.new(Baz.new)
foo_baz.do_something

foo_qux = Foo.new(Qux.new)
foo_qux.do_something

Notice we have removed the need for a conditional and just sent the message to the relevant object to be handled. Much cleaner and easier to maintain and scale.

Decompose Conditional

Not all conditional statements can be avoided through the use of polymorphism. In those cases you can simplify the conditional logic (and the subsequent statements) by extracting them into external methods.

Here is a simple example…

if date < SUMMER_START || date > SUMMER_END 
  charge = # some complex calculation if it's winter 
else 
  charge = # some other complex calculation if it's summer 
end 

…which we can refactor like so…

if not_summer(date) 
  charge = winter_charge 
else 
  charge = summer_charge 
end 

…much better.

Introduce Null Object

The motivation behind this technique is to avoid using a conditional whose purpose is to check whether a property exists or not before using it.

Here is a simple example of what we want to avoid…

class Post
  attr_reader :id

  def initialize id
    @id        = id
    @published = false
  end

  def self.find_and_publish id
    # Simulated database operation
    post = Posts.find { |post| post.id == id }
    post.publish unless post.nil?
  end

  def publish
    puts @published = true
  end
end

Posts = [Post.new(1), Post.new(2)]

Post.find_and_publish(0) # displays nothing
Post.find_and_publish(1) # displays true

…in the above example we check whether post is nil or not. If it isn’t nil then we call the publish method, otherwise we don’t do anything.

This is kind of ugly.

The following code demonstrates how we can avoid that problem by introducing the concept of having an object to handle null scenarios (it’s the same principle of using duck typing/trusted interfaces/polymorphism)…

class Post
  attr_reader :id

  def initialize id
    @id        = id
    @published = false
  end

  def self.find_and_publish id
    # Simulated database operation
    post = Posts.find { |post| post.id == id } || NullPost.new
    post.publish
  end

  def publish
    puts @published = true
  end
end

class NullPost
  def publish
    # noop
  end
end

Posts = [Post.new(1), Post.new(2)]

Post.find_and_publish(0) # displays nothing
Post.find_and_publish(1) # displays true

…as you can see, effectively we have the same code with the exception that we no longer check for nil? in the second example and instead we rely on another object NullPost implementing the same interface but returns a null related value.

This way we’re using objects to handle our logic. Yes, we end up with more code (one extra Class) but ultimately this is more maintainable and understandable than lots of inline logic.

Conclusion

There are still many different refactoring techniques that I’ve not included. But hopefully you’ve found this quick reference useful so far.


But before we wrap up... time (once again) for some self-promotion 🙊