Beefy Boxes and Bandwidth Generously Provided by pair Networks
Your skill will accomplish
what the force of many cannot
 
PerlMonks  

perspective and object-disorientation

by Ctrl-z (Friar)
on Jan 17, 2003 at 22:59 UTC ( [id://227847]=perlmeditation: print w/replies, xml ) Need Help??

forgive me monks, for i have sinned. This is my first confession

And what have you done my son?

I have impure thoughts on altering @ISA during runtime. Often.

Disclaimer: I am a newbie, to Perl and OOP - and largely dont understand the underlying concepts of how Perl works. I apologise if I cant provide a more informed case. This is what Im looking to get from posting this meditation.

So, as I understand it the @ISA is a bit of a hack onto Perl and possibly a conceptual faux pas in regard to "purer" OO languages. Using base.pm seems to be preferred to having the programmer directly manipulate @ISA, though of course, thats pretty much what base.pm does. I wonder that maybe this transparency is not a good thing, and that having a regular array of inheritence is a boon as oppose to a cheap trick.

Consider the obligitary Employee class. An Employee isa Person isa Mammal isa...

Of course, an Employee may also be a Musician, Artist, Trainspotter (in their spare time), or a Father, Husband, Buddy, or a Jerk, Hero, Nondescript-Bystander. There is no little tree diagram that can display this, because largely it is a matter of perspective. Once you have the perspective of the "viewer" (perhaps the user, or another object) then the tree of inheritence can organise itself. Its not the One True Tree of the Employee class - its just a perspective.

I dont yet subscribe to the "everything is an Object" type philosophy, but I can appreciate the power in thinking that way, and am enjoying the challenges of learning the methodology. However, most OO languages expect an objects lineage to be preordained by the God programmer with respect to whatever system he is working on. The fact an Employee isa Trainspotter is of little relevence to a Payroll program, and so in somewhat contrived ecosystems, there is no problem.

But what of other domains like AI, Neural Networks, Bioinformatics, Distributed computing, Peer-to-Peer?. The latter is more where my interest lies, and I often find that a clear line of relationship cannot be predefined. Sure, once there is a relationship you can make pretty tree diagrams, but that is again, based on perspective.

I am not a professional programmer or formally trained. I think of Perl more as an intillectual game than a tool for parsing log files. This is why I love Perlmonks - theres loads of theory up for grabs.

So, theorhetically, is manipulating an objects inheritence based on how it is currently being percieved, a worthwhile cause for meditation?

maybe there is somewhere I can read up on stuff like this?

Thankyou for any time

Replies are listed 'Best First'.
Re: perspective and object-disorientation
by MarkM (Curate) on Jan 17, 2003 at 23:29 UTC

    Ctrl-z writes:

    So, theorhetically, is manipulating an objects inheritence based on how it is currently being percieved, a worthwhile cause for meditation?

    Without intending to, you have pointed out the exact reason why so many people new to Perl have difficulty when understanding the effects of modifying @ISA.

    You say "manipulating an object's inheritance". The only way to manipulate an object's inheritance is to bless() it into another class:

    my $object = Class1->new; bless $object, 'Class2';

    Manipulating @ISA does not change the inheritance of an object. It changes the implementation of the class. The effect of this is that all objects that are blessed into the class suddenly inherit a different set of methods. To this end, we find chaos. Perl attempts to improve the performance of method invocations by caching the results of method lookups. These cached results become incorrect when @ISA is alterred. Also, from a code re-entrancy requirement, since changes to @ISA are global, it would be very difficult for two sections of code that had different 'perspectives' to access the same set of objects at the same time.

    You have a good point in your node -- the perspective of the programmer, and the requirements for the project dictate the class names that are decided upon. These names may be inaccurate to a programmer with a different perspective, or a project with a different set of requirements.

    The most common solution to this problem is the class hierarchy. The Employee class that you refer to above would perhaps better be named Acme::Payroll::Employee. This additional context specifies the context under which the class should be perceived from.

    Ctrl-z writes:

    Of course, an Employee may also be a Musician, Artist, Trainspotter (in their spare time), or a Father, Husband, Buddy, or a Jerk, Hero, Nondescript-Bystander. There is no little tree diagram that can display this, because largely it is a matter of perspective. Once you have the perspective of the "viewer" (perhaps the user, or another object) then the tree of inheritence can organise itself. Its not the One True Tree of the Employee class - its just a perspective.

    In English, we say 'Mark is an artist.' or 'John is a musician.' From a design perspective, however, 'Artist' is a professional role. The question "Is there an artist in this room?" is programmatically similar to:

    my @people_in_room = grep {$_->isa('Person')} $room->contained_objects +; my @artists_in_room; for my $person (@people_in_room) { push(@artists_in_room, $person) if grep {$_->isa('Artist')} $person->professional_roles; }

    The relationship between real life objects is quite sophisticated, and is often not a case of inheritance. In the programming domain, object models rarely ever need to be as complicated as they are in real life domain. Simple problems call for simple solutions.

    UPDATE: Abigail-II is insistent that the method cache problem is not an issue, since it is fixed in recent versions of Perl. Although he could have been more polite about it, I accept his criticism, and have striken out the offending sentence. Cheers!

      Perl attempts to improve the performance of method invocations by caching the results of method lookups. These cached results become incorrect when @ISA is alterred

      Oh, come on. Please get a newer version of Perl. I reported this bug in the beginning of 1997, and it was fixed shortly after. The Camel-II explicitely mentions that modifying @ISA clears the cache.

      You're claiming that modifying @ISA is bad, because it changes the implementation of the class. But is that always bad? Installing a sub in an AUTOLOAD also changes the implementation of a class, and that's something done often.

      I wouldn't recommend modifying @ISA, unless you're really sure what you are doing. But I also won't claim modifying @ISA should never been done.

      Abigail

        I wouldn't recommend modifying @ISA, unless you're really sure what you are doing. But I also won't claim modifying @ISA should never been done.

        See Test::Class & self-shunt pattern for one example where altering @ISA might be useful :-)

        Abigail: Come 'on' yourself. You must be having a crappy day to take only one thing out of my node and s$it on it. :-)

        I never claimed that modifying @ISA should never be done. Just, those who normally resort to modifying @ISA, are new to Perl, and don't really understand what they are doing.

        And even for people that do know what they are doing... it doesn't hurt to take a second look and consider whether there might not be an alternative that is more portable to other languages.

      Also, from a code re-entrancy requirement, since changes to @ISA are global, it would be very difficult for two sections of code that had different 'perspectives' to access the same set of objects at the same time.

      While I don't think changing @ISA willy-nilly is a good idea, changes are global only if you choose to make them that way.

      @ISA can be changed locally using... well... local :-) It can be a useful idiom when testing to make one object temporarily appear as another.

        Changing @ISA can be a useful idiom when testing to make one object temporarily appear as another
        But only if you insist on trying to turn Perl into a pessimistically typed language. Us optimistic types just implement the appropriate methods and have done with it. But we've done this discussion already haven't we :)
      UPDATE: Abigail-II is insistent that the method cache problem is not an issue, since it is fixed in recent versions of Perl. Although he could have been more polite about it, I accept his criticism, and have striken out the offending sentence.

      I propose that both correctness, and Perl, are much more interesting than politeness. When I was first getting started, Abigail was probably the most useful person to in my learning. Precicely because he would skip all the niceties and just tell me, "no that's totally wrong, ..."


      --
      Snazzy tagline here
