Sam Kong <sam.s.kong / gmail.com> wrote:
> Hello!
>
> I have a question about using instance member variables in a method.
> This is rather a general OO implementation question than specific Ruby
> one.
>
> As you know, all instance methods can access insatance member
> variables freely.
> Thus, instance member variables are like global variables in a class
> (I mean... in an object).
> So you don't have to pass those data beween methods in a class.
>
> However, I feel more comfortable when I make those data passed as
> arguments.
>
> See the examples (very simple and stupid one):
>
> class Tax1
> def initialize(emp_id)
> @emp_id = emp_id
> end
>
> def tax
> #explicitly pass the argument even if get_salary can access @emp_id
> salary = get_salary(@emp_id)
> return salary * 0.1
> end
>
> def get_salary(emp_id)
> #do some calcuation using emp_id and data from db
> #...
> return salary
> end
>
> private :get_salary
>
> end
>
> class Tax2
> def initialize(emp_id)
> @emp_id = emp_id
> end
>
> def tax
> salary = get_salary #no argument
> return salary * 0.1
> end
>
> def get_salary
> #do some calcuation using @emp_id and data from db
> #...
> return salary
> end
>
> private :get_salary
>
> end
>
>
> For public methods, it's obvious that you shouldn't put arguments as
> the format affects objects' clients.
> But for private methods, I like to make the methods more standalone
> (not depending the member variables).
>
> Is this an acceptable habit?

Well, acceptable by whom?  If you work on this code with other people you 
should ask them.  If you're doing it all on your own and don't plan to 
distribute it you decide. :-)

> Do you feel the same way as I do?

Not exactly.  I usually draw a line between general algorithms and methods 
specific to an instance.  When implementing general algorithms, I choose 
static methods in Java and class methods in Ruby thus making clear they 
don't depend on instance state.

class SillyExample
  attr :foo

  def initialize(foo) @foo = foo end

  def to_s
    # instance method
    SillyExample.transform foo
    # alternative invocation:
    # self.class.transform foo
  end

  def self.transform(s)
    # algorithm
    s.gsub(/^.*$/, '<\\&>')
  end
end

In your example I'd probably try to keep the DB code completely out of the 
class.  There are plenty smart ways in Ruby to fetch data from a DB 
(ActiveRecord etc.) which don't make it necessary to scatter all persistency 
code throughout classes.  If you want it in there then I'd prefer a mixin 
module that does all the db stuff.  This can be reused by several classes.

HTH

Kind regards

    robert