tags:

views:

160

answers:

4

I notice in Ruby it is very common to for vendor APIs to pass back results as arrays? Shouldn't Plain Old Objects (Like POJOs in Java) be more of a standard? If I write my own library shouldn't I use POJOs POROs?

+3  A: 

I think array vs object is a false dichotomy.

It is perfectly reasonable, where an API call is returning more than one of a thing, that it is in the form of an array (and an array is a fairly simple object, and therefore arguably a 'PORO', in Ruby anyway)

Edit: in response to your comments:

The example you cite ( http://github.com/cjheath/geoip ) returns an array of differing items. I agree this is not necessarily the best format to return the data in. In that case I would have thought a hash with sensibly named keys would be a better structure.

As John Topley says, the OO nature of Ruby means people don't have to invent such terminology as 'PORO', as a hash is pretty much as simple as you can get.

DanSingerman
No, because you need to refer to the API documentation to determine which value is being passed back at what location. If it were in a custom object, you wouldn't have to refer back to the rdoc.
Zombies
Are you actually referring to an array where you have different class instances at pre-defined points of the array? Can you link to an example of the sort of thing you are referring to?
DanSingerman
http://github.com/cjheath/geoip ....It seems to be that those functions would benefit from returning custom objects instead of a **variable** amount of strings in an array
Zombies
Ok, I get you now. In that case I think a hash, with sensibly named keys would be an improvement.
DanSingerman
Good point, thanks.
Zombies
+1  A: 

What do those arrays of results contain? The answer is that in Ruby they contain objects, because everything in Ruby is an object.

POJOs in the Java world were a reaction against some of the complexities inflicted upon the world by enterprise Java e.g. EJBs. To quote Martin Fowler who coined the term:

"We wondered why people were so against using regular objects in their systems and concluded that it was because simple objects lacked a fancy name. So we gave them one, and it's caught on very nicely."

Fortunately in Ruby it has always been natural for people to just practise object-oriented programming without the need to invent terminologies around it.

John Topley
I suppose what I am really asking is if there is a better way to get named attributes returned and why it isn't used more, so perhaps I should just re-ask this question!
Zombies
One reason might be that Gems such as HTTParty make it very easy to wrap Web services in Ruby and get a lightweight object wrapper around the returned JSON or XML for free.
John Topley
+1  A: 

I personally use POROs in almost anything I write that isn't a complete throwaway script.

I find myself often creating a data holder type of class that would manage and hold multiple objects of my specific type and include some helper methods. I find this convenient for when someone else has to work with my code as well.

I think this question is very subjective in the sense that there isn't an answer that is always right. Sometimes just passing back an array is fine and there is no need to create an extra class. Sometimes the extra level of abstraction makes something a lot more clear to the user.

Beanish
This is exactly what I was wondering about. Thanks for adding your input. I don't think it is subjective as I am trying to see what others do and take all of these into consideration for my own edification...
Zombies
+1  A: 

It's all objects, all the time. The key is whether the objects being returned have behavior associated with them. It's fine to do this:

  def read_first_and_last_name(data_source)
    [data_source.read_string, data_source.read_string]
  end

But the moment you find there is behavior associated with those data items...

  def print_name(first_name, last_name)
    puts "#{first_name} #{last_name}"
  end

  def read_and_print_name
    first_name, last_name = read_first_and_last_name(data_source)
    print_name(first_name, last_name)
  end

...then they should be a class:

  class FullName

    def FullName.read(data_source)
      FullName.new(data_source.read_string, data_source.read_strng)
    end

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

    def print
      puts "#{@first_name} #{@last_name}"
    end

  end

With a name's behavior nicely encapsulated, usage becomes as simple as:

  def read_and_print_name
    FullName.read(data_source).print
  end
Wayne Conrad