in reply to Object Heirarchy / Design

I would follow the second thing that btrott suggested. (EDIT I had misread what he wrote slightly and thought I was differing when I wasn't.)

I would have your object contain two other objects, one for input and one for output. The connect method could then be implemented something like this (untested):

sub connect_read { my $self = shift; my $class = shift; $class = "Obj::Driver::$class"; # Load the class if need be then instantiate require $class; $self->{input} = $class->connect_read(@_); }
Similarly for your output method.

For both types of class (input and output) I would define a base class that is worthwhile to inherit from. For instance many of your drivers might need a number of rather low-level functions, but in your object code you may want to talk to a rather high-level functions. Well in your base class put the layer of obvious functions between the simple functions your drivers need to provide and the complex functions you would like to call. Then a driver only need inherit from the base and write a set of low-level functions, and the high-level functions will just work.

Replies are listed 'Best First'.
RE: RE (tilly) 1: Object Heirarchy / Design
by lattice (Initiate) on Nov 15, 2000 at 06:54 UTC
    This brings up some other questions that I forgot to bring up.

    1. How should logging be handled from these input classes? Obviously, they should all log through a standard interface, but due to the fact that they're not direct subclasses, I can't simply call $self->log( $msg ) or anything like that.
    2. If there is an object hierachy such as follows:
      package Obj; package Obj::Input; @ISA = 'Obj'; package Obj::Input::Type; @ISA = 'Obj::Input';
      then Obj::Input::Type is inheriting from Obj, which doesn't make sense, since Obj::Input::Type isn't an Obj. But it should have access to some of the 'utility' functions provided by Obj. Those utility functions should somehow be provided by Obj::Input, which should also definitely by in Obj::Input::Type's @ISA.
      phew.
      As tilly wrote: Obj::Input::Type doesn't need to inherit from Obj. If those "utility" functions are needed by both Obj::Input::Type and Obj, then they should be broken out of Obj and moved into their own utility class.

      I don't know what your "utility" methods are (perhaps you mean logging, etc.), but my personal preference is this: if from a logical perspective it doesn't make sense to have them methods of Obj, then they shouldn't be declared as methods of Obj. In my opinion, it doesn't make sense for an Obj to have a "log" method. Why should it? How is "log" acting on, or acting with, or have anything to do with an Obj object? I don't think it does. If you come at it from that perspective, I think it may be a bit clearer what methods belong in what classes.

      Why would Obj::Input bother inheriting from Obj? What does either Obj or Obj::Input get from this?

      Think about your classic diagrams with Dog and Cat inheriting from Animal. Well Animals generally contain four instances of Leg, that doesn't mean that a Leg is an Animal though!

      Instead Obj::Input exists for the purpose of containing useful utility methods for drivers to use. Your Obj class just assumes the interface it needs will work.

      As for logging (if you want it), provide a logging method in your base class, then you do just call the method.