Dependency Injection

Dependency injection is a technique to replace brittle dependencies that frequently change with abstract dependencies that are more flexible and less likely to change. In the following example the Company class knows the name of the Person class, that it requires two arguments to be initialized, that the first_name argument is first and the last_name argument is second, and that instances of the Person class respond to first_name and last_name messages.

class Company
  def initialize(first_name, last_name)
    @first_name = first_name
    @last_name = last_name
  end
 
  def introduce_ceo
    ceo = Person.new(@first_name, @last_name)
    "Our company is led by #{ceo.first_name} #{ceo.last_name}"
  end
end

class Person
  attr_reader :first_name, :last_name
  def initialize(first_name, last_name)
    @first_name = first_name
    @last_name = last_name
  end
end

The Company class only works with instances of the Person class and cannot be used with another object, even if the object responds to first_name and last_name messages.

We can refactor the Company class so it only depends on being initialized with an object that responds to first_name and last_name messages (this object does not necessarily need to be an instance of the Person class).

class Company
  attr_reader :ceo
  def initialize(ceo)
    @ceo = ceo
  end
 
  def introduce_ceo
    "Our company is led by #{ceo.first_name} #{ceo.last_name}"
  end
end

The Company#introduce_ceo method will now work with any object that responds to first_name and last_name messages.

Dude = Struct.new(:first_name, :last_name)
dude = Dude.new("Cool", "Dude")
Company.new(dude).introduce_ceo
# => "Our company is led by Cool Dude"
someone = Object.new
def someone.first_name
  "Crazy"
end
def someone.last_name
  "Bill"
end
Company.new(someone).introduce_ceo
# => "Our company is led by Crazy Bill"

The Company object no longer depends on the Person object at all. A concrete dependency (a reliance on an instance of the Person class) has been replaced with an abstract dependency (a reliance on an object that responds to the first_name and last_name messages). The technique of dependency injection reduces coupling between classes and makes code that is easier to test and maintain.

Advertisements

One thought on “Dependency Injection

  1. Pingback: Good Code Is Better Than Bad Code With Tests | Ruby/Rails Programming

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s