From: Gavin Sinclair Date: 2002-08-31T16:23:13+09:00 Subject: Re: Newbie converting brain from perl ----- Original Message ----- From: "William Pietri" > Howdy, Gavin. Thanks for taking the time to answer! > > Tobias responded to a lot of your comments already; I just wanted to add a > little more: Your problem and solution, with its variants, have made interesting reading :) I've ruthlessly snipped the rest for brevity. > > > Basically, I think you should put all the logic of what subclass best > > represents the line into LogLine, like: [...] > > > > case line > > when SENDMAIL_REGEX > > return SendMailLogLine.new(...) > > when NAMED_REGEX > > return NamedLogLine.new(...) > > else > > return BasicLogLine.new(line) > > end > > end > > end > > That's a good start, but you will run into trouble with that over time. > > The case statement approach works for a few LogLine types, but is brittle. > If you only have a couple of subclasses, then keeping the superclass in > sync with the subclasses is easy. But with 20, it's a big pain, exactly the > kind of pain that OO is supposed to save us from. > > And if you want other people to be able to write dynamically loadable log > parsing modules that extend your current functionality, the case statement > approach breaks down entirely. > > It's been my experience that often when I write a complicated if or case > statement, there's a set of subclasses waiting to be born. Or if they > already exist, then there's an opportunity to move the code into the > subclasses. I agree with all of the above. I think the issue os one of scalability. Decomposing if/case statements into polymorphism is a good practice, but you never get rid of them all - you just factor them into the single if/case statement that decides what type of object it's going to be: like my code above. When I think "factory", I think "assembly line that spits out objects", not "a communications link for objects to decide what type they want to be". 20 subclasses doesn't necessarily make it a pain: those subclasses will be arranged in a heirarchy, so the "factory" logic can be spread out a bit. Keeping the base class in sync, and allowing new modules to fit automatically, is a great point. I hope your approach works well. > > It may be a bit awkward for the client of LogLine to know what to do with > > the return value - it'll probably have to type-check it - but that's > > because of the subclassing, not because of my approach. > > I don't think awkward is quite the right word; one of the points of object > orientation is that you have typing built in to the language. > > In my case, some parts of the code are interested only in certain types of > LogLines; they will indeed check for type. But many parts of the code will > work with any LogLine at all. So a ReportGenerator object would accept a > collection of LogLine objects, but the SendmailReportGenerator would only > choose to process things of the SendmailLogLine type. The reason I think it may be awkward is because I can't imagine the various types of LogLine having much in common. So you can't write client code that sends generic methods to specific objects. I may be wrong here, and you have pointed out that there is some domain-specific similarity in your project, but I still envisage a lot of case statements in the client code. > > Thanks again for taking the time to lend me a hand! > > William Pleasure. If there are no issues, I'd like to see the source code when you're done, out of curiosity. Good luck. Gavin