Initialize: keep it simple

The more objects I build, the more I am realising that I need to keep my initialize methods simple. Not doing so, leads to problems later on.

The key is in the name: best practice is to keep the initialize method to just initially loading instance variables.

An example

Suppose I want to build a class to translate Spanish text into English.

The wrong way to do it

class Translator < String
  def initialize(text)
    super(to_english(text))
  end
.......  
  def to_english(text)
    EasyTranslate.translate(text, :to => :en)
  end
end

Translate.new('Este es texto')    ---->  'This is text'

So what is the problem

This solution works. However, it doesn’t scale.

What if I want to use Translator to translate Spanish to German, or English to Spanish? My initialize method assumes that I’ll only be translating to English. As well as adding code to do the new translation code, I’d also have to modify initialize to work with the new code.

This is not too much of a problem with such a simple class, but what if there were many methods and each of them relied on the initialize method’s modification of the text as a starting point. I’d have to modify all those methods too.

Also it is not easy to test any instance method without processing the to_english method. It then becomes difficult to isolate a method test to simply testing the actions of that method.

A better solution

class Translator
  def initialize(text)
    @text = text
  end
..............................
  def to_english
    EasyTranslate.translate(@text, :to => :en)
  end
end

Now if I want to add a method to translate to German, it is just a case of adding the new method.

The downside, is when I use the code, the input is now more verbose:

 Translate.new('Este es texto').to_english    ---->  'This is text'

However I can easily fix that with a class method:

  def self.to_english(text)
    new(text).to_english
  end

Personally, I might not keep the class and instance methods using the same name, but this demonstrates how easy it is to create more succinct usage:

 Translate.to_english('Este es texto')    ---->  'This is text'
This entry was posted in Ruby. Bookmark the permalink.