in reply to perspective and object-disorientation

Of course, an Employee may also be a Musician, Artist, Trainspotter (in their spare time)
I think I see your error here. When a Person becomes employed by an Organization, then his role within that Organization becomes that of Employee. This does not affect his role within a family, nor does it affect his Hobbies or whatever.

One way of handling this within your object model is to look at using the Decorator pattern. Consider the following code from your Domain objects:

package Organization; ... sub recruit { my $self = shift; my $new_hire = shift; $self->add_employee(Employee->wrap($new_hire)); return $self; } package Employee; sub wrap { my $class = shift; my $person = shift; $class->new->set_person($person); } sub set_person { my $self = shift; my $new_person = shift; $self->{person} = $new_person; return $self; } sub surname { my $self = shift; $self->person->surname; } sub employee_number { my $self = shift; $self->{employee_number}; } ...
What's happening here is that the Employee class delegates all the 'Person' stuff that's relevant to the organization to its decorated Person object, and handles all the organization specific methods and attributes itself. Thus, the Organization only ever deals with Employees. (In a real (commercial) Object model of course, Employee would probably end up being a 'whole' class, without needing the flexibility of the Decorator pattern, simply because no other entities need to make use of an underlying Person object.)

As for the Musician/Artist/Trainspotter thing, just give your Person class a list of Role objects to which the person delegates appropriate methods (though getting that behaving neatly may take a little more work on the programmers part (and there are several different ideas about what is 'right') so I'm going to resort to a handwave at this point.

Father/Husband/Buddy etc are all relationships rather than intrinsics. Depending on what your object model dictates these may end up being full on decorater classes or simple references from one Person to another.

Replies are listed 'Best First'.
Re: Re: perspective and object-disorientation
by Ctrl-z (Friar) on Jan 19, 2003 at 21:57 UTC
    I see what you are saying. I think the Employee/Artist example i gave doesn't really hold up to what I was trying to express, but was more convenient than getting too contrived on a subject Im not 100% on. (not 25% on!)

    So far I have been using a similar setup to what you suggest. Im not too clued-up on patterns, but it seems to be like the hasa relationship suggested by others?.
    I find this kind of "orientation" simple to manage - it is DOM-ish and familiar. All objects inherit a common base-class for general introspection and delegation , then rely on their own class to provide their "individuality".

    The problem i find with this, is that an objects "individuality" is purely based on its data - it is difficult to have dynamic behaviour, sensitive to both the environment the object is created in, and the relationship between (for example) caller() and $self at any given time.
    If @ISA were an instance variable, then this could be realistically implemented. The class may provide a default - but time, context and environment could mutate it appropriately. As it stands, @ISA is per class, so the only way I can think of to hack it, would be something like
    sub callMethod { my $self = shift; my ($method, @args) = @_; # pseudo-code only ;) (defined( $self->{buddies}->{ caller() } ) ) ? unshift @ISA, "Behaviour::Informal" : unshift @ISA, "Behaviour::Guarded" ; my @return = $self->$method(@args) if $self->can($method); # hide what we just did from the rest of our class! shift @ISA; return @return; }

    I realise the limitations with the above code, but i guess its somewhat less abstract than the pseudo-existential waffle of "perspectives" ;)
    Im pretty much out of my depth here, so perhaps I am just thrashing in comp.sci terminology?
      But caller doesn't do what you want. Try:
      sub respond_to_message_from { my $self = shift; my($message, $sender); my $attitude = $self->appropriate_attitude_to($sender); $attitude->respond_to_message_from($self, $message, $sender); }
      This avoids monkeying with @ISA, which can only be a good thing. $attitude is an example of the Strategy Pattern. Note that I've not got an @args parameter to this function, instead I'd expect them to be wrapped up in teh $message object (which can be thought of as an example of the Argument Object pattern.
        ah!

        I realised the insufficiency of using caller() in that way - but your example is still great. Having the  $self->appropriate_attitude_to($sender) return an object is really...neat.

        Thanks, I'll play around with this