From: "David A. Black" Date: 2009-01-29T21:11:52+09:00 Subject: Re: proper use of classes 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!