Re: perspective and object-disorientation
by djantzen (Priest) on Jan 18, 2003 at 00:01 UTC

    Looking at an object through different lenses depending upon which aspects and relationships you want to emphasize is indeed a very powerful way of utilizing code. However, it would be a mistake to try to accomplish that by altering the inheritance chain at runtime, or frivolously between compilations for that matter, for the practical reason that trying to build an inheritance structure flexible enough to allow that without breaking is damn hard, and for the theoretical reason that to say that a class is a descendant of a particular base class is to say something permanent about the kind of being that it is, not to indicate a transitory characteristic.

    The problem stems at least in part from the ambivalence in English of the word "is". Clinton was not entirely BSing in his deposition, because the word can mean one of three things: the assignment of a predicate to a noun, i.e., "the tie is gold"; a strict identification between two or more things, i.e., "the dress with the stain is the blue dress"; or it can indicate subsumption under a general category, i.e., "he is a man".

    In comparison, look at the difference between estar and ser in Spanish. both mean "to be", however "estoy en Norteamérica" means "I am in North America", and "soy norteamericano" means "I am a North American". It's the difference between a characteristic that is incidental to who and what I am, and one that is intrinsic to the kind of being that I am. Inheritance in an object model ought to capture only the latter.

    Now I'm not going to argue that there is no bleedover between the three variations of "is", especially between the ascription of predicates and the placement of an object under a general category. For example, if a person works as a trainspotter for a single week, does it make sense to say that that person is in any way intrinsically a trainspotter? In the same way that he/she is a mammal? Probably not, but it might make sense to say that of a person who's been a trainspotter for his/her entire adult life. Nonetheless, in planning out an object model utilizing inheritance you have to think about what defines your classes in their most basic, abstract, and essential sense. In many cases, it won't be sensible or sufficiently flexible and powerful to explain immediately what something "is" by looking for an inheritance relation. Rather, what you would find better in your example above is to define a class Job that a Person could possess, and a class FamilyRelation to describe the Person as a father, sister, etc., and perhaps a BehavioralModes class for being a jerk or hero. Altering the fundamental being of an object is something that should happen only under conditions of extraordinary stress. But I would not say it should never happen, so just long as the rules according to which it will are clearly laid out in advance.

    Good Question!

