proper use of classes

Discussion in 'Ruby' started by Tom Cloyd, Jan 29, 2009.

  1. Tom Cloyd

    Tom Cloyd Guest

    Greetings...

    I'm continuing my learn-to-write-OO-Ruby journey. Had a recent bad
    experience trying to convert a complex method to a class. The method
    gets a lot of use in my program, and each time it needs to know a lot
    about the environment outside itself. I found myself having to write a
    ton of instance variable data into the class instance to get it to do
    its job, before I called it each time, then read a few more back out to
    get the results. It was awful. What had been a one line call was now
    about 14 lines of code. Ack! I gave up and converted it back to a
    method, which simply makes more sense. I could not find any
    "class-magic" in this experience - just a lot of locked doors.

    I now have three questions. I have read a number of people's accounts of
    what classes are and how you build them, etc., etc., and no one seems to
    address these matters at all well (or else I missed it):

    1. HOW do you use a class?

    I was assuming that since I couldn't pass data to an instance, after
    creation, I have no option but to write data into its instance vars as
    needed. Sometimes, it seems there simply is no other option.

    But, is it approved practice to do something like

    junk = MyClass.new( var_1...var_n ).mymethod

    which creates an instance and calls a method which leaves its results in
    some instance vars., then simple read the results with...but how?
    there's no instance object! (Not that I can find, anyway.) That seems to
    leave me only with this possibility:

    myclass = MyClass.newMyClass.new( var_1...var_n )
    myclass.mymethod
    varA = myclass.var_whatever
    etc....until I have all my results back out of the instance.

    Compared to a simple method call, this seems designed to make me crazy
    quickly. Is there a better way?

    Then, to call the instance again, I have to write new data into its
    instance vars. This simply looks like nonsense, unless one really needs
    to have the encapsulation that an instance offers. Am I missing
    something? Is this just the facts of life when using classes?

    2. Is it accepted practice to simply create a new instance every time
    the class is needed, thus setting the instance's state once, using it
    with one or more method calls, then moving on to the next new instance?
    It occurs to me that maybe Ruby's garbage collection would sweep the old
    instance right up, knowing it won't be used again, but I don't know.

    My nightmare case is a class which operates on an input record, but
    differently each time, depending upon a number of factors in the
    environment outside the class. I just can't see a graceful way to do
    this. I'm struggling to see why I do OO programming at all in this case.

    3. Finally, I'm still struggling with the "when do I make something a
    class?" question. I'm surprised that this question is so unimportant or
    its answer so obvious that no one much addresses it. Dave Thomas, in his
    3rd ed. (I just upgraded, and its really nice!) finally gives two
    sentences to the matter, which is way more than I can find anywhere
    else: "Whenever you’re designing OO systems, a good first step is to
    identify the things you’re dealing with. Typically each type of thing
    becomes a class in your final program, and the things themselves are
    instances of these classes."(p. 59)

    I've been thinking only in terms of functions, things my program does,
    and not things it works on or with. Both are relevant, clearly, and I'm
    now out on a hunt for "things" that are more than functions. Maybe that
    will help.

    Anyone have any additional advice about "when to make something a
    class?" The principle reasons I see are to achieve scope closure,
    persistent state, and object duplication (multiple instances). Did I
    miss anything important?

    I come to the list with these questions only after days of struggle,
    with lots of code, some of it a rather nasty experience (errors I've
    never ever seen before!!!). The questions above are the ones I simply
    have not been able to resolve, and any help offered will be gratefully
    received.

    Thanks,

    Tom


    The easier one (probably):

    --

    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    Tom Cloyd, MS MA, LMHC - Private practice Psychotherapist
    Bellingham, Washington, U.S.A: (360) 920-1226
    << >> (email)
    << TomCloyd.com >> (website)
    << sleightmind.wordpress.com >> (mental health weblog)
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     
    Tom Cloyd, Jan 29, 2009
    #1
    1. Advertising

  2. Hi --

    On Thu, 29 Jan 2009, Tom Cloyd wrote:

    > 1. HOW do you use a class?
    >
    > I was assuming that since I couldn't pass data to an instance, after
    > creation, I have no option but to write data into its instance vars as
    > needed. Sometimes, it seems there simply is no other option.


    You can pass data to an instance:

    instance.some_method(data)

    > But, is it approved practice to do something like
    >
    > junk = MyClass.new( var_1...var_n ).mymethod
    >
    > which creates an instance and calls a method which leaves its results in some
    > instance vars., then simple read the results with...but how? there's no
    > instance object!


    What you've written here is similar to:

    upstring = String.new("David").upcase

    or something like that, and it's perfectly legit, though you might
    also want to grab the object separately:

    string = String.new("David")
    upstring = string.upcase

    > (Not that I can find, anyway.) That seems to leave me only
    > with this possibility:
    >
    > myclass = MyClass.newMyClass.new( var_1...var_n )


    I don't quite get that line. What's newMyClass? (Or maybe it's
    garbling again between our machines?)

    > myclass.mymethod
    > varA = myclass.var_whatever
    > etc....until I have all my results back out of the instance.
    >
    > Compared to a simple method call, this seems designed to make me crazy
    > quickly. Is there a better way?


    I'm not sure I'm following. I guess the short answer is that there's a
    ton of different patterns you can follow, depending on what you need
    to do.

    > Then, to call the instance again, I have to write new data into its instance
    > vars. This simply looks like nonsense, unless one really needs to have the
    > encapsulation that an instance offers. Am I missing something? Is this just
    > the facts of life when using classes?
    >
    > 2. Is it accepted practice to simply create a new instance every time the
    > class is needed, thus setting the instance's state once, using it with one or
    > more method calls, then moving on to the next new instance? It occurs to me
    > that maybe Ruby's garbage collection would sweep the old instance right up,
    > knowing it won't be used again, but I don't know.
    >
    > My nightmare case is a class which operates on an input record, but
    > differently each time, depending upon a number of factors in the environment
    > outside the class. I just can't see a graceful way to do this. I'm struggling
    > to see why I do OO programming at all in this case.


    Normally you'd write a class in cases where you want more than one of
    something. I'm not sure that's the case here. What exactly do you mean
    by a class operating on an input record? Or, to go at it a different
    way, what exactly is the flow of events that you want to handle? It
    may be that you could use a class called InputHandler (or whatever),
    and you'd do something like:

    ih = InputHandler.new(filename)
    fields = ih.parse_into_fields

    A class is a generalization. So if what you're doing isn't general,
    you may not need or want to model it in classes. If you're writing a
    script to parse one particular file, there's quite likely no point
    writing a generalized handler class.

    I feel like I'm failing to get beyond the rather unhelpful "it
    depends" level, but maybe prompt me with some further specifics....


    David

    --
    David A. Black / Ruby Power and Light, LLC
    Ruby/Rails consulting & training: http://www.rubypal.com
    Coming in 2009: The Well-Grounded Rubyist (http://manning.com/black2)

    http://www.wishsight.com => Independent, social wishlist management!
     
    David A. Black, Jan 29, 2009
    #2
    1. Advertising

  3. Tom Cloyd

    Tom Cloyd Guest

    David A. Black wrote:
    > Hi --
    >
    > On Thu, 29 Jan 2009, Tom Cloyd wrote:
    >
    >> 1. HOW do you use a class?
    >>
    >> I was assuming that since I couldn't pass data to an instance, after
    >> creation, I have no option but to write data into its instance vars
    >> as needed. Sometimes, it seems there simply is no other option.

    >
    > You can pass data to an instance:
    >
    > instance.some_method(data)

    Uh, yes. I had undervalued this possibility, about which I did know. I
    suppose I could pass in an array of data describing some external state,
    and parse it inside the class. Now, suddenly, I'm seeing a very
    economical way to use classes.
    >
    >> But, is it approved practice to do something like
    >>
    >> junk = MyClass.new( var_1...var_n ).mymethod
    >>
    >> which creates an instance and calls a method which leaves its results
    >> in some instance vars., then simple read the results with...but how?
    >> there's no instance object!

    >
    > What you've written here is similar to:
    >
    > upstring = String.new("David").upcase
    >
    > or something like that, and it's perfectly legit, though you might
    > also want to grab the object separately:
    >
    > string = String.new("David")
    > upstring = string.upcase

    Yes, I think usually one would.
    >
    >> (Not that I can find, anyway.) That seems to leave me only with this
    >> possibility:
    >>
    >> myclass = MyClass.newMyClass.new( var_1...var_n )

    >
    > I don't quite get that line. What's newMyClass? (Or maybe it's
    > garbling again between our machines?)

    Yeah, it's garble. Don't know why that happened.
    >
    >> myclass.mymethod
    >> varA = myclass.var_whatever
    >> etc....until I have all my results back out of the instance.
    >>
    >> Compared to a simple method call, this seems designed to make me
    >> crazy quickly. Is there a better way?

    Yeah - stuff the variables into an array, and access the array.
    >
    > I'm not sure I'm following. I guess the short answer is that there's a
    > ton of different patterns you can follow, depending on what you need
    > to do.

    It's clear to me now that if I can pass in an array of data describing
    external state, and can pull it back out by accessing a class instance
    variable containing that array, transformed in some way by its having
    passed through the class instance. Ah...I'm feeling much better now.
    >
    >> Then, to call the instance again, I have to write new data into its
    >> instance vars. This simply looks like nonsense, unless one really
    >> needs to have the encapsulation that an instance offers. Am I missing
    >> something? Is this just the facts of life when using classes?

    The "nonsense" remains, in that so far I'm just employing a method,
    which happens to be formed as a class. There no obvious reason to have
    formed it up as a class. Again I wonder - what's the point of using a
    class? When do we do it? I can think of some applications, but mostly it
    appears that mere methods are fine.
    >>
    >> 2. Is it accepted practice to simply create a new instance every time
    >> the class is needed, thus setting the instance's state once, using it
    >> with one or more method calls, then moving on to the next new
    >> instance? It occurs to me that maybe Ruby's garbage collection would
    >> sweep the old instance right up, knowing it won't be used again, but
    >> I don't know.
    >>
    >> My nightmare case is a class which operates on an input record, but
    >> differently each time, depending upon a number of factors in the
    >> environment outside the class. I just can't see a graceful way to do
    >> this. I'm struggling to see why I do OO programming at all in this case.

    >
    > Normally you'd write a class in cases where you want more than one of
    > something. I'm not sure that's the case here. What exactly do you mean
    > by a class operating on an input record? Or, to go at it a different
    > way, what exactly is the flow of events that you want to handle? It
    > may be that you could use a class called InputHandler (or whatever),
    > and you'd do something like:
    >
    > ih = InputHandler.new(filename)
    > fields = ih.parse_into_fields

    This looks like a method dressed up as a class. Why do this? I guess it
    could make your root program simpler. Every time you want a new record,
    you tickle the single class instance you have, and it spits out some
    data. But, it quakes like a duck (method), so I have to say that's what
    it is, disguised as a class. In the example, as given to this point,
    there's no reason for the conversion to a class - none that I can see.
    >
    > A class is a generalization. So if what you're doing isn't general,
    > you may not need or want to model it in classes. If you're writing a
    > script to parse one particular file, there's quite likely no point
    > writing a generalized handler class.

    I have to agree. I reached that conclusion over the weekend, with some
    disappointment. I started out some days ago wondering "why classes"? I
    got some decent answers back, but have yet to really find an
    application. Dave Thomas uses an example of a book story inventory
    program, and creates a book class, one instance of which is created for
    every book. So where does that leave us, I wonder? With a running
    inventory program that has 50,000 little book objects bouncing around
    inside? That makes no sense, to me. It certainly is an illustration of
    using classes, but to me in no way illustrates the NECESSITY or even the
    benefit of doing do. I keep thinking I'm missing something that everyone
    else is seeing.

    The technology of classes isn't the problem for me. It's the rationale.
    I look at some of gems I use, and I see herds of classes. They make some
    sense as containers for methods, certainly, but modules could do that,
    or some clever naming scheme for set of classes which share some common
    domain.

    Maybe it's just an organizational thing. A class is way to create a
    complex thing that looks and acts simple. That, of course, is a terrific
    idea. But, again, mere methods do that quite nicely.

    Somehow I'm not quite grasping the heart of the problem I'm having. One
    more try - it's clear why sometimes one uses integers and other times
    floats. I'm trying to get to that level of clarity regarding classes.
    Right now, I appreciate the idea that I might do myClassInstance.a, then
    *.b, , and so on, accessing various methods that are conveniently
    grouped in my ClassInstance. AND that I might want to subclass this so
    as to have a slightly different flavor of it. It's also clear that I
    might want to hold the state of some domain, while I go off and do other
    things, returning at times to make use of that held state and any
    associated methods. It all sounds like a nice idea.

    I need to find some part of my code that cries out for this nice
    concept, and so far I haven't. So far, I have a class that opens some
    files and loads their contents in hashes. Once. And a similar one that
    dumps the hashes back out. Once. A method would the job just as well.
    Making those classes was just an exercise, it now seems.

    I just looked over all my methods, in my current project. They're all
    simply blocks of code that get used repeatedly. There's no need to hold
    state. All state resides in the main program. Now, THAT - a main program
    which manages a database modeled on a graph - I'll turn into a class, as
    I might need to have multiple instances running simultaneously, and play
    them off each other. THAT, I think, is the first clear need for a class
    I've yet seen, in my little coding world. The absolute first.

    Well, sorry for the digressive nature of my ruminations. I wander
    because I AM a bit lost. Fascinated, but lost. Meanwhile, the code is
    coming along nicely, so I can't really complain too much.

    Thanks for your thoughts, David- they WERE helpful. If you have any
    more, please pass them along. Your comments have always been helpful.

    Tom

    --

    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    Tom Cloyd, MS MA, LMHC - Private practice Psychotherapist
    Bellingham, Washington, U.S.A: (360) 920-1226
    << >> (email)
    << TomCloyd.com >> (website)
    << sleightmind.wordpress.com >> (mental health weblog)
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     
    Tom Cloyd, Jan 29, 2009
    #3
  4. Hi --

    On Thu, 29 Jan 2009, Tom Cloyd wrote:

    > David A. Black wrote:
    >>
    >> You wrote:
    >>>
    >>> My nightmare case is a class which operates on an input record, but
    >>> differently each time, depending upon a number of factors in the
    >>> environment outside the class. I just can't see a graceful way to do this.
    >>> I'm struggling to see why I do OO programming at all in this case.

    >>
    >> Normally you'd write a class in cases where you want more than one of
    >> something. I'm not sure that's the case here. What exactly do you mean
    >> by a class operating on an input record? Or, to go at it a different
    >> way, what exactly is the flow of events that you want to handle? It
    >> may be that you could use a class called InputHandler (or whatever),
    >> and you'd do something like:
    >>
    >> ih = InputHandler.new(filename)
    >> fields = ih.parse_into_fields

    > This looks like a method dressed up as a class.


    "Class" and "method" are not commensurate. They're categorically
    different; they don't stand in for each other. What I've got there is
    a class, an instance of that class, and an instance method.

    > Why do this? I guess it could
    > make your root program simpler. Every time you want a new record, you tickle
    > the single class instance you have, and it spits out some data. But, it
    > quakes like a duck (method), so I have to say that's what it is, disguised as
    > a class. In the example, as given to this point, there's no reason for the
    > conversion to a class - none that I can see.


    It feels to me like you've overthinking the issue. For one thing, it's
    important to get back to *objects*. In other words, it's not a tug of
    war between classes and methods; it's all about which objects will
    help you the most. (Classes are objects, but that's secondary at the
    moment.)

    In my example, ih is an object that has state (it knows of a filename)
    and behavior (it can parse the file into fields, whatever that may
    mean). It's possible that I'd need an object that does not have state,
    but that can parse files -- in which case, I might write a method on a
    class or module (like YAML.load). But if I want my handler to remember
    its filename, then a class is not appropriate, because I might have
    more than one handler, or some other library that I load might want to
    use the handler. The ability to create instances of a class, and
    associate each instance with a file, means that the class itself
    doesn't have to track who's using which file.

    Again, it's really about objects, not classes. If I need three input
    handlers, then I want a convenient way to create them. I could do this
    each time:

    handler = Object.new
    handler.extend(SomeHandlerModule)
    handler.filename = filename
    handler.parse_into_fields

    and so on, but a class is a shortcut way of doing something similar.

    >> A class is a generalization. So if what you're doing isn't general,
    >> you may not need or want to model it in classes. If you're writing a
    >> script to parse one particular file, there's quite likely no point
    >> writing a generalized handler class.

    > I have to agree. I reached that conclusion over the weekend, with some
    > disappointment. I started out some days ago wondering "why classes"? I got
    > some decent answers back, but have yet to really find an application. Dave
    > Thomas uses an example of a book story inventory program, and creates a book
    > class, one instance of which is created for every book. So where does that
    > leave us, I wonder? With a running inventory program that has 50,000 little
    > book objects bouncing around inside? That makes no sense, to me. It certainly
    > is an illustration of using classes, but to me in no way illustrates the
    > NECESSITY or even the benefit of doing do. I keep thinking I'm missing
    > something that everyone else is seeing.
    >
    > The technology of classes isn't the problem for me. It's the rationale. I
    > look at some of gems I use, and I see herds of classes. They make some sense
    > as containers for methods, certainly, but modules could do that, or some
    > clever naming scheme for set of classes which share some common domain.


    You can certainly use modules. The class Class is, in fact, a subclass
    of the class Module, which means that in a certain sense, classes are
    a specialization of module (basically, a module that can spawn
    instances).

    > Maybe it's just an organizational thing. A class is way to create a complex
    > thing that looks and acts simple. That, of course, is a terrific idea. But,
    > again, mere methods do that quite nicely.
    >
    > Somehow I'm not quite grasping the heart of the problem I'm having. One more
    > try - it's clear why sometimes one uses integers and other times floats.


    And Integer and Float are both classes :)

    > I'm
    > trying to get to that level of clarity regarding classes. Right now, I
    > appreciate the idea that I might do myClassInstance.a, then *.b, , and so on,
    > accessing various methods that are conveniently grouped in my ClassInstance.
    > AND that I might want to subclass this so as to have a slightly different
    > flavor of it. It's also clear that I might want to hold the state of some
    > domain, while I go off and do other things, returning at times to make use of
    > that held state and any associated methods. It all sounds like a nice idea.
    >
    > I need to find some part of my code that cries out for this nice concept, and
    > so far I haven't. So far, I have a class that opens some files and loads
    > their contents in hashes. Once. And a similar one that dumps the hashes back
    > out. Once. A method would the job just as well. Making those classes was just
    > an exercise, it now seems.


    Again, class and method are not warring concepts. Even if you write
    classes, you still write methods -- and *every* method in Ruby resides
    in either a class or a module.

    > I just looked over all my methods, in my current project. They're all simply
    > blocks of code that get used repeatedly. There's no need to hold state. All
    > state resides in the main program. Now, THAT - a main program which manages a
    > database modeled on a graph - I'll turn into a class, as I might need to have
    > multiple instances running simultaneously, and play them off each other.
    > THAT, I think, is the first clear need for a class I've yet seen, in my
    > little coding world. The absolute first.


    There's absolutely no technical imperative to write classes that you
    don't need. It's not a higher plateau of programming; it's just a tool
    for spawning objects.

    One way to get a sense of how classes are used (and useful) is to
    consider the Ruby language itself. In any language, you need to be
    able to have multiple filehandles open. In Ruby, that need is
    addressed by modeling each filehandle as an instance of File. The
    class is, so to speak, the dispatch station, where requests for new
    filehandles are fielded. But the class itself does not attach itself
    to a particular file, since that would severely limit you.

    In my Intro to Ruby training, I've got an exercise where you write a
    program modeling a deck of cards. The exercise comes in several
    flavors: write a Card class and Deck class, with Deck either
    inheriting from Array or not, and write the whole program again
    without defining any classes. It's all very valuable, and all the
    techniques exposed by the exercise are important. As always, it comes
    down to objects, and to what's the best way to launch the objects you
    need.


    David

    --
    David A. Black / Ruby Power and Light, LLC
    Ruby/Rails consulting & training: http://www.rubypal.com
    Coming in 2009: The Well-Grounded Rubyist (http://manning.com/black2)

    http://www.wishsight.com => Independent, social wishlist management!
     
    David A. Black, Jan 29, 2009
    #4
  5. 2009/1/29 Tom Cloyd <>:
    > Greetings...
    >
    > I'm continuing my learn-to-write-OO-Ruby journey. Had a recent bad
    > experience trying to convert a complex method to a class. The method gets a
    > lot of use in my program, and each time it needs to know a lot about the
    > environment outside itself. I found myself having to write a ton of instance
    > variable data into the class instance to get it to do its job, before I
    > called it each time, then read a few more back out to get the results. It
    > was awful. What had been a one line call was now about 14 lines of code.
    > Ack! I gave up and converted it back to a method, which simply makes more
    > sense. I could not find any "class-magic" in this experience - just a lot of
    > locked doors.
    >
    > I now have three questions. I have read a number of people's accounts of
    > what classes are and how you build them, etc., etc., and no one seems to
    > address these matters at all well (or else I missed it):
    >
    > 1. HOW do you use a class?


    You might want to have a look at all those patterns around - they
    should give you an idea how to use them. You could start here:
    http://c2.com/cgi-bin/wiki?WelcomeVisitors

    > I was assuming that since I couldn't pass data to an instance, after
    > creation, I have no option but to write data into its instance vars as
    > needed. Sometimes, it seems there simply is no other option.
    >
    > But, is it approved practice to do something like
    >
    > junk = MyClass.new( var_1...var_n ).mymethod


    That is a rather seldom idiom because usually you want your objects to
    live longer. Having said that, there is room for something like that
    namely with complex calculations that need a lot of intermediate state
    that you want to store in the instance.

    > 2. Is it accepted practice to simply create a new instance every time the
    > class is needed, thus setting the instance's state once, using it with one
    > or more method calls, then moving on to the next new instance? It occurs to
    > me that maybe Ruby's garbage collection would sweep the old instance right
    > up, knowing it won't be used again, but I don't know.


    Yes, that's accepted although one usually tries to keep instances for
    longer. In the command pattern you create an instance instead of
    invoking a single method:

    http://en.wikipedia.org/wiki/Command_pattern
    http://c2.com/cgi-bin/wiki?CommandPattern

    But even in this case the object lives rather long because the
    calculation is typically complex and takes more time.

    > My nightmare case is a class which operates on an input record, but
    > differently each time, depending upon a number of factors in the environment
    > outside the class. I just can't see a graceful way to do this. I'm
    > struggling to see why I do OO programming at all in this case.


    This smells like State or Strategy Pattern.

    http://en.wikipedia.org/wiki/Strategy_pattern
    http://en.wikipedia.org/wiki/State_pattern

    > 3. Finally, I'm still struggling with the "when do I make something a
    > class?" question. I'm surprised that this question is so unimportant or its
    > answer so obvious that no one much addresses it. Dave Thomas, in his 3rd ed.
    > (I just upgraded, and its really nice!) finally gives two sentences to the
    > matter, which is way more than I can find anywhere else: "Whenever you're
    > designing OO systems, a good first step is to identify the things you're
    > dealing with. Typically each type of thing becomes a class in your final
    > program, and the things themselves are instances of these classes."(p. 59)


    There are a number of approaches to finding classes. An easy one is
    to identify nouns in your description of the problem. Those are
    candidate classes and verbs are candidate methods. See the "tutorial"
    section for more
    http://users.csc.calpoly.edu/~dbutler/tutorials/winter96/crc_b/

    > I've been thinking only in terms of functions, things my program does, and
    > not things it works on or with. Both are relevant, clearly, and I'm now out
    > on a hunt for "things" that are more than functions. Maybe that will help.


    Yes, sounds as if this shift in perspective would help you. Rather ask
    "what artifacts do I have in my problem domain" instead of "what needs
    to be done"?

    > Anyone have any additional advice about "when to make something a class?"
    > The principle reasons I see are to achieve scope closure, persistent state,
    > and object duplication (multiple instances). Did I miss anything important?


    I guess with "scope closure" you mean "encapsulation". Persistence is
    not mandatory for OO.

    I found this book rather inspiring although it might not be the best
    introductory text:
    http://archive.eiffel.com/doc/oosc/

    Kind regards

    robert

    --
    remember.guy do |as, often| as.you_can - without end
     
    Robert Klemme, Jan 29, 2009
    #5
  6. David A. Black wrote:
    > One way to get a sense of how classes are used (and useful) is to
    > consider the Ruby language itself. In any language, you need to be
    > able to have multiple filehandles open. In Ruby, that need is
    > addressed by modeling each filehandle as an instance of File. The
    > class is, so to speak, the dispatch station, where requests for new
    > filehandles are fielded. But the class itself does not attach itself
    > to a particular file, since that would severely limit you.


    Good example. Similarly, methods which act on the filesystem, but don't
    need to
    maintain their own state, are class methods: e.g. File.exist?,
    File.rename, File.delete

    Another example you could consider is an XML parser. You could write
    this as a standalone method in a module:

    result = XMLParser.parse(source)

    That would parse the source from start to end in one operation. It might
    return an object representing the results, or it could yield each
    element to a block that you parse. But once the parsing is done, it's
    done, and there's no need to remember anything.

    One reason you might want to create an *instance* of a parser is to
    remember options which will be re-used when parsing multiple documents:

    parser = XMLParser.new:)arrays => true, :strip_space => false)
    res1 = parser.parse(source1)
    res2 = parser.parse(source2)

    A completely different reason is so that the parser object can be
    attached to a particular document that you are parsing. This would allow
    the parsing operation to be spread out over time, and you could ask it
    when you like for the next tag - a "pull parser"

    parser = XMLParser.new(source)
    e1 = parser.next_element
    e2 = parser.next_element
    ...

    Here, the object instance keeps a reference to the source object, and
    keeps track of the parsing state (e.g. stack of open tags)

    So the need to keep state is driven by the user's requirements. If you
    don't need to keep state, then don't.

    > I've been thinking only in terms of functions, things my program does,
    > and not things it works on or with.


    There is absolutely nothing wrong with this, and if you follow it to its
    conclusion you will end up with functional programming, where every
    output is a product of its inputs only. This is how many computer
    science courses introduce programming.

    For example, if you look at data structures in Erlang, generally you
    pass in the old data structure as an argument and receive a new one as a
    result:

    add_element(Element, Set1) -> Set2

    There's no "set object" as such, just some data structure representing a
    set, which is passed in and returned.

    In Ruby, if you make an object representing a set, the first argument is
    implicitly 'self', so there's no need to pass in Set1. Also, your method
    may choose to return a new object, or to modify its own state.

    Note that whilst you can demonstrate functional programming techniques
    with Ruby, the language isn't really geared up to support them fully.
    --
    Posted via http://www.ruby-forum.com/.
     
    Brian Candler, Jan 29, 2009
    #6
  7. Tom Cloyd

    Tom Cloyd Guest

    Robert Klemme wrote:
    > 2009/1/29 Tom Cloyd <>:
    >
    >> Greetings...
    >>
    >> I'm continuing my learn-to-write-OO-Ruby journey. Had a recent bad
    >> experience trying to convert a complex method to a class. The method gets a
    >> lot of use in my program, and each time it needs to know a lot about the
    >> environment outside itself. I found myself having to write a ton of instance
    >> variable data into the class instance to get it to do its job, before I
    >> called it each time, then read a few more back out to get the results. It
    >> was awful. What had been a one line call was now about 14 lines of code.
    >> Ack! I gave up and converted it back to a method, which simply makes more
    >> sense. I could not find any "class-magic" in this experience - just a lot of
    >> locked doors.
    >>
    >> I now have three questions. I have read a number of people's accounts of
    >> what classes are and how you build them, etc., etc., and no one seems to
    >> address these matters at all well (or else I missed it):
    >>
    >> 1. HOW do you use a class?
    >>

    >
    > You might want to have a look at all those patterns around - they
    > should give you an idea how to use them. You could start here:
    > http://c2.com/cgi-bin/wiki?WelcomeVisitors
    >
    >
    >> I was assuming that since I couldn't pass data to an instance, after
    >> creation, I have no option but to write data into its instance vars as
    >> needed. Sometimes, it seems there simply is no other option.
    >>
    >> But, is it approved practice to do something like
    >>
    >> junk = MyClass.new( var_1...var_n ).mymethod
    >>

    >
    > That is a rather seldom idiom because usually you want your objects to
    > live longer. Having said that, there is room for something like that
    > namely with complex calculations that need a lot of intermediate state
    > that you want to store in the instance.
    >
    >
    >> 2. Is it accepted practice to simply create a new instance every time the
    >> class is needed, thus setting the instance's state once, using it with one
    >> or more method calls, then moving on to the next new instance? It occurs to
    >> me that maybe Ruby's garbage collection would sweep the old instance right
    >> up, knowing it won't be used again, but I don't know.
    >>

    >
    > Yes, that's accepted although one usually tries to keep instances for
    > longer. In the command pattern you create an instance instead of
    > invoking a single method:
    >
    > http://en.wikipedia.org/wiki/Command_pattern
    > http://c2.com/cgi-bin/wiki?CommandPattern
    >
    > But even in this case the object lives rather long because the
    > calculation is typically complex and takes more time.
    >
    >
    >> My nightmare case is a class which operates on an input record, but
    >> differently each time, depending upon a number of factors in the environment
    >> outside the class. I just can't see a graceful way to do this. I'm
    >> struggling to see why I do OO programming at all in this case.
    >>

    >
    > This smells like State or Strategy Pattern.
    >
    > http://en.wikipedia.org/wiki/Strategy_pattern
    > http://en.wikipedia.org/wiki/State_pattern
    >
    >
    >> 3. Finally, I'm still struggling with the "when do I make something a
    >> class?" question. I'm surprised that this question is so unimportant or its
    >> answer so obvious that no one much addresses it. Dave Thomas, in his 3rd ed.
    >> (I just upgraded, and its really nice!) finally gives two sentences to the
    >> matter, which is way more than I can find anywhere else: "Whenever you're
    >> designing OO systems, a good first step is to identify the things you're
    >> dealing with. Typically each type of thing becomes a class in your final
    >> program, and the things themselves are instances of these classes."(p. 59)
    >>

    >
    > There are a number of approaches to finding classes. An easy one is
    > to identify nouns in your description of the problem. Those are
    > candidate classes and verbs are candidate methods. See the "tutorial"
    > section for more
    > http://users.csc.calpoly.edu/~dbutler/tutorials/winter96/crc_b/
    >
    >
    >> I've been thinking only in terms of functions, things my program does, and
    >> not things it works on or with. Both are relevant, clearly, and I'm now out
    >> on a hunt for "things" that are more than functions. Maybe that will help.
    >>

    >
    > Yes, sounds as if this shift in perspective would help you. Rather ask
    > "what artifacts do I have in my problem domain" instead of "what needs
    > to be done"?
    >
    >
    >> Anyone have any additional advice about "when to make something a class?"
    >> The principle reasons I see are to achieve scope closure, persistent state,
    >> and object duplication (multiple instances). Did I miss anything important?
    >>

    >
    > I guess with "scope closure" you mean "encapsulation". Persistence is
    > not mandatory for OO.
    >
    > I found this book rather inspiring although it might not be the best
    > introductory text:
    > http://archive.eiffel.com/doc/oosc/
    >
    > Kind regards
    >
    > robert
    >
    >

    David, Brian, Robert - THANKS!

    I'm fascinated to read your thoughtful responses, this morning - that,
    and gratified. You each responded in different ways, and have offered me
    considerable material to think on, and resources to explore. This is
    precisely what I was hoping for. I think you "got it" that I'm genuinely
    wanting to see this matter from the inside out, and your serious
    responses, coupled with my coding adventures, will get the job done, I'm
    sure.

    My "overthinking" (I've been accused of that before on this list!) is
    due to my background in philosophy. To my mind, making sense is the most
    important thing we do with our minds, and it often requires a lot of
    analytical probing, until all the meaningful dimensions of a problem
    space are explored. Only then have you mapped the domain adequately.
    That approach has often been my default method, with important things.
    Not everyone's style, to be sure, but it is mine.

    Again, my sincere gratitude for your taking the time to give me so much.
    I will make good use of it!

    Tom

    --

    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    Tom Cloyd, MS MA, LMHC - Private practice Psychotherapist
    Bellingham, Washington, U.S.A: (360) 920-1226
    << >> (email)
    << TomCloyd.com >> (website)
    << sleightmind.wordpress.com >> (mental health weblog)
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     
    Tom Cloyd, Jan 29, 2009
    #7
  8. On Thu, Jan 29, 2009 at 6:03 AM, Tom Cloyd <> wrote:
    > Greetings...
    >
    > I'm continuing my learn-to-write-OO-Ruby journey. Had a recent bad
    > experience trying to convert a complex method to a class. The method gets a
    > lot of use in my program, and each time it needs to know a lot about the
    > environment outside itself. I found myself having to write a ton of instance
    > variable data into the class instance to get it to do its job, before I
    > called it each time, then read a few more back out to get the results. It
    > was awful. What had been a one line call was now about 14 lines of code.
    > Ack! I gave up and converted it back to a method, which simply makes more
    > sense. I could not find any "class-magic" in this experience - just a lot of
    > locked doors.


    One thing that might help is an object to encapsulate the environment
    that is passed to your method. For instance, a method that worked out
    whether two particles, given by their initial positions and
    velocities, would collide, would look something like

    projectCollision(x1, y1, z1, vx1, vy1, vz1, x2, y2, z2, vx2, vy2, vz2)

    As a first pass, we'd define a particle class

    class Particle
    attr_accessor :x, :y, :z, :vx, :vy, :vz
    ...
    end

    and call our method with

    projectCollision(particle1, particle2)

    now particle1 and particle2 are objects of the class Particle, who get
    their positions and velocities updated at the appropriate places in
    the code. Your methods that deal with updating the particles'
    positions and velocities need only pass particle objects around, and
    the objects themselves act as slates to track changes to their
    internal data. To a first approximation, I've found that using classes
    to group and encapsulate function parameters is at least as useful a
    refactoring as using classes to hold the functions themselves.

    martin
     
    Martin DeMello, Jan 29, 2009
    #8
  9. Tom Cloyd

    Tom Cloyd Guest

    Martin DeMello wrote:
    > On Thu, Jan 29, 2009 at 6:03 AM, Tom Cloyd <> wrote:
    >
    >> Greetings...
    >>
    >> I'm continuing my learn-to-write-OO-Ruby journey. Had a recent bad
    >> experience trying to convert a complex method to a class. The method gets a
    >> lot of use in my program, and each time it needs to know a lot about the
    >> environment outside itself. I found myself having to write a ton of instance
    >> variable data into the class instance to get it to do its job, before I
    >> called it each time, then read a few more back out to get the results. It
    >> was awful. What had been a one line call was now about 14 lines of code.
    >> Ack! I gave up and converted it back to a method, which simply makes more
    >> sense. I could not find any "class-magic" in this experience - just a lot of
    >> locked doors.
    >>

    >
    > One thing that might help is an object to encapsulate the environment
    > that is passed to your method. For instance, a method that worked out
    > whether two particles, given by their initial positions and
    > velocities, would collide, would look something like
    >
    > projectCollision(x1, y1, z1, vx1, vy1, vz1, x2, y2, z2, vx2, vy2, vz2)
    >
    > As a first pass, we'd define a particle class
    >
    > class Particle
    > attr_accessor :x, :y, :z, :vx, :vy, :vz
    > ...
    > end
    >
    > and call our method with
    >
    > projectCollision(particle1, particle2)
    >
    > now particle1 and particle2 are objects of the class Particle, who get
    > their positions and velocities updated at the appropriate places in
    > the code. Your methods that deal with updating the particles'
    > positions and velocities need only pass particle objects around, and
    > the objects themselves act as slates to track changes to their
    > internal data. To a first approximation, I've found that using classes
    > to group and encapsulate function parameters is at least as useful a
    > refactoring as using classes to hold the functions themselves.
    >
    > martin
    >
    >
    >

    Wow. Martin that's a fascinating idea. Terrific notion. Gonna try to
    make use of this. But just the idea is great for me to know aout.

    Thanks!

    Tom

    --

    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    Tom Cloyd, MS MA, LMHC - Private practice Psychotherapist
    Bellingham, Washington, U.S.A: (360) 920-1226
    << >> (email)
    << TomCloyd.com >> (website)
    << sleightmind.wordpress.com >> (mental health weblog)
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     
    Tom Cloyd, Jan 29, 2009
    #9
  10. Hi --

    On Fri, 30 Jan 2009, Tom Cloyd wrote:

    > David, Brian, Robert - THANKS!
    >
    > I'm fascinated to read your thoughtful responses, this morning - that, and
    > gratified. You each responded in different ways, and have offered me
    > considerable material to think on, and resources to explore. This is
    > precisely what I was hoping for. I think you "got it" that I'm genuinely
    > wanting to see this matter from the inside out, and your serious responses,
    > coupled with my coding adventures, will get the job done, I'm sure.
    >
    > My "overthinking" (I've been accused of that before on this list!) is due to
    > my background in philosophy. To my mind, making sense is the most important
    > thing we do with our minds, and it often requires a lot of analytical
    > probing, until all the meaningful dimensions of a problem space are explored.
    > Only then have you mapped the domain adequately. That approach has often been
    > my default method, with important things. Not everyone's style, to be sure,
    > but it is mine.


    I definitely would not discourage exploration of this kind. I'm 100%
    in favor of fully understanding the techniques you're using, and
    knowing exactly what Ruby is actually doing. But I still think you're
    overthinking it :)

    By that I don't mean that you should stop trying to understand. It's
    more that you're multiplying the complexity beyond what it actually
    is, for example by positing a kind of substitution relation between
    classes and methods.

    That said, I think it's true that people learn and grapple with new
    things in different ways. I tend to learn in what I think of as the
    "Polaroid" style: I start with a breadth-first but very faint
    perception of a technology, and gradually the whole picture comes into
    view. It's actually kind of weird, because I can know that I'm going
    to understand something by the end of the day, and yet not be able to
    accelerate the process.

    By the same token, I think that what I call "overthinking" is, as you
    say, your way of getting there. I just wanted to clarify the point
    that I'm not discouraging a deep understanding, just sounding the
    buzzer as you cross the invisible line between the road and the
    shoulder :)


    David

    --
    David A. Black / Ruby Power and Light, LLC
    Ruby/Rails consulting & training: http://www.rubypal.com
    Coming in 2009: The Well-Grounded Rubyist (http://manning.com/black2)

    http://www.wishsight.com => Independent, social wishlist management!
     
    David A. Black, Jan 30, 2009
    #10
  11. Tom Cloyd

    Tom Cloyd Guest

    David A. Black wrote:
    > Hi --
    >
    > On Fri, 30 Jan 2009, Tom Cloyd wrote:
    >
    >> David, Brian, Robert - THANKS!
    >>
    >> I'm fascinated to read your thoughtful responses, this morning -
    >> that, and gratified. You each responded in different ways, and have
    >> offered me considerable material to think on, and resources to
    >> explore. This is precisely what I was hoping for. I think you "got
    >> it" that I'm genuinely wanting to see this matter from the inside
    >> out, and your serious responses, coupled with my coding adventures,
    >> will get the job done, I'm sure.
    >>
    >> My "overthinking" (I've been accused of that before on this list!) is
    >> due to my background in philosophy. To my mind, making sense is the
    >> most important thing we do with our minds, and it often requires a
    >> lot of analytical probing, until all the meaningful dimensions of a
    >> problem space are explored. Only then have you mapped the domain
    >> adequately. That approach has often been my default method, with
    >> important things. Not everyone's style, to be sure, but it is mine.

    >
    > I definitely would not discourage exploration of this kind. I'm 100%
    > in favor of fully understanding the techniques you're using, and
    > knowing exactly what Ruby is actually doing. But I still think you're
    > overthinking it :)
    >
    > By that I don't mean that you should stop trying to understand. It's
    > more that you're multiplying the complexity beyond what it actually
    > is, for example by positing a kind of substitution relation between
    > classes and methods.

    Ah. Now I understand. I actually never positing that at all. I didn't
    clarify things when you implied that a while back. Was too busy trying
    to keep up with the new material in the developing thread. My problem
    was simply that as I was trying to introduce classes into my project
    code, I didn't know when I really SHOULD create a class. I had gotten
    the impression somewhere that major methods should virtually always be
    reconceptualized as classes. I didn't arrive at that notion by thinking.
    I'd given up on that, as I didn't have enough material to work with.

    But, that perception didn't really make a lot of sense. Still, I
    couldn't find any explicit guidance anywhere regarding the fundamental
    question I kept asking: WHEN is it the thing to do to make a class? I
    did find those two sentences in Thomas (3rd ed) - but that's sparse
    pickins, and I didn't find them until AFTER my weekend disaster in which
    I spend a pile of time converting a complex method into a class, getting
    completely exasperated with the experience, and converting it back. So,
    I wasn't overthinking at all. I was mis-perceiving, in the presence of
    an absence (ha!) - an absence of clear guidance about the
    WHEN-do-classes issue. The best sense I could make of things was that
    "big stuff oughta be classes" (bad idea). I didn't yet "get it"
    (understatement).
    >
    > That said, I think it's true that people learn and grapple with new
    > things in different ways. I tend to learn in what I think of as the
    > "Polaroid" style: I start with a breadth-first but very faint
    > perception of a technology, and gradually the whole picture comes into
    > view. It's actually kind of weird, because I can know that I'm going
    > to understand something by the end of the day, and yet not be able to
    > accelerate the process.

    This is one of two learning styles that has been documented among
    programmers, leading to the realization that programming needs to be
    taught simultaneously in two quite different ways - the left-brained
    folks need linear progressions and the right-brained folks need
    gradually emerging patterns, just as you have described for yourself.
    >
    > By the same token, I think that what I call "overthinking" is, as you
    > say, your way of getting there. I just wanted to clarify the point
    > that I'm not discouraging a deep understanding, just sounding the
    > buzzer as you cross the invisible line between the road and the
    > shoulder :)

    Hey, I can usually use all the warning calls anyone cares to give me,
    believe me!

    In any case, this thread has been remarkably useful to me, in my
    tortured journey toward a more classy (uhem) way of programming.

    BTW, I was puzzled for years by the mathematical notion of a function.
    It just eluded me. Baffled me. Then, as I was learning to program in
    Fortran, years ago, I began to wonder if there was any relation between
    Fortran functions (hope you know a little Fortran) and mathematical
    functions. Of course, there is. Fortran functions was no problem at all
    to grasp, and once I realized they were just another way of expressing a
    mathematical function (or perhaps I should say that a math function can
    be expressed as a Fortran function, and in fact that was what they were
    for), I was seriously rageful. I couldn't understand why something so
    easy had been made so hard (for me) in math. classes. I'm still a little
    pissed about that. There's little excuse for that kind of stupid teaching.

    So, we must attend to our students, and how it is they REALLY learn. I
    like to think that we're better at that now than we used to be.

    t.
    >
    >
    > David
    >



    --

    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    Tom Cloyd, MS MA, LMHC - Private practice Psychotherapist
    Bellingham, Washington, U.S.A: (360) 920-1226
    << >> (email)
    << TomCloyd.com >> (website)
    << sleightmind.wordpress.com >> (mental health weblog)
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     
    Tom Cloyd, Jan 31, 2009
    #11
  12. Tom Cloyd <> writes:
    > [...] My problem
    > was simply that as I was trying to introduce classes into my project
    > code, I didn't know when I really SHOULD create a class. I had gotten
    > the impression somewhere that major methods should virtually always be
    > reconceptualized as classes. I didn't arrive at that notion by thinking.
    > I'd given up on that, as I didn't have enough material to work with.
    >
    > But, that perception didn't really make a lot of sense. Still, I
    > couldn't find any explicit guidance anywhere regarding the fundamental
    > question I kept asking: WHEN is it the thing to do to make a class? I
    > did find those two sentences in Thomas (3rd ed) - but that's sparse
    > pickins, and I didn't find them until AFTER my weekend disaster in which
    > I spend a pile of time converting a complex method into a class, getting
    > completely exasperated with the experience, and converting it back. So,
    > I wasn't overthinking at all. I was mis-perceiving, in the presence of
    > an absence (ha!) - an absence of clear guidance about the
    > WHEN-do-classes issue. The best sense I could make of things was that
    > "big stuff oughta be classes" (bad idea). I didn't yet "get it"
    > (understatement).


    First you write a problem statement.
    Then you identify the important words in it.
    Nouns will become classes.
    Verbs will become methods.
    (approximatively).

    The idea is that what has nouns in natural language are the objects
    that have some stability in the real world, and what has verbs are the
    actions.


    Of course, you can have reification of the actions or the
    associations, when you start to speak about verbs (notice that "verb"
    is a noun, not a verb).

    For example, when you write:

    (def m(x)
    (2 * x)
    end)

    you actually instantiate an object of the class Method:

    (Object . method "m")
    --> #<Method: Class(Object)#m>

    but you do that only when you're talking at a meta-level, here it's
    the level of the Ruby language, not that of your problem domain.


    Instead of reifying the "big stuff", you should rather try to reify
    the _stable_ stuff. A Person is something that is table, from her
    birth to her death. On the other hand, eating, sleeping, working,
    reproducing, breathing, are temporary actions. There even are actions
    that cannot be done during all the life time. For example, a baby
    Person has no walk method. This method is programmed during the first
    few years.


    Objects encapsulate state and methods.

    When your problem domain (cf the problem statement) considers a Person
    only in her relations with the surrounding world, then the methods of
    a Person will be Ruby methods. You won't need to reify these methods.

    On the other hand, if your problem statement is to implement a Person
    simulator, then it's possible that the methods of a Person need to be
    reifed, so you can add, change and remove these methods. Imagine
    having to write a Person simulator that starts in the baby state, and
    that should evolve a walk method. In this case, you could have a
    MotorMethod class, and a Walk subclass, as well as classes such as
    Muscle, Bone, Nerve, etc. But these kind of classes would be named in
    the problem statement (at least latently, sometimes problem statements
    are brief).

    --
    __Pascal Bourguignon__
     
    Pascal J. Bourguignon, Jan 31, 2009
    #12
  13. On 31.01.2009 10:02, Tom Cloyd wrote:
    > BTW, I was puzzled for years by the mathematical notion of a function.
    > It just eluded me. Baffled me. Then, as I was learning to program in
    > Fortran, years ago, I began to wonder if there was any relation between
    > Fortran functions (hope you know a little Fortran) and mathematical
    > functions. Of course, there is. Fortran functions was no problem at all
    > to grasp, and once I realized they were just another way of expressing a
    > mathematical function (or perhaps I should say that a math function can
    > be expressed as a Fortran function, and in fact that was what they were
    > for), I was seriously rageful.


    IMHO there is an important distinction though which makes Fortran
    functions a bad example: mathematical functions usually do not have side
    effects, i.e. they can be completely described in terms of input and
    output. I view them as a relationship (or call it a mapping) which
    assigns particular output values to particular input values. If I'm not
    mistaken, a Fortran function can have side effects on arguments (and
    probably global variables). A closer analogy are functions in - you
    guessed it - functional languages.

    Kind regards

    robert
     
    Robert Klemme, Jan 31, 2009
    #13
  14. Tom Cloyd

    Tom Cloyd Guest

    Robert Klemme wrote:
    > On 31.01.2009 10:02, Tom Cloyd wrote:
    >> BTW, I was puzzled for years by the mathematical notion of a
    >> function. It just eluded me. Baffled me. Then, as I was learning to
    >> program in Fortran, years ago, I began to wonder if there was any
    >> relation between Fortran functions (hope you know a little Fortran)
    >> and mathematical functions. Of course, there is. Fortran functions
    >> was no problem at all to grasp, and once I realized they were just
    >> another way of expressing a mathematical function (or perhaps I
    >> should say that a math function can be expressed as a Fortran
    >> function, and in fact that was what they were for), I was seriously
    >> rageful.

    >
    > IMHO there is an important distinction though which makes Fortran
    > functions a bad example: mathematical functions usually do not have
    > side effects, i.e. they can be completely described in terms of input
    > and output. I view them as a relationship (or call it a mapping)
    > which assigns particular output values to particular input values. If
    > I'm not mistaken, a Fortran function can have side effects on
    > arguments (and probably global variables). A closer analogy are
    > functions in - you guessed it - functional languages.
    >
    > Kind regards
    >
    > robert
    >
    >

    Robert - I absolutely agree, and I can to that (or THOSE)
    understanding(s) in my first pass through grad. school. The idea of a
    function being a rule that associates two sets of numbers seems to me
    the most useful. However, the initial breakthrough for me was to see a
    function as a little program - a process: put something in, get
    something out. So easy. For some reason, that view it escaped me
    throughout high school, etc. (I was a writer, not a calculator!).

    Thanks for your thoughts, as always. I always enjoy what you have to say!

    Tom

    --

    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    Tom Cloyd, MS MA, LMHC - Private practice Psychotherapist
    Bellingham, Washington, U.S.A: (360) 920-1226
    << >> (email)
    << TomCloyd.com >> (website)
    << sleightmind.wordpress.com >> (mental health weblog)
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     
    Tom Cloyd, Jan 31, 2009
    #14
  15. Tom Cloyd

    Tom Cloyd Guest

    Pascal J. Bourguignon wrote:
    > Tom Cloyd <> writes:
    >
    >> [...] My problem
    >> was simply that as I was trying to introduce classes into my project
    >> code, I didn't know when I really SHOULD create a class. I had gotten
    >> the impression somewhere that major methods should virtually always be
    >> reconceptualized as classes. I didn't arrive at that notion by thinking.
    >> I'd given up on that, as I didn't have enough material to work with.
    >>
    >> But, that perception didn't really make a lot of sense. Still, I
    >> couldn't find any explicit guidance anywhere regarding the fundamental
    >> question I kept asking: WHEN is it the thing to do to make a class? I
    >> did find those two sentences in Thomas (3rd ed) - but that's sparse
    >> pickins, and I didn't find them until AFTER my weekend disaster in which
    >> I spend a pile of time converting a complex method into a class, getting
    >> completely exasperated with the experience, and converting it back. So,
    >> I wasn't overthinking at all. I was mis-perceiving, in the presence of
    >> an absence (ha!) - an absence of clear guidance about the
    >> WHEN-do-classes issue. The best sense I could make of things was that
    >> "big stuff oughta be classes" (bad idea). I didn't yet "get it"
    >> (understatement).
    >>

    >
    > First you write a problem statement.
    > Then you identify the important words in it.
    > Nouns will become classes.
    > Verbs will become methods.
    > (approximatively).
    >
    > The idea is that what has nouns in natural language are the objects
    > that have some stability in the real world, and what has verbs are the
    > actions.
    >
    >
    > Of course, you can have reification of the actions or the
    > associations, when you start to speak about verbs (notice that "verb"
    > is a noun, not a verb).
    >
    > For example, when you write:
    >
    > (def m(x)
    > (2 * x)
    > end)
    >
    > you actually instantiate an object of the class Method:
    >
    > (Object . method "m")
    > --> #<Method: Class(Object)#m>
    >
    > but you do that only when you're talking at a meta-level, here it's
    > the level of the Ruby language, not that of your problem domain.
    >
    >
    > Instead of reifying the "big stuff", you should rather try to reify
    > the _stable_ stuff. A Person is something that is table, from her
    > birth to her death. On the other hand, eating, sleeping, working,
    > reproducing, breathing, are temporary actions. There even are actions
    > that cannot be done during all the life time. For example, a baby
    > Person has no walk method. This method is programmed during the first
    > few years.
    >
    >
    > Objects encapsulate state and methods.
    >
    > When your problem domain (cf the problem statement) considers a Person
    > only in her relations with the surrounding world, then the methods of
    > a Person will be Ruby methods. You won't need to reify these methods.
    >
    > On the other hand, if your problem statement is to implement a Person
    > simulator, then it's possible that the methods of a Person need to be
    > reifed, so you can add, change and remove these methods. Imagine
    > having to write a Person simulator that starts in the baby state, and
    > that should evolve a walk method. In this case, you could have a
    > MotorMethod class, and a Walk subclass, as well as classes such as
    > Muscle, Bone, Nerve, etc. But these kind of classes would be named in
    > the problem statement (at least latently, sometimes problem statements
    > are brief).
    >
    >

    Pascal,

    This is a simply lovely exposition. I'll add it to the other in this
    very helpful thread. And, I'm returning to my code, with these thoughts
    in mind, to see what I can learn.

    Thanks for taking the time to make these things so clear. Much appreciated.

    Tom

    --

    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    Tom Cloyd, MS MA, LMHC - Private practice Psychotherapist
    Bellingham, Washington, U.S.A: (360) 920-1226
    << >> (email)
    << TomCloyd.com >> (website)
    << sleightmind.wordpress.com >> (mental health weblog)
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     
    Tom Cloyd, Jan 31, 2009
    #15
  16. Its a Free Language

    An attractive aspect of Ruby is how it is usually presented as agnostic
    - you can use it in an object oriented style or you can choose
    functional or procedural styles. So if you like to think in terms of
    procedures instead of objects you can still sit at the same tables as
    other Ruby programmers. Having said that, I would guess that any
    procedure can be re-represented in terms of objects and your thinking
    should move in that direction over time to align with the essence of the
    language.

    --
    Posted via http://www.ruby-forum.com/.
     
    Mike Stephens, Jan 31, 2009
    #16
  17. Re: Its a Free Language

    Hi --

    On Sun, 1 Feb 2009, Mike Stephens wrote:

    > An attractive aspect of Ruby is how it is usually presented as agnostic
    > - you can use it in an object oriented style or you can choose
    > functional or procedural styles. So if you like to think in terms of
    > procedures instead of objects you can still sit at the same tables as
    > other Ruby programmers. Having said that, I would guess that any
    > procedure can be re-represented in terms of objects and your thinking
    > should move in that direction over time to align with the essence of the
    > language.


    I particularly like the way the functional/procedural programming
    style is engineered to work with the OO style, in the sense that
    functional-style method calls are actually calls to private methods --
    and privacy is enforced by having to omit the explicit receiver... so
    that methods like puts, which are private methods of Object, can be
    called at any point in the program, since self is always an instance
    of a descendant of Object.

    In some respects, this is perhaps the most productive use of private
    methods in Ruby, since the privacy is not strictly enforced. If it did
    nothing else than provide a way to integrate the functional style into
    the OO architecture, it would still be worth it.


    David

    --
    David A. Black / Ruby Power and Light, LLC
    Ruby/Rails consulting & training: http://www.rubypal.com
    Coming in 2009: The Well-Grounded Rubyist (http://manning.com/black2)

    http://www.wishsight.com => Independent, social wishlist management!
     
    David A. Black, Feb 1, 2009
    #17
  18. Re: Its a Free Language

    On Sat, Jan 31, 2009 at 11:00 PM, Mike Stephens <> wrote:
    > An attractive aspect of Ruby is how it is usually presented as agnostic
    > - you can use it in an object oriented style or you can choose
    > functional or procedural styles. So if you like to think in terms of
    > procedures instead of objects you can still sit at the same tables as
    > other Ruby programmers. Having said that, I would guess that any
    > procedure can be re-represented in terms of objects and your thinking
    > should move in that direction over time to align with the essence of the
    > language.
    >


    The power of Ruby does not come from its object-orientation alone -
    how many times do we really use polymorphism or inheritance? Yet I bet
    most of us use #select, #map, blocks and literal regular expressions
    in almost every program we write. I certainly do.

    I personally see Ruby as an elegant melding of Lisp, Smalltalk and
    Perl - functional, object-oriented and pragmatic, evenly balanced and
    working in harmony.

    I recommend every programmer should read
    http://csis.pace.edu/~bergin/patterns/ppoop.html as an (unintentional)
    precautionary tale against the over-zealous application of
    object-oriented design,

    Regards,
    Sean
     
    Sean O'Halpin, Feb 1, 2009
    #18
  19. Re: Its a Free Language

    Hi --

    On Sun, 1 Feb 2009, Sean O'Halpin wrote:

    > On Sat, Jan 31, 2009 at 11:00 PM, Mike Stephens <> wrote:
    >> An attractive aspect of Ruby is how it is usually presented as agnostic
    >> - you can use it in an object oriented style or you can choose
    >> functional or procedural styles. So if you like to think in terms of
    >> procedures instead of objects you can still sit at the same tables as
    >> other Ruby programmers. Having said that, I would guess that any
    >> procedure can be re-represented in terms of objects and your thinking
    >> should move in that direction over time to align with the essence of the
    >> language.
    >>

    >
    > The power of Ruby does not come from its object-orientation alone -
    > how many times do we really use polymorphism or inheritance? Yet I bet
    > most of us use #select, #map, blocks and literal regular expressions
    > in almost every program we write. I certainly do.


    At the same time, though, I'd say that object orientation per se
    doesn't depend on polymorphism and inheritance. To me it's the
    convergence back onto the sending-msgs-to-objects paradigm that's at
    the heart of it (though I don't put that forth as a CS-ly correct
    characterization, just my sense of it).

    On the third hand... :) there's that functional style of calling
    methods in Ruby, though it's also OO under the hood of course.


    David

    --
    David A. Black / Ruby Power and Light, LLC
    Ruby/Rails consulting & training: http://www.rubypal.com
    Coming in 2009: The Well-Grounded Rubyist (http://manning.com/black2)

    http://www.wishsight.com => Independent, social wishlist management!
     
    David A. Black, Feb 1, 2009
    #19
  20. Re: Its a Free Language

    On Feb 1, 2009, at 6:54 AM, David A. Black wrote:

    > On the third hand... :) there's that functional style of calling
    > methods in Ruby, though it's also OO under the hood of course.
    >
    >
    > David



    I think you mean: "On the gripping hand..."

    (If you read Larry Niven, that is ;-)

    -Rob

    Rob Biedenharn http://agileconsultingllc.com
     
    Rob Biedenharn, Feb 1, 2009
    #20
    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. Harald Kirsch

    Proper use of CharsetDecoder?

    Harald Kirsch, Aug 4, 2003, in forum: Java
    Replies:
    1
    Views:
    3,925
    Roedy Green
    Aug 5, 2003
  2. Kees de Winter

    Generating proper classes with XSD.exe

    Kees de Winter, Feb 2, 2007, in forum: ASP .Net
    Replies:
    2
    Views:
    558
    =?Utf-8?B?UGV0ZXIgQnJvbWJlcmcgW0MjIE1WUF0=?=
    Feb 2, 2007
  3. tenxian
    Replies:
    7
    Views:
    370
    Mark Space
    Apr 28, 2008
  4. Quek
    Replies:
    3
    Views:
    347
  5. H. Wade Minter
    Replies:
    8
    Views:
    309
    Robin
    Apr 25, 2004
Loading...

Share This Page