what is wrong with class variables? (newby)

Discussion in 'Ruby' started by weathercoach@gmail.com, Nov 16, 2007.

  1. Guest

    Hello. I'm new to programming and new to ruby. I've recently
    written a script and have asked people (including this group) about
    components of the script. When people see that I'm using class
    variables they ask me why and make a frowny face;).

    So as I'm trying to get a better understanding of ruby I ask what's
    wrong with class variables? Or could it be how I've used them and not
    a problem with class variables? I use class variables as a list where
    I can add items for future reference. For example let's say I have a
    class variable (@@over_quota) that holds the list of users who are
    over quoata. Then I iterate through the passwd file and check each
    users home directory and if they are over quota I toss them onto the
    class variable (@@over_quoata). Once I've iterated through the
    passwd file I see if anything is in my class variable
    (@@over_quota)and then iterate over the class variable sending email
    to each user who's over quoata.

    I've recently (hour ago) learned about class instance variables and
    I'm wondering if they are less frowned upon than class variables.
    In the following example would it be better to use an class instance
    variable over a class variable. From my perpective the end result
    is the same.
    #!/usr/bin/env ruby -w

    class Simple
    @@var = []
    def Simple.append(l)
    @@var << l
    end
    def Simple.return_var
    @@var
    end
    end

    one = Simple.append("fred")
    puts Simple.return_var
    two = Simple.append("tony")
    puts Simple.return_var

    ../class_variable.rb
    fred
    fred
    tony

    #!/usr/bin/env ruby -w
    class Simple
    @var = []
    def Simple.append(l)
    @var << l
    end
    def Simple.return_var
    @var
    end
    end

    one = Simple.append("fred")
    puts Simple.return_var
    two = Simple.append("tony")
    puts Simple.return_var

    fred
    fred
    tony

    Thanks in advance for your time!
    Hopefully one day I'll be able to answer someone elses question!
    G.
    , Nov 16, 2007
    #1
    1. Advertising

  2. Brian Marick Guest

    On Nov 16, 2007, at 2:55 PM, wrote:
    > So as I'm trying to get a better understanding of ruby I ask what's
    > wrong with class variables?


    There are probably profound philosophical reasons that they're wrong,
    but I think the most convincing reason is experience. They were
    invented a long time ago (late 70's, I believe), people used them,
    and they turned out to cause problems. They made it harder to write a
    program, leave it, come back to it, extend it, and have that work.
    They made confusing bugs more likely. And (often) it's just as easy
    to do without them.

    One lesson I've learned the hard way is that it's almost always
    better to use an instance than a class. For example, you have this:

    > one = Simple.append("fred")
    > puts Simple.return_var
    > two = Simple.append("tony")
    > puts Simple.return_var


    I'd be tempted to do that if I knew -- absolutely knew -- that there
    was never going to be more than one Simple. But I've learned to
    prefer something like this:

    simple = Simple.new
    one = simple.append("fred")
    puts simple.return_var
    two = simple.append("tony")
    puts simple.return_var

    Why? Because almost *every* *time* I use the class instead of an
    instance, I end up regretting it.

    Notice that if you use the instance, you'll change your
    implementation of Simple to this:

    class Simple
    def initialize
    @var = []
    end

    def append(i)
    @var << i
    end

    def return_var
    @var
    end
    end

    Class variable is gone. And you can start taking advantage of other
    Ruby features. For example, you can use attributes to avoid writing
    some code:

    class Simple
    attr_reader :var # replaces the def of return_var

    def initialize
    @var = []
    end

    def append(i)
    @var << i
    end

    end


    In what I guess you'd call the modern style of coding, people write
    tests before writing the code. What that does is make long-term
    unpleasantness into immediate unpleasantness. For example, class
    variables make classes hard to test, so testing encourages you not to
    use them.

    Now for the blatant plug: I describe this style of coding in
    _Everyday Scripting with Ruby_ <http://www.pragprog.com/titles/bmsft>.

    -----
    Brian Marick, independent consultant
    Mostly on agile methods with a testing slant
    www.exampler.com, www.exampler.com/blog, twitter.com/marick
    Brian Marick, Nov 16, 2007
    #2
    1. Advertising

  3. Guest

    >
    > and they turned out to cause problems. They made it harder to write a
    > program, leave it, come back to it, extend it, and have that work.
    > They made confusing bugs more likely. And (often) it's just as easy


    Brian.
    Now I understand the frowny faces. Your explanation is great in
    that I don't have to be a skilled programmer to comprehend your
    point. Thank you very much for breaking it down like this.
    I'll see if my boss will get me the book;)
    Thanks again. G.



    > to do without them.
    >
    > One lesson I've learned the hard way is that it's almost always
    > better to use an instance than a class. For example, you have this:
    >
    > > one = Simple.append("fred")
    > > puts Simple.return_var
    > > two = Simple.append("tony")
    > > puts Simple.return_var

    >
    > I'd be tempted to do that if I knew -- absolutely knew -- that there
    > was never going to be more than one Simple. But I've learned to
    > prefer something like this:
    >
    > simple = Simple.new
    > one = simple.append("fred")
    > puts simple.return_var
    > two = simple.append("tony")
    > puts simple.return_var
    >
    > Why? Because almost *every* *time* I use the class instead of an
    > instance, I end up regretting it.
    >
    > Notice that if you use the instance, you'll change your
    > implementation of Simple to this:
    >
    > class Simple
    > def initialize
    > @var = []
    > end
    >
    > def append(i)
    > @var << i
    > end
    >
    > def return_var
    > @var
    > end
    > end
    >
    > Class variable is gone. And you can start taking advantage of other
    > Ruby features. For example, you can use attributes to avoid writing
    > some code:
    >
    > class Simple
    > attr_reader :var # replaces the def of return_var
    >
    > def initialize
    > @var = []
    > end
    >
    > def append(i)
    > @var << i
    > end
    >
    > end
    >
    > In what I guess you'd call the modern style of coding, people write
    > tests before writing the code. What that does is make long-term
    > unpleasantness into immediate unpleasantness. For example, class
    > variables make classes hard to test, so testing encourages you not to
    > use them.
    >
    > Now for the blatant plug: I describe this style of coding in
    > _Everyday Scripting with Ruby_ <http://www.pragprog.com/titles/bmsft>.
    >
    > -----
    > Brian Marick, independent consultant
    > Mostly on agile methods with a testing slantwww.exampler.com,www.exampler.com/blog, twitter.com/marick
    , Nov 16, 2007
    #3
  4. wrote:
    > When people see that I'm using class
    > variables they ask me why and make a frowny face;).


    Brian Marick wrote:
    > There are probably profound philosophical reasons that they're wrong,
    > but I think the most convincing reason is experience. They were
    > invented a long time ago (late 70's, I believe), people used them,
    > and they turned out to cause problems..


    The trouble was (is?) that programmers used them to store 'State' that
    was read and written by several components; the result was that the
    complexity of the system (the number of possible 'states') grew
    exponentially with each of those variables (of course, they are so easy
    to use that they cut down the schedule at the beginning; these problems
    are never only 'technical'..).

    Furthermore, in Ruby a 'class variable' is visible across the whole
    hierarchy of subclasses (a modification done anywhere impacts all);
    therefore, the potential for trouble is high.

    Having said that, now for the part that may be controversial: I think
    that class varibles can be VERY USEFUL, if used correctly; for example,
    when there is a quasi-static condition to be transmitted to a hierarchy
    of classes. Rails uses them profusely, for example in
    action_controller/base.rb,

    ------
    # All requests are considered local by default, so everyone will
    # be exposed to detailed debugging screens on errors. When the
    # application is ready to go public, this should be set to false

    @@consider_all_requests_local = true
    cattr_accessor :consider_all_requests_local
    -------

    There are many variables like that, which propagate quasi-static
    conditions to the whole hierarchy. Notice also how they are complemented
    with a 'class attribute accessor', so that they are accessed via methods
    (which allows one day to change the implementation, if necessary).

    Personally, I think that this is simply splendid: maximizing the benefit
    (cheap distribution of quasi-static info across a hierarchy), minimizing
    the evils.

    Rails does even something more interesting: sometimes we want the
    benefits of a class variable - eg, to inherit its content from the
    superclass - but we want to be able to change it privately in a class;
    this is done via the 'class_inheritable_accessor' (which plays a
    fundamental role to chain modules to the View).

    In conclusion, I think that very few things in programming are totally
    'evil' (or totally 'good'); it all depends from the context, the
    purpose, and the intelligence of the programmer using them.
    --
    Posted via http://www.ruby-forum.com/.
    Raul Parolari, Nov 16, 2007
    #4
  5. On Nov 16, 2007 6:19 PM, Raul Parolari <> wrote:
    >
    > wrote:
    > > When people see that I'm using class
    > > variables they ask me why and make a frowny face;).

    >
    > Brian Marick wrote:
    > > There are probably profound philosophical reasons that they're wrong,
    > > but I think the most convincing reason is experience. They were
    > > invented a long time ago (late 70's, I believe), people used them,
    > > and they turned out to cause problems..

    >
    > The trouble was (is?) that programmers used them to store 'State' that
    > was read and written by several components; the result was that the
    > complexity of the system (the number of possible 'states') grew
    > exponentially with each of those variables (of course, they are so easy
    > to use that they cut down the schedule at the beginning; these problems
    > are never only 'technical'..).
    >
    > Furthermore, in Ruby a 'class variable' is visible across the whole
    > hierarchy of subclasses (a modification done anywhere impacts all);
    > therefore, the potential for trouble is high.
    >
    > Having said that, now for the part that may be controversial: I think
    > that class varibles can be VERY USEFUL, if used correctly; for example,
    > when there is a quasi-static condition to be transmitted to a hierarchy
    > of classes. Rails uses them profusely, for example in
    > action_controller/base.rb,
    >
    > ------
    > # All requests are considered local by default, so everyone will
    > # be exposed to detailed debugging screens on errors. When the
    > # application is ready to go public, this should be set to false
    >
    > @@consider_all_requests_local = true
    > cattr_accessor :consider_all_requests_local
    > -------
    >
    > There are many variables like that, which propagate quasi-static
    > conditions to the whole hierarchy. Notice also how they are complemented
    > with a 'class attribute accessor', so that they are accessed via methods
    > (which allows one day to change the implementation, if necessary).
    >
    > Personally, I think that this is simply splendid: maximizing the benefit
    > (cheap distribution of quasi-static info across a hierarchy), minimizing
    > the evils.
    >
    > Rails does even something more interesting: sometimes we want the
    > benefits of a class variable - eg, to inherit its content from the
    > superclass - but we want to be able to change it privately in a class;
    > this is done via the 'class_inheritable_accessor' (which plays a
    > fundamental role to chain modules to the View).
    >
    > In conclusion, I think that very few things in programming are totally
    > 'evil' (or totally 'good'); it all depends from the context, the
    > purpose, and the intelligence of the programmer using them.


    Great observations!

    I've struggled with Ruby class variables myself. Of course I looked
    at them in the light of my Smalltalk experience.

    Smalltalk also has class variables which have the same kind of
    visibility as in Ruby, class variables are visible to a sub-hierarchy
    of Classes and their instances.

    In Smalltalk they are (or at least used to be) used sparingly, and
    almost always for static data. In effect they were used for the kind
    of things you'd define as constants in a .h file.

    The big difference that I can see between class variables in Ruby and
    Smalltalk springs from the fact that while Smalltalk variable names
    are declared, in Ruby they are introduced dynamically at first mention
    during execution.

    In Smalltalk the development environment would prevent redeclaration
    of a class variable name, while in Ruby this can be done and causes
    problems when a superclass creates a class variable which already
    exists below, breaking the identity of the variable's scope.

    And, yes, I think that overuse of class variables for changeable state
    is problematic either in Smalltalk or Ruby, but hadn't thought about
    that much until Raul so eloquently described it.

    --
    Rick DeNatale

    My blog on Ruby
    http://talklikeaduck.denhaven2.com/
    Rick DeNatale, Nov 17, 2007
    #5
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Fred Nelson

    Base Windows Form Class (newby)

    Fred Nelson, Feb 10, 2004, in forum: ASP .Net
    Replies:
    2
    Views:
    682
    Fred Nelson
    Feb 10, 2004
  2. Sonoman
    Replies:
    2
    Views:
    466
    Victor Bazarov
    Jun 30, 2003
  3. Lionel Thiry
    Replies:
    19
    Views:
    362
    Randy Kramer
    Mar 15, 2005
  4. chris
    Replies:
    5
    Views:
    90
    Randy Webb
    Oct 16, 2005
  5. Replies:
    22
    Views:
    195
Loading...

Share This Page