Post hero cover

Dependency Injection

Imagine you have a class which gets XML data, parses it and then stores the parsed data on a database. You could very well write it like this:

class Consumer
  def consume(data)
    parsed_data = XMLParser.parse(data)
    DB.store(parsed_data)
  end
end

There is (at least) one big problem with this approach, and it will manifest itself when you want to support another data format, such as JSON. The Consumer class is tightly coupled with the XMLParser, and therefore it’s hard to add other parsers, so we need to decouple them. We’re going to do that using a technique called Dependency Injection, like so:

class Consumer
  attr_accessor :parser

  def initialize(parser: XMLParser)
    @parser = parser
  end

  def consume(data)
    parsed_data = parser.parse(data)
    DB.store(parsed_data)
  end
end

This way we can inject the parser on initialization, or even after that. Note that we have a default which is the XMLParser, but it is not mandatory to have a default value.

So, after the refactoring, adding a JSONParser is easy.

consumer = Consumer.new(parser: JSONParser)
consumer.consume(data)

This technique can be used in many scenarios, in this example we used it as part of a pattern that’s called strategy pattern.

Note: The same technique could be applied to inject the DB class instead of hard coding it.

Luis Zamith

About Luis Zamith

Has worked on the web for a while now, mainly using Ruby and Ruby on Rails. Enjoys open source and giving back to the community, having taught Rails to hundreds of people.
Like what you've read so far? Let's work together.