5

a rubygem I'm writing and that is useful for counting word occurrences in a text, I choose to put 3 parameters in class constructor.

The code is working, but I want to refactor it for niceness. In your experience, it's easier to read/mantain/use as API a class with a constructor with no params and a lot of setters/getters method or a code like this one, with all the params in the constructor?

TIA

Paolo

def initialize(filename, words, hide_list)

  if ! filename.nil?
    @filename = filename
    @occurrences = read
  else
    @filename = STDIN
    @occurrences = feed
  end

  @hide_list = hide_list
  @sorted = Array(occurrences).sort { |one, two| -(one[1] <=> two[1]) }
  @words = words

end
JasonMArcher
  • 14,195
  • 22
  • 56
  • 52
Paolo Perego
  • 393
  • 3
  • 9
  • 1
    One benefit of having parameters in the constructor in other languages at least, is that you can make the type immutable. You can't do that if you set everything separately. I don't know whether that applies to Ruby or not, which is why this is a comment rather than an answer. – Jon Skeet Jul 09 '10 at 15:28
  • @Jon: http://stackoverflow.com/questions/408208/ruby-immutable-objects discusses whether you can do immutable objects in ruby (which may be different from immutable type) – Andrew Grimm Jul 11 '10 at 23:26

3 Answers3

3

In my experience I can tell that the very reason for allowing constructor parameters in most languages, apart from the fact of increasing the easiness in class instantiation, is to make it easy to use the API.

Favoring constructor, over getter/setter instantiation, also helps immutability, that is, creating an object thorough its constructor, and not letting anyone modify its properties later on.

Jose Diaz
  • 5,353
  • 1
  • 31
  • 29
  • _apart from the fact of increasing the easiness in class instantiation, is to make it easy to use the API_. Can you explain what means "to make it easy to use API"? – zuba Aug 08 '16 at 16:26
3

You could do it the rails way, where options are given in a hash:

def initialize(filename = nil, options = {})
  @hide_list = options[:hide_list]
  @words = options[:words]

  if filename
    @filename = filename
    @occurrences = read
  else
    @filename = STDIN
    @occurrences = feed
  end

  @sorted = Array(occurrences).sort { |one, two| -(one[1] <=> two[1]) }

end

Then you can call it like this:

WC.new "file.txt", :hide_list => %w(a the to), :words => %w(some words here)

or this:

wc = WC.new
wc.hide_list = %w(a the is)
wc.words = %w(some words here)
mckeed
  • 9,719
  • 2
  • 37
  • 41
0

I dont know how it is in Ruby, but in other languages you usually put those arguments in the constructor signature that are needed to initialize the object into a valid state. All other state can be set through setters.

Gordon
  • 312,688
  • 75
  • 539
  • 559
  • In this case, parameters are options to customize class behavior when firing its task. There aren't required to object initialization. – Paolo Perego Jul 09 '10 at 15:39
  • @thesp0nge if Ruby supports optional arguments, then you could make those optional arguments to reflect their optionality. Or add setters for the options. You should also consider what the others said about mutability. – Gordon Jul 09 '10 at 15:44