The Nightstar Zoo

Nightstar IRC Network -
It is currently Mon Apr 22, 2019 7:49 am

All times are UTC - 6 hours [ DST ]

Post new topic Reply to topic  [ 2 posts ] 
Author Message
PostPosted: Thu Jul 01, 2004 9:12 pm 
Nightstar Graveyard Daemon
User avatar

Joined: Mon Jun 03, 2002 8:30 pm
Posts: 1071
Location: Wouldn't you rather observe my Velocity?

Object-Oriented Epiphany.

This will hopefully become a series of posts here. This isn't the first, or even the hundredth epiphany I've had about OOA/D/P, but meh, the posts gotta start somewhere. You are welcome to--in fact, please do--post replies here on the subject. Feel free to explore side tangents in here--as long as it's connected to other posts in the thread, I'll call it on-topic. For example, if you wanted to applaud the fact that I just split an infinitive with an entire phrase instead of the traditional adverb, that's fine. I'll also start deliberate tangent-jumping-off-points before dropping them to stay on my main point.

Enough introduction. Let's begin.

So I've been having this pain trying to do OO. You know the kind, it hurts right there, and it makes you wonder if OO is such a hot idea in the first place. Today on the way home, I had that pain and got lucky enough to notice what I was doing.

I have a procedural system that I'm slowly converting to an OO system. (Aside: Converting PC to OO smoothly may be beyond me at this point. To convert smoothly, you must have a rock-solid understanding of the destination, and for me this is not so clear. Thus, smoothly transitioning is painful and filled with doubt and false starts. Tangent: Discuss this difficulty and/or the stupidity of doing it anyway below if you wish.) It's a database survey system, and there's a headscratcher in there: the knowledge of how to filter out incomplete survey responses seems to belong to the survey response class. However, it is extremely inefficient to load all the records from the database, contruct objects from them, and use the function to discard the invalids. That's what the database engine is for, and it does it quite well. It would be stupid to short that out and reinvent it at the object level. (This is, IMO, one of the most patently difficult and/or inappropriate problems faced by OO code. My thinking right now is that if I can come up with a reasonable, intelligent and efficient OO solution, then I would be willing to say that OO really is a darn good thing in and of itself. Heads up, Pi: Armageddon, or possibly Christmas, may be coming.)

Thing is, there are two types of survey in the database now. One has 13 questions, and we select "WHERE Q13 IS NOT NULL" to get valid responses. After a certain cutoff date, however, the survey changed to 17 questions--and Q13 was removed from the survey (but not the database to preserve historical reporting). Now we select "WHERE Q17 IS NOT NULL" to find valid questions.

This has bitten me on the tucas so many times already. I've got a mere 2500 lines of code in this project, but it's procedural so there are literally several dozen places where "Q13 IS NOT NULL" had to be changed to "Q17 IS NOT NULL" and then, when I realized I had neatly blocked out all the historical data, to "(Q13 IS NOT NULL OR Q17 IS NOT NULL)". Yuck. (Tangent: even in PC code this is abominable. Once identified, I wrote a function getValidResponseSql() that returns the correct text.)

Now, to my epiphany. I was playing the "I am a ______." game, and obviously there's a Response object and a Report object. And it does make sense for a Response to know if it is a valid response and of which type of survey, etc. But I've already covered how that's not an efficient design for filtering the records in the database before creating objects. I thought about writing a static method, but for some reason that seems icky. A Response should know if it is valid, but that's not the same thing as knowing how to tell a database how to select valid records. I'm bashing my brains out trying to figure out where this getValidResponseSql() function belongs, when it hits me:

I have a function, and I don't have an object. I got here by asking "What are the functions in the system" instead of "what are the objects in the system". I'm experiencing pain because I'm trying to do OO, but my feet have led me unconsciously down the well-worn path that they know--functional decomposition.

I had to drop the function completely from my mental whiteboard. I literally envisioned the function as a stick held in my hand that I needed to drop on the floor to clear my mind. I went back to square one, and asked, "What are the objects in the system?"

That's when the follow-on epiphany hit me: there is an object missing from my design. I started to think about what object would have to exist to give that function a home, then realized that I had picked up that darn stick again. I mentally slapped my own wrist and dropped it again. Square one, square one, square one! What are the objects in the system?

I didn't have a ready answer, but I did hit on a more OO way of thinking about that function: I have a function without a home, but more importantly I have a responsibility that is not being met: that of handling the database, filtering records from it, and constructing relevant objects from it. I thought I was being clever writing a Response object that knew how to serialize itself to and from a database table, but that imposed the efficiency restriction that trips to and from the database could only every have one object in them.

Another responsibility springs immediately to mind: the management of collections of Responses. It's called a Report, and it has dozens of incarnations: statistical spreads, filtering on specific hotels and date ranges, population frequencies and counts. This class probably still doesn't talk to the database directly, but if it doesn't I bet it would cooperate with a class capable of formulating queries and grabbing groups of records at once.

That's where it stands. There is clearly a need for a collection class for Responses. There may also be a need for a database table class--having ResponseCollection do it smacks of taking on too much responsibility.

Another implication of my epiphany is that OO and PC require orthogonal thinking, and if you get locked into Procedural thinking, you will end up knocking your head. Don't blame the doorway for only being three feet high: it's seven feet wide and you're 90 degrees out of phase!

PostPosted: Thu Jul 01, 2004 10:00 pm 
Chalain wrote:
However, it is extremely inefficient to load all the records from the database, contruct objects from them, and use the function to discard the invalids.

Ahh, the first kink. ;) You have to be immensely careful to avoid problems like this in pure OO. To make a long rant short I'm not saying It Can't Be Efficient. Just that sometimes the forethought required to make OO code both clean and efficient can make it prohibitive (unless you enjoy such exercises, which I do, heh heh).

I thought I was being clever writing a Response object that knew how to serialize itself to and from a database table, but that imposed the efficiency restriction that trips to and from the database could only every have one object in them.

A common problem I run into. Invariably a superior object does the trick. That is to say that, using your example, ResponseSet would become the object that interfaced with the DB. Response could still do so, you just wouldn't use those interfaces. Instead you would give Response the interfaces ResponseSet needed to fill it out (batch DB requests and fill out each Response object when you have the data).

I look at this very much like a parent/child relationship. Perhaps more accurately, family/child.

It sounds like you've already come to a conclusion like this yourself, but what the hell, eh? :)

Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 2 posts ] 

All times are UTC - 6 hours [ DST ]

Who is online

Users browsing this forum: No registered users and 1 guest

You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group