Re: perspective and object-disorientation
by gjb (Vicar) on Jan 17, 2003 at 23:14 UTC

    Not every hierarchy is a tree as you mention. This can be solved in several ways:

    1. C++ and other languages (Perl among them) offer multiple inheritance, this means that a class can have multiple base classes. If you start drawing diagrams, you'll notice this can get quite nasty (or at least very tricky) if one exagerates.
    2. Java offers interfaces: one can view this as a kind of contract. Certain functions must be implemented in the class that is to adhere to the interface. This can be done in OO languages that don't support multiple inheritance, but also in C++.
    The approach using interfaces has the advantage that one can "attach" properties to a tree. A person could implement the trainspotter interface and offer the method seenWhatTrainsToday().

    The issue has been discussed recently in this node, but you might also be interested in the following book:

    @book{Lau01,
      author =       {Y.-T.\ Lau},
      title =        {The art of objects: object-oriented design and architecture},
      publisher =    {Addison-Wesley},
      year =         {2001},
      series =       {Object technology series},
      address =      {Upper Saddle River, NJ}
    }
    

    Just my 2 cents, -gjb-

Re: perspective and object-disorientation
by pg (Canon) on Jan 18, 2003 at 02:24 UTC
    When we look at the same thing from DIFFERENT "perscpective", we are looking at exactly the SAME thing, there is NO doubt about this, but we focus on DIFFERENT attributes, as we need.

    To be frank, my first feeling is that, Perl or @ISA is not quite relevant to what we want to talk about here, actually this is more a question about OO ITSELF.

    Let's look at your example. An employee could be a father, a mother, a musician (although might be a lousy one ;-).

    1. What do you want to abstract from the real world?

      Each application always has its PARTICULAR PURPOSE. For example, if this is a HR (Human resource) application, we want to abstract employee as a class, but most likely not musician or father. If this is a system for a special group of musicians in my city, then I would abstract musician as a class.

      Then where would the other information go? You can argure that you obviously care whether a employee is a musician, so you may use him for your company's Xmas party.

      Very good, but those should really be treated as attributes rather than a separate class. Again, this is about what the PURPOSE is, and what the FOCUS is.

    2. Is this a subclass or an attribute?

      This question may sound stupid (or way too obvious) to some people, but actually not. Say there is one employee, and he has two attributes:
      1. He is a father;
      2. He is a manager;
      You can treat both as attributes, but you may also think that, the attribute whether a person is a manager is important enough, that a new class should be abstracted as a subclass of employee.

      Again this is about PURPOSE. When it is extreamly reasonable to abstract manager as a subclass in a HR system, it is definitely uneccessary to abstract a manager class in a "house hold management system", just because the father of that family happens to be a manager in his work place, because it is irrelevant to the PURPOSE of your "house hold management system".

    3. Last but not least, the POWER of human thinking is that, we gather all relevant information, and then FILTER and SIMPLIFY what we see, and UNDERSTAND it from a particular PERSPECTIVE, base on our purpose and focus. We try to UNDERSTAND the world around us, within the capbility and capicity of our brain, but not try to be CONFUSED by it.



    Ctrl-Z, you are not sinned. No body is sinned because he thinks, anyone thinks is blessed.
Re: perspective and object-disorientation
by boo_radley (Parson) on Jan 17, 2003 at 23:37 UTC
    Sure, once there is a relationship you can make pretty tree diagrams, but that is again, based on perspective.
    And just as a draftsman will use a picture to create a piece of machinery, we can chart out software to ensure its cohesiveness and viability. If you find that the system you're developing is too mutable, it may be that you're observing several different, but interrelated systems which are part of a larger whole.
    So, theorhetically, is manipulating an objects inheritence based on how it is currently being percieved, a worthwhile cause for meditation?
    This would be the object oriented version of GOTO spaghetti code.
    Further, I seem to remember that part of perl objects get memoized by the compiler at some point in time (methods? ->can calls?), so horribly mutating an object like this might not do what you want, depending on what you've already done to it.
Re: perspective and object-disorientation
by chromatic (Archbishop) on Jan 18, 2003 at 01:21 UTC

    @ISA influences two things. One, it lists where to look for methods that aren't found in the current class. Two, it lists where to look when isa() is called on the class or an object of a class.

    I think those are two different concepts: where does this class keep the implementations of its behavior and how does this class relate to other classes. (I'd also add in a third concept, what kind of behaviors can this class perform, but not everyone sees the world this way.)

    Right now, I can't come up with any really good reasons (besides in testing, where I do it way too often) to change @ISA at runtime, as there are other ways to change #1 and #2 above, but it's nice to work with a language that allows it, if necessary.

Re: perspective and object-disorientation
by pdcawley (Hermit) on Jan 19, 2003 at 18:45 UTC
    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.

      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.
Re: perspective and object-disorientation
by Ctrl-z (Friar) on Jan 19, 2003 at 00:34 UTC

    Thankyou all for the comprehensive replies.
    An especial thanks to fever, something really 'clicked' while reading that note.

    The overall impression I get is that, "well its OK, but you probably dont want to". Thats fine, Im happy to keep playing around with it while looking for alternatives. My biggest problem was that there is not many places it would be considered acceptable to ask such a question, so it was slowly doing my head in!
    I genuinely appreciate such esteemed monks took the time to entertain my musings.
    To respond to a couple of monks:

    markM and adrianh:

    reblessing an object into a different package? A whole new avenue of perversion !
    This could actually be what Im looking for. Each object shares the same abstract base-class and my hope is that the base-class will support the freeform structure above. The idea of changing states seems to sit well with my "perspectives".

    pg

    Yes, you are right. I think the term perspective I am using is, in most cases, the perspective of what the program does and a logical heirarchy can be organised. I have found object orientation to be a great organiser, but the program that raised the above question was dileberately being awkward, mostly for my own learning.

    castaway

    It sounds like you're thinking of writing a self-evolving program which can change its own objects as it likes... Fun..

    Well, it beats staring at the TV ;)

     

    To restate the obvious - this place rocks!

    regards

Re: perspective and object-disorientation
by adrianh (Chancellor) on Jan 18, 2003 at 20:13 UTC

    While changing the ISA relationships of a class is possible - it's not something that you will often need to do.

    A more common perl idiom for changing an objects behaviour is to bless it into another package. You can use this as one way to implement OO state transition systems in perl. Again, this is not something to be done casually.

    Part of your confusion might be because of the common misconception that ISA is the only kind of relationship in OO development. It isn't - it's just the most obvious one because it's supported by explicit language constructs.

    Other relationships you will see in OO design include:

    • uses - your data-munging object might be given a logging object to use for it's log requests
    • hasa - your car object might have four wheel objects
    • implemented with - you might implement your process scheduling object with a queue object

    All these relationships are largely orthagonal to isa relationships. Take a look at Class::Delegation for one way to make these other relationships more explicit.

    I'd recommend reading some general OO texts. One of my personal favourites is Meyer's Object Oriented Software Construction. A good read.

    Aspect-oriented programming (for perl take a look at the Aspect modules) is another way of looking at the various relationships between objects and classes. I'm not really convinced that this is as radical approach to development as some people say - but it makes interesting reading.

    If your problem is purely about categorisation you may find it helpful to look at some of the methods and techniques from artifical intelligence research - the AI:: modules might be a useful starting point.

Re: perspective and object-disorientation
by castaway (Parson) on Jan 18, 2003 at 12:28 UTC
    It's an interesting question..
    You're looking at programming and OO as if you'd like to be able to define really complex systems with it (such as Real Life), to be able to use the exact same programm for different aspects at the same time. This doesn't really represent real life though. I would view a Person as something which changes states over time. He may be an Employee and a Trainspotter and a Father, but each of these states are not active simultaneously when they are being actively 'carried out'.
    When writing a programm/object in which you want to look at the objects in a lot of different perspectives, its better to deal with a generic object, and set states for however you are looking at it at the time. (Person->atWork(), Person->atHome(), Person->atTheTrainStation().. )

    As to changing @ISA at runtime, its not occured to me to do that, and I can't think of a reason to do it at the moment (a real one). It did however, just occur to me, that you can also change the inherited classes as you like as well, theres nothing to stop you doing 'use base (Blah.pm);' and then add stuff to Blah.pm in your code (package Blah.pm; changestuff), or eval'ing code at runtime to do this.

    It sounds like you're thinking of writing a self-evolving program which can change its own objects as it likes... Fun..

    C.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlmeditation [id://227847]
Approved by gjb
Front-paged by djantzen
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others sharing their wisdom with the Monastery: (2)
As of 2024-03-19 04:08 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found